From: Hauke Mehrtens Date: Wed, 25 Sep 2013 21:47:25 +0000 (+0000) Subject: bcm53xx: update bgmac driver X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=0bdc137636ec10b39dad18abe25a946323155b9c;p=openwrt%2Fstaging%2Fdedeckeh.git bcm53xx: update bgmac driver Update the bgmac driver with the patches already used for bcm47xx target. Signed-off-by: Hauke Mehrtens SVN-Revision: 38199 --- diff --git a/target/linux/bcm53xx/patches-3.10/201-bgmac-add-dependency-to-phylib.patch b/target/linux/bcm53xx/patches-3.10/201-bgmac-add-dependency-to-phylib.patch deleted file mode 100644 index a0abae9c24..0000000000 --- a/target/linux/bcm53xx/patches-3.10/201-bgmac-add-dependency-to-phylib.patch +++ /dev/null @@ -1,19 +0,0 @@ -bgmac: add dependency to phylib - -bgmac is using functions from phylib, add the dependency. - -Signed-off-by: Hauke Mehrtens ---- - drivers/net/ethernet/broadcom/Kconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/net/ethernet/broadcom/Kconfig -+++ b/drivers/net/ethernet/broadcom/Kconfig -@@ -133,6 +133,7 @@ config BNX2X_SRIOV - config BGMAC - tristate "BCMA bus GBit core support" - depends on BCMA_HOST_SOC && HAS_DMA -+ select PHYLIB - ---help--- - This driver supports GBit MAC and BCM4706 GBit MAC cores on BCMA bus. - They can be found on BCM47xx SoCs and provide gigabit ethernet. diff --git a/target/linux/bcm53xx/patches-3.10/203-bgmac-register-phy.patch b/target/linux/bcm53xx/patches-3.10/203-bgmac-register-phy.patch index 4467d2365a..6a00cdf0fb 100644 --- a/target/linux/bcm53xx/patches-3.10/203-bgmac-register-phy.patch +++ b/target/linux/bcm53xx/patches-3.10/203-bgmac-register-phy.patch @@ -1,11 +1,13 @@ -bgmac: register phy - -Signed-off-by: Hauke Mehrtens ---- - drivers/net/ethernet/broadcom/bgmac.c | 137 ++++++++++++++++----------------- - drivers/net/ethernet/broadcom/bgmac.h | 3 + - 2 files changed, 71 insertions(+), 69 deletions(-) - +--- a/drivers/net/ethernet/broadcom/Kconfig ++++ b/drivers/net/ethernet/broadcom/Kconfig +@@ -133,6 +133,7 @@ config BNX2X_SRIOV + config BGMAC + tristate "BCMA bus GBit core support" + depends on BCMA_HOST_SOC && HAS_DMA ++ select PHYLIB + ---help--- + This driver supports GBit MAC and BCM4706 GBit MAC cores on BCMA bus. + They can be found on BCM47xx SoCs and provide gigabit ethernet. --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -1205,27 +1205,14 @@ static int bgmac_set_mac_address(struct @@ -33,8 +35,8 @@ Signed-off-by: Hauke Mehrtens - default: - return -EOPNOTSUPP; - } -+ if (!netif_running(net_dev)) -+ return -EINVAL; ++ if (!netif_running(net_dev)) ++ return -EINVAL; + + if (!bgmac->phydev) + return -EINVAL; @@ -43,7 +45,7 @@ Signed-off-by: Hauke Mehrtens } static const struct net_device_ops bgmac_netdev_ops = { -@@ -1247,61 +1234,18 @@ static int bgmac_get_settings(struct net +@@ -1247,61 +1234,16 @@ static int bgmac_get_settings(struct net { struct bgmac *bgmac = netdev_priv(net_dev); @@ -95,7 +97,6 @@ Signed-off-by: Hauke Mehrtens } -#if 0 -+ static int bgmac_set_settings(struct net_device *net_dev, struct ethtool_cmd *cmd) { @@ -105,11 +106,10 @@ Signed-off-by: Hauke Mehrtens + return phy_ethtool_sset(bgmac->phydev, cmd); } -#endif -+ static void bgmac_get_drvinfo(struct net_device *net_dev, struct ethtool_drvinfo *info) -@@ -1312,6 +1256,7 @@ static void bgmac_get_drvinfo(struct net +@@ -1312,6 +1254,7 @@ static void bgmac_get_drvinfo(struct net static const struct ethtool_ops bgmac_ethtool_ops = { .get_settings = bgmac_get_settings, @@ -117,7 +117,7 @@ Signed-off-by: Hauke Mehrtens .get_drvinfo = bgmac_get_drvinfo, }; -@@ -1330,10 +1275,42 @@ static int bgmac_mii_write(struct mii_bu +@@ -1330,10 +1273,36 @@ static int bgmac_mii_write(struct mii_bu return bgmac_phy_write(bus->priv, mii_id, regnum, value); } @@ -125,7 +125,7 @@ Signed-off-by: Hauke Mehrtens +{ + struct bgmac *bgmac = netdev_priv(dev); + struct phy_device *phydev = bgmac->phydev; -+ int status_changed = 0; ++ bool status_changed = 0; + + BUG_ON(!phydev); + @@ -140,14 +140,8 @@ Signed-off-by: Hauke Mehrtens + bgmac->old_duplex = phydev->duplex; + } + -+ if (status_changed) { -+ pr_info("%s: link %s", dev->name, phydev->link ? -+ "UP" : "DOWN"); -+ if (phydev->link) -+ pr_cont(" - %d/%s", phydev->speed, -+ phydev->duplex == DUPLEX_FULL ? "full" : "half"); -+ pr_cont("\n"); -+ } ++ if (status_changed) ++ phy_print_status(phydev); +} + static int bgmac_mii_register(struct bgmac *bgmac) @@ -160,7 +154,7 @@ Signed-off-by: Hauke Mehrtens mii_bus = mdiobus_alloc(); if (!mii_bus) -@@ -1364,7 +1341,29 @@ static int bgmac_mii_register(struct bgm +@@ -1364,7 +1333,28 @@ static int bgmac_mii_register(struct bgm bgmac->mii_bus = mii_bus; @@ -173,7 +167,7 @@ Signed-off-by: Hauke Mehrtens + PHY_INTERFACE_MODE_MII); + + if (IS_ERR(phydev)) { -+ netdev_err(net_dev, "could not attach PHY: %s", phy_id); ++ netdev_err(net_dev, "could not attach PHY: %s\n", phy_id); + bgmac->phyaddr = BGMAC_PHY_NOREGS; + return PTR_ERR(phydev); + } @@ -183,9 +177,8 @@ Signed-off-by: Hauke Mehrtens + bgmac->old_duplex = -1; + bgmac->phyaddr = phydev->addr; + -+ netdev_info(net_dev, "attached PHY driver [%s] " -+ "(mii_bus:phy_addr=%s)\n", -+ phydev->drv->name, dev_name(&phydev->dev)); ++ netdev_info(net_dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s)\n", ++ phydev->drv->name, dev_name(&phydev->dev)); + + return 0; diff --git a/target/linux/bcm53xx/patches-3.10/210-bgmac_fix_internal_switch_initialization.patch b/target/linux/bcm53xx/patches-3.10/210-bgmac_fix_internal_switch_initialization.patch new file mode 100644 index 0000000000..a5ace95636 --- /dev/null +++ b/target/linux/bcm53xx/patches-3.10/210-bgmac_fix_internal_switch_initialization.patch @@ -0,0 +1,33 @@ +bgmac: fix internal switch initialization + +Some devices (BCM4749, BCM5357, BCM53572) have internal switch that +requires initialization. We already have code for this, but because +of the typo in code it was never working. This resulted in network not +working for some routers and possibility of soft-bricking them. + +Use correct bit for switch initialization and fix typo in the define. + +Signed-off-by: Rafał Miłecki + +--- a/drivers/net/ethernet/broadcom/bgmac.c ++++ b/drivers/net/ethernet/broadcom/bgmac.c +@@ -931,7 +931,7 @@ static void bgmac_chip_reset(struct bgma + struct bcma_drv_cc *cc = &bgmac->core->bus->drv_cc; + u8 et_swtype = 0; + u8 sw_type = BGMAC_CHIPCTL_1_SW_TYPE_EPHY | +- BGMAC_CHIPCTL_1_IF_TYPE_RMII; ++ BGMAC_CHIPCTL_1_IF_TYPE_MII; + char buf[2]; + + if (bcm47xx_nvram_getenv("et_swtype", buf, 1) > 0) { +--- a/drivers/net/ethernet/broadcom/bgmac.h ++++ b/drivers/net/ethernet/broadcom/bgmac.h +@@ -334,7 +334,7 @@ + + #define BGMAC_CHIPCTL_1_IF_TYPE_MASK 0x00000030 + #define BGMAC_CHIPCTL_1_IF_TYPE_RMII 0x00000000 +-#define BGMAC_CHIPCTL_1_IF_TYPE_MI 0x00000010 ++#define BGMAC_CHIPCTL_1_IF_TYPE_MII 0x00000010 + #define BGMAC_CHIPCTL_1_IF_TYPE_RGMII 0x00000020 + #define BGMAC_CHIPCTL_1_SW_TYPE_MASK 0x000000C0 + #define BGMAC_CHIPCTL_1_SW_TYPE_EPHY 0x00000000 diff --git a/target/linux/bcm53xx/patches-3.10/211-bgmac_fix_parsing_of_et_swtype.patch b/target/linux/bcm53xx/patches-3.10/211-bgmac_fix_parsing_of_et_swtype.patch new file mode 100644 index 0000000000..2f79b8d823 --- /dev/null +++ b/target/linux/bcm53xx/patches-3.10/211-bgmac_fix_parsing_of_et_swtype.patch @@ -0,0 +1,14 @@ +--- a/drivers/net/ethernet/broadcom/bgmac.c ++++ b/drivers/net/ethernet/broadcom/bgmac.c +@@ -932,9 +932,9 @@ static void bgmac_chip_reset(struct bgma + u8 et_swtype = 0; + u8 sw_type = BGMAC_CHIPCTL_1_SW_TYPE_EPHY | + BGMAC_CHIPCTL_1_IF_TYPE_MII; +- char buf[2]; ++ char buf[4]; + +- if (bcm47xx_nvram_getenv("et_swtype", buf, 1) > 0) { ++ if (bcm47xx_nvram_getenv("et_swtype", buf, sizeof(buf)) > 0) { + if (kstrtou8(buf, 0, &et_swtype)) + bgmac_err(bgmac, "Failed to parse et_swtype (%s)\n", + buf); diff --git a/target/linux/bcm53xx/patches-3.10/212-bgmac_implement_unaligned_addressing.patch b/target/linux/bcm53xx/patches-3.10/212-bgmac_implement_unaligned_addressing.patch new file mode 100644 index 0000000000..4987e5e720 --- /dev/null +++ b/target/linux/bcm53xx/patches-3.10/212-bgmac_implement_unaligned_addressing.patch @@ -0,0 +1,140 @@ +bgmac: implement unaligned addressing for DMA rings that support it + +This is important patch for new devices that support unaligned +addressing. That devices suffer from the backward-compatibility bug in +DMA engine. In theory we should be able to use old mechanism, but in +practice DMA address seems to be randomly copied into status register +when hardware reaches end of a ring. This breaks reading slot number +from status register and we can't use DMA anymore. + +Signed-off-by: Rafał Miłecki + +--- a/drivers/net/ethernet/broadcom/bgmac.c ++++ b/drivers/net/ethernet/broadcom/bgmac.c +@@ -162,6 +162,7 @@ static netdev_tx_t bgmac_dma_tx_add(stru + if (++ring->end >= BGMAC_TX_RING_SLOTS) + ring->end = 0; + bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_INDEX, ++ ring->index_base + + ring->end * sizeof(struct bgmac_dma_desc)); + + /* Always keep one slot free to allow detecting bugged calls. */ +@@ -186,6 +187,8 @@ static void bgmac_dma_tx_free(struct bgm + /* The last slot that hardware didn't consume yet */ + empty_slot = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_STATUS); + empty_slot &= BGMAC_DMA_TX_STATDPTR; ++ empty_slot -= ring->index_base; ++ empty_slot &= BGMAC_DMA_TX_STATDPTR; + empty_slot /= sizeof(struct bgmac_dma_desc); + + while (ring->start != empty_slot) { +@@ -279,6 +282,8 @@ static int bgmac_dma_rx_read(struct bgma + + end_slot = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_STATUS); + end_slot &= BGMAC_DMA_RX_STATDPTR; ++ end_slot -= ring->index_base; ++ end_slot &= BGMAC_DMA_RX_STATDPTR; + end_slot /= sizeof(struct bgmac_dma_desc); + + ring->end = end_slot; +@@ -423,9 +428,6 @@ static int bgmac_dma_alloc(struct bgmac + ring = &bgmac->tx_ring[i]; + ring->num_slots = BGMAC_TX_RING_SLOTS; + ring->mmio_base = ring_base[i]; +- if (bgmac_dma_unaligned(bgmac, ring, BGMAC_DMA_RING_TX)) +- bgmac_warn(bgmac, "TX on ring 0x%X supports unaligned addressing but this feature is not implemented\n", +- ring->mmio_base); + + /* Alloc ring of descriptors */ + size = ring->num_slots * sizeof(struct bgmac_dma_desc); +@@ -440,6 +442,13 @@ static int bgmac_dma_alloc(struct bgmac + if (ring->dma_base & 0xC0000000) + bgmac_warn(bgmac, "DMA address using 0xC0000000 bit(s), it may need translation trick\n"); + ++ ring->unaligned = bgmac_dma_unaligned(bgmac, ring, ++ BGMAC_DMA_RING_TX); ++ if (ring->unaligned) ++ ring->index_base = lower_32_bits(ring->dma_base); ++ else ++ ring->index_base = 0; ++ + /* No need to alloc TX slots yet */ + } + +@@ -449,9 +458,6 @@ static int bgmac_dma_alloc(struct bgmac + ring = &bgmac->rx_ring[i]; + ring->num_slots = BGMAC_RX_RING_SLOTS; + ring->mmio_base = ring_base[i]; +- if (bgmac_dma_unaligned(bgmac, ring, BGMAC_DMA_RING_RX)) +- bgmac_warn(bgmac, "RX on ring 0x%X supports unaligned addressing but this feature is not implemented\n", +- ring->mmio_base); + + /* Alloc ring of descriptors */ + size = ring->num_slots * sizeof(struct bgmac_dma_desc); +@@ -467,6 +473,13 @@ static int bgmac_dma_alloc(struct bgmac + if (ring->dma_base & 0xC0000000) + bgmac_warn(bgmac, "DMA address using 0xC0000000 bit(s), it may need translation trick\n"); + ++ ring->unaligned = bgmac_dma_unaligned(bgmac, ring, ++ BGMAC_DMA_RING_RX); ++ if (ring->unaligned) ++ ring->index_base = lower_32_bits(ring->dma_base); ++ else ++ ring->index_base = 0; ++ + /* Alloc RX slots */ + for (j = 0; j < ring->num_slots; j++) { + err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]); +@@ -494,12 +507,14 @@ static void bgmac_dma_init(struct bgmac + for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) { + ring = &bgmac->tx_ring[i]; + +- /* We don't implement unaligned addressing, so enable first */ +- bgmac_dma_tx_enable(bgmac, ring); ++ if (!ring->unaligned) ++ bgmac_dma_tx_enable(bgmac, ring); + bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGLO, + lower_32_bits(ring->dma_base)); + bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGHI, + upper_32_bits(ring->dma_base)); ++ if (ring->unaligned) ++ bgmac_dma_tx_enable(bgmac, ring); + + ring->start = 0; + ring->end = 0; /* Points the slot that should *not* be read */ +@@ -510,12 +525,14 @@ static void bgmac_dma_init(struct bgmac + + ring = &bgmac->rx_ring[i]; + +- /* We don't implement unaligned addressing, so enable first */ +- bgmac_dma_rx_enable(bgmac, ring); ++ if (!ring->unaligned) ++ bgmac_dma_rx_enable(bgmac, ring); + bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGLO, + lower_32_bits(ring->dma_base)); + bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGHI, + upper_32_bits(ring->dma_base)); ++ if (ring->unaligned) ++ bgmac_dma_rx_enable(bgmac, ring); + + for (j = 0, dma_desc = ring->cpu_base; j < ring->num_slots; + j++, dma_desc++) { +@@ -536,6 +553,7 @@ static void bgmac_dma_init(struct bgmac + } + + bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX, ++ ring->index_base + + ring->num_slots * sizeof(struct bgmac_dma_desc)); + + ring->start = 0; +--- a/drivers/net/ethernet/broadcom/bgmac.h ++++ b/drivers/net/ethernet/broadcom/bgmac.h +@@ -386,6 +386,8 @@ struct bgmac_dma_ring { + u16 mmio_base; + struct bgmac_dma_desc *cpu_base; + dma_addr_t dma_base; ++ u32 index_base; /* Used for unaligned rings only, otherwise 0 */ ++ bool unaligned; + + struct bgmac_slot_info slots[BGMAC_RX_RING_SLOTS]; + }; diff --git a/target/linux/bcm53xx/patches-3.10/213-bgmac-add-support-for-Byte-Queue-Limits.patch b/target/linux/bcm53xx/patches-3.10/213-bgmac-add-support-for-Byte-Queue-Limits.patch new file mode 100644 index 0000000000..440461ae1e --- /dev/null +++ b/target/linux/bcm53xx/patches-3.10/213-bgmac-add-support-for-Byte-Queue-Limits.patch @@ -0,0 +1,50 @@ +From: Hauke Mehrtens +bgmac: add support for Byte Queue Limits + +--- a/drivers/net/ethernet/broadcom/bgmac.c ++++ b/drivers/net/ethernet/broadcom/bgmac.c +@@ -183,6 +183,7 @@ static void bgmac_dma_tx_free(struct bgm + struct device *dma_dev = bgmac->core->dma_dev; + int empty_slot; + bool freed = false; ++ unsigned bytes_compl = 0, pkts_compl = 0; + + /* The last slot that hardware didn't consume yet */ + empty_slot = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_STATUS); +@@ -200,6 +201,9 @@ static void bgmac_dma_tx_free(struct bgm + slot->skb->len, DMA_TO_DEVICE); + slot->dma_addr = 0; + ++ bytes_compl += slot->skb->len; ++ pkts_compl++; ++ + /* Free memory! :) */ + dev_kfree_skb(slot->skb); + slot->skb = NULL; +@@ -213,6 +217,8 @@ static void bgmac_dma_tx_free(struct bgm + freed = true; + } + ++ netdev_completed_queue(bgmac->net_dev, pkts_compl, bytes_compl); ++ + if (freed && netif_queue_stopped(bgmac->net_dev)) + netif_wake_queue(bgmac->net_dev); + } +@@ -1013,6 +1019,8 @@ static void bgmac_chip_reset(struct bgma + bgmac_set(bgmac, BGMAC_PHY_CNTL, BGMAC_PC_MTE); + bgmac_miiconfig(bgmac); + bgmac_phy_init(bgmac); ++ ++ netdev_reset_queue(bgmac->net_dev); + + bgmac->int_status = 0; + } +@@ -1227,6 +1235,8 @@ static netdev_tx_t bgmac_start_xmit(stru + struct bgmac *bgmac = netdev_priv(net_dev); + struct bgmac_dma_ring *ring; + ++ netdev_sent_queue(net_dev, skb->len); ++ + /* No QOS support yet */ + ring = &bgmac->tx_ring[0]; + return bgmac_dma_tx_add(bgmac, ring, skb);