From f5fbf115691c350f88bae103f629503e201a7bff Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 29 Oct 2014 17:07:50 -0700 Subject: bnx2x: use napi_schedule_irqoff() bnx2x_msix_fp_int() and bnx2x_interrupt() run from hard interrupt context. They can use napi_schedule_irqoff() instead of napi_schedule() Signed-off-by: Eric Dumazet Cc: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 2 +- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 40beef5..e9af4af 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1139,7 +1139,7 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie) prefetch(fp->txdata_ptr[cos]->tx_cons_sb); prefetch(&fp->sb_running_index[SM_RX_ID]); - napi_schedule(&bnx2x_fp(bp, fp->index, napi)); + napi_schedule_irqoff(&bnx2x_fp(bp, fp->index, napi)); return IRQ_HANDLED; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 74fbf9e..c4bd025 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -1931,7 +1931,7 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) for_each_cos_in_tx_queue(fp, cos) prefetch(fp->txdata_ptr[cos]->tx_cons_sb); prefetch(&fp->sb_running_index[SM_RX_ID]); - napi_schedule(&bnx2x_fp(bp, fp->index, napi)); + napi_schedule_irqoff(&bnx2x_fp(bp, fp->index, napi)); status &= ~mask; } } -- cgit v1.1 From 9dfa9a27b620640322588df399eb8f624b48d877 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 12 Nov 2014 15:40:43 -0800 Subject: net: systemport: fix tx work done in TX napi poll With commit d75b1ade567 ("net: less interrupt masking in NAPI") napi repoll is done only when work_done == budget. bcm_sysport_tx_poll() always returns 0 whether or not we completed the poll quantum. Fix this by returning either 0 when we did complete the TX ring reclaim, or budget to trigger a repoll. Fixes: d75b1ade567 ("net: less interrupt masking in NAPI") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bcmsysport.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 531bb7c..3cb2411 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -731,9 +731,11 @@ static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget) napi_complete(napi); /* re-enable TX interrupt */ intrl2_1_mask_clear(ring->priv, BIT(ring->index)); + + return 0; } - return 0; + return budget; } static void bcm_sysport_tx_reclaim_all(struct bcm_sysport_priv *priv) -- cgit v1.1 From e3ec69ca80a202f3a685c50daa18b63fbafcc536 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 16 Nov 2014 06:23:07 -0800 Subject: bnx2x: use netdev_rss_key_fill() helper Use netdev_rss_key_fill() helper, as it provides better support for some bonding setups. Signed-off-by: Eric Dumazet Cc: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index e9af4af..b4d71fd 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -2099,7 +2099,7 @@ int bnx2x_rss(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj, if (config_hash) { /* RSS keys */ - prandom_bytes(params.rss_key, T_ETH_RSS_KEY * 4); + netdev_rss_key_fill(params.rss_key, T_ETH_RSS_KEY * 4); __set_bit(BNX2X_RSS_SET_SRCH, ¶ms.rss_flags); } -- cgit v1.1 From 3964835644091b57cf24c33ea95de4b5a26a5b1f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 16 Nov 2014 06:23:08 -0800 Subject: tg3: use netdev_rss_key_fill() helper Use of well known RSS key increases attack surface. Switch to a random one, using generic helper so that all ports share a common key. Signed-off-by: Eric Dumazet Cc: Prashant Sreedharan Cc: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index dbb41c1..2dc0015 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -10540,19 +10540,14 @@ static int tg3_reset_hw(struct tg3 *tp, bool reset_phy) udelay(100); if (tg3_flag(tp, ENABLE_RSS)) { + u32 rss_key[10]; + tg3_rss_write_indir_tbl(tp); - /* Setup the "secret" hash key. */ - tw32(MAC_RSS_HASH_KEY_0, 0x5f865437); - tw32(MAC_RSS_HASH_KEY_1, 0xe4ac62cc); - tw32(MAC_RSS_HASH_KEY_2, 0x50103a45); - tw32(MAC_RSS_HASH_KEY_3, 0x36621985); - tw32(MAC_RSS_HASH_KEY_4, 0xbf14c0e8); - tw32(MAC_RSS_HASH_KEY_5, 0x1bc27a1e); - tw32(MAC_RSS_HASH_KEY_6, 0x84f4b556); - tw32(MAC_RSS_HASH_KEY_7, 0x094ea6fe); - tw32(MAC_RSS_HASH_KEY_8, 0x7dda01e7); - tw32(MAC_RSS_HASH_KEY_9, 0xc04d7481); + netdev_rss_key_fill(rss_key, 10 * sizeof(u32)); + + for (i = 0; i < 10 ; i++) + tw32(MAC_RSS_HASH_KEY_0 + i*4, rss_key[i]); } tp->rx_mode = RX_MODE_ENABLE; -- cgit v1.1 From 60b4ea1781fd862e9222d082af79a5770440d390 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 19 Nov 2014 10:29:55 -0800 Subject: net: systemport: log RX buffer allocation and RX/TX DMA failures To help troubleshoot heavy memory pressure conditions, add a bunch of statistics counter to log RX buffer allocation and RX/TX DMA mapping failures. These are reported like any other counters through the ethtool stats interface. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bcmsysport.c | 10 +++++++++- drivers/net/ethernet/broadcom/bcmsysport.h | 3 +++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 3cb2411..c1d2559 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -274,6 +274,9 @@ static const struct bcm_sysport_stats bcm_sysport_gstrings_stats[] = { /* RBUF misc statistics */ STAT_RBUF("rbuf_ovflow_cnt", mib.rbuf_ovflow_cnt, RBUF_OVFL_DISC_CNTR), STAT_RBUF("rbuf_err_cnt", mib.rbuf_err_cnt, RBUF_ERR_PKT_CNTR), + STAT_MIB_RX("alloc_rx_buff_failed", mib.alloc_rx_buff_failed), + STAT_MIB_RX("rx_dma_failed", mib.rx_dma_failed), + STAT_MIB_TX("tx_dma_failed", mib.tx_dma_failed), }; #define BCM_SYSPORT_STATS_LEN ARRAY_SIZE(bcm_sysport_gstrings_stats) @@ -477,6 +480,7 @@ static int bcm_sysport_rx_refill(struct bcm_sysport_priv *priv, RX_BUF_LENGTH, DMA_FROM_DEVICE); ret = dma_mapping_error(kdev, mapping); if (ret) { + priv->mib.rx_dma_failed++; bcm_sysport_free_cb(cb); netif_err(priv, rx_err, ndev, "DMA mapping failure\n"); return ret; @@ -526,6 +530,7 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, unsigned int p_index; u16 len, status; struct bcm_rsb *rsb; + int ret; /* Determine how much we should process since last call */ p_index = rdma_readl(priv, RDMA_PROD_INDEX); @@ -620,7 +625,9 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, napi_gro_receive(&priv->napi, skb); refill: - bcm_sysport_rx_refill(priv, cb); + ret = bcm_sysport_rx_refill(priv, cb); + if (ret) + priv->mib.alloc_rx_buff_failed++; } return processed; @@ -973,6 +980,7 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb, mapping = dma_map_single(kdev, skb->data, skb_len, DMA_TO_DEVICE); if (dma_mapping_error(kdev, mapping)) { + priv->mib.tx_dma_failed++; netif_err(priv, tx_err, dev, "DMA map failed at %p (len=%d)\n", skb->data, skb_len); ret = NETDEV_TX_OK; diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h index b08dab8..fc19417 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.h +++ b/drivers/net/ethernet/broadcom/bcmsysport.h @@ -557,6 +557,9 @@ struct bcm_sysport_mib { u32 rxchk_other_pkt_disc; u32 rbuf_ovflow_cnt; u32 rbuf_err_cnt; + u32 alloc_rx_buff_failed; + u32 rx_dma_failed; + u32 tx_dma_failed; }; /* HW maintains a large list of counters */ -- cgit v1.1 From 44c8bc3ce39f4cbeb7bf13162666fb6d0aad864d Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 19 Nov 2014 10:29:56 -0800 Subject: net: bcmgenet: log RX buffer allocation and RX/TX dma failures To help troubleshoot heavy memory pressure conditions, add a bunch of statistics counter to log RX buffer allocation and RX/TX DMA mapping failures. These are reported like any other counters through the ethtool stats interface. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 10 +++++++++- drivers/net/ethernet/broadcom/genet/bcmgenet.h | 3 +++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index da1a250..fcbf125 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -613,6 +613,9 @@ static const struct bcmgenet_stats bcmgenet_gstrings_stats[] = { UMAC_RBUF_OVFL_CNT), STAT_GENET_MISC("rbuf_err_cnt", mib.rbuf_err_cnt, UMAC_RBUF_ERR_CNT), STAT_GENET_MISC("mdf_err_cnt", mib.mdf_err_cnt, UMAC_MDF_ERR_CNT), + STAT_GENET_MIB_RX("alloc_rx_buff_failed", mib.alloc_rx_buff_failed), + STAT_GENET_MIB_RX("rx_dma_failed", mib.rx_dma_failed), + STAT_GENET_MIB_TX("tx_dma_failed", mib.tx_dma_failed), }; #define BCMGENET_STATS_LEN ARRAY_SIZE(bcmgenet_gstrings_stats) @@ -989,6 +992,7 @@ static int bcmgenet_xmit_single(struct net_device *dev, mapping = dma_map_single(kdev, skb->data, skb_len, DMA_TO_DEVICE); ret = dma_mapping_error(kdev, mapping); if (ret) { + priv->mib.tx_dma_failed++; netif_err(priv, tx_err, dev, "Tx DMA map failed\n"); dev_kfree_skb(skb); return ret; @@ -1035,6 +1039,7 @@ static int bcmgenet_xmit_frag(struct net_device *dev, skb_frag_size(frag), DMA_TO_DEVICE); ret = dma_mapping_error(kdev, mapping); if (ret) { + priv->mib.tx_dma_failed++; netif_err(priv, tx_err, dev, "%s: Tx DMA map failed\n", __func__); return ret; @@ -1231,6 +1236,7 @@ static int bcmgenet_rx_refill(struct bcmgenet_priv *priv, struct enet_cb *cb) priv->rx_buf_len, DMA_FROM_DEVICE); ret = dma_mapping_error(kdev, mapping); if (ret) { + priv->mib.rx_dma_failed++; bcmgenet_free_cb(cb); netif_err(priv, rx_err, priv->dev, "%s DMA map failed\n", __func__); @@ -1397,8 +1403,10 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv, /* refill RX path on the current control block */ refill: err = bcmgenet_rx_refill(priv, cb); - if (err) + if (err) { + priv->mib.alloc_rx_buff_failed++; netif_err(priv, rx_err, dev, "Rx refill failed\n"); + } rxpktprocessed++; priv->rx_read_ptr++; diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index 31b2da5..c4ca728 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -143,6 +143,9 @@ struct bcmgenet_mib_counters { u32 rbuf_ovflow_cnt; u32 rbuf_err_cnt; u32 mdf_err_cnt; + u32 alloc_rx_buff_failed; + u32 rx_dma_failed; + u32 tx_dma_failed; }; #define UMAC_HD_BKP_CTRL 0x004 -- cgit v1.1 From d0a6db8dd05da6d65ac1ba111da911de6a34d76a Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 25 Nov 2014 21:16:34 -0800 Subject: net: bcmgenet: add register definitions for EEE Add register definitions to control EEE in the UniMAC, RBUF and TBUF register ranges. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index c4ca728..ea6f0ab 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -185,6 +185,21 @@ struct bcmgenet_mib_counters { #define UMAC_MAC1 0x010 #define UMAC_MAX_FRAME_LEN 0x014 +#define UMAC_EEE_CTRL 0x064 +#define EN_LPI_RX_PAUSE (1 << 0) +#define EN_LPI_TX_PFC (1 << 1) +#define EN_LPI_TX_PAUSE (1 << 2) +#define EEE_EN (1 << 3) +#define RX_FIFO_CHECK (1 << 4) +#define EEE_TX_CLK_DIS (1 << 5) +#define DIS_EEE_10M (1 << 6) +#define LP_IDLE_PREDICTION_MODE (1 << 7) + +#define UMAC_EEE_LPI_TIMER 0x068 +#define UMAC_EEE_WAKE_TIMER 0x06C +#define UMAC_EEE_REF_COUNT 0x070 +#define EEE_REFERENCE_COUNT_MASK 0xffff + #define UMAC_TX_FLUSH 0x334 #define UMAC_MIB_START 0x400 @@ -232,6 +247,10 @@ struct bcmgenet_mib_counters { #define RBUF_RXCHK_EN (1 << 0) #define RBUF_SKIP_FCS (1 << 4) +#define RBUF_ENERGY_CTRL 0x9c +#define RBUF_EEE_EN (1 << 0) +#define RBUF_PM_EN (1 << 1) + #define RBUF_TBUF_SIZE_CTRL 0xb4 #define RBUF_HFB_CTRL_V1 0x38 @@ -247,6 +266,9 @@ struct bcmgenet_mib_counters { #define TBUF_CTRL 0x00 #define TBUF_BP_MC 0x0C +#define TBUF_ENERGY_CTRL 0x14 +#define TBUF_EEE_EN (1 << 0) +#define TBUF_PM_EN (1 << 1) #define TBUF_CTRL_V1 0x80 #define TBUF_BP_MC_V1 0xA0 -- cgit v1.1 From 6ef398ea60d931b97d69ed080bd0bd00fac38ec6 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 25 Nov 2014 21:16:35 -0800 Subject: net: bcmgenet: add EEE support Allow enabling and disabling EEE using the designated ethtool getters and setters. GENET allows controlling EEE at the UniMAC, RBUF and TBUF levels. We also take care of restoring EEE after a suspend/resume cycle if it was enabled prior to suspending. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 96 ++++++++++++++++++++++++++ drivers/net/ethernet/broadcom/genet/bcmgenet.h | 4 ++ 2 files changed, 100 insertions(+) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index fcbf125..bf44e0e 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -714,6 +714,91 @@ static void bcmgenet_get_ethtool_stats(struct net_device *dev, } } +static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable) +{ + struct bcmgenet_priv *priv = netdev_priv(dev); + u32 off = priv->hw_params->tbuf_offset + TBUF_ENERGY_CTRL; + u32 reg; + + if (enable && !priv->clk_eee_enabled) { + clk_prepare_enable(priv->clk_eee); + priv->clk_eee_enabled = true; + } + + reg = bcmgenet_umac_readl(priv, UMAC_EEE_CTRL); + if (enable) + reg |= EEE_EN; + else + reg &= ~EEE_EN; + bcmgenet_umac_writel(priv, reg, UMAC_EEE_CTRL); + + /* Enable EEE and switch to a 27Mhz clock automatically */ + reg = __raw_readl(priv->base + off); + if (enable) + reg |= TBUF_EEE_EN | TBUF_PM_EN; + else + reg &= ~(TBUF_EEE_EN | TBUF_PM_EN); + __raw_writel(reg, priv->base + off); + + /* Do the same for thing for RBUF */ + reg = bcmgenet_rbuf_readl(priv, RBUF_ENERGY_CTRL); + if (enable) + reg |= RBUF_EEE_EN | RBUF_PM_EN; + else + reg &= ~(RBUF_EEE_EN | RBUF_PM_EN); + bcmgenet_rbuf_writel(priv, reg, RBUF_ENERGY_CTRL); + + if (!enable && priv->clk_eee_enabled) { + clk_disable_unprepare(priv->clk_eee); + priv->clk_eee_enabled = false; + } + + priv->eee.eee_enabled = enable; + priv->eee.eee_active = enable; +} + +static int bcmgenet_get_eee(struct net_device *dev, struct ethtool_eee *e) +{ + struct bcmgenet_priv *priv = netdev_priv(dev); + struct ethtool_eee *p = &priv->eee; + + if (GENET_IS_V1(priv)) + return -EOPNOTSUPP; + + e->eee_enabled = p->eee_enabled; + e->eee_active = p->eee_active; + e->tx_lpi_timer = bcmgenet_umac_readl(priv, UMAC_EEE_LPI_TIMER); + + return phy_ethtool_get_eee(priv->phydev, e); +} + +static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e) +{ + struct bcmgenet_priv *priv = netdev_priv(dev); + struct ethtool_eee *p = &priv->eee; + int ret = 0; + + if (GENET_IS_V1(priv)) + return -EOPNOTSUPP; + + p->eee_enabled = e->eee_enabled; + + if (!p->eee_enabled) { + bcmgenet_eee_enable_set(dev, false); + } else { + ret = phy_init_eee(priv->phydev, 0); + if (ret) { + netif_err(priv, hw, dev, "EEE initialization failed\n"); + return ret; + } + + bcmgenet_umac_writel(priv, e->tx_lpi_timer, UMAC_EEE_LPI_TIMER); + bcmgenet_eee_enable_set(dev, true); + } + + return phy_ethtool_set_eee(priv->phydev, e); +} + /* standard ethtool support functions. */ static struct ethtool_ops bcmgenet_ethtool_ops = { .get_strings = bcmgenet_get_strings, @@ -727,6 +812,8 @@ static struct ethtool_ops bcmgenet_ethtool_ops = { .set_msglevel = bcmgenet_set_msglevel, .get_wol = bcmgenet_get_wol, .set_wol = bcmgenet_set_wol, + .get_eee = bcmgenet_get_eee, + .set_eee = bcmgenet_set_eee, }; /* Power down the unimac, based on mode. */ @@ -2585,6 +2672,12 @@ static int bcmgenet_probe(struct platform_device *pdev) if (IS_ERR(priv->clk_wol)) dev_warn(&priv->pdev->dev, "failed to get enet-wol clock\n"); + priv->clk_eee = devm_clk_get(&priv->pdev->dev, "enet-eee"); + if (IS_ERR(priv->clk_eee)) { + dev_warn(&priv->pdev->dev, "failed to get enet-eee clock\n"); + priv->clk_eee = NULL; + } + err = reset_umac(priv); if (err) goto err_clk_disable; @@ -2735,6 +2828,9 @@ static int bcmgenet_resume(struct device *d) phy_resume(priv->phydev); + if (priv->eee.eee_enabled) + bcmgenet_eee_enable_set(dev, true); + bcmgenet_netif_start(dev); return 0; diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index ea6f0ab..b36ddec 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -573,6 +573,8 @@ struct bcmgenet_priv { struct device_node *phy_dn; struct mii_bus *mii_bus; u16 gphy_rev; + struct clk *clk_eee; + bool clk_eee_enabled; /* PHY device variables */ int old_link; @@ -609,6 +611,8 @@ struct bcmgenet_priv { u32 wolopts; struct bcmgenet_mib_counters mib; + + struct ethtool_eee eee; }; #define GENET_IO_MACRO(name, offset) \ -- cgit v1.1 From 6b0c54060ecb678473d442bba01fcb2b3079f594 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 25 Nov 2014 21:16:36 -0800 Subject: net: bcmgenet: support restarting auto-negotiation Hook a nway_reset ethtool callback to allow restarting the auto-negotiation process when asked to. We defer to the PHY library call to do the heavy lifting. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index bf44e0e..f2fadb0 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -799,6 +799,13 @@ static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e) return phy_ethtool_set_eee(priv->phydev, e); } +static int bcmgenet_nway_reset(struct net_device *dev) +{ + struct bcmgenet_priv *priv = netdev_priv(dev); + + return genphy_restart_aneg(priv->phydev); +} + /* standard ethtool support functions. */ static struct ethtool_ops bcmgenet_ethtool_ops = { .get_strings = bcmgenet_get_strings, @@ -814,6 +821,7 @@ static struct ethtool_ops bcmgenet_ethtool_ops = { .set_wol = bcmgenet_set_wol, .get_eee = bcmgenet_get_eee, .set_eee = bcmgenet_set_eee, + .nway_reset = bcmgenet_nway_reset, }; /* Power down the unimac, based on mode. */ -- cgit v1.1 From 02637fce3e0103ba086b9c33b6d529e69460e4b6 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 28 Nov 2014 14:34:16 +0100 Subject: net: rename netdev_phys_port_id to more generic name So this can be reused for identification of other "items" as well. Signed-off-by: Jiri Pirko Reviewed-by: Thomas Graf Acked-by: John Fastabend Acked-by: Andy Gospodarek Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index c4bd025..336ef3c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -12537,7 +12537,7 @@ static int bnx2x_validate_addr(struct net_device *dev) } static int bnx2x_get_phys_port_id(struct net_device *netdev, - struct netdev_phys_port_id *ppid) + struct netdev_phys_item_id *ppid) { struct bnx2x *bp = netdev_priv(netdev); -- cgit v1.1 From 5580373fb27706f07be3375c304558980eb90c4e Mon Sep 17 00:00:00 2001 From: Andrey Skvortsov Date: Thu, 4 Dec 2014 11:32:46 -0500 Subject: SSB / B44: fix WOL for BCM4401 Wake On Lan was not working on laptop DELL Vostro 1500. If WOL was turned on, BCM4401 was powered up in suspend mode. LEDs blinked. But the laptop could not be woken up with the Magic Packet. The reason for that was that PCIE was not enabled as a system wakeup source and therefore the host PCI bridge was not powered up in suspend mode. PCIE was not enabled in suspend by PM because no child devices were registered as wakeup source during suspend process. On laptop BCM4401 is connected through the SSB bus, that is connected to the PCI-Express bus. SSB and B44 did not use standard PM wakeup functions and did not forward wakeup settings to their parents. To fix that B44 driver enables PM wakeup and registers new wakeup source using device_set_wakeup_enable(). Wakeup is automatically reported to the parent SSB bus via power.wakeup_path. SSB bus enables wakeup for the parent PCI bridge, if there is any child devices with enabled wakeup functionality. All other steps are done by PM core code. Signed-off-by: Andrey Skvortsov Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/ethernet/broadcom/b44.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index 416620f..ffeaf47 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -2104,6 +2104,7 @@ static int b44_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) bp->flags &= ~B44_FLAG_WOL_ENABLE; spin_unlock_irq(&bp->lock); + device_set_wakeup_enable(bp->sdev->dev, wol->wolopts & WAKE_MAGIC); return 0; } @@ -2452,6 +2453,7 @@ static int b44_init_one(struct ssb_device *sdev, } } + device_set_wakeup_capable(sdev->dev, true); netdev_info(dev, "%s %pM\n", DRV_DESCRIPTION, dev->dev_addr); return 0; -- cgit v1.1 From b0ba512e25d729a43858ad1f6cb8b94dbb95dbeb Mon Sep 17 00:00:00 2001 From: Petri Gynther Date: Mon, 1 Dec 2014 16:18:08 -0800 Subject: net: bcmgenet: enable driver to work without a device tree Modify bcmgenet driver so that it can be used on Broadcom 7xxx MIPS-based STB platforms without a device tree. Signed-off-by: Petri Gynther Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/Kconfig | 1 - drivers/net/ethernet/broadcom/genet/bcmgenet.c | 31 ++++-- drivers/net/ethernet/broadcom/genet/bcmmii.c | 126 ++++++++++++++++++++----- 3 files changed, 125 insertions(+), 33 deletions(-) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index c3e260c..888247a 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -62,7 +62,6 @@ config BCM63XX_ENET config BCMGENET tristate "Broadcom GENET internal MAC support" - depends on OF select MII select PHYLIB select FIXED_PHY if BCMGENET=y diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index f2fadb0..adfef5c 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -42,6 +42,7 @@ #include #include #include +#include #include @@ -2586,8 +2587,9 @@ static const struct of_device_id bcmgenet_match[] = { static int bcmgenet_probe(struct platform_device *pdev) { + struct bcmgenet_platform_data *pd = pdev->dev.platform_data; struct device_node *dn = pdev->dev.of_node; - const struct of_device_id *of_id; + const struct of_device_id *of_id = NULL; struct bcmgenet_priv *priv; struct net_device *dev; const void *macaddr; @@ -2601,9 +2603,11 @@ static int bcmgenet_probe(struct platform_device *pdev) return -ENOMEM; } - of_id = of_match_node(bcmgenet_match, dn); - if (!of_id) - return -EINVAL; + if (dn) { + of_id = of_match_node(bcmgenet_match, dn); + if (!of_id) + return -EINVAL; + } priv = netdev_priv(dev); priv->irq0 = platform_get_irq(pdev, 0); @@ -2615,11 +2619,15 @@ static int bcmgenet_probe(struct platform_device *pdev) goto err; } - macaddr = of_get_mac_address(dn); - if (!macaddr) { - dev_err(&pdev->dev, "can't find MAC address\n"); - err = -EINVAL; - goto err; + if (dn) { + macaddr = of_get_mac_address(dn); + if (!macaddr) { + dev_err(&pdev->dev, "can't find MAC address\n"); + err = -EINVAL; + goto err; + } + } else { + macaddr = pd->mac_address; } r = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -2659,7 +2667,10 @@ static int bcmgenet_probe(struct platform_device *pdev) priv->dev = dev; priv->pdev = pdev; - priv->version = (enum bcmgenet_version)of_id->data; + if (of_id) + priv->version = (enum bcmgenet_version)of_id->data; + else + priv->version = pd->genet_version; priv->clk = devm_clk_get(&priv->pdev->dev, "enet"); if (IS_ERR(priv->clk)) diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index 933cd7e..446889c 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "bcmgenet.h" @@ -312,22 +313,6 @@ static int bcmgenet_mii_probe(struct net_device *dev) u32 phy_flags; int ret; - if (priv->phydev) { - pr_info("PHY already attached\n"); - return 0; - } - - /* In the case of a fixed PHY, the DT node associated - * to the PHY is the Ethernet MAC DT node. - */ - if (!priv->phy_dn && of_phy_is_fixed_link(dn)) { - ret = of_phy_register_fixed_link(dn); - if (ret) - return ret; - - priv->phy_dn = of_node_get(dn); - } - /* Communicate the integrated PHY revision */ phy_flags = priv->gphy_rev; @@ -337,11 +322,39 @@ static int bcmgenet_mii_probe(struct net_device *dev) priv->old_duplex = -1; priv->old_pause = -1; - phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup, - phy_flags, priv->phy_interface); - if (!phydev) { - pr_err("could not attach to PHY\n"); - return -ENODEV; + if (dn) { + if (priv->phydev) { + pr_info("PHY already attached\n"); + return 0; + } + + /* In the case of a fixed PHY, the DT node associated + * to the PHY is the Ethernet MAC DT node. + */ + if (!priv->phy_dn && of_phy_is_fixed_link(dn)) { + ret = of_phy_register_fixed_link(dn); + if (ret) + return ret; + + priv->phy_dn = of_node_get(dn); + } + + phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup, + phy_flags, priv->phy_interface); + if (!phydev) { + pr_err("could not attach to PHY\n"); + return -ENODEV; + } + } else { + phydev = priv->phydev; + phydev->dev_flags = phy_flags; + + ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup, + priv->phy_interface); + if (ret) { + pr_err("could not attach to PHY\n"); + return -ENODEV; + } } priv->phydev = phydev; @@ -438,6 +451,75 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv) return 0; } +static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv) +{ + struct device *kdev = &priv->pdev->dev; + struct bcmgenet_platform_data *pd = kdev->platform_data; + struct mii_bus *mdio = priv->mii_bus; + struct phy_device *phydev; + int ret; + + if (pd->phy_interface != PHY_INTERFACE_MODE_MOCA && pd->mdio_enabled) { + /* + * Internal or external PHY with MDIO access + */ + if (pd->phy_address >= 0 && pd->phy_address < PHY_MAX_ADDR) + mdio->phy_mask = ~(1 << pd->phy_address); + else + mdio->phy_mask = 0; + + ret = mdiobus_register(mdio); + if (ret) { + dev_err(kdev, "failed to register MDIO bus\n"); + return ret; + } + + if (pd->phy_address >= 0 && pd->phy_address < PHY_MAX_ADDR) + phydev = mdio->phy_map[pd->phy_address]; + else + phydev = phy_find_first(mdio); + + if (!phydev) { + dev_err(kdev, "failed to register PHY device\n"); + mdiobus_unregister(mdio); + return -ENODEV; + } + } else { + /* + * MoCA port or no MDIO access. + * Use fixed PHY to represent the link layer. + */ + struct fixed_phy_status fphy_status = { + .link = 1, + .speed = pd->phy_speed, + .duplex = pd->phy_duplex, + .pause = 0, + .asym_pause = 0, + }; + + phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL); + if (!phydev || IS_ERR(phydev)) { + dev_err(kdev, "failed to register fixed PHY device\n"); + return -ENODEV; + } + } + + priv->phydev = phydev; + priv->phy_interface = pd->phy_interface; + + return 0; +} + +static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv) +{ + struct device_node *dn = priv->pdev->dev.of_node; + + if (dn) + return bcmgenet_mii_of_init(priv); + else + return bcmgenet_mii_pd_init(priv); +} + int bcmgenet_mii_init(struct net_device *dev) { struct bcmgenet_priv *priv = netdev_priv(dev); @@ -447,7 +529,7 @@ int bcmgenet_mii_init(struct net_device *dev) if (ret) return ret; - ret = bcmgenet_mii_of_init(priv); + ret = bcmgenet_mii_bus_init(priv); if (ret) goto out_free; -- cgit v1.1 From 892311f66f2411b813ca631009356891a0c2b0a1 Mon Sep 17 00:00:00 2001 From: Eyal Perry Date: Tue, 2 Dec 2014 18:12:10 +0200 Subject: ethtool: Support for configurable RSS hash function This patch extends the set/get_rxfh ethtool-options for getting or setting the RSS hash function. It modifies drivers implementation of set/get_rxfh accordingly. This change also delegates the responsibility of checking whether a modification to a certain RX flow hash parameter is supported to the driver implementation of set_rxfh. User-kernel API is done through the new hfunc bitmask field in the ethtool_rxfh struct. A bit set in the hfunc field is corresponding to an index in the new string-set ETH_SS_RSS_HASH_FUNCS. Got approval from most of the relevant driver maintainers that their driver is using Toeplitz, and for the few that didn't answered, also assumed it is Toeplitz. Cc: Tom Lendacky Cc: Ariel Elior Cc: Prashant Sreedharan Cc: Michael Chan Cc: Hariprasad S Cc: Sathya Perla Cc: Subbu Seetharaman Cc: Ajit Khaparde Cc: Jeff Kirsher Cc: Jesse Brandeburg Cc: Bruce Allan Cc: Carolyn Wyborny Cc: Don Skidmore Cc: Greg Rose Cc: Matthew Vick Cc: John Ronciak Cc: Mitch Williams Cc: Amir Vadai Cc: Solarflare linux maintainers Cc: Shradha Shah Cc: Shreyas Bhatewara Cc: "VMware, Inc." Cc: Ben Hutchings Signed-off-by: Eyal Perry Signed-off-by: Amir Vadai Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 20 ++++++++++++++++++-- drivers/net/ethernet/broadcom/tg3.c | 20 ++++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 1edc931..ffe4e00 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -3358,12 +3358,18 @@ static u32 bnx2x_get_rxfh_indir_size(struct net_device *dev) return T_ETH_INDIRECTION_TABLE_SIZE; } -static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key) +static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, + u8 *hfunc) { struct bnx2x *bp = netdev_priv(dev); u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0}; size_t i; + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; + if (!indir) + return 0; + /* Get the current configuration of the RSS indirection table */ bnx2x_get_rss_ind_table(&bp->rss_conf_obj, ind_table); @@ -3383,11 +3389,21 @@ static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key) } static int bnx2x_set_rxfh(struct net_device *dev, const u32 *indir, - const u8 *key) + const u8 *key, const u8 hfunc) { struct bnx2x *bp = netdev_priv(dev); size_t i; + /* We require at least one supported parameter to be changed and no + * change in any of the unsupported parameters + */ + if (key || + (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)) + return -EOPNOTSUPP; + + if (!indir) + return 0; + for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) { /* * The same as in bnx2x_get_rxfh: we can't use a memcpy() diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 43fd1b7..bb48a61 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -12561,22 +12561,38 @@ static u32 tg3_get_rxfh_indir_size(struct net_device *dev) return size; } -static int tg3_get_rxfh(struct net_device *dev, u32 *indir, u8 *key) +static int tg3_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc) { struct tg3 *tp = netdev_priv(dev); int i; + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; + if (!indir) + return 0; + for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) indir[i] = tp->rss_ind_tbl[i]; return 0; } -static int tg3_set_rxfh(struct net_device *dev, const u32 *indir, const u8 *key) +static int tg3_set_rxfh(struct net_device *dev, const u32 *indir, const u8 *key, + const u8 hfunc) { struct tg3 *tp = netdev_priv(dev); size_t i; + /* We require at least one supported parameter to be changed and no + * change in any of the unsupported parameters + */ + if (key || + (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)) + return -EOPNOTSUPP; + + if (!indir) + return 0; + for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) tp->rss_ind_tbl[i] = indir[i]; -- cgit v1.1 From b04a2f5b9ff5460a0bfbc97c9d6dd0017ad0cbe5 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 3 Dec 2014 09:56:59 -0800 Subject: net: bcmgenet: add support for new GENET PHY revision scheme Starting with GPHY revision G0, the GENET register layout has changed to use the same numbering scheme as the Starfighter 2 switch. This means that GPHY major revision is in bits 15:12, minor in bits 11:8 and patch level is in bits 7:4. Introduce a small heuristic which checks for the old scheme first, tests for the new scheme and finally attempts to catch reserved values and aborts. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index adfef5c..7078bd3 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -2504,6 +2504,7 @@ static void bcmgenet_set_hw_params(struct bcmgenet_priv *priv) struct bcmgenet_hw_params *params; u32 reg; u8 major; + u16 gphy_rev; if (GENET_IS_V4(priv)) { bcmgenet_dma_regs = bcmgenet_dma_regs_v3plus; @@ -2552,8 +2553,29 @@ static void bcmgenet_set_hw_params(struct bcmgenet_priv *priv) * to pass this information to the PHY driver. The PHY driver expects * to find the PHY major revision in bits 15:8 while the GENET register * stores that information in bits 7:0, account for that. + * + * On newer chips, starting with PHY revision G0, a new scheme is + * deployed similar to the Starfighter 2 switch with GPHY major + * revision in bits 15:8 and patch level in bits 7:0. Major revision 0 + * is reserved as well as special value 0x01ff, we have a small + * heuristic to check for the new GPHY revision and re-arrange things + * so the GPHY driver is happy. */ - priv->gphy_rev = (reg & 0xffff) << 8; + gphy_rev = reg & 0xffff; + + /* This is the good old scheme, just GPHY major, no minor nor patch */ + if ((gphy_rev & 0xf0) != 0) + priv->gphy_rev = gphy_rev << 8; + + /* This is the new scheme, GPHY major rolls over with 0x10 = rev G0 */ + else if ((gphy_rev & 0xff00) != 0) + priv->gphy_rev = gphy_rev; + + /* This is reserved so should require special treatment */ + else if (gphy_rev == 0 || gphy_rev == 0x01ff) { + pr_warn("Invalid GPHY revision detected: 0x%04x\n", gphy_rev); + return; + } #ifdef CONFIG_PHYS_ADDR_T_64BIT if (!(params->flags & GENET_HAS_40BITS)) -- cgit v1.1 From c9cdc74dfab260ebc37190bc359f99d83fc7104f Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 3 Dec 2014 14:15:20 +0200 Subject: bnx2x: Limit 1G link enforcement Change 1G-SFP module detection by verifying not only that it's not compliant with 10G-Ethernet, but also that it's 1G-ethernet compliant. Signed-off-by: Yaniv Rosner Signed-off-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 549549e..778e4cd 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -8119,10 +8119,11 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy, case SFP_EEPROM_CON_TYPE_VAL_LC: case SFP_EEPROM_CON_TYPE_VAL_RJ45: check_limiting_mode = 1; - if ((val[SFP_EEPROM_10G_COMP_CODE_ADDR] & + if (((val[SFP_EEPROM_10G_COMP_CODE_ADDR] & (SFP_EEPROM_10G_COMP_CODE_SR_MASK | SFP_EEPROM_10G_COMP_CODE_LR_MASK | - SFP_EEPROM_10G_COMP_CODE_LRM_MASK)) == 0) { + SFP_EEPROM_10G_COMP_CODE_LRM_MASK)) == 0) && + (val[SFP_EEPROM_1G_COMP_CODE_ADDR] != 0)) { DP(NETIF_MSG_LINK, "1G SFP module detected\n"); phy->media_type = ETH_PHY_SFP_1G_FIBER; if (phy->req_line_speed != SPEED_1000) { -- cgit v1.1 From 02dc4025a088ea7ff53fcb35ba9e0f295078a4a0 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Thu, 4 Dec 2014 12:52:06 +0200 Subject: bnx2x: Use correct fastpath version for VFs. Our FW can support several fastpath HSI [for backward compatibility] but up until now VFs were always configured to use latest fastpath HSI [although VF driver might be older and use an older fastpath HSI]. For linux drivers, the differences are insignificant since driver never utilized features that were overridden by the HSI change. But for VMs running other operating systems this might be a problem. In addition, eventually FW might change fastpath HSI in such a manner that backward compatibility WILL break unless configured with proper version. This patch fixes the issue for other operating system VMs, as well as lays the ground work for forward compatibility in regard to the fastpath HSI. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 2 + drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c | 2 +- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h | 2 + drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 1 + drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 2 + drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | 75 ++++++++++++++++++++++- drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h | 9 ++- 7 files changed, 88 insertions(+), 5 deletions(-) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 336ef3c..07c6368 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -3163,6 +3163,8 @@ static void bnx2x_pf_q_prep_general(struct bnx2x *bp, gen_init->mtu = bp->dev->mtu; gen_init->cos = cos; + + gen_init->fp_hsi = ETH_FP_HSI_VERSION; } static void bnx2x_pf_rx_q_prep(struct bnx2x *bp, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 7bc2924..07cdf9b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -4336,7 +4336,7 @@ static void bnx2x_q_fill_init_general_data(struct bnx2x *bp, test_bit(BNX2X_Q_FLG_FCOE, flags) ? LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW; - gen_data->fp_hsi_ver = ETH_FP_HSI_VERSION; + gen_data->fp_hsi_ver = params->fp_hsi; DP(BNX2X_MSG_SP, "flags: active %d, cos %d, stats en %d\n", gen_data->activate_flg, gen_data->cos, gen_data->statistics_en_flg); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h index e97275f..86baecb 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h @@ -937,6 +937,8 @@ struct bnx2x_general_setup_params { u8 spcl_id; u16 mtu; u8 cos; + + u8 fp_hsi; }; struct bnx2x_rxq_setup_params { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index c88b20a..e5aca2d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -193,6 +193,7 @@ void bnx2x_vfop_qctor_prep(struct bnx2x *bp, /* Setup-op general parameters */ setup_p->gen_params.spcl_id = vf->sp_cl_id; setup_p->gen_params.stat_id = vfq_stat_id(vf, q); + setup_p->gen_params.fp_hsi = vf->fp_hsi; /* Setup-op pause params: * Nothing to do, the pause thresholds are set by default to 0 which diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index 01bafa4..66ee62a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -205,6 +205,8 @@ struct bnx2x_virtf { /* slow-path operations */ struct mutex op_mutex; /* one vfop at a time mutex */ enum channel_tlvs op_current; + + u8 fp_hsi; }; #define BNX2X_NR_VIRTFN(bp) ((bp)->vfdb->sriov.nr_virtfn) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index b1d9c44..be40eab 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c @@ -224,6 +224,7 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count) struct vfpf_acquire_tlv *req = &bp->vf2pf_mbox->req.acquire; struct pfvf_acquire_resp_tlv *resp = &bp->vf2pf_mbox->resp.acquire_resp; struct vfpf_port_phys_id_resp_tlv *phys_port_resp; + struct vfpf_fp_hsi_resp_tlv *fp_hsi_resp; u32 vf_id; bool resources_acquired = false; @@ -237,6 +238,7 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count) req->vfdev_info.vf_id = vf_id; req->vfdev_info.vf_os = 0; + req->vfdev_info.fp_hsi_ver = ETH_FP_HSI_VERSION; req->resc_request.num_rxqs = rx_count; req->resc_request.num_txqs = tx_count; @@ -316,9 +318,14 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count) memset(&bp->vf2pf_mbox->resp, 0, sizeof(union pfvf_tlvs)); } else { - /* PF reports error */ - BNX2X_ERR("Failed to get the requested amount of resources: %d. Breaking...\n", - bp->acquire_resp.hdr.status); + /* Determine reason of PF failure of acquire process */ + fp_hsi_resp = bnx2x_search_tlv_list(bp, resp, + CHANNEL_TLV_FP_HSI_SUPPORT); + if (fp_hsi_resp && !fp_hsi_resp->is_supported) + BNX2X_ERR("Old hypervisor - doesn't support current fastpath HSI version; Need to downgrade VF driver [or upgrade hypervisor]\n"); + else + BNX2X_ERR("Failed to get the requested amount of resources: %d. Breaking...\n", + bp->acquire_resp.hdr.status); rc = -EAGAIN; goto out; } @@ -333,6 +340,25 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count) bp->flags |= HAS_PHYS_PORT_ID; } + /* Old Hypevisors might not even support the FP_HSI_SUPPORT TLV. + * If that's the case, we need to make certain required FW was + * supported by such a hypervisor [i.e., v0-v2]. + */ + fp_hsi_resp = bnx2x_search_tlv_list(bp, resp, + CHANNEL_TLV_FP_HSI_SUPPORT); + if (!fp_hsi_resp && (ETH_FP_HSI_VERSION > ETH_FP_HSI_VER_2)) { + BNX2X_ERR("Old hypervisor - need to downgrade VF's driver\n"); + + /* Since acquire succeeded on the PF side, we need to send a + * release message in order to allow future probes. + */ + bnx2x_vfpf_finalize(bp, &req->first_tlv); + bnx2x_vfpf_release(bp); + + rc = -EINVAL; + goto out; + } + /* get HW info */ bp->common.chip_id |= (bp->acquire_resp.pfdev_info.chip_num & 0xffff); bp->link_params.chip_id = bp->common.chip_id; @@ -1125,6 +1151,26 @@ static void bnx2x_vf_mbx_resp_phys_port(struct bnx2x *bp, *offset += sizeof(struct vfpf_port_phys_id_resp_tlv); } +static void bnx2x_vf_mbx_resp_fp_hsi_ver(struct bnx2x *bp, + struct bnx2x_virtf *vf, + void *buffer, + u16 *offset) +{ + struct vfpf_fp_hsi_resp_tlv *fp_hsi; + + bnx2x_add_tlv(bp, buffer, *offset, CHANNEL_TLV_FP_HSI_SUPPORT, + sizeof(struct vfpf_fp_hsi_resp_tlv)); + + fp_hsi = (struct vfpf_fp_hsi_resp_tlv *) + (((u8 *)buffer) + *offset); + fp_hsi->is_supported = (vf->fp_hsi > ETH_FP_HSI_VERSION) ? 0 : 1; + + /* Offset should continue representing the offset to the tail + * of TLV data (outside this function scope) + */ + *offset += sizeof(struct vfpf_fp_hsi_resp_tlv); +} + static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf, struct bnx2x_vf_mbx *mbx, int vfop_status) { @@ -1219,6 +1265,12 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf, CHANNEL_TLV_PHYS_PORT_ID)) bnx2x_vf_mbx_resp_phys_port(bp, vf, &mbx->msg->resp, &length); + /* `New' vfs will want to know if fastpath HSI is supported, since + * if that's not the case they could print into system log the fact + * the driver version must be updated. + */ + bnx2x_vf_mbx_resp_fp_hsi_ver(bp, vf, &mbx->msg->resp, &length); + bnx2x_add_tlv(bp, &mbx->msg->resp, length, CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); @@ -1288,6 +1340,23 @@ static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf, goto out; } + /* Verify the VF fastpath HSI can be supported by the loaded FW. + * Linux vfs should be oblivious to changes between v0 and v2. + */ + if (bnx2x_vf_mbx_is_windows_vm(bp, &mbx->msg->req.acquire)) + vf->fp_hsi = acquire->vfdev_info.fp_hsi_ver; + else + vf->fp_hsi = max_t(u8, acquire->vfdev_info.fp_hsi_ver, + ETH_FP_HSI_VER_2); + if (vf->fp_hsi > ETH_FP_HSI_VERSION) { + DP(BNX2X_MSG_IOV, + "VF [%d] - Can't support acquire request since VF requests a FW version which is too new [%02x > %02x]\n", + vf->abs_vfid, acquire->vfdev_info.fp_hsi_ver, + ETH_FP_HSI_VERSION); + rc = -EINVAL; + goto out; + } + /* acquire the resources */ rc = bnx2x_vf_acquire(bp, vf, &acquire->resc_request); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h index 15670c4..b86479f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h @@ -124,7 +124,7 @@ struct vfpf_acquire_tlv { #define VF_OS_UNDEFINED (0 << VF_OS_SHIFT) #define VF_OS_WINDOWS (1 << VF_OS_SHIFT) - u8 padding; + u8 fp_hsi_ver; u8 caps; #define VF_CAP_SUPPORT_EXT_BULLETIN (1 << 0) } vfdev_info; @@ -204,6 +204,12 @@ struct vfpf_port_phys_id_resp_tlv { u8 padding[2]; }; +struct vfpf_fp_hsi_resp_tlv { + struct channel_tlv tl; + u8 is_supported; + u8 padding[3]; +}; + #define VFPF_INIT_FLG_STATS_COALESCE (1 << 0) /* when set the VFs queues * stats will be coalesced on * the leading RSS queue @@ -448,6 +454,7 @@ enum channel_tlvs { CHANNEL_TLV_UPDATE_RSS, CHANNEL_TLV_PHYS_PORT_ID, CHANNEL_TLV_UPDATE_TPA, + CHANNEL_TLV_FP_HSI_SUPPORT, CHANNEL_TLV_MAX }; -- cgit v1.1 From 51de7bb9ab430f1db4d07e2b5e0711c48cb5a7e6 Mon Sep 17 00:00:00 2001 From: Joe Stringer Date: Fri, 5 Dec 2014 11:35:46 -0800 Subject: bnx2x: Implement ndo_gso_check() Use vxlan_gso_check() to advertise offload support for this NIC. Signed-off-by: Joe Stringer Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 74fbf9e..893cdb6 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -12550,6 +12551,11 @@ static int bnx2x_get_phys_port_id(struct net_device *netdev, return 0; } +static bool bnx2x_gso_check(struct sk_buff *skb, struct net_device *dev) +{ + return vxlan_gso_check(skb); +} + static const struct net_device_ops bnx2x_netdev_ops = { .ndo_open = bnx2x_open, .ndo_stop = bnx2x_close, @@ -12581,6 +12587,7 @@ static const struct net_device_ops bnx2x_netdev_ops = { #endif .ndo_get_phys_port_id = bnx2x_get_phys_port_id, .ndo_set_vf_link_state = bnx2x_set_vf_link_state, + .ndo_gso_check = bnx2x_gso_check, }; static int bnx2x_set_coherency_mask(struct bnx2x *bp) -- cgit v1.1 From fb3b596d3c4a8b6e3867079794856637db4e5283 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 8 Dec 2014 15:59:18 -0800 Subject: net: systemport: allow changing MAC address Hook a ndo_set_mac_address callback, update the internal Ethernet MAC in the netdevice structure, and finally write that address down to the UniMAC registers. If the interface is down, and most likely clock gated, we do not update the registers but just the local copy, such that next ndo_open() call will effectively write down the address. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bcmsysport.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index c1d2559..a91a8c2 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -1409,6 +1409,27 @@ static void topctrl_flush(struct bcm_sysport_priv *priv) topctrl_writel(priv, 0, TX_FLUSH_CNTL); } +static int bcm_sysport_change_mac(struct net_device *dev, void *p) +{ + struct bcm_sysport_priv *priv = netdev_priv(dev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + /* interface is disabled, changes to MAC will be reflected on next + * open call + */ + if (!netif_running(dev)) + return 0; + + umac_set_hw_addr(priv, dev->dev_addr); + + return 0; +} + static void bcm_sysport_netif_start(struct net_device *dev) { struct bcm_sysport_priv *priv = netdev_priv(dev); @@ -1628,6 +1649,7 @@ static const struct net_device_ops bcm_sysport_netdev_ops = { .ndo_stop = bcm_sysport_stop, .ndo_set_features = bcm_sysport_set_features, .ndo_set_rx_mode = bcm_sysport_set_rx_mode, + .ndo_set_mac_address = bcm_sysport_change_mac, }; #define REV_FMT "v%2x.%02x" -- cgit v1.1 From 45abfb1069e4c365f6c1e2fc97c5927272725bfa Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Tue, 9 Dec 2014 19:41:17 -0800 Subject: ethernet/broadcom: Use napi_alloc_skb instead of netdev_alloc_skb_ip_align This patch replaces the calls to netdev_alloc_skb_ip_align in the copybreak paths. Cc: Gary Zambrano Cc: Florian Fainelli Cc: Ariel Elior Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/b44.c | 2 +- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 2 +- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/ethernet/broadcom') diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index ffeaf47..d86d6ba 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -836,7 +836,7 @@ static int b44_rx(struct b44 *bp, int budget) struct sk_buff *copy_skb; b44_recycle_rx(bp, cons, bp->rx_prod); - copy_skb = netdev_alloc_skb_ip_align(bp->dev, len); + copy_skb = napi_alloc_skb(&bp->napi, len); if (copy_skb == NULL) goto drop_it_no_recycle; diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index 3e8d1a8..21206d3 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -385,7 +385,7 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget) if (len < copybreak) { struct sk_buff *nskb; - nskb = netdev_alloc_skb_ip_align(dev, len); + nskb = napi_alloc_skb(&priv->napi, len); if (!nskb) { /* forget packet, just rearm desc */ dev->stats.rx_dropped++; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index b4d71fd..1d1147c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1015,7 +1015,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) */ if ((bp->dev->mtu > ETH_MAX_PACKET_SIZE) && (len <= RX_COPY_THRESH)) { - skb = netdev_alloc_skb_ip_align(bp->dev, len); + skb = napi_alloc_skb(&fp->napi, len); if (skb == NULL) { DP(NETIF_MSG_RX_ERR | NETIF_MSG_RX_STATUS, "ERROR packet dropped because of alloc failure\n"); -- cgit v1.1