diff --git a/debian/changelog b/debian/changelog index c547b4ede..e8f30c693 100644 --- a/debian/changelog +++ b/debian/changelog @@ -50,6 +50,10 @@ linux-2.6 (2.6.30~rc7-1~experimental.1) UNRELEASED; urgency=low * [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 Mon, 30 Mar 2009 14:40:26 +0200 linux-2.6 (2.6.29-5) unstable; urgency=low diff --git a/debian/config/arm/config.footbridge b/debian/config/arm/config.footbridge index efd29fc2d..4d6f8aae6 100644 --- a/debian/config/arm/config.footbridge +++ b/debian/config/arm/config.footbridge @@ -646,6 +646,7 @@ CONFIG_NE2K_PCI=m # 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 diff --git a/debian/config/arm/config.orion5x b/debian/config/arm/config.orion5x index 7cfbd579e..a99f131a4 100644 --- a/debian/config/arm/config.orion5x +++ b/debian/config/arm/config.orion5x @@ -328,6 +328,7 @@ CONFIG_NETDEV_1000=y # 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 diff --git a/debian/config/arm/config.versatile b/debian/config/arm/config.versatile index 72c187b19..4d77c540f 100644 --- a/debian/config/arm/config.versatile +++ b/debian/config/arm/config.versatile @@ -275,6 +275,7 @@ CONFIG_NETDEV_1000=y # 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 diff --git a/debian/config/armel/config.kirkwood b/debian/config/armel/config.kirkwood index 2719012ab..6c7a4000a 100644 --- a/debian/config/armel/config.kirkwood +++ b/debian/config/armel/config.kirkwood @@ -345,6 +345,7 @@ CONFIG_NETDEV_1000=y # 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 diff --git a/debian/config/config b/debian/config/config index a86827645..251f9ed3e 100644 --- a/debian/config/config +++ b/debian/config/config @@ -1269,6 +1269,7 @@ CONFIG_SKY2=m CONFIG_VIA_VELOCITY=m CONFIG_TIGON3=m CONFIG_BNX2=m +CONFIG_BNX2X=m CONFIG_QLA3XXX=m CONFIG_ATL1=m CONFIG_ATL1E=m diff --git a/debian/config/mips/config.r5k-ip32 b/debian/config/mips/config.r5k-ip32 index 376466655..8af3fa65c 100644 --- a/debian/config/mips/config.r5k-ip32 +++ b/debian/config/mips/config.r5k-ip32 @@ -405,6 +405,7 @@ CONFIG_E100=m # 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 diff --git a/debian/config/mipsel/config.r5k-cobalt b/debian/config/mipsel/config.r5k-cobalt index 2d86dbf36..9d69d490d 100644 --- a/debian/config/mipsel/config.r5k-cobalt +++ b/debian/config/mipsel/config.r5k-cobalt @@ -510,6 +510,7 @@ CONFIG_VIA_RHINE=m # 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 diff --git a/debian/patches/features/all/bnx2x-Separated-FW-from-the-source.patch b/debian/patches/features/all/bnx2x-Separated-FW-from-the-source.patch new file mode 100644 index 000000000..c56beeb8b --- /dev/null +++ b/debian/patches/features/all/bnx2x-Separated-FW-from-the-source.patch @@ -0,0 +1,1876 @@ +From 08fa4f9f5ec207b19f950662e247fea584dc21c4 Mon Sep 17 00:00:00 2001 +From: Vladislav Zolotarov +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--.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 +Signed-off-by: Eilon Greenstein +Signed-off-by: David S. Miller +--- + 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 + +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 ++ * Written by: Vladislav Zolotarov ++ * Based on the original idea of John Wright . ++ */ ++ ++#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 + * Written by: Eliezer Tamir ++ * Modified by: Vladislav Zolotarov + */ + + #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 ++ * Written by: Vladislav Zolotarov ++ */ ++#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 ++#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 diff --git a/debian/patches/features/all/bnx2x-driver-version-1.48.105-1.patch b/debian/patches/features/all/bnx2x-driver-version-1.48.105-1.patch new file mode 100644 index 000000000..faf32150e --- /dev/null +++ b/debian/patches/features/all/bnx2x-driver-version-1.48.105-1.patch @@ -0,0 +1,30 @@ +From cf0ee91376694cdf023b75c41ed1b1c8c4518479 Mon Sep 17 00:00:00 2001 +From: Vladislav Zolotarov +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 +Signed-off-by: Eilon Greenstein +Signed-off-by: David S. Miller +--- + 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 +-- +1.6.2.3 + diff --git a/debian/patches/series/base b/debian/patches/series/base index ba8a1323a..bd8d9a1ff 100644 --- a/debian/patches/series/base +++ b/debian/patches/series/base @@ -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 +