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 */
RTW_STATUS_CODE(int error_code)15 inline int RTW_STATUS_CODE(int error_code)
16 {
17 if (error_code >= 0)
18 return _SUCCESS;
19 return _FAIL;
20 }
21
rtw_malloc2d(int h,int w,int size)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
rtw_systime_to_ms(u32 systime)45 inline u32 rtw_systime_to_ms(u32 systime)
46 {
47 return systime * 1000 / HZ;
48 }
49
rtw_ms_to_systime(u32 ms)50 inline u32 rtw_ms_to_systime(u32 ms)
51 {
52 return ms * HZ / 1000;
53 }
54
55 /* the input parameter start use the same unit as jiffies */
rtw_get_passing_time_ms(u32 start)56 inline s32 rtw_get_passing_time_ms(u32 start)
57 {
58 return rtw_systime_to_ms(jiffies - start);
59 }
60
rtw_usleep_os(int us)61 void rtw_usleep_os(int us)
62 {
63 if (1 < (us / 1000))
64 msleep(1);
65 else
66 msleep((us / 1000) + 1);
67 }
68
69 static const struct device_type wlan_type = {
70 .name = "wlan",
71 };
72
rtw_alloc_etherdev_with_old_priv(int sizeof_priv,void * old_priv)73 struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv,
74 void *old_priv)
75 {
76 struct net_device *pnetdev;
77 struct rtw_netdev_priv_indicator *pnpi;
78
79 pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
80 if (!pnetdev)
81 goto RETURN;
82
83 pnetdev->dev.type = &wlan_type;
84 pnpi = netdev_priv(pnetdev);
85 pnpi->priv = old_priv;
86 pnpi->sizeof_priv = sizeof_priv;
87
88 RETURN:
89 return pnetdev;
90 }
91
rtw_alloc_etherdev(int sizeof_priv)92 struct net_device *rtw_alloc_etherdev(int sizeof_priv)
93 {
94 struct net_device *pnetdev;
95 struct rtw_netdev_priv_indicator *pnpi;
96
97 pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
98 if (!pnetdev)
99 goto RETURN;
100
101 pnpi = netdev_priv(pnetdev);
102
103 pnpi->priv = vzalloc(sizeof_priv);
104 if (!pnpi->priv) {
105 free_netdev(pnetdev);
106 pnetdev = NULL;
107 goto RETURN;
108 }
109
110 pnpi->sizeof_priv = sizeof_priv;
111 RETURN:
112 return pnetdev;
113 }
114
rtw_free_netdev(struct net_device * netdev)115 void rtw_free_netdev(struct net_device *netdev)
116 {
117 struct rtw_netdev_priv_indicator *pnpi;
118
119 if (!netdev)
120 goto RETURN;
121
122 pnpi = netdev_priv(netdev);
123
124 if (!pnpi->priv)
125 goto RETURN;
126
127 vfree(pnpi->priv);
128 free_netdev(netdev);
129
130 RETURN:
131 return;
132 }
133
rtw_change_ifname(struct adapter * padapter,const char * ifname)134 int rtw_change_ifname(struct adapter *padapter, const char *ifname)
135 {
136 struct net_device *pnetdev;
137 struct net_device *cur_pnetdev;
138 struct rereg_nd_name_data *rereg_priv;
139 int ret;
140
141 if (!padapter)
142 goto error;
143
144 cur_pnetdev = padapter->pnetdev;
145 rereg_priv = &padapter->rereg_nd_name_priv;
146
147 /* free the old_pnetdev */
148 if (rereg_priv->old_pnetdev) {
149 free_netdev(rereg_priv->old_pnetdev);
150 rereg_priv->old_pnetdev = NULL;
151 }
152
153 if (!rtnl_is_locked())
154 unregister_netdev(cur_pnetdev);
155 else
156 unregister_netdevice(cur_pnetdev);
157
158 rereg_priv->old_pnetdev = cur_pnetdev;
159
160 pnetdev = rtw_init_netdev(padapter);
161 if (!pnetdev) {
162 ret = -1;
163 goto error;
164 }
165
166 SET_NETDEV_DEV(pnetdev, dvobj_to_dev(adapter_to_dvobj(padapter)));
167
168 rtw_init_netdev_name(pnetdev, ifname);
169
170 eth_hw_addr_set(pnetdev, padapter->eeprompriv.mac_addr);
171
172 if (!rtnl_is_locked())
173 ret = register_netdev(pnetdev);
174 else
175 ret = register_netdevice(pnetdev);
176 if (ret != 0)
177 goto error;
178
179 return 0;
180 error:
181 return -1;
182 }
183
rtw_buf_update(u8 ** buf,u32 * buf_len,u8 * src,u32 src_len)184 void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len)
185 {
186 u32 dup_len = 0;
187 u8 *ori = NULL;
188 u8 *dup = NULL;
189
190 if (!buf || !buf_len)
191 return;
192
193 if (!src || !src_len)
194 goto keep_ori;
195
196 /* duplicate src */
197 dup = kmalloc(src_len, GFP_ATOMIC);
198 if (dup) {
199 dup_len = src_len;
200 memcpy(dup, src, dup_len);
201 }
202
203 keep_ori:
204 ori = *buf;
205
206 /* replace buf with dup */
207 *buf_len = 0;
208 *buf = dup;
209 *buf_len = dup_len;
210
211 /* free ori */
212 kfree(ori);
213 }
214
215 /**
216 * rtw_cbuf_empty - test if cbuf is empty
217 * @cbuf: pointer of struct rtw_cbuf
218 *
219 * Returns: true if cbuf is empty
220 */
rtw_cbuf_empty(struct rtw_cbuf * cbuf)221 inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf)
222 {
223 return (cbuf->write == cbuf->read) ? true : false;
224 }
225
226 /**
227 * rtw_cbuf_pop - pop a pointer from cbuf
228 * @cbuf: pointer of struct rtw_cbuf
229 *
230 * Lock free operation, be careful of the use scheme
231 * Returns: pointer popped out
232 */
rtw_cbuf_pop(struct rtw_cbuf * cbuf)233 void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)
234 {
235 void *buf;
236 if (rtw_cbuf_empty(cbuf))
237 return NULL;
238
239 if (0)
240 DBG_88E("%s on %u\n", __func__, cbuf->read);
241 buf = cbuf->bufs[cbuf->read];
242 cbuf->read = (cbuf->read + 1) % cbuf->size;
243
244 return buf;
245 }
246
247 /**
248 * rtw_cbuf_alloc - allocate a rtw_cbuf with given size and do initialization
249 * @size: size of pointer
250 *
251 * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
252 */
rtw_cbuf_alloc(u32 size)253 struct rtw_cbuf *rtw_cbuf_alloc(u32 size)
254 {
255 struct rtw_cbuf *cbuf;
256
257 cbuf = kmalloc(struct_size(cbuf, bufs, size), GFP_KERNEL);
258
259 if (cbuf) {
260 cbuf->write = 0;
261 cbuf->read = 0;
262 cbuf->size = size;
263 }
264 return cbuf;
265 }
266