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*/ 14inline int RTW_STATUS_CODE(int error_code) 15{ 16 if (error_code >= 0) 17 return _SUCCESS; 18 return _FAIL; 19} 20 21void *_rtw_malloc(u32 sz) 22{ 23 return kmalloc(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); 24} 25 26void *_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 36inline struct sk_buff *_rtw_skb_alloc(u32 sz) 37{ 38 return __dev_alloc_skb(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); 39} 40 41inline 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 46inline int _rtw_netif_rx(struct net_device *ndev, struct sk_buff *skb) 47{ 48 skb->dev = ndev; 49 return netif_rx(skb); 50} 51 52struct 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 65RETURN: 66 return pnetdev; 67} 68 69struct 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; 88RETURN: 89 return pnetdev; 90} 91 92void 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 107RETURN: 108 return; 109} 110 111void 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 123void 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 142keep_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 */ 163inline 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 */ 174inline 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 */ 187bool 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 */ 205void *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 */ 223struct 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