Changeset 40424


Ignore:
Timestamp:
2014-04-08T21:50:17+02:00 (4 years ago)
Author:
hauke
Message:

kernel: bgmac: rework patch checking packet length

This bgmac patch was an attempt to fix/workaround bug reported in
https://dev.archive.openwrt.org/ticket/7198.html 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@…>

Location:
trunk/target/linux/generic
Files:
3 added
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/generic/patches-3.10/775-bgmac-check-length-of-received-frame.patch

    r39201 r40424  
    1010--- a/drivers/net/ethernet/broadcom/bgmac.c 
    1111+++ b/drivers/net/ethernet/broadcom/bgmac.c 
    12 @@ -349,6 +349,7 @@ static int bgmac_dma_rx_read(struct bgma 
    13                 struct sk_buff *skb = slot->skb; 
    14                 struct bgmac_rx_header *rx; 
    15                 u16 len, flags; 
    16 +               int count; 
    17   
    18                 /* Unmap buffer to make it accessible to the CPU */ 
    19                 dma_sync_single_for_cpu(dma_dev, slot->dma_addr, 
    20 @@ -357,6 +358,12 @@ static int bgmac_dma_rx_read(struct bgma 
    21                 /* Get info from the header */ 
    22                 rx = (struct bgmac_rx_header *)skb->data; 
    23                 len = le16_to_cpu(rx->len); 
    24 +               for (count = 0; count < 200; count++) { 
    25 +                       len = le16_to_cpu(rx->len); 
    26 +                       if (len) 
    27 +                               break; 
    28 +                       udelay(1); 
    29 +               } 
    30                 flags = le16_to_cpu(rx->flags); 
    31   
    32                 do { 
    33 @@ -364,7 +371,7 @@ static int bgmac_dma_rx_read(struct bgma 
     12@@ -363,6 +363,27 @@ static int bgmac_dma_rx_read(struct bgma 
     13                        dma_addr_t old_dma_addr = slot->dma_addr; 
    3414                        int err; 
    3515  
     16+                       if (len > BGMAC_RX_MAX_FRAME_SIZE) { 
     17+                               struct bgmac_dma_desc *dma_desc = ring->cpu_base + ring->start; 
     18+ 
     19+                               bgmac_err(bgmac, "Hardware reported invalid packet length %d for slot %d!\n", len, ring->start); 
     20+                               bgmac_err(bgmac, "flags: 0x%04X\n", flags); 
     21+                               bgmac_err(bgmac, "ctl0: 0x%08X\tctl1: 0x%08X\n", le32_to_cpu(dma_desc->ctl0), le32_to_cpu(dma_desc->ctl1)); 
     22+ 
     23+                               bgmac_err(bgmac, "   BGMAC_DMA_RX_CTL: 0x%08X\n", bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL)); 
     24+                               bgmac_err(bgmac, " BGMAC_DMA_RX_INDEX: 0x%08X\n", bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX)); 
     25+                               bgmac_err(bgmac, "BGMAC_DMA_RX_RINGLO: 0x%08X\n", bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGLO)); 
     26+                               bgmac_err(bgmac, "BGMAC_DMA_RX_RINGHI: 0x%08X\n", bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGHI)); 
     27+                               bgmac_err(bgmac, "BGMAC_DMA_RX_STATUS: 0x%08X\n", bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_STATUS)); 
     28+                               bgmac_err(bgmac, " BGMAC_DMA_RX_ERROR: 0x%08X\n", bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_ERROR)); 
     29+ 
     30+                               dma_sync_single_for_device(dma_dev, 
     31+                                                          slot->dma_addr, 
     32+                                                          BGMAC_RX_BUF_SIZE, 
     33+                                                          DMA_FROM_DEVICE); 
     34+                               break; 
     35+                       } 
     36+ 
    3637                        /* Check for poison and drop or pass the packet */ 
    37 -                       if (len == 0xdead && flags == 0xbeef) { 
    38 +                       if (!len || (len == 0xdead && flags == 0xbeef)) { 
     38                        if (len == 0xdead && flags == 0xbeef) { 
    3939                                bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n", 
    40                                           ring->start); 
    41                                 dma_sync_single_for_device(dma_dev, 
Note: See TracChangeset for help on using the changeset viewer.