From 70b9986ca4baaf6deb6f0e01d50f72457579adea Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:43:48 +0000 Subject: bnx2x: Free IRQ Error check could result with not freeing the IRQ Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 7c533797c064..ce98ecf8cb1c 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6684,6 +6684,9 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq)); bnx2x_stats_handle(bp, STATS_EVENT_STOP); + /* Release IRQs */ + bnx2x_free_irq(bp); + /* Wait until tx fast path tasks complete */ for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; @@ -6711,9 +6714,6 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) /* Give HW time to discard old tx messages */ msleep(1); - /* Release IRQs */ - bnx2x_free_irq(bp); - if (CHIP_IS_E1(bp)) { struct mac_configuration_cmd *config = bnx2x_sp(bp, mcast_config); -- cgit v1.2.3 From 693fc0d14334859430733ab902adac182fdd8153 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:43:52 +0000 Subject: bnx2x: Handling probe failures Failures in the probe not handled correctly - separate the flow to handle different failures Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ce98ecf8cb1c..911067586a4a 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -10269,17 +10269,15 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, return rc; } - rc = register_netdev(dev); - if (rc) { - dev_err(&pdev->dev, "Cannot register net device\n"); - goto init_one_exit; - } - pci_set_drvdata(pdev, dev); rc = bnx2x_init_bp(bp); + if (rc) + goto init_one_exit; + + rc = register_netdev(dev); if (rc) { - unregister_netdev(dev); + dev_err(&pdev->dev, "Cannot register net device\n"); goto init_one_exit; } -- cgit v1.2.3 From b4661739c67acd15a02f8e112f8cc52d24b609ed Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:43:56 +0000 Subject: bnx2x: Potential race after iSCSI boot The lock was release too soon. Make sure the HW is marked as locked until the boot driver was unloaded from FW perspective Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 911067586a4a..70fc61033ddf 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6874,10 +6874,6 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) */ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); val = REG_RD(bp, DORQ_REG_NORM_CID_OFST); - if (val == 0x7) - REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0); - bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); - if (val == 0x7) { u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; /* save our func */ @@ -6885,6 +6881,9 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) u32 swap_en; u32 swap_val; + /* clear the UNDI indication */ + REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0); + BNX2X_DEV_INFO("UNDI is active! reset device\n"); /* try unload UNDI on port 0 */ @@ -6910,6 +6909,9 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) bnx2x_fw_command(bp, reset_code); } + /* now it's safe to release the lock */ + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); + REG_WR(bp, (BP_PORT(bp) ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0), 0x1000); @@ -6954,7 +6956,9 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) bp->fw_seq = (SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) & DRV_MSG_SEQ_NUMBER_MASK); - } + + } else + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); } } -- cgit v1.2.3 From af2464011f0954785687071b298f066f6cbb1c84 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:43:59 +0000 Subject: bnx2x: Wrong HDR offset in CAM Has a negative side effect when sending MAC update with no content (as done in the self-test) Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 70fc61033ddf..8f8271d76db6 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6144,7 +6144,7 @@ static void bnx2x_set_mac_addr_e1(struct bnx2x *bp, int set) * multicast 64-127:port0 128-191:port1 */ config->hdr.length_6b = 2; - config->hdr.offset = port ? 31 : 0; + config->hdr.offset = port ? 32 : 0; config->hdr.client_id = BP_CL_ID(bp); config->hdr.reserved1 = 0; @@ -8910,7 +8910,10 @@ static int bnx2x_test_intr(struct bnx2x *bp) return -ENODEV; config->hdr.length_6b = 0; - config->hdr.offset = 0; + if (CHIP_IS_E1(bp)) + config->hdr.offset = (BP_PORT(bp) ? 32 : 0); + else + config->hdr.offset = BP_FUNC(bp); config->hdr.client_id = BP_CL_ID(bp); config->hdr.reserved1 = 0; @@ -9863,7 +9866,7 @@ static void bnx2x_set_rx_mode(struct net_device *dev) for (; i < old; i++) { if (CAM_IS_INVALID(config-> config_table[i])) { - i--; /* already invalidated */ + /* already invalidated */ break; } /* invalidate */ -- cgit v1.2.3 From 5a40e08e666e8caa1227333de41fd1e2cd84d4f5 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:04 +0000 Subject: bnx2x: Read chip ID Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 8f8271d76db6..7ee6a211f9ba 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6975,7 +6975,7 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) id |= ((val & 0xf) << 12); val = REG_RD(bp, MISC_REG_CHIP_METAL); id |= ((val & 0xff) << 4); - REG_RD(bp, MISC_REG_BOND_ID); + val = REG_RD(bp, MISC_REG_BOND_ID); id |= (val & 0xf); bp->common.chip_id = id; bp->link_params.chip_id = bp->common.chip_id; -- cgit v1.2.3 From 2add3acb11a26cc14b54669433ae6ace6406cbf2 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:07 +0000 Subject: bnx2x: Block nvram access when the device is inactive Don't dump eeprom when bnx2x adapter is down. Running ethtool -e causes an eeh without it when the device is down Signed-off-by: Paul Larson Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 7ee6a211f9ba..ca5090c3341e 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -8107,6 +8107,9 @@ static int bnx2x_get_eeprom(struct net_device *dev, struct bnx2x *bp = netdev_priv(dev); int rc; + if (!netif_running(dev)) + return -EAGAIN; + DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n" DP_LEVEL " magic 0x%x offset 0x%x (%d) len 0x%x (%d)\n", eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset, -- cgit v1.2.3 From 632da4d66324b5baf947a048dd1f1e9093b6dd90 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:10 +0000 Subject: bnx2x: Overstepping array bounds If the page size is > 8KB this violation happens Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ca5090c3341e..2e00da6ab172 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -9427,6 +9427,7 @@ static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) return rc; } +#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3) /* check if packet requires linearization (packet is too fragmented) */ static int bnx2x_pkt_req_lin(struct bnx2x *bp, struct sk_buff *skb, u32 xmit_type) @@ -9504,6 +9505,7 @@ exit_lbl: return to_copy; } +#endif /* called with netif_tx_lock * bnx2x_tx_int() runs without netif_tx_lock unless it needs to call @@ -9544,6 +9546,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr, ip_hdr(skb)->protocol, skb_shinfo(skb)->gso_type, xmit_type); +#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3) /* First, check if we need to linearize the skb (due to FW restrictions) */ if (bnx2x_pkt_req_lin(bp, skb, xmit_type)) { @@ -9556,6 +9559,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } } +#endif /* Please read carefully. First we use one BD which we mark as start, -- cgit v1.2.3 From e47d7e6eb841c1850f0e69b95ae6cf3c86881f53 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:28 +0000 Subject: bnx2x: Driver description update The Driver supports the 57711 and 57711E as well but the description was out of date Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 2e00da6ab172..dc05e37c581d 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -69,7 +69,7 @@ static char version[] __devinitdata = DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("Eliezer Tamir"); -MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 Driver"); +MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710/57711/57711E Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); -- cgit v1.2.3 From 237907c1ded8a1a447cea7c4f97ab853e8b46052 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:42:44 +0000 Subject: bnx2x: Barriers for the compiler To make sure no swapping are made by the compiler, changed HAS_WORK to inline functions and added all the necessary barriers Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 9 +-------- drivers/net/bnx2x_main.c | 37 ++++++++++++++++++++++++++----------- 2 files changed, 27 insertions(+), 19 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 6fcccef4cf3d..18f60aa3efdd 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -271,14 +271,7 @@ struct bnx2x_fastpath { #define bnx2x_fp(bp, nr, var) (bp->fp[nr].var) -#define BNX2X_HAS_TX_WORK(fp) \ - ((fp->tx_pkt_prod != le16_to_cpu(*fp->tx_cons_sb)) || \ - (fp->tx_pkt_prod != fp->tx_pkt_cons)) - -#define BNX2X_HAS_RX_WORK(fp) \ - (fp->rx_comp_cons != rx_cons_sb) - -#define BNX2X_HAS_WORK(fp) (BNX2X_HAS_RX_WORK(fp) || BNX2X_HAS_TX_WORK(fp)) +#define BNX2X_HAS_WORK(fp) (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp)) /* MC hsi */ diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index dc05e37c581d..3236527477a3 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -733,6 +733,17 @@ static u16 bnx2x_ack_int(struct bnx2x *bp) * fast path service functions */ +static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp) +{ + u16 tx_cons_sb; + + /* Tell compiler that status block fields can change */ + barrier(); + tx_cons_sb = le16_to_cpu(*fp->tx_cons_sb); + return ((fp->tx_pkt_prod != tx_cons_sb) || + (fp->tx_pkt_prod != fp->tx_pkt_cons)); +} + /* free skb in the packet ring at pos idx * return idx of last bd freed */ @@ -6693,7 +6704,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) cnt = 1000; smp_rmb(); - while (BNX2X_HAS_TX_WORK(fp)) { + while (bnx2x_has_tx_work(fp)) { bnx2x_tx_int(fp, 1000); if (!cnt) { @@ -9281,6 +9292,18 @@ static int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state) return 0; } +static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp) +{ + u16 rx_cons_sb; + + /* Tell compiler that status block fields can change */ + barrier(); + rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); + if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) + rx_cons_sb++; + return (fp->rx_comp_cons != rx_cons_sb); +} + /* * net_device service functions */ @@ -9291,7 +9314,6 @@ static int bnx2x_poll(struct napi_struct *napi, int budget) napi); struct bnx2x *bp = fp->bp; int work_done = 0; - u16 rx_cons_sb; #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) @@ -9304,19 +9326,12 @@ static int bnx2x_poll(struct napi_struct *napi, int budget) bnx2x_update_fpsb_idx(fp); - if (BNX2X_HAS_TX_WORK(fp)) + if (bnx2x_has_tx_work(fp)) bnx2x_tx_int(fp, budget); - rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); - if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) - rx_cons_sb++; - if (BNX2X_HAS_RX_WORK(fp)) + if (bnx2x_has_rx_work(fp)) work_done = bnx2x_rx_int(fp, budget); - rmb(); /* BNX2X_HAS_WORK() reads the status block */ - rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); - if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) - rx_cons_sb++; /* must not complete if we consumed full budget */ if ((work_done < budget) && !BNX2X_HAS_WORK(fp)) { -- cgit v1.2.3 From d05c26ce690e867aabfc7d708d481e0f86f23496 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Sat, 17 Jan 2009 23:26:13 -0800 Subject: bnx2x: Version update Updating the version and the year of updated files Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 2 +- drivers/net/bnx2x_link.c | 2 +- drivers/net/bnx2x_main.c | 6 +++--- drivers/net/bnx2x_reg.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 18f60aa3efdd..15a5cf0f676b 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -1,6 +1,6 @@ /* bnx2x.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2008 Broadcom Corporation + * Copyright (c) 2007-2009 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index b4527a4a60e3..aea26b4dc453 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -1,4 +1,4 @@ -/* Copyright 2008 Broadcom Corporation +/* Copyright 2008-2009 Broadcom Corporation * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 3236527477a3..074374ff93f3 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -1,6 +1,6 @@ /* bnx2x_main.c: Broadcom Everest network driver. * - * Copyright (c) 2007-2008 Broadcom Corporation + * Copyright (c) 2007-2009 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,8 +57,8 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.45.23" -#define DRV_MODULE_RELDATE "2008/11/03" +#define DRV_MODULE_VERSION "1.45.24" +#define DRV_MODULE_RELDATE "2009/01/14" #define BNX2X_BC_VER 0x040200 /* Time in jiffies before concluding the transmitter is hung */ diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x_reg.h index a67b0c358ae4..d084e5fc4b51 100644 --- a/drivers/net/bnx2x_reg.h +++ b/drivers/net/bnx2x_reg.h @@ -1,6 +1,6 @@ /* bnx2x_reg.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2008 Broadcom Corporation + * Copyright (c) 2007-2009 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- cgit v1.2.3 From 81f75bbf67c7a26ea1266ac93b9319bb985d588d Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 03:37:31 +0000 Subject: bnx2x: Reset HW before use To avoid complications, make sure that the HW is in reset (as it should be) before trying to take it out of reset. In normal flows, the HW is indeed in rest so this should have no effect Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 074374ff93f3..ed8b34665931 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -5148,12 +5148,21 @@ static void enable_blocks_attention(struct bnx2x *bp) } +static void bnx2x_reset_common(struct bnx2x *bp) +{ + /* reset_common */ + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, + 0xd3ffff7f); + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 0x1403); +} + static int bnx2x_init_common(struct bnx2x *bp) { u32 val, i; DP(BNX2X_MSG_MCP, "starting common init func %d\n", BP_FUNC(bp)); + bnx2x_reset_common(bp); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc); @@ -6640,14 +6649,6 @@ static void bnx2x_reset_port(struct bnx2x *bp) /* TODO: Close Doorbell port? */ } -static void bnx2x_reset_common(struct bnx2x *bp) -{ - /* reset_common */ - REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, - 0xd3ffff7f); - REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 0x1403); -} - static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code) { DP(BNX2X_MSG_MCP, "function %d reset_code %x\n", -- cgit v1.2.3 From e94d8af3da79f4bfbd22819d28ecf0602456f06f Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 03:37:36 +0000 Subject: bnx2x: Disable napi Calling napi disabled unconditionally at netif stop Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ed8b34665931..860b9f8ddd30 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6143,8 +6143,8 @@ static void bnx2x_netif_start(struct bnx2x *bp) static void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw) { bnx2x_int_disable_sync(bp, disable_hw); + bnx2x_napi_disable(bp); if (netif_running(bp->dev)) { - bnx2x_napi_disable(bp); netif_tx_disable(bp->dev); bp->dev->trans_start = jiffies; /* prevent tx timeout */ } @@ -6689,8 +6689,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) bnx2x_set_storm_rx_mode(bp); bnx2x_netif_stop(bp, 1); - if (!netif_running(bp->dev)) - bnx2x_napi_disable(bp); + del_timer_sync(&bp->timer); SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb, (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq)); -- cgit v1.2.3 From 2dfe0e1fecb582b4aae7f2490904864c05472f3a Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 03:37:44 +0000 Subject: bnx2x: Handling load failures Failures on load were not handled correctly - separate the flow to handle different failures Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 154 +++++++++++++++++++++++++++-------------------- 1 file changed, 88 insertions(+), 66 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 860b9f8ddd30..707c4bbe46a4 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6328,7 +6328,7 @@ static void bnx2x_set_rx_mode(struct net_device *dev); static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) { u32 load_code; - int i, rc; + int i, rc = 0; #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) return -EPERM; @@ -6336,48 +6336,6 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD; - /* Send LOAD_REQUEST command to MCP - Returns the type of LOAD command: - if it is the first port to be initialized - common blocks should be initialized, otherwise - not - */ - if (!BP_NOMCP(bp)) { - load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ); - if (!load_code) { - BNX2X_ERR("MCP response failure, aborting\n"); - return -EBUSY; - } - if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) - return -EBUSY; /* other port in diagnostic mode */ - - } else { - int port = BP_PORT(bp); - - DP(NETIF_MSG_IFUP, "NO MCP load counts before us %d, %d, %d\n", - load_count[0], load_count[1], load_count[2]); - load_count[0]++; - load_count[1 + port]++; - DP(NETIF_MSG_IFUP, "NO MCP new load counts %d, %d, %d\n", - load_count[0], load_count[1], load_count[2]); - if (load_count[0] == 1) - load_code = FW_MSG_CODE_DRV_LOAD_COMMON; - else if (load_count[1 + port] == 1) - load_code = FW_MSG_CODE_DRV_LOAD_PORT; - else - load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION; - } - - if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) || - (load_code == FW_MSG_CODE_DRV_LOAD_PORT)) - bp->port.pmf = 1; - else - bp->port.pmf = 0; - DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf); - - /* if we can't use MSI-X we only need one fp, - * so try to enable MSI-X with the requested number of fp's - * and fallback to inta with one fp - */ if (use_inta) { bp->num_queues = 1; @@ -6392,7 +6350,15 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) else bp->num_queues = 1; - if (bnx2x_enable_msix(bp)) { + DP(NETIF_MSG_IFUP, + "set number of queues to %d\n", bp->num_queues); + + /* if we can't use MSI-X we only need one fp, + * so try to enable MSI-X with the requested number of fp's + * and fallback to MSI or legacy INTx with one fp + */ + rc = bnx2x_enable_msix(bp); + if (rc) { /* failed to enable MSI-X */ bp->num_queues = 1; if (use_multi) @@ -6400,8 +6366,6 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) " to enable MSI-X\n"); } } - DP(NETIF_MSG_IFUP, - "set number of queues to %d\n", bp->num_queues); if (bnx2x_alloc_mem(bp)) return -ENOMEM; @@ -6410,30 +6374,85 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bnx2x_fp(bp, i, disable_tpa) = ((bp->flags & TPA_ENABLE_FLAG) == 0); + for_each_queue(bp, i) + netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), + bnx2x_poll, 128); + +#ifdef BNX2X_STOP_ON_ERROR + for_each_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + + fp->poll_no_work = 0; + fp->poll_calls = 0; + fp->poll_max_calls = 0; + fp->poll_complete = 0; + fp->poll_exit = 0; + } +#endif + bnx2x_napi_enable(bp); + if (bp->flags & USING_MSIX_FLAG) { rc = bnx2x_req_msix_irqs(bp); if (rc) { pci_disable_msix(bp->pdev); - goto load_error; + goto load_error1; } + printk(KERN_INFO PFX "%s: using MSI-X\n", bp->dev->name); } else { bnx2x_ack_int(bp); rc = bnx2x_req_irq(bp); if (rc) { - BNX2X_ERR("IRQ request failed, aborting\n"); - goto load_error; + BNX2X_ERR("IRQ request failed rc %d, aborting\n", rc); + goto load_error1; } } - for_each_queue(bp, i) - netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), - bnx2x_poll, 128); + /* Send LOAD_REQUEST command to MCP + Returns the type of LOAD command: + if it is the first port to be initialized + common blocks should be initialized, otherwise - not + */ + if (!BP_NOMCP(bp)) { + load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ); + if (!load_code) { + BNX2X_ERR("MCP response failure, aborting\n"); + rc = -EBUSY; + goto load_error2; + } + if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) { + rc = -EBUSY; /* other port in diagnostic mode */ + goto load_error2; + } + + } else { + int port = BP_PORT(bp); + + DP(NETIF_MSG_IFUP, "NO MCP load counts before us %d, %d, %d\n", + load_count[0], load_count[1], load_count[2]); + load_count[0]++; + load_count[1 + port]++; + DP(NETIF_MSG_IFUP, "NO MCP new load counts %d, %d, %d\n", + load_count[0], load_count[1], load_count[2]); + if (load_count[0] == 1) + load_code = FW_MSG_CODE_DRV_LOAD_COMMON; + else if (load_count[1 + port] == 1) + load_code = FW_MSG_CODE_DRV_LOAD_PORT; + else + load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION; + } + + if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) || + (load_code == FW_MSG_CODE_DRV_LOAD_PORT)) + bp->port.pmf = 1; + else + bp->port.pmf = 0; + DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf); /* Initialize HW */ rc = bnx2x_init_hw(bp, load_code); if (rc) { BNX2X_ERR("HW init failed, aborting\n"); - goto load_int_disable; + goto load_error2; } /* Setup NIC internals and enable interrupts */ @@ -6445,7 +6464,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) if (!load_code) { BNX2X_ERR("MCP response failure, aborting\n"); rc = -EBUSY; - goto load_rings_free; + goto load_error3; } } @@ -6454,7 +6473,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) rc = bnx2x_setup_leading(bp); if (rc) { BNX2X_ERR("Setup leading failed!\n"); - goto load_netif_stop; + goto load_error3; } if (CHIP_IS_E1H(bp)) @@ -6467,7 +6486,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) for_each_nondefault_queue(bp, i) { rc = bnx2x_setup_multi(bp, i); if (rc) - goto load_netif_stop; + goto load_error3; } if (CHIP_IS_E1(bp)) @@ -6483,18 +6502,18 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) case LOAD_NORMAL: /* Tx queue should be only reenabled */ netif_wake_queue(bp->dev); + /* Initialize the receive filter. */ bnx2x_set_rx_mode(bp->dev); break; case LOAD_OPEN: netif_start_queue(bp->dev); + /* Initialize the receive filter. */ bnx2x_set_rx_mode(bp->dev); - if (bp->flags & USING_MSIX_FLAG) - printk(KERN_INFO PFX "%s: using MSI-X\n", - bp->dev->name); break; case LOAD_DIAG: + /* Initialize the receive filter. */ bnx2x_set_rx_mode(bp->dev); bp->state = BNX2X_STATE_DIAG; break; @@ -6512,20 +6531,23 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) return 0; -load_netif_stop: - bnx2x_napi_disable(bp); -load_rings_free: +load_error3: + bnx2x_int_disable_sync(bp, 1); + if (!BP_NOMCP(bp)) { + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP); + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); + } + bp->port.pmf = 0; /* Free SKBs, SGEs, TPA pool and driver internals */ bnx2x_free_skbs(bp); for_each_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); -load_int_disable: - bnx2x_int_disable_sync(bp, 1); +load_error2: /* Release IRQs */ bnx2x_free_irq(bp); -load_error: +load_error1: + bnx2x_napi_disable(bp); bnx2x_free_mem(bp); - bp->port.pmf = 0; /* TBD we really need to reset the chip if we want to recover from this */ -- cgit v1.2.3 From 6eccabb301d442e6106ecc84b07a976c2816d9fb Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 03:37:48 +0000 Subject: bnx2x: Carrier off first call Call carrier off should not be called after register_netdev since after register netdev open can be called at any time followed by an interrupt that will set it to carrier_on and the probe will resume control and set it to off Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 707c4bbe46a4..fbd71659cca6 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -9827,6 +9827,8 @@ static int bnx2x_open(struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); + netif_carrier_off(dev); + bnx2x_set_power_state(bp, PCI_D0); return bnx2x_nic_load(bp, LOAD_OPEN); @@ -10332,8 +10334,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, goto init_one_exit; } - netif_carrier_off(dev); - bp->common.name = board_info[ent->driver_data].name; printk(KERN_INFO "%s: %s (%c%d) PCI-E x%d %s found at mem %lx," " IRQ %d, ", dev->name, bp->common.name, -- cgit v1.2.3 From 7cde1c8b79f913a0158bae4f4c612de2cb98e7e4 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 06:01:25 +0000 Subject: bnx2x: Calling napi_del rmmod might hang without this patch since the reference counter is not going down Signed-off-by: Yitchak Gertner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index fbd71659cca6..71fbf2dbda3b 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6547,6 +6547,8 @@ load_error2: bnx2x_free_irq(bp); load_error1: bnx2x_napi_disable(bp); + for_each_queue(bp, i) + netif_napi_del(&bnx2x_fp(bp, i, napi)); bnx2x_free_mem(bp); /* TBD we really need to reset the chip @@ -6855,6 +6857,8 @@ unload_error: bnx2x_free_skbs(bp); for_each_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); + for_each_queue(bp, i) + netif_napi_del(&bnx2x_fp(bp, i, napi)); bnx2x_free_mem(bp); bp->state = BNX2X_STATE_CLOSED; @@ -10481,6 +10485,8 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp) bnx2x_free_skbs(bp); for_each_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); + for_each_queue(bp, i) + netif_napi_del(&bnx2x_fp(bp, i, napi)); bnx2x_free_mem(bp); bp->state = BNX2X_STATE_CLOSED; -- cgit v1.2.3 From 5650d9d4cbf3898d3f9725ccad5dfca6bc086324 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 06:01:29 +0000 Subject: bnx2x: Missing rmb when waiting for FW response Waiting for the FW to response requires a memory barrier Signed-off-by: Michal Kalderon Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 71fbf2dbda3b..f71b8a5872b3 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6622,6 +6622,7 @@ static int bnx2x_stop_leading(struct bnx2x *bp) } cnt--; msleep(1); + rmb(); /* Refresh the dsb_sp_prod */ } bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD; bp->fp[0].state = BNX2X_FP_STATE_CLOSED; -- cgit v1.2.3 From 3910c8ae44c59cebed721e33aa496f0a385b4e03 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 06:01:32 +0000 Subject: bnx2x: loopback test failure A link change interrupt might be queued and activated after the loopback was set and it will cause the loopback to fail. The PHY lock should be kept until the loopback test is over. That implies that the bnx2x_test_link should used within the loopback function and not bnx2x_wait_for_link since that function also takes the PHY link Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index f71b8a5872b3..d95714f780f3 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -8750,18 +8750,17 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) if (loopback_mode == BNX2X_MAC_LOOPBACK) { bp->link_params.loopback_mode = LOOPBACK_BMAC; - bnx2x_acquire_phy_lock(bp); bnx2x_phy_init(&bp->link_params, &bp->link_vars); - bnx2x_release_phy_lock(bp); } else if (loopback_mode == BNX2X_PHY_LOOPBACK) { + u16 cnt = 1000; bp->link_params.loopback_mode = LOOPBACK_XGXS_10; - bnx2x_acquire_phy_lock(bp); bnx2x_phy_init(&bp->link_params, &bp->link_vars); - bnx2x_release_phy_lock(bp); /* wait until link state is restored */ - bnx2x_wait_for_link(bp, link_up); - + if (link_up) + while (cnt-- && bnx2x_test_link(&bp->link_params, + &bp->link_vars)) + msleep(10); } else return -EINVAL; @@ -8867,6 +8866,7 @@ static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up) return BNX2X_LOOPBACK_FAILED; bnx2x_netif_stop(bp, 1); + bnx2x_acquire_phy_lock(bp); if (bnx2x_run_loopback(bp, BNX2X_MAC_LOOPBACK, link_up)) { DP(NETIF_MSG_PROBE, "MAC loopback failed\n"); @@ -8878,6 +8878,7 @@ static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up) rc |= BNX2X_PHY_LOOPBACK_FAILED; } + bnx2x_release_phy_lock(bp); bnx2x_netif_start(bp); return rc; -- cgit v1.2.3 From 5422a2257350d984094e655b2361abed51a9ddc1 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 06:01:37 +0000 Subject: bnx2x: Version Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index d95714f780f3..4b84f6ce5ed2 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -57,8 +57,8 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.45.24" -#define DRV_MODULE_RELDATE "2009/01/14" +#define DRV_MODULE_VERSION "1.45.25" +#define DRV_MODULE_RELDATE "2009/01/22" #define BNX2X_BC_VER 0x040200 /* Time in jiffies before concluding the transmitter is hung */ -- cgit v1.2.3 From e8b5fc514d1c7637cb4b8f77e7d8ac33ef66130c Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Mon, 26 Jan 2009 12:36:42 -0800 Subject: bnx2x: tx_has_work should not wait for FW The current tx_has_work waited until all packets sent by the driver are marked as completed by the FW. This is too greedy and it causes the bnx2x_poll to spin in vain. The driver should only check that all packets FW already completed are freed - only in unload flow the driver should make sure that transmit queue is empty Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers/net/bnx2x_main.c') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 4b84f6ce5ed2..d3e7775a9ccf 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -57,8 +57,8 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.45.25" -#define DRV_MODULE_RELDATE "2009/01/22" +#define DRV_MODULE_VERSION "1.45.26" +#define DRV_MODULE_RELDATE "2009/01/26" #define BNX2X_BC_VER 0x040200 /* Time in jiffies before concluding the transmitter is hung */ @@ -740,8 +740,15 @@ static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp) /* Tell compiler that status block fields can change */ barrier(); tx_cons_sb = le16_to_cpu(*fp->tx_cons_sb); - return ((fp->tx_pkt_prod != tx_cons_sb) || - (fp->tx_pkt_prod != fp->tx_pkt_cons)); + return (fp->tx_pkt_cons != tx_cons_sb); +} + +static inline int bnx2x_has_tx_work_unload(struct bnx2x_fastpath *fp) +{ + /* Tell compiler that consumer and producer can change */ + barrier(); + return (fp->tx_pkt_prod != fp->tx_pkt_cons); + } /* free skb in the packet ring at pos idx @@ -6729,7 +6736,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) cnt = 1000; smp_rmb(); - while (bnx2x_has_tx_work(fp)) { + while (bnx2x_has_tx_work_unload(fp)) { bnx2x_tx_int(fp, 1000); if (!cnt) { -- cgit v1.2.3