Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : :
4 : : Broadcom B43legacy wireless driver
5 : :
6 : : DMA ringbuffer and descriptor allocation/management
7 : :
8 : : Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
9 : :
10 : : Some code in this file is derived from the b44.c driver
11 : : Copyright (C) 2002 David S. Miller
12 : : Copyright (C) Pekka Pietikainen
13 : :
14 : :
15 : : */
16 : :
17 : : #include "b43legacy.h"
18 : : #include "dma.h"
19 : : #include "main.h"
20 : : #include "debugfs.h"
21 : : #include "xmit.h"
22 : :
23 : : #include <linux/dma-mapping.h>
24 : : #include <linux/pci.h>
25 : : #include <linux/delay.h>
26 : : #include <linux/skbuff.h>
27 : : #include <linux/slab.h>
28 : : #include <net/dst.h>
29 : :
30 : : /* 32bit DMA ops. */
31 : : static
32 : 0 : struct b43legacy_dmadesc32 *op32_idx2desc(struct b43legacy_dmaring *ring,
33 : : int slot,
34 : : struct b43legacy_dmadesc_meta **meta)
35 : : {
36 : 0 : struct b43legacy_dmadesc32 *desc;
37 : :
38 : 0 : *meta = &(ring->meta[slot]);
39 : 0 : desc = ring->descbase;
40 : 0 : desc = &(desc[slot]);
41 : :
42 : 0 : return desc;
43 : : }
44 : :
45 : 0 : static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
46 : : struct b43legacy_dmadesc32 *desc,
47 : : dma_addr_t dmaaddr, u16 bufsize,
48 : : int start, int end, int irq)
49 : : {
50 : 0 : struct b43legacy_dmadesc32 *descbase = ring->descbase;
51 : 0 : int slot;
52 : 0 : u32 ctl;
53 : 0 : u32 addr;
54 : 0 : u32 addrext;
55 : :
56 : 0 : slot = (int)(desc - descbase);
57 [ # # # # : 0 : B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
# # ]
58 : :
59 : 0 : addr = (u32)(dmaaddr & ~SSB_DMA_TRANSLATION_MASK);
60 : 0 : addrext = (u32)(dmaaddr & SSB_DMA_TRANSLATION_MASK)
61 : : >> SSB_DMA_TRANSLATION_SHIFT;
62 : 0 : addr |= ring->dev->dma.translation;
63 : 0 : ctl = (bufsize - ring->frameoffset)
64 : : & B43legacy_DMA32_DCTL_BYTECNT;
65 [ # # ]: 0 : if (slot == ring->nr_slots - 1)
66 : 0 : ctl |= B43legacy_DMA32_DCTL_DTABLEEND;
67 [ # # ]: 0 : if (start)
68 : 0 : ctl |= B43legacy_DMA32_DCTL_FRAMESTART;
69 [ # # ]: 0 : if (end)
70 : 0 : ctl |= B43legacy_DMA32_DCTL_FRAMEEND;
71 [ # # ]: 0 : if (irq)
72 : 0 : ctl |= B43legacy_DMA32_DCTL_IRQ;
73 : 0 : ctl |= (addrext << B43legacy_DMA32_DCTL_ADDREXT_SHIFT)
74 : : & B43legacy_DMA32_DCTL_ADDREXT_MASK;
75 : :
76 : 0 : desc->control = cpu_to_le32(ctl);
77 : 0 : desc->address = cpu_to_le32(addr);
78 : 0 : }
79 : :
80 : 0 : static void op32_poke_tx(struct b43legacy_dmaring *ring, int slot)
81 : : {
82 : 0 : b43legacy_dma_write(ring, B43legacy_DMA32_TXINDEX,
83 : : (u32)(slot * sizeof(struct b43legacy_dmadesc32)));
84 : : }
85 : :
86 : : static void op32_tx_suspend(struct b43legacy_dmaring *ring)
87 : : {
88 : : b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL,
89 : : b43legacy_dma_read(ring, B43legacy_DMA32_TXCTL)
90 : : | B43legacy_DMA32_TXSUSPEND);
91 : : }
92 : :
93 : : static void op32_tx_resume(struct b43legacy_dmaring *ring)
94 : : {
95 : : b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL,
96 : : b43legacy_dma_read(ring, B43legacy_DMA32_TXCTL)
97 : : & ~B43legacy_DMA32_TXSUSPEND);
98 : : }
99 : :
100 : 0 : static int op32_get_current_rxslot(struct b43legacy_dmaring *ring)
101 : : {
102 : 0 : u32 val;
103 : :
104 : 0 : val = b43legacy_dma_read(ring, B43legacy_DMA32_RXSTATUS);
105 : 0 : val &= B43legacy_DMA32_RXDPTR;
106 : :
107 : 0 : return (val / sizeof(struct b43legacy_dmadesc32));
108 : : }
109 : :
110 : 0 : static void op32_set_current_rxslot(struct b43legacy_dmaring *ring,
111 : : int slot)
112 : : {
113 : 0 : b43legacy_dma_write(ring, B43legacy_DMA32_RXINDEX,
114 : : (u32)(slot * sizeof(struct b43legacy_dmadesc32)));
115 : : }
116 : :
117 : 0 : static inline int free_slots(struct b43legacy_dmaring *ring)
118 : : {
119 : 0 : return (ring->nr_slots - ring->used_slots);
120 : : }
121 : :
122 : 0 : static inline int next_slot(struct b43legacy_dmaring *ring, int slot)
123 : : {
124 [ # # # # : 0 : B43legacy_WARN_ON(!(slot >= -1 && slot <= ring->nr_slots - 1));
# # # # #
# # # # #
# # # # #
# ]
125 [ # # # # : 0 : if (slot == ring->nr_slots - 1)
# # # # #
# ]
126 : : return 0;
127 : 0 : return slot + 1;
128 : : }
129 : :
130 : : static inline int prev_slot(struct b43legacy_dmaring *ring, int slot)
131 : : {
132 : : B43legacy_WARN_ON(!(slot >= 0 && slot <= ring->nr_slots - 1));
133 : : if (slot == 0)
134 : : return ring->nr_slots - 1;
135 : : return slot - 1;
136 : : }
137 : :
138 : : #ifdef CONFIG_B43LEGACY_DEBUG
139 : 0 : static void update_max_used_slots(struct b43legacy_dmaring *ring,
140 : : int current_used_slots)
141 : : {
142 [ # # ]: 0 : if (current_used_slots <= ring->max_used_slots)
143 : : return;
144 : 0 : ring->max_used_slots = current_used_slots;
145 [ # # ]: 0 : if (b43legacy_debug(ring->dev, B43legacy_DBG_DMAVERBOSE))
146 : 0 : b43legacydbg(ring->dev->wl,
147 : : "max_used_slots increased to %d on %s ring %d\n",
148 : : ring->max_used_slots,
149 [ # # ]: 0 : ring->tx ? "TX" : "RX",
150 : : ring->index);
151 : : }
152 : : #else
153 : : static inline
154 : : void update_max_used_slots(struct b43legacy_dmaring *ring,
155 : : int current_used_slots)
156 : : { }
157 : : #endif /* DEBUG */
158 : :
159 : : /* Request a slot for usage. */
160 : : static inline
161 : 0 : int request_slot(struct b43legacy_dmaring *ring)
162 : : {
163 : 0 : int slot;
164 : :
165 [ # # ]: 0 : B43legacy_WARN_ON(!ring->tx);
166 [ # # ]: 0 : B43legacy_WARN_ON(ring->stopped);
167 [ # # ]: 0 : B43legacy_WARN_ON(free_slots(ring) == 0);
168 : :
169 [ # # ]: 0 : slot = next_slot(ring, ring->current_slot);
170 : 0 : ring->current_slot = slot;
171 : 0 : ring->used_slots++;
172 : :
173 : 0 : update_max_used_slots(ring, ring->used_slots);
174 : :
175 : 0 : return slot;
176 : : }
177 : :
178 : : /* Mac80211-queue to b43legacy-ring mapping */
179 : 0 : static struct b43legacy_dmaring *priority_to_txring(
180 : : struct b43legacy_wldev *dev,
181 : : int queue_priority)
182 : : {
183 : 0 : struct b43legacy_dmaring *ring;
184 : :
185 : : /*FIXME: For now we always run on TX-ring-1 */
186 : 0 : return dev->dma.tx_ring1;
187 : :
188 : : /* 0 = highest priority */
189 : : switch (queue_priority) {
190 : : default:
191 : : B43legacy_WARN_ON(1);
192 : : /* fallthrough */
193 : : case 0:
194 : : ring = dev->dma.tx_ring3;
195 : : break;
196 : : case 1:
197 : : ring = dev->dma.tx_ring2;
198 : : break;
199 : : case 2:
200 : : ring = dev->dma.tx_ring1;
201 : : break;
202 : : case 3:
203 : : ring = dev->dma.tx_ring0;
204 : : break;
205 : : case 4:
206 : : ring = dev->dma.tx_ring4;
207 : : break;
208 : : case 5:
209 : : ring = dev->dma.tx_ring5;
210 : : break;
211 : : }
212 : :
213 : : return ring;
214 : : }
215 : :
216 : : /* Bcm4301-ring to mac80211-queue mapping */
217 : : static inline int txring_to_priority(struct b43legacy_dmaring *ring)
218 : : {
219 : : static const u8 idx_to_prio[] =
220 : : { 3, 2, 1, 0, 4, 5, };
221 : :
222 : : /*FIXME: have only one queue, for now */
223 : : return 0;
224 : :
225 : : return idx_to_prio[ring->index];
226 : : }
227 : :
228 : :
229 : 0 : static u16 b43legacy_dmacontroller_base(enum b43legacy_dmatype type,
230 : : int controller_idx)
231 : : {
232 : 0 : static const u16 map32[] = {
233 : : B43legacy_MMIO_DMA32_BASE0,
234 : : B43legacy_MMIO_DMA32_BASE1,
235 : : B43legacy_MMIO_DMA32_BASE2,
236 : : B43legacy_MMIO_DMA32_BASE3,
237 : : B43legacy_MMIO_DMA32_BASE4,
238 : : B43legacy_MMIO_DMA32_BASE5,
239 : : };
240 : :
241 : 0 : B43legacy_WARN_ON(!(controller_idx >= 0 &&
242 : : controller_idx < ARRAY_SIZE(map32)));
243 : 0 : return map32[controller_idx];
244 : : }
245 : :
246 : : static inline
247 : 0 : dma_addr_t map_descbuffer(struct b43legacy_dmaring *ring,
248 : : unsigned char *buf,
249 : : size_t len,
250 : : int tx)
251 : : {
252 : 0 : dma_addr_t dmaaddr;
253 : :
254 : 0 : if (tx)
255 : 0 : dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
256 : : buf, len,
257 : : DMA_TO_DEVICE);
258 : : else
259 : : dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
260 : : buf, len,
261 : : DMA_FROM_DEVICE);
262 : :
263 : 0 : return dmaaddr;
264 : : }
265 : :
266 : : static inline
267 : 0 : void unmap_descbuffer(struct b43legacy_dmaring *ring,
268 : : dma_addr_t addr,
269 : : size_t len,
270 : : int tx)
271 : : {
272 : 0 : if (tx)
273 : 0 : dma_unmap_single(ring->dev->dev->dma_dev,
274 : : addr, len,
275 : : DMA_TO_DEVICE);
276 : : else
277 : 0 : dma_unmap_single(ring->dev->dev->dma_dev,
278 : : addr, len,
279 : : DMA_FROM_DEVICE);
280 : : }
281 : :
282 : : static inline
283 : : void sync_descbuffer_for_cpu(struct b43legacy_dmaring *ring,
284 : : dma_addr_t addr,
285 : : size_t len)
286 : : {
287 : : B43legacy_WARN_ON(ring->tx);
288 : :
289 : : dma_sync_single_for_cpu(ring->dev->dev->dma_dev,
290 : : addr, len, DMA_FROM_DEVICE);
291 : : }
292 : :
293 : : static inline
294 : : void sync_descbuffer_for_device(struct b43legacy_dmaring *ring,
295 : : dma_addr_t addr,
296 : : size_t len)
297 : : {
298 : : B43legacy_WARN_ON(ring->tx);
299 : :
300 : : dma_sync_single_for_device(ring->dev->dev->dma_dev,
301 : : addr, len, DMA_FROM_DEVICE);
302 : : }
303 : :
304 : : static inline
305 : 0 : void free_descriptor_buffer(struct b43legacy_dmaring *ring,
306 : : struct b43legacy_dmadesc_meta *meta,
307 : : int irq_context)
308 : : {
309 : 0 : if (meta->skb) {
310 : 0 : if (irq_context)
311 : : dev_kfree_skb_irq(meta->skb);
312 : : else
313 : 0 : dev_kfree_skb(meta->skb);
314 : 0 : meta->skb = NULL;
315 : : }
316 : : }
317 : :
318 : 0 : static int alloc_ringmemory(struct b43legacy_dmaring *ring)
319 : : {
320 : : /* GFP flags must match the flags in free_ringmemory()! */
321 : 0 : ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
322 : : B43legacy_DMA_RINGMEMSIZE,
323 : : &(ring->dmabase), GFP_KERNEL);
324 [ # # ]: 0 : if (!ring->descbase)
325 : 0 : return -ENOMEM;
326 : :
327 : : return 0;
328 : : }
329 : :
330 : 0 : static void free_ringmemory(struct b43legacy_dmaring *ring)
331 : : {
332 : 0 : dma_free_coherent(ring->dev->dev->dma_dev, B43legacy_DMA_RINGMEMSIZE,
333 : : ring->descbase, ring->dmabase);
334 : 0 : }
335 : :
336 : : /* Reset the RX DMA channel */
337 : 0 : static int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev,
338 : : u16 mmio_base,
339 : : enum b43legacy_dmatype type)
340 : : {
341 : 0 : int i;
342 : 0 : u32 value;
343 : 0 : u16 offset;
344 : :
345 : 0 : might_sleep();
346 : :
347 : 0 : offset = B43legacy_DMA32_RXCTL;
348 : 0 : b43legacy_write32(dev, mmio_base + offset, 0);
349 [ # # ]: 0 : for (i = 0; i < 10; i++) {
350 : 0 : offset = B43legacy_DMA32_RXSTATUS;
351 : 0 : value = b43legacy_read32(dev, mmio_base + offset);
352 : 0 : value &= B43legacy_DMA32_RXSTATE;
353 [ # # ]: 0 : if (value == B43legacy_DMA32_RXSTAT_DISABLED) {
354 : : i = -1;
355 : : break;
356 : : }
357 : 0 : msleep(1);
358 : : }
359 [ # # ]: 0 : if (i != -1) {
360 : 0 : b43legacyerr(dev->wl, "DMA RX reset timed out\n");
361 : 0 : return -ENODEV;
362 : : }
363 : :
364 : : return 0;
365 : : }
366 : :
367 : : /* Reset the RX DMA channel */
368 : 0 : static int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev,
369 : : u16 mmio_base,
370 : : enum b43legacy_dmatype type)
371 : : {
372 : 0 : int i;
373 : 0 : u32 value;
374 : 0 : u16 offset;
375 : :
376 : 0 : might_sleep();
377 : :
378 [ # # ]: 0 : for (i = 0; i < 10; i++) {
379 : 0 : offset = B43legacy_DMA32_TXSTATUS;
380 : 0 : value = b43legacy_read32(dev, mmio_base + offset);
381 : 0 : value &= B43legacy_DMA32_TXSTATE;
382 : 0 : if (value == B43legacy_DMA32_TXSTAT_DISABLED ||
383 [ # # # # ]: 0 : value == B43legacy_DMA32_TXSTAT_IDLEWAIT ||
384 : : value == B43legacy_DMA32_TXSTAT_STOPPED)
385 : : break;
386 : 0 : msleep(1);
387 : : }
388 : 0 : offset = B43legacy_DMA32_TXCTL;
389 : 0 : b43legacy_write32(dev, mmio_base + offset, 0);
390 [ # # ]: 0 : for (i = 0; i < 10; i++) {
391 : 0 : offset = B43legacy_DMA32_TXSTATUS;
392 : 0 : value = b43legacy_read32(dev, mmio_base + offset);
393 : 0 : value &= B43legacy_DMA32_TXSTATE;
394 [ # # ]: 0 : if (value == B43legacy_DMA32_TXSTAT_DISABLED) {
395 : : i = -1;
396 : : break;
397 : : }
398 : 0 : msleep(1);
399 : : }
400 [ # # ]: 0 : if (i != -1) {
401 : 0 : b43legacyerr(dev->wl, "DMA TX reset timed out\n");
402 : 0 : return -ENODEV;
403 : : }
404 : : /* ensure the reset is completed. */
405 : 0 : msleep(1);
406 : :
407 : 0 : return 0;
408 : : }
409 : :
410 : : /* Check if a DMA mapping address is invalid. */
411 : 0 : static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring,
412 : : dma_addr_t addr,
413 : : size_t buffersize,
414 : : bool dma_to_device)
415 : : {
416 [ # # ]: 0 : if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr)))
417 : : return true;
418 : :
419 [ # # # ]: 0 : switch (ring->type) {
420 : 0 : case B43legacy_DMA_30BIT:
421 [ # # ]: 0 : if ((u64)addr + buffersize > (1ULL << 30))
422 : 0 : goto address_error;
423 : : break;
424 : 0 : case B43legacy_DMA_32BIT:
425 [ # # ]: 0 : if ((u64)addr + buffersize > (1ULL << 32))
426 : 0 : goto address_error;
427 : : break;
428 : : }
429 : :
430 : : /* The address is OK. */
431 : : return false;
432 : :
433 : 0 : address_error:
434 : : /* We can't support this address. Unmap it again. */
435 : 0 : unmap_descbuffer(ring, addr, buffersize, dma_to_device);
436 : :
437 : 0 : return true;
438 : : }
439 : :
440 : : static int setup_rx_descbuffer(struct b43legacy_dmaring *ring,
441 : : struct b43legacy_dmadesc32 *desc,
442 : : struct b43legacy_dmadesc_meta *meta,
443 : : gfp_t gfp_flags)
444 : : {
445 : : struct b43legacy_rxhdr_fw3 *rxhdr;
446 : : struct b43legacy_hwtxstatus *txstat;
447 : : dma_addr_t dmaaddr;
448 : : struct sk_buff *skb;
449 : :
450 : : B43legacy_WARN_ON(ring->tx);
451 : :
452 : : skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
453 : : if (unlikely(!skb))
454 : : return -ENOMEM;
455 : : dmaaddr = map_descbuffer(ring, skb->data,
456 : : ring->rx_buffersize, 0);
457 : : if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
458 : : /* ugh. try to realloc in zone_dma */
459 : : gfp_flags |= GFP_DMA;
460 : :
461 : : dev_kfree_skb_any(skb);
462 : :
463 : : skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
464 : : if (unlikely(!skb))
465 : : return -ENOMEM;
466 : : dmaaddr = map_descbuffer(ring, skb->data,
467 : : ring->rx_buffersize, 0);
468 : : }
469 : :
470 : : if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
471 : : dev_kfree_skb_any(skb);
472 : : return -EIO;
473 : : }
474 : :
475 : : meta->skb = skb;
476 : : meta->dmaaddr = dmaaddr;
477 : : op32_fill_descriptor(ring, desc, dmaaddr, ring->rx_buffersize, 0, 0, 0);
478 : :
479 : : rxhdr = (struct b43legacy_rxhdr_fw3 *)(skb->data);
480 : : rxhdr->frame_len = 0;
481 : : txstat = (struct b43legacy_hwtxstatus *)(skb->data);
482 : : txstat->cookie = 0;
483 : :
484 : : return 0;
485 : : }
486 : :
487 : : /* Allocate the initial descbuffers.
488 : : * This is used for an RX ring only.
489 : : */
490 : 0 : static int alloc_initial_descbuffers(struct b43legacy_dmaring *ring)
491 : : {
492 : 0 : int i;
493 : 0 : int err = -ENOMEM;
494 : 0 : struct b43legacy_dmadesc32 *desc;
495 : 0 : struct b43legacy_dmadesc_meta *meta;
496 : :
497 [ # # ]: 0 : for (i = 0; i < ring->nr_slots; i++) {
498 : 0 : desc = op32_idx2desc(ring, i, &meta);
499 : :
500 : 0 : err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
501 [ # # ]: 0 : if (err) {
502 : 0 : b43legacyerr(ring->dev->wl,
503 : : "Failed to allocate initial descbuffers\n");
504 : 0 : goto err_unwind;
505 : : }
506 : : }
507 : 0 : mb(); /* all descbuffer setup before next line */
508 : 0 : ring->used_slots = ring->nr_slots;
509 : 0 : err = 0;
510 : 0 : out:
511 : 0 : return err;
512 : :
513 : : err_unwind:
514 [ # # ]: 0 : for (i--; i >= 0; i--) {
515 : 0 : desc = op32_idx2desc(ring, i, &meta);
516 : :
517 : 0 : unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
518 : 0 : dev_kfree_skb(meta->skb);
519 : : }
520 : 0 : goto out;
521 : : }
522 : :
523 : : /* Do initial setup of the DMA controller.
524 : : * Reset the controller, write the ring busaddress
525 : : * and switch the "enable" bit on.
526 : : */
527 : 0 : static int dmacontroller_setup(struct b43legacy_dmaring *ring)
528 : : {
529 : 0 : int err = 0;
530 : 0 : u32 value;
531 : 0 : u32 addrext;
532 : 0 : u32 trans = ring->dev->dma.translation;
533 : 0 : u32 ringbase = (u32)(ring->dmabase);
534 : :
535 [ # # ]: 0 : if (ring->tx) {
536 : 0 : addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
537 : : >> SSB_DMA_TRANSLATION_SHIFT;
538 : 0 : value = B43legacy_DMA32_TXENABLE;
539 : 0 : value |= (addrext << B43legacy_DMA32_TXADDREXT_SHIFT)
540 : : & B43legacy_DMA32_TXADDREXT_MASK;
541 : 0 : b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL, value);
542 : 0 : b43legacy_dma_write(ring, B43legacy_DMA32_TXRING,
543 : 0 : (ringbase & ~SSB_DMA_TRANSLATION_MASK)
544 : : | trans);
545 : : } else {
546 : 0 : err = alloc_initial_descbuffers(ring);
547 [ # # ]: 0 : if (err)
548 : 0 : goto out;
549 : :
550 : 0 : addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
551 : : >> SSB_DMA_TRANSLATION_SHIFT;
552 : 0 : value = (ring->frameoffset <<
553 : : B43legacy_DMA32_RXFROFF_SHIFT);
554 : 0 : value |= B43legacy_DMA32_RXENABLE;
555 : 0 : value |= (addrext << B43legacy_DMA32_RXADDREXT_SHIFT)
556 : : & B43legacy_DMA32_RXADDREXT_MASK;
557 : 0 : b43legacy_dma_write(ring, B43legacy_DMA32_RXCTL, value);
558 : 0 : b43legacy_dma_write(ring, B43legacy_DMA32_RXRING,
559 : 0 : (ringbase & ~SSB_DMA_TRANSLATION_MASK)
560 : : | trans);
561 : 0 : b43legacy_dma_write(ring, B43legacy_DMA32_RXINDEX, 200);
562 : : }
563 : :
564 : 0 : out:
565 : 0 : return err;
566 : : }
567 : :
568 : : /* Shutdown the DMA controller. */
569 : 0 : static void dmacontroller_cleanup(struct b43legacy_dmaring *ring)
570 : : {
571 [ # # ]: 0 : if (ring->tx) {
572 : 0 : b43legacy_dmacontroller_tx_reset(ring->dev, ring->mmio_base,
573 : : ring->type);
574 : 0 : b43legacy_dma_write(ring, B43legacy_DMA32_TXRING, 0);
575 : : } else {
576 : 0 : b43legacy_dmacontroller_rx_reset(ring->dev, ring->mmio_base,
577 : : ring->type);
578 : 0 : b43legacy_dma_write(ring, B43legacy_DMA32_RXRING, 0);
579 : : }
580 : 0 : }
581 : :
582 : 0 : static void free_all_descbuffers(struct b43legacy_dmaring *ring)
583 : : {
584 : 0 : struct b43legacy_dmadesc_meta *meta;
585 : 0 : int i;
586 : :
587 [ # # ]: 0 : if (!ring->used_slots)
588 : : return;
589 [ # # ]: 0 : for (i = 0; i < ring->nr_slots; i++) {
590 : 0 : op32_idx2desc(ring, i, &meta);
591 : :
592 [ # # ]: 0 : if (!meta->skb) {
593 [ # # ]: 0 : B43legacy_WARN_ON(!ring->tx);
594 : 0 : continue;
595 : : }
596 [ # # ]: 0 : if (ring->tx)
597 : 0 : unmap_descbuffer(ring, meta->dmaaddr,
598 : 0 : meta->skb->len, 1);
599 : : else
600 : 0 : unmap_descbuffer(ring, meta->dmaaddr,
601 : 0 : ring->rx_buffersize, 0);
602 [ # # ]: 0 : free_descriptor_buffer(ring, meta, 0);
603 : : }
604 : : }
605 : :
606 : : static enum b43legacy_dmatype b43legacy_engine_type(struct b43legacy_wldev *dev)
607 : : {
608 : : u32 tmp;
609 : : u16 mmio_base;
610 : :
611 : : mmio_base = b43legacy_dmacontroller_base(0, 0);
612 : : b43legacy_write32(dev,
613 : : mmio_base + B43legacy_DMA32_TXCTL,
614 : : B43legacy_DMA32_TXADDREXT_MASK);
615 : : tmp = b43legacy_read32(dev, mmio_base +
616 : : B43legacy_DMA32_TXCTL);
617 : : if (tmp & B43legacy_DMA32_TXADDREXT_MASK)
618 : : return B43legacy_DMA_32BIT;
619 : : return B43legacy_DMA_30BIT;
620 : : }
621 : :
622 : : /* Main initialization function. */
623 : : static
624 : 0 : struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
625 : : int controller_index,
626 : : int for_tx,
627 : : enum b43legacy_dmatype type)
628 : : {
629 : 0 : struct b43legacy_dmaring *ring;
630 : 0 : int err;
631 : 0 : int nr_slots;
632 : 0 : dma_addr_t dma_test;
633 : :
634 : 0 : ring = kzalloc(sizeof(*ring), GFP_KERNEL);
635 [ # # ]: 0 : if (!ring)
636 : 0 : goto out;
637 : 0 : ring->type = type;
638 : 0 : ring->dev = dev;
639 : :
640 : 0 : nr_slots = B43legacy_RXRING_SLOTS;
641 [ # # ]: 0 : if (for_tx)
642 : 0 : nr_slots = B43legacy_TXRING_SLOTS;
643 : :
644 : 0 : ring->meta = kcalloc(nr_slots, sizeof(struct b43legacy_dmadesc_meta),
645 : : GFP_KERNEL);
646 [ # # ]: 0 : if (!ring->meta)
647 : 0 : goto err_kfree_ring;
648 [ # # ]: 0 : if (for_tx) {
649 : 0 : ring->txhdr_cache = kcalloc(nr_slots,
650 : : sizeof(struct b43legacy_txhdr_fw3),
651 : : GFP_KERNEL);
652 [ # # ]: 0 : if (!ring->txhdr_cache)
653 : 0 : goto err_kfree_meta;
654 : :
655 : : /* test for ability to dma to txhdr_cache */
656 : 0 : dma_test = dma_map_single(dev->dev->dma_dev, ring->txhdr_cache,
657 : : sizeof(struct b43legacy_txhdr_fw3),
658 : : DMA_TO_DEVICE);
659 : :
660 [ # # ]: 0 : if (b43legacy_dma_mapping_error(ring, dma_test,
661 : : sizeof(struct b43legacy_txhdr_fw3), 1)) {
662 : : /* ugh realloc */
663 : 0 : kfree(ring->txhdr_cache);
664 : 0 : ring->txhdr_cache = kcalloc(nr_slots,
665 : : sizeof(struct b43legacy_txhdr_fw3),
666 : : GFP_KERNEL | GFP_DMA);
667 [ # # ]: 0 : if (!ring->txhdr_cache)
668 : 0 : goto err_kfree_meta;
669 : :
670 : 0 : dma_test = dma_map_single(dev->dev->dma_dev,
671 : : ring->txhdr_cache,
672 : : sizeof(struct b43legacy_txhdr_fw3),
673 : : DMA_TO_DEVICE);
674 : :
675 [ # # ]: 0 : if (b43legacy_dma_mapping_error(ring, dma_test,
676 : : sizeof(struct b43legacy_txhdr_fw3), 1))
677 : 0 : goto err_kfree_txhdr_cache;
678 : : }
679 : :
680 : 0 : dma_unmap_single(dev->dev->dma_dev, dma_test,
681 : : sizeof(struct b43legacy_txhdr_fw3),
682 : : DMA_TO_DEVICE);
683 : : }
684 : :
685 : 0 : ring->nr_slots = nr_slots;
686 [ # # ]: 0 : ring->mmio_base = b43legacy_dmacontroller_base(type, controller_index);
687 : 0 : ring->index = controller_index;
688 [ # # ]: 0 : if (for_tx) {
689 : 0 : ring->tx = true;
690 : 0 : ring->current_slot = -1;
691 : : } else {
692 [ # # ]: 0 : if (ring->index == 0) {
693 : 0 : ring->rx_buffersize = B43legacy_DMA0_RX_BUFFERSIZE;
694 : 0 : ring->frameoffset = B43legacy_DMA0_RX_FRAMEOFFSET;
695 [ # # ]: 0 : } else if (ring->index == 3) {
696 : 0 : ring->rx_buffersize = B43legacy_DMA3_RX_BUFFERSIZE;
697 : 0 : ring->frameoffset = B43legacy_DMA3_RX_FRAMEOFFSET;
698 : : } else
699 : 0 : B43legacy_WARN_ON(1);
700 : : }
701 : : #ifdef CONFIG_B43LEGACY_DEBUG
702 : 0 : ring->last_injected_overflow = jiffies;
703 : : #endif
704 : :
705 : 0 : err = alloc_ringmemory(ring);
706 [ # # ]: 0 : if (err)
707 : 0 : goto err_kfree_txhdr_cache;
708 : 0 : err = dmacontroller_setup(ring);
709 [ # # ]: 0 : if (err)
710 : 0 : goto err_free_ringmemory;
711 : :
712 : 0 : out:
713 : 0 : return ring;
714 : :
715 : : err_free_ringmemory:
716 : 0 : free_ringmemory(ring);
717 : 0 : err_kfree_txhdr_cache:
718 : 0 : kfree(ring->txhdr_cache);
719 : 0 : err_kfree_meta:
720 : 0 : kfree(ring->meta);
721 : 0 : err_kfree_ring:
722 : 0 : kfree(ring);
723 : 0 : ring = NULL;
724 : 0 : goto out;
725 : : }
726 : :
727 : : /* Main cleanup function. */
728 : 0 : static void b43legacy_destroy_dmaring(struct b43legacy_dmaring *ring)
729 : : {
730 [ # # ]: 0 : if (!ring)
731 : : return;
732 : :
733 : 0 : b43legacydbg(ring->dev->wl, "DMA-%u 0x%04X (%s) max used slots:"
734 : 0 : " %d/%d\n", (unsigned int)(ring->type), ring->mmio_base,
735 [ # # ]: 0 : (ring->tx) ? "TX" : "RX", ring->max_used_slots,
736 : : ring->nr_slots);
737 : : /* Device IRQs are disabled prior entering this function,
738 : : * so no need to take care of concurrency with rx handler stuff.
739 : : */
740 : 0 : dmacontroller_cleanup(ring);
741 : 0 : free_all_descbuffers(ring);
742 : 0 : free_ringmemory(ring);
743 : :
744 : 0 : kfree(ring->txhdr_cache);
745 : 0 : kfree(ring->meta);
746 : 0 : kfree(ring);
747 : : }
748 : :
749 : 0 : void b43legacy_dma_free(struct b43legacy_wldev *dev)
750 : : {
751 : 0 : struct b43legacy_dma *dma;
752 : :
753 [ # # ]: 0 : if (b43legacy_using_pio(dev))
754 : : return;
755 : 0 : dma = &dev->dma;
756 : :
757 : 0 : b43legacy_destroy_dmaring(dma->rx_ring3);
758 : 0 : dma->rx_ring3 = NULL;
759 : 0 : b43legacy_destroy_dmaring(dma->rx_ring0);
760 : 0 : dma->rx_ring0 = NULL;
761 : :
762 : 0 : b43legacy_destroy_dmaring(dma->tx_ring5);
763 : 0 : dma->tx_ring5 = NULL;
764 : 0 : b43legacy_destroy_dmaring(dma->tx_ring4);
765 : 0 : dma->tx_ring4 = NULL;
766 : 0 : b43legacy_destroy_dmaring(dma->tx_ring3);
767 : 0 : dma->tx_ring3 = NULL;
768 : 0 : b43legacy_destroy_dmaring(dma->tx_ring2);
769 : 0 : dma->tx_ring2 = NULL;
770 : 0 : b43legacy_destroy_dmaring(dma->tx_ring1);
771 : 0 : dma->tx_ring1 = NULL;
772 : 0 : b43legacy_destroy_dmaring(dma->tx_ring0);
773 : 0 : dma->tx_ring0 = NULL;
774 : : }
775 : :
776 : 0 : int b43legacy_dma_init(struct b43legacy_wldev *dev)
777 : : {
778 : 0 : struct b43legacy_dma *dma = &dev->dma;
779 : 0 : struct b43legacy_dmaring *ring;
780 : 0 : enum b43legacy_dmatype type = b43legacy_engine_type(dev);
781 : 0 : int err;
782 : :
783 [ # # ]: 0 : err = dma_set_mask_and_coherent(dev->dev->dma_dev, DMA_BIT_MASK(type));
784 [ # # ]: 0 : if (err) {
785 : : #ifdef CONFIG_B43LEGACY_PIO
786 : 0 : b43legacywarn(dev->wl, "DMA for this device not supported. "
787 : : "Falling back to PIO\n");
788 : 0 : dev->__using_pio = true;
789 : 0 : return -EAGAIN;
790 : : #else
791 : : b43legacyerr(dev->wl, "DMA for this device not supported and "
792 : : "no PIO support compiled in\n");
793 : : return -EOPNOTSUPP;
794 : : #endif
795 : : }
796 : 0 : dma->translation = ssb_dma_translation(dev->dev);
797 : :
798 : 0 : err = -ENOMEM;
799 : : /* setup TX DMA channels. */
800 : 0 : ring = b43legacy_setup_dmaring(dev, 0, 1, type);
801 [ # # ]: 0 : if (!ring)
802 : 0 : goto out;
803 : 0 : dma->tx_ring0 = ring;
804 : :
805 : 0 : ring = b43legacy_setup_dmaring(dev, 1, 1, type);
806 [ # # ]: 0 : if (!ring)
807 : 0 : goto err_destroy_tx0;
808 : 0 : dma->tx_ring1 = ring;
809 : :
810 : 0 : ring = b43legacy_setup_dmaring(dev, 2, 1, type);
811 [ # # ]: 0 : if (!ring)
812 : 0 : goto err_destroy_tx1;
813 : 0 : dma->tx_ring2 = ring;
814 : :
815 : 0 : ring = b43legacy_setup_dmaring(dev, 3, 1, type);
816 [ # # ]: 0 : if (!ring)
817 : 0 : goto err_destroy_tx2;
818 : 0 : dma->tx_ring3 = ring;
819 : :
820 : 0 : ring = b43legacy_setup_dmaring(dev, 4, 1, type);
821 [ # # ]: 0 : if (!ring)
822 : 0 : goto err_destroy_tx3;
823 : 0 : dma->tx_ring4 = ring;
824 : :
825 : 0 : ring = b43legacy_setup_dmaring(dev, 5, 1, type);
826 [ # # ]: 0 : if (!ring)
827 : 0 : goto err_destroy_tx4;
828 : 0 : dma->tx_ring5 = ring;
829 : :
830 : : /* setup RX DMA channels. */
831 : 0 : ring = b43legacy_setup_dmaring(dev, 0, 0, type);
832 [ # # ]: 0 : if (!ring)
833 : 0 : goto err_destroy_tx5;
834 : 0 : dma->rx_ring0 = ring;
835 : :
836 [ # # ]: 0 : if (dev->dev->id.revision < 5) {
837 : 0 : ring = b43legacy_setup_dmaring(dev, 3, 0, type);
838 [ # # ]: 0 : if (!ring)
839 : 0 : goto err_destroy_rx0;
840 : 0 : dma->rx_ring3 = ring;
841 : : }
842 : :
843 : 0 : b43legacydbg(dev->wl, "%u-bit DMA initialized\n", (unsigned int)type);
844 : 0 : err = 0;
845 : : out:
846 : : return err;
847 : :
848 : : err_destroy_rx0:
849 : 0 : b43legacy_destroy_dmaring(dma->rx_ring0);
850 : 0 : dma->rx_ring0 = NULL;
851 : 0 : err_destroy_tx5:
852 : 0 : b43legacy_destroy_dmaring(dma->tx_ring5);
853 : 0 : dma->tx_ring5 = NULL;
854 : 0 : err_destroy_tx4:
855 : 0 : b43legacy_destroy_dmaring(dma->tx_ring4);
856 : 0 : dma->tx_ring4 = NULL;
857 : 0 : err_destroy_tx3:
858 : 0 : b43legacy_destroy_dmaring(dma->tx_ring3);
859 : 0 : dma->tx_ring3 = NULL;
860 : 0 : err_destroy_tx2:
861 : 0 : b43legacy_destroy_dmaring(dma->tx_ring2);
862 : 0 : dma->tx_ring2 = NULL;
863 : 0 : err_destroy_tx1:
864 : 0 : b43legacy_destroy_dmaring(dma->tx_ring1);
865 : 0 : dma->tx_ring1 = NULL;
866 : 0 : err_destroy_tx0:
867 : 0 : b43legacy_destroy_dmaring(dma->tx_ring0);
868 : 0 : dma->tx_ring0 = NULL;
869 : 0 : goto out;
870 : : }
871 : :
872 : : /* Generate a cookie for the TX header. */
873 : 0 : static u16 generate_cookie(struct b43legacy_dmaring *ring,
874 : : int slot)
875 : : {
876 : 0 : u16 cookie = 0x1000;
877 : :
878 : : /* Use the upper 4 bits of the cookie as
879 : : * DMA controller ID and store the slot number
880 : : * in the lower 12 bits.
881 : : * Note that the cookie must never be 0, as this
882 : : * is a special value used in RX path.
883 : : */
884 : 0 : switch (ring->index) {
885 : : case 0:
886 : : cookie = 0xA000;
887 : : break;
888 : : case 1:
889 : : cookie = 0xB000;
890 : : break;
891 : : case 2:
892 : : cookie = 0xC000;
893 : : break;
894 : : case 3:
895 : : cookie = 0xD000;
896 : : break;
897 : : case 4:
898 : : cookie = 0xE000;
899 : : break;
900 : : case 5:
901 : : cookie = 0xF000;
902 : : break;
903 : : }
904 [ # # ]: 0 : B43legacy_WARN_ON(!(((u16)slot & 0xF000) == 0x0000));
905 : 0 : cookie |= (u16)slot;
906 : :
907 : 0 : return cookie;
908 : : }
909 : :
910 : : /* Inspect a cookie and find out to which controller/slot it belongs. */
911 : : static
912 : 0 : struct b43legacy_dmaring *parse_cookie(struct b43legacy_wldev *dev,
913 : : u16 cookie, int *slot)
914 : : {
915 : 0 : struct b43legacy_dma *dma = &dev->dma;
916 : 0 : struct b43legacy_dmaring *ring = NULL;
917 : :
918 [ # # # # : 0 : switch (cookie & 0xF000) {
# # # ]
919 : 0 : case 0xA000:
920 : 0 : ring = dma->tx_ring0;
921 : 0 : break;
922 : 0 : case 0xB000:
923 : 0 : ring = dma->tx_ring1;
924 : 0 : break;
925 : 0 : case 0xC000:
926 : 0 : ring = dma->tx_ring2;
927 : 0 : break;
928 : 0 : case 0xD000:
929 : 0 : ring = dma->tx_ring3;
930 : 0 : break;
931 : 0 : case 0xE000:
932 : 0 : ring = dma->tx_ring4;
933 : 0 : break;
934 : 0 : case 0xF000:
935 : 0 : ring = dma->tx_ring5;
936 : 0 : break;
937 : : default:
938 : 0 : B43legacy_WARN_ON(1);
939 : : }
940 : 0 : *slot = (cookie & 0x0FFF);
941 [ # # # # : 0 : B43legacy_WARN_ON(!(ring && *slot >= 0 && *slot < ring->nr_slots));
# # ]
942 : :
943 : 0 : return ring;
944 : : }
945 : :
946 : 0 : static int dma_tx_fragment(struct b43legacy_dmaring *ring,
947 : : struct sk_buff **in_skb)
948 : : {
949 : 0 : struct sk_buff *skb = *in_skb;
950 [ # # ]: 0 : struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
951 : 0 : u8 *header;
952 : 0 : int slot, old_top_slot, old_used_slots;
953 : 0 : int err;
954 : 0 : struct b43legacy_dmadesc32 *desc;
955 : 0 : struct b43legacy_dmadesc_meta *meta;
956 : 0 : struct b43legacy_dmadesc_meta *meta_hdr;
957 : 0 : struct sk_buff *bounce_skb;
958 : :
959 : : #define SLOTS_PER_PACKET 2
960 [ # # ]: 0 : B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0);
961 : :
962 : 0 : old_top_slot = ring->current_slot;
963 : 0 : old_used_slots = ring->used_slots;
964 : :
965 : : /* Get a slot for the header. */
966 : 0 : slot = request_slot(ring);
967 : 0 : desc = op32_idx2desc(ring, slot, &meta_hdr);
968 : 0 : memset(meta_hdr, 0, sizeof(*meta_hdr));
969 : :
970 : 0 : header = &(ring->txhdr_cache[slot * sizeof(
971 : : struct b43legacy_txhdr_fw3)]);
972 : 0 : err = b43legacy_generate_txhdr(ring->dev, header,
973 : 0 : skb->data, skb->len, info,
974 [ # # ]: 0 : generate_cookie(ring, slot));
975 [ # # ]: 0 : if (unlikely(err)) {
976 : 0 : ring->current_slot = old_top_slot;
977 : 0 : ring->used_slots = old_used_slots;
978 : 0 : return err;
979 : : }
980 : :
981 : 0 : meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
982 : : sizeof(struct b43legacy_txhdr_fw3), 1);
983 [ # # ]: 0 : if (b43legacy_dma_mapping_error(ring, meta_hdr->dmaaddr,
984 : : sizeof(struct b43legacy_txhdr_fw3), 1)) {
985 : 0 : ring->current_slot = old_top_slot;
986 : 0 : ring->used_slots = old_used_slots;
987 : 0 : return -EIO;
988 : : }
989 : 0 : op32_fill_descriptor(ring, desc, meta_hdr->dmaaddr,
990 : : sizeof(struct b43legacy_txhdr_fw3), 1, 0, 0);
991 : :
992 : : /* Get a slot for the payload. */
993 : 0 : slot = request_slot(ring);
994 : 0 : desc = op32_idx2desc(ring, slot, &meta);
995 : 0 : memset(meta, 0, sizeof(*meta));
996 : :
997 : 0 : meta->skb = skb;
998 : 0 : meta->is_last_fragment = true;
999 : :
1000 : 0 : meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
1001 : : /* create a bounce buffer in zone_dma on mapping failure. */
1002 [ # # ]: 0 : if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
1003 : 0 : bounce_skb = alloc_skb(skb->len, GFP_KERNEL | GFP_DMA);
1004 [ # # ]: 0 : if (!bounce_skb) {
1005 : 0 : ring->current_slot = old_top_slot;
1006 : 0 : ring->used_slots = old_used_slots;
1007 : 0 : err = -ENOMEM;
1008 : 0 : goto out_unmap_hdr;
1009 : : }
1010 : :
1011 : 0 : skb_put_data(bounce_skb, skb->data, skb->len);
1012 : 0 : memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb));
1013 : 0 : bounce_skb->dev = skb->dev;
1014 : 0 : skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb));
1015 : 0 : info = IEEE80211_SKB_CB(bounce_skb);
1016 : :
1017 : 0 : dev_kfree_skb_any(skb);
1018 : 0 : skb = bounce_skb;
1019 : 0 : *in_skb = bounce_skb;
1020 : 0 : meta->skb = skb;
1021 : 0 : meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
1022 [ # # ]: 0 : if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
1023 : 0 : ring->current_slot = old_top_slot;
1024 : 0 : ring->used_slots = old_used_slots;
1025 : 0 : err = -EIO;
1026 : 0 : goto out_free_bounce;
1027 : : }
1028 : : }
1029 : :
1030 : 0 : op32_fill_descriptor(ring, desc, meta->dmaaddr,
1031 : 0 : skb->len, 0, 1, 1);
1032 : :
1033 : 0 : wmb(); /* previous stuff MUST be done */
1034 : : /* Now transfer the whole frame. */
1035 [ # # ]: 0 : op32_poke_tx(ring, next_slot(ring, slot));
1036 : 0 : return 0;
1037 : :
1038 : : out_free_bounce:
1039 : 0 : dev_kfree_skb_any(skb);
1040 : 0 : out_unmap_hdr:
1041 : 0 : unmap_descbuffer(ring, meta_hdr->dmaaddr,
1042 : : sizeof(struct b43legacy_txhdr_fw3), 1);
1043 : 0 : return err;
1044 : : }
1045 : :
1046 : : static inline
1047 : 0 : int should_inject_overflow(struct b43legacy_dmaring *ring)
1048 : : {
1049 : : #ifdef CONFIG_B43LEGACY_DEBUG
1050 [ # # ]: 0 : if (unlikely(b43legacy_debug(ring->dev,
1051 : : B43legacy_DBG_DMAOVERFLOW))) {
1052 : : /* Check if we should inject another ringbuffer overflow
1053 : : * to test handling of this situation in the stack. */
1054 : 0 : unsigned long next_overflow;
1055 : :
1056 : 0 : next_overflow = ring->last_injected_overflow + HZ;
1057 [ # # ]: 0 : if (time_after(jiffies, next_overflow)) {
1058 : 0 : ring->last_injected_overflow = jiffies;
1059 : 0 : b43legacydbg(ring->dev->wl,
1060 : : "Injecting TX ring overflow on "
1061 : : "DMA controller %d\n", ring->index);
1062 : 0 : return 1;
1063 : : }
1064 : : }
1065 : : #endif /* CONFIG_B43LEGACY_DEBUG */
1066 : : return 0;
1067 : : }
1068 : :
1069 : 0 : int b43legacy_dma_tx(struct b43legacy_wldev *dev,
1070 : : struct sk_buff *skb)
1071 : : {
1072 : 0 : struct b43legacy_dmaring *ring;
1073 : 0 : int err = 0;
1074 : :
1075 [ # # ]: 0 : ring = priority_to_txring(dev, skb_get_queue_mapping(skb));
1076 [ # # ]: 0 : B43legacy_WARN_ON(!ring->tx);
1077 : :
1078 [ # # ]: 0 : if (unlikely(ring->stopped)) {
1079 : : /* We get here only because of a bug in mac80211.
1080 : : * Because of a race, one packet may be queued after
1081 : : * the queue is stopped, thus we got called when we shouldn't.
1082 : : * For now, just refuse the transmit. */
1083 [ # # ]: 0 : if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE))
1084 : 0 : b43legacyerr(dev->wl, "Packet after queue stopped\n");
1085 : 0 : return -ENOSPC;
1086 : : }
1087 : :
1088 [ # # # # ]: 0 : if (WARN_ON(free_slots(ring) < SLOTS_PER_PACKET)) {
1089 : : /* If we get here, we have a real error with the queue
1090 : : * full, but queues not stopped. */
1091 : 0 : b43legacyerr(dev->wl, "DMA queue overflow\n");
1092 : 0 : return -ENOSPC;
1093 : : }
1094 : :
1095 : : /* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing
1096 : : * into the skb data or cb now. */
1097 : 0 : err = dma_tx_fragment(ring, &skb);
1098 [ # # ]: 0 : if (unlikely(err == -ENOKEY)) {
1099 : : /* Drop this packet, as we don't have the encryption key
1100 : : * anymore and must not transmit it unencrypted. */
1101 : 0 : dev_kfree_skb_any(skb);
1102 : 0 : return 0;
1103 : : }
1104 [ # # ]: 0 : if (unlikely(err)) {
1105 : 0 : b43legacyerr(dev->wl, "DMA tx mapping failure\n");
1106 : 0 : return err;
1107 : : }
1108 [ # # # # ]: 0 : if ((free_slots(ring) < SLOTS_PER_PACKET) ||
1109 : 0 : should_inject_overflow(ring)) {
1110 : : /* This TX ring is full. */
1111 : 0 : unsigned int skb_mapping = skb_get_queue_mapping(skb);
1112 : 0 : ieee80211_stop_queue(dev->wl->hw, skb_mapping);
1113 : 0 : dev->wl->tx_queue_stopped[skb_mapping] = 1;
1114 : 0 : ring->stopped = true;
1115 [ # # ]: 0 : if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE))
1116 : 0 : b43legacydbg(dev->wl, "Stopped TX ring %d\n",
1117 : : ring->index);
1118 : : }
1119 : : return err;
1120 : : }
1121 : :
1122 : 0 : void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
1123 : : const struct b43legacy_txstatus *status)
1124 : : {
1125 : 0 : struct b43legacy_dmaring *ring;
1126 : 0 : struct b43legacy_dmadesc_meta *meta;
1127 : 0 : int retry_limit;
1128 : 0 : int slot;
1129 : 0 : int firstused;
1130 : :
1131 : 0 : ring = parse_cookie(dev, status->cookie, &slot);
1132 [ # # ]: 0 : if (unlikely(!ring))
1133 : 0 : return;
1134 [ # # ]: 0 : B43legacy_WARN_ON(!ring->tx);
1135 : :
1136 : : /* Sanity check: TX packets are processed in-order on one ring.
1137 : : * Check if the slot deduced from the cookie really is the first
1138 : : * used slot. */
1139 : 0 : firstused = ring->current_slot - ring->used_slots + 1;
1140 [ # # ]: 0 : if (firstused < 0)
1141 : 0 : firstused = ring->nr_slots + firstused;
1142 [ # # ]: 0 : if (unlikely(slot != firstused)) {
1143 : : /* This possibly is a firmware bug and will result in
1144 : : * malfunction, memory leaks and/or stall of DMA functionality.
1145 : : */
1146 : 0 : b43legacydbg(dev->wl, "Out of order TX status report on DMA "
1147 : : "ring %d. Expected %d, but got %d\n",
1148 : : ring->index, firstused, slot);
1149 : 0 : return;
1150 : : }
1151 : :
1152 : 0 : while (1) {
1153 [ # # # # : 0 : B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
# # ]
1154 : 0 : op32_idx2desc(ring, slot, &meta);
1155 : :
1156 [ # # ]: 0 : if (meta->skb)
1157 : 0 : unmap_descbuffer(ring, meta->dmaaddr,
1158 : 0 : meta->skb->len, 1);
1159 : : else
1160 : 0 : unmap_descbuffer(ring, meta->dmaaddr,
1161 : : sizeof(struct b43legacy_txhdr_fw3),
1162 : : 1);
1163 : :
1164 [ # # ]: 0 : if (meta->is_last_fragment) {
1165 : 0 : struct ieee80211_tx_info *info;
1166 [ # # ]: 0 : BUG_ON(!meta->skb);
1167 : 0 : info = IEEE80211_SKB_CB(meta->skb);
1168 : :
1169 : : /* preserve the confiured retry limit before clearing the status
1170 : : * The xmit function has overwritten the rc's value with the actual
1171 : : * retry limit done by the hardware */
1172 : 0 : retry_limit = info->status.rates[0].count;
1173 : 0 : ieee80211_tx_info_clear_status(info);
1174 : :
1175 [ # # ]: 0 : if (status->acked)
1176 : 0 : info->flags |= IEEE80211_TX_STAT_ACK;
1177 : :
1178 [ # # ]: 0 : if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
1179 : : /*
1180 : : * If the short retries (RTS, not data frame) have exceeded
1181 : : * the limit, the hw will not have tried the selected rate,
1182 : : * but will have used the fallback rate instead.
1183 : : * Don't let the rate control count attempts for the selected
1184 : : * rate in this case, otherwise the statistics will be off.
1185 : : */
1186 : 0 : info->status.rates[0].count = 0;
1187 : 0 : info->status.rates[1].count = status->frame_count;
1188 : : } else {
1189 [ # # ]: 0 : if (status->frame_count > retry_limit) {
1190 : 0 : info->status.rates[0].count = retry_limit;
1191 : 0 : info->status.rates[1].count = status->frame_count -
1192 : : retry_limit;
1193 : :
1194 : : } else {
1195 : 0 : info->status.rates[0].count = status->frame_count;
1196 : 0 : info->status.rates[1].idx = -1;
1197 : : }
1198 : : }
1199 : :
1200 : : /* Call back to inform the ieee80211 subsystem about the
1201 : : * status of the transmission.
1202 : : * Some fields of txstat are already filled in dma_tx().
1203 : : */
1204 : 0 : ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb);
1205 : : /* skb is freed by ieee80211_tx_status_irqsafe() */
1206 : 0 : meta->skb = NULL;
1207 : : } else {
1208 : : /* No need to call free_descriptor_buffer here, as
1209 : : * this is only the txhdr, which is not allocated.
1210 : : */
1211 [ # # ]: 0 : B43legacy_WARN_ON(meta->skb != NULL);
1212 : : }
1213 : :
1214 : : /* Everything unmapped and free'd. So it's not used anymore. */
1215 : 0 : ring->used_slots--;
1216 : :
1217 [ # # ]: 0 : if (meta->is_last_fragment)
1218 : : break;
1219 [ # # ]: 0 : slot = next_slot(ring, slot);
1220 : : }
1221 : 0 : dev->stats.last_tx = jiffies;
1222 [ # # ]: 0 : if (ring->stopped) {
1223 [ # # ]: 0 : B43legacy_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET);
1224 : 0 : ring->stopped = false;
1225 : : }
1226 : :
1227 [ # # ]: 0 : if (dev->wl->tx_queue_stopped[ring->queue_prio]) {
1228 : 0 : dev->wl->tx_queue_stopped[ring->queue_prio] = 0;
1229 : : } else {
1230 : : /* If the driver queue is running wake the corresponding
1231 : : * mac80211 queue. */
1232 : 0 : ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
1233 [ # # ]: 0 : if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE))
1234 : 0 : b43legacydbg(dev->wl, "Woke up TX ring %d\n",
1235 : : ring->index);
1236 : : }
1237 : : /* Add work to the queue. */
1238 : 0 : ieee80211_queue_work(dev->wl->hw, &dev->wl->tx_work);
1239 : : }
1240 : :
1241 : 0 : static void dma_rx(struct b43legacy_dmaring *ring,
1242 : : int *slot)
1243 : : {
1244 : 0 : struct b43legacy_dmadesc32 *desc;
1245 : 0 : struct b43legacy_dmadesc_meta *meta;
1246 : 0 : struct b43legacy_rxhdr_fw3 *rxhdr;
1247 : 0 : struct sk_buff *skb;
1248 : 0 : u16 len;
1249 : 0 : int err;
1250 : 0 : dma_addr_t dmaaddr;
1251 : :
1252 : 0 : desc = op32_idx2desc(ring, *slot, &meta);
1253 : :
1254 : 0 : sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
1255 : 0 : skb = meta->skb;
1256 : :
1257 [ # # ]: 0 : if (ring->index == 3) {
1258 : : /* We received an xmit status. */
1259 : 0 : struct b43legacy_hwtxstatus *hw =
1260 : : (struct b43legacy_hwtxstatus *)skb->data;
1261 : 0 : int i = 0;
1262 : :
1263 [ # # ]: 0 : while (hw->cookie == 0) {
1264 [ # # ]: 0 : if (i > 100)
1265 : : break;
1266 : 0 : i++;
1267 : 0 : udelay(2);
1268 : 0 : barrier();
1269 : : }
1270 : 0 : b43legacy_handle_hwtxstatus(ring->dev, hw);
1271 : : /* recycle the descriptor buffer. */
1272 : 0 : sync_descbuffer_for_device(ring, meta->dmaaddr,
1273 : 0 : ring->rx_buffersize);
1274 : :
1275 : 0 : return;
1276 : : }
1277 : 0 : rxhdr = (struct b43legacy_rxhdr_fw3 *)skb->data;
1278 : 0 : len = le16_to_cpu(rxhdr->frame_len);
1279 [ # # ]: 0 : if (len == 0) {
1280 : : int i = 0;
1281 : :
1282 : 0 : do {
1283 : 0 : udelay(2);
1284 : 0 : barrier();
1285 : 0 : len = le16_to_cpu(rxhdr->frame_len);
1286 [ # # # # ]: 0 : } while (len == 0 && i++ < 5);
1287 [ # # ]: 0 : if (unlikely(len == 0)) {
1288 : : /* recycle the descriptor buffer. */
1289 : 0 : sync_descbuffer_for_device(ring, meta->dmaaddr,
1290 : 0 : ring->rx_buffersize);
1291 : 0 : goto drop;
1292 : : }
1293 : : }
1294 [ # # ]: 0 : if (unlikely(len > ring->rx_buffersize)) {
1295 : : /* The data did not fit into one descriptor buffer
1296 : : * and is split over multiple buffers.
1297 : : * This should never happen, as we try to allocate buffers
1298 : : * big enough. So simply ignore this packet.
1299 : : */
1300 : 0 : int cnt = 0;
1301 : 0 : s32 tmp = len;
1302 : :
1303 : 0 : while (1) {
1304 : 0 : desc = op32_idx2desc(ring, *slot, &meta);
1305 : : /* recycle the descriptor buffer. */
1306 : 0 : sync_descbuffer_for_device(ring, meta->dmaaddr,
1307 : 0 : ring->rx_buffersize);
1308 [ # # ]: 0 : *slot = next_slot(ring, *slot);
1309 : 0 : cnt++;
1310 : 0 : tmp -= ring->rx_buffersize;
1311 [ # # ]: 0 : if (tmp <= 0)
1312 : : break;
1313 : : }
1314 : 0 : b43legacyerr(ring->dev->wl, "DMA RX buffer too small "
1315 : : "(len: %u, buffer: %u, nr-dropped: %d)\n",
1316 : : len, ring->rx_buffersize, cnt);
1317 : 0 : goto drop;
1318 : : }
1319 : :
1320 : 0 : dmaaddr = meta->dmaaddr;
1321 : 0 : err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC);
1322 [ # # ]: 0 : if (unlikely(err)) {
1323 : 0 : b43legacydbg(ring->dev->wl, "DMA RX: setup_rx_descbuffer()"
1324 : : " failed\n");
1325 : 0 : sync_descbuffer_for_device(ring, dmaaddr,
1326 : 0 : ring->rx_buffersize);
1327 : 0 : goto drop;
1328 : : }
1329 : :
1330 : 0 : unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
1331 : 0 : skb_put(skb, len + ring->frameoffset);
1332 : 0 : skb_pull(skb, ring->frameoffset);
1333 : :
1334 : 0 : b43legacy_rx(ring->dev, skb, rxhdr);
1335 : 0 : drop:
1336 : : return;
1337 : : }
1338 : :
1339 : 0 : void b43legacy_dma_rx(struct b43legacy_dmaring *ring)
1340 : : {
1341 : 0 : int slot;
1342 : 0 : int current_slot;
1343 : 0 : int used_slots = 0;
1344 : :
1345 [ # # ]: 0 : B43legacy_WARN_ON(ring->tx);
1346 : 0 : current_slot = op32_get_current_rxslot(ring);
1347 [ # # # # ]: 0 : B43legacy_WARN_ON(!(current_slot >= 0 && current_slot <
1348 : : ring->nr_slots));
1349 : :
1350 : 0 : slot = ring->current_slot;
1351 [ # # # # ]: 0 : for (; slot != current_slot; slot = next_slot(ring, slot)) {
1352 : 0 : dma_rx(ring, &slot);
1353 : 0 : update_max_used_slots(ring, ++used_slots);
1354 : : }
1355 : 0 : op32_set_current_rxslot(ring, slot);
1356 : 0 : ring->current_slot = slot;
1357 : 0 : }
1358 : :
1359 : 0 : static void b43legacy_dma_tx_suspend_ring(struct b43legacy_dmaring *ring)
1360 : : {
1361 [ # # ]: 0 : B43legacy_WARN_ON(!ring->tx);
1362 : 0 : op32_tx_suspend(ring);
1363 : 0 : }
1364 : :
1365 : 0 : static void b43legacy_dma_tx_resume_ring(struct b43legacy_dmaring *ring)
1366 : : {
1367 [ # # ]: 0 : B43legacy_WARN_ON(!ring->tx);
1368 : 0 : op32_tx_resume(ring);
1369 : 0 : }
1370 : :
1371 : 0 : void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev)
1372 : : {
1373 : 0 : b43legacy_power_saving_ctl_bits(dev, -1, 1);
1374 : 0 : b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring0);
1375 : 0 : b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring1);
1376 : 0 : b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring2);
1377 : 0 : b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring3);
1378 : 0 : b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring4);
1379 : 0 : b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring5);
1380 : 0 : }
1381 : :
1382 : 0 : void b43legacy_dma_tx_resume(struct b43legacy_wldev *dev)
1383 : : {
1384 : 0 : b43legacy_dma_tx_resume_ring(dev->dma.tx_ring5);
1385 : 0 : b43legacy_dma_tx_resume_ring(dev->dma.tx_ring4);
1386 : 0 : b43legacy_dma_tx_resume_ring(dev->dma.tx_ring3);
1387 : 0 : b43legacy_dma_tx_resume_ring(dev->dma.tx_ring2);
1388 : 0 : b43legacy_dma_tx_resume_ring(dev->dma.tx_ring1);
1389 : 0 : b43legacy_dma_tx_resume_ring(dev->dma.tx_ring0);
1390 : 0 : b43legacy_power_saving_ctl_bits(dev, -1, -1);
1391 : 0 : }
|