From: "Edgar E. Iglesias" <edgar.igles...@xilinx.com>

Currently, we only use the first receive queue and leave the
remaining DMA descriptor pointers pointing at 0.

Disable unused queues by connecting them to a looped descriptor
chain without free slots.

Signed-off-by: Edgar E. Iglesias <edgar.igles...@xilinx.com>
Signed-off-by: Harini Katakam <hari...@xilinx.com>
Signed-off-by: Michal Simek <michal.si...@xilinx.com>
---
 drivers/net/ethernet/cadence/macb.h      |  2 ++
 drivers/net/ethernet/cadence/macb_main.c | 42 ++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/drivers/net/ethernet/cadence/macb.h 
b/drivers/net/ethernet/cadence/macb.h
index acb6578..974c801 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -994,6 +994,7 @@ struct macb {
        unsigned int            rx_tail;
        unsigned int            rx_prepared_head;
        struct macb_dma_desc    *rx_ring;
+       struct macb_dma_desc    *rx_ring_tieoff;
        struct sk_buff          **rx_skbuff;
        void                    *rx_buffers;
        size_t                  rx_buffer_size;
@@ -1019,6 +1020,7 @@ struct macb {
        }                       hw_stats;
 
        dma_addr_t              rx_ring_dma;
+       dma_addr_t              rx_ring_tieoff_dma;
        dma_addr_t              rx_buffers_dma;
 
        struct macb_or_gem_ops  macbgem_ops;
diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index 623ae9c..b14a04d 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -1755,6 +1755,12 @@ static void macb_free_consistent(struct macb *bp)
                bp->rx_ring = NULL;
        }
 
+       if (bp->rx_ring_tieoff) {
+               dma_free_coherent(&bp->pdev->dev, sizeof(bp->rx_ring_tieoff[0]),
+                                 bp->rx_ring_tieoff, bp->rx_ring_tieoff_dma);
+               bp->rx_ring_tieoff = NULL;
+       }
+
        for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
                kfree(queue->tx_skb);
                queue->tx_skb = NULL;
@@ -1826,6 +1832,19 @@ static int macb_alloc_consistent(struct macb *bp)
                                         &bp->rx_ring_dma, GFP_KERNEL);
        if (!bp->rx_ring)
                goto out_err;
+
+       /* If we have more than one queue, allocate a tie off descriptor
+        * that will be used to disable unused RX queues.
+        */
+       if (bp->num_queues > 1) {
+               bp->rx_ring_tieoff = dma_alloc_coherent(&bp->pdev->dev,
+                                               sizeof(bp->rx_ring_tieoff[0]),
+                                               &bp->rx_ring_tieoff_dma,
+                                               GFP_KERNEL);
+               if (!bp->rx_ring_tieoff)
+                       goto out_err;
+       }
+
        netdev_dbg(bp->dev,
                   "Allocated RX ring of %d bytes at %08lx (mapped %p)\n",
                   size, (unsigned long)bp->rx_ring_dma, bp->rx_ring);
@@ -1840,6 +1859,19 @@ static int macb_alloc_consistent(struct macb *bp)
        return -ENOMEM;
 }
 
+static void macb_init_tieoff(struct macb *bp)
+{
+       struct macb_dma_desc *d = bp->rx_ring_tieoff;
+
+       if (bp->num_queues > 1) {
+               /* Setup a wrapping descriptor with no free slots
+                * (WRAP and USED) to tie off/disable unused RX queues.
+                */
+               d->addr = MACB_BIT(RX_WRAP) | MACB_BIT(RX_USED);
+               d->ctrl = 0;
+       }
+}
+
 static void gem_init_rings(struct macb *bp)
 {
        struct macb_queue *queue;
@@ -1862,6 +1894,7 @@ static void gem_init_rings(struct macb *bp)
        bp->rx_prepared_head = 0;
 
        gem_rx_refill(bp);
+       macb_init_tieoff(bp);
 }
 
 static void macb_init_rings(struct macb *bp)
@@ -1879,6 +1912,7 @@ static void macb_init_rings(struct macb *bp)
        bp->queues[0].tx_head = 0;
        bp->queues[0].tx_tail = 0;
        desc->ctrl |= MACB_BIT(TX_WRAP);
+       macb_init_tieoff(bp);
 }
 
 static void macb_reset_hw(struct macb *bp)
@@ -2063,6 +2097,14 @@ static void macb_init_hw(struct macb *bp)
                        queue_writel(queue, TBQPH, 
upper_32_bits(queue->tx_ring_dma));
 #endif
 
+               /* We only use the first queue at the moment. Remaining
+                * queues must be tied-off before we enable the receiver.
+                *
+                * See the documentation for receive_q1_ptr for more info.
+                */
+               if (q)
+                       queue_writel(queue, RBQP, bp->rx_ring_tieoff_dma);
+
                /* Enable interrupts */
                queue_writel(queue, IER,
                             MACB_RX_INT_FLAGS |
-- 
2.7.4

Reply via email to