Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-block.git] / drivers / staging / rtl8723bs / os_dep / osdep_service.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7
8
9 #define _OSDEP_SERVICE_C_
10
11 #include <drv_types.h>
12 #include <rtw_debug.h>
13
14 /*
15 * Translate the OS dependent @param error_code to OS independent RTW_STATUS_CODE
16 * @return: one of RTW_STATUS_CODE
17 */
18 inline int RTW_STATUS_CODE(int error_code)
19 {
20         if (error_code >= 0)
21                 return _SUCCESS;
22         return _FAIL;
23 }
24
25 void *_rtw_malloc(u32 sz)
26 {
27         return kmalloc(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
28 }
29
30 void *_rtw_zmalloc(u32 sz)
31 {
32         void *pbuf = _rtw_malloc(sz);
33
34         if (pbuf)
35                 memset(pbuf, 0, sz);
36
37         return pbuf;
38 }
39
40 inline struct sk_buff *_rtw_skb_alloc(u32 sz)
41 {
42         return __dev_alloc_skb(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
43 }
44
45 inline struct sk_buff *_rtw_skb_copy(const struct sk_buff *skb)
46 {
47         return skb_copy(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
48 }
49
50 inline struct sk_buff *_rtw_skb_clone(struct sk_buff *skb)
51 {
52         return skb_clone(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
53 }
54
55 inline int _rtw_netif_rx(_nic_hdl ndev, struct sk_buff *skb)
56 {
57         skb->dev = ndev;
58         return netif_rx(skb);
59 }
60
61 void _rtw_init_queue(struct __queue *pqueue)
62 {
63         INIT_LIST_HEAD(&(pqueue->queue));
64
65         spin_lock_init(&(pqueue->lock));
66 }
67
68 struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, void *old_priv)
69 {
70         struct net_device *pnetdev;
71         struct rtw_netdev_priv_indicator *pnpi;
72
73         pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
74         if (!pnetdev)
75                 goto RETURN;
76
77         pnpi = netdev_priv(pnetdev);
78         pnpi->priv = old_priv;
79         pnpi->sizeof_priv = sizeof_priv;
80
81 RETURN:
82         return pnetdev;
83 }
84
85 struct net_device *rtw_alloc_etherdev(int sizeof_priv)
86 {
87         struct net_device *pnetdev;
88         struct rtw_netdev_priv_indicator *pnpi;
89
90         pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
91         if (!pnetdev)
92                 goto RETURN;
93
94         pnpi = netdev_priv(pnetdev);
95
96         pnpi->priv = vzalloc(sizeof_priv);
97         if (!pnpi->priv) {
98                 free_netdev(pnetdev);
99                 pnetdev = NULL;
100                 goto RETURN;
101         }
102
103         pnpi->sizeof_priv = sizeof_priv;
104 RETURN:
105         return pnetdev;
106 }
107
108 void rtw_free_netdev(struct net_device *netdev)
109 {
110         struct rtw_netdev_priv_indicator *pnpi;
111
112         if (!netdev)
113                 goto RETURN;
114
115         pnpi = netdev_priv(netdev);
116
117         if (!pnpi->priv)
118                 goto RETURN;
119
120         vfree(pnpi->priv);
121         free_netdev(netdev);
122
123 RETURN:
124         return;
125 }
126
127 int rtw_change_ifname(struct adapter *padapter, const char *ifname)
128 {
129         struct net_device *pnetdev;
130         struct net_device *cur_pnetdev;
131         struct rereg_nd_name_data *rereg_priv;
132         int ret;
133
134         if (!padapter)
135                 goto error;
136
137         cur_pnetdev = padapter->pnetdev;
138         rereg_priv = &padapter->rereg_nd_name_priv;
139
140         /* free the old_pnetdev */
141         if (rereg_priv->old_pnetdev) {
142                 free_netdev(rereg_priv->old_pnetdev);
143                 rereg_priv->old_pnetdev = NULL;
144         }
145
146         if (!rtnl_is_locked())
147                 unregister_netdev(cur_pnetdev);
148         else
149                 unregister_netdevice(cur_pnetdev);
150
151         rereg_priv->old_pnetdev = cur_pnetdev;
152
153         pnetdev = rtw_init_netdev(padapter);
154         if (!pnetdev)  {
155                 ret = -1;
156                 goto error;
157         }
158
159         SET_NETDEV_DEV(pnetdev, dvobj_to_dev(adapter_to_dvobj(padapter)));
160
161         rtw_init_netdev_name(pnetdev, ifname);
162
163         memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
164
165         if (!rtnl_is_locked())
166                 ret = register_netdev(pnetdev);
167         else
168                 ret = register_netdevice(pnetdev);
169
170         if (ret != 0) {
171                 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("register_netdev() failed\n"));
172                 goto error;
173         }
174
175         return 0;
176
177 error:
178
179         return -1;
180
181 }
182
183 void rtw_buf_free(u8 **buf, u32 *buf_len)
184 {
185         if (!buf || !buf_len)
186                 return;
187
188         if (*buf) {
189                 *buf_len = 0;
190                 kfree(*buf);
191                 *buf = NULL;
192         }
193 }
194
195 void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len)
196 {
197         u32 ori_len = 0, dup_len = 0;
198         u8 *ori = NULL;
199         u8 *dup = NULL;
200
201         if (!buf || !buf_len)
202                 return;
203
204         if (!src || !src_len)
205                 goto keep_ori;
206
207         /* duplicate src */
208         dup = rtw_malloc(src_len);
209         if (dup) {
210                 dup_len = src_len;
211                 memcpy(dup, src, dup_len);
212         }
213
214 keep_ori:
215         ori = *buf;
216         ori_len = *buf_len;
217
218         /* replace buf with dup */
219         *buf_len = 0;
220         *buf = dup;
221         *buf_len = dup_len;
222
223         /* free ori */
224         if (ori && ori_len > 0)
225                 kfree(ori);
226 }
227
228
229 /**
230  * rtw_cbuf_full - test if cbuf is full
231  * @cbuf: pointer of struct rtw_cbuf
232  *
233  * Returns: true if cbuf is full
234  */
235 inline bool rtw_cbuf_full(struct rtw_cbuf *cbuf)
236 {
237         return (cbuf->write == cbuf->read - 1) ? true : false;
238 }
239
240 /**
241  * rtw_cbuf_empty - test if cbuf is empty
242  * @cbuf: pointer of struct rtw_cbuf
243  *
244  * Returns: true if cbuf is empty
245  */
246 inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf)
247 {
248         return (cbuf->write == cbuf->read) ? true : false;
249 }
250
251 /**
252  * rtw_cbuf_push - push a pointer into cbuf
253  * @cbuf: pointer of struct rtw_cbuf
254  * @buf: pointer to push in
255  *
256  * Lock free operation, be careful of the use scheme
257  * Returns: true push success
258  */
259 bool rtw_cbuf_push(struct rtw_cbuf *cbuf, void *buf)
260 {
261         if (rtw_cbuf_full(cbuf))
262                 return _FAIL;
263
264         DBG_871X("%s on %u\n", __func__, cbuf->write);
265         cbuf->bufs[cbuf->write] = buf;
266         cbuf->write = (cbuf->write + 1) % cbuf->size;
267
268         return _SUCCESS;
269 }
270
271 /**
272  * rtw_cbuf_pop - pop a pointer from cbuf
273  * @cbuf: pointer of struct rtw_cbuf
274  *
275  * Lock free operation, be careful of the use scheme
276  * Returns: pointer popped out
277  */
278 void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)
279 {
280         void *buf;
281         if (rtw_cbuf_empty(cbuf))
282                 return NULL;
283
284         DBG_871X("%s on %u\n", __func__, cbuf->read);
285         buf = cbuf->bufs[cbuf->read];
286         cbuf->read = (cbuf->read + 1) % cbuf->size;
287
288         return buf;
289 }
290
291 /**
292  * rtw_cbuf_alloc - allocte a rtw_cbuf with given size and do initialization
293  * @size: size of pointer
294  *
295  * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
296  */
297 struct rtw_cbuf *rtw_cbuf_alloc(u32 size)
298 {
299         struct rtw_cbuf *cbuf;
300
301         cbuf = rtw_malloc(sizeof(*cbuf) + sizeof(void *) * size);
302
303         if (cbuf) {
304                 cbuf->write = cbuf->read = 0;
305                 cbuf->size = size;
306         }
307
308         return cbuf;
309 }