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