summaryrefslogtreecommitdiff
path: root/target/linux/generic/patches-3.10/775-bgmac-check-length-of-received-frame.patch
diff options
context:
space:
mode:
authorhauke <hauke@3c298f89-4303-0410-b956-a3cf2f4a3e73>2014-04-08 19:50:17 +0000
committerhauke <hauke@3c298f89-4303-0410-b956-a3cf2f4a3e73>2014-04-08 19:50:17 +0000
commit421797fed79eb198eae103fd61c9609eb7a09219 (patch)
tree11ffccb02373e0e5ab762cb7c4b59351f84da43d /target/linux/generic/patches-3.10/775-bgmac-check-length-of-received-frame.patch
parent1972881c20e5f43dd1bdb7f5a6d9e7423bcfd674 (diff)
kernel: bgmac: rework patch checking packet length
This bgmac patch was an attempt to fix/workaround bug reported in https://dev.openwrt.org/ticket/7198 noticed on WNR3500L. Patch assumed length reported by the hardware was 0 and was trying to read it until getting a different value. This was actually the opposite. Lenghts were some invalid & huge values that resulted in skb_over_panic. For example: skbuff: skb_over_panic: text:83b21074 len:57222 (...) skbuff: skb_over_panic: text:87af1024 len:43226 (...) skbuff: skb_over_panic: text:87af5024 len:8739 (...) So instead of that not-working patch checking for 0, write a new one checking for huge values. In case something like that happens, dump hardware state and drop the packet. Signed-off-by: Rafał Miłecki <zajec5@gmail.com> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@40424 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/generic/patches-3.10/775-bgmac-check-length-of-received-frame.patch')
-rw-r--r--target/linux/generic/patches-3.10/775-bgmac-check-length-of-received-frame.patch50
1 files changed, 24 insertions, 26 deletions
diff --git a/target/linux/generic/patches-3.10/775-bgmac-check-length-of-received-frame.patch b/target/linux/generic/patches-3.10/775-bgmac-check-length-of-received-frame.patch
index f708e7dcec..c3d63b65fa 100644
--- a/target/linux/generic/patches-3.10/775-bgmac-check-length-of-received-frame.patch
+++ b/target/linux/generic/patches-3.10/775-bgmac-check-length-of-received-frame.patch
@@ -9,33 +9,31 @@ Subject: [PATCH] bgmac: check length of received frame
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
-@@ -349,6 +349,7 @@ static int bgmac_dma_rx_read(struct bgma
- struct sk_buff *skb = slot->skb;
- struct bgmac_rx_header *rx;
- u16 len, flags;
-+ int count;
-
- /* Unmap buffer to make it accessible to the CPU */
- dma_sync_single_for_cpu(dma_dev, slot->dma_addr,
-@@ -357,6 +358,12 @@ static int bgmac_dma_rx_read(struct bgma
- /* Get info from the header */
- rx = (struct bgmac_rx_header *)skb->data;
- len = le16_to_cpu(rx->len);
-+ for (count = 0; count < 200; count++) {
-+ len = le16_to_cpu(rx->len);
-+ if (len)
-+ break;
-+ udelay(1);
-+ }
- flags = le16_to_cpu(rx->flags);
-
- do {
-@@ -364,7 +371,7 @@ static int bgmac_dma_rx_read(struct bgma
+@@ -363,6 +363,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) {
-+ if (!len || (len == 0xdead && flags == 0xbeef)) {
+ 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,