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 */
RTW_STATUS_CODE(int error_code)18 inline int RTW_STATUS_CODE(int error_code)
19 {
20 	if (error_code >= 0)
21 		return _SUCCESS;
22 	return _FAIL;
23 }
24 
_rtw_malloc(u32 sz)25 void *_rtw_malloc(u32 sz)
26 {
27 	return kmalloc(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
28 }
29 
_rtw_zmalloc(u32 sz)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 
_rtw_skb_alloc(u32 sz)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 
_rtw_skb_copy(const struct sk_buff * skb)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 
_rtw_netif_rx(struct net_device * ndev,struct sk_buff * skb)50 inline int _rtw_netif_rx(struct net_device *ndev, struct sk_buff *skb)
51 {
52 	skb->dev = ndev;
53 	return netif_rx(skb);
54 }
55 
_rtw_init_queue(struct __queue * pqueue)56 void _rtw_init_queue(struct __queue *pqueue)
57 {
58 	INIT_LIST_HEAD(&(pqueue->queue));
59 
60 	spin_lock_init(&(pqueue->lock));
61 }
62 
rtw_alloc_etherdev_with_old_priv(int sizeof_priv,void * old_priv)63 struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, void *old_priv)
64 {
65 	struct net_device *pnetdev;
66 	struct rtw_netdev_priv_indicator *pnpi;
67 
68 	pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
69 	if (!pnetdev)
70 		goto RETURN;
71 
72 	pnpi = netdev_priv(pnetdev);
73 	pnpi->priv = old_priv;
74 	pnpi->sizeof_priv = sizeof_priv;
75 
76 RETURN:
77 	return pnetdev;
78 }
79 
rtw_alloc_etherdev(int sizeof_priv)80 struct net_device *rtw_alloc_etherdev(int sizeof_priv)
81 {
82 	struct net_device *pnetdev;
83 	struct rtw_netdev_priv_indicator *pnpi;
84 
85 	pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
86 	if (!pnetdev)
87 		goto RETURN;
88 
89 	pnpi = netdev_priv(pnetdev);
90 
91 	pnpi->priv = vzalloc(sizeof_priv);
92 	if (!pnpi->priv) {
93 		free_netdev(pnetdev);
94 		pnetdev = NULL;
95 		goto RETURN;
96 	}
97 
98 	pnpi->sizeof_priv = sizeof_priv;
99 RETURN:
100 	return pnetdev;
101 }
102 
rtw_free_netdev(struct net_device * netdev)103 void rtw_free_netdev(struct net_device *netdev)
104 {
105 	struct rtw_netdev_priv_indicator *pnpi;
106 
107 	if (!netdev)
108 		goto RETURN;
109 
110 	pnpi = netdev_priv(netdev);
111 
112 	if (!pnpi->priv)
113 		goto RETURN;
114 
115 	vfree(pnpi->priv);
116 	free_netdev(netdev);
117 
118 RETURN:
119 	return;
120 }
121 
rtw_change_ifname(struct adapter * padapter,const char * ifname)122 int rtw_change_ifname(struct adapter *padapter, const char *ifname)
123 {
124 	struct net_device *pnetdev;
125 	struct net_device *cur_pnetdev;
126 	struct rereg_nd_name_data *rereg_priv;
127 	int ret;
128 
129 	if (!padapter)
130 		goto error;
131 
132 	cur_pnetdev = padapter->pnetdev;
133 	rereg_priv = &padapter->rereg_nd_name_priv;
134 
135 	/* free the old_pnetdev */
136 	if (rereg_priv->old_pnetdev) {
137 		free_netdev(rereg_priv->old_pnetdev);
138 		rereg_priv->old_pnetdev = NULL;
139 	}
140 
141 	if (!rtnl_is_locked())
142 		unregister_netdev(cur_pnetdev);
143 	else
144 		unregister_netdevice(cur_pnetdev);
145 
146 	rereg_priv->old_pnetdev = cur_pnetdev;
147 
148 	pnetdev = rtw_init_netdev(padapter);
149 	if (!pnetdev)
150 		goto error;
151 
152 	SET_NETDEV_DEV(pnetdev, dvobj_to_dev(adapter_to_dvobj(padapter)));
153 
154 	rtw_init_netdev_name(pnetdev, ifname);
155 
156 	memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
157 
158 	if (!rtnl_is_locked())
159 		ret = register_netdev(pnetdev);
160 	else
161 		ret = register_netdevice(pnetdev);
162 
163 	if (ret != 0)
164 		goto error;
165 
166 	return 0;
167 
168 error:
169 	return -1;
170 }
171 
rtw_buf_free(u8 ** buf,u32 * buf_len)172 void rtw_buf_free(u8 **buf, u32 *buf_len)
173 {
174 	if (!buf || !buf_len)
175 		return;
176 
177 	if (*buf) {
178 		*buf_len = 0;
179 		kfree(*buf);
180 		*buf = NULL;
181 	}
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 ori_len = 0, 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 = rtw_malloc(src_len);
198 	if (dup) {
199 		dup_len = src_len;
200 		memcpy(dup, src, dup_len);
201 	}
202 
203 keep_ori:
204 	ori = *buf;
205 	ori_len = *buf_len;
206 
207 	/* replace buf with dup */
208 	*buf_len = 0;
209 	*buf = dup;
210 	*buf_len = dup_len;
211 
212 	/* free ori */
213 	if (ori && ori_len > 0)
214 		kfree(ori);
215 }
216 
217 
218 /**
219  * rtw_cbuf_full - test if cbuf is full
220  * @cbuf: pointer of struct rtw_cbuf
221  *
222  * Returns: true if cbuf is full
223  */
rtw_cbuf_full(struct rtw_cbuf * cbuf)224 inline bool rtw_cbuf_full(struct rtw_cbuf *cbuf)
225 {
226 	return (cbuf->write == cbuf->read - 1) ? true : false;
227 }
228 
229 /**
230  * rtw_cbuf_empty - test if cbuf is empty
231  * @cbuf: pointer of struct rtw_cbuf
232  *
233  * Returns: true if cbuf is empty
234  */
rtw_cbuf_empty(struct rtw_cbuf * cbuf)235 inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf)
236 {
237 	return (cbuf->write == cbuf->read) ? true : false;
238 }
239 
240 /**
241  * rtw_cbuf_push - push a pointer into cbuf
242  * @cbuf: pointer of struct rtw_cbuf
243  * @buf: pointer to push in
244  *
245  * Lock free operation, be careful of the use scheme
246  * Returns: true push success
247  */
rtw_cbuf_push(struct rtw_cbuf * cbuf,void * buf)248 bool rtw_cbuf_push(struct rtw_cbuf *cbuf, void *buf)
249 {
250 	if (rtw_cbuf_full(cbuf))
251 		return _FAIL;
252 
253 	cbuf->bufs[cbuf->write] = buf;
254 	cbuf->write = (cbuf->write + 1) % cbuf->size;
255 
256 	return _SUCCESS;
257 }
258 
259 /**
260  * rtw_cbuf_pop - pop a pointer from cbuf
261  * @cbuf: pointer of struct rtw_cbuf
262  *
263  * Lock free operation, be careful of the use scheme
264  * Returns: pointer popped out
265  */
rtw_cbuf_pop(struct rtw_cbuf * cbuf)266 void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)
267 {
268 	void *buf;
269 	if (rtw_cbuf_empty(cbuf))
270 		return NULL;
271 
272 	buf = cbuf->bufs[cbuf->read];
273 	cbuf->read = (cbuf->read + 1) % cbuf->size;
274 
275 	return buf;
276 }
277 
278 /**
279  * rtw_cbuf_alloc - allocate a rtw_cbuf with given size and do initialization
280  * @size: size of pointer
281  *
282  * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
283  */
rtw_cbuf_alloc(u32 size)284 struct rtw_cbuf *rtw_cbuf_alloc(u32 size)
285 {
286 	struct rtw_cbuf *cbuf;
287 
288 	cbuf = rtw_malloc(sizeof(*cbuf) + sizeof(void *) * size);
289 
290 	if (cbuf) {
291 		cbuf->write = cbuf->read = 0;
292 		cbuf->size = size;
293 	}
294 
295 	return cbuf;
296 }
297