From: Felix Fietkau Date: Sun, 12 Apr 2015 22:10:40 +0000 (+0000) Subject: kernel: bgmac: add more DMA related fixes X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=afafbc0d7454cb3271477698782cdf3197d06295;p=openwrt%2Fstaging%2Fyousong.git kernel: bgmac: add more DMA related fixes Signed-off-by: Felix Fietkau SVN-Revision: 45407 --- diff --git a/target/linux/generic/patches-3.18/077-07-bgmac-fix-DMA-rx-corruption.patch b/target/linux/generic/patches-3.18/077-07-bgmac-fix-DMA-rx-corruption.patch deleted file mode 100644 index 5cf34e5cf5..0000000000 --- a/target/linux/generic/patches-3.18/077-07-bgmac-fix-DMA-rx-corruption.patch +++ /dev/null @@ -1,84 +0,0 @@ -From: Felix Fietkau -Date: Sun, 12 Apr 2015 11:59:47 +0200 -Subject: [PATCH] bgmac: fix DMA rx corruption - -The driver needs to inform the hardware about the first invalid (not yet -filled) rx slot, by writing its DMA descriptor pointer offset to the -BGMAC_DMA_RX_INDEX register. - -This register was set to a value exceeding the rx ring size, effectively -allowing the hardware constant access to the full ring, regardless of -which slots are initialized. - -Fix this by updating the register in bgmac_dma_rx_setup_desc. - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/broadcom/bgmac.c -+++ b/drivers/net/ethernet/broadcom/bgmac.c -@@ -362,6 +362,16 @@ static int bgmac_dma_rx_skb_for_slot(str - return 0; - } - -+static void bgmac_dma_rx_update_index(struct bgmac *bgmac, -+ struct bgmac_dma_ring *ring) -+{ -+ wmb(); -+ -+ bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX, -+ ring->index_base + -+ ring->end * sizeof(struct bgmac_dma_desc)); -+} -+ - static void bgmac_dma_rx_setup_desc(struct bgmac *bgmac, - struct bgmac_dma_ring *ring, int desc_idx) - { -@@ -380,6 +390,8 @@ static void bgmac_dma_rx_setup_desc(stru - dma_desc->addr_high = cpu_to_le32(upper_32_bits(ring->slots[desc_idx].dma_addr)); - dma_desc->ctl0 = cpu_to_le32(ctl0); - dma_desc->ctl1 = cpu_to_le32(ctl1); -+ -+ ring->end = (desc_idx + 1) % BGMAC_RX_RING_SLOTS; - } - - static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring, -@@ -394,9 +406,7 @@ static int bgmac_dma_rx_read(struct bgma - end_slot &= BGMAC_DMA_RX_STATDPTR; - end_slot /= sizeof(struct bgmac_dma_desc); - -- ring->end = end_slot; -- -- while (ring->start != ring->end) { -+ while (ring->start != end_slot) { - struct device *dma_dev = bgmac->core->dma_dev; - struct bgmac_slot_info *slot = &ring->slots[ring->start]; - struct bgmac_rx_header *rx = slot->buf + BGMAC_RX_BUF_OFFSET; -@@ -468,6 +478,8 @@ static int bgmac_dma_rx_read(struct bgma - break; - } - -+ bgmac_dma_rx_update_index(bgmac, ring); -+ - return handled; - } - -@@ -690,15 +702,12 @@ static void bgmac_dma_init(struct bgmac - if (ring->unaligned) - bgmac_dma_rx_enable(bgmac, ring); - -+ ring->start = 0; -+ ring->end = 0; - for (j = 0; j < ring->num_slots; j++) - bgmac_dma_rx_setup_desc(bgmac, ring, j); - -- bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX, -- ring->index_base + -- ring->num_slots * sizeof(struct bgmac_dma_desc)); -- -- ring->start = 0; -- ring->end = 0; -+ bgmac_dma_rx_update_index(bgmac, ring); - } - } - diff --git a/target/linux/generic/patches-3.18/077-07-bgmac-simplify-rx-DMA-error-handling.patch b/target/linux/generic/patches-3.18/077-07-bgmac-simplify-rx-DMA-error-handling.patch new file mode 100644 index 0000000000..f26e42c20d --- /dev/null +++ b/target/linux/generic/patches-3.18/077-07-bgmac-simplify-rx-DMA-error-handling.patch @@ -0,0 +1,68 @@ +From: Felix Fietkau +Date: Sun, 12 Apr 2015 22:23:07 +0200 +Subject: [PATCH] bgmac: simplify rx DMA error handling + +Unmap the DMA buffer before checking it. If it is poisoned, map it again +and pass it back to the hardware. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/broadcom/bgmac.c ++++ b/drivers/net/ethernet/broadcom/bgmac.c +@@ -405,25 +405,20 @@ static int bgmac_dma_rx_read(struct bgma + u16 len, flags; + + /* Unmap buffer to make it accessible to the CPU */ +- dma_sync_single_for_cpu(dma_dev, slot->dma_addr, +- BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE); ++ dma_unmap_single(dma_dev, slot->dma_addr, ++ BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE); + + /* Get info from the header */ + len = le16_to_cpu(rx->len); + flags = le16_to_cpu(rx->flags); + + do { +- dma_addr_t old_dma_addr = slot->dma_addr; + int err; + + /* Check for poison and drop or pass the packet */ + if (len == 0xdead && flags == 0xbeef) { + bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n", + ring->start); +- dma_sync_single_for_device(dma_dev, +- slot->dma_addr, +- BGMAC_RX_BUF_SIZE, +- DMA_FROM_DEVICE); + break; + } + +@@ -436,18 +431,8 @@ static int bgmac_dma_rx_read(struct bgma + /* Poison the old skb */ + rx->len = cpu_to_le16(0xdead); + rx->flags = cpu_to_le16(0xbeef); +- +- dma_sync_single_for_device(dma_dev, +- slot->dma_addr, +- BGMAC_RX_BUF_SIZE, +- DMA_FROM_DEVICE); + break; + } +- bgmac_dma_rx_setup_desc(bgmac, ring, ring->start); +- +- /* Unmap old skb, we'll pass it to the netfif */ +- dma_unmap_single(dma_dev, old_dma_addr, +- BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE); + + skb = build_skb(buf, BGMAC_RX_ALLOC_SIZE); + skb_put(skb, BGMAC_RX_FRAME_OFFSET + +@@ -461,6 +446,8 @@ static int bgmac_dma_rx_read(struct bgma + handled++; + } while (0); + ++ bgmac_dma_rx_setup_desc(bgmac, ring, ring->start); ++ + if (++ring->start >= BGMAC_RX_RING_SLOTS) + ring->start = 0; + diff --git a/target/linux/generic/patches-3.18/077-08-bgmac-add-check-for-oversized-packets.patch b/target/linux/generic/patches-3.18/077-08-bgmac-add-check-for-oversized-packets.patch new file mode 100644 index 0000000000..fa45a43686 --- /dev/null +++ b/target/linux/generic/patches-3.18/077-08-bgmac-add-check-for-oversized-packets.patch @@ -0,0 +1,28 @@ +From: Felix Fietkau +Date: Sun, 12 Apr 2015 22:28:20 +0200 +Subject: [PATCH] bgmac: add check for oversized packets + +In very rare cases, the MAC can catch an internal buffer that is bigger +than it's supposed to be. Instead of crashing the kernel, simply pass +the buffer back to the hardware + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/broadcom/bgmac.c ++++ b/drivers/net/ethernet/broadcom/bgmac.c +@@ -422,6 +422,14 @@ static int bgmac_dma_rx_read(struct bgma + break; + } + ++ if (len > BGMAC_RX_ALLOC_SIZE) { ++ bgmac_err(bgmac, "Found oversized packet at slot %d, DMA issue!\n", ++ ring->start); ++ rx->len = cpu_to_le16(0xdead); ++ rx->flags = cpu_to_le16(0xbeef); ++ break; ++ } ++ + /* Omit CRC. */ + len -= ETH_FCS_LEN; + diff --git a/target/linux/generic/patches-3.18/077-09-bgmac-increase-rx-ring-size-from-511-to-512.patch b/target/linux/generic/patches-3.18/077-09-bgmac-increase-rx-ring-size-from-511-to-512.patch new file mode 100644 index 0000000000..4888cc32af --- /dev/null +++ b/target/linux/generic/patches-3.18/077-09-bgmac-increase-rx-ring-size-from-511-to-512.patch @@ -0,0 +1,23 @@ +From: Felix Fietkau +Date: Sun, 12 Apr 2015 22:36:16 +0200 +Subject: [PATCH] bgmac: increase rx ring size from 511 to 512 + +Limiting it to 511 looks like a failed attempt at leaving one descriptor +empty to allow the hardware to stop processing a buffer that has not +been prepared yet. However, this doesn't work because this affects the +total ring size as well + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/broadcom/bgmac.h ++++ b/drivers/net/ethernet/broadcom/bgmac.h +@@ -356,7 +356,7 @@ + #define BGMAC_MAX_RX_RINGS 1 + + #define BGMAC_TX_RING_SLOTS 128 +-#define BGMAC_RX_RING_SLOTS 512 - 1 /* Why -1? Well, Broadcom does that... */ ++#define BGMAC_RX_RING_SLOTS 512 + + #define BGMAC_RX_HEADER_LEN 28 /* Last 24 bytes are unused. Well... */ + #define BGMAC_RX_FRAME_OFFSET 30 /* There are 2 unused bytes between header and real data */ diff --git a/target/linux/generic/patches-3.18/077-10-bgmac-simplify-dma-init-cleanup.patch b/target/linux/generic/patches-3.18/077-10-bgmac-simplify-dma-init-cleanup.patch new file mode 100644 index 0000000000..be68fa7269 --- /dev/null +++ b/target/linux/generic/patches-3.18/077-10-bgmac-simplify-dma-init-cleanup.patch @@ -0,0 +1,164 @@ +From: Felix Fietkau +Date: Sun, 12 Apr 2015 23:19:32 +0200 +Subject: [PATCH] bgmac: simplify dma init/cleanup + +Instead of allocating buffers at device init time and initializing +descriptors at device open, do both at the same time (during open). +Free all buffers when closing the device. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/broadcom/bgmac.c ++++ b/drivers/net/ethernet/broadcom/bgmac.c +@@ -549,18 +549,26 @@ static void bgmac_dma_ring_desc_free(str + ring->dma_base); + } + +-static void bgmac_dma_free(struct bgmac *bgmac) ++static void bgmac_dma_cleanup(struct bgmac *bgmac) + { + int i; + +- for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) { ++ for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) + bgmac_dma_tx_ring_free(bgmac, &bgmac->tx_ring[i]); +- bgmac_dma_ring_desc_free(bgmac, &bgmac->tx_ring[i]); +- } +- for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) { ++ ++ for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) + bgmac_dma_rx_ring_free(bgmac, &bgmac->rx_ring[i]); ++} ++ ++static void bgmac_dma_free(struct bgmac *bgmac) ++{ ++ int i; ++ ++ for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) ++ bgmac_dma_ring_desc_free(bgmac, &bgmac->tx_ring[i]); ++ ++ for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) + bgmac_dma_ring_desc_free(bgmac, &bgmac->rx_ring[i]); +- } + } + + static int bgmac_dma_alloc(struct bgmac *bgmac) +@@ -608,8 +616,6 @@ static int bgmac_dma_alloc(struct bgmac + } + + for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) { +- int j; +- + ring = &bgmac->rx_ring[i]; + ring->num_slots = BGMAC_RX_RING_SLOTS; + ring->mmio_base = ring_base[i]; +@@ -632,15 +638,6 @@ static int bgmac_dma_alloc(struct bgmac + ring->index_base = lower_32_bits(ring->dma_base); + else + ring->index_base = 0; +- +- /* Alloc RX slots */ +- for (j = 0; j < ring->num_slots; j++) { +- err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]); +- if (err) { +- bgmac_err(bgmac, "Can't allocate skb for slot in RX ring\n"); +- goto err_dma_free; +- } +- } + } + + return 0; +@@ -650,10 +647,10 @@ err_dma_free: + return -ENOMEM; + } + +-static void bgmac_dma_init(struct bgmac *bgmac) ++static int bgmac_dma_init(struct bgmac *bgmac) + { + struct bgmac_dma_ring *ring; +- int i; ++ int i, err; + + for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) { + ring = &bgmac->tx_ring[i]; +@@ -685,8 +682,13 @@ static void bgmac_dma_init(struct bgmac + if (ring->unaligned) + bgmac_dma_rx_enable(bgmac, ring); + +- for (j = 0; j < ring->num_slots; j++) ++ for (j = 0; j < ring->num_slots; j++) { ++ err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]); ++ if (err) ++ return err; ++ + bgmac_dma_rx_setup_desc(bgmac, ring, j); ++ } + + bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX, + ring->index_base + +@@ -695,6 +697,8 @@ static void bgmac_dma_init(struct bgmac + ring->start = 0; + ring->end = 0; + } ++ ++ return 0; + } + + /************************************************** +@@ -1170,11 +1174,8 @@ static void bgmac_enable(struct bgmac *b + } + + /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipinit */ +-static void bgmac_chip_init(struct bgmac *bgmac, bool full_init) ++static void bgmac_chip_init(struct bgmac *bgmac) + { +- struct bgmac_dma_ring *ring; +- int i; +- + /* 1 interrupt per received frame */ + bgmac_write(bgmac, BGMAC_INT_RECV_LAZY, 1 << BGMAC_IRL_FC_SHIFT); + +@@ -1192,16 +1193,7 @@ static void bgmac_chip_init(struct bgmac + + bgmac_write(bgmac, BGMAC_RXMAX_LENGTH, 32 + ETHER_MAX_LEN); + +- if (full_init) { +- bgmac_dma_init(bgmac); +- if (1) /* FIXME: is there any case we don't want IRQs? */ +- bgmac_chip_intrs_on(bgmac); +- } else { +- for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) { +- ring = &bgmac->rx_ring[i]; +- bgmac_dma_rx_enable(bgmac, ring); +- } +- } ++ bgmac_chip_intrs_on(bgmac); + + bgmac_enable(bgmac); + } +@@ -1261,8 +1253,15 @@ static int bgmac_open(struct net_device + int err = 0; + + bgmac_chip_reset(bgmac); ++ ++ err = bgmac_dma_init(bgmac); ++ if (err) { ++ bgmac_dma_cleanup(bgmac); ++ return err; ++ } ++ + /* Specs say about reclaiming rings here, but we do that in DMA init */ +- bgmac_chip_init(bgmac, true); ++ bgmac_chip_init(bgmac); + + err = request_irq(bgmac->core->irq, bgmac_interrupt, IRQF_SHARED, + KBUILD_MODNAME, net_dev); +@@ -1293,6 +1292,7 @@ static int bgmac_stop(struct net_device + free_irq(bgmac->core->irq, net_dev); + + bgmac_chip_reset(bgmac); ++ bgmac_dma_cleanup(bgmac); + + return 0; + } diff --git a/target/linux/generic/patches-3.18/077-11-bgmac-fix-DMA-rx-corruption.patch b/target/linux/generic/patches-3.18/077-11-bgmac-fix-DMA-rx-corruption.patch new file mode 100644 index 0000000000..5f5fe93703 --- /dev/null +++ b/target/linux/generic/patches-3.18/077-11-bgmac-fix-DMA-rx-corruption.patch @@ -0,0 +1,88 @@ +From: Felix Fietkau +Date: Sun, 12 Apr 2015 11:59:47 +0200 +Subject: [PATCH] bgmac: fix DMA rx corruption + +The driver needs to inform the hardware about the first invalid (not yet +filled) rx slot, by writing its DMA descriptor pointer offset to the +BGMAC_DMA_RX_INDEX register. + +This register was set to a value exceeding the rx ring size, effectively +allowing the hardware constant access to the full ring, regardless of +which slots are initialized. + +To fix this issue, always mark the last filled rx slot as invalid. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/broadcom/bgmac.c ++++ b/drivers/net/ethernet/broadcom/bgmac.c +@@ -362,6 +362,16 @@ static int bgmac_dma_rx_skb_for_slot(str + return 0; + } + ++static void bgmac_dma_rx_update_index(struct bgmac *bgmac, ++ struct bgmac_dma_ring *ring) ++{ ++ wmb(); ++ ++ bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX, ++ ring->index_base + ++ ring->end * sizeof(struct bgmac_dma_desc)); ++} ++ + static void bgmac_dma_rx_setup_desc(struct bgmac *bgmac, + struct bgmac_dma_ring *ring, int desc_idx) + { +@@ -380,6 +390,8 @@ static void bgmac_dma_rx_setup_desc(stru + dma_desc->addr_high = cpu_to_le32(upper_32_bits(ring->slots[desc_idx].dma_addr)); + dma_desc->ctl0 = cpu_to_le32(ctl0); + dma_desc->ctl1 = cpu_to_le32(ctl1); ++ ++ ring->end = desc_idx; + } + + static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring, +@@ -394,9 +406,7 @@ static int bgmac_dma_rx_read(struct bgma + end_slot &= BGMAC_DMA_RX_STATDPTR; + end_slot /= sizeof(struct bgmac_dma_desc); + +- ring->end = end_slot; +- +- while (ring->start != ring->end) { ++ while (ring->start != end_slot) { + struct device *dma_dev = bgmac->core->dma_dev; + struct bgmac_slot_info *slot = &ring->slots[ring->start]; + struct bgmac_rx_header *rx = slot->buf + BGMAC_RX_BUF_OFFSET; +@@ -463,6 +473,8 @@ static int bgmac_dma_rx_read(struct bgma + break; + } + ++ bgmac_dma_rx_update_index(bgmac, ring); ++ + return handled; + } + +@@ -682,6 +694,8 @@ static int bgmac_dma_init(struct bgmac * + if (ring->unaligned) + bgmac_dma_rx_enable(bgmac, ring); + ++ ring->start = 0; ++ ring->end = 0; + for (j = 0; j < ring->num_slots; j++) { + err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]); + if (err) +@@ -690,12 +704,7 @@ static int bgmac_dma_init(struct bgmac * + bgmac_dma_rx_setup_desc(bgmac, ring, j); + } + +- bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX, +- ring->index_base + +- ring->num_slots * sizeof(struct bgmac_dma_desc)); +- +- ring->start = 0; +- ring->end = 0; ++ bgmac_dma_rx_update_index(bgmac, ring); + } + + return 0; diff --git a/target/linux/generic/patches-3.18/077-12-bgmac-drop-ring-num_slots.patch b/target/linux/generic/patches-3.18/077-12-bgmac-drop-ring-num_slots.patch new file mode 100644 index 0000000000..7525b63d6a --- /dev/null +++ b/target/linux/generic/patches-3.18/077-12-bgmac-drop-ring-num_slots.patch @@ -0,0 +1,132 @@ +From: Felix Fietkau +Date: Sun, 12 Apr 2015 23:28:38 +0200 +Subject: [PATCH] bgmac: drop ring->num_slots + +The ring size is always known at compile time, so make the code a bit +more efficient + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/broadcom/bgmac.c ++++ b/drivers/net/ethernet/broadcom/bgmac.c +@@ -123,7 +123,7 @@ bgmac_dma_tx_add_buf(struct bgmac *bgmac + struct bgmac_dma_desc *dma_desc; + u32 ctl1; + +- if (i == ring->num_slots - 1) ++ if (i == BGMAC_TX_RING_SLOTS - 1) + ctl0 |= BGMAC_DESC_CTL0_EOT; + + ctl1 = len & BGMAC_DESC_CTL1_LEN; +@@ -378,7 +378,7 @@ static void bgmac_dma_rx_setup_desc(stru + struct bgmac_dma_desc *dma_desc = ring->cpu_base + desc_idx; + u32 ctl0 = 0, ctl1 = 0; + +- if (desc_idx == ring->num_slots - 1) ++ if (desc_idx == BGMAC_RX_RING_SLOTS - 1) + ctl0 |= BGMAC_DESC_CTL0_EOT; + ctl1 |= BGMAC_RX_BUF_SIZE & BGMAC_DESC_CTL1_LEN; + /* Is there any BGMAC device that requires extension? */ +@@ -508,7 +508,7 @@ static void bgmac_dma_tx_ring_free(struc + struct bgmac_slot_info *slot; + int i; + +- for (i = 0; i < ring->num_slots; i++) { ++ for (i = 0; i < BGMAC_TX_RING_SLOTS; i++) { + int len = dma_desc[i].ctl1 & BGMAC_DESC_CTL1_LEN; + + slot = &ring->slots[i]; +@@ -533,7 +533,7 @@ static void bgmac_dma_rx_ring_free(struc + struct bgmac_slot_info *slot; + int i; + +- for (i = 0; i < ring->num_slots; i++) { ++ for (i = 0; i < BGMAC_RX_RING_SLOTS; i++) { + slot = &ring->slots[i]; + if (!slot->buf) + continue; +@@ -547,7 +547,8 @@ static void bgmac_dma_rx_ring_free(struc + } + + static void bgmac_dma_ring_desc_free(struct bgmac *bgmac, +- struct bgmac_dma_ring *ring) ++ struct bgmac_dma_ring *ring, ++ int num_slots) + { + struct device *dma_dev = bgmac->core->dma_dev; + int size; +@@ -556,7 +557,7 @@ static void bgmac_dma_ring_desc_free(str + return; + + /* Free ring of descriptors */ +- size = ring->num_slots * sizeof(struct bgmac_dma_desc); ++ size = num_slots * sizeof(struct bgmac_dma_desc); + dma_free_coherent(dma_dev, size, ring->cpu_base, + ring->dma_base); + } +@@ -577,10 +578,12 @@ static void bgmac_dma_free(struct bgmac + int i; + + for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) +- bgmac_dma_ring_desc_free(bgmac, &bgmac->tx_ring[i]); ++ bgmac_dma_ring_desc_free(bgmac, &bgmac->tx_ring[i], ++ BGMAC_TX_RING_SLOTS); + + for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) +- bgmac_dma_ring_desc_free(bgmac, &bgmac->rx_ring[i]); ++ bgmac_dma_ring_desc_free(bgmac, &bgmac->rx_ring[i], ++ BGMAC_RX_RING_SLOTS); + } + + static int bgmac_dma_alloc(struct bgmac *bgmac) +@@ -603,11 +606,10 @@ static int bgmac_dma_alloc(struct bgmac + + for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) { + ring = &bgmac->tx_ring[i]; +- ring->num_slots = BGMAC_TX_RING_SLOTS; + ring->mmio_base = ring_base[i]; + + /* Alloc ring of descriptors */ +- size = ring->num_slots * sizeof(struct bgmac_dma_desc); ++ size = BGMAC_TX_RING_SLOTS * sizeof(struct bgmac_dma_desc); + ring->cpu_base = dma_zalloc_coherent(dma_dev, size, + &ring->dma_base, + GFP_KERNEL); +@@ -629,11 +631,10 @@ static int bgmac_dma_alloc(struct bgmac + + for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) { + ring = &bgmac->rx_ring[i]; +- ring->num_slots = BGMAC_RX_RING_SLOTS; + ring->mmio_base = ring_base[i]; + + /* Alloc ring of descriptors */ +- size = ring->num_slots * sizeof(struct bgmac_dma_desc); ++ size = BGMAC_RX_RING_SLOTS * sizeof(struct bgmac_dma_desc); + ring->cpu_base = dma_zalloc_coherent(dma_dev, size, + &ring->dma_base, + GFP_KERNEL); +@@ -696,7 +697,7 @@ static int bgmac_dma_init(struct bgmac * + + ring->start = 0; + ring->end = 0; +- for (j = 0; j < ring->num_slots; j++) { ++ for (j = 0; j < BGMAC_RX_RING_SLOTS; j++) { + err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]); + if (err) + return err; +--- a/drivers/net/ethernet/broadcom/bgmac.h ++++ b/drivers/net/ethernet/broadcom/bgmac.h +@@ -419,11 +419,10 @@ struct bgmac_dma_ring { + u32 start; + u32 end; + +- u16 num_slots; +- u16 mmio_base; + struct bgmac_dma_desc *cpu_base; + dma_addr_t dma_base; + u32 index_base; /* Used for unaligned rings only, otherwise 0 */ ++ u16 mmio_base; + bool unaligned; + + struct bgmac_slot_info slots[BGMAC_RX_RING_SLOTS]; diff --git a/target/linux/generic/patches-3.18/773-bgmac-add-srab-switch.patch b/target/linux/generic/patches-3.18/773-bgmac-add-srab-switch.patch index 2f9dce8c75..2219f85f3c 100644 --- a/target/linux/generic/patches-3.18/773-bgmac-add-srab-switch.patch +++ b/target/linux/generic/patches-3.18/773-bgmac-add-srab-switch.patch @@ -12,7 +12,7 @@ Signed-off-by: Hauke Mehrtens #include static const struct bcma_device_id bgmac_bcma_tbl[] = { -@@ -1538,6 +1539,17 @@ static void bgmac_mii_unregister(struct +@@ -1524,6 +1525,17 @@ static void bgmac_mii_unregister(struct mdiobus_free(mii_bus); } @@ -30,7 +30,7 @@ Signed-off-by: Hauke Mehrtens /************************************************** * BCMA bus ops **************************************************/ -@@ -1661,6 +1673,16 @@ static int bgmac_probe(struct bcma_devic +@@ -1647,6 +1659,16 @@ static int bgmac_probe(struct bcma_devic net_dev->hw_features = net_dev->features; net_dev->vlan_features = net_dev->features; @@ -47,7 +47,7 @@ Signed-off-by: Hauke Mehrtens err = register_netdev(bgmac->net_dev); if (err) { bgmac_err(bgmac, "Cannot register net device\n"); -@@ -1687,6 +1709,10 @@ static void bgmac_remove(struct bcma_dev +@@ -1673,6 +1695,10 @@ static void bgmac_remove(struct bcma_dev { struct bgmac *bgmac = bcma_get_drvdata(core); diff --git a/target/linux/generic/patches-3.18/775-bgmac-check-length-of-received-frame.patch b/target/linux/generic/patches-3.18/775-bgmac-check-length-of-received-frame.patch deleted file mode 100644 index 2be1c3676d..0000000000 --- a/target/linux/generic/patches-3.18/775-bgmac-check-length-of-received-frame.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 2d12a9abf3f81de5b51852e3cfcba8cedac82642 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Fri, 6 Dec 2013 01:14:52 +0100 -Subject: [PATCH] bgmac: check length of received frame - ---- - drivers/net/ethernet/broadcom/bgmac.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/broadcom/bgmac.c -+++ b/drivers/net/ethernet/broadcom/bgmac.c -@@ -427,6 +427,27 @@ static int bgmac_dma_rx_read(struct bgma - dma_addr_t old_dma_addr = slot->dma_addr; - int err; - -+ if (len > BGMAC_RX_MAX_FRAME_SIZE) { -+ struct bgmac_dma_desc *dma_desc = ring->cpu_base + ring->start; -+ -+ bgmac_err(bgmac, "Hardware reported invalid packet length %d for slot %d!\n", len, ring->start); -+ bgmac_err(bgmac, "flags: 0x%04X\n", flags); -+ bgmac_err(bgmac, "ctl0: 0x%08X\tctl1: 0x%08X\n", le32_to_cpu(dma_desc->ctl0), le32_to_cpu(dma_desc->ctl1)); -+ -+ bgmac_err(bgmac, " BGMAC_DMA_RX_CTL: 0x%08X\n", bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL)); -+ bgmac_err(bgmac, " BGMAC_DMA_RX_INDEX: 0x%08X\n", bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX)); -+ bgmac_err(bgmac, "BGMAC_DMA_RX_RINGLO: 0x%08X\n", bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGLO)); -+ bgmac_err(bgmac, "BGMAC_DMA_RX_RINGHI: 0x%08X\n", bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGHI)); -+ bgmac_err(bgmac, "BGMAC_DMA_RX_STATUS: 0x%08X\n", bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_STATUS)); -+ bgmac_err(bgmac, " BGMAC_DMA_RX_ERROR: 0x%08X\n", bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_ERROR)); -+ -+ dma_sync_single_for_device(dma_dev, -+ slot->dma_addr, -+ BGMAC_RX_BUF_SIZE, -+ DMA_FROM_DEVICE); -+ break; -+ } -+ - /* Check for poison and drop or pass the packet */ - if (len == 0xdead && flags == 0xbeef) { - bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n",