[kernel] r16248 - in dists/sid/linux-2.6/debian: . patches/features/all patches/series
Dann Frazier
dannf at alioth.debian.org
Wed Sep 8 21:39:19 UTC 2010
Author: dannf
Date: Wed Sep 8 21:39:07 2010
New Revision: 16248
Log:
netxen_nic: add support for loading unified firmware images
Added:
dists/sid/linux-2.6/debian/patches/features/all/netxen-unified-fw-image.patch
Modified:
dists/sid/linux-2.6/debian/changelog
dists/sid/linux-2.6/debian/patches/series/22
Modified: dists/sid/linux-2.6/debian/changelog
==============================================================================
--- dists/sid/linux-2.6/debian/changelog Tue Sep 7 01:17:59 2010 (r16247)
+++ dists/sid/linux-2.6/debian/changelog Wed Sep 8 21:39:07 2010 (r16248)
@@ -52,6 +52,9 @@
- kirkwood: Unbreak PCIe I/O port
- Kirkwood: support for Seagate DockStar
+ [ dann frazier ]
+ * netxen_nic: add support for loading unified firmware images
+
-- Ben Hutchings <ben at decadent.org.uk> Fri, 27 Aug 2010 08:38:26 +0100
linux-2.6 (2.6.32-21) unstable; urgency=high
Added: dists/sid/linux-2.6/debian/patches/features/all/netxen-unified-fw-image.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/netxen-unified-fw-image.patch Wed Sep 8 21:39:07 2010 (r16248)
@@ -0,0 +1,1566 @@
+commit 5fe4d5c338291bbd504b8ebbd4d3931adfa61772
+Author: Amit Kumar Salecha <amit.salecha at qlogic.com>
+Date: Mon Mar 29 02:43:44 2010 +0000
+
+ netxen: fix fw load from file
+
+ Rarely: Fw file size can be unaligned to 8.
+
+ Signed-off-by: Amit Kumar Salecha <amit.salecha at qlogic.com>
+ Signed-off-by: David S. Miller <davem at davemloft.net>
+
+commit 3111bf7ed99902687728eeec2ad068c2a7f8e5f0
+Author: Rajesh K Borundia <rajesh.borundia at qlogic.com>
+Date: Mon Mar 29 02:43:43 2010 +0000
+
+ netxen: validate unified romimage
+
+ Signed-off-by: Rajesh K Borundia <rajesh.borundia at qlogic.com>
+ Signed-off-by: Amit Kumar Salecha <amit.salecha at qlogic.com>
+
+ Validate all sections of unified romimage, before accessing them,
+ to avoid seg fault.
+
+ Signed-off-by: Amit Kumar Salecha <amit.salecha at qlogic.com>
+ Signed-off-by: David S. Miller <davem at davemloft.net>
+
+commit e9c75051c380aa07e237fd271a191f71cc5b79ef
+Author: Amit Kumar Salecha <amit.salecha at qlogic.com>
+Date: Fri Mar 26 00:30:07 2010 +0000
+
+ netxen: fix bios version calculation
+
+ Bios sub version from unified fw image is calculated incorrect.
+
+ Signed-off-by: Amit Kumar Salecha <amit.salecha at qlogic.com>
+ Signed-off-by: David S. Miller <davem at davemloft.net>
+
+commit 31ae5cfdfd99db77ef6f213d4c35422320356d3b
+Author: Amit Kumar Salecha <amit.salecha at qlogic.com>
+Date: Tue Dec 8 20:40:57 2009 +0000
+
+ netxen: fix unified fw size check
+
+ o Unified firmware image size can be < 1 MB
+
+ Signed-off-by: Amit Kumar Salecha <amit.salecha at qlogic.com>
+ Signed-off-by: David S. Miller <davem at davemloft.net>
+
+commit fd1ae25890ba3e63c62f4ba53519ec21bcc7181b
+Author: Dhananjay Phadke <dhananjay at netxen.com>
+Date: Sat Dec 5 12:23:56 2009 +0000
+
+ netxen: fix firmware type check
+
+ Unified firmware image may not contain MN type of firmware.
+ Driver should fall back to NOMN firmware type instead
+ of going to flash.
+
+ Signed-off-by: Dhananjay Phadke <dhananjay at netxen.com>
+ Signed-off-by: Amit Kumar Salecha <amit.salecha at qlogic.com>
+ Signed-off-by: David S. Miller <davem at davemloft.net>
+
+commit 629073465ea87a2f5792225dc4647b9f965ee2d3
+Author: Amit Kumar Salecha <amit at netxen.com>
+Date: Sat Oct 24 16:03:58 2009 +0000
+
+ netxen: support for new firmware file format
+
+ Add support for extracting firmware from a unified
+ file format which embeds firmware images for all chip
+ revisions. Fallback to orginal file formats if new
+ image is not found.
+
+ Signed-off-by: Amit Kumar Salecha <amit at netxen.com>
+ Signed-off-by: Dhananjay Phadke <dhananjay at netxen.com>
+ Signed-off-by: David S. Miller <davem at davemloft.net>
+
+commit 57cf596bef5692dc543b846cd1c05ea075270741
+Author: Dhananjay Phadke <dhananjay at netxen.com>
+Date: Fri Oct 16 15:50:10 2009 +0000
+
+ netxen: fix error codes in for tools access
+
+ [Backported to Debian's 2.6.26 by dann frazier <dannf at debian.org>]
+
+ Use -EIO or -EINVAL as error codes, these can get passed up
+ to applications (tools).
+
+ Signed-off-by: Dhananjay Phadke <dhananjay at netxen.com>
+ Signed-off-by: David S. Miller <davem at davemloft.net>
+
+commit 1648870d11e31d16b0c44d9a104ec68ebb5d9b58
+Author: Amit Kumar Salecha <amit at qlogic.com>
+Date: Fri Oct 16 15:50:06 2009 +0000
+
+ netxen: defines for next revision
+
+ Signed-off-by: Amit Kumar Salecha <amit at netxen.com>
+ Signed-off-by: Dhananjay Phadke <dhananjay at netxen.com>
+ Signed-off-by: David S. Miller <davem at davemloft.net>
+
+commit 43afdee1baceca4bdeccde45f98f5983302e80c2
+Author: Amit Kumar Salecha <amit at netxen.com>
+Date: Tue Oct 13 05:31:41 2009 +0000
+
+ netxen: remove sub 64-bit mem accesses
+
+ Sub 64-bit / unaligned access to oncard memory was only used
+ by old diagnostic tools, causes some intermittent issues when
+ memory controller agent is used. The new access method was
+ added by commit ea6828b8aa3a8ebae8d7740f32f212ba1d2f0742
+ ("netxen: improve pci memory access"). Firmware init anyway
+ uses 8-byte strides.
+
+ This also fixes address/offset calculation for NX2031 context
+ memory (SIU). For NX3031, SIU uses same register offsets
+ as packet memory (MIU).
+
+ Signed-off-by: Amit Kumar Salecha <amit at netxen.com>
+ Signed-off-by: Dhananjay Phadke <dhananjay at netxen.com>
+ Signed-off-by: David S. Miller <davem at davemloft.net>
+diff -urpN a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
+--- a/drivers/net/netxen/netxen_nic.h 2010-08-30 19:40:21.000000000 -0600
++++ b/drivers/net/netxen/netxen_nic.h 2010-08-30 19:42:40.000000000 -0600
+@@ -117,9 +117,11 @@
+ #define NX_P3_B0 0x40
+ #define NX_P3_B1 0x41
+ #define NX_P3_B2 0x42
++#define NX_P3P_A0 0x50
+
+ #define NX_IS_REVISION_P2(REVISION) (REVISION <= NX_P2_C1)
+ #define NX_IS_REVISION_P3(REVISION) (REVISION >= NX_P3_A0)
++#define NX_IS_REVISION_P3P(REVISION) (REVISION >= NX_P3P_A0)
+
+ #define FIRST_PAGE_GROUP_START 0
+ #define FIRST_PAGE_GROUP_END 0x100000
+@@ -419,6 +421,33 @@ struct status_desc {
+ __le64 status_desc_data[2];
+ } __attribute__ ((aligned(16)));
+
++/* UNIFIED ROMIMAGE *************************/
++#define NX_UNI_DIR_SECT_PRODUCT_TBL 0x0
++#define NX_UNI_DIR_SECT_BOOTLD 0x6
++#define NX_UNI_DIR_SECT_FW 0x7
++
++/*Offsets */
++#define NX_UNI_CHIP_REV_OFF 10
++#define NX_UNI_FLAGS_OFF 11
++#define NX_UNI_BIOS_VERSION_OFF 12
++#define NX_UNI_BOOTLD_IDX_OFF 27
++#define NX_UNI_FIRMWARE_IDX_OFF 29
++
++struct uni_table_desc{
++ uint32_t findex;
++ uint32_t num_entries;
++ uint32_t entry_size;
++ uint32_t reserved[5];
++};
++
++struct uni_data_desc{
++ uint32_t findex;
++ uint32_t size;
++ uint32_t reserved[5];
++};
++
++/* UNIFIED ROMIMAGE *************************/
++
+ /* The version of the main data structure */
+ #define NETXEN_BDINFO_VERSION 1
+
+@@ -485,11 +514,14 @@ struct status_desc {
+ #define NX_P2_MN_ROMIMAGE 0
+ #define NX_P3_CT_ROMIMAGE 1
+ #define NX_P3_MN_ROMIMAGE 2
+-#define NX_FLASH_ROMIMAGE 3
++#define NX_UNIFIED_ROMIMAGE 3
++#define NX_FLASH_ROMIMAGE 4
++#define NX_UNKNOWN_ROMIMAGE 0xff
+
+ #define NX_P2_MN_ROMIMAGE_NAME "nxromimg.bin"
+ #define NX_P3_CT_ROMIMAGE_NAME "nx3fwct.bin"
+ #define NX_P3_MN_ROMIMAGE_NAME "nx3fwmn.bin"
++#define NX_UNIFIED_ROMIMAGE_NAME "phanfw.bin"
+ #define NX_FLASH_ROMIMAGE_NAME "flash"
+
+ extern char netxen_nic_driver_name[];
+@@ -1187,8 +1219,8 @@ struct netxen_adapter {
+ u32 (*crb_read)(struct netxen_adapter *, ulong);
+ int (*crb_write)(struct netxen_adapter *, ulong, u32);
+
+- int (*pci_mem_read)(struct netxen_adapter *, u64, void *, int);
+- int (*pci_mem_write)(struct netxen_adapter *, u64, void *, int);
++ int (*pci_mem_read)(struct netxen_adapter *, u64, u64 *);
++ int (*pci_mem_write)(struct netxen_adapter *, u64, u64);
+
+ unsigned long (*pci_set_window)(struct netxen_adapter *,
+ unsigned long long);
+@@ -1215,7 +1247,7 @@ struct netxen_adapter {
+ nx_nic_intr_coalesce_t coal;
+
+ unsigned long state;
+- u32 resv5;
++ __le32 file_prd_off; /*File fw product offset*/
+ u32 fw_version;
+ const struct firmware *fw;
+ };
+diff -urpN a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
+--- a/drivers/net/netxen/netxen_nic_hdr.h 2009-12-02 20:51:21.000000000 -0700
++++ b/drivers/net/netxen/netxen_nic_hdr.h 2010-08-30 19:42:40.000000000 -0600
+@@ -664,40 +664,47 @@ enum {
+ #define NETXEN_NIU_AP_STATION_ADDR_0(I) (NETXEN_CRB_NIU+0xa0040+(I)*0x10000)
+ #define NETXEN_NIU_AP_STATION_ADDR_1(I) (NETXEN_CRB_NIU+0xa0044+(I)*0x10000)
+
++
++#define TEST_AGT_CTRL (0x00)
++
++#define TA_CTL_START 1
++#define TA_CTL_ENABLE 2
++#define TA_CTL_WRITE 4
++#define TA_CTL_BUSY 8
++
+ /*
+ * Register offsets for MN
+ */
+-#define MIU_CONTROL (0x000)
+-#define MIU_TEST_AGT_CTRL (0x090)
+-#define MIU_TEST_AGT_ADDR_LO (0x094)
+-#define MIU_TEST_AGT_ADDR_HI (0x098)
+-#define MIU_TEST_AGT_WRDATA_LO (0x0a0)
+-#define MIU_TEST_AGT_WRDATA_HI (0x0a4)
+-#define MIU_TEST_AGT_WRDATA(i) (0x0a0+(4*(i)))
+-#define MIU_TEST_AGT_RDDATA_LO (0x0a8)
+-#define MIU_TEST_AGT_RDDATA_HI (0x0ac)
+-#define MIU_TEST_AGT_RDDATA(i) (0x0a8+(4*(i)))
+-#define MIU_TEST_AGT_ADDR_MASK 0xfffffff8
+-#define MIU_TEST_AGT_UPPER_ADDR(off) (0)
+-
+-/* MIU_TEST_AGT_CTRL flags. work for SIU as well */
+-#define MIU_TA_CTL_START 1
+-#define MIU_TA_CTL_ENABLE 2
+-#define MIU_TA_CTL_WRITE 4
+-#define MIU_TA_CTL_BUSY 8
+-
+-#define SIU_TEST_AGT_CTRL (0x060)
+-#define SIU_TEST_AGT_ADDR_LO (0x064)
+-#define SIU_TEST_AGT_ADDR_HI (0x078)
+-#define SIU_TEST_AGT_WRDATA_LO (0x068)
+-#define SIU_TEST_AGT_WRDATA_HI (0x06c)
+-#define SIU_TEST_AGT_WRDATA(i) (0x068+(4*(i)))
+-#define SIU_TEST_AGT_RDDATA_LO (0x070)
+-#define SIU_TEST_AGT_RDDATA_HI (0x074)
+-#define SIU_TEST_AGT_RDDATA(i) (0x070+(4*(i)))
++#define MIU_TEST_AGT_BASE (0x90)
++
++#define MIU_TEST_AGT_ADDR_LO (0x04)
++#define MIU_TEST_AGT_ADDR_HI (0x08)
++#define MIU_TEST_AGT_WRDATA_LO (0x10)
++#define MIU_TEST_AGT_WRDATA_HI (0x14)
++#define MIU_TEST_AGT_WRDATA(i) (0x10+(4*(i)))
++#define MIU_TEST_AGT_RDDATA_LO (0x18)
++#define MIU_TEST_AGT_RDDATA_HI (0x1c)
++#define MIU_TEST_AGT_RDDATA(i) (0x18+(4*(i)))
++
++#define MIU_TEST_AGT_ADDR_MASK 0xfffffff8
++#define MIU_TEST_AGT_UPPER_ADDR(off) (0)
++
++/*
++ * Register offsets for MS
++ */
++#define SIU_TEST_AGT_BASE (0x60)
++
++#define SIU_TEST_AGT_ADDR_LO (0x04)
++#define SIU_TEST_AGT_ADDR_HI (0x18)
++#define SIU_TEST_AGT_WRDATA_LO (0x08)
++#define SIU_TEST_AGT_WRDATA_HI (0x0c)
++#define SIU_TEST_AGT_WRDATA(i) (0x08+(4*(i)))
++#define SIU_TEST_AGT_RDDATA_LO (0x10)
++#define SIU_TEST_AGT_RDDATA_HI (0x14)
++#define SIU_TEST_AGT_RDDATA(i) (0x10+(4*(i)))
+
+-#define SIU_TEST_AGT_ADDR_MASK 0x3ffff8
+-#define SIU_TEST_AGT_UPPER_ADDR(off) ((off)>>22)
++#define SIU_TEST_AGT_ADDR_MASK 0x3ffff8
++#define SIU_TEST_AGT_UPPER_ADDR(off) ((off)>>22)
+
+ /* XG Link status */
+ #define XG_LINK_UP 0x10
+diff -urpN a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
+--- a/drivers/net/netxen/netxen_nic_hw.c 2009-12-02 20:51:21.000000000 -0700
++++ b/drivers/net/netxen/netxen_nic_hw.c 2010-08-30 19:42:40.000000000 -0600
+@@ -326,7 +326,7 @@ netxen_pcie_sem_lock(struct netxen_adapt
+ if (done == 1)
+ break;
+ if (++timeout >= NETXEN_PCIE_SEM_TIMEOUT)
+- return -1;
++ return -EIO;
+ msleep(1);
+ }
+
+@@ -1116,7 +1116,7 @@ netxen_nic_pci_change_crbwindow_128M(str
+ }
+
+ /*
+- * Return -1 if off is not valid,
++ * Returns < 0 if off is not valid,
+ * 1 if window access is needed. 'off' is set to offset from
+ * CRB space in 128M pci map
+ * 0 if no window access is needed. 'off' is set to 2M addr
+@@ -1129,7 +1129,7 @@ netxen_nic_pci_get_crb_addr_2M(struct ne
+
+
+ if (*off >= NETXEN_CRB_MAX)
+- return -1;
++ return -EINVAL;
+
+ if (*off >= NETXEN_PCI_CAMQM && (*off < NETXEN_PCI_CAMQM_2M_END)) {
+ *off = (*off - NETXEN_PCI_CAMQM) + NETXEN_PCI_CAMQM_2M_BASE +
+@@ -1138,7 +1138,7 @@ netxen_nic_pci_get_crb_addr_2M(struct ne
+ }
+
+ if (*off < NETXEN_PCI_CRBSPACE)
+- return -1;
++ return -EINVAL;
+
+ *off -= NETXEN_PCI_CRBSPACE;
+
+@@ -1251,25 +1251,26 @@ netxen_nic_hw_write_wx_2M(struct netxen_
+
+ rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off);
+
+- if (rv == -1) {
+- printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
+- __func__, off);
+- dump_stack();
+- return -1;
++ if (rv == 0) {
++ writel(data, (void __iomem *)off);
++ return 0;
+ }
+
+- if (rv == 1) {
++ if (rv > 0) {
++ /* indirect access */
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ crb_win_lock(adapter);
+ netxen_nic_pci_set_crbwindow_2M(adapter, &off);
+ writel(data, (void __iomem *)off);
+ crb_win_unlock(adapter);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+- } else
+- writel(data, (void __iomem *)off);
+-
++ return 0;
++ }
+
+- return 0;
++ dev_err(&adapter->pdev->dev,
++ "%s: invalid offset: 0x%016lx\n", __func__, off);
++ dump_stack();
++ return -EIO;
+ }
+
+ static u32
+@@ -1281,24 +1282,24 @@ netxen_nic_hw_read_wx_2M(struct netxen_a
+
+ rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off);
+
+- if (rv == -1) {
+- printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
+- __func__, off);
+- dump_stack();
+- return -1;
+- }
++ if (rv == 0)
++ return readl((void __iomem *)off);
+
+- if (rv == 1) {
++ if (rv > 0) {
++ /* indirect access */
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ crb_win_lock(adapter);
+ netxen_nic_pci_set_crbwindow_2M(adapter, &off);
+ data = readl((void __iomem *)off);
+ crb_win_unlock(adapter);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+- } else
+- data = readl((void __iomem *)off);
++ return data;
++ }
+
+- return data;
++ dev_err(&adapter->pdev->dev,
++ "%s: invalid offset: 0x%016lx\n", __func__, off);
++ dump_stack();
++ return -1;
+ }
+
+ static int netxen_pci_set_window_warning_count;
+@@ -1485,101 +1486,69 @@ netxen_nic_pci_set_window_2M(struct netx
+
+ static int
+ netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,
+- u64 off, void *data, int size)
++ u64 off, u64 data)
+ {
+ unsigned long flags;
+- int i, j, ret = 0, loop, sz[2], off0;
+- uint32_t temp;
+- uint64_t off8, tmpw, word[2] = {0, 0};
++ int j, ret;
++ u32 temp, off_lo, off_hi, addr_hi, data_hi, data_lo;
+ void __iomem *mem_crb;
+
+- if (size != 8)
++ /* Only 64-bit aligned access */
++ if (off & 7)
+ return -EIO;
+
++ /* P2 has different SIU and MIU test agent base addr */
+ if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET,
+ NETXEN_ADDR_QDR_NET_MAX_P2)) {
+- mem_crb = pci_base_offset(adapter, NETXEN_CRB_QDR_NET);
++ mem_crb = pci_base_offset(adapter,
++ NETXEN_CRB_QDR_NET+SIU_TEST_AGT_BASE);
++ addr_hi = SIU_TEST_AGT_ADDR_HI;
++ data_lo = SIU_TEST_AGT_WRDATA_LO;
++ data_hi = SIU_TEST_AGT_WRDATA_HI;
++ off_lo = off & SIU_TEST_AGT_ADDR_MASK;
++ off_hi = SIU_TEST_AGT_UPPER_ADDR(off);
+ goto correct;
+ }
+
+ if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
+- mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
++ mem_crb = pci_base_offset(adapter,
++ NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE);
++ addr_hi = MIU_TEST_AGT_ADDR_HI;
++ data_lo = MIU_TEST_AGT_WRDATA_LO;
++ data_hi = MIU_TEST_AGT_WRDATA_HI;
++ off_lo = off & MIU_TEST_AGT_ADDR_MASK;
++ off_hi = 0;
+ goto correct;
+ }
+
+ return -EIO;
+
+ correct:
+- off8 = off & 0xfffffff8;
+- off0 = off & 0x7;
+- sz[0] = (size < (8 - off0)) ? size : (8 - off0);
+- sz[1] = size - sz[0];
+- loop = ((off0 + size - 1) >> 3) + 1;
+-
+- if ((size != 8) || (off0 != 0)) {
+- for (i = 0; i < loop; i++) {
+- if (adapter->pci_mem_read(adapter,
+- off8 + (i << 3), &word[i], 8))
+- return -1;
+- }
+- }
+-
+- switch (size) {
+- case 1:
+- tmpw = *((uint8_t *)data);
+- break;
+- case 2:
+- tmpw = *((uint16_t *)data);
+- break;
+- case 4:
+- tmpw = *((uint32_t *)data);
+- break;
+- case 8:
+- default:
+- tmpw = *((uint64_t *)data);
+- break;
+- }
+- word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
+- word[0] |= tmpw << (off0 * 8);
+-
+- if (loop == 2) {
+- word[1] &= ~(~0ULL << (sz[1] * 8));
+- word[1] |= tmpw >> (sz[0] * 8);
+- }
+-
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+
+- for (i = 0; i < loop; i++) {
+- writel((uint32_t)(off8 + (i << 3)),
+- (mem_crb+MIU_TEST_AGT_ADDR_LO));
+- writel(0,
+- (mem_crb+MIU_TEST_AGT_ADDR_HI));
+- writel(word[i] & 0xffffffff,
+- (mem_crb+MIU_TEST_AGT_WRDATA_LO));
+- writel((word[i] >> 32) & 0xffffffff,
+- (mem_crb+MIU_TEST_AGT_WRDATA_HI));
+- writel(MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
+- (mem_crb+MIU_TEST_AGT_CTRL));
+- writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
+- (mem_crb+MIU_TEST_AGT_CTRL));
+-
+- for (j = 0; j < MAX_CTL_CHECK; j++) {
+- temp = readl(
+- (mem_crb+MIU_TEST_AGT_CTRL));
+- if ((temp & MIU_TA_CTL_BUSY) == 0)
+- break;
+- }
+-
+- if (j >= MAX_CTL_CHECK) {
+- if (printk_ratelimit())
+- dev_err(&adapter->pdev->dev,
+- "failed to write through agent\n");
+- ret = -1;
++ writel(off_lo, (mem_crb + MIU_TEST_AGT_ADDR_LO));
++ writel(off_hi, (mem_crb + addr_hi));
++ writel(data & 0xffffffff, (mem_crb + data_lo));
++ writel((data >> 32) & 0xffffffff, (mem_crb + data_hi));
++ writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL));
++ writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE),
++ (mem_crb + TEST_AGT_CTRL));
++
++ for (j = 0; j < MAX_CTL_CHECK; j++) {
++ temp = readl((mem_crb + TEST_AGT_CTRL));
++ if ((temp & TA_CTL_BUSY) == 0)
+ break;
+- }
+ }
+
++ if (j >= MAX_CTL_CHECK) {
++ if (printk_ratelimit())
++ dev_err(&adapter->pdev->dev,
++ "failed to write through agent\n");
++ ret = -EIO;
++ } else
++ ret = 0;
++
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ return ret;
+@@ -1587,304 +1556,202 @@ correct:
+
+ static int
+ netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
+- u64 off, void *data, int size)
++ u64 off, u64 *data)
+ {
+ unsigned long flags;
+- int i, j = 0, k, start, end, loop, sz[2], off0[2];
+- uint32_t temp;
+- uint64_t off8, val, word[2] = {0, 0};
++ int j, ret;
++ u32 temp, off_lo, off_hi, addr_hi, data_hi, data_lo;
++ u64 val;
+ void __iomem *mem_crb;
+
+- if (size != 8)
++ /* Only 64-bit aligned access */
++ if (off & 7)
+ return -EIO;
+
++ /* P2 has different SIU and MIU test agent base addr */
+ if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET,
+ NETXEN_ADDR_QDR_NET_MAX_P2)) {
+- mem_crb = pci_base_offset(adapter, NETXEN_CRB_QDR_NET);
++ mem_crb = pci_base_offset(adapter,
++ NETXEN_CRB_QDR_NET+SIU_TEST_AGT_BASE);
++ addr_hi = SIU_TEST_AGT_ADDR_HI;
++ data_lo = SIU_TEST_AGT_RDDATA_LO;
++ data_hi = SIU_TEST_AGT_RDDATA_HI;
++ off_lo = off & SIU_TEST_AGT_ADDR_MASK;
++ off_hi = SIU_TEST_AGT_UPPER_ADDR(off);
+ goto correct;
+ }
+
+ if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
+- mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
++ mem_crb = pci_base_offset(adapter,
++ NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE);
++ addr_hi = MIU_TEST_AGT_ADDR_HI;
++ data_lo = MIU_TEST_AGT_RDDATA_LO;
++ data_hi = MIU_TEST_AGT_RDDATA_HI;
++ off_lo = off & MIU_TEST_AGT_ADDR_MASK;
++ off_hi = 0;
+ goto correct;
+ }
+
+ return -EIO;
+
+ correct:
+- off8 = off & 0xfffffff8;
+- off0[0] = off & 0x7;
+- off0[1] = 0;
+- sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
+- sz[1] = size - sz[0];
+- loop = ((off0[0] + size - 1) >> 3) + 1;
+-
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+
+- for (i = 0; i < loop; i++) {
+- writel((uint32_t)(off8 + (i << 3)),
+- (mem_crb+MIU_TEST_AGT_ADDR_LO));
+- writel(0,
+- (mem_crb+MIU_TEST_AGT_ADDR_HI));
+- writel(MIU_TA_CTL_ENABLE,
+- (mem_crb+MIU_TEST_AGT_CTRL));
+- writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE,
+- (mem_crb+MIU_TEST_AGT_CTRL));
+-
+- for (j = 0; j < MAX_CTL_CHECK; j++) {
+- temp = readl(
+- (mem_crb+MIU_TEST_AGT_CTRL));
+- if ((temp & MIU_TA_CTL_BUSY) == 0)
+- break;
+- }
++ writel(off_lo, (mem_crb + MIU_TEST_AGT_ADDR_LO));
++ writel(off_hi, (mem_crb + addr_hi));
++ writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL));
++ writel((TA_CTL_START|TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL));
++
++ for (j = 0; j < MAX_CTL_CHECK; j++) {
++ temp = readl(mem_crb + TEST_AGT_CTRL);
++ if ((temp & TA_CTL_BUSY) == 0)
++ break;
++ }
+
+- if (j >= MAX_CTL_CHECK) {
+- if (printk_ratelimit())
+- dev_err(&adapter->pdev->dev,
++ if (j >= MAX_CTL_CHECK) {
++ if (printk_ratelimit())
++ dev_err(&adapter->pdev->dev,
+ "failed to read through agent\n");
+- break;
+- }
++ ret = -EIO;
++ } else {
+
+- start = off0[i] >> 2;
+- end = (off0[i] + sz[i] - 1) >> 2;
+- for (k = start; k <= end; k++) {
+- word[i] |= ((uint64_t) readl(
+- (mem_crb +
+- MIU_TEST_AGT_RDDATA(k))) << (32*k));
+- }
++ temp = readl(mem_crb + data_hi);
++ val = ((u64)temp << 32);
++ val |= readl(mem_crb + data_lo);
++ *data = val;
++ ret = 0;
+ }
+
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+
+- if (j >= MAX_CTL_CHECK)
+- return -1;
+-
+- if (sz[0] == 8) {
+- val = word[0];
+- } else {
+- val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
+- ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
+- }
+-
+- switch (size) {
+- case 1:
+- *(uint8_t *)data = val;
+- break;
+- case 2:
+- *(uint16_t *)data = val;
+- break;
+- case 4:
+- *(uint32_t *)data = val;
+- break;
+- case 8:
+- *(uint64_t *)data = val;
+- break;
+- }
+- return 0;
++ return ret;
+ }
+
+ static int
+ netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter,
+- u64 off, void *data, int size)
++ u64 off, u64 data)
+ {
+- int i, j, ret = 0, loop, sz[2], off0;
+- uint32_t temp;
+- uint64_t off8, tmpw, word[2] = {0, 0};
++ unsigned long flags;
++ int j, ret;
++ u32 temp, off8;
+ void __iomem *mem_crb;
+
+- if (size != 8)
++ /* Only 64-bit aligned access */
++ if (off & 7)
+ return -EIO;
+
++ /* P3 onward, test agent base for MIU and SIU is same */
+ if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET,
+ NETXEN_ADDR_QDR_NET_MAX_P3)) {
+- mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_QDR_NET);
++ mem_crb = netxen_get_ioaddr(adapter,
++ NETXEN_CRB_QDR_NET+MIU_TEST_AGT_BASE);
+ goto correct;
+ }
+
+ if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
+- mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_DDR_NET);
++ mem_crb = netxen_get_ioaddr(adapter,
++ NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE);
+ goto correct;
+ }
+
+ return -EIO;
+
+ correct:
+- off8 = off & 0xfffffff8;
+- off0 = off & 0x7;
+- sz[0] = (size < (8 - off0)) ? size : (8 - off0);
+- sz[1] = size - sz[0];
+- loop = ((off0 + size - 1) >> 3) + 1;
+-
+- if ((size != 8) || (off0 != 0)) {
+- for (i = 0; i < loop; i++) {
+- if (adapter->pci_mem_read(adapter,
+- off8 + (i << 3), &word[i], 8))
+- return -1;
+- }
+- }
+-
+- switch (size) {
+- case 1:
+- tmpw = *((uint8_t *)data);
+- break;
+- case 2:
+- tmpw = *((uint16_t *)data);
+- break;
+- case 4:
+- tmpw = *((uint32_t *)data);
+- break;
+- case 8:
+- default:
+- tmpw = *((uint64_t *)data);
+- break;
+- }
+-
+- word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
+- word[0] |= tmpw << (off0 * 8);
+-
+- if (loop == 2) {
+- word[1] &= ~(~0ULL << (sz[1] * 8));
+- word[1] |= tmpw >> (sz[0] * 8);
+- }
+-
+- /*
+- * don't lock here - write_wx gets the lock if each time
+- * write_lock_irqsave(&adapter->adapter_lock, flags);
+- * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+- */
++ off8 = off & MIU_TEST_AGT_ADDR_MASK;
+
+- for (i = 0; i < loop; i++) {
+- writel(off8 + (i << 3), mem_crb+MIU_TEST_AGT_ADDR_LO);
+- writel(0, mem_crb+MIU_TEST_AGT_ADDR_HI);
+- writel(word[i] & 0xffffffff, mem_crb+MIU_TEST_AGT_WRDATA_LO);
+- writel((word[i] >> 32) & 0xffffffff,
+- mem_crb+MIU_TEST_AGT_WRDATA_HI);
+- writel((MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE),
+- mem_crb+MIU_TEST_AGT_CTRL);
+- writel(MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE,
+- mem_crb+MIU_TEST_AGT_CTRL);
+-
+- for (j = 0; j < MAX_CTL_CHECK; j++) {
+- temp = readl(mem_crb + MIU_TEST_AGT_CTRL);
+- if ((temp & MIU_TA_CTL_BUSY) == 0)
+- break;
+- }
++ write_lock_irqsave(&adapter->adapter_lock, flags);
+
+- if (j >= MAX_CTL_CHECK) {
+- if (printk_ratelimit())
+- dev_err(&adapter->pdev->dev,
+- "failed to write through agent\n");
+- ret = -1;
++ writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO));
++ writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI));
++ writel(data & 0xffffffff, mem_crb + MIU_TEST_AGT_WRDATA_LO);
++ writel((data >> 32) & 0xffffffff, mem_crb + MIU_TEST_AGT_WRDATA_HI);
++ writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL));
++ writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE),
++ (mem_crb + TEST_AGT_CTRL));
++
++ for (j = 0; j < MAX_CTL_CHECK; j++) {
++ temp = readl(mem_crb + TEST_AGT_CTRL);
++ if ((temp & TA_CTL_BUSY) == 0)
+ break;
+- }
+ }
+
+- /*
+- * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+- * write_unlock_irqrestore(&adapter->adapter_lock, flags);
+- */
++ if (j >= MAX_CTL_CHECK) {
++ if (printk_ratelimit())
++ dev_err(&adapter->pdev->dev,
++ "failed to write through agent\n");
++ ret = -EIO;
++ } else
++ ret = 0;
++
++ write_unlock_irqrestore(&adapter->adapter_lock, flags);
++
+ return ret;
+ }
+
+ static int
+ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,
+- u64 off, void *data, int size)
++ u64 off, u64 *data)
+ {
+- int i, j = 0, k, start, end, loop, sz[2], off0[2];
+- uint32_t temp;
+- uint64_t off8, val, word[2] = {0, 0};
++ unsigned long flags;
++ int j, ret;
++ u32 temp, off8;
++ u64 val;
+ void __iomem *mem_crb;
+
+- if (size != 8)
++ /* Only 64-bit aligned access */
++ if (off & 7)
+ return -EIO;
+
++ /* P3 onward, test agent base for MIU and SIU is same */
+ if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET,
+ NETXEN_ADDR_QDR_NET_MAX_P3)) {
+- mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_QDR_NET);
++ mem_crb = netxen_get_ioaddr(adapter,
++ NETXEN_CRB_QDR_NET+MIU_TEST_AGT_BASE);
+ goto correct;
+ }
+
+ if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
+- mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_DDR_NET);
++ mem_crb = netxen_get_ioaddr(adapter,
++ NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE);
+ goto correct;
+ }
+
+ return -EIO;
+
+ correct:
+- off8 = off & 0xfffffff8;
+- off0[0] = off & 0x7;
+- off0[1] = 0;
+- sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
+- sz[1] = size - sz[0];
+- loop = ((off0[0] + size - 1) >> 3) + 1;
+-
+- /*
+- * don't lock here - write_wx gets the lock if each time
+- * write_lock_irqsave(&adapter->adapter_lock, flags);
+- * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+- */
++ off8 = off & MIU_TEST_AGT_ADDR_MASK;
+
+- for (i = 0; i < loop; i++) {
+- writel(off8 + (i << 3), mem_crb + MIU_TEST_AGT_ADDR_LO);
+- writel(0, mem_crb + MIU_TEST_AGT_ADDR_HI);
+- writel(MIU_TA_CTL_ENABLE, mem_crb + MIU_TEST_AGT_CTRL);
+- writel(MIU_TA_CTL_START | MIU_TA_CTL_ENABLE,
+- mem_crb + MIU_TEST_AGT_CTRL);
+-
+- for (j = 0; j < MAX_CTL_CHECK; j++) {
+- temp = readl(mem_crb + MIU_TEST_AGT_CTRL);
+- if ((temp & MIU_TA_CTL_BUSY) == 0)
+- break;
+- }
++ write_lock_irqsave(&adapter->adapter_lock, flags);
+
+- if (j >= MAX_CTL_CHECK) {
+- if (printk_ratelimit())
+- dev_err(&adapter->pdev->dev,
+- "failed to read through agent\n");
++ writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO));
++ writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI));
++ writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL));
++ writel((TA_CTL_START | TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL));
++
++ for (j = 0; j < MAX_CTL_CHECK; j++) {
++ temp = readl(mem_crb + TEST_AGT_CTRL);
++ if ((temp & TA_CTL_BUSY) == 0)
+ break;
+- }
+-
+- start = off0[i] >> 2;
+- end = (off0[i] + sz[i] - 1) >> 2;
+- for (k = start; k <= end; k++) {
+- temp = readl(mem_crb + MIU_TEST_AGT_RDDATA(k));
+- word[i] |= ((uint64_t)temp << (32 * k));
+- }
+ }
+
+- /*
+- * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+- * write_unlock_irqrestore(&adapter->adapter_lock, flags);
+- */
+-
+- if (j >= MAX_CTL_CHECK)
+- return -1;
+-
+- if (sz[0] == 8) {
+- val = word[0];
++ if (j >= MAX_CTL_CHECK) {
++ if (printk_ratelimit())
++ dev_err(&adapter->pdev->dev,
++ "failed to read through agent\n");
++ ret = -EIO;
+ } else {
+- val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
+- ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
++ temp = readl(mem_crb + MIU_TEST_AGT_RDDATA_HI);
++ val = (u64)temp << 32;
++ val |= readl(mem_crb + MIU_TEST_AGT_RDDATA_LO);
++ *data = val;
++ ret = 0;
+ }
+
+- switch (size) {
+- case 1:
+- *(uint8_t *)data = val;
+- break;
+- case 2:
+- *(uint16_t *)data = val;
+- break;
+- case 4:
+- *(uint32_t *)data = val;
+- break;
+- case 8:
+- *(uint64_t *)data = val;
+- break;
+- }
+- return 0;
++ write_unlock_irqrestore(&adapter->adapter_lock, flags);
++
++ return ret;
+ }
+
+ void
+diff -urpN a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
+--- a/drivers/net/netxen/netxen_nic_init.c 2010-08-30 19:40:21.000000000 -0600
++++ b/drivers/net/netxen/netxen_nic_init.c 2010-08-30 19:42:40.000000000 -0600
+@@ -46,6 +46,7 @@ static unsigned int crb_addr_xform[NETXE
+ static void
+ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
+ struct nx_host_rds_ring *rds_ring);
++static int netxen_p3_has_mn(struct netxen_adapter *adapter);
+
+ static void crb_addr_transform_setup(void)
+ {
+@@ -607,6 +608,310 @@ int netxen_pinit_from_rom(struct netxen_
+ return 0;
+ }
+
++static struct uni_table_desc *nx_get_table_desc(const u8 *unirom, int section)
++{
++ uint32_t i;
++ struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
++ __le32 entries = cpu_to_le32(directory->num_entries);
++
++ for (i = 0; i < entries; i++) {
++
++ __le32 offs = cpu_to_le32(directory->findex) +
++ (i * cpu_to_le32(directory->entry_size));
++ __le32 tab_type = cpu_to_le32(*((u32 *)&unirom[offs] + 8));
++
++ if (tab_type == section)
++ return (struct uni_table_desc *) &unirom[offs];
++ }
++
++ return NULL;
++}
++
++#define QLCNIC_FILEHEADER_SIZE (14 * 4)
++
++static int
++netxen_nic_validate_header(struct netxen_adapter *adapter)
++ {
++ const u8 *unirom = adapter->fw->data;
++ struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
++ u32 fw_file_size = adapter->fw->size;
++ u32 tab_size;
++ __le32 entries;
++ __le32 entry_size;
++
++ if (fw_file_size < QLCNIC_FILEHEADER_SIZE)
++ return -EINVAL;
++
++ entries = cpu_to_le32(directory->num_entries);
++ entry_size = cpu_to_le32(directory->entry_size);
++ tab_size = cpu_to_le32(directory->findex) + (entries * entry_size);
++
++ if (fw_file_size < tab_size)
++ return -EINVAL;
++
++ return 0;
++}
++
++static int
++netxen_nic_validate_bootld(struct netxen_adapter *adapter)
++{
++ struct uni_table_desc *tab_desc;
++ struct uni_data_desc *descr;
++ const u8 *unirom = adapter->fw->data;
++ __le32 idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
++ NX_UNI_BOOTLD_IDX_OFF));
++ u32 offs;
++ u32 tab_size;
++ u32 data_size;
++
++ tab_desc = nx_get_table_desc(unirom, NX_UNI_DIR_SECT_BOOTLD);
++
++ if (!tab_desc)
++ return -EINVAL;
++
++ tab_size = cpu_to_le32(tab_desc->findex) +
++ (cpu_to_le32(tab_desc->entry_size) * (idx + 1));
++
++ if (adapter->fw->size < tab_size)
++ return -EINVAL;
++
++ offs = cpu_to_le32(tab_desc->findex) +
++ (cpu_to_le32(tab_desc->entry_size) * (idx));
++ descr = (struct uni_data_desc *)&unirom[offs];
++
++ data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size);
++
++ if (adapter->fw->size < data_size)
++ return -EINVAL;
++
++ return 0;
++}
++
++static int
++netxen_nic_validate_fw(struct netxen_adapter *adapter)
++{
++ struct uni_table_desc *tab_desc;
++ struct uni_data_desc *descr;
++ const u8 *unirom = adapter->fw->data;
++ __le32 idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
++ NX_UNI_FIRMWARE_IDX_OFF));
++ u32 offs;
++ u32 tab_size;
++ u32 data_size;
++
++ tab_desc = nx_get_table_desc(unirom, NX_UNI_DIR_SECT_FW);
++
++ if (!tab_desc)
++ return -EINVAL;
++
++ tab_size = cpu_to_le32(tab_desc->findex) +
++ (cpu_to_le32(tab_desc->entry_size) * (idx + 1));
++
++ if (adapter->fw->size < tab_size)
++ return -EINVAL;
++
++ offs = cpu_to_le32(tab_desc->findex) +
++ (cpu_to_le32(tab_desc->entry_size) * (idx));
++ descr = (struct uni_data_desc *)&unirom[offs];
++ data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size);
++
++ if (adapter->fw->size < data_size)
++ return -EINVAL;
++
++ return 0;
++}
++
++
++static int
++netxen_nic_validate_product_offs(struct netxen_adapter *adapter)
++{
++ struct uni_table_desc *ptab_descr;
++ const u8 *unirom = adapter->fw->data;
++ int mn_present = (NX_IS_REVISION_P2(adapter->ahw.revision_id)) ?
++ 1 : netxen_p3_has_mn(adapter);
++ __le32 entries;
++ __le32 entry_size;
++ u32 tab_size;
++ u32 i;
++
++ ptab_descr = nx_get_table_desc(unirom, NX_UNI_DIR_SECT_PRODUCT_TBL);
++ if (ptab_descr == NULL)
++ return -EINVAL;
++
++ entries = cpu_to_le32(ptab_descr->num_entries);
++ entry_size = cpu_to_le32(ptab_descr->entry_size);
++ tab_size = cpu_to_le32(ptab_descr->findex) + (entries * entry_size);
++
++ if (adapter->fw->size < tab_size)
++ return -EINVAL;
++
++nomn:
++ for (i = 0; i < entries; i++) {
++
++ __le32 flags, file_chiprev, offs;
++ u8 chiprev = adapter->ahw.revision_id;
++ uint32_t flagbit;
++
++ offs = cpu_to_le32(ptab_descr->findex) +
++ (i * cpu_to_le32(ptab_descr->entry_size));
++ flags = cpu_to_le32(*((int *)&unirom[offs] + NX_UNI_FLAGS_OFF));
++ file_chiprev = cpu_to_le32(*((int *)&unirom[offs] +
++ NX_UNI_CHIP_REV_OFF));
++
++ flagbit = mn_present ? 1 : 2;
++
++ if ((chiprev == file_chiprev) &&
++ ((1ULL << flagbit) & flags)) {
++ adapter->file_prd_off = offs;
++ return 0;
++ }
++ }
++
++ if (mn_present && NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
++ mn_present = 0;
++ goto nomn;
++ }
++
++ return -EINVAL;
++}
++
++static int
++netxen_nic_validate_unified_romimage(struct netxen_adapter *adapter)
++{
++ if (netxen_nic_validate_header(adapter)) {
++ dev_err(&adapter->pdev->dev,
++ "unified image: header validation failed\n");
++ return -EINVAL;
++ }
++
++ if (netxen_nic_validate_product_offs(adapter)) {
++ dev_err(&adapter->pdev->dev,
++ "unified image: product validation failed\n");
++ return -EINVAL;
++ }
++
++ if (netxen_nic_validate_bootld(adapter)) {
++ dev_err(&adapter->pdev->dev,
++ "unified image: bootld validation failed\n");
++ return -EINVAL;
++ }
++
++ if (netxen_nic_validate_fw(adapter)) {
++ dev_err(&adapter->pdev->dev,
++ "unified image: firmware validation failed\n");
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static struct uni_data_desc *nx_get_data_desc(struct netxen_adapter *adapter,
++ u32 section, u32 idx_offset)
++{
++ const u8 *unirom = adapter->fw->data;
++ int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
++ idx_offset));
++ struct uni_table_desc *tab_desc;
++ __le32 offs;
++
++ tab_desc = nx_get_table_desc(unirom, section);
++
++ if (tab_desc == NULL)
++ return NULL;
++
++ offs = cpu_to_le32(tab_desc->findex) +
++ (cpu_to_le32(tab_desc->entry_size) * idx);
++
++ return (struct uni_data_desc *)&unirom[offs];
++}
++
++static u8 *
++nx_get_bootld_offs(struct netxen_adapter *adapter)
++{
++ u32 offs = NETXEN_BOOTLD_START;
++
++ if (adapter->fw_type == NX_UNIFIED_ROMIMAGE)
++ offs = cpu_to_le32((nx_get_data_desc(adapter,
++ NX_UNI_DIR_SECT_BOOTLD,
++ NX_UNI_BOOTLD_IDX_OFF))->findex);
++
++ return (u8 *)&adapter->fw->data[offs];
++}
++
++static u8 *
++nx_get_fw_offs(struct netxen_adapter *adapter)
++{
++ u32 offs = NETXEN_IMAGE_START;
++
++ if (adapter->fw_type == NX_UNIFIED_ROMIMAGE)
++ offs = cpu_to_le32((nx_get_data_desc(adapter,
++ NX_UNI_DIR_SECT_FW,
++ NX_UNI_FIRMWARE_IDX_OFF))->findex);
++
++ return (u8 *)&adapter->fw->data[offs];
++}
++
++static __le32
++nx_get_fw_size(struct netxen_adapter *adapter)
++{
++ if (adapter->fw_type == NX_UNIFIED_ROMIMAGE)
++ return cpu_to_le32((nx_get_data_desc(adapter,
++ NX_UNI_DIR_SECT_FW,
++ NX_UNI_FIRMWARE_IDX_OFF))->size);
++ else
++ return cpu_to_le32(
++ *(u32 *)&adapter->fw->data[NX_FW_SIZE_OFFSET]);
++}
++
++static __le32
++nx_get_fw_version(struct netxen_adapter *adapter)
++{
++ struct uni_data_desc *fw_data_desc;
++ const struct firmware *fw = adapter->fw;
++ __le32 major, minor, sub;
++ const u8 *ver_str;
++ int i, ret = 0;
++
++ if (adapter->fw_type == NX_UNIFIED_ROMIMAGE) {
++
++ fw_data_desc = nx_get_data_desc(adapter,
++ NX_UNI_DIR_SECT_FW, NX_UNI_FIRMWARE_IDX_OFF);
++ ver_str = fw->data + cpu_to_le32(fw_data_desc->findex) +
++ cpu_to_le32(fw_data_desc->size) - 17;
++
++ for (i = 0; i < 12; i++) {
++ if (!strncmp(&ver_str[i], "REV=", 4)) {
++ ret = sscanf(&ver_str[i+4], "%u.%u.%u ",
++ &major, &minor, &sub);
++ break;
++ }
++ }
++
++ if (ret != 3)
++ return 0;
++
++ return major + (minor << 8) + (sub << 16);
++
++ } else
++ return cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
++}
++
++static __le32
++nx_get_bios_version(struct netxen_adapter *adapter)
++{
++ const struct firmware *fw = adapter->fw;
++ __le32 bios_ver, prd_off = adapter->file_prd_off;
++
++ if (adapter->fw_type == NX_UNIFIED_ROMIMAGE) {
++ bios_ver = cpu_to_le32(*((u32 *) (&fw->data[prd_off])
++ + NX_UNI_BIOS_VERSION_OFF));
++ return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) +
++ (bios_ver >> 24);
++ } else
++ return cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]);
++
++}
++
+ int
+ netxen_need_fw_reset(struct netxen_adapter *adapter)
+ {
+@@ -646,9 +951,8 @@ netxen_need_fw_reset(struct netxen_adapt
+ /* check if we have got newer or different file firmware */
+ if (adapter->fw) {
+
+- const struct firmware *fw = adapter->fw;
++ val = nx_get_fw_version(adapter);
+
+- val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
+ version = NETXEN_DECODE_VERSION(val);
+
+ major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
+@@ -658,7 +962,8 @@ netxen_need_fw_reset(struct netxen_adapt
+ if (version > NETXEN_VERSION_CODE(major, minor, build))
+ return 1;
+
+- if (version == NETXEN_VERSION_CODE(major, minor, build)) {
++ if (version == NETXEN_VERSION_CODE(major, minor, build) &&
++ adapter->fw_type != NX_UNIFIED_ROMIMAGE) {
+
+ val = NXRD32(adapter, NETXEN_MIU_MN_CONTROL);
+ fw_type = (val & 0x4) ?
+@@ -676,6 +981,7 @@ static char *fw_name[] = {
+ NX_P2_MN_ROMIMAGE_NAME,
+ NX_P3_CT_ROMIMAGE_NAME,
+ NX_P3_MN_ROMIMAGE_NAME,
++ NX_UNIFIED_ROMIMAGE_NAME,
+ NX_FLASH_ROMIMAGE_NAME,
+ };
+
+@@ -698,30 +1004,42 @@ netxen_load_firmware(struct netxen_adapt
+
+ size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8;
+
+- ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START];
++ ptr64 = (u64 *)nx_get_bootld_offs(adapter);
+ flashaddr = NETXEN_BOOTLD_START;
+
+ for (i = 0; i < size; i++) {
+ data = cpu_to_le64(ptr64[i]);
+- adapter->pci_mem_write(adapter, flashaddr, &data, 8);
++
++ if (adapter->pci_mem_write(adapter, flashaddr, data))
++ return -EIO;
++
+ flashaddr += 8;
+ }
+
+- size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET];
+- size = (__force u32)cpu_to_le32(size) / 8;
++ size = (__force u32)nx_get_fw_size(adapter) / 8;
+
+- ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START];
++ ptr64 = (u64 *)nx_get_fw_offs(adapter);
+ flashaddr = NETXEN_IMAGE_START;
+
+ for (i = 0; i < size; i++) {
+ data = cpu_to_le64(ptr64[i]);
+
+ if (adapter->pci_mem_write(adapter,
+- flashaddr, &data, 8))
++ flashaddr, data))
+ return -EIO;
+
+ flashaddr += 8;
+ }
++
++ size = (__force u32)nx_get_fw_size(adapter) % 8;
++ if (size) {
++ data = cpu_to_le64(ptr64[i]);
++
++ if (adapter->pci_mem_write(adapter,
++ flashaddr, data))
++ return -EIO;
++ }
++
+ } else {
+ u64 data;
+ u32 hi, lo;
+@@ -731,17 +1049,17 @@ netxen_load_firmware(struct netxen_adapt
+
+ for (i = 0; i < size; i++) {
+ if (netxen_rom_fast_read(adapter,
+- flashaddr, &lo) != 0)
++ flashaddr, (int *)&lo) != 0)
+ return -EIO;
+ if (netxen_rom_fast_read(adapter,
+- flashaddr + 4, &hi) != 0)
++ flashaddr + 4, (int *)&hi) != 0)
+ return -EIO;
+
+ /* hi, lo are already in host endian byteorder */
+ data = (((u64)hi << 32) | lo);
+
+ if (adapter->pci_mem_write(adapter,
+- flashaddr, &data, 8))
++ flashaddr, data))
+ return -EIO;
+
+ flashaddr += 8;
+@@ -760,21 +1078,27 @@ netxen_load_firmware(struct netxen_adapt
+ }
+
+ static int
+-netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname)
++netxen_validate_firmware(struct netxen_adapter *adapter)
+ {
+ __le32 val;
+ u32 ver, min_ver, bios;
+ struct pci_dev *pdev = adapter->pdev;
+ const struct firmware *fw = adapter->fw;
++ u8 fw_type = adapter->fw_type;
+
+- if (fw->size < NX_FW_MIN_SIZE)
+- return -EINVAL;
++ if (fw_type == NX_UNIFIED_ROMIMAGE) {
++ if (netxen_nic_validate_unified_romimage(adapter))
++ return -EINVAL;
++ } else {
++ val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]);
++ if ((__force u32)val != NETXEN_BDINFO_MAGIC)
++ return -EINVAL;
+
+- val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]);
+- if ((__force u32)val != NETXEN_BDINFO_MAGIC)
+- return -EINVAL;
++ if (fw->size < NX_FW_MIN_SIZE)
++ return -EINVAL;
++ }
+
+- val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
++ val = nx_get_fw_version(adapter);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ min_ver = NETXEN_VERSION_CODE(4, 0, 216);
+@@ -786,15 +1110,15 @@ netxen_validate_firmware(struct netxen_a
+ if ((_major(ver) > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) {
+ dev_err(&pdev->dev,
+ "%s: firmware version %d.%d.%d unsupported\n",
+- fwname, _major(ver), _minor(ver), _build(ver));
++ fw_name[fw_type], _major(ver), _minor(ver), _build(ver));
+ return -EINVAL;
+ }
+
+- val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]);
++ val = nx_get_bios_version(adapter);
+ netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios);
+ if ((__force u32)val != bios) {
+ dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
+- fwname);
++ fw_name[fw_type]);
+ return -EINVAL;
+ }
+
+@@ -805,7 +1129,7 @@ netxen_validate_firmware(struct netxen_a
+ val = NETXEN_DECODE_VERSION(val);
+ if (val > ver) {
+ dev_info(&pdev->dev, "%s: firmware is older than flash\n",
+- fwname);
++ fw_name[fw_type]);
+ return -EINVAL;
+ }
+
+@@ -813,12 +1137,51 @@ netxen_validate_firmware(struct netxen_a
+ return 0;
+ }
+
++static void
++nx_get_next_fwtype(struct netxen_adapter *adapter)
++{
++ u8 fw_type;
++
++ switch (adapter->fw_type) {
++ case NX_UNKNOWN_ROMIMAGE:
++ fw_type = NX_UNIFIED_ROMIMAGE;
++ break;
++
++ case NX_UNIFIED_ROMIMAGE:
++ if (NX_IS_REVISION_P3P(adapter->ahw.revision_id))
++ fw_type = NX_FLASH_ROMIMAGE;
++ else if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
++ fw_type = NX_P2_MN_ROMIMAGE;
++ else if (netxen_p3_has_mn(adapter))
++ fw_type = NX_P3_MN_ROMIMAGE;
++ else
++ fw_type = NX_P3_CT_ROMIMAGE;
++ break;
++
++ case NX_P3_MN_ROMIMAGE:
++ fw_type = NX_P3_CT_ROMIMAGE;
++ break;
++
++ case NX_P2_MN_ROMIMAGE:
++ case NX_P3_CT_ROMIMAGE:
++ default:
++ fw_type = NX_FLASH_ROMIMAGE;
++ break;
++ }
++
++ adapter->fw_type = fw_type;
++}
++
+ static int
+ netxen_p3_has_mn(struct netxen_adapter *adapter)
+ {
+ u32 capability, flashed_ver;
+ capability = 0;
+
++ /* NX2031 always had MN */
++ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
++ return 1;
++
+ netxen_rom_fast_read(adapter,
+ NX_FW_VERSION_OFFSET, (int *)&flashed_ver);
+ flashed_ver = NETXEN_DECODE_VERSION(flashed_ver);
+@@ -834,49 +1197,29 @@ netxen_p3_has_mn(struct netxen_adapter *
+
+ void netxen_request_firmware(struct netxen_adapter *adapter)
+ {
+- u8 fw_type;
+ struct pci_dev *pdev = adapter->pdev;
+ int rc = 0;
+
+- if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+- fw_type = NX_P2_MN_ROMIMAGE;
+- goto request_fw;
+- }
++ adapter->fw_type = NX_UNKNOWN_ROMIMAGE;
+
+- fw_type = netxen_p3_has_mn(adapter) ?
+- NX_P3_MN_ROMIMAGE : NX_P3_CT_ROMIMAGE;
++next:
++ nx_get_next_fwtype(adapter);
+
+-request_fw:
+- rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev);
+- if (rc != 0) {
+- if (fw_type == NX_P3_MN_ROMIMAGE) {
+- msleep(1);
+- fw_type = NX_P3_CT_ROMIMAGE;
+- goto request_fw;
+- }
+-
+- fw_type = NX_FLASH_ROMIMAGE;
++ if (adapter->fw_type == NX_FLASH_ROMIMAGE) {
+ adapter->fw = NULL;
+- goto done;
+- }
+-
+- rc = netxen_validate_firmware(adapter, fw_name[fw_type]);
+- if (rc != 0) {
+- release_firmware(adapter->fw);
+-
+- if (fw_type == NX_P3_MN_ROMIMAGE) {
++ } else {
++ rc = request_firmware(&adapter->fw,
++ fw_name[adapter->fw_type], &pdev->dev);
++ if (rc != 0)
++ goto next;
++
++ rc = netxen_validate_firmware(adapter);
++ if (rc != 0) {
++ release_firmware(adapter->fw);
+ msleep(1);
+- fw_type = NX_P3_CT_ROMIMAGE;
+- goto request_fw;
++ goto next;
+ }
+-
+- fw_type = NX_FLASH_ROMIMAGE;
+- adapter->fw = NULL;
+- goto done;
+ }
+-
+-done:
+- adapter->fw_type = fw_type;
+ }
+
+
+diff -urpN a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
+--- a/drivers/net/netxen/netxen_nic_main.c 2010-08-30 19:40:21.000000000 -0600
++++ b/drivers/net/netxen/netxen_nic_main.c 2010-08-30 19:42:40.000000000 -0600
+@@ -41,6 +41,7 @@ MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONI
+ MODULE_FIRMWARE(NX_P2_MN_ROMIMAGE_NAME);
+ MODULE_FIRMWARE(NX_P3_CT_ROMIMAGE_NAME);
+ MODULE_FIRMWARE(NX_P3_MN_ROMIMAGE_NAME);
++MODULE_FIRMWARE(NX_UNIFIED_ROMIMAGE_NAME);
+
+ char netxen_nic_driver_name[] = "netxen_nic";
+ static char netxen_nic_driver_string[] = "NetXen Network Driver version "
Modified: dists/sid/linux-2.6/debian/patches/series/22
==============================================================================
--- dists/sid/linux-2.6/debian/patches/series/22 Tue Sep 7 01:17:59 2010 (r16247)
+++ dists/sid/linux-2.6/debian/patches/series/22 Wed Sep 8 21:39:07 2010 (r16248)
@@ -100,3 +100,4 @@
+ features/arm/kirkwood-unbreak-pcie-io-port.patch
+ features/arm/dockstar-support.patch
+ bugfix/all/3c59x-Fix-deadlock-in-vortex_error.patch
++ features/all/netxen-unified-fw-image.patch
More information about the Kernel-svn-changes
mailing list