aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2009-11-18 14:53:05 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-11-18 17:09:28 -0500
commit9bd568a50c446433038dec2a5186c5c57c3dbd23 (patch)
treeb753571eb581f0646343c8d78688aba1d7a32c7b /drivers/net/wireless
parent76aa5e704c80fb7ca8bd3d05593d9a28298c92cd (diff)
b43: Enforce DMA descriptor memory constraints
Enforce all device constraints on the descriptor memory region. There are several constraints on the descriptor memory, as documented in the specification. The current code does not enforce them and/or incorrectly enforces them. Those constraints are: - The address limitations on 30/32bit engines, that also apply to the skbs. - The 4k alignment requirement on 30/32bit engines. - The 8k alignment requirement on 64bit engines. Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/b43/dma.c197
-rw-r--r--drivers/net/wireless/b43/dma.h7
2 files changed, 158 insertions, 46 deletions
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index b5cd7f57055b..18b97c02b8af 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -383,44 +383,160 @@ static inline
383 } 383 }
384} 384}
385 385
386/* Check if a DMA region fits the device constraints.
387 * Returns true, if the region is OK for usage with this device. */
388static inline bool b43_dma_address_ok(struct b43_dmaring *ring,
389 dma_addr_t addr, size_t size)
390{
391 switch (ring->type) {
392 case B43_DMA_30BIT:
393 if ((u64)addr + size > (1ULL << 30))
394 return 0;
395 break;
396 case B43_DMA_32BIT:
397 if ((u64)addr + size > (1ULL << 32))
398 return 0;
399 break;
400 case B43_DMA_64BIT:
401 /* Currently we can't have addresses beyond
402 * 64bit in the kernel. */
403 break;
404 }
405 return 1;
406}
407
408#define is_4k_aligned(addr) (((u64)(addr) & 0x0FFFull) == 0)
409#define is_8k_aligned(addr) (((u64)(addr) & 0x1FFFull) == 0)
410
411static void b43_unmap_and_free_ringmem(struct b43_dmaring *ring, void *base,
412 dma_addr_t dmaaddr, size_t size)
413{
414 ssb_dma_unmap_single(ring->dev->dev, dmaaddr, size, DMA_TO_DEVICE);
415 free_pages((unsigned long)base, get_order(size));
416}
417
418static void * __b43_get_and_map_ringmem(struct b43_dmaring *ring,
419 dma_addr_t *dmaaddr, size_t size,
420 gfp_t gfp_flags)
421{
422 void *base;
423
424 base = (void *)__get_free_pages(gfp_flags, get_order(size));
425 if (!base)
426 return NULL;
427 memset(base, 0, size);
428 *dmaaddr = ssb_dma_map_single(ring->dev->dev, base, size,
429 DMA_TO_DEVICE);
430 if (ssb_dma_mapping_error(ring->dev->dev, *dmaaddr)) {
431 free_pages((unsigned long)base, get_order(size));
432 return NULL;
433 }
434
435 return base;
436}
437
438static void * b43_get_and_map_ringmem(struct b43_dmaring *ring,
439 dma_addr_t *dmaaddr, size_t size)
440{
441 void *base;
442
443 base = __b43_get_and_map_ringmem(ring, dmaaddr, size,
444 GFP_KERNEL);
445 if (!base) {
446 b43err(ring->dev->wl, "Failed to allocate or map pages "
447 "for DMA ringmemory\n");
448 return NULL;
449 }
450 if (!b43_dma_address_ok(ring, *dmaaddr, size)) {
451 /* The memory does not fit our device constraints.
452 * Retry with GFP_DMA set to get lower memory. */
453 b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size);
454 base = __b43_get_and_map_ringmem(ring, dmaaddr, size,
455 GFP_KERNEL | GFP_DMA);
456 if (!base) {
457 b43err(ring->dev->wl, "Failed to allocate or map pages "
458 "in the GFP_DMA region for DMA ringmemory\n");
459 return NULL;
460 }
461 if (!b43_dma_address_ok(ring, *dmaaddr, size)) {
462 b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size);
463 b43err(ring->dev->wl, "Failed to allocate DMA "
464 "ringmemory that fits device constraints\n");
465 return NULL;
466 }
467 }
468 /* We expect the memory to be 4k aligned, at least. */
469 if (B43_WARN_ON(!is_4k_aligned(*dmaaddr))) {
470 b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size);
471 return NULL;
472 }
473
474 return base;
475}
476
386static int alloc_ringmemory(struct b43_dmaring *ring) 477static int alloc_ringmemory(struct b43_dmaring *ring)
387{ 478{
388 gfp_t flags = GFP_KERNEL; 479 unsigned int required;
389 480 void *base;
390 /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K 481 dma_addr_t dmaaddr;
391 * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing 482
392 * has shown that 4K is sufficient for the latter as long as the buffer 483 /* There are several requirements to the descriptor ring memory:
393 * does not cross an 8K boundary. 484 * - The memory region needs to fit the address constraints for the
394 * 485 * device (same as for frame buffers).
395 * For unknown reasons - possibly a hardware error - the BCM4311 rev 486 * - For 30/32bit DMA devices, the descriptor ring must be 4k aligned.
396 * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, 487 * - For 64bit DMA devices, the descriptor ring must be 8k aligned.
397 * which accounts for the GFP_DMA flag below.
398 *
399 * The flags here must match the flags in free_ringmemory below!
400 */ 488 */
489
401 if (ring->type == B43_DMA_64BIT) 490 if (ring->type == B43_DMA_64BIT)
402 flags |= GFP_DMA; 491 required = ring->nr_slots * sizeof(struct b43_dmadesc64);
403 ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, 492 else
404 B43_DMA_RINGMEMSIZE, 493 required = ring->nr_slots * sizeof(struct b43_dmadesc32);
405 &(ring->dmabase), flags); 494 if (B43_WARN_ON(required > 0x1000))
406 if (!ring->descbase) { 495 return -ENOMEM;
407 b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); 496
497 ring->alloc_descsize = 0x1000;
498 base = b43_get_and_map_ringmem(ring, &dmaaddr, ring->alloc_descsize);
499 if (!base)
500 return -ENOMEM;
501 ring->alloc_descbase = base;
502 ring->alloc_dmabase = dmaaddr;
503
504 if ((ring->type != B43_DMA_64BIT) || is_8k_aligned(dmaaddr)) {
505 /* We're on <=32bit DMA, or we already got 8k aligned memory.
506 * That's all we need, so we're fine. */
507 ring->descbase = base;
508 ring->dmabase = dmaaddr;
509 return 0;
510 }
511 b43_unmap_and_free_ringmem(ring, base, dmaaddr, ring->alloc_descsize);
512
513 /* Ok, we failed at the 8k alignment requirement.
514 * Try to force-align the memory region now. */
515 ring->alloc_descsize = 0x2000;
516 base = b43_get_and_map_ringmem(ring, &dmaaddr, ring->alloc_descsize);
517 if (!base)
408 return -ENOMEM; 518 return -ENOMEM;
519 ring->alloc_descbase = base;
520 ring->alloc_dmabase = dmaaddr;
521
522 if (is_8k_aligned(dmaaddr)) {
523 /* We're already 8k aligned. That Ok, too. */
524 ring->descbase = base;
525 ring->dmabase = dmaaddr;
526 return 0;
409 } 527 }
410 memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE); 528 /* Force-align it to 8k */
529 ring->descbase = (void *)((u8 *)base + 0x1000);
530 ring->dmabase = dmaaddr + 0x1000;
531 B43_WARN_ON(!is_8k_aligned(ring->dmabase));
411 532
412 return 0; 533 return 0;
413} 534}
414 535
415static void free_ringmemory(struct b43_dmaring *ring) 536static void free_ringmemory(struct b43_dmaring *ring)
416{ 537{
417 gfp_t flags = GFP_KERNEL; 538 b43_unmap_and_free_ringmem(ring, ring->alloc_descbase,
418 539 ring->alloc_dmabase, ring->alloc_descsize);
419 if (ring->type == B43_DMA_64BIT)
420 flags |= GFP_DMA;
421
422 ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE,
423 ring->descbase, ring->dmabase, flags);
424} 540}
425 541
426/* Reset the RX DMA channel */ 542/* Reset the RX DMA channel */
@@ -530,29 +646,14 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
530 if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) 646 if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr)))
531 return 1; 647 return 1;
532 648
533 switch (ring->type) { 649 if (!b43_dma_address_ok(ring, addr, buffersize)) {
534 case B43_DMA_30BIT: 650 /* We can't support this address. Unmap it again. */
535 if ((u64)addr + buffersize > (1ULL << 30)) 651 unmap_descbuffer(ring, addr, buffersize, dma_to_device);
536 goto address_error; 652 return 1;
537 break;
538 case B43_DMA_32BIT:
539 if ((u64)addr + buffersize > (1ULL << 32))
540 goto address_error;
541 break;
542 case B43_DMA_64BIT:
543 /* Currently we can't have addresses beyond
544 * 64bit in the kernel. */
545 break;
546 } 653 }
547 654
548 /* The address is OK. */ 655 /* The address is OK. */
549 return 0; 656 return 0;
550
551address_error:
552 /* We can't support this address. Unmap it again. */
553 unmap_descbuffer(ring, addr, buffersize, dma_to_device);
554
555 return 1;
556} 657}
557 658
558static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb) 659static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb)
@@ -614,6 +715,9 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
614 meta->dmaaddr = dmaaddr; 715 meta->dmaaddr = dmaaddr;
615 ring->ops->fill_descriptor(ring, desc, dmaaddr, 716 ring->ops->fill_descriptor(ring, desc, dmaaddr,
616 ring->rx_buffersize, 0, 0, 0); 717 ring->rx_buffersize, 0, 0, 0);
718 ssb_dma_sync_single_for_device(ring->dev->dev,
719 ring->alloc_dmabase,
720 ring->alloc_descsize, DMA_TO_DEVICE);
617 721
618 return 0; 722 return 0;
619} 723}
@@ -1246,6 +1350,9 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
1246 } 1350 }
1247 /* Now transfer the whole frame. */ 1351 /* Now transfer the whole frame. */
1248 wmb(); 1352 wmb();
1353 ssb_dma_sync_single_for_device(ring->dev->dev,
1354 ring->alloc_dmabase,
1355 ring->alloc_descsize, DMA_TO_DEVICE);
1249 ops->poke_tx(ring, next_slot(ring, slot)); 1356 ops->poke_tx(ring, next_slot(ring, slot));
1250 return 0; 1357 return 0;
1251 1358
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h
index f0b0838fb5ba..356a0ff8f044 100644
--- a/drivers/net/wireless/b43/dma.h
+++ b/drivers/net/wireless/b43/dma.h
@@ -157,7 +157,6 @@ struct b43_dmadesc_generic {
157} __attribute__ ((__packed__)); 157} __attribute__ ((__packed__));
158 158
159/* Misc DMA constants */ 159/* Misc DMA constants */
160#define B43_DMA_RINGMEMSIZE PAGE_SIZE
161#define B43_DMA0_RX_FRAMEOFFSET 30 160#define B43_DMA0_RX_FRAMEOFFSET 30
162 161
163/* DMA engine tuning knobs */ 162/* DMA engine tuning knobs */
@@ -243,6 +242,12 @@ struct b43_dmaring {
243 /* The QOS priority assigned to this ring. Only used for TX rings. 242 /* The QOS priority assigned to this ring. Only used for TX rings.
244 * This is the mac80211 "queue" value. */ 243 * This is the mac80211 "queue" value. */
245 u8 queue_prio; 244 u8 queue_prio;
245 /* Pointers and size of the originally allocated and mapped memory
246 * region for the descriptor ring. */
247 void *alloc_descbase;
248 dma_addr_t alloc_dmabase;
249 unsigned int alloc_descsize;
250 /* Pointer to our wireless device. */
246 struct b43_wldev *dev; 251 struct b43_wldev *dev;
247#ifdef CONFIG_B43_DEBUG 252#ifdef CONFIG_B43_DEBUG
248 /* Maximum number of used slots. */ 253 /* Maximum number of used slots. */