static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask) { u64 orig_mask = mask; bool fallback = false; int err; /* Try to set the DMA mask. If it fails, try falling back to a * lower mask, as we can always also support a lower one. */ while (1) { err = dma_set_mask_and_coherent(dev->dev->dma_dev, mask); if (!err) break; if (mask == DMA_BIT_MASK(64)) { mask = DMA_BIT_MASK(32); fallback = true; continue; } if (mask == DMA_BIT_MASK(32)) { mask = DMA_BIT_MASK(30); fallback = true; continue; } b43err(dev->wl, "The machine/kernel does not support " "the required %u-bit DMA mask\n", (unsigned int)dma_mask_to_engine_type(orig_mask)); return -EOPNOTSUPP; } if (fallback) { b43info(dev->wl, "DMA mask fallback from %u-bit to %u-bit\n", (unsigned int)dma_mask_to_engine_type(orig_mask), (unsigned int)dma_mask_to_engine_type(mask)); } return 0; }
/* Enable/Disable Direct FIFO Receive Mode (PIO) on a RX engine. * This is called from PIO code, so DMA structures are not available. */ void b43_dma_direct_fifo_rx(struct b43_wldev *dev, unsigned int engine_index, bool enable) { enum b43_dmatype type; u16 mmio_base; type = dma_mask_to_engine_type(supported_dma_mask(dev)); mmio_base = b43_dmacontroller_base(type, engine_index); direct_fifo_rx(dev, type, mmio_base, enable); }
static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask) { u64 orig_mask = mask; bool fallback = false; int err; while (1) { err = dma_set_mask(dev->dev->dma_dev, mask); if (!err) { err = dma_set_coherent_mask(dev->dev->dma_dev, mask); if (!err) break; } if (mask == DMA_BIT_MASK(64)) { mask = DMA_BIT_MASK(32); fallback = true; continue; } if (mask == DMA_BIT_MASK(32)) { mask = DMA_BIT_MASK(30); fallback = true; continue; } b43err(dev->wl, "The machine/kernel does not support " "the required %u-bit DMA mask\n", (unsigned int)dma_mask_to_engine_type(orig_mask)); return -EOPNOTSUPP; } if (fallback) { b43info(dev->wl, "DMA mask fallback from %u-bit to %u-bit\n", (unsigned int)dma_mask_to_engine_type(orig_mask), (unsigned int)dma_mask_to_engine_type(mask)); } return 0; }
int b43_dma_init(struct b43_wldev *dev) { struct b43_dma *dma = &dev->dma; int err; u64 dmamask; enum b43_dmatype type; dmamask = supported_dma_mask(dev); type = dma_mask_to_engine_type(dmamask); err = b43_dma_set_mask(dev, dmamask); if (err) return err; switch (dev->dev->bus_type) { #ifdef CPTCFG_B43_BCMA case B43_BUS_BCMA: dma->translation = bcma_core_dma_translation(dev->dev->bdev); break; #endif #ifdef CPTCFG_B43_SSB case B43_BUS_SSB: dma->translation = ssb_dma_translation(dev->dev->sdev); break; #endif } dma->translation_in_low = b43_dma_translation_in_low_word(dev, type); dma->parity = true; #ifdef CPTCFG_B43_BCMA /* TODO: find out which SSB devices need disabling parity */ if (dev->dev->bus_type == B43_BUS_BCMA) dma->parity = false; #endif err = -ENOMEM; /* setup TX DMA channels. */ dma->tx_ring_AC_BK = b43_setup_dmaring(dev, 0, 1, type); if (!dma->tx_ring_AC_BK) goto out; dma->tx_ring_AC_BE = b43_setup_dmaring(dev, 1, 1, type); if (!dma->tx_ring_AC_BE) goto err_destroy_bk; dma->tx_ring_AC_VI = b43_setup_dmaring(dev, 2, 1, type); if (!dma->tx_ring_AC_VI) goto err_destroy_be; dma->tx_ring_AC_VO = b43_setup_dmaring(dev, 3, 1, type); if (!dma->tx_ring_AC_VO) goto err_destroy_vi; dma->tx_ring_mcast = b43_setup_dmaring(dev, 4, 1, type); if (!dma->tx_ring_mcast) goto err_destroy_vo; /* setup RX DMA channel. */ dma->rx_ring = b43_setup_dmaring(dev, 0, 0, type); if (!dma->rx_ring) goto err_destroy_mcast; /* No support for the TX status DMA ring. */ B43_WARN_ON(dev->dev->core_rev < 5); b43dbg(dev->wl, "%u-bit DMA initialized\n", (unsigned int)type); err = 0; out: return err; err_destroy_mcast: destroy_ring(dma, tx_ring_mcast); err_destroy_vo: destroy_ring(dma, tx_ring_AC_VO); err_destroy_vi: destroy_ring(dma, tx_ring_AC_VI); err_destroy_be: destroy_ring(dma, tx_ring_AC_BE); err_destroy_bk: destroy_ring(dma, tx_ring_AC_BK); return err; }