diff options
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmutil/utils.c')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmutil/utils.c | 218 |
1 files changed, 44 insertions, 174 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c index f27c4891082..b7537f70a79 100644 --- a/drivers/net/wireless/brcm80211/brcmutil/utils.c +++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | |||
19 | #include <brcmu_utils.h> | 20 | #include <brcmu_utils.h> |
20 | 21 | ||
21 | MODULE_AUTHOR("Broadcom Corporation"); | 22 | MODULE_AUTHOR("Broadcom Corporation"); |
@@ -40,74 +41,20 @@ EXPORT_SYMBOL(brcmu_pkt_buf_get_skb); | |||
40 | /* Free the driver packet. Free the tag if present */ | 41 | /* Free the driver packet. Free the tag if present */ |
41 | void brcmu_pkt_buf_free_skb(struct sk_buff *skb) | 42 | void brcmu_pkt_buf_free_skb(struct sk_buff *skb) |
42 | { | 43 | { |
43 | struct sk_buff *nskb; | 44 | WARN_ON(skb->next); |
44 | int nest = 0; | 45 | if (skb->destructor) |
45 | 46 | /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if | |
46 | /* perversion: we use skb->next to chain multi-skb packets */ | 47 | * destructor exists |
47 | while (skb) { | 48 | */ |
48 | nskb = skb->next; | 49 | dev_kfree_skb_any(skb); |
49 | skb->next = NULL; | 50 | else |
50 | 51 | /* can free immediately (even in_irq()) if destructor | |
51 | if (skb->destructor) | 52 | * does not exist |
52 | /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if | 53 | */ |
53 | * destructor exists | 54 | dev_kfree_skb(skb); |
54 | */ | ||
55 | dev_kfree_skb_any(skb); | ||
56 | else | ||
57 | /* can free immediately (even in_irq()) if destructor | ||
58 | * does not exist | ||
59 | */ | ||
60 | dev_kfree_skb(skb); | ||
61 | |||
62 | nest++; | ||
63 | skb = nskb; | ||
64 | } | ||
65 | } | 55 | } |
66 | EXPORT_SYMBOL(brcmu_pkt_buf_free_skb); | 56 | EXPORT_SYMBOL(brcmu_pkt_buf_free_skb); |
67 | 57 | ||
68 | |||
69 | /* copy a buffer into a pkt buffer chain */ | ||
70 | uint brcmu_pktfrombuf(struct sk_buff *p, uint offset, int len, | ||
71 | unsigned char *buf) | ||
72 | { | ||
73 | uint n, ret = 0; | ||
74 | |||
75 | /* skip 'offset' bytes */ | ||
76 | for (; p && offset; p = p->next) { | ||
77 | if (offset < (uint) (p->len)) | ||
78 | break; | ||
79 | offset -= p->len; | ||
80 | } | ||
81 | |||
82 | if (!p) | ||
83 | return 0; | ||
84 | |||
85 | /* copy the data */ | ||
86 | for (; p && len; p = p->next) { | ||
87 | n = min((uint) (p->len) - offset, (uint) len); | ||
88 | memcpy(p->data + offset, buf, n); | ||
89 | buf += n; | ||
90 | len -= n; | ||
91 | ret += n; | ||
92 | offset = 0; | ||
93 | } | ||
94 | |||
95 | return ret; | ||
96 | } | ||
97 | EXPORT_SYMBOL(brcmu_pktfrombuf); | ||
98 | |||
99 | /* return total length of buffer chain */ | ||
100 | uint brcmu_pkttotlen(struct sk_buff *p) | ||
101 | { | ||
102 | uint total; | ||
103 | |||
104 | total = 0; | ||
105 | for (; p; p = p->next) | ||
106 | total += p->len; | ||
107 | return total; | ||
108 | } | ||
109 | EXPORT_SYMBOL(brcmu_pkttotlen); | ||
110 | |||
111 | /* | 58 | /* |
112 | * osl multiple-precedence packet queue | 59 | * osl multiple-precedence packet queue |
113 | * hi_prec is always >= the number of the highest non-empty precedence | 60 | * hi_prec is always >= the number of the highest non-empty precedence |
@@ -115,21 +62,13 @@ EXPORT_SYMBOL(brcmu_pkttotlen); | |||
115 | struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec, | 62 | struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec, |
116 | struct sk_buff *p) | 63 | struct sk_buff *p) |
117 | { | 64 | { |
118 | struct pktq_prec *q; | 65 | struct sk_buff_head *q; |
119 | 66 | ||
120 | if (pktq_full(pq) || pktq_pfull(pq, prec)) | 67 | if (pktq_full(pq) || pktq_pfull(pq, prec)) |
121 | return NULL; | 68 | return NULL; |
122 | 69 | ||
123 | q = &pq->q[prec]; | 70 | q = &pq->q[prec].skblist; |
124 | 71 | skb_queue_tail(q, p); | |
125 | if (q->head) | ||
126 | q->tail->prev = p; | ||
127 | else | ||
128 | q->head = p; | ||
129 | |||
130 | q->tail = p; | ||
131 | q->len++; | ||
132 | |||
133 | pq->len++; | 72 | pq->len++; |
134 | 73 | ||
135 | if (pq->hi_prec < prec) | 74 | if (pq->hi_prec < prec) |
@@ -142,20 +81,13 @@ EXPORT_SYMBOL(brcmu_pktq_penq); | |||
142 | struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec, | 81 | struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec, |
143 | struct sk_buff *p) | 82 | struct sk_buff *p) |
144 | { | 83 | { |
145 | struct pktq_prec *q; | 84 | struct sk_buff_head *q; |
146 | 85 | ||
147 | if (pktq_full(pq) || pktq_pfull(pq, prec)) | 86 | if (pktq_full(pq) || pktq_pfull(pq, prec)) |
148 | return NULL; | 87 | return NULL; |
149 | 88 | ||
150 | q = &pq->q[prec]; | 89 | q = &pq->q[prec].skblist; |
151 | 90 | skb_queue_head(q, p); | |
152 | if (q->head == NULL) | ||
153 | q->tail = p; | ||
154 | |||
155 | p->prev = q->head; | ||
156 | q->head = p; | ||
157 | q->len++; | ||
158 | |||
159 | pq->len++; | 91 | pq->len++; |
160 | 92 | ||
161 | if (pq->hi_prec < prec) | 93 | if (pq->hi_prec < prec) |
@@ -167,53 +99,30 @@ EXPORT_SYMBOL(brcmu_pktq_penq_head); | |||
167 | 99 | ||
168 | struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec) | 100 | struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec) |
169 | { | 101 | { |
170 | struct pktq_prec *q; | 102 | struct sk_buff_head *q; |
171 | struct sk_buff *p; | 103 | struct sk_buff *p; |
172 | 104 | ||
173 | q = &pq->q[prec]; | 105 | q = &pq->q[prec].skblist; |
174 | 106 | p = skb_dequeue(q); | |
175 | p = q->head; | ||
176 | if (p == NULL) | 107 | if (p == NULL) |
177 | return NULL; | 108 | return NULL; |
178 | 109 | ||
179 | q->head = p->prev; | ||
180 | if (q->head == NULL) | ||
181 | q->tail = NULL; | ||
182 | |||
183 | q->len--; | ||
184 | |||
185 | pq->len--; | 110 | pq->len--; |
186 | |||
187 | p->prev = NULL; | ||
188 | |||
189 | return p; | 111 | return p; |
190 | } | 112 | } |
191 | EXPORT_SYMBOL(brcmu_pktq_pdeq); | 113 | EXPORT_SYMBOL(brcmu_pktq_pdeq); |
192 | 114 | ||
193 | struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec) | 115 | struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec) |
194 | { | 116 | { |
195 | struct pktq_prec *q; | 117 | struct sk_buff_head *q; |
196 | struct sk_buff *p, *prev; | 118 | struct sk_buff *p; |
197 | |||
198 | q = &pq->q[prec]; | ||
199 | 119 | ||
200 | p = q->head; | 120 | q = &pq->q[prec].skblist; |
121 | p = skb_dequeue_tail(q); | ||
201 | if (p == NULL) | 122 | if (p == NULL) |
202 | return NULL; | 123 | return NULL; |
203 | 124 | ||
204 | for (prev = NULL; p != q->tail; p = p->prev) | ||
205 | prev = p; | ||
206 | |||
207 | if (prev) | ||
208 | prev->prev = NULL; | ||
209 | else | ||
210 | q->head = NULL; | ||
211 | |||
212 | q->tail = prev; | ||
213 | q->len--; | ||
214 | |||
215 | pq->len--; | 125 | pq->len--; |
216 | |||
217 | return p; | 126 | return p; |
218 | } | 127 | } |
219 | EXPORT_SYMBOL(brcmu_pktq_pdeq_tail); | 128 | EXPORT_SYMBOL(brcmu_pktq_pdeq_tail); |
@@ -222,31 +131,17 @@ void | |||
222 | brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir, | 131 | brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir, |
223 | bool (*fn)(struct sk_buff *, void *), void *arg) | 132 | bool (*fn)(struct sk_buff *, void *), void *arg) |
224 | { | 133 | { |
225 | struct pktq_prec *q; | 134 | struct sk_buff_head *q; |
226 | struct sk_buff *p, *prev = NULL; | 135 | struct sk_buff *p, *next; |
227 | 136 | ||
228 | q = &pq->q[prec]; | 137 | q = &pq->q[prec].skblist; |
229 | p = q->head; | 138 | skb_queue_walk_safe(q, p, next) { |
230 | while (p) { | ||
231 | if (fn == NULL || (*fn) (p, arg)) { | 139 | if (fn == NULL || (*fn) (p, arg)) { |
232 | bool head = (p == q->head); | 140 | skb_unlink(p, q); |
233 | if (head) | ||
234 | q->head = p->prev; | ||
235 | else | ||
236 | prev->prev = p->prev; | ||
237 | p->prev = NULL; | ||
238 | brcmu_pkt_buf_free_skb(p); | 141 | brcmu_pkt_buf_free_skb(p); |
239 | q->len--; | ||
240 | pq->len--; | 142 | pq->len--; |
241 | p = (head ? q->head : prev->prev); | ||
242 | } else { | ||
243 | prev = p; | ||
244 | p = p->prev; | ||
245 | } | 143 | } |
246 | } | 144 | } |
247 | |||
248 | if (q->head == NULL) | ||
249 | q->tail = NULL; | ||
250 | } | 145 | } |
251 | EXPORT_SYMBOL(brcmu_pktq_pflush); | 146 | EXPORT_SYMBOL(brcmu_pktq_pflush); |
252 | 147 | ||
@@ -271,8 +166,10 @@ void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len) | |||
271 | 166 | ||
272 | pq->max = (u16) max_len; | 167 | pq->max = (u16) max_len; |
273 | 168 | ||
274 | for (prec = 0; prec < num_prec; prec++) | 169 | for (prec = 0; prec < num_prec; prec++) { |
275 | pq->q[prec].max = pq->max; | 170 | pq->q[prec].max = pq->max; |
171 | skb_queue_head_init(&pq->q[prec].skblist); | ||
172 | } | ||
276 | } | 173 | } |
277 | EXPORT_SYMBOL(brcmu_pktq_init); | 174 | EXPORT_SYMBOL(brcmu_pktq_init); |
278 | 175 | ||
@@ -284,13 +181,13 @@ struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out) | |||
284 | return NULL; | 181 | return NULL; |
285 | 182 | ||
286 | for (prec = 0; prec < pq->hi_prec; prec++) | 183 | for (prec = 0; prec < pq->hi_prec; prec++) |
287 | if (pq->q[prec].head) | 184 | if (!skb_queue_empty(&pq->q[prec].skblist)) |
288 | break; | 185 | break; |
289 | 186 | ||
290 | if (prec_out) | 187 | if (prec_out) |
291 | *prec_out = prec; | 188 | *prec_out = prec; |
292 | 189 | ||
293 | return pq->q[prec].tail; | 190 | return skb_peek_tail(&pq->q[prec].skblist); |
294 | } | 191 | } |
295 | EXPORT_SYMBOL(brcmu_pktq_peek_tail); | 192 | EXPORT_SYMBOL(brcmu_pktq_peek_tail); |
296 | 193 | ||
@@ -303,7 +200,7 @@ int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp) | |||
303 | 200 | ||
304 | for (prec = 0; prec <= pq->hi_prec; prec++) | 201 | for (prec = 0; prec <= pq->hi_prec; prec++) |
305 | if (prec_bmp & (1 << prec)) | 202 | if (prec_bmp & (1 << prec)) |
306 | len += pq->q[prec].len; | 203 | len += pq->q[prec].skblist.qlen; |
307 | 204 | ||
308 | return len; | 205 | return len; |
309 | } | 206 | } |
@@ -313,39 +210,32 @@ EXPORT_SYMBOL(brcmu_pktq_mlen); | |||
313 | struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, | 210 | struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, |
314 | int *prec_out) | 211 | int *prec_out) |
315 | { | 212 | { |
316 | struct pktq_prec *q; | 213 | struct sk_buff_head *q; |
317 | struct sk_buff *p; | 214 | struct sk_buff *p; |
318 | int prec; | 215 | int prec; |
319 | 216 | ||
320 | if (pq->len == 0) | 217 | if (pq->len == 0) |
321 | return NULL; | 218 | return NULL; |
322 | 219 | ||
323 | while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) | 220 | while ((prec = pq->hi_prec) > 0 && |
221 | skb_queue_empty(&pq->q[prec].skblist)) | ||
324 | pq->hi_prec--; | 222 | pq->hi_prec--; |
325 | 223 | ||
326 | while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) | 224 | while ((prec_bmp & (1 << prec)) == 0 || |
225 | skb_queue_empty(&pq->q[prec].skblist)) | ||
327 | if (prec-- == 0) | 226 | if (prec-- == 0) |
328 | return NULL; | 227 | return NULL; |
329 | 228 | ||
330 | q = &pq->q[prec]; | 229 | q = &pq->q[prec].skblist; |
331 | 230 | p = skb_dequeue(q); | |
332 | p = q->head; | ||
333 | if (p == NULL) | 231 | if (p == NULL) |
334 | return NULL; | 232 | return NULL; |
335 | 233 | ||
336 | q->head = p->prev; | 234 | pq->len--; |
337 | if (q->head == NULL) | ||
338 | q->tail = NULL; | ||
339 | |||
340 | q->len--; | ||
341 | 235 | ||
342 | if (prec_out) | 236 | if (prec_out) |
343 | *prec_out = prec; | 237 | *prec_out = prec; |
344 | 238 | ||
345 | pq->len--; | ||
346 | |||
347 | p->prev = NULL; | ||
348 | |||
349 | return p; | 239 | return p; |
350 | } | 240 | } |
351 | EXPORT_SYMBOL(brcmu_pktq_mdeq); | 241 | EXPORT_SYMBOL(brcmu_pktq_mdeq); |
@@ -364,23 +254,3 @@ void brcmu_prpkt(const char *msg, struct sk_buff *p0) | |||
364 | } | 254 | } |
365 | EXPORT_SYMBOL(brcmu_prpkt); | 255 | EXPORT_SYMBOL(brcmu_prpkt); |
366 | #endif /* defined(BCMDBG) */ | 256 | #endif /* defined(BCMDBG) */ |
367 | |||
368 | #if defined(BCMDBG) | ||
369 | /* | ||
370 | * print bytes formatted as hex to a string. return the resulting | ||
371 | * string length | ||
372 | */ | ||
373 | int brcmu_format_hex(char *str, const void *bytes, int len) | ||
374 | { | ||
375 | int i; | ||
376 | char *p = str; | ||
377 | const u8 *src = (const u8 *)bytes; | ||
378 | |||
379 | for (i = 0; i < len; i++) { | ||
380 | p += snprintf(p, 3, "%02X", *src); | ||
381 | src++; | ||
382 | } | ||
383 | return (int)(p - str); | ||
384 | } | ||
385 | EXPORT_SYMBOL(brcmu_format_hex); | ||
386 | #endif /* defined(BCMDBG) */ | ||