[kernel] r13688 - in dists/trunk/linux-2.6/debian: . config config/arm config/armel config/mips config/mipsel patches/features/all patches/series

Dann Frazier dannf at alioth.debian.org
Wed May 27 17:09:31 UTC 2009


Author: dannf
Date: Wed May 27 17:09:30 2009
New Revision: 13688

Log:
Enable bnx2x, using firmware-split patches from net-next and mirroring
the per-subarch config settings used for bnx2

Added:
   dists/trunk/linux-2.6/debian/patches/features/all/bnx2x-Separated-FW-from-the-source.patch
   dists/trunk/linux-2.6/debian/patches/features/all/bnx2x-driver-version-1.48.105-1.patch
Modified:
   dists/trunk/linux-2.6/debian/changelog
   dists/trunk/linux-2.6/debian/config/arm/config.footbridge
   dists/trunk/linux-2.6/debian/config/arm/config.orion5x
   dists/trunk/linux-2.6/debian/config/arm/config.versatile
   dists/trunk/linux-2.6/debian/config/armel/config.kirkwood
   dists/trunk/linux-2.6/debian/config/config
   dists/trunk/linux-2.6/debian/config/mips/config.r5k-ip32
   dists/trunk/linux-2.6/debian/config/mipsel/config.r5k-cobalt
   dists/trunk/linux-2.6/debian/patches/series/base

Modified: dists/trunk/linux-2.6/debian/changelog
==============================================================================
--- dists/trunk/linux-2.6/debian/changelog	Wed May 27 17:06:03 2009	(r13687)
+++ dists/trunk/linux-2.6/debian/changelog	Wed May 27 17:09:30 2009	(r13688)
@@ -50,6 +50,10 @@
   * [i386] Disable PentiumPro errata workaround.
   * [i386] Enable support for big SMP systems.
 
+  [ dann frazier ]
+  * Enable bnx2x, using firmware-split patches from net-next and mirroring
+    the per-subarch config settings used for bnx2
+
  -- maximilian attems <maks at debian.org>  Mon, 30 Mar 2009 14:40:26 +0200
 
 linux-2.6 (2.6.29-5) unstable; urgency=low

Modified: dists/trunk/linux-2.6/debian/config/arm/config.footbridge
==============================================================================
--- dists/trunk/linux-2.6/debian/config/arm/config.footbridge	Wed May 27 17:06:03 2009	(r13687)
+++ dists/trunk/linux-2.6/debian/config/arm/config.footbridge	Wed May 27 17:09:30 2009	(r13688)
@@ -646,6 +646,7 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_BNX2X is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 # CONFIG_PLIP is not set

Modified: dists/trunk/linux-2.6/debian/config/arm/config.orion5x
==============================================================================
--- dists/trunk/linux-2.6/debian/config/arm/config.orion5x	Wed May 27 17:06:03 2009	(r13687)
+++ dists/trunk/linux-2.6/debian/config/arm/config.orion5x	Wed May 27 17:09:30 2009	(r13688)
@@ -328,6 +328,7 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_BNX2X is not set
 CONFIG_MV643XX_ETH=m
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set

Modified: dists/trunk/linux-2.6/debian/config/arm/config.versatile
==============================================================================
--- dists/trunk/linux-2.6/debian/config/arm/config.versatile	Wed May 27 17:06:03 2009	(r13687)
+++ dists/trunk/linux-2.6/debian/config/arm/config.versatile	Wed May 27 17:09:30 2009	(r13688)
@@ -275,6 +275,7 @@
 # CONFIG_IP1000 is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_BNX2X is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set

Modified: dists/trunk/linux-2.6/debian/config/armel/config.kirkwood
==============================================================================
--- dists/trunk/linux-2.6/debian/config/armel/config.kirkwood	Wed May 27 17:06:03 2009	(r13687)
+++ dists/trunk/linux-2.6/debian/config/armel/config.kirkwood	Wed May 27 17:09:30 2009	(r13688)
@@ -345,6 +345,7 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_BNX2X is not set
 CONFIG_MV643XX_ETH=m
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set

Modified: dists/trunk/linux-2.6/debian/config/config
==============================================================================
--- dists/trunk/linux-2.6/debian/config/config	Wed May 27 17:06:03 2009	(r13687)
+++ dists/trunk/linux-2.6/debian/config/config	Wed May 27 17:09:30 2009	(r13688)
@@ -1269,6 +1269,7 @@
 CONFIG_VIA_VELOCITY=m
 CONFIG_TIGON3=m
 CONFIG_BNX2=m
+CONFIG_BNX2X=m
 CONFIG_QLA3XXX=m
 CONFIG_ATL1=m
 CONFIG_ATL1E=m

Modified: dists/trunk/linux-2.6/debian/config/mips/config.r5k-ip32
==============================================================================
--- dists/trunk/linux-2.6/debian/config/mips/config.r5k-ip32	Wed May 27 17:06:03 2009	(r13687)
+++ dists/trunk/linux-2.6/debian/config/mips/config.r5k-ip32	Wed May 27 17:09:30 2009	(r13688)
@@ -405,6 +405,7 @@
 # CONFIG_SKY2 is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_BNX2X is not set
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set

Modified: dists/trunk/linux-2.6/debian/config/mipsel/config.r5k-cobalt
==============================================================================
--- dists/trunk/linux-2.6/debian/config/mipsel/config.r5k-cobalt	Wed May 27 17:06:03 2009	(r13687)
+++ dists/trunk/linux-2.6/debian/config/mipsel/config.r5k-cobalt	Wed May 27 17:09:30 2009	(r13688)
@@ -510,6 +510,7 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_BNX2X is not set
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set

