From 1bf8e555bb3466baf775113ab27aa8f05f0e6aa7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 13 Apr 2015 17:32:33 +0000 Subject: [PATCH] kernel: sync bgmac changes with latest upstream submission Signed-off-by: Felix Fietkau SVN-Revision: 45420 --- ...rrupts-disabled-as-long-as-there-is-.patch | 2 +- ...bgmac-simplify-rx-DMA-error-handling.patch | 73 ++++++++++++++----- ...gmac-add-check-for-oversized-packets.patch | 5 +- ...7-10-bgmac-simplify-dma-init-cleanup.patch | 34 +++++---- .../077-11-bgmac-fix-DMA-rx-corruption.patch | 8 +- .../077-12-bgmac-drop-ring-num_slots.patch | 16 ++-- ...bgmac-reset-all-4-GMAC-cores-on-init.patch | 2 +- .../773-bgmac-add-srab-switch.patch | 6 +- 8 files changed, 92 insertions(+), 54 deletions(-) diff --git a/target/linux/generic/patches-3.18/077-05-bgmac-leave-interrupts-disabled-as-long-as-there-is-.patch b/target/linux/generic/patches-3.18/077-05-bgmac-leave-interrupts-disabled-as-long-as-there-is-.patch index 79746540c9..7118d0d145 100644 --- a/target/linux/generic/patches-3.18/077-05-bgmac-leave-interrupts-disabled-as-long-as-there-is-.patch +++ b/target/linux/generic/patches-3.18/077-05-bgmac-leave-interrupts-disabled-as-long-as-there-is-.patch @@ -69,7 +69,7 @@ Signed-off-by: Felix Fietkau - bgmac_err(bgmac, "Unknown IRQs: 0x%08X\n", bgmac->int_status); - bgmac->int_status = 0; - } -+ /* poll again if more events arrived in the mean time */ ++ /* Poll again if more events arrived in the meantime */ + if (bgmac_read(bgmac, BGMAC_INT_STATUS) & (BGMAC_IS_TX0 | BGMAC_IS_RX)) + return handled; 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 index f26e42c20d..e1e8c8f656 100644 --- 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 @@ -2,30 +2,44 @@ 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. +Unmap the DMA buffer before checking it. If an error occurs, free the +buffer and allocate a new one. If allocation or mapping fails, retry as +long as there is NAPI poll budget left (count every attempt instead of +every frame). 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 +@@ -404,51 +404,33 @@ static int bgmac_dma_rx_read(struct bgma + void *buf = slot->buf; u16 len, flags; - /* Unmap buffer to make it accessible to the CPU */ +- /* 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); +- +- /* Get info from the header */ +- len = le16_to_cpu(rx->len); +- flags = le16_to_cpu(rx->flags); ++ if (++handled >= weight - 1) /* Should never be greater */ ++ break; do { - dma_addr_t old_dma_addr = slot->dma_addr; - int err; +- int err; ++ if (!slot->dma_addr) ++ break; ++ ++ /* Unmap buffer to make it accessible to the CPU */ ++ dma_unmap_single(dma_dev, slot->dma_addr, ++ BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE); ++ slot->dma_addr = 0; ++ ++ /* Get info from the header */ ++ len = le16_to_cpu(rx->len); ++ flags = le16_to_cpu(rx->flags); /* Check for poison and drop or pass the packet */ if (len == 0xdead && flags == 0xbeef) { @@ -35,34 +49,53 @@ Signed-off-by: Felix Fietkau - slot->dma_addr, - BGMAC_RX_BUF_SIZE, - DMA_FROM_DEVICE); ++ kfree(buf); 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); + /* Omit CRC. */ + len -= ETH_FCS_LEN; + +- /* Prepare new skb as replacement */ +- err = bgmac_dma_rx_skb_for_slot(bgmac, slot); +- if (err) { +- /* 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; - } +- 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++; + BGMAC_RX_BUF_OFFSET + len); +@@ -458,14 +440,16 @@ static int bgmac_dma_rx_read(struct bgma + skb_checksum_none_assert(skb); + skb->protocol = eth_type_trans(skb, bgmac->net_dev); + napi_gro_receive(&bgmac->napi, skb); +- handled++; } while (0); ++ /* Prepare new skb as replacement */ ++ if (bgmac_dma_rx_skb_for_slot(bgmac, slot)) ++ continue; ++ + bgmac_dma_rx_setup_desc(bgmac, ring, ring->start); + if (++ring->start >= BGMAC_RX_RING_SLOTS) ring->start = 0; +- +- if (handled >= weight) /* Should never be greater */ +- break; + } + return handled; 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 index fa45a43686..89e1a32368 100644 --- 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 @@ -11,15 +11,14 @@ 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 +@@ -428,6 +428,13 @@ 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); ++ kfree(buf); + break; + } + 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 index be68fa7269..16bb64870d 100644 --- 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 @@ -11,7 +11,7 @@ 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 +@@ -545,18 +545,26 @@ static void bgmac_dma_ring_desc_free(str ring->dma_base); } @@ -44,7 +44,7 @@ Signed-off-by: Felix Fietkau } static int bgmac_dma_alloc(struct bgmac *bgmac) -@@ -608,8 +616,6 @@ static int bgmac_dma_alloc(struct bgmac +@@ -604,8 +612,6 @@ static int bgmac_dma_alloc(struct bgmac } for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) { @@ -53,7 +53,7 @@ Signed-off-by: Felix Fietkau 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 +@@ -628,15 +634,6 @@ static int bgmac_dma_alloc(struct bgmac ring->index_base = lower_32_bits(ring->dma_base); else ring->index_base = 0; @@ -69,7 +69,7 @@ Signed-off-by: Felix Fietkau } return 0; -@@ -650,10 +647,10 @@ err_dma_free: +@@ -646,10 +643,10 @@ err_dma_free: return -ENOMEM; } @@ -82,7 +82,7 @@ Signed-off-by: Felix Fietkau 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 +@@ -681,8 +678,13 @@ static void bgmac_dma_init(struct bgmac if (ring->unaligned) bgmac_dma_rx_enable(bgmac, ring); @@ -97,7 +97,7 @@ Signed-off-by: Felix Fietkau bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX, ring->index_base + -@@ -695,6 +697,8 @@ static void bgmac_dma_init(struct bgmac +@@ -691,6 +693,8 @@ static void bgmac_dma_init(struct bgmac ring->start = 0; ring->end = 0; } @@ -106,7 +106,7 @@ Signed-off-by: Felix Fietkau } /************************************************** -@@ -1170,11 +1174,8 @@ static void bgmac_enable(struct bgmac *b +@@ -1166,11 +1170,8 @@ static void bgmac_enable(struct bgmac *b } /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipinit */ @@ -119,7 +119,7 @@ Signed-off-by: Felix Fietkau /* 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 +@@ -1188,16 +1189,7 @@ static void bgmac_chip_init(struct bgmac bgmac_write(bgmac, BGMAC_RXMAX_LENGTH, 32 + ETHER_MAX_LEN); @@ -137,16 +137,14 @@ Signed-off-by: Felix Fietkau bgmac_enable(bgmac); } -@@ -1261,8 +1253,15 @@ static int bgmac_open(struct net_device +@@ -1257,8 +1249,13 @@ 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; -+ } ++ if (err) ++ goto err_out; + /* Specs say about reclaiming rings here, but we do that in DMA init */ - bgmac_chip_init(bgmac, true); @@ -154,7 +152,15 @@ Signed-off-by: Felix Fietkau 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 +@@ -1273,6 +1270,7 @@ static int bgmac_open(struct net_device + netif_carrier_on(net_dev); + + err_out: ++ bgmac_dma_cleanup(bgmac); + return err; + } + +@@ -1289,6 +1287,7 @@ static int bgmac_stop(struct net_device free_irq(bgmac->core->irq, net_dev); bgmac_chip_reset(bgmac); 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 index 5f5fe93703..846e2ee0e2 100644 --- 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 @@ -54,8 +54,8 @@ Signed-off-by: Felix Fietkau 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; +@@ -459,6 +469,8 @@ static int bgmac_dma_rx_read(struct bgma + ring->start = 0; } + bgmac_dma_rx_update_index(bgmac, ring); @@ -63,7 +63,7 @@ Signed-off-by: Felix Fietkau return handled; } -@@ -682,6 +694,8 @@ static int bgmac_dma_init(struct bgmac * +@@ -678,6 +690,8 @@ static int bgmac_dma_init(struct bgmac * if (ring->unaligned) bgmac_dma_rx_enable(bgmac, ring); @@ -72,7 +72,7 @@ Signed-off-by: Felix Fietkau 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 * +@@ -686,12 +700,7 @@ static int bgmac_dma_init(struct bgmac * bgmac_dma_rx_setup_desc(bgmac, ring, j); } 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 index 7525b63d6a..6709aaa4ea 100644 --- 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 @@ -28,7 +28,7 @@ Signed-off-by: Felix Fietkau 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 +@@ -504,7 +504,7 @@ static void bgmac_dma_tx_ring_free(struc struct bgmac_slot_info *slot; int i; @@ -37,7 +37,7 @@ Signed-off-by: Felix Fietkau 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 +@@ -529,7 +529,7 @@ static void bgmac_dma_rx_ring_free(struc struct bgmac_slot_info *slot; int i; @@ -46,7 +46,7 @@ Signed-off-by: Felix Fietkau slot = &ring->slots[i]; if (!slot->buf) continue; -@@ -547,7 +547,8 @@ static void bgmac_dma_rx_ring_free(struc +@@ -543,7 +543,8 @@ static void bgmac_dma_rx_ring_free(struc } static void bgmac_dma_ring_desc_free(struct bgmac *bgmac, @@ -56,7 +56,7 @@ Signed-off-by: Felix Fietkau { struct device *dma_dev = bgmac->core->dma_dev; int size; -@@ -556,7 +557,7 @@ static void bgmac_dma_ring_desc_free(str +@@ -552,7 +553,7 @@ static void bgmac_dma_ring_desc_free(str return; /* Free ring of descriptors */ @@ -65,7 +65,7 @@ Signed-off-by: Felix Fietkau dma_free_coherent(dma_dev, size, ring->cpu_base, ring->dma_base); } -@@ -577,10 +578,12 @@ static void bgmac_dma_free(struct bgmac +@@ -573,10 +574,12 @@ static void bgmac_dma_free(struct bgmac int i; for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) @@ -80,7 +80,7 @@ Signed-off-by: Felix Fietkau } static int bgmac_dma_alloc(struct bgmac *bgmac) -@@ -603,11 +606,10 @@ static int bgmac_dma_alloc(struct bgmac +@@ -599,11 +602,10 @@ static int bgmac_dma_alloc(struct bgmac for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) { ring = &bgmac->tx_ring[i]; @@ -93,7 +93,7 @@ Signed-off-by: Felix Fietkau 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 +@@ -625,11 +627,10 @@ static int bgmac_dma_alloc(struct bgmac for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) { ring = &bgmac->rx_ring[i]; @@ -106,7 +106,7 @@ Signed-off-by: Felix Fietkau 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 * +@@ -692,7 +693,7 @@ static int bgmac_dma_init(struct bgmac * ring->start = 0; ring->end = 0; diff --git a/target/linux/generic/patches-3.18/077-14-bgmac-reset-all-4-GMAC-cores-on-init.patch b/target/linux/generic/patches-3.18/077-14-bgmac-reset-all-4-GMAC-cores-on-init.patch index d1b63f155b..b38a116f93 100644 --- a/target/linux/generic/patches-3.18/077-14-bgmac-reset-all-4-GMAC-cores-on-init.patch +++ b/target/linux/generic/patches-3.18/077-14-bgmac-reset-all-4-GMAC-cores-on-init.patch @@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c -@@ -1609,8 +1609,11 @@ static int bgmac_probe(struct bcma_devic +@@ -1604,8 +1604,11 @@ static int bgmac_probe(struct bcma_devic ns_core = bcma_find_core_unit(core->bus, BCMA_CORE_MAC_GBIT, ns_gmac); 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 a18be96417..14c640719c 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[] = { -@@ -1524,6 +1525,17 @@ static void bgmac_mii_unregister(struct +@@ -1519,6 +1520,17 @@ static void bgmac_mii_unregister(struct mdiobus_free(mii_bus); } @@ -30,7 +30,7 @@ Signed-off-by: Hauke Mehrtens /************************************************** * BCMA bus ops **************************************************/ -@@ -1650,6 +1662,16 @@ static int bgmac_probe(struct bcma_devic +@@ -1645,6 +1657,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"); -@@ -1676,6 +1698,10 @@ static void bgmac_remove(struct bcma_dev +@@ -1671,6 +1693,10 @@ static void bgmac_remove(struct bcma_dev { struct bgmac *bgmac = bcma_get_drvdata(core);