bcm53xx: update bgmac driver

Update the bgmac driver with the patches already used for bcm47xx target.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>

SVN-Revision: 38199
owl
Hauke Mehrtens 2013-09-25 21:47:25 +00:00
parent c75a970337
commit 0bdc137636
6 changed files with 259 additions and 48 deletions

View File

@ -1,19 +0,0 @@
bgmac: add dependency to phylib
bgmac is using functions from phylib, add the dependency.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
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.

View File

@ -1,11 +1,13 @@
bgmac: register phy
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
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 <hauke@hauke-m.de>
- 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 <hauke@hauke-m.de>
}
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 <hauke@hauke-m.de>
}
-#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 <hauke@hauke-m.de>
+ 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 <hauke@hauke-m.de>
.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 <hauke@hauke-m.de>
+{
+ 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 <hauke@hauke-m.de>
+ 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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
+ 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 <hauke@hauke-m.de>
+ 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;

View File

@ -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 <zajec5@gmail.com>
--- 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

View File

@ -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);

View File

@ -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 <zajec5@gmail.com>
--- 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];
};

View File

@ -0,0 +1,50 @@
From: Hauke Mehrtens <hauke@hauke-m.de>
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);