1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #include <drv_types.h>
8 #include <rtw_debug.h>
9 
10 /*
11 * Translate the OS dependent @param error_code to OS independent RTW_STATUS_CODE
12 * @return: one of RTW_STATUS_CODE
13 */
RTW_STATUS_CODE(int error_code)14 inline int RTW_STATUS_CODE(int error_code)
15 {
16 	if (error_code >= 0)
17 		return _SUCCESS;
18 	return _FAIL;
19 }
20 
_rtw_malloc(u32 sz)21 void *_rtw_malloc(u32 sz)
22 {
23 	return kmalloc(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
24 }
25 
_rtw_zmalloc(u32 sz)26 void *_rtw_zmalloc(u32 sz)
27 {
28 	void *pbuf = _rtw_malloc(sz);
29 
30 	if (pbuf)
31 		memset(pbuf, 0, sz);
32 
33 	return pbuf;
34 }
35 
_rtw_skb_alloc(u32 sz)36 inline struct sk_buff *_rtw_skb_alloc(u32 sz)
37 {
38 	return __dev_alloc_skb(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
39 }
40 
_rtw_skb_copy(const struct sk_buff * skb)41 inline struct sk_buff *_rtw_skb_copy(const struct sk_buff *skb)
42 {
43 	return skb_copy(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
44 }
45 
_rtw_netif_rx(struct net_device * ndev,struct sk_buff * skb)46 inline int _rtw_netif_rx(struct net_device *ndev, struct sk_buff *skb)
47 {
48 	skb->dev = ndev;
49 	return netif_rx(skb);
50 }
51 
rtw_alloc_etherdev_with_old_priv(int sizeof_priv,void * old_priv)52 struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, void *old_priv)
53 {
54 	struct net_device *pnetdev;
55 	struct rtw_netdev_priv_indicator *pnpi;
56 
57 	pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
58 	if (!pnetdev)
59 		goto RETURN;
60 
61 	pnpi = netdev_priv(pnetdev);
62 	pnpi->priv = old_priv;
63 	pnpi->sizeof_priv = sizeof_priv;
64 
65 RETURN:
66 	return pnetdev;
67 }
68 
rtw_alloc_etherdev(int sizeof_priv)69 struct net_device *rtw_alloc_etherdev(int sizeof_priv)
70 {
71 	struct net_device *pnetdev;
72 	struct rtw_netdev_priv_indicator *pnpi;
73 
74 	pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
75 	if (!pnetdev)
76 		goto RETURN;
77 
78 	pnpi = netdev_priv(pnetdev);
79 
80 	pnpi->priv = vzalloc(sizeof_priv);
81 	if (!pnpi->priv) {
82 		free_netdev(pnetdev);
83 		pnetdev = NULL;
84 		goto RETURN;
85 	}
86 
87 	pnpi->sizeof_priv = sizeof_priv;
88 RETURN:
89 	return pnetdev;
90 }
91 
rtw_free_netdev(struct net_device * netdev)92 void rtw_free_netdev(struct net_device *netdev)
93 {
94 	struct rtw_netdev_priv_indicator *pnpi;
95 
96 	if (!netdev)
97 		goto RETURN;
98 
99 	pnpi = netdev_priv(netdev);
100 
101 	if (!pnpi->priv)
102 		goto RETURN;
103 
104 	vfree(pnpi->priv);
105 	free_netdev(netdev);
106 
107 RETURN:
108 	return;
109 }
110 
rtw_change_ifname(struct adapter * padapter,const char * ifname)111 int rtw_change_ifname(struct adapter *padapter, const char *ifname)
112 {
113 	struct net_device *pnetdev;
114 	struct net_device *cur_pnetdev;
115 	struct rereg_nd_name_data *rereg_priv;
116 	int ret;
117 
118 	if (!padapter)
119 		goto error;
120 
121 	cur_pnetdev = padapter->pnetdev;
122 	rereg_priv = &padapter->rereg_nd_name_priv;
123 
124 	/* free the old_pnetdev */
125 	if (rereg_priv->old_pnetdev) {
126 		free_netdev(rereg_priv->old_pnetdev);
127 		rereg_priv->old_pnetdev = NULL;
128 	}
129 
130 	if (!rtnl_is_locked())
131 		unregister_netdev(cur_pnetdev);
132 	else
133 		unregister_netdevice(cur_pnetdev);
134 
135 	rereg_priv->old_pnetdev = cur_pnetdev;
136 
137 	pnetdev = rtw_init_netdev(padapter);
138 	if (!pnetdev)
139 		goto error;
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 
152 	if (ret != 0)
153 		goto error;
154 
155 	return 0;
156 
157 error:
158 	return -1;
159 }
160 
rtw_buf_free(u8 ** buf,u32 * buf_len)161 void rtw_buf_free(u8 **buf, u32 *buf_len)
162 {
163 	if (!buf || !buf_len)
164 		return;
165 
166 	if (*buf) {
167 		*buf_len = 0;
168 		kfree(*buf);
169 		*buf = NULL;
170 	}
171 }
172 
rtw_buf_update(u8 ** buf,u32 * buf_len,u8 * src,u32 src_len)173 void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len)
174 {
175 	u32 ori_len = 0, dup_len = 0;
176 	u8 *ori = NULL;
177 	u8 *dup = NULL;
178 
179 	if (!buf || !buf_len)
180 		return;
181 
182 	if (!src || !src_len)
183 		goto keep_ori;
184 
185 	/* duplicate src */
186 	dup = rtw_malloc(src_len);
187 	if (dup) {
188 		dup_len = src_len;
189 		memcpy(dup, src, dup_len);
190 	}
191 
192 keep_ori:
193 	ori = *buf;
194 	ori_len = *buf_len;
195 
196 	/* replace buf with dup */
197 	*buf_len = 0;
198 	*buf = dup;
199 	*buf_len = dup_len;
200 
201 	/* free ori */
202 	if (ori && ori_len > 0)
203 		kfree(ori);
204 }
205 
206 
207 /**
208  * rtw_cbuf_full - test if cbuf is full
209  * @cbuf: pointer of struct rtw_cbuf
210  *
211  * Returns: true if cbuf is full
212  */
rtw_cbuf_full(struct rtw_cbuf * cbuf)213 inline bool rtw_cbuf_full(struct rtw_cbuf *cbuf)
214 {
215 	return (cbuf->write == cbuf->read - 1) ? true : false;
216 }
217 
218 /**
219  * rtw_cbuf_empty - test if cbuf is empty
220  * @cbuf: pointer of struct rtw_cbuf
221  *
222  * Returns: true if cbuf is empty
223  */
rtw_cbuf_empty(struct rtw_cbuf * cbuf)224 inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf)
225 {
226 	return (cbuf->write == cbuf->read) ? true : false;
227 }
228 
229 /**
230  * rtw_cbuf_push - push a pointer into cbuf
231  * @cbuf: pointer of struct rtw_cbuf
232  * @buf: pointer to push in
233  *
234  * Lock free operation, be careful of the use scheme
235  * Returns: true push success
236  */
rtw_cbuf_push(struct rtw_cbuf * cbuf,void * buf)237 bool rtw_cbuf_push(struct rtw_cbuf *cbuf, void *buf)
238 {
239 	if (rtw_cbuf_full(cbuf))
240 		return _FAIL;
241 
242 	cbuf->bufs[cbuf->write] = buf;
243 	cbuf->write = (cbuf->write + 1) % cbuf->size;
244 
245 	return _SUCCESS;
246 }
247 
248 /**
249  * rtw_cbuf_pop - pop a pointer from cbuf
250  * @cbuf: pointer of struct rtw_cbuf
251  *
252  * Lock free operation, be careful of the use scheme
253  * Returns: pointer popped out
254  */
rtw_cbuf_pop(struct rtw_cbuf * cbuf)255 void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)
256 {
257 	void *buf;
258 	if (rtw_cbuf_empty(cbuf))
259 		return NULL;
260 
261 	buf = cbuf->bufs[cbuf->read];
262 	cbuf->read = (cbuf->read + 1) % cbuf->size;
263 
264 	return buf;
265 }
266 
267 /**
268  * rtw_cbuf_alloc - allocate a rtw_cbuf with given size and do initialization
269  * @size: size of pointer
270  *
271  * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
272  */
rtw_cbuf_alloc(u32 size)273 struct rtw_cbuf *rtw_cbuf_alloc(u32 size)
274 {
275 	struct rtw_cbuf *cbuf;
276 
277 	cbuf = rtw_malloc(struct_size(cbuf, bufs, size));
278 
279 	if (cbuf) {
280 		cbuf->write = cbuf->read = 0;
281 		cbuf->size = size;
282 	}
283 
284 	return cbuf;
285 }
286