mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-03 22:44:27 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			126 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			126 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From: Felix Fietkau <nbd@nbd.name>
 | 
						|
Date: Sun, 12 Apr 2015 09:58:56 +0200
 | 
						|
Subject: [PATCH] bgmac: simplify tx ring index handling
 | 
						|
 | 
						|
Keep incrementing ring->start and ring->end instead of pointing it to
 | 
						|
the actual ring slot entry. This simplifies the calculation of the
 | 
						|
number of free slots.
 | 
						|
 | 
						|
Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | 
						|
---
 | 
						|
 | 
						|
--- a/drivers/net/ethernet/broadcom/bgmac.c
 | 
						|
+++ b/drivers/net/ethernet/broadcom/bgmac.c
 | 
						|
@@ -142,11 +142,10 @@ static netdev_tx_t bgmac_dma_tx_add(stru
 | 
						|
 {
 | 
						|
 	struct device *dma_dev = bgmac->core->dma_dev;
 | 
						|
 	struct net_device *net_dev = bgmac->net_dev;
 | 
						|
-	struct bgmac_slot_info *slot = &ring->slots[ring->end];
 | 
						|
-	int free_slots;
 | 
						|
+	int index = ring->end % BGMAC_TX_RING_SLOTS;
 | 
						|
+	struct bgmac_slot_info *slot = &ring->slots[index];
 | 
						|
 	int nr_frags;
 | 
						|
 	u32 flags;
 | 
						|
-	int index = ring->end;
 | 
						|
 	int i;
 | 
						|
 
 | 
						|
 	if (skb->len > BGMAC_DESC_CTL1_LEN) {
 | 
						|
@@ -159,12 +158,10 @@ static netdev_tx_t bgmac_dma_tx_add(stru
 | 
						|
 
 | 
						|
 	nr_frags = skb_shinfo(skb)->nr_frags;
 | 
						|
 
 | 
						|
-	if (ring->start <= ring->end)
 | 
						|
-		free_slots = ring->start - ring->end + BGMAC_TX_RING_SLOTS;
 | 
						|
-	else
 | 
						|
-		free_slots = ring->start - ring->end;
 | 
						|
-
 | 
						|
-	if (free_slots <= nr_frags + 1) {
 | 
						|
+	/* ring->end - ring->start will return the number of valid slots,
 | 
						|
+	 * even when ring->end overflows
 | 
						|
+	 */
 | 
						|
+	if (ring->end - ring->start + nr_frags + 1 >= BGMAC_TX_RING_SLOTS) {
 | 
						|
 		bgmac_err(bgmac, "TX ring is full, queue should be stopped!\n");
 | 
						|
 		netif_stop_queue(net_dev);
 | 
						|
 		return NETDEV_TX_BUSY;
 | 
						|
@@ -200,7 +197,7 @@ static netdev_tx_t bgmac_dma_tx_add(stru
 | 
						|
 	}
 | 
						|
 
 | 
						|
 	slot->skb = skb;
 | 
						|
-
 | 
						|
+	ring->end += nr_frags + 1;
 | 
						|
 	netdev_sent_queue(net_dev, skb->len);
 | 
						|
 
 | 
						|
 	wmb();
 | 
						|
@@ -208,13 +205,12 @@ static netdev_tx_t bgmac_dma_tx_add(stru
 | 
						|
 	/* Increase ring->end to point empty slot. We tell hardware the first
 | 
						|
 	 * slot it should *not* read.
 | 
						|
 	 */
 | 
						|
-	ring->end = (index + 1) % BGMAC_TX_RING_SLOTS;
 | 
						|
 	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_INDEX,
 | 
						|
 		    ring->index_base +
 | 
						|
-		    ring->end * sizeof(struct bgmac_dma_desc));
 | 
						|
+		    (ring->end % BGMAC_TX_RING_SLOTS) *
 | 
						|
+		    sizeof(struct bgmac_dma_desc));
 | 
						|
 
 | 
						|
-	free_slots -= nr_frags + 1;
 | 
						|
-	if (free_slots < 8)
 | 
						|
+	if (ring->end - ring->start >= BGMAC_TX_RING_SLOTS - 8)
 | 
						|
 		netif_stop_queue(net_dev);
 | 
						|
 
 | 
						|
 	return NETDEV_TX_OK;
 | 
						|
@@ -256,17 +252,17 @@ static void bgmac_dma_tx_free(struct bgm
 | 
						|
 	empty_slot &= BGMAC_DMA_TX_STATDPTR;
 | 
						|
 	empty_slot /= sizeof(struct bgmac_dma_desc);
 | 
						|
 
 | 
						|
-	while (ring->start != empty_slot) {
 | 
						|
-		struct bgmac_slot_info *slot = &ring->slots[ring->start];
 | 
						|
-		u32 ctl1 = le32_to_cpu(ring->cpu_base[ring->start].ctl1);
 | 
						|
-		int len = ctl1 & BGMAC_DESC_CTL1_LEN;
 | 
						|
+	while (ring->start != ring->end) {
 | 
						|
+		int slot_idx = ring->start % BGMAC_TX_RING_SLOTS;
 | 
						|
+		struct bgmac_slot_info *slot = &ring->slots[slot_idx];
 | 
						|
+		u32 ctl1;
 | 
						|
+		int len;
 | 
						|
 
 | 
						|
-		if (!slot->dma_addr) {
 | 
						|
-			bgmac_err(bgmac, "Hardware reported transmission for empty TX ring slot %d! End of ring: %d\n",
 | 
						|
-				  ring->start, ring->end);
 | 
						|
-			goto next;
 | 
						|
-		}
 | 
						|
+		if (slot_idx == empty_slot)
 | 
						|
+			break;
 | 
						|
 
 | 
						|
+		ctl1 = le32_to_cpu(ring->cpu_base[slot_idx].ctl1);
 | 
						|
+		len = ctl1 & BGMAC_DESC_CTL1_LEN;
 | 
						|
 		if (ctl1 & BGMAC_DESC_CTL0_SOF)
 | 
						|
 			/* Unmap no longer used buffer */
 | 
						|
 			dma_unmap_single(dma_dev, slot->dma_addr, len,
 | 
						|
@@ -284,10 +280,8 @@ static void bgmac_dma_tx_free(struct bgm
 | 
						|
 			slot->skb = NULL;
 | 
						|
 		}
 | 
						|
 
 | 
						|
-next:
 | 
						|
 		slot->dma_addr = 0;
 | 
						|
-		if (++ring->start >= BGMAC_TX_RING_SLOTS)
 | 
						|
-			ring->start = 0;
 | 
						|
+		ring->start++;
 | 
						|
 		freed = true;
 | 
						|
 	}
 | 
						|
 
 | 
						|
--- a/drivers/net/ethernet/broadcom/bgmac.h
 | 
						|
+++ b/drivers/net/ethernet/broadcom/bgmac.h
 | 
						|
@@ -414,10 +414,10 @@ enum bgmac_dma_ring_type {
 | 
						|
  * empty.
 | 
						|
  */
 | 
						|
 struct bgmac_dma_ring {
 | 
						|
-	u16 num_slots;
 | 
						|
-	u16 start;
 | 
						|
-	u16 end;
 | 
						|
+	u32 start;
 | 
						|
+	u32 end;
 | 
						|
 
 | 
						|
+	u16 num_slots;
 | 
						|
 	u16 mmio_base;
 | 
						|
 	struct bgmac_dma_desc *cpu_base;
 | 
						|
 	dma_addr_t dma_base;
 |