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