/** * axienet_mcdma_tx_q_init - Setup buffer descriptor rings for individual Axi * MCDMA-Tx * @ndev: Pointer to the net_device structure * @q: Pointer to DMA queue structure * * Return: 0, on success -ENOMEM, on failure * * This function is helper function to axienet_dma_bd_init */ int __maybe_unused axienet_mcdma_tx_q_init(struct net_device *ndev, struct axienet_dma_q *q) { u32 cr, chan_en; int i; struct axienet_local *lp = netdev_priv(ndev); q->tx_bd_ci = 0; q->tx_bd_tail = 0; q->txq_bd_v = dma_zalloc_coherent(ndev->dev.parent, sizeof(*q->txq_bd_v) * TX_BD_NUM, &q->tx_bd_p, GFP_KERNEL); if (!q->txq_bd_v) goto out; if (!q->eth_hasdre) { q->tx_bufs = dma_zalloc_coherent(ndev->dev.parent, XAE_MAX_PKT_LEN * TX_BD_NUM, &q->tx_bufs_dma, GFP_KERNEL); if (!q->tx_bufs) goto out; for (i = 0; i < TX_BD_NUM; i++) q->tx_buf[i] = &q->tx_bufs[i * XAE_MAX_PKT_LEN]; } for (i = 0; i < TX_BD_NUM; i++) { q->txq_bd_v[i].next = q->tx_bd_p + sizeof(*q->txq_bd_v) * ((i + 1) % TX_BD_NUM); } /* Start updating the Tx channel control register */ cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id)); /* Update the interrupt coalesce count */ cr = (((cr & ~XMCDMA_COALESCE_MASK)) | ((lp->coalesce_count_tx) << XMCDMA_COALESCE_SHIFT)); /* Update the delay timer count */ cr = (((cr & ~XMCDMA_DELAY_MASK)) | (XAXIDMA_DFT_TX_WAITBOUND << XMCDMA_DELAY_SHIFT)); /* Enable coalesce, delay timer and error interrupts */ cr |= XMCDMA_IRQ_ALL_MASK; /* Write to the Tx channel control register */ axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id), cr); /* Write to the RS (Run-stop) bit in the Tx channel control register. * Tx channel is now ready to run. But only after we write to the * tail pointer register that the Tx channel will start transmitting. */ axienet_dma_bdout(q, XMCDMA_CHAN_CURDESC_OFFSET(q->chan_id), q->tx_bd_p); cr = axienet_dma_in32(q, XMCDMA_CR_OFFSET); axienet_dma_out32(q, XMCDMA_CR_OFFSET, cr | XMCDMA_CR_RUNSTOP_MASK); cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id)); axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id), cr | XMCDMA_CR_RUNSTOP_MASK); chan_en = axienet_dma_in32(q, XMCDMA_CHEN_OFFSET); chan_en |= (1 << (q->chan_id - 1)); axienet_dma_out32(q, XMCDMA_CHEN_OFFSET, chan_en); return 0; out: for_each_tx_dma_queue(lp, i) { axienet_mcdma_tx_bd_free(ndev, lp->dq[i]); }
/** * axienet_dma_bd_init - Setup buffer descriptor rings for Axi DMA * @ndev: Pointer to the net_device structure * * Return: 0, on success -ENOMEM, on failure * * This function is called to initialize the Rx and Tx DMA descriptor * rings. This initializes the descriptors with required default values * and is called when Axi Ethernet driver reset is called. */ static int axienet_dma_bd_init(struct net_device *ndev) { u32 cr; int i; struct sk_buff *skb; struct axienet_local *lp = netdev_priv(ndev); /* Reset the indexes which are used for accessing the BDs */ lp->tx_bd_ci = 0; lp->tx_bd_tail = 0; lp->rx_bd_ci = 0; /* Allocate the Tx and Rx buffer descriptors. */ lp->tx_bd_v = dma_zalloc_coherent(ndev->dev.parent, sizeof(*lp->tx_bd_v) * TX_BD_NUM, &lp->tx_bd_p, GFP_KERNEL); if (!lp->tx_bd_v) goto out; lp->rx_bd_v = dma_zalloc_coherent(ndev->dev.parent, sizeof(*lp->rx_bd_v) * RX_BD_NUM, &lp->rx_bd_p, GFP_KERNEL); if (!lp->rx_bd_v) goto out; for (i = 0; i < TX_BD_NUM; i++) { lp->tx_bd_v[i].next = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * ((i + 1) % TX_BD_NUM); } for (i = 0; i < RX_BD_NUM; i++) { lp->rx_bd_v[i].next = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * ((i + 1) % RX_BD_NUM); skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size); if (!skb) goto out; lp->rx_bd_v[i].sw_id_offset = (u32) skb; lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent, skb->data, lp->max_frm_size, DMA_FROM_DEVICE); lp->rx_bd_v[i].cntrl = lp->max_frm_size; } /* Start updating the Rx channel control register */ cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); /* Update the interrupt coalesce count */ cr = ((cr & ~XAXIDMA_COALESCE_MASK) | ((lp->coalesce_count_rx) << XAXIDMA_COALESCE_SHIFT)); /* Update the delay timer count */ cr = ((cr & ~XAXIDMA_DELAY_MASK) | (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT)); /* Enable coalesce, delay timer and error interrupts */ cr |= XAXIDMA_IRQ_ALL_MASK; /* Write to the Rx channel control register */ axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr); /* Start updating the Tx channel control register */ cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); /* Update the interrupt coalesce count */ cr = (((cr & ~XAXIDMA_COALESCE_MASK)) | ((lp->coalesce_count_tx) << XAXIDMA_COALESCE_SHIFT)); /* Update the delay timer count */ cr = (((cr & ~XAXIDMA_DELAY_MASK)) | (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT)); /* Enable coalesce, delay timer and error interrupts */ cr |= XAXIDMA_IRQ_ALL_MASK; /* Write to the Tx channel control register */ axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr); /* Populate the tail pointer and bring the Rx Axi DMA engine out of * halted state. This will make the Rx side ready for reception. */ axienet_dma_out32(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p); cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr | XAXIDMA_CR_RUNSTOP_MASK); axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1))); /* Write to the RS (Run-stop) bit in the Tx channel control register. * Tx channel is now ready to run. But only after we write to the * tail pointer register that the Tx channel will start transmitting. */ axienet_dma_out32(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p); cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr | XAXIDMA_CR_RUNSTOP_MASK); return 0; out: axienet_dma_bd_release(ndev); return -ENOMEM; }
static int axienet_dma_bd_init(struct net_device *ndev) { u32 cr; int i; struct sk_buff *skb; struct axienet_local *lp = netdev_priv(ndev); lp->tx_bd_ci = 0; lp->tx_bd_tail = 0; lp->rx_bd_ci = 0; lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent, sizeof(*lp->tx_bd_v) * TX_BD_NUM, &lp->tx_bd_p, GFP_KERNEL); if (!lp->tx_bd_v) { dev_err(&ndev->dev, "unable to allocate DMA Tx buffer " "descriptors"); goto out; } lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent, sizeof(*lp->rx_bd_v) * RX_BD_NUM, &lp->rx_bd_p, GFP_KERNEL); if (!lp->rx_bd_v) { dev_err(&ndev->dev, "unable to allocate DMA Rx buffer " "descriptors"); goto out; } memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM); for (i = 0; i < TX_BD_NUM; i++) { lp->tx_bd_v[i].next = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * ((i + 1) % TX_BD_NUM); } memset(lp->rx_bd_v, 0, sizeof(*lp->rx_bd_v) * RX_BD_NUM); for (i = 0; i < RX_BD_NUM; i++) { lp->rx_bd_v[i].next = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * ((i + 1) % RX_BD_NUM); skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size); if (!skb) { dev_err(&ndev->dev, "alloc_skb error %d\n", i); goto out; } lp->rx_bd_v[i].sw_id_offset = (u32) skb; lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent, skb->data, lp->max_frm_size, DMA_FROM_DEVICE); lp->rx_bd_v[i].cntrl = lp->max_frm_size; } cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); cr = ((cr & ~XAXIDMA_COALESCE_MASK) | ((lp->coalesce_count_rx) << XAXIDMA_COALESCE_SHIFT)); cr = ((cr & ~XAXIDMA_DELAY_MASK) | (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT)); cr |= XAXIDMA_IRQ_ALL_MASK; axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr); cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); cr = (((cr & ~XAXIDMA_COALESCE_MASK)) | ((lp->coalesce_count_tx) << XAXIDMA_COALESCE_SHIFT)); cr = (((cr & ~XAXIDMA_DELAY_MASK)) | (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT)); cr |= XAXIDMA_IRQ_ALL_MASK; axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr); axienet_dma_out32(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p); cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr | XAXIDMA_CR_RUNSTOP_MASK); axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1))); axienet_dma_out32(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p); cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr | XAXIDMA_CR_RUNSTOP_MASK); return 0; out: axienet_dma_bd_release(ndev); return -ENOMEM; }