GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / staging / r8188eu / os_dep / osdep_service.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2012 Realtek Corporation. */
3
4 #define _OSDEP_SERVICE_C_
5
6 #include "../include/osdep_service.h"
7 #include "../include/drv_types.h"
8 #include "../include/recv_osdep.h"
9 #include "../include/rtw_ioctl_set.h"
10
11 /*
12 * Translate the OS dependent @param error_code to OS independent RTW_STATUS_CODE
13 * @return: one of RTW_STATUS_CODE
14 */
15 inline int RTW_STATUS_CODE(int error_code)
16 {
17         if (error_code >= 0)
18                 return _SUCCESS;
19         return _FAIL;
20 }
21
22 void *rtw_malloc2d(int h, int w, int size)
23 {
24         int j;
25
26         void **a = kzalloc(h * sizeof(void *) + h * w * size, GFP_KERNEL);
27         if (!a)
28                 return NULL;
29
30         for (j = 0; j < h; j++)
31                 a[j] = ((char *)(a + h)) + j * w * size;
32
33         return a;
34 }
35
36 /*
37 For the following list_xxx operations,
38 caller must guarantee the atomic context.
39 Otherwise, there will be racing condition.
40 */
41 /*
42 Caller must check if the list is empty before calling rtw_list_delete
43 */
44
45 void rtw_usleep_os(int us)
46 {
47         if (1 < (us / 1000))
48                 msleep(1);
49         else
50                 msleep((us / 1000) + 1);
51 }
52
53 static const struct device_type wlan_type = {
54         .name = "wlan",
55 };
56
57 struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv,
58                                                     void *old_priv)
59 {
60         struct net_device *pnetdev;
61         struct rtw_netdev_priv_indicator *pnpi;
62
63         pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
64         if (!pnetdev)
65                 goto RETURN;
66
67         pnetdev->dev.type = &wlan_type;
68         pnpi = netdev_priv(pnetdev);
69         pnpi->priv = old_priv;
70         pnpi->sizeof_priv = sizeof_priv;
71
72 RETURN:
73         return pnetdev;
74 }
75
76 struct net_device *rtw_alloc_etherdev(int sizeof_priv)
77 {
78         struct net_device *pnetdev;
79         struct rtw_netdev_priv_indicator *pnpi;
80
81         pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
82         if (!pnetdev)
83                 goto RETURN;
84
85         pnpi = netdev_priv(pnetdev);
86
87         pnpi->priv = vzalloc(sizeof_priv);
88         if (!pnpi->priv) {
89                 free_netdev(pnetdev);
90                 pnetdev = NULL;
91                 goto RETURN;
92         }
93
94         pnpi->sizeof_priv = sizeof_priv;
95 RETURN:
96         return pnetdev;
97 }
98
99 void rtw_free_netdev(struct net_device *netdev)
100 {
101         struct rtw_netdev_priv_indicator *pnpi;
102
103         pnpi = netdev_priv(netdev);
104
105         vfree(pnpi->priv);
106         free_netdev(netdev);
107 }
108
109 int rtw_change_ifname(struct adapter *padapter, const char *ifname)
110 {
111         struct net_device *pnetdev;
112         struct net_device *cur_pnetdev;
113         struct rereg_nd_name_data *rereg_priv;
114         int ret;
115
116         if (!padapter)
117                 goto error;
118
119         cur_pnetdev = padapter->pnetdev;
120         rereg_priv = &padapter->rereg_nd_name_priv;
121
122         /* free the old_pnetdev */
123         if (rereg_priv->old_pnetdev) {
124                 free_netdev(rereg_priv->old_pnetdev);
125                 rereg_priv->old_pnetdev = NULL;
126         }
127
128         if (!rtnl_is_locked())
129                 unregister_netdev(cur_pnetdev);
130         else
131                 unregister_netdevice(cur_pnetdev);
132
133         rereg_priv->old_pnetdev = cur_pnetdev;
134
135         pnetdev = rtw_init_netdev(padapter);
136         if (!pnetdev)  {
137                 ret = -1;
138                 goto error;
139         }
140
141         SET_NETDEV_DEV(pnetdev, dvobj_to_dev(adapter_to_dvobj(padapter)));
142
143         rtw_init_netdev_name(pnetdev, ifname);
144
145         eth_hw_addr_set(pnetdev, padapter->eeprompriv.mac_addr);
146
147         if (!rtnl_is_locked())
148                 ret = register_netdev(pnetdev);
149         else
150                 ret = register_netdevice(pnetdev);
151         if (ret != 0)
152                 goto error;
153
154         return 0;
155 error:
156         return -1;
157 }
158
159 void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len)
160 {
161         u32 dup_len = 0;
162         u8 *ori = NULL;
163         u8 *dup = NULL;
164
165         if (!buf || !buf_len)
166                 return;
167
168         if (!src || !src_len)
169                 goto keep_ori;
170
171         /* duplicate src */
172         dup = kmalloc(src_len, GFP_ATOMIC);
173         if (dup) {
174                 dup_len = src_len;
175                 memcpy(dup, src, dup_len);
176         }
177
178 keep_ori:
179         ori = *buf;
180
181         /* replace buf with dup */
182         *buf_len = 0;
183         *buf = dup;
184         *buf_len = dup_len;
185
186         /* free ori */
187         kfree(ori);
188 }
189
190 /**
191  * rtw_cbuf_empty - test if cbuf is empty
192  * @cbuf: pointer of struct rtw_cbuf
193  *
194  * Returns: true if cbuf is empty
195  */
196 inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf)
197 {
198         return cbuf->write == cbuf->read;
199 }
200
201 /**
202  * rtw_cbuf_pop - pop a pointer from cbuf
203  * @cbuf: pointer of struct rtw_cbuf
204  *
205  * Lock free operation, be careful of the use scheme
206  * Returns: pointer popped out
207  */
208 void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)
209 {
210         void *buf;
211         if (rtw_cbuf_empty(cbuf))
212                 return NULL;
213
214         buf = cbuf->bufs[cbuf->read];
215         cbuf->read = (cbuf->read + 1) % cbuf->size;
216
217         return buf;
218 }
219
220 /**
221  * rtw_cbuf_alloc - allocate a rtw_cbuf with given size and do initialization
222  * @size: size of pointer
223  *
224  * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
225  */
226 struct rtw_cbuf *rtw_cbuf_alloc(u32 size)
227 {
228         struct rtw_cbuf *cbuf;
229
230         cbuf = kmalloc(struct_size(cbuf, bufs, size), GFP_KERNEL);
231
232         if (cbuf) {
233                 cbuf->write = 0;
234                 cbuf->read = 0;
235                 cbuf->size = size;
236         }
237         return cbuf;
238 }