Added: dists/trunk/linux-2.6/debian/patches/features/all/bnx2x-Separated-FW-from-the-source.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/trunk/linux-2.6/debian/patches/features/all/bnx2x-Separated-FW-from-the-source.patch	Wed May 27 17:09:30 2009	(r13688)
@@ -0,0 +1,1876 @@
+From 08fa4f9f5ec207b19f950662e247fea584dc21c4 Mon Sep 17 00:00:00 2001
+From: Vladislav Zolotarov <vladz at broadcom.com>
+Date: Mon, 27 Apr 2009 03:27:43 -0700
+Subject: [PATCH 1/2] bnx2x: Separated FW from the source.
+
+>From now on FW will be downloaded from the binary file using request_firmware.
+
+There will be different files for every supported chip. Currently 57710 (e1) and
+57711 (e1h).
+
+File names have the following format: bnx2x-<chip version>-<FW version>.fw.
+ihex versions of current FW files are submitted in the next patch.
+
+Each binary file has a header in the following format:
+
+struct bnx2x_fw_file_section {
+	__be32 len;
+	__be32 offset;
+}
+
+struct bnx2x_fw_file_hdr {
+	struct bnx2x_fw_file_section init_ops;
+	struct bnx2x_fw_file_section init_ops_offsets;
+	struct bnx2x_fw_file_section init_data;
+	struct bnx2x_fw_file_section tsem_int_table_data;
+	struct bnx2x_fw_file_section tsem_pram_data;
+	struct bnx2x_fw_file_section usem_int_table_data;
+	struct bnx2x_fw_file_section usem_pram_data;
+	struct bnx2x_fw_file_section csem_int_table_data;
+	struct bnx2x_fw_file_section csem_pram_data;
+	struct bnx2x_fw_file_section xsem_int_table_data;
+	struct bnx2x_fw_file_section xsem_pram_data;
+	struct bnx2x_fw_file_section fw_version;
+}
+
+Each bnx2x_fw_file_section contains the length and the offset of the appropriate
+section in the binary file. Values are stored in the big endian format.
+
+Data types of arrays:
+
+init_data            __be32
+init_ops_offsets     __be16
+XXsem_pram_data         u8
+XXsem_int_table_data    u8
+init_ops             struct raw_op {
+                          u8   op;
+			__be24 offset;
+                        __be32 data;
+		     }
+fw_version              u8
+
+>From now boundaries of a specific initialization stage are stored in
+init_ops_offsets array instead of being defined by separate macroes. The index
+in init_ops_offsets is calculated by BLOCK_OPS_IDX macro:
+
+#define BLOCK_OPS_IDX(block, stage, end) \
+       (2*(((block)*STAGE_IDX_MAX) + (stage)) + (end))
+
+Security:
+
+In addition to sanity check of array boundaries bnx2x will check a FW version.
+Additional checks might be added in the future.
+
+Signed-off-by: Vladislav Zolotarov <vladz at broadcom.com>
+Signed-off-by: Eilon Greenstein <eilong at broadcom.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/Kconfig             |    1 +
+ drivers/net/bnx2x.h             |   15 +
+ drivers/net/bnx2x_fw_file_hdr.h |   37 +++
+ drivers/net/bnx2x_init.h        |  605 +++++----------------------------------
+ drivers/net/bnx2x_init_ops.h    |  442 ++++++++++++++++++++++++++++
+ drivers/net/bnx2x_main.c        |  343 ++++++++++++++++++----
+ firmware/Makefile               |    1 +
+ firmware/WHENCE                 |   20 ++
+ 8 files changed, 866 insertions(+), 598 deletions(-)
+ create mode 100644 drivers/net/bnx2x_fw_file_hdr.h
+ create mode 100644 drivers/net/bnx2x_init_ops.h
+
+Adjusted to apply to Debian's 2.6.30-rc6 by dann frazier <dannf at debian.org>
+
+diff -urpN linux-2.6-2.6.30~rc6.orig/drivers/net/bnx2x_fw_file_hdr.h linux-2.6-2.6.30~rc6/drivers/net/bnx2x_fw_file_hdr.h
+--- linux-2.6-2.6.30~rc6.orig/drivers/net/bnx2x_fw_file_hdr.h	1969-12-31 17:00:00.000000000 -0700
++++ linux-2.6-2.6.30~rc6/drivers/net/bnx2x_fw_file_hdr.h	2009-05-26 15:20:01.000000000 -0600
+@@ -0,0 +1,37 @@
++/* bnx2x_fw_file_hdr.h: FW binary file header structure.
++ *
++ * Copyright (c) 2007-2009 Broadcom Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation.
++ *
++ * Maintained by: Eilon Greenstein <eilong at broadcom.com>
++ * Written by: Vladislav Zolotarov <vladz at broadcom.com>
++ * Based on the original idea of John Wright <john.wright at hp.com>.
++ */
++
++#ifndef BNX2X_INIT_FILE_HDR_H
++#define BNX2X_INIT_FILE_HDR_H
++
++struct bnx2x_fw_file_section {
++	__be32 len;
++	__be32 offset;
++};
++
++struct bnx2x_fw_file_hdr {
++	struct bnx2x_fw_file_section init_ops;
++	struct bnx2x_fw_file_section init_ops_offsets;
++	struct bnx2x_fw_file_section init_data;
++	struct bnx2x_fw_file_section tsem_int_table_data;
++	struct bnx2x_fw_file_section tsem_pram_data;
++	struct bnx2x_fw_file_section usem_int_table_data;
++	struct bnx2x_fw_file_section usem_pram_data;
++	struct bnx2x_fw_file_section csem_int_table_data;
++	struct bnx2x_fw_file_section csem_pram_data;
++	struct bnx2x_fw_file_section xsem_int_table_data;
++	struct bnx2x_fw_file_section xsem_pram_data;
++	struct bnx2x_fw_file_section fw_version;
++};
++
++#endif /* BNX2X_INIT_FILE_HDR_H */
+diff -urpN linux-2.6-2.6.30~rc6.orig/drivers/net/bnx2x.h linux-2.6-2.6.30~rc6/drivers/net/bnx2x.h
+--- linux-2.6-2.6.30~rc6.orig/drivers/net/bnx2x.h	2009-05-19 03:52:18.000000000 -0600
++++ linux-2.6-2.6.30~rc6/drivers/net/bnx2x.h	2009-05-26 15:20:01.000000000 -0600
+@@ -965,6 +965,21 @@ struct bnx2x {
+ 	int			gunzip_outlen;
+ #define FW_BUF_SIZE			0x8000
+ 
++	struct raw_op          *init_ops;
++	/* Init blocks offsets inside init_ops */
++	u16                    *init_ops_offsets;
++	/* Data blob - has 32 bit granularity */
++	u32                    *init_data;
++	/* Zipped PRAM blobs - raw data */
++	const u8               *tsem_int_table_data;
++	const u8               *tsem_pram_data;
++	const u8               *usem_int_table_data;
++	const u8               *usem_pram_data;
++	const u8               *xsem_int_table_data;
++	const u8               *xsem_pram_data;
++	const u8               *csem_int_table_data;
++	const u8               *csem_pram_data;
++        const struct firmware  *firmware;
+ };
+ 
+ 
+diff -urpN linux-2.6-2.6.30~rc6.orig/drivers/net/bnx2x_init.h linux-2.6-2.6.30~rc6/drivers/net/bnx2x_init.h
+--- linux-2.6-2.6.30~rc6.orig/drivers/net/bnx2x_init.h	2009-05-19 03:52:18.000000000 -0600
++++ linux-2.6-2.6.30~rc6/drivers/net/bnx2x_init.h	2009-05-26 15:20:01.000000000 -0600
+@@ -1,4 +1,5 @@
+ /* bnx2x_init.h: Broadcom Everest network driver.
++ *               Structures and macroes needed during the initialization.
+  *
+  * Copyright (c) 2007-2009 Broadcom Corporation
+  *
+@@ -8,6 +9,7 @@
+  *
+  * Maintained by: Eilon Greenstein <eilong at broadcom.com>
+  * Written by: Eliezer Tamir
++ * Modified by: Vladislav Zolotarov <vladz at broadcom.com>
+  */
+ 
+ #ifndef BNX2X_INIT_H
+@@ -45,33 +47,71 @@
+ #define OP_WR_64		0x8 /* write 64 bit pattern */
+ #define OP_WB			0x9 /* copy a string using DMAE */
+ 
+-/* Operation specific for E1 */
+-#define OP_RD_E1		0xa /* read single register */
+-#define OP_WR_E1		0xb /* write single register */
+-#define OP_IW_E1		0xc /* write single register using mailbox */
+-#define OP_SW_E1		0xd /* copy a string to the device */
+-#define OP_SI_E1		0xe /* copy a string using mailbox */
+-#define OP_ZR_E1		0xf /* clear memory */
+-#define OP_ZP_E1		0x10 /* unzip then copy with DMAE */
+-#define OP_WR_64_E1		0x11 /* write 64 bit pattern on E1 */
+-#define OP_WB_E1		0x12 /* copy a string using DMAE */
+-
+-/* Operation specific for E1H */
+-#define OP_RD_E1H		0x13 /* read single register */
+-#define OP_WR_E1H		0x14 /* write single register */
+-#define OP_IW_E1H		0x15 /* write single register using mailbox */
+-#define OP_SW_E1H		0x16 /* copy a string to the device */
+-#define OP_SI_E1H		0x17 /* copy a string using mailbox */
+-#define OP_ZR_E1H		0x18 /* clear memory */
+-#define OP_ZP_E1H		0x19 /* unzip then copy with DMAE */
+-#define OP_WR_64_E1H		0x1a /* write 64 bit pattern on E1H */
+-#define OP_WB_E1H		0x1b /* copy a string using DMAE */
+-
+ /* FPGA and EMUL specific operations */
+-#define OP_WR_EMUL_E1H		0x1c /* write single register on E1H Emul */
+-#define OP_WR_EMUL		0x1d /* write single register on Emulation */
+-#define OP_WR_FPGA		0x1e /* write single register on FPGA */
+-#define OP_WR_ASIC		0x1f /* write single register on ASIC */
++#define OP_WR_EMUL		0xa /* write single register on Emulation */
++#define OP_WR_FPGA		0xb /* write single register on FPGA */
++#define OP_WR_ASIC		0xc /* write single register on ASIC */
++
++/* Init stages */
++#define COMMON_STAGE            0
++#define PORT0_STAGE     	1
++#define PORT1_STAGE     	2
++/* Never reorder FUNCx stages !!! */
++#define FUNC0_STAGE     	3
++#define FUNC1_STAGE     	4
++#define FUNC2_STAGE     	5
++#define FUNC3_STAGE     	6
++#define FUNC4_STAGE     	7
++#define FUNC5_STAGE     	8
++#define FUNC6_STAGE     	9
++#define FUNC7_STAGE     	10
++#define STAGE_IDX_MAX   	11
++
++#define STAGE_START     	0
++#define STAGE_END       	1
++
++
++/* Indices of blocks */
++#define PRS_BLOCK               0
++#define SRCH_BLOCK              1
++#define TSDM_BLOCK              2
++#define TCM_BLOCK               3
++#define BRB1_BLOCK              4
++#define TSEM_BLOCK              5
++#define PXPCS_BLOCK             6
++#define EMAC0_BLOCK             7
++#define EMAC1_BLOCK             8
++#define DBU_BLOCK               9
++#define MISC_BLOCK              10
++#define DBG_BLOCK               11
++#define NIG_BLOCK               12
++#define MCP_BLOCK               13
++#define UPB_BLOCK               14
++#define CSDM_BLOCK              15
++#define USDM_BLOCK              16
++#define CCM_BLOCK               17
++#define UCM_BLOCK               18
++#define USEM_BLOCK              19
++#define CSEM_BLOCK              20
++#define XPB_BLOCK               21
++#define DQ_BLOCK                22
++#define TIMERS_BLOCK            23
++#define XSDM_BLOCK              24
++#define QM_BLOCK                25
++#define PBF_BLOCK               26
++#define XCM_BLOCK               27
++#define XSEM_BLOCK              28
++#define CDU_BLOCK               29
++#define DMAE_BLOCK              30
++#define PXP_BLOCK               31
++#define CFC_BLOCK               32
++#define HC_BLOCK                33
++#define PXP2_BLOCK              34
++#define MISC_AEU_BLOCK          35
++
++/* Returns the index of start or end of a specific block stage in ops array*/
++#define BLOCK_OPS_IDX(block, stage, end) \
++       (2*(((block)*STAGE_IDX_MAX) + (stage)) + (end))
+ 
+ 
+ struct raw_op {
+@@ -118,292 +158,6 @@ union init_op {
+ 	struct raw_op		raw;
+ };
+ 
+-#include "bnx2x_init_values.h"
+-
+-static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
+-static int bnx2x_gunzip(struct bnx2x *bp, u8 *zbuf, int len);
+-
+-static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data,
+-			      u32 len)
+-{
+-	int i;
+-
+-	for (i = 0; i < len; i++) {
+-		REG_WR(bp, addr + i*4, data[i]);
+-		if (!(i % 10000)) {
+-			touch_softlockup_watchdog();
+-			cpu_relax();
+-		}
+-	}
+-}
+-
+-static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data,
+-			      u16 len)
+-{
+-	int i;
+-
+-	for (i = 0; i < len; i++) {
+-		REG_WR_IND(bp, addr + i*4, data[i]);
+-		if (!(i % 10000)) {
+-			touch_softlockup_watchdog();
+-			cpu_relax();
+-		}
+-	}
+-}
+-
+-static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len)
+-{
+-	int offset = 0;
+-
+-	if (bp->dmae_ready) {
+-		while (len > DMAE_LEN32_WR_MAX) {
+-			bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
+-					 addr + offset, DMAE_LEN32_WR_MAX);
+-			offset += DMAE_LEN32_WR_MAX * 4;
+-			len -= DMAE_LEN32_WR_MAX;
+-		}
+-		bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
+-				 addr + offset, len);
+-	} else
+-		bnx2x_init_str_wr(bp, addr, bp->gunzip_buf, len);
+-}
+-
+-static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
+-{
+-	u32 buf_len = (((len * 4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len * 4));
+-	u32 buf_len32 = buf_len / 4;
+-	int i;
+-
+-	memset(bp->gunzip_buf, fill, buf_len);
+-
+-	for (i = 0; i < len; i += buf_len32) {
+-		u32 cur_len = min(buf_len32, len - i);
+-
+-		bnx2x_write_big_buf(bp, addr + i * 4, cur_len);
+-	}
+-}
+-
+-static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data,
+-			     u32 len64)
+-{
+-	u32 buf_len32 = FW_BUF_SIZE / 4;
+-	u32 len = len64 * 2;
+-	u64 data64 = 0;
+-	int i;
+-
+-	/* 64 bit value is in a blob: first low DWORD, then high DWORD */
+-	data64 = HILO_U64((*(data + 1)), (*data));
+-	len64 = min((u32)(FW_BUF_SIZE/8), len64);
+-	for (i = 0; i < len64; i++) {
+-		u64 *pdata = ((u64 *)(bp->gunzip_buf)) + i;
+-
+-		*pdata = data64;
+-	}
+-
+-	for (i = 0; i < len; i += buf_len32) {
+-		u32 cur_len = min(buf_len32, len - i);
+-
+-		bnx2x_write_big_buf(bp, addr + i * 4, cur_len);
+-	}
+-}
+-
+-/*********************************************************
+-   There are different blobs for each PRAM section.
+-   In addition, each blob write operation is divided into a few operations
+-   in order to decrease the amount of phys. contiguous buffer needed.
+-   Thus, when we select a blob the address may be with some offset
+-   from the beginning of PRAM section.
+-   The same holds for the INT_TABLE sections.
+-**********************************************************/
+-#define IF_IS_INT_TABLE_ADDR(base, addr) \
+-			if (((base) <= (addr)) && ((base) + 0x400 >= (addr)))
+-
+-#define IF_IS_PRAM_ADDR(base, addr) \
+-			if (((base) <= (addr)) && ((base) + 0x40000 >= (addr)))
+-
+-static const u32 *bnx2x_sel_blob(u32 addr, const u32 *data, int is_e1)
+-{
+-	IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE, addr)
+-		data = is_e1 ? tsem_int_table_data_e1 :
+-			       tsem_int_table_data_e1h;
+-	else
+-		IF_IS_INT_TABLE_ADDR(CSEM_REG_INT_TABLE, addr)
+-			data = is_e1 ? csem_int_table_data_e1 :
+-				       csem_int_table_data_e1h;
+-	else
+-		IF_IS_INT_TABLE_ADDR(USEM_REG_INT_TABLE, addr)
+-			data = is_e1 ? usem_int_table_data_e1 :
+-				       usem_int_table_data_e1h;
+-	else
+-		IF_IS_INT_TABLE_ADDR(XSEM_REG_INT_TABLE, addr)
+-			data = is_e1 ? xsem_int_table_data_e1 :
+-				       xsem_int_table_data_e1h;
+-	else
+-		IF_IS_PRAM_ADDR(TSEM_REG_PRAM, addr)
+-			data = is_e1 ? tsem_pram_data_e1 : tsem_pram_data_e1h;
+-	else
+-		IF_IS_PRAM_ADDR(CSEM_REG_PRAM, addr)
+-			data = is_e1 ? csem_pram_data_e1 : csem_pram_data_e1h;
+-	else
+-		IF_IS_PRAM_ADDR(USEM_REG_PRAM, addr)
+-			data = is_e1 ? usem_pram_data_e1 : usem_pram_data_e1h;
+-	else
+-		IF_IS_PRAM_ADDR(XSEM_REG_PRAM, addr)
+-			data = is_e1 ? xsem_pram_data_e1 : xsem_pram_data_e1h;
+-
+-	return data;
+-}
+-
+-static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, const u32 *data,
+-			     u32 len, int gunzip, int is_e1, u32 blob_off)
+-{
+-	int offset = 0;
+-
+-	data = bnx2x_sel_blob(addr, data, is_e1) + blob_off;
+-
+-	if (gunzip) {
+-		int rc;
+-#ifdef __BIG_ENDIAN
+-		int i, size;
+-		u32 *temp;
+-
+-		temp = kmalloc(len, GFP_KERNEL);
+-		size = (len / 4) + ((len % 4) ? 1 : 0);
+-		for (i = 0; i < size; i++)
+-			temp[i] = swab32(data[i]);
+-		data = temp;
+-#endif
+-		rc = bnx2x_gunzip(bp, (u8 *)data, len);
+-		if (rc) {
+-			BNX2X_ERR("gunzip failed ! rc %d\n", rc);
+-#ifdef __BIG_ENDIAN
+-			kfree(temp);
+-#endif
+-			return;
+-		}
+-		len = bp->gunzip_outlen;
+-#ifdef __BIG_ENDIAN
+-		kfree(temp);
+-		for (i = 0; i < len; i++)
+-			((u32 *)bp->gunzip_buf)[i] =
+-					swab32(((u32 *)bp->gunzip_buf)[i]);
+-#endif
+-	} else {
+-		if ((len * 4) > FW_BUF_SIZE) {
+-			BNX2X_ERR("LARGE DMAE OPERATION ! "
+-				  "addr 0x%x  len 0x%x\n", addr, len*4);
+-			return;
+-		}
+-		memcpy(bp->gunzip_buf, data, len * 4);
+-	}
+-
+-	if (bp->dmae_ready) {
+-		while (len > DMAE_LEN32_WR_MAX) {
+-			bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
+-					 addr + offset, DMAE_LEN32_WR_MAX);
+-			offset += DMAE_LEN32_WR_MAX * 4;
+-			len -= DMAE_LEN32_WR_MAX;
+-		}
+-		bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
+-				 addr + offset, len);
+-	} else
+-		bnx2x_init_ind_wr(bp, addr, bp->gunzip_buf, len);
+-}
+-
+-static void bnx2x_init_block(struct bnx2x *bp, u32 op_start, u32 op_end)
+-{
+-	int is_e1       = CHIP_IS_E1(bp);
+-	int is_e1h      = CHIP_IS_E1H(bp);
+-	int is_emul_e1h = (CHIP_REV_IS_EMUL(bp) && is_e1h);
+-	int hw_wr, i;
+-	union init_op *op;
+-	u32 op_type, addr, len;
+-	const u32 *data, *data_base;
+-
+-	if (CHIP_REV_IS_FPGA(bp))
+-		hw_wr = OP_WR_FPGA;
+-	else if (CHIP_REV_IS_EMUL(bp))
+-		hw_wr = OP_WR_EMUL;
+-	else
+-		hw_wr = OP_WR_ASIC;
+-
+-	if (is_e1)
+-		data_base = init_data_e1;
+-	else /* CHIP_IS_E1H(bp) */
+-		data_base = init_data_e1h;
+-
+-	for (i = op_start; i < op_end; i++) {
+-
+-		op = (union init_op *)&(init_ops[i]);
+-
+-		op_type = op->str_wr.op;
+-		addr = op->str_wr.offset;
+-		len = op->str_wr.data_len;
+-		data = data_base + op->str_wr.data_off;
+-
+-		/* careful! it must be in order */
+-		if (unlikely(op_type > OP_WB)) {
+-
+-			/* If E1 only */
+-			if (op_type <= OP_WB_E1) {
+-				if (is_e1)
+-					op_type -= (OP_RD_E1 - OP_RD);
+-
+-			/* If E1H only */
+-			} else if (op_type <= OP_WB_E1H) {
+-				if (is_e1h)
+-					op_type -= (OP_RD_E1H - OP_RD);
+-			}
+-
+-			/* HW/EMUL specific */
+-			if (op_type == hw_wr)
+-				op_type = OP_WR;
+-
+-			/* EMUL on E1H is special */
+-			if ((op_type == OP_WR_EMUL_E1H) && is_emul_e1h)
+-				op_type = OP_WR;
+-		}
+-
+-		switch (op_type) {
+-		case OP_RD:
+-			REG_RD(bp, addr);
+-			break;
+-		case OP_WR:
+-			REG_WR(bp, addr, op->write.val);
+-			break;
+-		case OP_SW:
+-			bnx2x_init_str_wr(bp, addr, data, len);
+-			break;
+-		case OP_WB:
+-			bnx2x_init_wr_wb(bp, addr, data, len, 0, is_e1, 0);
+-			break;
+-		case OP_SI:
+-			bnx2x_init_ind_wr(bp, addr, data, len);
+-			break;
+-		case OP_ZR:
+-			bnx2x_init_fill(bp, addr, 0, op->zero.len);
+-			break;
+-		case OP_ZP:
+-			bnx2x_init_wr_wb(bp, addr, data, len, 1, is_e1,
+-					 op->str_wr.data_off);
+-			break;
+-		case OP_WR_64:
+-			bnx2x_init_wr_64(bp, addr, data, len);
+-			break;
+-		default:
+-			/* happens whenever an op is of a diff HW */
+-#if 0
+-			DP(NETIF_MSG_HW, "skipping init operation  "
+-			   "index %d[%d:%d]: type %d  addr 0x%x  "
+-			   "len %d(0x%x)\n",
+-			   i, op_start, op_end, op_type, addr, len, len);
+-#endif
+-			break;
+-		}
+-	}
+-}
+-
+-
+ /****************************************************************************
+ * PXP
+ ****************************************************************************/
+@@ -567,111 +321,6 @@ static const struct arb_line write_arb_a
+ 		PXP2_REG_RQ_BW_WR_UBOUND30}
+ };
+ 
+-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, &devctl);
+-	DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl);
+-	w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
+-	if (bp->mrrs == -1)
+-		r_order = ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12);
+-	else {
+-		DP(NETIF_MSG_HW, "force read order to %d\n", bp->mrrs);
+-		r_order = bp->mrrs;
+-	}
+-
+-	if (r_order > MAX_RD_ORD) {
+-		DP(NETIF_MSG_HW, "read order of %d  order adjusted to %d\n",
+-		   r_order, MAX_RD_ORD);
+-		r_order = MAX_RD_ORD;
+-	}
+-	if (w_order > MAX_WR_ORD) {
+-		DP(NETIF_MSG_HW, "write order of %d  order adjusted to %d\n",
+-		   w_order, MAX_WR_ORD);
+-		w_order = MAX_WR_ORD;
+-	}
+-	if (CHIP_REV_IS_FPGA(bp)) {
+-		DP(NETIF_MSG_HW, "write order adjusted to 1 for FPGA\n");
+-		w_order = 0;
+-	}
+-	DP(NETIF_MSG_HW, "read order %d  write order %d\n", r_order, w_order);
+-
+-	for (i = 0; i < NUM_RD_Q-1; i++) {
+-		REG_WR(bp, read_arb_addr[i].l, read_arb_data[i][r_order].l);
+-		REG_WR(bp, read_arb_addr[i].add,
+-		       read_arb_data[i][r_order].add);
+-		REG_WR(bp, read_arb_addr[i].ubound,
+-		       read_arb_data[i][r_order].ubound);
+-	}
+-
+-	for (i = 0; i < NUM_WR_Q-1; i++) {
+-		if ((write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L29) ||
+-		    (write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L30)) {
+-
+-			REG_WR(bp, write_arb_addr[i].l,
+-			       write_arb_data[i][w_order].l);
+-
+-			REG_WR(bp, write_arb_addr[i].add,
+-			       write_arb_data[i][w_order].add);
+-
+-			REG_WR(bp, write_arb_addr[i].ubound,
+-			       write_arb_data[i][w_order].ubound);
+-		} else {
+-
+-			val = REG_RD(bp, write_arb_addr[i].l);
+-			REG_WR(bp, write_arb_addr[i].l,
+-			       val | (write_arb_data[i][w_order].l << 10));
+-
+-			val = REG_RD(bp, write_arb_addr[i].add);
+-			REG_WR(bp, write_arb_addr[i].add,
+-			       val | (write_arb_data[i][w_order].add << 10));
+-
+-			val = REG_RD(bp, write_arb_addr[i].ubound);
+-			REG_WR(bp, write_arb_addr[i].ubound,
+-			       val | (write_arb_data[i][w_order].ubound << 7));
+-		}
+-	}
+-
+-	val =  write_arb_data[NUM_WR_Q-1][w_order].add;
+-	val += write_arb_data[NUM_WR_Q-1][w_order].ubound << 10;
+-	val += write_arb_data[NUM_WR_Q-1][w_order].l << 17;
+-	REG_WR(bp, PXP2_REG_PSWRQ_BW_RD, val);
+-
+-	val =  read_arb_data[NUM_RD_Q-1][r_order].add;
+-	val += read_arb_data[NUM_RD_Q-1][r_order].ubound << 10;
+-	val += read_arb_data[NUM_RD_Q-1][r_order].l << 17;
+-	REG_WR(bp, PXP2_REG_PSWRQ_BW_WR, val);
+-
+-	REG_WR(bp, PXP2_REG_RQ_WR_MBS0, w_order);
+-	REG_WR(bp, PXP2_REG_RQ_WR_MBS1, w_order);
+-	REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order);
+-	REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order);
+-
+-	if (r_order == MAX_RD_ORD)
+-		REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00);
+-
+-	REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
+-
+-	if (CHIP_IS_E1H(bp)) {
+-		val = ((w_order == 0) ? 2 : 3);
+-		REG_WR(bp, PXP2_REG_WR_HC_MPS, val);
+-		REG_WR(bp, PXP2_REG_WR_USDM_MPS, val);
+-		REG_WR(bp, PXP2_REG_WR_CSDM_MPS, val);
+-		REG_WR(bp, PXP2_REG_WR_TSDM_MPS, val);
+-		REG_WR(bp, PXP2_REG_WR_XSDM_MPS, val);
+-		REG_WR(bp, PXP2_REG_WR_QM_MPS, val);
+-		REG_WR(bp, PXP2_REG_WR_TM_MPS, val);
+-		REG_WR(bp, PXP2_REG_WR_SRC_MPS, val);
+-		REG_WR(bp, PXP2_REG_WR_DBG_MPS, val);
+-		REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2); /* DMAE is special */
+-		REG_WR(bp, PXP2_REG_WR_CDU_MPS, val);
+-	}
+-}
+-
+ 
+ /****************************************************************************
+ * CDU
+@@ -695,128 +344,12 @@ static void bnx2x_init_pxp(struct bnx2x 
+ 	(0x80 | ((_type) & 0xf << 3) | (CDU_CRC8(_cid, _region, _type) & 0x7))
+ #define CDU_RSRVD_INVALIDATE_CONTEXT_VALUE(_val)	((_val) & ~0x80)
+ 
+-/*****************************************************************************
+- * Description:
+- *         Calculates crc 8 on a word value: polynomial 0-1-2-8
+- *         Code was translated from Verilog.
+- ****************************************************************************/
+-static u8 calc_crc8(u32 data, u8 crc)
+-{
+-	u8 D[32];
+-	u8 NewCRC[8];
+-	u8 C[8];
+-	u8 crc_res;
+-	u8 i;
+-
+-	/* split the data into 31 bits */
+-	for (i = 0; i < 32; i++) {
+-		D[i] = data & 1;
+-		data = data >> 1;
+-	}
+-
+-	/* split the crc into 8 bits */
+-	for (i = 0; i < 8; i++) {
+-		C[i] = crc & 1;
+-		crc = crc >> 1;
+-	}
+-
+-	NewCRC[0] = D[31] ^ D[30] ^ D[28] ^ D[23] ^ D[21] ^ D[19] ^ D[18] ^
+-		D[16] ^ D[14] ^ D[12] ^ D[8] ^ D[7] ^ D[6] ^ D[0] ^ C[4] ^
+-		C[6] ^ C[7];
+-	NewCRC[1] = D[30] ^ D[29] ^ D[28] ^ D[24] ^ D[23] ^ D[22] ^ D[21] ^
+-		D[20] ^ D[18] ^ D[17] ^ D[16] ^ D[15] ^ D[14] ^ D[13] ^
+-		D[12] ^ D[9] ^ D[6] ^ D[1] ^ D[0] ^ C[0] ^ C[4] ^ C[5] ^ C[6];
+-	NewCRC[2] = D[29] ^ D[28] ^ D[25] ^ D[24] ^ D[22] ^ D[17] ^ D[15] ^
+-		D[13] ^ D[12] ^ D[10] ^ D[8] ^ D[6] ^ D[2] ^ D[1] ^ D[0] ^
+-		C[0] ^ C[1] ^ C[4] ^ C[5];
+-	NewCRC[3] = D[30] ^ D[29] ^ D[26] ^ D[25] ^ D[23] ^ D[18] ^ D[16] ^
+-		D[14] ^ D[13] ^ D[11] ^ D[9] ^ D[7] ^ D[3] ^ D[2] ^ D[1] ^
+-		C[1] ^ C[2] ^ C[5] ^ C[6];
+-	NewCRC[4] = D[31] ^ D[30] ^ D[27] ^ D[26] ^ D[24] ^ D[19] ^ D[17] ^
+-		D[15] ^ D[14] ^ D[12] ^ D[10] ^ D[8] ^ D[4] ^ D[3] ^ D[2] ^
+-		C[0] ^ C[2] ^ C[3] ^ C[6] ^ C[7];
+-	NewCRC[5] = D[31] ^ D[28] ^ D[27] ^ D[25] ^ D[20] ^ D[18] ^ D[16] ^
+-		D[15] ^ D[13] ^ D[11] ^ D[9] ^ D[5] ^ D[4] ^ D[3] ^ C[1] ^
+-		C[3] ^ C[4] ^ C[7];
+-	NewCRC[6] = D[29] ^ D[28] ^ D[26] ^ D[21] ^ D[19] ^ D[17] ^ D[16] ^
+-		D[14] ^ D[12] ^ D[10] ^ D[6] ^ D[5] ^ D[4] ^ C[2] ^ C[4] ^
+-		C[5];
+-	NewCRC[7] = D[30] ^ D[29] ^ D[27] ^ D[22] ^ D[20] ^ D[18] ^ D[17] ^
+-		D[15] ^ D[13] ^ D[11] ^ D[7] ^ D[6] ^ D[5] ^ C[3] ^ C[5] ^
+-		C[6];
+-
+-	crc_res = 0;
+-	for (i = 0; i < 8; i++)
+-		crc_res |= (NewCRC[i] << i);
+-
+-	return crc_res;
+-}
+ 
+ /* registers addresses are not in order
+    so these arrays help simplify the code */
+-static const int cm_start[E1H_FUNC_MAX][9] = {
+-	{MISC_FUNC0_START, TCM_FUNC0_START, UCM_FUNC0_START, CCM_FUNC0_START,
+-	 XCM_FUNC0_START, TSEM_FUNC0_START, USEM_FUNC0_START, CSEM_FUNC0_START,
+-	 XSEM_FUNC0_START},
+-	{MISC_FUNC1_START, TCM_FUNC1_START, UCM_FUNC1_START, CCM_FUNC1_START,
+-	 XCM_FUNC1_START, TSEM_FUNC1_START, USEM_FUNC1_START, CSEM_FUNC1_START,
+-	 XSEM_FUNC1_START},
+-	{MISC_FUNC2_START, TCM_FUNC2_START, UCM_FUNC2_START, CCM_FUNC2_START,
+-	 XCM_FUNC2_START, TSEM_FUNC2_START, USEM_FUNC2_START, CSEM_FUNC2_START,
+-	 XSEM_FUNC2_START},
+-	{MISC_FUNC3_START, TCM_FUNC3_START, UCM_FUNC3_START, CCM_FUNC3_START,
+-	 XCM_FUNC3_START, TSEM_FUNC3_START, USEM_FUNC3_START, CSEM_FUNC3_START,
+-	 XSEM_FUNC3_START},
+-	{MISC_FUNC4_START, TCM_FUNC4_START, UCM_FUNC4_START, CCM_FUNC4_START,
+-	 XCM_FUNC4_START, TSEM_FUNC4_START, USEM_FUNC4_START, CSEM_FUNC4_START,
+-	 XSEM_FUNC4_START},
+-	{MISC_FUNC5_START, TCM_FUNC5_START, UCM_FUNC5_START, CCM_FUNC5_START,
+-	 XCM_FUNC5_START, TSEM_FUNC5_START, USEM_FUNC5_START, CSEM_FUNC5_START,
+-	 XSEM_FUNC5_START},
+-	{MISC_FUNC6_START, TCM_FUNC6_START, UCM_FUNC6_START, CCM_FUNC6_START,
+-	 XCM_FUNC6_START, TSEM_FUNC6_START, USEM_FUNC6_START, CSEM_FUNC6_START,
+-	 XSEM_FUNC6_START},
+-	{MISC_FUNC7_START, TCM_FUNC7_START, UCM_FUNC7_START, CCM_FUNC7_START,
+-	 XCM_FUNC7_START, TSEM_FUNC7_START, USEM_FUNC7_START, CSEM_FUNC7_START,
+-	 XSEM_FUNC7_START}
+-};
+-
+-static const int cm_end[E1H_FUNC_MAX][9] = {
+-	{MISC_FUNC0_END, TCM_FUNC0_END, UCM_FUNC0_END, CCM_FUNC0_END,
+-	 XCM_FUNC0_END, TSEM_FUNC0_END, USEM_FUNC0_END, CSEM_FUNC0_END,
+-	 XSEM_FUNC0_END},
+-	{MISC_FUNC1_END, TCM_FUNC1_END, UCM_FUNC1_END, CCM_FUNC1_END,
+-	 XCM_FUNC1_END, TSEM_FUNC1_END, USEM_FUNC1_END, CSEM_FUNC1_END,
+-	 XSEM_FUNC1_END},
+-	{MISC_FUNC2_END, TCM_FUNC2_END, UCM_FUNC2_END, CCM_FUNC2_END,
+-	 XCM_FUNC2_END, TSEM_FUNC2_END, USEM_FUNC2_END, CSEM_FUNC2_END,
+-	 XSEM_FUNC2_END},
+-	{MISC_FUNC3_END, TCM_FUNC3_END, UCM_FUNC3_END, CCM_FUNC3_END,
+-	 XCM_FUNC3_END, TSEM_FUNC3_END, USEM_FUNC3_END, CSEM_FUNC3_END,
+-	 XSEM_FUNC3_END},
+-	{MISC_FUNC4_END, TCM_FUNC4_END, UCM_FUNC4_END, CCM_FUNC4_END,
+-	 XCM_FUNC4_END, TSEM_FUNC4_END, USEM_FUNC4_END, CSEM_FUNC4_END,
+-	 XSEM_FUNC4_END},
+-	{MISC_FUNC5_END, TCM_FUNC5_END, UCM_FUNC5_END, CCM_FUNC5_END,
+-	 XCM_FUNC5_END, TSEM_FUNC5_END, USEM_FUNC5_END, CSEM_FUNC5_END,
+-	 XSEM_FUNC5_END},
+-	{MISC_FUNC6_END, TCM_FUNC6_END, UCM_FUNC6_END, CCM_FUNC6_END,
+-	 XCM_FUNC6_END, TSEM_FUNC6_END, USEM_FUNC6_END, CSEM_FUNC6_END,
+-	 XSEM_FUNC6_END},
+-	{MISC_FUNC7_END, TCM_FUNC7_END, UCM_FUNC7_END, CCM_FUNC7_END,
+-	 XCM_FUNC7_END, TSEM_FUNC7_END, USEM_FUNC7_END, CSEM_FUNC7_END,
+-	 XSEM_FUNC7_END},
+-};
+-
+-static const int hc_limits[E1H_FUNC_MAX][2] = {
+-	{HC_FUNC0_START, HC_FUNC0_END},
+-	{HC_FUNC1_START, HC_FUNC1_END},
+-	{HC_FUNC2_START, HC_FUNC2_END},
+-	{HC_FUNC3_START, HC_FUNC3_END},
+-	{HC_FUNC4_START, HC_FUNC4_END},
+-	{HC_FUNC5_START, HC_FUNC5_END},
+-	{HC_FUNC6_START, HC_FUNC6_END},
+-	{HC_FUNC7_START, HC_FUNC7_END}
++static const int cm_blocks[9] = {
++	MISC_BLOCK, TCM_BLOCK,  UCM_BLOCK,  CCM_BLOCK, XCM_BLOCK,
++	TSEM_BLOCK, USEM_BLOCK, CSEM_BLOCK, XSEM_BLOCK
+ };
+ 
+ #endif /* BNX2X_INIT_H */
+diff -urpN linux-2.6-2.6.30~rc6.orig/drivers/net/bnx2x_init_ops.h linux-2.6-2.6.30~rc6/drivers/net/bnx2x_init_ops.h
+--- linux-2.6-2.6.30~rc6.orig/drivers/net/bnx2x_init_ops.h	1969-12-31 17:00:00.000000000 -0700
++++ linux-2.6-2.6.30~rc6/drivers/net/bnx2x_init_ops.h	2009-05-26 15:20:01.000000000 -0600
+@@ -0,0 +1,442 @@
++/* bnx2x_init_ops.h: Broadcom Everest network driver.
++ *               Static functions needed during the initialization.
++ *               This file is "included" in bnx2x_main.c.
++ *
++ * Copyright (c) 2007-2009 Broadcom Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation.
++ *
++ * Maintained by: Eilon Greenstein <eilong at broadcom.com>
++ * Written by: Vladislav Zolotarov <vladz at broadcom.com>
++ */
++#ifndef BNX2X_INIT_OPS_H
++#define BNX2X_INIT_OPS_H
++
++static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
++static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len);
++
++static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data,
++			      u32 len)
++{
++	int i;
++
++	for (i = 0; i < len; i++) {
++		REG_WR(bp, addr + i*4, data[i]);
++		if (!(i % 10000)) {
++			touch_softlockup_watchdog();
++			cpu_relax();
++		}
++	}
++}
++
++static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data,
++			      u16 len)
++{
++	int i;
++
++	for (i = 0; i < len; i++) {
++		REG_WR_IND(bp, addr + i*4, data[i]);
++		if (!(i % 10000)) {
++			touch_softlockup_watchdog();
++			cpu_relax();
++		}
++	}
++}
++
++static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len)
++{
++	int offset = 0;
++
++	if (bp->dmae_ready) {
++		while (len > DMAE_LEN32_WR_MAX) {
++			bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
++					 addr + offset, DMAE_LEN32_WR_MAX);
++			offset += DMAE_LEN32_WR_MAX * 4;
++			len -= DMAE_LEN32_WR_MAX;
++		}
++		bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
++				 addr + offset, len);
++	} else
++		bnx2x_init_str_wr(bp, addr, bp->gunzip_buf, len);
++}
++
++static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
++{
++	u32 buf_len = (((len * 4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len * 4));
++	u32 buf_len32 = buf_len / 4;
++	int i;
++
++	memset(bp->gunzip_buf, fill, buf_len);
++
++	for (i = 0; i < len; i += buf_len32) {
++		u32 cur_len = min(buf_len32, len - i);
++
++		bnx2x_write_big_buf(bp, addr + i * 4, cur_len);
++	}
++}
++
++static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data,
++			     u32 len64)
++{
++	u32 buf_len32 = FW_BUF_SIZE / 4;
++	u32 len = len64 * 2;
++	u64 data64 = 0;
++	int i;
++
++	/* 64 bit value is in a blob: first low DWORD, then high DWORD */
++	data64 = HILO_U64((*(data + 1)), (*data));
++	len64 = min((u32)(FW_BUF_SIZE/8), len64);
++	for (i = 0; i < len64; i++) {
++		u64 *pdata = ((u64 *)(bp->gunzip_buf)) + i;
++
++		*pdata = data64;
++	}
++
++	for (i = 0; i < len; i += buf_len32) {
++		u32 cur_len = min(buf_len32, len - i);
++
++		bnx2x_write_big_buf(bp, addr + i * 4, cur_len);
++	}
++}
++
++/*********************************************************
++   There are different blobs for each PRAM section.
++   In addition, each blob write operation is divided into a few operations
++   in order to decrease the amount of phys. contiguous buffer needed.
++   Thus, when we select a blob the address may be with some offset
++   from the beginning of PRAM section.
++   The same holds for the INT_TABLE sections.
++**********************************************************/
++#define IF_IS_INT_TABLE_ADDR(base, addr) \
++			if (((base) <= (addr)) && ((base) + 0x400 >= (addr)))
++
++#define IF_IS_PRAM_ADDR(base, addr) \
++			if (((base) <= (addr)) && ((base) + 0x40000 >= (addr)))
++
++static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr, const u8 *data)
++{
++	IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE, addr)
++		data = bp->tsem_int_table_data;
++	else IF_IS_INT_TABLE_ADDR(CSEM_REG_INT_TABLE, addr)
++		data = bp->csem_int_table_data;
++	else IF_IS_INT_TABLE_ADDR(USEM_REG_INT_TABLE, addr)
++		data = bp->usem_int_table_data;
++	else IF_IS_INT_TABLE_ADDR(XSEM_REG_INT_TABLE, addr)
++		data = bp->xsem_int_table_data;
++	else IF_IS_PRAM_ADDR(TSEM_REG_PRAM, addr)
++		data = bp->tsem_pram_data;
++	else IF_IS_PRAM_ADDR(CSEM_REG_PRAM, addr)
++		data = bp->csem_pram_data;
++	else IF_IS_PRAM_ADDR(USEM_REG_PRAM, addr)
++		data = bp->usem_pram_data;
++	else IF_IS_PRAM_ADDR(XSEM_REG_PRAM, addr)
++		data = bp->xsem_pram_data;
++
++	return data;
++}
++
++static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len)
++{
++	int offset = 0;
++
++	if (bp->dmae_ready) {
++		while (len > DMAE_LEN32_WR_MAX) {
++			bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
++					 addr + offset, DMAE_LEN32_WR_MAX);
++			offset += DMAE_LEN32_WR_MAX * 4;
++			len -= DMAE_LEN32_WR_MAX;
++		}
++		bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
++				 addr + offset, len);
++	} else
++		bnx2x_init_ind_wr(bp, addr, bp->gunzip_buf, len);
++}
++
++static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, const u32 *data,
++			     u32 len)
++{
++	/* This is needed for NO_ZIP mode, currently supported
++	   in little endian mode only */
++	data = (const u32*)bnx2x_sel_blob(bp, addr, (const u8*)data);
++
++	if ((len * 4) > FW_BUF_SIZE) {
++		BNX2X_ERR("LARGE DMAE OPERATION ! "
++			  "addr 0x%x  len 0x%x\n", addr, len*4);
++		return;
++	}
++	memcpy(bp->gunzip_buf, data, len * 4);
++
++	bnx2x_write_big_buf_wb(bp, addr, len);
++}
++
++static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr,
++			     u32 len, u32 blob_off)
++{
++	int rc, i;
++        const u8 *data = NULL;
++
++	data = bnx2x_sel_blob(bp, addr, data) + 4*blob_off;
++
++	if (data == NULL) {
++		panic("Blob not found for addr 0x%x\n", addr);
++		return;
++	}
++
++	rc = bnx2x_gunzip(bp, data, len);
++	if (rc) {
++		BNX2X_ERR("gunzip failed ! addr 0x%x rc %d\n", addr, rc);
++		BNX2X_ERR("blob_offset=0x%x\n", blob_off);
++		return;
++	}
++
++	/* gunzip_outlen is in dwords */
++	len = bp->gunzip_outlen;
++	for (i = 0; i < len; i++)
++		((u32 *)bp->gunzip_buf)[i] =
++			cpu_to_le32(((u32 *)bp->gunzip_buf)[i]);
++
++	bnx2x_write_big_buf_wb(bp, addr, len);
++}
++
++static void bnx2x_init_block(struct bnx2x *bp, u32 block, u32 stage)
++{
++	int hw_wr, i;
++	u16 op_start =
++		bp->init_ops_offsets[BLOCK_OPS_IDX(block,stage,STAGE_START)];
++	u16 op_end =
++		bp->init_ops_offsets[BLOCK_OPS_IDX(block,stage,STAGE_END)];
++	union init_op *op;
++	u32 op_type, addr, len;
++	const u32 *data, *data_base;
++
++	/* If empty block */
++	if (op_start == op_end)
++		return;
++
++	if (CHIP_REV_IS_FPGA(bp))
++		hw_wr = OP_WR_FPGA;
++	else if (CHIP_REV_IS_EMUL(bp))
++		hw_wr = OP_WR_EMUL;
++	else
++		hw_wr = OP_WR_ASIC;
++
++	data_base = bp->init_data;
++
++	for (i = op_start; i < op_end; i++) {
++
++		op = (union init_op *)&(bp->init_ops[i]);
++
++		op_type = op->str_wr.op;
++		addr = op->str_wr.offset;
++		len = op->str_wr.data_len;
++		data = data_base + op->str_wr.data_off;
++
++		/* HW/EMUL specific */
++		if (unlikely((op_type > OP_WB) && (op_type == hw_wr)))
++			op_type = OP_WR;
++
++		switch (op_type) {
++		case OP_RD:
++			REG_RD(bp, addr);
++			break;
++		case OP_WR:
++			REG_WR(bp, addr, op->write.val);
++			break;
++		case OP_SW:
++			bnx2x_init_str_wr(bp, addr, data, len);
++			break;
++		case OP_WB:
++			bnx2x_init_wr_wb(bp, addr, data, len);
++			break;
++		case OP_SI:
++			bnx2x_init_ind_wr(bp, addr, data, len);
++			break;
++		case OP_ZR:
++			bnx2x_init_fill(bp, addr, 0, op->zero.len);
++			break;
++		case OP_ZP:
++			bnx2x_init_wr_zp(bp, addr, len,
++					 op->str_wr.data_off);
++			break;
++		case OP_WR_64:
++			bnx2x_init_wr_64(bp, addr, data, len);
++			break;
++		default:
++			/* happens whenever an op is of a diff HW */
++#if 0
++			DP(NETIF_MSG_HW, "skipping init operation  "
++			   "index %d[%d:%d]: type %d  addr 0x%x  "
++			   "len %d(0x%x)\n",
++			   i, op_start, op_end, op_type, addr, len, len);
++#endif
++			break;
++		}
++	}
++}
++
++/* PXP */
++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, &devctl);
++	DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl);
++	w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
++	if (bp->mrrs == -1)
++		r_order = ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12);
++	else {
++		DP(NETIF_MSG_HW, "force read order to %d\n", bp->mrrs);
++		r_order = bp->mrrs;
++	}
++
++	if (r_order > MAX_RD_ORD) {
++		DP(NETIF_MSG_HW, "read order of %d  order adjusted to %d\n",
++		   r_order, MAX_RD_ORD);
++		r_order = MAX_RD_ORD;
++	}
++	if (w_order > MAX_WR_ORD) {
++		DP(NETIF_MSG_HW, "write order of %d  order adjusted to %d\n",
++		   w_order, MAX_WR_ORD);
++		w_order = MAX_WR_ORD;
++	}
++	if (CHIP_REV_IS_FPGA(bp)) {
++		DP(NETIF_MSG_HW, "write order adjusted to 1 for FPGA\n");
++		w_order = 0;
++	}
++	DP(NETIF_MSG_HW, "read order %d  write order %d\n", r_order, w_order);
++
++	for (i = 0; i < NUM_RD_Q-1; i++) {
++		REG_WR(bp, read_arb_addr[i].l, read_arb_data[i][r_order].l);
++		REG_WR(bp, read_arb_addr[i].add,
++		       read_arb_data[i][r_order].add);
++		REG_WR(bp, read_arb_addr[i].ubound,
++		       read_arb_data[i][r_order].ubound);
++	}
++
++	for (i = 0; i < NUM_WR_Q-1; i++) {
++		if ((write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L29) ||
++		    (write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L30)) {
++
++			REG_WR(bp, write_arb_addr[i].l,
++			       write_arb_data[i][w_order].l);
++
++			REG_WR(bp, write_arb_addr[i].add,
++			       write_arb_data[i][w_order].add);
++
++			REG_WR(bp, write_arb_addr[i].ubound,
++			       write_arb_data[i][w_order].ubound);
++		} else {
++
++			val = REG_RD(bp, write_arb_addr[i].l);
++			REG_WR(bp, write_arb_addr[i].l,
++			       val | (write_arb_data[i][w_order].l << 10));
++
++			val = REG_RD(bp, write_arb_addr[i].add);
++			REG_WR(bp, write_arb_addr[i].add,
++			       val | (write_arb_data[i][w_order].add << 10));
++
++			val = REG_RD(bp, write_arb_addr[i].ubound);
++			REG_WR(bp, write_arb_addr[i].ubound,
++			       val | (write_arb_data[i][w_order].ubound << 7));
++		}
++	}
++
++	val =  write_arb_data[NUM_WR_Q-1][w_order].add;
++	val += write_arb_data[NUM_WR_Q-1][w_order].ubound << 10;
++	val += write_arb_data[NUM_WR_Q-1][w_order].l << 17;
++	REG_WR(bp, PXP2_REG_PSWRQ_BW_RD, val);
++
++	val =  read_arb_data[NUM_RD_Q-1][r_order].add;
++	val += read_arb_data[NUM_RD_Q-1][r_order].ubound << 10;
++	val += read_arb_data[NUM_RD_Q-1][r_order].l << 17;
++	REG_WR(bp, PXP2_REG_PSWRQ_BW_WR, val);
++
++	REG_WR(bp, PXP2_REG_RQ_WR_MBS0, w_order);
++	REG_WR(bp, PXP2_REG_RQ_WR_MBS1, w_order);
++	REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order);
++	REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order);
++
++	if (r_order == MAX_RD_ORD)
++		REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00);
++
++	REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
++
++	if (CHIP_IS_E1H(bp)) {
++		val = ((w_order == 0) ? 2 : 3);
++		REG_WR(bp, PXP2_REG_WR_HC_MPS, val);
++		REG_WR(bp, PXP2_REG_WR_USDM_MPS, val);
++		REG_WR(bp, PXP2_REG_WR_CSDM_MPS, val);
++		REG_WR(bp, PXP2_REG_WR_TSDM_MPS, val);
++		REG_WR(bp, PXP2_REG_WR_XSDM_MPS, val);
++		REG_WR(bp, PXP2_REG_WR_QM_MPS, val);
++		REG_WR(bp, PXP2_REG_WR_TM_MPS, val);
++		REG_WR(bp, PXP2_REG_WR_SRC_MPS, val);
++		REG_WR(bp, PXP2_REG_WR_DBG_MPS, val);
++		REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2); /* DMAE is special */
++		REG_WR(bp, PXP2_REG_WR_CDU_MPS, val);
++	}
++}
++
++/*****************************************************************************
++ * Description:
++ *         Calculates crc 8 on a word value: polynomial 0-1-2-8
++ *         Code was translated from Verilog.
++ ****************************************************************************/
++static u8 calc_crc8(u32 data, u8 crc)
++{
++	u8 D[32];
++	u8 NewCRC[8];
++	u8 C[8];
++	u8 crc_res;
++	u8 i;
++
++	/* split the data into 31 bits */
++	for (i = 0; i < 32; i++) {
++		D[i] = data & 1;
++		data = data >> 1;
++	}
++
++	/* split the crc into 8 bits */
++	for (i = 0; i < 8; i++) {
++		C[i] = crc & 1;
++		crc = crc >> 1;
++	}
++
++	NewCRC[0] = D[31] ^ D[30] ^ D[28] ^ D[23] ^ D[21] ^ D[19] ^ D[18] ^
++		D[16] ^ D[14] ^ D[12] ^ D[8] ^ D[7] ^ D[6] ^ D[0] ^ C[4] ^
++		C[6] ^ C[7];
++	NewCRC[1] = D[30] ^ D[29] ^ D[28] ^ D[24] ^ D[23] ^ D[22] ^ D[21] ^
++		D[20] ^ D[18] ^ D[17] ^ D[16] ^ D[15] ^ D[14] ^ D[13] ^
++		D[12] ^ D[9] ^ D[6] ^ D[1] ^ D[0] ^ C[0] ^ C[4] ^ C[5] ^ C[6];
++	NewCRC[2] = D[29] ^ D[28] ^ D[25] ^ D[24] ^ D[22] ^ D[17] ^ D[15] ^
++		D[13] ^ D[12] ^ D[10] ^ D[8] ^ D[6] ^ D[2] ^ D[1] ^ D[0] ^
++		C[0] ^ C[1] ^ C[4] ^ C[5];
++	NewCRC[3] = D[30] ^ D[29] ^ D[26] ^ D[25] ^ D[23] ^ D[18] ^ D[16] ^
++		D[14] ^ D[13] ^ D[11] ^ D[9] ^ D[7] ^ D[3] ^ D[2] ^ D[1] ^
++		C[1] ^ C[2] ^ C[5] ^ C[6];
++	NewCRC[4] = D[31] ^ D[30] ^ D[27] ^ D[26] ^ D[24] ^ D[19] ^ D[17] ^
++		D[15] ^ D[14] ^ D[12] ^ D[10] ^ D[8] ^ D[4] ^ D[3] ^ D[2] ^
++		C[0] ^ C[2] ^ C[3] ^ C[6] ^ C[7];
++	NewCRC[5] = D[31] ^ D[28] ^ D[27] ^ D[25] ^ D[20] ^ D[18] ^ D[16] ^
++		D[15] ^ D[13] ^ D[11] ^ D[9] ^ D[5] ^ D[4] ^ D[3] ^ C[1] ^
++		C[3] ^ C[4] ^ C[7];
++	NewCRC[6] = D[29] ^ D[28] ^ D[26] ^ D[21] ^ D[19] ^ D[17] ^ D[16] ^
++		D[14] ^ D[12] ^ D[10] ^ D[6] ^ D[5] ^ D[4] ^ C[2] ^ C[4] ^
++		C[5];
++	NewCRC[7] = D[30] ^ D[29] ^ D[27] ^ D[22] ^ D[20] ^ D[18] ^ D[17] ^
++		D[15] ^ D[13] ^ D[11] ^ D[7] ^ D[6] ^ D[5] ^ C[3] ^ C[5] ^
++		C[6];
++
++	crc_res = 0;
++	for (i = 0; i < 8; i++)
++		crc_res |= (NewCRC[i] << i);
++
++	return crc_res;
++}
++
++#endif /* BNX2X_INIT_OPS_H */
+diff -urpN linux-2.6-2.6.30~rc6.orig/drivers/net/bnx2x_main.c linux-2.6-2.6.30~rc6/drivers/net/bnx2x_main.c
+--- linux-2.6-2.6.30~rc6.orig/drivers/net/bnx2x_main.c	2009-05-19 03:52:19.000000000 -0600
++++ linux-2.6-2.6.30~rc6/drivers/net/bnx2x_main.c	2009-05-26 15:20:01.000000000 -0600
+@@ -53,12 +53,19 @@
+ 
+ #include "bnx2x.h"
+ #include "bnx2x_init.h"
++#include "bnx2x_init_ops.h"
+ #include "bnx2x_dump.h"
+ 
+ #define DRV_MODULE_VERSION	"1.48.105"
+ #define DRV_MODULE_RELDATE	"2009/03/02"
+ #define BNX2X_BC_VER		0x040200
+ 
++#include <linux/firmware.h>
++#include "bnx2x_fw_file_hdr.h"
++/* FW files */
++#define FW_FILE_PREFIX_E1		"bnx2x-e1-"
++#define FW_FILE_PREFIX_E1H		"bnx2x-e1h-"
++
+ /* Time in jiffies before concluding the transmitter is hung */
+ #define TX_TIMEOUT		(5*HZ)
+ 
+@@ -5232,13 +5239,15 @@ static void bnx2x_gunzip_end(struct bnx2
+ 	}
+ }
+ 
+-static int bnx2x_gunzip(struct bnx2x *bp, u8 *zbuf, int len)
++static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len)
+ {
+ 	int n, rc;
+ 
+ 	/* check gzip header */
+-	if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED))
++	if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED)) {
++		BNX2X_ERR("Bad gzip header\n");
+ 		return -EINVAL;
++	}
+ 
+ 	n = 10;
+ 
+@@ -5247,7 +5256,7 @@ static int bnx2x_gunzip(struct bnx2x *bp
+ 	if (zbuf[3] & FNAME)
+ 		while ((zbuf[n++] != 0) && (n < len));
+ 
+-	bp->strm->next_in = zbuf + n;
++	bp->strm->next_in = (typeof(bp->strm->next_in))zbuf + n;
+ 	bp->strm->avail_in = len - n;
+ 	bp->strm->next_out = bp->gunzip_buf;
+ 	bp->strm->avail_out = FW_BUF_SIZE;
+@@ -5369,8 +5378,8 @@ static int bnx2x_int_mem_test(struct bnx
+ 	msleep(50);
+ 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03);
+ 	msleep(50);
+-	bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END);
+-	bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END);
++	bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
++	bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
+ 
+ 	DP(NETIF_MSG_HW, "part2\n");
+ 
+@@ -5434,8 +5443,8 @@ static int bnx2x_int_mem_test(struct bnx
+ 	msleep(50);
+ 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03);
+ 	msleep(50);
+-	bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END);
+-	bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END);
++	bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
++	bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
+ #ifndef BCM_ISCSI
+ 	/* set NIC mode */
+ 	REG_WR(bp, PRS_REG_NIC_MODE, 1);
+@@ -5510,7 +5519,7 @@ static int bnx2x_init_common(struct bnx2
+ 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff);
+ 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc);
+ 
+-	bnx2x_init_block(bp, MISC_COMMON_START, MISC_COMMON_END);
++	bnx2x_init_block(bp, MISC_BLOCK, COMMON_STAGE);
+ 	if (CHIP_IS_E1H(bp))
+ 		REG_WR(bp, MISC_REG_E1HMF_MODE, IS_E1HMF(bp));
+ 
+@@ -5518,14 +5527,14 @@ static int bnx2x_init_common(struct bnx2
+ 	msleep(30);
+ 	REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x0);
+ 
+-	bnx2x_init_block(bp, PXP_COMMON_START, PXP_COMMON_END);
++	bnx2x_init_block(bp, PXP_BLOCK, COMMON_STAGE);
+ 	if (CHIP_IS_E1(bp)) {
+ 		/* enable HW interrupt from PXP on USDM overflow
+ 		   bit 16 on INT_MASK_0 */
+ 		REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
+ 	}
+ 
+-	bnx2x_init_block(bp, PXP2_COMMON_START, PXP2_COMMON_END);
++	bnx2x_init_block(bp, PXP2_BLOCK, COMMON_STAGE);
+ 	bnx2x_init_pxp(bp);
+ 
+ #ifdef __BIG_ENDIAN
+@@ -5571,60 +5580,60 @@ static int bnx2x_init_common(struct bnx2
+ 	REG_WR(bp, PXP2_REG_RQ_DISABLE_INPUTS, 0);
+ 	REG_WR(bp, PXP2_REG_RD_DISABLE_INPUTS, 0);
+ 
+-	bnx2x_init_block(bp, DMAE_COMMON_START, DMAE_COMMON_END);
++	bnx2x_init_block(bp, DMAE_BLOCK, COMMON_STAGE);
+ 
+ 	/* clean the DMAE memory */
+ 	bp->dmae_ready = 1;
+ 	bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8);
+ 
+-	bnx2x_init_block(bp, TCM_COMMON_START, TCM_COMMON_END);
+-	bnx2x_init_block(bp, UCM_COMMON_START, UCM_COMMON_END);
+-	bnx2x_init_block(bp, CCM_COMMON_START, CCM_COMMON_END);
+-	bnx2x_init_block(bp, XCM_COMMON_START, XCM_COMMON_END);
++	bnx2x_init_block(bp, TCM_BLOCK, COMMON_STAGE);
++	bnx2x_init_block(bp, UCM_BLOCK, COMMON_STAGE);
++	bnx2x_init_block(bp, CCM_BLOCK, COMMON_STAGE);
++	bnx2x_init_block(bp, XCM_BLOCK, COMMON_STAGE);
+ 
+ 	bnx2x_read_dmae(bp, XSEM_REG_PASSIVE_BUFFER, 3);
+ 	bnx2x_read_dmae(bp, CSEM_REG_PASSIVE_BUFFER, 3);
+ 	bnx2x_read_dmae(bp, TSEM_REG_PASSIVE_BUFFER, 3);
+ 	bnx2x_read_dmae(bp, USEM_REG_PASSIVE_BUFFER, 3);
+ 
+-	bnx2x_init_block(bp, QM_COMMON_START, QM_COMMON_END);
++	bnx2x_init_block(bp, QM_BLOCK, COMMON_STAGE);
+ 	/* soft reset pulse */
+ 	REG_WR(bp, QM_REG_SOFT_RESET, 1);
+ 	REG_WR(bp, QM_REG_SOFT_RESET, 0);
+ 
+ #ifdef BCM_ISCSI
+-	bnx2x_init_block(bp, TIMERS_COMMON_START, TIMERS_COMMON_END);
++	bnx2x_init_block(bp, TIMERS_BLOCK, COMMON_STAGE);
+ #endif
+ 
+-	bnx2x_init_block(bp, DQ_COMMON_START, DQ_COMMON_END);
++	bnx2x_init_block(bp, DQ_BLOCK, COMMON_STAGE);
+ 	REG_WR(bp, DORQ_REG_DPM_CID_OFST, BCM_PAGE_SHIFT);
+ 	if (!CHIP_REV_IS_SLOW(bp)) {
+ 		/* enable hw interrupt from doorbell Q */
+ 		REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
+ 	}
+ 
+-	bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END);
+-	bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END);
++	bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
++	bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
+ 	REG_WR(bp, PRS_REG_A_PRSU_20, 0xf);
+ 	/* set NIC mode */
+ 	REG_WR(bp, PRS_REG_NIC_MODE, 1);
+ 	if (CHIP_IS_E1H(bp))
+ 		REG_WR(bp, PRS_REG_E1HOV_MODE, IS_E1HMF(bp));
+ 
+-	bnx2x_init_block(bp, TSDM_COMMON_START, TSDM_COMMON_END);
+-	bnx2x_init_block(bp, CSDM_COMMON_START, CSDM_COMMON_END);
+-	bnx2x_init_block(bp, USDM_COMMON_START, USDM_COMMON_END);
+-	bnx2x_init_block(bp, XSDM_COMMON_START, XSDM_COMMON_END);
++	bnx2x_init_block(bp, TSDM_BLOCK, COMMON_STAGE);
++	bnx2x_init_block(bp, CSDM_BLOCK, COMMON_STAGE);
++	bnx2x_init_block(bp, USDM_BLOCK, COMMON_STAGE);
++	bnx2x_init_block(bp, XSDM_BLOCK, COMMON_STAGE);
+ 
+ 	bnx2x_init_fill(bp, TSTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp));
+ 	bnx2x_init_fill(bp, USTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp));
+ 	bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp));
+ 	bnx2x_init_fill(bp, XSTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp));
+ 
+-	bnx2x_init_block(bp, TSEM_COMMON_START, TSEM_COMMON_END);
+-	bnx2x_init_block(bp, USEM_COMMON_START, USEM_COMMON_END);
+-	bnx2x_init_block(bp, CSEM_COMMON_START, CSEM_COMMON_END);
+-	bnx2x_init_block(bp, XSEM_COMMON_START, XSEM_COMMON_END);
++	bnx2x_init_block(bp, TSEM_BLOCK, COMMON_STAGE);
++	bnx2x_init_block(bp, USEM_BLOCK, COMMON_STAGE);
++	bnx2x_init_block(bp, CSEM_BLOCK, COMMON_STAGE);
++	bnx2x_init_block(bp, XSEM_BLOCK, COMMON_STAGE);
+ 
+ 	/* sync semi rtc */
+ 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
+@@ -5632,16 +5641,16 @@ static int bnx2x_init_common(struct bnx2
+ 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
+ 	       0x80000000);
+ 
+-	bnx2x_init_block(bp, UPB_COMMON_START, UPB_COMMON_END);
+-	bnx2x_init_block(bp, XPB_COMMON_START, XPB_COMMON_END);
+-	bnx2x_init_block(bp, PBF_COMMON_START, PBF_COMMON_END);
++	bnx2x_init_block(bp, UPB_BLOCK, COMMON_STAGE);
++	bnx2x_init_block(bp, XPB_BLOCK, COMMON_STAGE);
++	bnx2x_init_block(bp, PBF_BLOCK, COMMON_STAGE);
+ 
+ 	REG_WR(bp, SRC_REG_SOFT_RST, 1);
+ 	for (i = SRC_REG_KEYRSS0_0; i <= SRC_REG_KEYRSS1_9; i += 4) {
+ 		REG_WR(bp, i, 0xc0cac01a);
+ 		/* TODO: replace with something meaningful */
+ 	}
+-	bnx2x_init_block(bp, SRCH_COMMON_START, SRCH_COMMON_END);
++	bnx2x_init_block(bp, SRCH_BLOCK, COMMON_STAGE);
+ 	REG_WR(bp, SRC_REG_SOFT_RST, 0);
+ 
+ 	if (sizeof(union cdu_context) != 1024)
+@@ -5649,7 +5658,7 @@ static int bnx2x_init_common(struct bnx2
+ 		printk(KERN_ALERT PFX "please adjust the size of"
+ 		       " cdu_context(%ld)\n", (long)sizeof(union cdu_context));
+ 
+-	bnx2x_init_block(bp, CDU_COMMON_START, CDU_COMMON_END);
++	bnx2x_init_block(bp, CDU_BLOCK, COMMON_STAGE);
+ 	val = (4 << 24) + (0 << 12) + 1024;
+ 	REG_WR(bp, CDU_REG_CDU_GLOBAL_PARAMS, val);
+ 	if (CHIP_IS_E1(bp)) {
+@@ -5658,7 +5667,7 @@ static int bnx2x_init_common(struct bnx2
+ 		REG_WR(bp, CDU_REG_CDU_DEBUG, 0);
+ 	}
+ 
+-	bnx2x_init_block(bp, CFC_COMMON_START, CFC_COMMON_END);
++	bnx2x_init_block(bp, CFC_BLOCK, COMMON_STAGE);
+ 	REG_WR(bp, CFC_REG_INIT_REG, 0x7FF);
+ 	/* enable context validation interrupt from CFC */
+ 	REG_WR(bp, CFC_REG_CFC_INT_MASK, 0);
+@@ -5666,20 +5675,25 @@ static int bnx2x_init_common(struct bnx2
+ 	/* set the thresholds to prevent CFC/CDU race */
+ 	REG_WR(bp, CFC_REG_DEBUG0, 0x20020000);
+ 
+-	bnx2x_init_block(bp, HC_COMMON_START, HC_COMMON_END);
+-	bnx2x_init_block(bp, MISC_AEU_COMMON_START, MISC_AEU_COMMON_END);
++	bnx2x_init_block(bp, HC_BLOCK, COMMON_STAGE);
++	bnx2x_init_block(bp, MISC_AEU_BLOCK, COMMON_STAGE);
+ 
+ 	/* PXPCS COMMON comes here */
++	bnx2x_init_block(bp, PXPCS_BLOCK, COMMON_STAGE);
+ 	/* Reset PCIE errors for debug */
+ 	REG_WR(bp, 0x2814, 0xffffffff);
+ 	REG_WR(bp, 0x3820, 0xffffffff);
+ 
+ 	/* EMAC0 COMMON comes here */
++	bnx2x_init_block(bp, EMAC0_BLOCK, COMMON_STAGE);
+ 	/* EMAC1 COMMON comes here */
++	bnx2x_init_block(bp, EMAC1_BLOCK, COMMON_STAGE);
+ 	/* DBU COMMON comes here */
++	bnx2x_init_block(bp, DBU_BLOCK, COMMON_STAGE);
+ 	/* DBG COMMON comes here */
++	bnx2x_init_block(bp, DBG_BLOCK, COMMON_STAGE);
+ 
+-	bnx2x_init_block(bp, NIG_COMMON_START, NIG_COMMON_END);
++	bnx2x_init_block(bp, NIG_BLOCK, COMMON_STAGE);
+ 	if (CHIP_IS_E1H(bp)) {
+ 		REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_E1HMF(bp));
+ 		REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_E1HMF(bp));
+@@ -5763,6 +5777,7 @@ static int bnx2x_init_common(struct bnx2
+ static int bnx2x_init_port(struct bnx2x *bp)
+ {
+ 	int port = BP_PORT(bp);
++	int init_stage = port ? PORT1_STAGE : PORT0_STAGE;
+ 	u32 low, high;
+ 	u32 val;
+ 
+@@ -5771,7 +5786,9 @@ static int bnx2x_init_port(struct bnx2x 
+ 	REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
+ 
+ 	/* Port PXP comes here */
++	bnx2x_init_block(bp, PXP_BLOCK, init_stage);
+ 	/* Port PXP2 comes here */
++	bnx2x_init_block(bp, PXP2_BLOCK, init_stage);
+ #ifdef BCM_ISCSI
+ 	/* Port0  1
+ 	 * Port1  385 */
+@@ -5798,21 +5815,19 @@ static int bnx2x_init_port(struct bnx2x 
+ 	REG_WR(bp, PXP2_REG_PSWRQ_SRC0_L2P + func*4, PXP_ONE_ILT(i));
+ #endif
+ 	/* Port CMs come here */
+-	bnx2x_init_block(bp, (port ? XCM_PORT1_START : XCM_PORT0_START),
+-			     (port ? XCM_PORT1_END : XCM_PORT0_END));
++	bnx2x_init_block(bp, XCM_BLOCK, init_stage);
+ 
+ 	/* Port QM comes here */
+ #ifdef BCM_ISCSI
+ 	REG_WR(bp, TM_REG_LIN0_SCAN_TIME + func*4, 1024/64*20);
+ 	REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + func*4, 31);
+ 
+-	bnx2x_init_block(bp, func ? TIMERS_PORT1_START : TIMERS_PORT0_START,
+-			     func ? TIMERS_PORT1_END : TIMERS_PORT0_END);
++	bnx2x_init_block(bp, TIMERS_BLOCK, init_stage);
+ #endif
+ 	/* Port DQ comes here */
++	bnx2x_init_block(bp, DQ_BLOCK, init_stage);
+ 
+-	bnx2x_init_block(bp, (port ? BRB1_PORT1_START : BRB1_PORT0_START),
+-			     (port ? BRB1_PORT1_END : BRB1_PORT0_END));
++	bnx2x_init_block(bp, BRB1_BLOCK, init_stage);
+ 	if (CHIP_REV_IS_SLOW(bp) && !CHIP_IS_E1H(bp)) {
+ 		/* no pause for emulation and FPGA */
+ 		low = 0;
+@@ -5837,25 +5852,27 @@ static int bnx2x_init_port(struct bnx2x 
+ 
+ 
+ 	/* Port PRS comes here */
++	bnx2x_init_block(bp, PRS_BLOCK, init_stage);
+ 	/* Port TSDM comes here */
++	bnx2x_init_block(bp, TSDM_BLOCK, init_stage);
+ 	/* Port CSDM comes here */
++	bnx2x_init_block(bp, CSDM_BLOCK, init_stage);
+ 	/* Port USDM comes here */
++	bnx2x_init_block(bp, USDM_BLOCK, init_stage);
+ 	/* Port XSDM comes here */
++	bnx2x_init_block(bp, XSDM_BLOCK, init_stage);
+ 
+-	bnx2x_init_block(bp, port ? TSEM_PORT1_START : TSEM_PORT0_START,
+-			     port ? TSEM_PORT1_END : TSEM_PORT0_END);
+-	bnx2x_init_block(bp, port ? USEM_PORT1_START : USEM_PORT0_START,
+-			     port ? USEM_PORT1_END : USEM_PORT0_END);
+-	bnx2x_init_block(bp, port ? CSEM_PORT1_START : CSEM_PORT0_START,
+-			     port ? CSEM_PORT1_END : CSEM_PORT0_END);
+-	bnx2x_init_block(bp, port ? XSEM_PORT1_START : XSEM_PORT0_START,
+-			     port ? XSEM_PORT1_END : XSEM_PORT0_END);
++	bnx2x_init_block(bp, TSEM_BLOCK, init_stage);
++	bnx2x_init_block(bp, USEM_BLOCK, init_stage);
++	bnx2x_init_block(bp, CSEM_BLOCK, init_stage);
++	bnx2x_init_block(bp, XSEM_BLOCK, init_stage);
+ 
+ 	/* Port UPB comes here */
++	bnx2x_init_block(bp, UPB_BLOCK, init_stage);
+ 	/* Port XPB comes here */
++	bnx2x_init_block(bp, XPB_BLOCK, init_stage);
+ 
+-	bnx2x_init_block(bp, port ? PBF_PORT1_START : PBF_PORT0_START,
+-			     port ? PBF_PORT1_END : PBF_PORT0_END);
++	bnx2x_init_block(bp, PBF_BLOCK, init_stage);
+ 
+ 	/* configure PBF to work without PAUSE mtu 9000 */
+ 	REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
+@@ -5885,18 +5902,17 @@ static int bnx2x_init_port(struct bnx2x 
+ 	/* Port SRCH comes here */
+ #endif
+ 	/* Port CDU comes here */
++	bnx2x_init_block(bp, CDU_BLOCK, init_stage);
+ 	/* Port CFC comes here */
++	bnx2x_init_block(bp, CFC_BLOCK, init_stage);
+ 
+ 	if (CHIP_IS_E1(bp)) {
+ 		REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
+ 		REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
+ 	}
+-	bnx2x_init_block(bp, port ? HC_PORT1_START : HC_PORT0_START,
+-			     port ? HC_PORT1_END : HC_PORT0_END);
++	bnx2x_init_block(bp, HC_BLOCK, init_stage);
+ 
+-	bnx2x_init_block(bp, port ? MISC_AEU_PORT1_START :
+-				    MISC_AEU_PORT0_START,
+-			     port ? MISC_AEU_PORT1_END : MISC_AEU_PORT0_END);
++	bnx2x_init_block(bp, MISC_AEU_BLOCK, init_stage);
+ 	/* init aeu_mask_attn_func_0/1:
+ 	 *  - SF mode: bits 3-7 are masked. only bits 0-2 are in use
+ 	 *  - MF mode: bit 3 is masked. bits 0-2 are in use as in SF
+@@ -5905,13 +5921,17 @@ static int bnx2x_init_port(struct bnx2x 
+ 	       (IS_E1HMF(bp) ? 0xF7 : 0x7));
+ 
+ 	/* Port PXPCS comes here */
++	bnx2x_init_block(bp, PXPCS_BLOCK, init_stage);
+ 	/* Port EMAC0 comes here */
++	bnx2x_init_block(bp, EMAC0_BLOCK, init_stage);
+ 	/* Port EMAC1 comes here */
++	bnx2x_init_block(bp, EMAC1_BLOCK, init_stage);
+ 	/* Port DBU comes here */
++	bnx2x_init_block(bp, DBU_BLOCK, init_stage);
+ 	/* Port DBG comes here */
++	bnx2x_init_block(bp, DBG_BLOCK, init_stage);
+ 
+-	bnx2x_init_block(bp, port ? NIG_PORT1_START : NIG_PORT0_START,
+-			     port ? NIG_PORT1_END : NIG_PORT0_END);
++	bnx2x_init_block(bp, NIG_BLOCK, init_stage);
+ 
+ 	REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
+ 
+@@ -5931,7 +5951,9 @@ static int bnx2x_init_port(struct bnx2x 
+ 	}
+ 
+ 	/* Port MCP comes here */
++	bnx2x_init_block(bp, MCP_BLOCK, init_stage);
+ 	/* Port DMAE comes here */
++	bnx2x_init_block(bp, DMAE_BLOCK, init_stage);
+ 
+ 	switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) {
+ 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+@@ -6036,7 +6058,7 @@ static int bnx2x_init_func(struct bnx2x 
+ 	if (CHIP_IS_E1H(bp)) {
+ 		for (i = 0; i < 9; i++)
+ 			bnx2x_init_block(bp,
+-					 cm_start[func][i], cm_end[func][i]);
++					 cm_blocks[i], FUNC0_STAGE + func);
+ 
+ 		REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1);
+ 		REG_WR(bp, NIG_REG_LLH0_FUNC_VLAN_ID + port*8, bp->e1hov);
+@@ -6049,7 +6071,7 @@ static int bnx2x_init_func(struct bnx2x 
+ 		REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
+ 		REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
+ 	}
+-	bnx2x_init_block(bp, hc_limits[func][0], hc_limits[func][1]);
++	bnx2x_init_block(bp, HC_BLOCK, FUNC0_STAGE + func);
+ 
+ 	/* Reset PCIE errors for debug */
+ 	REG_WR(bp, 0x2114, 0xffffffff);
+@@ -11082,6 +11104,190 @@ static int __devinit bnx2x_get_pcie_spee
+ 	val = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT;
+ 	return val;
+ }
++static int __devinit bnx2x_check_firmware(struct bnx2x *bp)
++{
++	struct bnx2x_fw_file_hdr *fw_hdr;
++	struct bnx2x_fw_file_section *sections;
++	u16 *ops_offsets;
++	u32 offset, len, num_ops;
++	int i;
++	const struct firmware *firmware = bp->firmware;
++	const u8 * fw_ver;
++
++	if (firmware->size < sizeof(struct bnx2x_fw_file_hdr))
++		return -EINVAL;
++
++	fw_hdr = (struct bnx2x_fw_file_hdr *)firmware->data;
++	sections = (struct bnx2x_fw_file_section *)fw_hdr;
++
++	/* Make sure none of the offsets and sizes make us read beyond
++	 * the end of the firmware data */
++	for (i = 0; i < sizeof(*fw_hdr) / sizeof(*sections); i++) {
++		offset = be32_to_cpu(sections[i].offset);
++		len = be32_to_cpu(sections[i].len);
++		if (offset + len > firmware->size) {
++			printk(KERN_ERR PFX "Section %d length is out of bounds\n", i);
++			return -EINVAL;
++		}
++	}
++
++	/* Likewise for the init_ops offsets */
++	offset = be32_to_cpu(fw_hdr->init_ops_offsets.offset);
++	ops_offsets = (u16 *)(firmware->data + offset);
++	num_ops = be32_to_cpu(fw_hdr->init_ops.len) / sizeof(struct raw_op);
++
++	for (i = 0; i < be32_to_cpu(fw_hdr->init_ops_offsets.len) / 2; i++) {
++		if (be16_to_cpu(ops_offsets[i]) > num_ops) {
++			printk(KERN_ERR PFX "Section offset %d is out of bounds\n", i);
++			return -EINVAL;
++		}
++	}
++
++	/* Check FW version */
++	offset = be32_to_cpu(fw_hdr->fw_version.offset);
++	fw_ver = firmware->data + offset;
++	if ((fw_ver[0] != BCM_5710_FW_MAJOR_VERSION) ||
++	    (fw_ver[1] != BCM_5710_FW_MINOR_VERSION) ||
++	    (fw_ver[2] != BCM_5710_FW_REVISION_VERSION) ||
++	    (fw_ver[3] != BCM_5710_FW_ENGINEERING_VERSION)) {
++		printk(KERN_ERR PFX "Bad FW version:%d.%d.%d.%d."
++				    " Should be %d.%d.%d.%d\n",
++		       fw_ver[0], fw_ver[1], fw_ver[2],
++		       fw_ver[3], BCM_5710_FW_MAJOR_VERSION,
++		       BCM_5710_FW_MINOR_VERSION,
++		       BCM_5710_FW_REVISION_VERSION,
++		       BCM_5710_FW_ENGINEERING_VERSION);
++                return -EINVAL;
++	}
++
++	return 0;
++}
++
++static void inline be32_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
++{
++	u32 i;
++	const __be32 *source = (const __be32*)_source;
++	u32 *target = (u32*)_target;
++
++	for (i = 0; i < n/4; i++)
++		target[i] = be32_to_cpu(source[i]);
++}
++
++/*
++   Ops array is stored in the following format:
++   {op(8bit), offset(24bit, big endian), data(32bit, big endian)}
++ */
++static void inline bnx2x_prep_ops(const u8 *_source, u8 *_target, u32 n)
++{
++	u32 i, j, tmp;
++	const __be32 *source = (const __be32*)_source;
++	struct raw_op *target = (struct raw_op*)_target;
++
++	for (i = 0, j = 0; i < n/8; i++, j+=2) {
++		tmp = be32_to_cpu(source[j]);
++		target[i].op = (tmp >> 24) & 0xff;
++		target[i].offset =  tmp & 0xffffff;
++		target[i].raw_data = be32_to_cpu(source[j+1]);
++	}
++}
++static void inline be16_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
++{
++	u32 i;
++	u16 *target = (u16*)_target;
++	const __be16 *source = (const __be16*)_source;
++
++	for (i = 0; i < n/2; i++)
++		target[i] = be16_to_cpu(source[i]);
++}
++
++#define BNX2X_ALLOC_AND_SET(arr, lbl, func) \
++	do {   \
++		u32 len = be32_to_cpu(fw_hdr->arr.len);   \
++		bp->arr = kmalloc(len, GFP_KERNEL);  \
++		if (!bp->arr) { \
++			printk(KERN_ERR PFX "Failed to allocate %d bytes for "#arr"\n", len); \
++			goto lbl; \
++		} \
++		func(bp->firmware->data + \
++			be32_to_cpu(fw_hdr->arr.offset), \
++			(u8*)bp->arr, len); \
++	} while (0)
++
++
++static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev)
++{
++	char fw_file_name[40] = {0};
++        int rc, offset;
++	struct bnx2x_fw_file_hdr *fw_hdr;
++
++	/* Create a FW file name */
++	if (CHIP_IS_E1(bp))
++                offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1);
++	else
++		offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1H);
++
++	sprintf(fw_file_name + offset, "%d.%d.%d.%d.fw",
++		BCM_5710_FW_MAJOR_VERSION,
++                BCM_5710_FW_MINOR_VERSION,
++                BCM_5710_FW_REVISION_VERSION,
++                BCM_5710_FW_ENGINEERING_VERSION);
++
++	printk(KERN_INFO PFX "Loading %s\n", fw_file_name);
++
++	rc = request_firmware(&bp->firmware, fw_file_name, dev);
++	if (rc) {
++		printk(KERN_ERR PFX "Can't load firmware file %s\n", fw_file_name);
++		goto request_firmware_exit;
++	}
++
++	rc = bnx2x_check_firmware(bp);
++	if (rc) {
++		printk(KERN_ERR PFX "Corrupt firmware file %s\n", fw_file_name);
++		goto request_firmware_exit;
++	}
++
++	fw_hdr = (struct bnx2x_fw_file_hdr *)bp->firmware->data;
++
++	/* Initialize the pointers to the init arrays */
++	/* Blob */
++	BNX2X_ALLOC_AND_SET(init_data, request_firmware_exit, be32_to_cpu_n);
++
++	/* Opcodes */
++	BNX2X_ALLOC_AND_SET(init_ops, init_ops_alloc_err, bnx2x_prep_ops);
++
++	/* Offsets */
++	BNX2X_ALLOC_AND_SET(init_ops_offsets, init_offsets_alloc_err, be16_to_cpu_n);
++
++	/* STORMs firmware */
++	bp->tsem_int_table_data = bp->firmware->data +
++		be32_to_cpu(fw_hdr->tsem_int_table_data.offset);
++	bp->tsem_pram_data      = bp->firmware->data +
++		be32_to_cpu(fw_hdr->tsem_pram_data.offset);
++	bp->usem_int_table_data = bp->firmware->data +
++		be32_to_cpu(fw_hdr->usem_int_table_data.offset);
++	bp->usem_pram_data      = bp->firmware->data +
++		be32_to_cpu(fw_hdr->usem_pram_data.offset);
++	bp->xsem_int_table_data = bp->firmware->data +
++		be32_to_cpu(fw_hdr->xsem_int_table_data.offset);
++	bp->xsem_pram_data      = bp->firmware->data +
++		be32_to_cpu(fw_hdr->xsem_pram_data.offset);
++	bp->csem_int_table_data = bp->firmware->data +
++		be32_to_cpu(fw_hdr->csem_int_table_data.offset);
++	bp->csem_pram_data      = bp->firmware->data +
++		be32_to_cpu(fw_hdr->csem_pram_data.offset);
++
++	return 0;
++init_offsets_alloc_err:
++	kfree(bp->init_ops);
++init_ops_alloc_err:
++	kfree(bp->init_data);
++request_firmware_exit:
++	release_firmware(bp->firmware);
++
++	return rc;
++}
++
++
+ 
+ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
+ 				    const struct pci_device_id *ent)
+@@ -11116,6 +11322,13 @@ static int __devinit bnx2x_init_one(stru
+ 	if (rc)
+ 		goto init_one_exit;
+ 
++	/* Set init arrays */
++	rc = bnx2x_init_firmware(bp, &pdev->dev);
++	if (rc) {
++		printk(KERN_ERR PFX "Error loading firmware\n");
++		goto init_one_exit;
++	}
++
+ 	rc = register_netdev(dev);
+ 	if (rc) {
+ 		dev_err(&pdev->dev, "Cannot register net device\n");
+@@ -11163,6 +11376,11 @@ static void __devexit bnx2x_remove_one(s
+ 
+ 	unregister_netdev(dev);
+ 
++	kfree(bp->init_ops_offsets);
++	kfree(bp->init_ops);
++	kfree(bp->init_data);
++	release_firmware(bp->firmware);
++
+ 	if (bp->regview)
+ 		iounmap(bp->regview);
+ 
+@@ -11431,3 +11649,4 @@ static void __exit bnx2x_cleanup(void)
+ module_init(bnx2x_init);
+ module_exit(bnx2x_cleanup);
+ 
++
+diff -urpN linux-2.6-2.6.30~rc6.orig/drivers/net/Kconfig linux-2.6-2.6.30~rc6/drivers/net/Kconfig
+--- linux-2.6-2.6.30~rc6.orig/drivers/net/Kconfig	2009-05-19 03:53:04.000000000 -0600
++++ linux-2.6-2.6.30~rc6/drivers/net/Kconfig	2009-05-26 15:20:01.000000000 -0600
+@@ -2669,6 +2669,7 @@ config BNX2X
+ 	tristate "Broadcom NetXtremeII 10Gb support"
+ 	depends on BROKEN
+ 	depends on PCI
++	select FW_LOADER
+ 	select ZLIB_INFLATE
+ 	select LIBCRC32C
+ 	help

Added: dists/trunk/linux-2.6/debian/patches/features/all/bnx2x-driver-version-1.48.105-1.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/trunk/linux-2.6/debian/patches/features/all/bnx2x-driver-version-1.48.105-1.patch	Wed May 27 17:09:30 2009	(r13688)
@@ -0,0 +1,30 @@
+From cf0ee91376694cdf023b75c41ed1b1c8c4518479 Mon Sep 17 00:00:00 2001
+From: Vladislav Zolotarov <vladz at broadcom.com>
+Date: Mon, 27 Apr 2009 03:28:25 -0700
+Subject: [PATCH 2/2] bnx2x: driver version 1.48.105-1
+
+Signed-off-by: Vladislav Zolotarov <vladz at broadcom.com>
+Signed-off-by: Eilon Greenstein <eilong at broadcom.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/bnx2x_main.c |    4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
+index cdc80e0..a669bb7 100644
+--- a/drivers/net/bnx2x_main.c
++++ b/drivers/net/bnx2x_main.c
+@@ -56,8 +56,8 @@
+ #include "bnx2x_init_ops.h"
+ #include "bnx2x_dump.h"
+ 
+-#define DRV_MODULE_VERSION	"1.48.105"
+-#define DRV_MODULE_RELDATE	"2009/03/02"
++#define DRV_MODULE_VERSION	"1.48.105-1"
++#define DRV_MODULE_RELDATE	"2009/04/22"
+ #define BNX2X_BC_VER		0x040200
+ 
+ #include <linux/firmware.h>
+-- 
+1.6.2.3
+

Modified: dists/trunk/linux-2.6/debian/patches/series/base
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/base	Wed May 27 17:06:03 2009	(r13687)
+++ dists/trunk/linux-2.6/debian/patches/series/base	Wed May 27 17:09:30 2009	(r13688)
@@ -32,3 +32,7 @@
 + features/arm/kirkwood-cpu-idle.patch
 + bugfix/sparc/arch-zimage-target.patch
 + bugfix/all/mvsdio-ignore-high-speed.patch
++ features/all/bnx2x-Separated-FW-from-the-source.patch
++ features/all/bnx2x-driver-version-1.48.105-1.patch
+- debian/dfsg/drivers-net-bnx2x-disable.patch
+



More information about the Kernel-svn-changes mailing list