static int bgmac_dma_alloc(struct bgmac *bgmac) { struct device *dma_dev = bgmac->core->dma_dev; struct bgmac_dma_ring *ring; static const u16 ring_base[] = { BGMAC_DMA_BASE0, BGMAC_DMA_BASE1, BGMAC_DMA_BASE2, BGMAC_DMA_BASE3, }; int size; /* ring size: different for Tx and Rx */ int err; int i; BUILD_BUG_ON(BGMAC_MAX_TX_RINGS > ARRAY_SIZE(ring_base)); BUILD_BUG_ON(BGMAC_MAX_RX_RINGS > ARRAY_SIZE(ring_base)); if (!(bcma_aread32(bgmac->core, BCMA_IOST) & BCMA_IOST_DMA64)) { bgmac_err(bgmac, "Core does not report 64-bit DMA\n"); return -ENOTSUPP; } for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) { ring = &bgmac->tx_ring[i]; ring->mmio_base = ring_base[i]; /* Alloc ring of descriptors */ size = BGMAC_TX_RING_SLOTS * sizeof(struct bgmac_dma_desc); ring->cpu_base = dma_zalloc_coherent(dma_dev, size, &ring->dma_base, GFP_KERNEL); if (!ring->cpu_base) { bgmac_err(bgmac, "Allocation of TX ring 0x%X failed\n", ring->mmio_base); goto err_dma_free; } ring->unaligned = bgmac_dma_unaligned(bgmac, ring, BGMAC_DMA_RING_TX); if (ring->unaligned) ring->index_base = lower_32_bits(ring->dma_base); else ring->index_base = 0; /* No need to alloc TX slots yet */ } for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) { ring = &bgmac->rx_ring[i]; ring->mmio_base = ring_base[i]; /* Alloc ring of descriptors */ size = BGMAC_RX_RING_SLOTS * sizeof(struct bgmac_dma_desc); ring->cpu_base = dma_zalloc_coherent(dma_dev, size, &ring->dma_base, GFP_KERNEL); if (!ring->cpu_base) { bgmac_err(bgmac, "Allocation of RX ring 0x%X failed\n", ring->mmio_base); err = -ENOMEM; goto err_dma_free; } ring->unaligned = bgmac_dma_unaligned(bgmac, ring, BGMAC_DMA_RING_RX); if (ring->unaligned) ring->index_base = lower_32_bits(ring->dma_base); else ring->index_base = 0; } return 0; err_dma_free: bgmac_dma_free(bgmac); return -ENOMEM; }
static int bgmac_dma_alloc(struct bgmac *bgmac) { struct device *dma_dev = bgmac->core->dma_dev; struct bgmac_dma_ring *ring; static const u16 ring_base[] = { BGMAC_DMA_BASE0, BGMAC_DMA_BASE1, BGMAC_DMA_BASE2, BGMAC_DMA_BASE3, }; int size; /* ring size: different for Tx and Rx */ int err; int i; BUILD_BUG_ON(BGMAC_MAX_TX_RINGS > ARRAY_SIZE(ring_base)); BUILD_BUG_ON(BGMAC_MAX_RX_RINGS > ARRAY_SIZE(ring_base)); if (!(bcma_aread32(bgmac->core, BCMA_IOST) & BCMA_IOST_DMA64)) { bgmac_err(bgmac, "Core does not report 64-bit DMA\n"); return -ENOTSUPP; } for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) { ring = &bgmac->tx_ring[i]; ring->num_slots = BGMAC_TX_RING_SLOTS; ring->mmio_base = ring_base[i]; /* Alloc ring of descriptors */ size = ring->num_slots * sizeof(struct bgmac_dma_desc); ring->cpu_base = dma_zalloc_coherent(dma_dev, size, &ring->dma_base, GFP_KERNEL); if (!ring->cpu_base) { bgmac_err(bgmac, "Allocation of TX ring 0x%X failed\n", ring->mmio_base); goto err_dma_free; } if (ring->dma_base & 0xC0000000) bgmac_warn(bgmac, "DMA address using 0xC0000000 bit(s), it may need translation trick\n"); ring->unaligned = bgmac_dma_unaligned(bgmac, ring, BGMAC_DMA_RING_TX); if (ring->unaligned) ring->index_base = lower_32_bits(ring->dma_base); else ring->index_base = 0; /* No need to alloc TX slots yet */ } for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) { int j; ring = &bgmac->rx_ring[i]; ring->num_slots = BGMAC_RX_RING_SLOTS; ring->mmio_base = ring_base[i]; /* Alloc ring of descriptors */ size = ring->num_slots * sizeof(struct bgmac_dma_desc); ring->cpu_base = dma_zalloc_coherent(dma_dev, size, &ring->dma_base, GFP_KERNEL); if (!ring->cpu_base) { bgmac_err(bgmac, "Allocation of RX ring 0x%X failed\n", ring->mmio_base); err = -ENOMEM; goto err_dma_free; } if (ring->dma_base & 0xC0000000) bgmac_warn(bgmac, "DMA address using 0xC0000000 bit(s), it may need translation trick\n"); ring->unaligned = bgmac_dma_unaligned(bgmac, ring, BGMAC_DMA_RING_RX); if (ring->unaligned) ring->index_base = lower_32_bits(ring->dma_base); else ring->index_base = 0; /* Alloc RX slots */ for (j = 0; j < ring->num_slots; j++) { err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]); if (err) { bgmac_err(bgmac, "Can't allocate skb for slot in RX ring\n"); goto err_dma_free; } } } return 0; err_dma_free: bgmac_dma_free(bgmac); return -ENOMEM; }