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 */ 14 inline int RTW_STATUS_CODE(int error_code) 15 { 16 if (error_code >= 0) 17 return _SUCCESS; 18 return _FAIL; 19 } 20 21 void *_rtw_malloc(u32 sz) 22 { 23 return kmalloc(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); 24 } 25 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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