1b4c3e9b5SBjoern A. Zeeb // SPDX-License-Identifier: ISC
2b4c3e9b5SBjoern A. Zeeb /*
3b4c3e9b5SBjoern A. Zeeb * Copyright (c) 2010 Broadcom Corporation
4b4c3e9b5SBjoern A. Zeeb */
5b4c3e9b5SBjoern A. Zeeb
6b4c3e9b5SBjoern A. Zeeb #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7b4c3e9b5SBjoern A. Zeeb
8b4c3e9b5SBjoern A. Zeeb #include <linux/netdevice.h>
9b4c3e9b5SBjoern A. Zeeb #include <linux/module.h>
10*902136e0SBjoern A. Zeeb #if defined(__FreeBSD__)
11*902136e0SBjoern A. Zeeb #ifdef DEBUG
12*902136e0SBjoern A. Zeeb #include <linux/printk.h>
13*902136e0SBjoern A. Zeeb #endif
14*902136e0SBjoern A. Zeeb #endif
15b4c3e9b5SBjoern A. Zeeb
16b4c3e9b5SBjoern A. Zeeb #include <brcmu_utils.h>
17b4c3e9b5SBjoern A. Zeeb
18b4c3e9b5SBjoern A. Zeeb MODULE_AUTHOR("Broadcom Corporation");
19b4c3e9b5SBjoern A. Zeeb MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver utilities.");
20b4c3e9b5SBjoern A. Zeeb MODULE_LICENSE("Dual BSD/GPL");
21*902136e0SBjoern A. Zeeb #if defined(__FreeBSD__)
22*902136e0SBjoern A. Zeeb MODULE_VERSION(brcmutil, 1);
23*902136e0SBjoern A. Zeeb MODULE_DEPEND(brcmutil, linuxkpi, 1, 1, 1);
24*902136e0SBjoern A. Zeeb #endif
25b4c3e9b5SBjoern A. Zeeb
brcmu_pkt_buf_get_skb(uint len)26b4c3e9b5SBjoern A. Zeeb struct sk_buff *brcmu_pkt_buf_get_skb(uint len)
27b4c3e9b5SBjoern A. Zeeb {
28b4c3e9b5SBjoern A. Zeeb struct sk_buff *skb;
29b4c3e9b5SBjoern A. Zeeb
30b4c3e9b5SBjoern A. Zeeb skb = dev_alloc_skb(len);
31b4c3e9b5SBjoern A. Zeeb if (skb) {
32b4c3e9b5SBjoern A. Zeeb skb_put(skb, len);
33b4c3e9b5SBjoern A. Zeeb skb->priority = 0;
34b4c3e9b5SBjoern A. Zeeb }
35b4c3e9b5SBjoern A. Zeeb
36b4c3e9b5SBjoern A. Zeeb return skb;
37b4c3e9b5SBjoern A. Zeeb }
38b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_pkt_buf_get_skb);
39b4c3e9b5SBjoern A. Zeeb
40b4c3e9b5SBjoern A. Zeeb /* Free the driver packet. Free the tag if present */
brcmu_pkt_buf_free_skb(struct sk_buff * skb)41b4c3e9b5SBjoern A. Zeeb void brcmu_pkt_buf_free_skb(struct sk_buff *skb)
42b4c3e9b5SBjoern A. Zeeb {
43b4c3e9b5SBjoern A. Zeeb if (!skb)
44b4c3e9b5SBjoern A. Zeeb return;
45b4c3e9b5SBjoern A. Zeeb
46b4c3e9b5SBjoern A. Zeeb WARN_ON(skb->next);
47b4c3e9b5SBjoern A. Zeeb dev_kfree_skb_any(skb);
48b4c3e9b5SBjoern A. Zeeb }
49b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_pkt_buf_free_skb);
50b4c3e9b5SBjoern A. Zeeb
51b4c3e9b5SBjoern A. Zeeb /*
52b4c3e9b5SBjoern A. Zeeb * osl multiple-precedence packet queue
53b4c3e9b5SBjoern A. Zeeb * hi_prec is always >= the number of the highest non-empty precedence
54b4c3e9b5SBjoern A. Zeeb */
brcmu_pktq_penq(struct pktq * pq,int prec,struct sk_buff * p)55b4c3e9b5SBjoern A. Zeeb struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec,
56b4c3e9b5SBjoern A. Zeeb struct sk_buff *p)
57b4c3e9b5SBjoern A. Zeeb {
58b4c3e9b5SBjoern A. Zeeb struct sk_buff_head *q;
59b4c3e9b5SBjoern A. Zeeb
60b4c3e9b5SBjoern A. Zeeb if (pktq_full(pq) || pktq_pfull(pq, prec))
61b4c3e9b5SBjoern A. Zeeb return NULL;
62b4c3e9b5SBjoern A. Zeeb
63b4c3e9b5SBjoern A. Zeeb q = &pq->q[prec].skblist;
64b4c3e9b5SBjoern A. Zeeb skb_queue_tail(q, p);
65b4c3e9b5SBjoern A. Zeeb pq->len++;
66b4c3e9b5SBjoern A. Zeeb
67b4c3e9b5SBjoern A. Zeeb if (pq->hi_prec < prec)
68b4c3e9b5SBjoern A. Zeeb pq->hi_prec = (u8) prec;
69b4c3e9b5SBjoern A. Zeeb
70b4c3e9b5SBjoern A. Zeeb return p;
71b4c3e9b5SBjoern A. Zeeb }
72b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_pktq_penq);
73b4c3e9b5SBjoern A. Zeeb
brcmu_pktq_penq_head(struct pktq * pq,int prec,struct sk_buff * p)74b4c3e9b5SBjoern A. Zeeb struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec,
75b4c3e9b5SBjoern A. Zeeb struct sk_buff *p)
76b4c3e9b5SBjoern A. Zeeb {
77b4c3e9b5SBjoern A. Zeeb struct sk_buff_head *q;
78b4c3e9b5SBjoern A. Zeeb
79b4c3e9b5SBjoern A. Zeeb if (pktq_full(pq) || pktq_pfull(pq, prec))
80b4c3e9b5SBjoern A. Zeeb return NULL;
81b4c3e9b5SBjoern A. Zeeb
82b4c3e9b5SBjoern A. Zeeb q = &pq->q[prec].skblist;
83b4c3e9b5SBjoern A. Zeeb skb_queue_head(q, p);
84b4c3e9b5SBjoern A. Zeeb pq->len++;
85b4c3e9b5SBjoern A. Zeeb
86b4c3e9b5SBjoern A. Zeeb if (pq->hi_prec < prec)
87b4c3e9b5SBjoern A. Zeeb pq->hi_prec = (u8) prec;
88b4c3e9b5SBjoern A. Zeeb
89b4c3e9b5SBjoern A. Zeeb return p;
90b4c3e9b5SBjoern A. Zeeb }
91b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_pktq_penq_head);
92b4c3e9b5SBjoern A. Zeeb
brcmu_pktq_pdeq(struct pktq * pq,int prec)93b4c3e9b5SBjoern A. Zeeb struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec)
94b4c3e9b5SBjoern A. Zeeb {
95b4c3e9b5SBjoern A. Zeeb struct sk_buff_head *q;
96b4c3e9b5SBjoern A. Zeeb struct sk_buff *p;
97b4c3e9b5SBjoern A. Zeeb
98b4c3e9b5SBjoern A. Zeeb q = &pq->q[prec].skblist;
99b4c3e9b5SBjoern A. Zeeb p = skb_dequeue(q);
100b4c3e9b5SBjoern A. Zeeb if (p == NULL)
101b4c3e9b5SBjoern A. Zeeb return NULL;
102b4c3e9b5SBjoern A. Zeeb
103b4c3e9b5SBjoern A. Zeeb pq->len--;
104b4c3e9b5SBjoern A. Zeeb return p;
105b4c3e9b5SBjoern A. Zeeb }
106b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_pktq_pdeq);
107b4c3e9b5SBjoern A. Zeeb
108b4c3e9b5SBjoern A. Zeeb /*
109b4c3e9b5SBjoern A. Zeeb * precedence based dequeue with match function. Passing a NULL pointer
110b4c3e9b5SBjoern A. Zeeb * for the match function parameter is considered to be a wildcard so
111b4c3e9b5SBjoern A. Zeeb * any packet on the queue is returned. In that case it is no different
112b4c3e9b5SBjoern A. Zeeb * from brcmu_pktq_pdeq() above.
113b4c3e9b5SBjoern A. Zeeb */
brcmu_pktq_pdeq_match(struct pktq * pq,int prec,bool (* match_fn)(struct sk_buff * skb,void * arg),void * arg)114b4c3e9b5SBjoern A. Zeeb struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec,
115b4c3e9b5SBjoern A. Zeeb bool (*match_fn)(struct sk_buff *skb,
116b4c3e9b5SBjoern A. Zeeb void *arg), void *arg)
117b4c3e9b5SBjoern A. Zeeb {
118b4c3e9b5SBjoern A. Zeeb struct sk_buff_head *q;
119b4c3e9b5SBjoern A. Zeeb struct sk_buff *p, *next;
120b4c3e9b5SBjoern A. Zeeb
121b4c3e9b5SBjoern A. Zeeb q = &pq->q[prec].skblist;
122b4c3e9b5SBjoern A. Zeeb skb_queue_walk_safe(q, p, next) {
123b4c3e9b5SBjoern A. Zeeb if (match_fn == NULL || match_fn(p, arg)) {
124b4c3e9b5SBjoern A. Zeeb skb_unlink(p, q);
125b4c3e9b5SBjoern A. Zeeb pq->len--;
126b4c3e9b5SBjoern A. Zeeb return p;
127b4c3e9b5SBjoern A. Zeeb }
128b4c3e9b5SBjoern A. Zeeb }
129b4c3e9b5SBjoern A. Zeeb return NULL;
130b4c3e9b5SBjoern A. Zeeb }
131b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_pktq_pdeq_match);
132b4c3e9b5SBjoern A. Zeeb
brcmu_pktq_pdeq_tail(struct pktq * pq,int prec)133b4c3e9b5SBjoern A. Zeeb struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec)
134b4c3e9b5SBjoern A. Zeeb {
135b4c3e9b5SBjoern A. Zeeb struct sk_buff_head *q;
136b4c3e9b5SBjoern A. Zeeb struct sk_buff *p;
137b4c3e9b5SBjoern A. Zeeb
138b4c3e9b5SBjoern A. Zeeb q = &pq->q[prec].skblist;
139b4c3e9b5SBjoern A. Zeeb p = skb_dequeue_tail(q);
140b4c3e9b5SBjoern A. Zeeb if (p == NULL)
141b4c3e9b5SBjoern A. Zeeb return NULL;
142b4c3e9b5SBjoern A. Zeeb
143b4c3e9b5SBjoern A. Zeeb pq->len--;
144b4c3e9b5SBjoern A. Zeeb return p;
145b4c3e9b5SBjoern A. Zeeb }
146b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_pktq_pdeq_tail);
147b4c3e9b5SBjoern A. Zeeb
148b4c3e9b5SBjoern A. Zeeb void
brcmu_pktq_pflush(struct pktq * pq,int prec,bool dir,bool (* fn)(struct sk_buff *,void *),void * arg)149b4c3e9b5SBjoern A. Zeeb brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir,
150b4c3e9b5SBjoern A. Zeeb bool (*fn)(struct sk_buff *, void *), void *arg)
151b4c3e9b5SBjoern A. Zeeb {
152b4c3e9b5SBjoern A. Zeeb struct sk_buff_head *q;
153b4c3e9b5SBjoern A. Zeeb struct sk_buff *p, *next;
154b4c3e9b5SBjoern A. Zeeb
155b4c3e9b5SBjoern A. Zeeb q = &pq->q[prec].skblist;
156b4c3e9b5SBjoern A. Zeeb skb_queue_walk_safe(q, p, next) {
157b4c3e9b5SBjoern A. Zeeb if (fn == NULL || (*fn) (p, arg)) {
158b4c3e9b5SBjoern A. Zeeb skb_unlink(p, q);
159b4c3e9b5SBjoern A. Zeeb brcmu_pkt_buf_free_skb(p);
160b4c3e9b5SBjoern A. Zeeb pq->len--;
161b4c3e9b5SBjoern A. Zeeb }
162b4c3e9b5SBjoern A. Zeeb }
163b4c3e9b5SBjoern A. Zeeb }
164b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_pktq_pflush);
165b4c3e9b5SBjoern A. Zeeb
brcmu_pktq_flush(struct pktq * pq,bool dir,bool (* fn)(struct sk_buff *,void *),void * arg)166b4c3e9b5SBjoern A. Zeeb void brcmu_pktq_flush(struct pktq *pq, bool dir,
167b4c3e9b5SBjoern A. Zeeb bool (*fn)(struct sk_buff *, void *), void *arg)
168b4c3e9b5SBjoern A. Zeeb {
169b4c3e9b5SBjoern A. Zeeb int prec;
170b4c3e9b5SBjoern A. Zeeb for (prec = 0; prec < pq->num_prec; prec++)
171b4c3e9b5SBjoern A. Zeeb brcmu_pktq_pflush(pq, prec, dir, fn, arg);
172b4c3e9b5SBjoern A. Zeeb }
173b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_pktq_flush);
174b4c3e9b5SBjoern A. Zeeb
brcmu_pktq_init(struct pktq * pq,int num_prec,int max_len)175b4c3e9b5SBjoern A. Zeeb void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len)
176b4c3e9b5SBjoern A. Zeeb {
177b4c3e9b5SBjoern A. Zeeb int prec;
178b4c3e9b5SBjoern A. Zeeb
179b4c3e9b5SBjoern A. Zeeb /* pq is variable size; only zero out what's requested */
180b4c3e9b5SBjoern A. Zeeb memset(pq, 0,
181b4c3e9b5SBjoern A. Zeeb offsetof(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec));
182b4c3e9b5SBjoern A. Zeeb
183b4c3e9b5SBjoern A. Zeeb pq->num_prec = (u16) num_prec;
184b4c3e9b5SBjoern A. Zeeb
185b4c3e9b5SBjoern A. Zeeb pq->max = (u16) max_len;
186b4c3e9b5SBjoern A. Zeeb
187b4c3e9b5SBjoern A. Zeeb for (prec = 0; prec < num_prec; prec++) {
188b4c3e9b5SBjoern A. Zeeb pq->q[prec].max = pq->max;
189b4c3e9b5SBjoern A. Zeeb skb_queue_head_init(&pq->q[prec].skblist);
190b4c3e9b5SBjoern A. Zeeb }
191b4c3e9b5SBjoern A. Zeeb }
192b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_pktq_init);
193b4c3e9b5SBjoern A. Zeeb
brcmu_pktq_peek_tail(struct pktq * pq,int * prec_out)194b4c3e9b5SBjoern A. Zeeb struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out)
195b4c3e9b5SBjoern A. Zeeb {
196b4c3e9b5SBjoern A. Zeeb int prec;
197b4c3e9b5SBjoern A. Zeeb
198b4c3e9b5SBjoern A. Zeeb if (pktq_empty(pq))
199b4c3e9b5SBjoern A. Zeeb return NULL;
200b4c3e9b5SBjoern A. Zeeb
201b4c3e9b5SBjoern A. Zeeb for (prec = 0; prec < pq->hi_prec; prec++)
202b4c3e9b5SBjoern A. Zeeb if (!skb_queue_empty(&pq->q[prec].skblist))
203b4c3e9b5SBjoern A. Zeeb break;
204b4c3e9b5SBjoern A. Zeeb
205b4c3e9b5SBjoern A. Zeeb if (prec_out)
206b4c3e9b5SBjoern A. Zeeb *prec_out = prec;
207b4c3e9b5SBjoern A. Zeeb
208b4c3e9b5SBjoern A. Zeeb return skb_peek_tail(&pq->q[prec].skblist);
209b4c3e9b5SBjoern A. Zeeb }
210b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_pktq_peek_tail);
211b4c3e9b5SBjoern A. Zeeb
212b4c3e9b5SBjoern A. Zeeb /* Return sum of lengths of a specific set of precedences */
brcmu_pktq_mlen(struct pktq * pq,uint prec_bmp)213b4c3e9b5SBjoern A. Zeeb int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp)
214b4c3e9b5SBjoern A. Zeeb {
215b4c3e9b5SBjoern A. Zeeb int prec, len;
216b4c3e9b5SBjoern A. Zeeb
217b4c3e9b5SBjoern A. Zeeb len = 0;
218b4c3e9b5SBjoern A. Zeeb
219b4c3e9b5SBjoern A. Zeeb for (prec = 0; prec <= pq->hi_prec; prec++)
220b4c3e9b5SBjoern A. Zeeb if (prec_bmp & (1 << prec))
221b4c3e9b5SBjoern A. Zeeb len += pq->q[prec].skblist.qlen;
222b4c3e9b5SBjoern A. Zeeb
223b4c3e9b5SBjoern A. Zeeb return len;
224b4c3e9b5SBjoern A. Zeeb }
225b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_pktq_mlen);
226b4c3e9b5SBjoern A. Zeeb
227b4c3e9b5SBjoern A. Zeeb /* Priority dequeue from a specific set of precedences */
brcmu_pktq_mdeq(struct pktq * pq,uint prec_bmp,int * prec_out)228b4c3e9b5SBjoern A. Zeeb struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp,
229b4c3e9b5SBjoern A. Zeeb int *prec_out)
230b4c3e9b5SBjoern A. Zeeb {
231b4c3e9b5SBjoern A. Zeeb struct sk_buff_head *q;
232b4c3e9b5SBjoern A. Zeeb struct sk_buff *p;
233b4c3e9b5SBjoern A. Zeeb int prec;
234b4c3e9b5SBjoern A. Zeeb
235b4c3e9b5SBjoern A. Zeeb if (pktq_empty(pq))
236b4c3e9b5SBjoern A. Zeeb return NULL;
237b4c3e9b5SBjoern A. Zeeb
238b4c3e9b5SBjoern A. Zeeb while ((prec = pq->hi_prec) > 0 &&
239b4c3e9b5SBjoern A. Zeeb skb_queue_empty(&pq->q[prec].skblist))
240b4c3e9b5SBjoern A. Zeeb pq->hi_prec--;
241b4c3e9b5SBjoern A. Zeeb
242b4c3e9b5SBjoern A. Zeeb while ((prec_bmp & (1 << prec)) == 0 ||
243b4c3e9b5SBjoern A. Zeeb skb_queue_empty(&pq->q[prec].skblist))
244b4c3e9b5SBjoern A. Zeeb if (prec-- == 0)
245b4c3e9b5SBjoern A. Zeeb return NULL;
246b4c3e9b5SBjoern A. Zeeb
247b4c3e9b5SBjoern A. Zeeb q = &pq->q[prec].skblist;
248b4c3e9b5SBjoern A. Zeeb p = skb_dequeue(q);
249b4c3e9b5SBjoern A. Zeeb if (p == NULL)
250b4c3e9b5SBjoern A. Zeeb return NULL;
251b4c3e9b5SBjoern A. Zeeb
252b4c3e9b5SBjoern A. Zeeb pq->len--;
253b4c3e9b5SBjoern A. Zeeb
254b4c3e9b5SBjoern A. Zeeb if (prec_out)
255b4c3e9b5SBjoern A. Zeeb *prec_out = prec;
256b4c3e9b5SBjoern A. Zeeb
257b4c3e9b5SBjoern A. Zeeb return p;
258b4c3e9b5SBjoern A. Zeeb }
259b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_pktq_mdeq);
260b4c3e9b5SBjoern A. Zeeb
261b4c3e9b5SBjoern A. Zeeb /* Produce a human-readable string for boardrev */
brcmu_boardrev_str(u32 brev,char * buf)262b4c3e9b5SBjoern A. Zeeb char *brcmu_boardrev_str(u32 brev, char *buf)
263b4c3e9b5SBjoern A. Zeeb {
264b4c3e9b5SBjoern A. Zeeb char c;
265b4c3e9b5SBjoern A. Zeeb
266b4c3e9b5SBjoern A. Zeeb if (brev < 0x100) {
267b4c3e9b5SBjoern A. Zeeb snprintf(buf, BRCMU_BOARDREV_LEN, "%d.%d",
268b4c3e9b5SBjoern A. Zeeb (brev & 0xf0) >> 4, brev & 0xf);
269b4c3e9b5SBjoern A. Zeeb } else {
270b4c3e9b5SBjoern A. Zeeb c = (brev & 0xf000) == 0x1000 ? 'P' : 'A';
271b4c3e9b5SBjoern A. Zeeb snprintf(buf, BRCMU_BOARDREV_LEN, "%c%03x", c, brev & 0xfff);
272b4c3e9b5SBjoern A. Zeeb }
273b4c3e9b5SBjoern A. Zeeb return buf;
274b4c3e9b5SBjoern A. Zeeb }
275b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_boardrev_str);
276b4c3e9b5SBjoern A. Zeeb
brcmu_dotrev_str(u32 dotrev,char * buf)277b4c3e9b5SBjoern A. Zeeb char *brcmu_dotrev_str(u32 dotrev, char *buf)
278b4c3e9b5SBjoern A. Zeeb {
279b4c3e9b5SBjoern A. Zeeb u8 dotval[4];
280b4c3e9b5SBjoern A. Zeeb
281b4c3e9b5SBjoern A. Zeeb if (!dotrev) {
282b4c3e9b5SBjoern A. Zeeb snprintf(buf, BRCMU_DOTREV_LEN, "unknown");
283b4c3e9b5SBjoern A. Zeeb return buf;
284b4c3e9b5SBjoern A. Zeeb }
285b4c3e9b5SBjoern A. Zeeb dotval[0] = (dotrev >> 24) & 0xFF;
286b4c3e9b5SBjoern A. Zeeb dotval[1] = (dotrev >> 16) & 0xFF;
287b4c3e9b5SBjoern A. Zeeb dotval[2] = (dotrev >> 8) & 0xFF;
288b4c3e9b5SBjoern A. Zeeb dotval[3] = dotrev & 0xFF;
289b4c3e9b5SBjoern A. Zeeb
290b4c3e9b5SBjoern A. Zeeb if (dotval[3])
291b4c3e9b5SBjoern A. Zeeb snprintf(buf, BRCMU_DOTREV_LEN, "%d.%d.%d.%d", dotval[0],
292b4c3e9b5SBjoern A. Zeeb dotval[1], dotval[2], dotval[3]);
293b4c3e9b5SBjoern A. Zeeb else if (dotval[2])
294b4c3e9b5SBjoern A. Zeeb snprintf(buf, BRCMU_DOTREV_LEN, "%d.%d.%d", dotval[0],
295b4c3e9b5SBjoern A. Zeeb dotval[1], dotval[2]);
296b4c3e9b5SBjoern A. Zeeb else
297b4c3e9b5SBjoern A. Zeeb snprintf(buf, BRCMU_DOTREV_LEN, "%d.%d", dotval[0],
298b4c3e9b5SBjoern A. Zeeb dotval[1]);
299b4c3e9b5SBjoern A. Zeeb
300b4c3e9b5SBjoern A. Zeeb return buf;
301b4c3e9b5SBjoern A. Zeeb }
302b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_dotrev_str);
303b4c3e9b5SBjoern A. Zeeb
304b4c3e9b5SBjoern A. Zeeb #if defined(DEBUG)
305b4c3e9b5SBjoern A. Zeeb /* pretty hex print a pkt buffer chain */
brcmu_prpkt(const char * msg,struct sk_buff * p0)306b4c3e9b5SBjoern A. Zeeb void brcmu_prpkt(const char *msg, struct sk_buff *p0)
307b4c3e9b5SBjoern A. Zeeb {
308b4c3e9b5SBjoern A. Zeeb struct sk_buff *p;
309b4c3e9b5SBjoern A. Zeeb
310b4c3e9b5SBjoern A. Zeeb if (msg && (msg[0] != '\0'))
311b4c3e9b5SBjoern A. Zeeb pr_debug("%s:\n", msg);
312b4c3e9b5SBjoern A. Zeeb
313b4c3e9b5SBjoern A. Zeeb for (p = p0; p; p = p->next)
314b4c3e9b5SBjoern A. Zeeb print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, p->data, p->len);
315b4c3e9b5SBjoern A. Zeeb }
316b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_prpkt);
317b4c3e9b5SBjoern A. Zeeb
brcmu_dbg_hex_dump(const void * data,size_t size,const char * fmt,...)318b4c3e9b5SBjoern A. Zeeb void brcmu_dbg_hex_dump(const void *data, size_t size, const char *fmt, ...)
319b4c3e9b5SBjoern A. Zeeb {
320b4c3e9b5SBjoern A. Zeeb struct va_format vaf;
321b4c3e9b5SBjoern A. Zeeb va_list args;
322b4c3e9b5SBjoern A. Zeeb
323b4c3e9b5SBjoern A. Zeeb va_start(args, fmt);
324b4c3e9b5SBjoern A. Zeeb
325b4c3e9b5SBjoern A. Zeeb vaf.fmt = fmt;
326b4c3e9b5SBjoern A. Zeeb vaf.va = &args;
327b4c3e9b5SBjoern A. Zeeb
328b4c3e9b5SBjoern A. Zeeb pr_debug("%pV", &vaf);
329b4c3e9b5SBjoern A. Zeeb
330b4c3e9b5SBjoern A. Zeeb va_end(args);
331b4c3e9b5SBjoern A. Zeeb
332b4c3e9b5SBjoern A. Zeeb print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, data, size);
333b4c3e9b5SBjoern A. Zeeb }
334b4c3e9b5SBjoern A. Zeeb EXPORT_SYMBOL(brcmu_dbg_hex_dump);
335b4c3e9b5SBjoern A. Zeeb
336b4c3e9b5SBjoern A. Zeeb #endif /* defined(DEBUG) */
337