aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2005-08-25 18:35:24 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 19:10:34 -0400
commitcd339a0ed61097d92ce03b6d1042b1e4d58535e7 (patch)
tree872886c450910072c3615e8b69a71fb70fa0d42e
parentafdc08b9f9a7174d7912a160f657f39d46379b5e (diff)
[BNX2]: speedup serdes linkup
This speeds up link-up time on 5706 SerDes if the link partner does not autoneg, a rather common scenario in blade servers. Some blade servers use IPMI for keyboard input and it's important to minimize link disruptions. The speedup is achieved by shortening the timer to (HZ / 3) during the transient period right after initiating a SerDes autoneg. If autoneg does not complete, parallel detect can be done sooner. After the transient period is over, the timer goes back to its normal HZ interval. As suggested by Jeff Garzik, the timer initialization is moved to bnx2_init_board() from bnx2_open(). An eeprom bit is also added to allow default forced SerDes speed for even faster link-up time. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/bnx2.c52
-rw-r--r--drivers/net/bnx2.h6
2 files changed, 45 insertions, 13 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 635a5856102b..015ff7906601 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -806,7 +806,19 @@ bnx2_setup_serdes_phy(struct bnx2 *bp)
806 bnx2_write_phy(bp, MII_ADVERTISE, new_adv); 806 bnx2_write_phy(bp, MII_ADVERTISE, new_adv);
807 bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | 807 bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART |
808 BMCR_ANENABLE); 808 BMCR_ANENABLE);
809 bp->serdes_an_pending = SERDES_AN_TIMEOUT / bp->timer_interval; 809 if (CHIP_NUM(bp) == CHIP_NUM_5706) {
810 /* Speed up link-up time when the link partner
811 * does not autonegotiate which is very common
812 * in blade servers. Some blade servers use
813 * IPMI for kerboard input and it's important
814 * to minimize link disruptions. Autoneg. involves
815 * exchanging base pages plus 3 next pages and
816 * normally completes in about 120 msec.
817 */
818 bp->current_interval = SERDES_AN_TIMEOUT;
819 bp->serdes_an_pending = 1;
820 mod_timer(&bp->timer, jiffies + bp->current_interval);
821 }
810 } 822 }
811 823
812 return 0; 824 return 0;
@@ -3800,6 +3812,9 @@ bnx2_timer(unsigned long data)
3800 struct bnx2 *bp = (struct bnx2 *) data; 3812 struct bnx2 *bp = (struct bnx2 *) data;
3801 u32 msg; 3813 u32 msg;
3802 3814
3815 if (!netif_running(bp->dev))
3816 return;
3817
3803 if (atomic_read(&bp->intr_sem) != 0) 3818 if (atomic_read(&bp->intr_sem) != 0)
3804 goto bnx2_restart_timer; 3819 goto bnx2_restart_timer;
3805 3820
@@ -3817,6 +3832,8 @@ bnx2_timer(unsigned long data)
3817 else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) { 3832 else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) {
3818 u32 bmcr; 3833 u32 bmcr;
3819 3834
3835 bp->current_interval = bp->timer_interval;
3836
3820 bnx2_read_phy(bp, MII_BMCR, &bmcr); 3837 bnx2_read_phy(bp, MII_BMCR, &bmcr);
3821 3838
3822 if (bmcr & BMCR_ANENABLE) { 3839 if (bmcr & BMCR_ANENABLE) {
@@ -3859,14 +3876,14 @@ bnx2_timer(unsigned long data)
3859 3876
3860 } 3877 }
3861 } 3878 }
3879 else
3880 bp->current_interval = bp->timer_interval;
3862 3881
3863 spin_unlock_irqrestore(&bp->phy_lock, flags); 3882 spin_unlock_irqrestore(&bp->phy_lock, flags);
3864 } 3883 }
3865 3884
3866bnx2_restart_timer: 3885bnx2_restart_timer:
3867 bp->timer.expires = RUN_AT(bp->timer_interval); 3886 mod_timer(&bp->timer, jiffies + bp->current_interval);
3868
3869 add_timer(&bp->timer);
3870} 3887}
3871 3888
3872/* Called with rtnl_lock */ 3889/* Called with rtnl_lock */
@@ -3919,12 +3936,7 @@ bnx2_open(struct net_device *dev)
3919 return rc; 3936 return rc;
3920 } 3937 }
3921 3938
3922 init_timer(&bp->timer); 3939 mod_timer(&bp->timer, jiffies + bp->current_interval);
3923
3924 bp->timer.expires = RUN_AT(bp->timer_interval);
3925 bp->timer.data = (unsigned long) bp;
3926 bp->timer.function = bnx2_timer;
3927 add_timer(&bp->timer);
3928 3940
3929 atomic_set(&bp->intr_sem, 0); 3941 atomic_set(&bp->intr_sem, 0);
3930 3942
@@ -4485,8 +4497,9 @@ bnx2_nway_reset(struct net_device *dev)
4485 4497
4486 spin_lock_irq(&bp->phy_lock); 4498 spin_lock_irq(&bp->phy_lock);
4487 if (CHIP_NUM(bp) == CHIP_NUM_5706) { 4499 if (CHIP_NUM(bp) == CHIP_NUM_5706) {
4488 bp->serdes_an_pending = SERDES_AN_TIMEOUT / 4500 bp->current_interval = SERDES_AN_TIMEOUT;
4489 bp->timer_interval; 4501 bp->serdes_an_pending = 1;
4502 mod_timer(&bp->timer, jiffies + bp->current_interval);
4490 } 4503 }
4491 } 4504 }
4492 4505
@@ -5315,6 +5328,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
5315 bp->stats_ticks = 1000000 & 0xffff00; 5328 bp->stats_ticks = 1000000 & 0xffff00;
5316 5329
5317 bp->timer_interval = HZ; 5330 bp->timer_interval = HZ;
5331 bp->current_interval = HZ;
5318 5332
5319 /* Disable WOL support if we are running on a SERDES chip. */ 5333 /* Disable WOL support if we are running on a SERDES chip. */
5320 if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) { 5334 if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) {
@@ -5338,6 +5352,15 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
5338 bp->req_line_speed = 0; 5352 bp->req_line_speed = 0;
5339 if (bp->phy_flags & PHY_SERDES_FLAG) { 5353 if (bp->phy_flags & PHY_SERDES_FLAG) {
5340 bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg; 5354 bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
5355
5356 reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE +
5357 BNX2_PORT_HW_CFG_CONFIG);
5358 reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK;
5359 if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) {
5360 bp->autoneg = 0;
5361 bp->req_line_speed = bp->line_speed = SPEED_1000;
5362 bp->req_duplex = DUPLEX_FULL;
5363 }
5341 } 5364 }
5342 else { 5365 else {
5343 bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg; 5366 bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg;
@@ -5345,6 +5368,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
5345 5368
5346 bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX; 5369 bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX;
5347 5370
5371 init_timer(&bp->timer);
5372 bp->timer.expires = RUN_AT(bp->timer_interval);
5373 bp->timer.data = (unsigned long) bp;
5374 bp->timer.function = bnx2_timer;
5375
5348 return 0; 5376 return 0;
5349 5377
5350err_out_unmap: 5378err_out_unmap:
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 63b94ca0018b..e1fb099acbf2 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -3872,6 +3872,7 @@ struct bnx2 {
3872 char *name; 3872 char *name;
3873 3873
3874 int timer_interval; 3874 int timer_interval;
3875 int current_interval;
3875 struct timer_list timer; 3876 struct timer_list timer;
3876 struct work_struct reset_task; 3877 struct work_struct reset_task;
3877 int in_reset_task; 3878 int in_reset_task;
@@ -3986,7 +3987,7 @@ struct bnx2 {
3986#define PHY_LOOPBACK 2 3987#define PHY_LOOPBACK 2
3987 3988
3988 u8 serdes_an_pending; 3989 u8 serdes_an_pending;
3989#define SERDES_AN_TIMEOUT (2 * HZ) 3990#define SERDES_AN_TIMEOUT (HZ / 3)
3990 3991
3991 u8 mac_addr[8]; 3992 u8 mac_addr[8];
3992 3993
@@ -4172,6 +4173,9 @@ struct fw_info {
4172 4173
4173#define BNX2_PORT_HW_CFG_MAC_LOWER 0x00000054 4174#define BNX2_PORT_HW_CFG_MAC_LOWER 0x00000054
4174#define BNX2_PORT_HW_CFG_CONFIG 0x00000058 4175#define BNX2_PORT_HW_CFG_CONFIG 0x00000058
4176#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK 0x001f0000
4177#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_AN 0x00000000
4178#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G 0x00030000
4175 4179
4176#define BNX2_PORT_HW_CFG_IMD_MAC_A_UPPER 0x00000068 4180#define BNX2_PORT_HW_CFG_IMD_MAC_A_UPPER 0x00000068
4177#define BNX2_PORT_HW_CFG_IMD_MAC_A_LOWER 0x0000006c 4181#define BNX2_PORT_HW_CFG_IMD_MAC_A_LOWER 0x0000006c