kernel: sync bgmac changes with latest upstream submission

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

SVN-Revision: 45420
This commit is contained in:
Felix Fietkau 2015-04-13 17:32:33 +00:00
parent 24e9f52106
commit 1bf8e555bb
8 changed files with 92 additions and 54 deletions

View file

@ -69,7 +69,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
- 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;

View file

@ -2,30 +2,44 @@ From: Felix Fietkau <nbd@openwrt.org>
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 <nbd@openwrt.org>
---
--- 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 <nbd@openwrt.org>
- 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;

View file

@ -11,15 +11,14 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--- 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;
+ }
+

View file

@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--- 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 <nbd@openwrt.org>
}
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 <nbd@openwrt.org>
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 <nbd@openwrt.org>
}
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 <nbd@openwrt.org>
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 <nbd@openwrt.org>
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 <nbd@openwrt.org>
}
/**************************************************
@@ -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 <nbd@openwrt.org>
/* 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 <nbd@openwrt.org>
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 <nbd@openwrt.org>
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);

View file

@ -54,8 +54,8 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
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 <nbd@openwrt.org>
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 <nbd@openwrt.org>
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);
}

View file

@ -28,7 +28,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
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 <nbd@openwrt.org>
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 <nbd@openwrt.org>
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 <nbd@openwrt.org>
{
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 <nbd@openwrt.org>
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 <nbd@openwrt.org>
}
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 <nbd@openwrt.org>
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 <nbd@openwrt.org>
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;

View file

@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--- 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);

View file

@ -12,7 +12,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
#include <bcm47xx_nvram.h>
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 <hauke@hauke-m.de>
/**************************************************
* 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 <hauke@hauke-m.de>
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);