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