[RFC PATCH 2/2] net: macb: Tie-off unused RX queues

From: Harini Katakam
Date: Mon Nov 27 2017 - 02:10:42 EST


From: "Edgar E. Iglesias" <edgar.iglesias@xxxxxxxxxx>

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.iglesias@xxxxxxxxxx>
Signed-off-by: Harini Katakam <harinik@xxxxxxxxxx>
Signed-off-by: Michal Simek <michal.simek@xxxxxxxxxx>
---
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