netxen: add fw version compatibility check
authorAmit Kumar Salecha <amit.salecha@qlogic.com>
Wed, 20 Jul 2011 00:08:53 +0000 (00:08 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 22 Jul 2011 04:32:54 +0000 (21:32 -0700)
o Minimum fw version supported for P3 chip is 4.0.505
o File Fw > 4.0.554 is not supported if flash fw < 4.0.554.
o In mn firmware case, file fw older than flash fw is allowed.
o Change variable names for readability
o Update driver version 4.0.76

Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_main.c

index 77220687b92abb35a85c2dc53978610d3f4da735..f744d291218a2928e8277e030ac81e71125ae9f4 100644 (file)
@@ -53,8 +53,8 @@
 
 #define _NETXEN_NIC_LINUX_MAJOR 4
 #define _NETXEN_NIC_LINUX_MINOR 0
-#define _NETXEN_NIC_LINUX_SUBVERSION 75
-#define NETXEN_NIC_LINUX_VERSIONID  "4.0.75"
+#define _NETXEN_NIC_LINUX_SUBVERSION 76
+#define NETXEN_NIC_LINUX_VERSIONID  "4.0.76"
 
 #define NETXEN_VERSION_CODE(a, b, c)   (((a) << 24) + ((b) << 16) + (c))
 #define _major(v)      (((v) >> 24) & 0xff)
@@ -1302,6 +1302,7 @@ int netxen_nic_wol_supported(struct netxen_adapter *adapter);
 int netxen_init_dummy_dma(struct netxen_adapter *adapter);
 void netxen_free_dummy_dma(struct netxen_adapter *adapter);
 
+int netxen_check_flash_fw_compatibility(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);
index ca59b4f026f044717e4695d8cbab64232766f97b..e8993a76a08041b10b1bf54560ee69b2bb36409a 100644 (file)
@@ -964,6 +964,35 @@ netxen_need_fw_reset(struct netxen_adapter *adapter)
        return 0;
 }
 
+#define NETXEN_MIN_P3_FW_SUPP  NETXEN_VERSION_CODE(4, 0, 505)
+
+int
+netxen_check_flash_fw_compatibility(struct netxen_adapter *adapter)
+{
+       u32 flash_fw_ver, min_fw_ver;
+
+       if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+               return 0;
+
+       if (netxen_rom_fast_read(adapter,
+                       NX_FW_VERSION_OFFSET, (int *)&flash_fw_ver)) {
+               dev_err(&adapter->pdev->dev, "Unable to read flash fw"
+                       "version\n");
+               return -EIO;
+       }
+
+       flash_fw_ver = NETXEN_DECODE_VERSION(flash_fw_ver);
+       min_fw_ver = NETXEN_MIN_P3_FW_SUPP;
+       if (flash_fw_ver >= min_fw_ver)
+               return 0;
+
+       dev_info(&adapter->pdev->dev, "Flash fw[%d.%d.%d] is < min fw supported"
+               "[4.0.505]. Please update firmware on flash\n",
+               _major(flash_fw_ver), _minor(flash_fw_ver),
+               _build(flash_fw_ver));
+       return -EINVAL;
+}
+
 static char *fw_name[] = {
        NX_P2_MN_ROMIMAGE_NAME,
        NX_P3_CT_ROMIMAGE_NAME,
@@ -1071,10 +1100,12 @@ static int
 netxen_validate_firmware(struct netxen_adapter *adapter)
 {
        __le32 val;
-       u32 ver, min_ver, bios;
+       __le32 flash_fw_ver;
+       u32 file_fw_ver, min_ver, bios;
        struct pci_dev *pdev = adapter->pdev;
        const struct firmware *fw = adapter->fw;
        u8 fw_type = adapter->fw_type;
+       u32 crbinit_fix_fw;
 
        if (fw_type == NX_UNIFIED_ROMIMAGE) {
                if (netxen_nic_validate_unified_romimage(adapter))
@@ -1091,16 +1122,18 @@ netxen_validate_firmware(struct netxen_adapter *adapter)
        val = nx_get_fw_version(adapter);
 
        if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-               min_ver = NETXEN_VERSION_CODE(4, 0, 216);
+               min_ver = NETXEN_MIN_P3_FW_SUPP;
        else
                min_ver = NETXEN_VERSION_CODE(3, 4, 216);
 
-       ver = NETXEN_DECODE_VERSION(val);
+       file_fw_ver = NETXEN_DECODE_VERSION(val);
 
-       if ((_major(ver) > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) {
+       if ((_major(file_fw_ver) > _NETXEN_NIC_LINUX_MAJOR) ||
+           (file_fw_ver < min_ver)) {
                dev_err(&pdev->dev,
                                "%s: firmware version %d.%d.%d unsupported\n",
-               fw_name[fw_type], _major(ver), _minor(ver), _build(ver));
+               fw_name[fw_type], _major(file_fw_ver), _minor(file_fw_ver),
+                _build(file_fw_ver));
                return -EINVAL;
        }
 
@@ -1112,17 +1145,34 @@ netxen_validate_firmware(struct netxen_adapter *adapter)
                return -EINVAL;
        }
 
-       /* check if flashed firmware is newer */
        if (netxen_rom_fast_read(adapter,
-                       NX_FW_VERSION_OFFSET, (int *)&val))
+                       NX_FW_VERSION_OFFSET, (int *)&flash_fw_ver)) {
+               dev_err(&pdev->dev, "Unable to read flash fw version\n");
                return -EIO;
-       val = NETXEN_DECODE_VERSION(val);
-       if (val > ver) {
-               dev_info(&pdev->dev, "%s: firmware is older than flash\n",
-                               fw_name[fw_type]);
+       }
+       flash_fw_ver = NETXEN_DECODE_VERSION(flash_fw_ver);
+
+       /* New fw from file is not allowed, if fw on flash is < 4.0.554 */
+       crbinit_fix_fw = NETXEN_VERSION_CODE(4, 0, 554);
+       if (file_fw_ver >= crbinit_fix_fw && flash_fw_ver < crbinit_fix_fw &&
+           NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+               dev_err(&pdev->dev, "Incompatibility detected between driver "
+                       "and firmware version on flash. This configuration "
+                       "is not recommended. Please update the firmware on "
+                       "flash immediately\n");
                return -EINVAL;
        }
 
+       /* check if flashed firmware is newer only for no-mn and P2 case*/
+       if (!netxen_p3_has_mn(adapter) ||
+           NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+               if (flash_fw_ver > file_fw_ver) {
+                       dev_info(&pdev->dev, "%s: firmware is older than flash\n",
+                               fw_name[fw_type]);
+                       return -EINVAL;
+               }
+       }
+
        NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
        return 0;
 }
index 30f41e62049ac257b7eb6e7cd29d6571455ecd8a..f574edff7fcb8ed9790a5281d1cff27b1b76d2d4 100644 (file)
@@ -1388,6 +1388,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                break;
        }
 
+       err = netxen_check_flash_fw_compatibility(adapter);
+       if (err)
+               goto err_out_iounmap;
+
        if (adapter->portnum == 0) {
                val = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);
                if (val != 0xffffffff && val != 0) {