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
This commit is contained in:
parent
c75a970337
commit
0bdc137636
6 changed files with 259 additions and 48 deletions
|
@ -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.
|
|
@ -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
|
||||
|
@ -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,8 +177,7 @@ 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",
|
||||
+ netdev_info(net_dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s)\n",
|
||||
+ phydev->drv->name, dev_name(&phydev->dev));
|
||||
+
|
||||
+ return 0;
|
||||
|
|
|
@ -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
|
|
@ -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);
|
|
@ -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];
|
||||
};
|
|
@ -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);
|
Loading…
Reference in a new issue