netxen: avoid frequent firmware reset
authorDhananjay Phadke <dhananjay@netxen.com>
Wed, 1 Jul 2009 11:41:43 +0000 (11:41 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 2 Jul 2009 20:16:51 +0000 (13:16 -0700)
Restrict firmware reset to following cases -

o chip rev is NX2031 (firmare doesn't support heartbit).
o firmware is dead.
o previous attempt to init firmware had failed.
o we have got newer file firmware.

This speeds up module load tremendously (by upto 8 sec),
also avoids downtime for NCSI (management) pass-thru
traffic.

Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_hdr.h
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_main.c

index 26afcb5658d46b249762bb71ad4f1c65551d7d79..e1cdba752e09daa397c331b9c5708da267d8a7d9 100644 (file)
@@ -625,6 +625,7 @@ struct netxen_new_user_info {
 #define NX_P2_MN_ROMIMAGE      0
 #define NX_P3_CT_ROMIMAGE      1
 #define NX_P3_MN_ROMIMAGE      2
+#define NX_FLASH_ROMIMAGE      3
 
 #define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */
 
@@ -1254,7 +1255,7 @@ struct netxen_adapter {
        u32 resv3;
 
        u8 has_link_events;
-       u8 resv1;
+       u8 fw_type;
        u16 tx_context_id;
        u16 mtu;
        u16 is_up;
@@ -1398,6 +1399,7 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter);
 int netxen_initialize_adapter_offload(struct netxen_adapter *adapter);
 int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
 int netxen_load_firmware(struct netxen_adapter *adapter);
+int netxen_need_fw_reset(struct netxen_adapter *adapter);
 void netxen_request_firmware(struct netxen_adapter *adapter);
 void netxen_release_firmware(struct netxen_adapter *adapter);
 int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);
index 3cc047844af30d42b555efe35e2aca774c14d4eb..82410367564838aff7f2b5872c3c436a377a183c 100644 (file)
@@ -853,6 +853,7 @@ enum {
 #define NX_PEG_TUNE_CAPABILITY         (NETXEN_CAM_RAM(0x02c))
 
 #define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL               (0x14)
+#define NETXEN_PEG_ALIVE_COUNTER       (NETXEN_CAM_RAM(0xb0))
 
 #define        ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
 #define ISR_LEGACY_INT_TRIGGERED(VAL)  (((VAL) & 0x300) == 0x200)
index 7bdcbc67342f7e964d4b410fbc395b9c7af100fb..b899bd51fcd87e2563fa4fd495b8c760fe5c0e6d 100644 (file)
@@ -683,12 +683,85 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
        return 0;
 }
 
+int
+netxen_need_fw_reset(struct netxen_adapter *adapter)
+{
+       u32 count, old_count;
+       u32 val, version, major, minor, build;
+       int i, timeout;
+       u8 fw_type;
+
+       /* NX2031 firmware doesn't support heartbit */
+       if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+               return 1;
+
+       /* last attempt had failed */
+       if (NXRD32(adapter, CRB_CMDPEG_STATE) == PHAN_INITIALIZE_FAILED)
+               return 1;
+
+       old_count = count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
+
+       for (i = 0; i < 10; i++) {
+
+               timeout = msleep_interruptible(200);
+               if (timeout) {
+                       NXWR32(adapter, CRB_CMDPEG_STATE,
+                                       PHAN_INITIALIZE_FAILED);
+                       return -EINTR;
+               }
+
+               count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
+               if (count != old_count)
+                       break;
+       }
+
+       /* firmware is dead */
+       if (count == old_count)
+               return 1;
+
+       /* check if we have got newer or different file firmware */
+       if (adapter->fw) {
+
+               const struct firmware *fw = adapter->fw;
+
+               val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
+               version = NETXEN_DECODE_VERSION(val);
+
+               major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
+               minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
+               build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
+
+               if (version > NETXEN_VERSION_CODE(major, minor, build))
+                       return 1;
+
+               if (version == NETXEN_VERSION_CODE(major, minor, build)) {
+
+                       val = NXRD32(adapter, NETXEN_MIU_MN_CONTROL);
+                       fw_type = (val & 0x4) ?
+                               NX_P3_CT_ROMIMAGE : NX_P3_MN_ROMIMAGE;
+
+                       if (adapter->fw_type != fw_type)
+                               return 1;
+               }
+       }
+
+       return 0;
+}
+
+static char *fw_name[] = {
+       "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin", "flash",
+};
+
 int
 netxen_load_firmware(struct netxen_adapter *adapter)
 {
        u64 *ptr64;
        u32 i, flashaddr, size;
        const struct firmware *fw = adapter->fw;
+       struct pci_dev *pdev = adapter->pdev;
+
+       dev_info(&pdev->dev, "loading firmware from %s\n",
+                       fw_name[adapter->fw_type]);
 
        if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
                NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1);
@@ -806,12 +879,10 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname)
        return 0;
 }
 
-static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" };
-
 void netxen_request_firmware(struct netxen_adapter *adapter)
 {
        u32 capability, flashed_ver;
-       int fw_type;
+       u8 fw_type;
        struct pci_dev *pdev = adapter->pdev;
        int rc = 0;
 
@@ -838,6 +909,7 @@ request_mn:
                }
        }
 
+       fw_type = NX_FLASH_ROMIMAGE;
        adapter->fw = NULL;
        goto done;
 
@@ -849,6 +921,7 @@ request_fw:
                        goto request_mn;
                }
 
+               fw_type = NX_FLASH_ROMIMAGE;
                adapter->fw = NULL;
                goto done;
        }
@@ -862,16 +935,13 @@ request_fw:
                        goto request_mn;
                }
 
+               fw_type = NX_FLASH_ROMIMAGE;
                adapter->fw = NULL;
                goto done;
        }
 
 done:
-       if (adapter->fw)
-               dev_info(&pdev->dev, "loading firmware from file %s\n",
-                               fw_name[fw_type]);
-       else
-               dev_info(&pdev->dev, "loading firmware from flash\n");
+       adapter->fw_type = fw_type;
 }
 
 
index 2919a2d12bf40c5327f4979059eed3ea1de78878..27539ddf94c4f9304c8310e652c1ee7f120f78af 100644 (file)
@@ -718,6 +718,10 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw)
        if (request_fw)
                netxen_request_firmware(adapter);
 
+       err = netxen_need_fw_reset(adapter);
+       if (err <= 0)
+               return err;
+
        if (first_boot != 0x55555555) {
                NXWR32(adapter, CRB_CMDPEG_STATE, 0);
                netxen_pinit_from_rom(adapter, 0);