From: Andy Gospodarek <gospo@redhat.com> Date: Mon, 10 Nov 2008 12:00:39 -0500 Subject: [net] bnx2x: eeh, unload, probe, and endian fixes Message-id: 20081110170039.GD409@gospo.rdu.redhat.com O-Subject: [RHEL5.3 PATCH] bnx2x: eeh, unload, probe, and endian fixes Bugzilla: 468922 RH-Acked-by: John W. Linville <linville@redhat.com> RH-Acked-by: John Feeney <jfeeney@redhat.com> RH-Acked-by: Michal Schmidt <mschmidt@redhat.com> RH-Acked-by: Ivan Vecera <ivecera@redhat.com> This patch is made of 5 recent upstream additions that we should strongly consider for 5.3. The one brought to our attention by a partner was 9a0354405feb0f8bd460349a93db05e4cca8d166, but I can easily see how f8ef6e44474037b1671bb913bc259e048a7d5548 will be a problem one it gets tested. We do have at least one partner who is shipping bnx2x hardware on ppc, so I would also like to consider 7d96567ac0527703cf1b80043fc0ebd7f21a10ad, so we don't hear more complaints about performance issues. There is only a small change for 12b56ea89e70d4b04f2f5199750310e82894ebbd and it seems good as well. commit ca8eac55fa554043c57fd18d595ca356e752833e Author: Eilon Greenstein <eilong@broadcom.com> Date: Mon Nov 3 16:46:58 2008 -0800 bnx2x: Version Update commit 12b56ea89e70d4b04f2f5199750310e82894ebbd Author: Eilon Greenstein <eilong@broadcom.com> Date: Mon Nov 3 16:46:40 2008 -0800 bnx2x: Calling netif_carrier_off at the end of the probe commit 7d96567ac0527703cf1b80043fc0ebd7f21a10ad Author: Eilon Greenstein <eilong@broadcom.com> Date: Mon Nov 3 16:46:19 2008 -0800 bnx2x: PCI configuration bug on big-endian commit 9a0354405feb0f8bd460349a93db05e4cca8d166 Author: Eilon Greenstein <eilong@broadcom.com> Date: Mon Nov 3 16:45:55 2008 -0800 bnx2x: Removing the PMF indication when unloading commit f8ef6e44474037b1671bb913bc259e048a7d5548 Author: Yitchak Gertner <gertner@broadcom.com> Date: Tue Sep 9 05:07:25 2008 -0700 bnx2x: EEH recovery fix These should resolve the request in RHBZ 468922. Alex Chiang has already indicated that the module unload fixes will resolve his issue and I'm hoping he'll smoke test the rest of this patch as well. diff --git a/drivers/net/bnx2x_init.h b/drivers/net/bnx2x_init.h index 130927c..a6c0b3a 100644 --- a/drivers/net/bnx2x_init.h +++ b/drivers/net/bnx2x_init.h @@ -564,14 +564,15 @@ static const struct arb_line write_arb_addr[NUM_WR_Q-1] = { static void bnx2x_init_pxp(struct bnx2x *bp) { + u16 devctl; int r_order, w_order; u32 val, i; pci_read_config_word(bp->pdev, - bp->pcie_cap + PCI_EXP_DEVCTL, (u16 *)&val); - DP(NETIF_MSG_HW, "read 0x%x from devctl\n", (u16)val); - w_order = ((val & PCI_EXP_DEVCTL_PAYLOAD) >> 5); - r_order = ((val & PCI_EXP_DEVCTL_READRQ) >> 12); + bp->pcie_cap + PCI_EXP_DEVCTL, &devctl); + DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl); + w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); + r_order = ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12); if (r_order > MAX_RD_ORD) { DP(NETIF_MSG_HW, "read order of %d order adjusted to %d\n", diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index b01eee3..3be48aa 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -59,8 +59,8 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.45.21" -#define DRV_MODULE_RELDATE "2008/09/03" +#define DRV_MODULE_VERSION "1.45.23" +#define DRV_MODULE_RELDATE "2008/11/03" #define BNX2X_BC_VER 0x040200 /* Time in jiffies before concluding the transmitter is hung */ @@ -649,15 +649,16 @@ static void bnx2x_int_disable(struct bnx2x *bp) BNX2X_ERR("BUG! proper val not read from IGU!\n"); } -static void bnx2x_int_disable_sync(struct bnx2x *bp) +static void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw) { int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0; int i; /* disable interrupt handling */ atomic_inc(&bp->intr_sem); - /* prevent the HW from sending interrupts */ - bnx2x_int_disable(bp); + if (disable_hw) + /* prevent the HW from sending interrupts */ + bnx2x_int_disable(bp); /* make sure all ISRs are done */ if (msix) { @@ -6086,9 +6087,9 @@ static void bnx2x_netif_start(struct bnx2x *bp) } } -static void bnx2x_netif_stop(struct bnx2x *bp) +static void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw) { - bnx2x_int_disable_sync(bp); + bnx2x_int_disable_sync(bp, disable_hw); if (netif_running(bp->dev)) { bnx2x_napi_disable(bp); netif_tx_disable(bp->dev); @@ -6472,11 +6473,12 @@ load_rings_free: 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); + bnx2x_int_disable_sync(bp, 1); /* Release IRQs */ bnx2x_free_irq(bp); load_error: bnx2x_free_mem(bp); + bp->port.pmf = 0; /* TBD we really need to reset the chip if we want to recover from this */ @@ -6647,7 +6649,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) bp->rx_mode = BNX2X_RX_MODE_NONE; bnx2x_set_storm_rx_mode(bp); - bnx2x_netif_stop(bp); + bnx2x_netif_stop(bp, 1); if (!netif_running(bp->dev)) bnx2x_napi_disable(bp); del_timer_sync(&bp->timer); @@ -6787,6 +6789,7 @@ unload_error: /* Report UNLOAD_DONE to MCP */ if (!BP_NOMCP(bp)) 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); @@ -8794,7 +8797,7 @@ static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up) if (!netif_running(bp->dev)) return BNX2X_LOOPBACK_FAILED; - bnx2x_netif_stop(bp); + bnx2x_netif_stop(bp, 1); if (bnx2x_run_loopback(bp, BNX2X_MAC_LOOPBACK, link_up)) { DP(NETIF_MSG_PROBE, "MAC loopback failed\n"); @@ -10221,8 +10224,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, return -ENOMEM; } - netif_carrier_off(dev); - bp = netdev_priv(dev); bp->msglevel = debug; @@ -10249,6 +10250,8 @@ 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, @@ -10370,6 +10373,74 @@ static int bnx2x_resume(struct pci_dev *pdev) return rc; } +static int bnx2x_eeh_nic_unload(struct bnx2x *bp) +{ + int i; + + bp->state = BNX2X_STATE_ERROR; + + bp->rx_mode = BNX2X_RX_MODE_NONE; + + bnx2x_netif_stop(bp, 0); + + del_timer_sync(&bp->timer); + bp->stats_state = STATS_STATE_DISABLED; + DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n"); + + /* Release IRQs */ + bnx2x_free_irq(bp); + + if (CHIP_IS_E1(bp)) { + struct mac_configuration_cmd *config = + bnx2x_sp(bp, mcast_config); + + for (i = 0; i < config->hdr.length_6b; i++) + CAM_INVALIDATE(config->config_table[i]); + } + + /* 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); + bnx2x_free_mem(bp); + + bp->state = BNX2X_STATE_CLOSED; + + netif_carrier_off(bp->dev); + + return 0; +} + +static void bnx2x_eeh_recover(struct bnx2x *bp) +{ + u32 val; + + mutex_init(&bp->port.phy_mutex); + + bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR); + bp->link_params.shmem_base = bp->common.shmem_base; + BNX2X_DEV_INFO("shmem offset is 0x%x\n", bp->common.shmem_base); + + if (!bp->common.shmem_base || + (bp->common.shmem_base < 0xA0000) || + (bp->common.shmem_base >= 0xC0000)) { + BNX2X_DEV_INFO("MCP not active\n"); + bp->flags |= NO_MCP_FLAG; + return; + } + + val = SHMEM_RD(bp, validity_map[BP_PORT(bp)]); + if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) + != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) + BNX2X_ERR("BAD MCP validity signature\n"); + + if (!BP_NOMCP(bp)) { + bp->fw_seq = (SHMEM_RD(bp, func_mb[BP_FUNC(bp)].drv_mb_header) + & DRV_MSG_SEQ_NUMBER_MASK); + BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq); + } +} + /** * bnx2x_io_error_detected - called when PCI error is detected * @pdev: Pointer to PCI device @@ -10389,7 +10460,7 @@ static pci_ers_result_t bnx2x_io_error_detected(struct pci_dev *pdev, netif_device_detach(dev); if (netif_running(dev)) - bnx2x_nic_unload(bp, UNLOAD_CLOSE); + bnx2x_eeh_nic_unload(bp); pci_disable_device(pdev); @@ -10444,8 +10515,10 @@ static void bnx2x_io_resume(struct pci_dev *pdev) rtnl_lock(); + bnx2x_eeh_recover(bp); + if (netif_running(dev)) - bnx2x_nic_load(bp, LOAD_OPEN); + bnx2x_nic_load(bp, LOAD_NORMAL); netif_device_attach(dev);