aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/patches-3.18/077-04-bgmac-simplify-tx-ring-index-handling.patch
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2015-04-12 10:35:21 +0000
committerFelix Fietkau <nbd@openwrt.org>2015-04-12 10:35:21 +0000
commit8904cd1dcca81e0e4cf5e36cea6a180bfe5aaa0e (patch)
tree4a85fe0f0db5582594aef35d1c8b63f285039447 /target/linux/generic/patches-3.18/077-04-bgmac-simplify-tx-ring-index-handling.patch
parent503ccc502d98b32a33a196b5cf35b0e324143d27 (diff)
downloadupstream-8904cd1dcca81e0e4cf5e36cea6a180bfe5aaa0e.tar.gz
upstream-8904cd1dcca81e0e4cf5e36cea6a180bfe5aaa0e.tar.bz2
upstream-8904cd1dcca81e0e4cf5e36cea6a180bfe5aaa0e.zip
kernel: add bgmac fixes for various issues
Signed-off-by: Felix Fietkau <nbd@openwrt.org> SVN-Revision: 45388
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.patch123
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;