diff options
Diffstat (limited to 'target/linux/generic/patches-3.18/077-04-bgmac-simplify-tx-ring-index-handling.patch')
-rw-r--r-- | target/linux/generic/patches-3.18/077-04-bgmac-simplify-tx-ring-index-handling.patch | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/target/linux/generic/patches-3.18/077-04-bgmac-simplify-tx-ring-index-handling.patch b/target/linux/generic/patches-3.18/077-04-bgmac-simplify-tx-ring-index-handling.patch new file mode 100644 index 0000000000..cf62a50a2f --- /dev/null +++ b/target/linux/generic/patches-3.18/077-04-bgmac-simplify-tx-ring-index-handling.patch @@ -0,0 +1,123 @@ +From: Felix Fietkau <nbd@openwrt.org> +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@openwrt.org> +--- + +--- 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) { +@@ -158,13 +157,7 @@ static netdev_tx_t bgmac_dma_tx_add(stru + skb_checksum_help(skb); + + 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) { ++ 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 +193,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 +201,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 +248,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 +276,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; |