aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuval Mintz <yuvalmin@broadcom.com>2012-03-26 16:47:07 -0400
committerDavid S. Miller <davem@davemloft.net>2012-03-27 22:41:34 -0400
commit452427b015b1b0cbbef7b6207908726837d39d57 (patch)
tree221356cb1d3447160c5ad5741cf5e5107801540e
parenta2daf263107ba3eb6db33931881731fa51c95045 (diff)
bnx2x: previous driver unload revised
The flow in which the bnx2x driver starts after a previous driver has been terminated in an 'unclean' manner has several bugs and FW risks, which makes it possible for the driver to fail after boot-from-SAN or kdump. This patch contains a revised flow which performs a safer initialization, solving the possible crash scenarios. Notice this patch contains lines with over 80 characters, as it keeps print-strings in a single line. Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h7
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c40
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h3
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h3
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c1
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c464
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h4
8 files changed, 417 insertions, 107 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index e37161f1925..2c9ee552dff 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1173,6 +1173,13 @@ enum {
1173}; 1173};
1174 1174
1175 1175
1176struct bnx2x_prev_path_list {
1177 u8 bus;
1178 u8 slot;
1179 u8 path;
1180 struct list_head list;
1181};
1182
1176struct bnx2x { 1183struct bnx2x {
1177 /* Fields used in the tx and intr/napi performance paths 1184 /* Fields used in the tx and intr/napi performance paths
1178 * are grouped together in the beginning of the structure 1185 * are grouped together in the beginning of the structure
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index f1f3ca65667..44556b719e8 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -1721,6 +1721,29 @@ static void bnx2x_squeeze_objects(struct bnx2x *bp)
1721 } while (0) 1721 } while (0)
1722#endif 1722#endif
1723 1723
1724bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err)
1725{
1726 /* build FW version dword */
1727 u32 my_fw = (BCM_5710_FW_MAJOR_VERSION) +
1728 (BCM_5710_FW_MINOR_VERSION << 8) +
1729 (BCM_5710_FW_REVISION_VERSION << 16) +
1730 (BCM_5710_FW_ENGINEERING_VERSION << 24);
1731
1732 /* read loaded FW from chip */
1733 u32 loaded_fw = REG_RD(bp, XSEM_REG_PRAM);
1734
1735 DP(NETIF_MSG_IFUP, "loaded fw %x, my fw %x\n", loaded_fw, my_fw);
1736
1737 if (loaded_fw != my_fw) {
1738 if (is_err)
1739 BNX2X_ERR("bnx2x with FW %x was already loaded, which mismatches my %x FW. aborting\n",
1740 loaded_fw, my_fw);
1741 return false;
1742 }
1743
1744 return true;
1745}
1746
1724/* must be called with rtnl_lock */ 1747/* must be called with rtnl_lock */
1725int bnx2x_nic_load(struct bnx2x *bp, int load_mode) 1748int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
1726{ 1749{
@@ -1815,23 +1838,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
1815 } 1838 }
1816 if (load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP && 1839 if (load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP &&
1817 load_code != FW_MSG_CODE_DRV_LOAD_COMMON) { 1840 load_code != FW_MSG_CODE_DRV_LOAD_COMMON) {
1818 /* build FW version dword */
1819 u32 my_fw = (BCM_5710_FW_MAJOR_VERSION) +
1820 (BCM_5710_FW_MINOR_VERSION << 8) +
1821 (BCM_5710_FW_REVISION_VERSION << 16) +
1822 (BCM_5710_FW_ENGINEERING_VERSION << 24);
1823
1824 /* read loaded FW from chip */
1825 u32 loaded_fw = REG_RD(bp, XSEM_REG_PRAM);
1826
1827 DP(BNX2X_MSG_SP, "loaded fw %x, my fw %x",
1828 loaded_fw, my_fw);
1829
1830 /* abort nic load if version mismatch */ 1841 /* abort nic load if version mismatch */
1831 if (my_fw != loaded_fw) { 1842 if (!bnx2x_test_firmware_version(bp, true)) {
1832 BNX2X_ERR("bnx2x with FW %x already loaded, "
1833 "which mismatches my %x FW. aborting",
1834 loaded_fw, my_fw);
1835 rc = -EBUSY; 1843 rc = -EBUSY;
1836 LOAD_ERROR_EXIT(bp, load_error2); 1844 LOAD_ERROR_EXIT(bp, load_error2);
1837 } 1845 }
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index 8b163388659..5c27454d2ec 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -431,6 +431,9 @@ void bnx2x_panic_dump(struct bnx2x *bp);
431 431
432void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl); 432void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl);
433 433
434/* validate currect fw is loaded */
435bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err);
436
434/* dev_close main block */ 437/* dev_close main block */
435int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode); 438int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode);
436 439
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
index 5d71b7d4323..dbff5915b81 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
@@ -1251,6 +1251,9 @@ struct drv_func_mb {
1251 1251
1252 #define DRV_MSG_CODE_LINK_STATUS_CHANGED 0x01000000 1252 #define DRV_MSG_CODE_LINK_STATUS_CHANGED 0x01000000
1253 1253
1254 #define DRV_MSG_CODE_INITIATE_FLR 0x02000000
1255 #define REQ_BC_VER_4_INITIATE_FLR 0x00070213
1256
1254 #define BIOS_MSG_CODE_LIC_CHALLENGE 0xff010000 1257 #define BIOS_MSG_CODE_LIC_CHALLENGE 0xff010000
1255 #define BIOS_MSG_CODE_LIC_RESPONSE 0xff020000 1258 #define BIOS_MSG_CODE_LIC_RESPONSE 0xff020000
1256 #define BIOS_MSG_CODE_VIRT_MAC_PRIM 0xff030000 1259 #define BIOS_MSG_CODE_VIRT_MAC_PRIM 0xff030000
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index beb4cdbdb6e..efa557b76ac 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -35,7 +35,6 @@
35#define ETH_MAX_PACKET_SIZE 1500 35#define ETH_MAX_PACKET_SIZE 1500
36#define ETH_MAX_JUMBO_PACKET_SIZE 9600 36#define ETH_MAX_JUMBO_PACKET_SIZE 9600
37#define MDIO_ACCESS_TIMEOUT 1000 37#define MDIO_ACCESS_TIMEOUT 1000
38#define BMAC_CONTROL_RX_ENABLE 2
39#define WC_LANE_MAX 4 38#define WC_LANE_MAX 4
40#define I2C_SWITCH_WIDTH 2 39#define I2C_SWITCH_WIDTH 2
41#define I2C_BSC0 0 40#define I2C_BSC0 0
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
index 7ba557a610d..763535ee483 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
@@ -89,6 +89,8 @@
89#define PFC_BRB_FULL_LB_XON_THRESHOLD 250 89#define PFC_BRB_FULL_LB_XON_THRESHOLD 250
90 90
91#define MAXVAL(a, b) (((a) > (b)) ? (a) : (b)) 91#define MAXVAL(a, b) (((a) > (b)) ? (a) : (b))
92
93#define BMAC_CONTROL_RX_ENABLE 2
92/***********************************************************/ 94/***********************************************************/
93/* Structs */ 95/* Structs */
94/***********************************************************/ 96/***********************************************************/
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index f7f9aa80726..e077d250872 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -52,6 +52,7 @@
52#include <linux/prefetch.h> 52#include <linux/prefetch.h>
53#include <linux/zlib.h> 53#include <linux/zlib.h>
54#include <linux/io.h> 54#include <linux/io.h>
55#include <linux/semaphore.h>
55#include <linux/stringify.h> 56#include <linux/stringify.h>
56#include <linux/vmalloc.h> 57#include <linux/vmalloc.h>
57 58
@@ -211,6 +212,10 @@ static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = {
211 212
212MODULE_DEVICE_TABLE(pci, bnx2x_pci_tbl); 213MODULE_DEVICE_TABLE(pci, bnx2x_pci_tbl);
213 214
215/* Global resources for unloading a previously loaded device */
216#define BNX2X_PREV_WAIT_NEEDED 1
217static DEFINE_SEMAPHORE(bnx2x_prev_sem);
218static LIST_HEAD(bnx2x_prev_list);
214/**************************************************************************** 219/****************************************************************************
215* General service functions 220* General service functions
216****************************************************************************/ 221****************************************************************************/
@@ -8812,109 +8817,371 @@ static inline void bnx2x_undi_int_disable(struct bnx2x *bp)
8812 bnx2x_undi_int_disable_e1h(bp); 8817 bnx2x_undi_int_disable_e1h(bp);
8813} 8818}
8814 8819
8815static void __devinit bnx2x_undi_unload(struct bnx2x *bp) 8820static void __devinit bnx2x_prev_unload_close_mac(struct bnx2x *bp)
8816{ 8821{
8817 u32 val; 8822 u32 val, base_addr, offset, mask, reset_reg;
8823 bool mac_stopped = false;
8824 u8 port = BP_PORT(bp);
8818 8825
8819 /* possibly another driver is trying to reset the chip */ 8826 reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2);
8820 bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
8821 8827
8822 /* check if doorbell queue is reset */ 8828 if (!CHIP_IS_E3(bp)) {
8823 if (REG_RD(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET) 8829 val = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port * 4);
8824 & MISC_REGISTERS_RESET_REG_1_RST_DORQ) { 8830 mask = MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port;
8831 if ((mask & reset_reg) && val) {
8832 u32 wb_data[2];
8833 BNX2X_DEV_INFO("Disable bmac Rx\n");
8834 base_addr = BP_PORT(bp) ? NIG_REG_INGRESS_BMAC1_MEM
8835 : NIG_REG_INGRESS_BMAC0_MEM;
8836 offset = CHIP_IS_E2(bp) ? BIGMAC2_REGISTER_BMAC_CONTROL
8837 : BIGMAC_REGISTER_BMAC_CONTROL;
8825 8838
8826 /* 8839 /*
8827 * Check if it is the UNDI driver 8840 * use rd/wr since we cannot use dmae. This is safe
8841 * since MCP won't access the bus due to the request
8842 * to unload, and no function on the path can be
8843 * loaded at this time.
8844 */
8845 wb_data[0] = REG_RD(bp, base_addr + offset);
8846 wb_data[1] = REG_RD(bp, base_addr + offset + 0x4);
8847 wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
8848 REG_WR(bp, base_addr + offset, wb_data[0]);
8849 REG_WR(bp, base_addr + offset + 0x4, wb_data[1]);
8850
8851 }
8852 BNX2X_DEV_INFO("Disable emac Rx\n");
8853 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4, 0);
8854
8855 mac_stopped = true;
8856 } else {
8857 if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) {
8858 BNX2X_DEV_INFO("Disable xmac Rx\n");
8859 base_addr = BP_PORT(bp) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
8860 val = REG_RD(bp, base_addr + XMAC_REG_PFC_CTRL_HI);
8861 REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI,
8862 val & ~(1 << 1));
8863 REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI,
8864 val | (1 << 1));
8865 REG_WR(bp, base_addr + XMAC_REG_CTRL, 0);
8866 mac_stopped = true;
8867 }
8868 mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port;
8869 if (mask & reset_reg) {
8870 BNX2X_DEV_INFO("Disable umac Rx\n");
8871 base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
8872 REG_WR(bp, base_addr + UMAC_REG_COMMAND_CONFIG, 0);
8873 mac_stopped = true;
8874 }
8875 }
8876
8877 if (mac_stopped)
8878 msleep(20);
8879
8880}
8881
8882#define BNX2X_PREV_UNDI_PROD_ADDR(p) (BAR_TSTRORM_INTMEM + 0x1508 + ((p) << 4))
8883#define BNX2X_PREV_UNDI_RCQ(val) ((val) & 0xffff)
8884#define BNX2X_PREV_UNDI_BD(val) ((val) >> 16 & 0xffff)
8885#define BNX2X_PREV_UNDI_PROD(rcq, bd) ((bd) << 16 | (rcq))
8886
8887static void __devinit bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port,
8888 u8 inc)
8889{
8890 u16 rcq, bd;
8891 u32 tmp_reg = REG_RD(bp, BNX2X_PREV_UNDI_PROD_ADDR(port));
8892
8893 rcq = BNX2X_PREV_UNDI_RCQ(tmp_reg) + inc;
8894 bd = BNX2X_PREV_UNDI_BD(tmp_reg) + inc;
8895
8896 tmp_reg = BNX2X_PREV_UNDI_PROD(rcq, bd);
8897 REG_WR(bp, BNX2X_PREV_UNDI_PROD_ADDR(port), tmp_reg);
8898
8899 BNX2X_DEV_INFO("UNDI producer [%d] rings bd -> 0x%04x, rcq -> 0x%04x\n",
8900 port, bd, rcq);
8901}
8902
8903static int __devinit bnx2x_prev_mcp_done(struct bnx2x *bp)
8904{
8905 u32 rc = bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
8906 if (!rc) {
8907 BNX2X_ERR("MCP response failure, aborting\n");
8908 return -EBUSY;
8909 }
8910
8911 return 0;
8912}
8913
8914static bool __devinit bnx2x_prev_is_path_marked(struct bnx2x *bp)
8915{
8916 struct bnx2x_prev_path_list *tmp_list;
8917 int rc = false;
8918
8919 if (down_trylock(&bnx2x_prev_sem))
8920 return false;
8921
8922 list_for_each_entry(tmp_list, &bnx2x_prev_list, list) {
8923 if (PCI_SLOT(bp->pdev->devfn) == tmp_list->slot &&
8924 bp->pdev->bus->number == tmp_list->bus &&
8925 BP_PATH(bp) == tmp_list->path) {
8926 rc = true;
8927 BNX2X_DEV_INFO("Path %d was already cleaned from previous drivers\n",
8928 BP_PATH(bp));
8929 break;
8930 }
8931 }
8932
8933 up(&bnx2x_prev_sem);
8934
8935 return rc;
8936}
8937
8938static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp)
8939{
8940 struct bnx2x_prev_path_list *tmp_list;
8941 int rc;
8942
8943 tmp_list = (struct bnx2x_prev_path_list *)
8944 kmalloc(sizeof(struct bnx2x_prev_path_list), GFP_KERNEL);
8945 if (!tmp_list) {
8946 BNX2X_ERR("Failed to allocate 'bnx2x_prev_path_list'\n");
8947 return -ENOMEM;
8948 }
8949
8950 tmp_list->bus = bp->pdev->bus->number;
8951 tmp_list->slot = PCI_SLOT(bp->pdev->devfn);
8952 tmp_list->path = BP_PATH(bp);
8953
8954 rc = down_interruptible(&bnx2x_prev_sem);
8955 if (rc) {
8956 BNX2X_ERR("Received %d when tried to take lock\n", rc);
8957 kfree(tmp_list);
8958 } else {
8959 BNX2X_DEV_INFO("Marked path [%d] - finished previous unload\n",
8960 BP_PATH(bp));
8961 list_add(&tmp_list->list, &bnx2x_prev_list);
8962 up(&bnx2x_prev_sem);
8963 }
8964
8965 return rc;
8966}
8967
8968static bool __devinit bnx2x_can_flr(struct bnx2x *bp)
8969{
8970 int pos;
8971 u32 cap;
8972 struct pci_dev *dev = bp->pdev;
8973
8974 pos = pci_pcie_cap(dev);
8975 if (!pos)
8976 return false;
8977
8978 pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP, &cap);
8979 if (!(cap & PCI_EXP_DEVCAP_FLR))
8980 return false;
8981
8982 return true;
8983}
8984
8985static int __devinit bnx2x_do_flr(struct bnx2x *bp)
8986{
8987 int i, pos;
8988 u16 status;
8989 struct pci_dev *dev = bp->pdev;
8990
8991 /* probe the capability first */
8992 if (bnx2x_can_flr(bp))
8993 return -ENOTTY;
8994
8995 pos = pci_pcie_cap(dev);
8996 if (!pos)
8997 return -ENOTTY;
8998
8999 /* Wait for Transaction Pending bit clean */
9000 for (i = 0; i < 4; i++) {
9001 if (i)
9002 msleep((1 << (i - 1)) * 100);
9003
9004 pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status);
9005 if (!(status & PCI_EXP_DEVSTA_TRPND))
9006 goto clear;
9007 }
9008
9009 dev_err(&dev->dev,
9010 "transaction is not cleared; proceeding with reset anyway\n");
9011
9012clear:
9013 if (bp->common.bc_ver < REQ_BC_VER_4_INITIATE_FLR) {
9014 BNX2X_ERR("FLR not supported by BC_VER: 0x%x\n",
9015 bp->common.bc_ver);
9016 return -EINVAL;
9017 }
9018
9019 bnx2x_fw_command(bp, DRV_MSG_CODE_INITIATE_FLR, 0);
9020
9021 return 0;
9022}
9023
9024static int __devinit bnx2x_prev_unload_uncommon(struct bnx2x *bp)
9025{
9026 int rc;
9027
9028 BNX2X_DEV_INFO("Uncommon unload Flow\n");
9029
9030 /* Test if previous unload process was already finished for this path */
9031 if (bnx2x_prev_is_path_marked(bp))
9032 return bnx2x_prev_mcp_done(bp);
9033
9034 /* If function has FLR capabilities, and existing FW version matches
9035 * the one required, then FLR will be sufficient to clean any residue
9036 * left by previous driver
9037 */
9038 if (bnx2x_test_firmware_version(bp, false) && bnx2x_can_flr(bp))
9039 return bnx2x_do_flr(bp);
9040
9041 /* Close the MCP request, return failure*/
9042 rc = bnx2x_prev_mcp_done(bp);
9043 if (!rc)
9044 rc = BNX2X_PREV_WAIT_NEEDED;
9045
9046 return rc;
9047}
9048
9049static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
9050{
9051 u32 reset_reg, tmp_reg = 0, rc;
9052 /* It is possible a previous function received 'common' answer,
9053 * but hasn't loaded yet, therefore creating a scenario of
9054 * multiple functions receiving 'common' on the same path.
9055 */
9056 BNX2X_DEV_INFO("Common unload Flow\n");
9057
9058 if (bnx2x_prev_is_path_marked(bp))
9059 return bnx2x_prev_mcp_done(bp);
9060
9061 reset_reg = REG_RD(bp, MISC_REG_RESET_REG_1);
9062
9063 /* Reset should be performed after BRB is emptied */
9064 if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) {
9065 u32 timer_count = 1000;
9066 bool prev_undi = false;
9067
9068 /* Close the MAC Rx to prevent BRB from filling up */
9069 bnx2x_prev_unload_close_mac(bp);
9070
9071 /* Check if the UNDI driver was previously loaded
8828 * UNDI driver initializes CID offset for normal bell to 0x7 9072 * UNDI driver initializes CID offset for normal bell to 0x7
8829 */ 9073 */
8830 val = REG_RD(bp, DORQ_REG_NORM_CID_OFST); 9074 reset_reg = REG_RD(bp, MISC_REG_RESET_REG_1);
8831 if (val == 0x7) { 9075 if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_DORQ) {
8832 u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; 9076 tmp_reg = REG_RD(bp, DORQ_REG_NORM_CID_OFST);
8833 /* save our pf_num */ 9077 if (tmp_reg == 0x7) {
8834 int orig_pf_num = bp->pf_num; 9078 BNX2X_DEV_INFO("UNDI previously loaded\n");
8835 int port; 9079 prev_undi = true;
8836 u32 swap_en, swap_val, value; 9080 /* clear the UNDI indication */
8837 9081 REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0);
8838 /* clear the UNDI indication */
8839 REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0);
8840
8841 BNX2X_DEV_INFO("UNDI is active! reset device\n");
8842
8843 /* try unload UNDI on port 0 */
8844 bp->pf_num = 0;
8845 bp->fw_seq =
8846 (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
8847 DRV_MSG_SEQ_NUMBER_MASK);
8848 reset_code = bnx2x_fw_command(bp, reset_code, 0);
8849
8850 /* if UNDI is loaded on the other port */
8851 if (reset_code != FW_MSG_CODE_DRV_UNLOAD_COMMON) {
8852
8853 /* send "DONE" for previous unload */
8854 bnx2x_fw_command(bp,
8855 DRV_MSG_CODE_UNLOAD_DONE, 0);
8856
8857 /* unload UNDI on port 1 */
8858 bp->pf_num = 1;
8859 bp->fw_seq =
8860 (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
8861 DRV_MSG_SEQ_NUMBER_MASK);
8862 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
8863
8864 bnx2x_fw_command(bp, reset_code, 0);
8865 } 9082 }
9083 }
9084 /* wait until BRB is empty */
9085 tmp_reg = REG_RD(bp, BRB1_REG_NUM_OF_FULL_BLOCKS);
9086 while (timer_count) {
9087 u32 prev_brb = tmp_reg;
8866 9088
8867 bnx2x_undi_int_disable(bp); 9089 tmp_reg = REG_RD(bp, BRB1_REG_NUM_OF_FULL_BLOCKS);
8868 port = BP_PORT(bp); 9090 if (!tmp_reg)
8869 9091 break;
8870 /* close input traffic and wait for it */
8871 /* Do not rcv packets to BRB */
8872 REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_DRV_MASK :
8873 NIG_REG_LLH0_BRB1_DRV_MASK), 0x0);
8874 /* Do not direct rcv packets that are not for MCP to
8875 * the BRB */
8876 REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_NOT_MCP :
8877 NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
8878 /* clear AEU */
8879 REG_WR(bp, (port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
8880 MISC_REG_AEU_MASK_ATTN_FUNC_0), 0);
8881 msleep(10);
8882
8883 /* save NIG port swap info */
8884 swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
8885 swap_en = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
8886 /* reset device */
8887 REG_WR(bp,
8888 GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
8889 0xd3ffffff);
8890
8891 value = 0x1400;
8892 if (CHIP_IS_E3(bp)) {
8893 value |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
8894 value |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
8895 }
8896 9092
8897 REG_WR(bp, 9093 BNX2X_DEV_INFO("BRB still has 0x%08x\n", tmp_reg);
8898 GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
8899 value);
8900 9094
8901 /* take the NIG out of reset and restore swap values */ 9095 /* reset timer as long as BRB actually gets emptied */
8902 REG_WR(bp, 9096 if (prev_brb > tmp_reg)
8903 GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 9097 timer_count = 1000;
8904 MISC_REGISTERS_RESET_REG_1_RST_NIG); 9098 else
8905 REG_WR(bp, NIG_REG_PORT_SWAP, swap_val); 9099 timer_count--;
8906 REG_WR(bp, NIG_REG_STRAP_OVERRIDE, swap_en);
8907 9100
8908 /* send unload done to the MCP */ 9101 /* If UNDI resides in memory, manually increment it */
8909 bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0); 9102 if (prev_undi)
9103 bnx2x_prev_unload_undi_inc(bp, BP_PORT(bp), 1);
8910 9104
8911 /* restore our func and fw_seq */ 9105 udelay(10);
8912 bp->pf_num = orig_pf_num;
8913 } 9106 }
9107
9108 if (!timer_count)
9109 BNX2X_ERR("Failed to empty BRB, hope for the best\n");
9110
8914 } 9111 }
8915 9112
8916 /* now it's safe to release the lock */ 9113 /* No packets are in the pipeline, path is ready for reset */
8917 bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET); 9114 bnx2x_reset_common(bp);
9115
9116 rc = bnx2x_prev_mark_path(bp);
9117 if (rc) {
9118 bnx2x_prev_mcp_done(bp);
9119 return rc;
9120 }
9121
9122 return bnx2x_prev_mcp_done(bp);
9123}
9124
9125static int __devinit bnx2x_prev_unload(struct bnx2x *bp)
9126{
9127 int time_counter = 10;
9128 u32 rc, fw, hw_lock_reg, hw_lock_val;
9129 BNX2X_DEV_INFO("Entering Previous Unload Flow\n");
9130
9131 /* Release previously held locks */
9132 hw_lock_reg = (BP_FUNC(bp) <= 5) ?
9133 (MISC_REG_DRIVER_CONTROL_1 + BP_FUNC(bp) * 8) :
9134 (MISC_REG_DRIVER_CONTROL_7 + (BP_FUNC(bp) - 6) * 8);
9135
9136 hw_lock_val = (REG_RD(bp, hw_lock_reg));
9137 if (hw_lock_val) {
9138 if (hw_lock_val & HW_LOCK_RESOURCE_NVRAM) {
9139 BNX2X_DEV_INFO("Release Previously held NVRAM lock\n");
9140 REG_WR(bp, MCP_REG_MCPR_NVM_SW_ARB,
9141 (MCPR_NVM_SW_ARB_ARB_REQ_CLR1 << BP_PORT(bp)));
9142 }
9143
9144 BNX2X_DEV_INFO("Release Previously held hw lock\n");
9145 REG_WR(bp, hw_lock_reg, 0xffffffff);
9146 } else
9147 BNX2X_DEV_INFO("No need to release hw/nvram locks\n");
9148
9149 if (MCPR_ACCESS_LOCK_LOCK & REG_RD(bp, MCP_REG_MCPR_ACCESS_LOCK)) {
9150 BNX2X_DEV_INFO("Release previously held alr\n");
9151 REG_WR(bp, MCP_REG_MCPR_ACCESS_LOCK, 0);
9152 }
9153
9154
9155 do {
9156 /* Lock MCP using an unload request */
9157 fw = bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS, 0);
9158 if (!fw) {
9159 BNX2X_ERR("MCP response failure, aborting\n");
9160 rc = -EBUSY;
9161 break;
9162 }
9163
9164 if (fw == FW_MSG_CODE_DRV_UNLOAD_COMMON) {
9165 rc = bnx2x_prev_unload_common(bp);
9166 break;
9167 }
9168
9169 /* non-common reply from MCP night require looping */
9170 rc = bnx2x_prev_unload_uncommon(bp);
9171 if (rc != BNX2X_PREV_WAIT_NEEDED)
9172 break;
9173
9174 msleep(20);
9175 } while (--time_counter);
9176
9177 if (!time_counter || rc) {
9178 BNX2X_ERR("Failed unloading previous driver, aborting\n");
9179 rc = -EBUSY;
9180 }
9181
9182 BNX2X_DEV_INFO("Finished Previous Unload Flow [%d]\n", rc);
9183
9184 return rc;
8918} 9185}
8919 9186
8920static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) 9187static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
@@ -10100,8 +10367,16 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
10100 func = BP_FUNC(bp); 10367 func = BP_FUNC(bp);
10101 10368
10102 /* need to reset chip if undi was active */ 10369 /* need to reset chip if undi was active */
10103 if (!BP_NOMCP(bp)) 10370 if (!BP_NOMCP(bp)) {
10104 bnx2x_undi_unload(bp); 10371 /* init fw_seq */
10372 bp->fw_seq =
10373 SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
10374 DRV_MSG_SEQ_NUMBER_MASK;
10375 BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
10376
10377 bnx2x_prev_unload(bp);
10378 }
10379
10105 10380
10106 if (CHIP_REV_IS_FPGA(bp)) 10381 if (CHIP_REV_IS_FPGA(bp))
10107 dev_err(&bp->pdev->dev, "FPGA detected\n"); 10382 dev_err(&bp->pdev->dev, "FPGA detected\n");
@@ -11431,9 +11706,18 @@ static int __init bnx2x_init(void)
11431 11706
11432static void __exit bnx2x_cleanup(void) 11707static void __exit bnx2x_cleanup(void)
11433{ 11708{
11709 struct list_head *pos, *q;
11434 pci_unregister_driver(&bnx2x_pci_driver); 11710 pci_unregister_driver(&bnx2x_pci_driver);
11435 11711
11436 destroy_workqueue(bnx2x_wq); 11712 destroy_workqueue(bnx2x_wq);
11713
11714 /* Free globablly allocated resources */
11715 list_for_each_safe(pos, q, &bnx2x_prev_list) {
11716 struct bnx2x_prev_path_list *tmp =
11717 list_entry(pos, struct bnx2x_prev_path_list, list);
11718 list_del(pos);
11719 kfree(tmp);
11720 }
11437} 11721}
11438 11722
11439void bnx2x_notify_link_changed(struct bnx2x *bp) 11723void bnx2x_notify_link_changed(struct bnx2x *bp)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
index fd7fb458184..ab0a250f95f 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
@@ -987,6 +987,7 @@
987 * clear; 1 = set. Data valid only in addresses 0-4. all the rest are zero. */ 987 * clear; 1 = set. Data valid only in addresses 0-4. all the rest are zero. */
988#define IGU_REG_WRITE_DONE_PENDING 0x130480 988#define IGU_REG_WRITE_DONE_PENDING 0x130480
989#define MCP_A_REG_MCPR_SCRATCH 0x3a0000 989#define MCP_A_REG_MCPR_SCRATCH 0x3a0000
990#define MCP_REG_MCPR_ACCESS_LOCK 0x8009c
990#define MCP_REG_MCPR_CPU_PROGRAM_COUNTER 0x8501c 991#define MCP_REG_MCPR_CPU_PROGRAM_COUNTER 0x8501c
991#define MCP_REG_MCPR_GP_INPUTS 0x800c0 992#define MCP_REG_MCPR_GP_INPUTS 0x800c0
992#define MCP_REG_MCPR_GP_OENABLE 0x800c8 993#define MCP_REG_MCPR_GP_OENABLE 0x800c8
@@ -1686,6 +1687,7 @@
1686 [10] rst_dbg; [11] rst_misc_core; [12] rst_dbue (UART); [13] 1687 [10] rst_dbg; [11] rst_misc_core; [12] rst_dbue (UART); [13]
1687 Pci_resetmdio_n; [14] rst_emac0_hard_core; [15] rst_emac1_hard_core; 16] 1688 Pci_resetmdio_n; [14] rst_emac0_hard_core; [15] rst_emac1_hard_core; 16]
1688 rst_pxp_rq_rd_wr; 31:17] reserved */ 1689 rst_pxp_rq_rd_wr; 31:17] reserved */
1690#define MISC_REG_RESET_REG_1 0xa580
1689#define MISC_REG_RESET_REG_2 0xa590 1691#define MISC_REG_RESET_REG_2 0xa590
1690/* [RW 20] 20 bit GRC address where the scratch-pad of the MCP that is 1692/* [RW 20] 20 bit GRC address where the scratch-pad of the MCP that is
1691 shared with the driver resides */ 1693 shared with the driver resides */
@@ -5606,6 +5608,7 @@
5606/* [RC 32] Parity register #0 read clear */ 5608/* [RC 32] Parity register #0 read clear */
5607#define XSEM_REG_XSEM_PRTY_STS_CLR_0 0x280128 5609#define XSEM_REG_XSEM_PRTY_STS_CLR_0 0x280128
5608#define XSEM_REG_XSEM_PRTY_STS_CLR_1 0x280138 5610#define XSEM_REG_XSEM_PRTY_STS_CLR_1 0x280138
5611#define MCPR_ACCESS_LOCK_LOCK (1L<<31)
5609#define MCPR_NVM_ACCESS_ENABLE_EN (1L<<0) 5612#define MCPR_NVM_ACCESS_ENABLE_EN (1L<<0)
5610#define MCPR_NVM_ACCESS_ENABLE_WR_EN (1L<<1) 5613#define MCPR_NVM_ACCESS_ENABLE_WR_EN (1L<<1)
5611#define MCPR_NVM_ADDR_NVM_ADDR_VALUE (0xffffffL<<0) 5614#define MCPR_NVM_ADDR_NVM_ADDR_VALUE (0xffffffL<<0)
@@ -5732,6 +5735,7 @@
5732#define MISC_REGISTERS_GPIO_PORT_SHIFT 4 5735#define MISC_REGISTERS_GPIO_PORT_SHIFT 4
5733#define MISC_REGISTERS_GPIO_SET_POS 8 5736#define MISC_REGISTERS_GPIO_SET_POS 8
5734#define MISC_REGISTERS_RESET_REG_1_CLEAR 0x588 5737#define MISC_REGISTERS_RESET_REG_1_CLEAR 0x588
5738#define MISC_REGISTERS_RESET_REG_1_RST_BRB1 (0x1<<0)
5735#define MISC_REGISTERS_RESET_REG_1_RST_DORQ (0x1<<19) 5739#define MISC_REGISTERS_RESET_REG_1_RST_DORQ (0x1<<19)
5736#define MISC_REGISTERS_RESET_REG_1_RST_HC (0x1<<29) 5740#define MISC_REGISTERS_RESET_REG_1_RST_HC (0x1<<29)
5737#define MISC_REGISTERS_RESET_REG_1_RST_NIG (0x1<<7) 5741#define MISC_REGISTERS_RESET_REG_1_RST_NIG (0x1<<7)