From c6700ce2248ecf3b1b6fd009f6aed9b6387d3377 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 13 Feb 2012 15:20:15 +0000 Subject: tg3: Remove unneeded link_config.orig_... members This patch removes the unneeded link_config.orig_* members. When the phy is in a low power state, the TG3_PHYFLG_IS_LOW_POWER flag solely determines how the link is configured. When the phy is powered back up, it can resume using the original settings. For the phylib case, the link configuration still needs to be saved, but since the phylib maintains its own configuration, we can repurpose the (unused in this case) tg3 link configuration members. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.h | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/net/ethernet/broadcom/tg3.h') diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index aea8f72c24fa..2ddd92e5f54f 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -2707,14 +2707,6 @@ struct tg3_link_config { #define AUTONEG_INVALID 0xff u16 active_speed; u32 rmt_adv; - - /* When we go in and out of low power mode we need - * to swap with this state. - */ - u16 orig_speed; - u8 orig_duplex; - u8 orig_autoneg; - u32 orig_advertising; }; struct tg3_bufmgr_config { -- cgit v1.2.3 From e740522e6d3a6c3014da30f65fe254bc7f6410d7 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 13 Feb 2012 15:20:16 +0000 Subject: tg3: Use *_UNKNOWN ethtool definitions This patch replaces tg3's private SPEED_INVALID and DUPLEX_INVALID definitions with SPEED_UNKNOWN and DUPLEX_UNKNOWN respectively. Signed-off-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 40 ++++++++++++++++++------------------- drivers/net/ethernet/broadcom/tg3.h | 3 --- 2 files changed, 20 insertions(+), 23 deletions(-) (limited to 'drivers/net/ethernet/broadcom/tg3.h') diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 859bd22f814b..302c69bc58d7 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -1819,8 +1819,8 @@ static void tg3_adjust_link(struct net_device *dev) (6 << TX_LENGTHS_IPG_SHIFT) | (32 << TX_LENGTHS_SLOT_TIME_SHIFT))); - if ((phydev->link && tp->link_config.active_speed == SPEED_INVALID) || - (!phydev->link && tp->link_config.active_speed != SPEED_INVALID) || + if ((phydev->link && tp->link_config.active_speed == SPEED_UNKNOWN) || + (!phydev->link && tp->link_config.active_speed != SPEED_UNKNOWN) || phydev->speed != tp->link_config.active_speed || phydev->duplex != tp->link_config.active_duplex || oldflowctrl != tp->link_config.active_flowctrl) @@ -3813,8 +3813,8 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 DUPLEX_HALF; break; } - *speed = SPEED_INVALID; - *duplex = DUPLEX_INVALID; + *speed = SPEED_UNKNOWN; + *duplex = DUPLEX_UNKNOWN; break; } } @@ -3906,7 +3906,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp) tg3_phy_autoneg_cfg(tp, new_adv, FLOW_CTRL_TX | FLOW_CTRL_RX); - } else if (tp->link_config.speed == SPEED_INVALID) { + } else if (tp->link_config.speed == SPEED_UNKNOWN) { if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY) tp->link_config.advertising &= ~(ADVERTISED_1000baseT_Half | @@ -3938,7 +3938,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp) } if (tp->link_config.autoneg == AUTONEG_DISABLE && - tp->link_config.speed != SPEED_INVALID) { + tp->link_config.speed != SPEED_UNKNOWN) { u32 bmcr, orig_bmcr; tp->link_config.active_speed = tp->link_config.speed; @@ -4172,8 +4172,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) } current_link_up = 0; - current_speed = SPEED_INVALID; - current_duplex = DUPLEX_INVALID; + current_speed = SPEED_UNKNOWN; + current_duplex = DUPLEX_UNKNOWN; tp->phy_flags &= ~TG3_PHYFLG_MDIX_STATE; tp->link_config.rmt_adv = 0; @@ -5069,8 +5069,8 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) LED_CTRL_LNKLED_OVERRIDE | LED_CTRL_1000MBPS_ON)); } else { - tp->link_config.active_speed = SPEED_INVALID; - tp->link_config.active_duplex = DUPLEX_INVALID; + tp->link_config.active_speed = SPEED_UNKNOWN; + tp->link_config.active_duplex = DUPLEX_UNKNOWN; tw32(MAC_LED_CTRL, (tp->led_ctrl | LED_CTRL_LNKLED_OVERRIDE | LED_CTRL_TRAFFIC_OVERRIDE)); @@ -5118,8 +5118,8 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) tg3_phy_reset(tp); current_link_up = 0; - current_speed = SPEED_INVALID; - current_duplex = DUPLEX_INVALID; + current_speed = SPEED_UNKNOWN; + current_duplex = DUPLEX_UNKNOWN; tp->link_config.rmt_adv = 0; err |= tg3_readphy(tp, MII_BMSR, &bmsr); @@ -10515,8 +10515,8 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->eth_tp_mdix = ETH_TP_MDI; } } else { - ethtool_cmd_speed_set(cmd, SPEED_INVALID); - cmd->duplex = DUPLEX_INVALID; + ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN); + cmd->duplex = DUPLEX_UNKNOWN; cmd->eth_tp_mdix = ETH_TP_MDI_INVALID; } cmd->phy_address = tp->phy_addr; @@ -10598,8 +10598,8 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (cmd->autoneg == AUTONEG_ENABLE) { tp->link_config.advertising = (cmd->advertising | ADVERTISED_Autoneg); - tp->link_config.speed = SPEED_INVALID; - tp->link_config.duplex = DUPLEX_INVALID; + tp->link_config.speed = SPEED_UNKNOWN; + tp->link_config.duplex = DUPLEX_UNKNOWN; } else { tp->link_config.advertising = 0; tp->link_config.speed = speed; @@ -13347,11 +13347,11 @@ static void __devinit tg3_phy_init_link_config(struct tg3 *tp) adv |= ADVERTISED_FIBRE; tp->link_config.advertising = adv; - tp->link_config.speed = SPEED_INVALID; - tp->link_config.duplex = DUPLEX_INVALID; + tp->link_config.speed = SPEED_UNKNOWN; + tp->link_config.duplex = DUPLEX_UNKNOWN; tp->link_config.autoneg = AUTONEG_ENABLE; - tp->link_config.active_speed = SPEED_INVALID; - tp->link_config.active_duplex = DUPLEX_INVALID; + tp->link_config.active_speed = SPEED_UNKNOWN; + tp->link_config.active_duplex = DUPLEX_UNKNOWN; } static int __devinit tg3_phy_probe(struct tg3 *tp) diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index 2ddd92e5f54f..300c6e55a411 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -2702,9 +2702,6 @@ struct tg3_link_config { u8 active_flowctrl; u8 active_duplex; -#define SPEED_INVALID 0xffff -#define DUPLEX_INVALID 0xff -#define AUTONEG_INVALID 0xff u16 active_speed; u32 rmt_adv; }; -- cgit v1.2.3 From 9e056c0320fafc03dc170772d8562e3142ed1778 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 13 Feb 2012 15:20:17 +0000 Subject: tg3: Update copyright This patch updates the copyright dates in the tg3 driver. Signed-off-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 2 +- drivers/net/ethernet/broadcom/tg3.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/ethernet/broadcom/tg3.h') diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 302c69bc58d7..d604664fdb42 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -4,7 +4,7 @@ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com) * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com) * Copyright (C) 2004 Sun Microsystems Inc. - * Copyright (C) 2005-2011 Broadcom Corporation. + * Copyright (C) 2005-2012 Broadcom Corporation. * * Firmware is: * Derived from proprietary unpublished source code, diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index 300c6e55a411..22cbe74b3d11 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -4,7 +4,7 @@ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com) * Copyright (C) 2001 Jeff Garzik (jgarzik@pobox.com) * Copyright (C) 2004 Sun Microsystems Inc. - * Copyright (C) 2007-2011 Broadcom Corporation. + * Copyright (C) 2007-2012 Broadcom Corporation. */ #ifndef _T3_H -- cgit v1.2.3 From 34655ad63893d3dd64f3fbaaaa0791550e554fa9 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 22 Feb 2012 12:35:18 +0000 Subject: tg3: Fix link check in tg3_adjust_link The tg3 driver tried to detect link changes by comparing the tg3 local active_speed member with SPEED_UNKNOWN (or formerly SPEED_INVALID). This check is not correct, since phylib will never set its speed member to either of these two values. The code only appeared to work because tg3 initializes active_speed to SPEED_INVALID during tg3_init_one. This patch introduces a new "old_link" tg3 member and then compares the phy_device's link member against it to detect link state changes. Signed-off-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 6 ++++-- drivers/net/ethernet/broadcom/tg3.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net/ethernet/broadcom/tg3.h') diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 27dafd928279..0caf565fafe4 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -1819,13 +1819,13 @@ static void tg3_adjust_link(struct net_device *dev) (6 << TX_LENGTHS_IPG_SHIFT) | (32 << TX_LENGTHS_SLOT_TIME_SHIFT))); - if ((phydev->link && tp->link_config.active_speed == SPEED_UNKNOWN) || - (!phydev->link && tp->link_config.active_speed != SPEED_UNKNOWN) || + if (phydev->link != tp->old_link || phydev->speed != tp->link_config.active_speed || phydev->duplex != tp->link_config.active_duplex || oldflowctrl != tp->link_config.active_flowctrl) linkmesg = 1; + tp->old_link = phydev->link; tp->link_config.active_speed = phydev->speed; tp->link_config.active_duplex = phydev->duplex; @@ -13352,6 +13352,8 @@ static void __devinit tg3_phy_init_link_config(struct tg3 *tp) tp->link_config.autoneg = AUTONEG_ENABLE; tp->link_config.active_speed = SPEED_UNKNOWN; tp->link_config.active_duplex = DUPLEX_UNKNOWN; + + tp->old_link = -1; } static int __devinit tg3_phy_probe(struct tg3 *tp) diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index 22cbe74b3d11..66bcfca55261 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -3064,6 +3064,7 @@ struct tg3 { struct mii_bus *mdio_bus; int mdio_irq[PHY_MAX_ADDR]; + int old_link; u8 phy_addr; -- cgit v1.2.3 From 7ae5289017e5ed5514b2603d157fb54c058a3c82 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 21 Mar 2012 15:38:33 +0000 Subject: tg3: Fix RSS ring refill race condition The RSS feature in tg3 hardware has only one rx producer ring for all RSS rings. NAPI vector 1 is special and handles the refilling of the rx producer ring on behalf of all RSS rings. There is a race condition between these RSS NAPIs and the NAPI[1]. If NAPI[1] finishes checking for refill and then another RSS ring empties the rx producer ring before NAPI[1] exits NAPI, the chip will be completely out of SKBs in the rx producer ring. We fix this by adding a flag tp->rx_refill and rely on napi_schedule()/ napi_complete() to help synchronize it to close the race condition. Update driver version to 3.123. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 25 ++++++++++++++++++++++--- drivers/net/ethernet/broadcom/tg3.h | 1 + 2 files changed, 23 insertions(+), 3 deletions(-) (limited to 'drivers/net/ethernet/broadcom/tg3.h') diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index b0657466041d..7b71387cf93c 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -89,10 +89,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) #define DRV_MODULE_NAME "tg3" #define TG3_MAJ_NUM 3 -#define TG3_MIN_NUM 122 +#define TG3_MIN_NUM 123 #define DRV_MODULE_VERSION \ __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM) -#define DRV_MODULE_RELDATE "December 7, 2011" +#define DRV_MODULE_RELDATE "March 21, 2012" #define RESET_KIND_SHUTDOWN 0 #define RESET_KIND_INIT 1 @@ -5953,8 +5953,10 @@ next_pkt_nopost: tpr->rx_std_prod_idx = std_prod_idx & tp->rx_std_ring_mask; tpr->rx_jmb_prod_idx = jmb_prod_idx & tp->rx_jmb_ring_mask; - if (tnapi != &tp->napi[1]) + if (tnapi != &tp->napi[1]) { + tp->rx_refill = true; napi_schedule(&tp->napi[1].napi); + } } return received; @@ -6134,6 +6136,7 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) u32 std_prod_idx = dpr->rx_std_prod_idx; u32 jmb_prod_idx = dpr->rx_jmb_prod_idx; + tp->rx_refill = false; for (i = 1; i < tp->irq_cnt; i++) err |= tg3_rx_prodring_xfer(tp, dpr, &tp->napi[i].prodring); @@ -6197,9 +6200,25 @@ static int tg3_poll_msix(struct napi_struct *napi, int budget) /* check for RX/TX work to do */ if (likely(sblk->idx[0].tx_consumer == tnapi->tx_cons && *(tnapi->rx_rcb_prod_idx) == tnapi->rx_rcb_ptr)) { + + /* This test here is not race free, but will reduce + * the number of interrupts by looping again. + */ + if (tnapi == &tp->napi[1] && tp->rx_refill) + continue; + napi_complete(napi); /* Reenable interrupts. */ tw32_mailbox(tnapi->int_mbox, tnapi->last_tag << 24); + + /* This test here is synchronized by napi_schedule() + * and napi_complete() to close the race condition. + */ + if (unlikely(tnapi == &tp->napi[1] && tp->rx_refill)) { + tw32(HOSTCC_MODE, tp->coalesce_mode | + HOSTCC_MODE_ENABLE | + tnapi->coal_now); + } mmiowb(); break; } diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index 66bcfca55261..93865f899a4f 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -3007,6 +3007,7 @@ struct tg3 { u32 rx_std_max_post; u32 rx_offset; u32 rx_pkt_map_sz; + bool rx_refill; /* begin "everything else" cacheline(s) section */ -- cgit v1.2.3