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> SVN-Revision: 40424
This commit is contained in:
parent
4abcae7a1c
commit
64f54741e3
4 changed files with 141 additions and 26 deletions
|
@ -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,
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
From 2d12a9abf3f81de5b51852e3cfcba8cedac82642 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
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
|
||||
@@ -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) {
|
||||
bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n",
|
|
@ -0,0 +1,39 @@
|
|||
From 2d12a9abf3f81de5b51852e3cfcba8cedac82642 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
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
|
||||
@@ -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) {
|
||||
bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n",
|
|
@ -0,0 +1,39 @@
|
|||
From 2d12a9abf3f81de5b51852e3cfcba8cedac82642 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
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
|
||||
@@ -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) {
|
||||
bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n",
|
Loading…
Reference in a new issue