[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