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_usleep_os(int us)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 
rtw_alloc_etherdev_with_old_priv(int sizeof_priv,void * old_priv)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 
rtw_alloc_etherdev(int sizeof_priv)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 
rtw_free_netdev(struct net_device * netdev)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 
rtw_change_ifname(struct adapter * padapter,const char * ifname)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 
rtw_buf_update(u8 ** buf,u32 * buf_len,u8 * src,u32 src_len)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  */
rtw_cbuf_empty(struct rtw_cbuf * cbuf)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  */
rtw_cbuf_pop(struct rtw_cbuf * cbuf)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  */
rtw_cbuf_alloc(u32 size)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 }
239