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_buf_free(u8 ** buf,u32 * buf_len)111 void rtw_buf_free(u8 **buf, u32 *buf_len)
112 {
113 	if (!buf || !buf_len)
114 		return;
115 
116 	if (*buf) {
117 		*buf_len = 0;
118 		kfree(*buf);
119 		*buf = NULL;
120 	}
121 }
122 
rtw_buf_update(u8 ** buf,u32 * buf_len,u8 * src,u32 src_len)123 void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len)
124 {
125 	u32 ori_len = 0, dup_len = 0;
126 	u8 *ori = NULL;
127 	u8 *dup = NULL;
128 
129 	if (!buf || !buf_len)
130 		return;
131 
132 	if (!src || !src_len)
133 		goto keep_ori;
134 
135 	/* duplicate src */
136 	dup = rtw_malloc(src_len);
137 	if (dup) {
138 		dup_len = src_len;
139 		memcpy(dup, src, dup_len);
140 	}
141 
142 keep_ori:
143 	ori = *buf;
144 	ori_len = *buf_len;
145 
146 	/* replace buf with dup */
147 	*buf_len = 0;
148 	*buf = dup;
149 	*buf_len = dup_len;
150 
151 	/* free ori */
152 	if (ori && ori_len > 0)
153 		kfree(ori);
154 }
155 
156 
157 /**
158  * rtw_cbuf_full - test if cbuf is full
159  * @cbuf: pointer of struct rtw_cbuf
160  *
161  * Returns: true if cbuf is full
162  */
rtw_cbuf_full(struct rtw_cbuf * cbuf)163 inline bool rtw_cbuf_full(struct rtw_cbuf *cbuf)
164 {
165 	return (cbuf->write == cbuf->read - 1) ? true : false;
166 }
167 
168 /**
169  * rtw_cbuf_empty - test if cbuf is empty
170  * @cbuf: pointer of struct rtw_cbuf
171  *
172  * Returns: true if cbuf is empty
173  */
rtw_cbuf_empty(struct rtw_cbuf * cbuf)174 inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf)
175 {
176 	return (cbuf->write == cbuf->read) ? true : false;
177 }
178 
179 /**
180  * rtw_cbuf_push - push a pointer into cbuf
181  * @cbuf: pointer of struct rtw_cbuf
182  * @buf: pointer to push in
183  *
184  * Lock free operation, be careful of the use scheme
185  * Returns: true push success
186  */
rtw_cbuf_push(struct rtw_cbuf * cbuf,void * buf)187 bool rtw_cbuf_push(struct rtw_cbuf *cbuf, void *buf)
188 {
189 	if (rtw_cbuf_full(cbuf))
190 		return _FAIL;
191 
192 	cbuf->bufs[cbuf->write] = buf;
193 	cbuf->write = (cbuf->write + 1) % cbuf->size;
194 
195 	return _SUCCESS;
196 }
197 
198 /**
199  * rtw_cbuf_pop - pop a pointer from cbuf
200  * @cbuf: pointer of struct rtw_cbuf
201  *
202  * Lock free operation, be careful of the use scheme
203  * Returns: pointer popped out
204  */
rtw_cbuf_pop(struct rtw_cbuf * cbuf)205 void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)
206 {
207 	void *buf;
208 	if (rtw_cbuf_empty(cbuf))
209 		return NULL;
210 
211 	buf = cbuf->bufs[cbuf->read];
212 	cbuf->read = (cbuf->read + 1) % cbuf->size;
213 
214 	return buf;
215 }
216 
217 /**
218  * rtw_cbuf_alloc - allocate a rtw_cbuf with given size and do initialization
219  * @size: size of pointer
220  *
221  * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
222  */
rtw_cbuf_alloc(u32 size)223 struct rtw_cbuf *rtw_cbuf_alloc(u32 size)
224 {
225 	struct rtw_cbuf *cbuf;
226 
227 	cbuf = rtw_malloc(struct_size(cbuf, bufs, size));
228 
229 	if (cbuf) {
230 		cbuf->write = cbuf->read = 0;
231 		cbuf->size = size;
232 	}
233 
234 	return cbuf;
235 }
236