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