diff --git a/debian/changelog b/debian/changelog index 5a8d05f32..94dca7928 100644 --- a/debian/changelog +++ b/debian/changelog @@ -57,6 +57,8 @@ linux-2.6 (2.6.25~rc4-1~experimental.1) UNRELEASED; urgency=low - Broadcom NetXtremeII 10Gb support * Disable now broken drivers: - Broadcom NetXtremeII 10Gb support + * Fix broken drivers: + - Broadcom NetXtremeII support * [powerpc] Use new wrapper install support. -- Bastian Blank Tue, 26 Feb 2008 23:59:55 -0700 diff --git a/debian/patches/debian/dfsg/drivers-net-bnx2-request_firmware-1.patch b/debian/patches/debian/dfsg/drivers-net-bnx2-request_firmware-1.patch new file mode 100644 index 000000000..007929b04 --- /dev/null +++ b/debian/patches/debian/dfsg/drivers-net-bnx2-request_firmware-1.patch @@ -0,0 +1,531 @@ +diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c +index 8b552c6..ec72b56 100644 +--- a/drivers/net/bnx2.c ++++ b/drivers/net/bnx2.c +@@ -46,11 +46,10 @@ + #include + #include + #include +-#include ++#include + + #include "bnx2.h" +-#include "bnx2_fw.h" +-#include "bnx2_fw2.h" ++#include "bnx2_fw_file.h" + + #define FW_BUF_SIZE 0x10000 + +@@ -58,12 +57,20 @@ + #define PFX DRV_MODULE_NAME ": " + #define DRV_MODULE_VERSION "1.7.4" + #define DRV_MODULE_RELDATE "February 18, 2008" ++#define FW_FILE_06 "bnx2-06-4.0.5.fw" ++#define FW_FILE_09 "bnx2-09-4.0.5.fw" + + #define RUN_AT(x) (jiffies + (x)) + + /* Time in jiffies before concluding the transmitter is hung. */ + #define TX_TIMEOUT (5*HZ) + ++#ifdef DEBUG ++# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) ++#else ++# define DPRINTK(fmt, args...) ++#endif ++ + static char version[] __devinitdata = + "Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; + +@@ -71,6 +78,8 @@ MODULE_AUTHOR("Michael Chan "); + MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708 Driver"); + MODULE_LICENSE("GPL"); + MODULE_VERSION(DRV_MODULE_VERSION); ++MODULE_FIRMWARE(FW_FILE_06); ++MODULE_FIRMWARE(FW_FILE_09); + + static int disable_msi = 0; + +@@ -3161,26 +3170,32 @@ bnx2_set_rx_mode(struct net_device *dev) + spin_unlock_bh(&bp->phy_lock); + } + +-static void +-load_rv2p_fw(struct bnx2 *bp, __le32 *rv2p_code, u32 rv2p_code_len, +- u32 rv2p_proc) ++static int ++load_rv2p_fw(struct bnx2 *bp, u32 rv2p_proc, const struct bnx2_fw_file_section *fw_section) + { +- int i; ++ int i, len, offset; ++ u32 *data; + u32 val; + ++ len = be32_to_cpu(fw_section->len); ++ offset = be32_to_cpu(fw_section->offset); ++ ++ if (!len || !offset || len + offset > bp->firmware->size) ++ return -EINVAL; ++ DPRINTK("load rv2p firmware with length %u from file offset %u\n", len, offset); ++ ++ data = (u32 *)(bp->firmware->data + offset); + +- for (i = 0; i < rv2p_code_len; i += 8) { +- REG_WR(bp, BNX2_RV2P_INSTR_HIGH, le32_to_cpu(*rv2p_code)); +- rv2p_code++; +- REG_WR(bp, BNX2_RV2P_INSTR_LOW, le32_to_cpu(*rv2p_code)); +- rv2p_code++; ++ for (i = 0; i < (len / 4); i += 2) { ++ REG_WR(bp, BNX2_RV2P_INSTR_HIGH, be32_to_cpu(data[i])); ++ REG_WR(bp, BNX2_RV2P_INSTR_LOW, be32_to_cpu(data[i+1])); + + if (rv2p_proc == RV2P_PROC1) { +- val = (i / 8) | BNX2_RV2P_PROC1_ADDR_CMD_RDWR; ++ val = (i / 2) | BNX2_RV2P_PROC1_ADDR_CMD_RDWR; + REG_WR(bp, BNX2_RV2P_PROC1_ADDR_CMD, val); + } + else { +- val = (i / 8) | BNX2_RV2P_PROC2_ADDR_CMD_RDWR; ++ val = (i / 2) | BNX2_RV2P_PROC2_ADDR_CMD_RDWR; + REG_WR(bp, BNX2_RV2P_PROC2_ADDR_CMD, val); + } + } +@@ -3192,14 +3207,18 @@ load_rv2p_fw(struct bnx2 *bp, __le32 *rv2p_code, u32 rv2p_code_len, + else { + REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET); + } ++ ++ return 0; + } + + static int +-load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw) ++load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, ++ const struct bnx2_fw_file_entry *fw_entry) + { ++ u32 addr, len, file_offset; + u32 offset; + u32 val; +- int rc; ++ u32 *data; + + /* Halt the CPU. */ + val = bnx2_reg_rd_ind(bp, cpu_reg->mode); +@@ -3208,64 +3227,87 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw) + bnx2_reg_wr_ind(bp, cpu_reg->state, cpu_reg->state_value_clear); + + /* Load the Text area. */ +- offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base); +- if (fw->gz_text) { ++ addr = be32_to_cpu(fw_entry->text.addr); ++ len = be32_to_cpu(fw_entry->text.len); ++ file_offset = be32_to_cpu(fw_entry->text.offset); ++ data = (u32 *)(bp->firmware->data + file_offset); ++ DPRINTK("load text section to %x with length %u from file offset %x\n", addr, len, file_offset); ++ ++ offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base); ++ if (len) { + int j; + +- rc = zlib_inflate_blob(fw->text, FW_BUF_SIZE, fw->gz_text, +- fw->gz_text_len); +- if (rc < 0) +- return rc; +- +- for (j = 0; j < (fw->text_len / 4); j++, offset += 4) { +- bnx2_reg_wr_ind(bp, offset, le32_to_cpu(fw->text[j])); ++ for (j = 0; j < (len / 4); j++, offset += 4) { ++ bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j])); + } + } + + /* Load the Data area. */ +- offset = cpu_reg->spad_base + (fw->data_addr - cpu_reg->mips_view_base); +- if (fw->data) { ++ addr = be32_to_cpu(fw_entry->data.addr); ++ len = be32_to_cpu(fw_entry->data.len); ++ file_offset = be32_to_cpu(fw_entry->data.offset); ++ data = (u32 *)(bp->firmware->data + file_offset); ++ DPRINTK("load data section to %x with length %u from file offset %x\n", addr, len, file_offset); ++ ++ offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base); ++ if (len) { + int j; + +- for (j = 0; j < (fw->data_len / 4); j++, offset += 4) { +- bnx2_reg_wr_ind(bp, offset, fw->data[j]); ++ for (j = 0; j < (len / 4); j++, offset += 4) { ++ bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j])); + } + } + + /* Load the SBSS area. */ +- offset = cpu_reg->spad_base + (fw->sbss_addr - cpu_reg->mips_view_base); +- if (fw->sbss_len) { ++ addr = be32_to_cpu(fw_entry->sbss.addr); ++ len = be32_to_cpu(fw_entry->sbss.len); ++ DPRINTK("init sbss section on %x with length %u\n", addr, len); ++ ++ offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base); ++ if (len) { + int j; + +- for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4) { ++ for (j = 0; j < (len / 4); j++, offset += 4) { + bnx2_reg_wr_ind(bp, offset, 0); + } + } + + /* Load the BSS area. */ +- offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base); +- if (fw->bss_len) { ++ addr = be32_to_cpu(fw_entry->bss.addr); ++ len = be32_to_cpu(fw_entry->bss.len); ++ DPRINTK("init bss section on %x with length %u\n", addr, len); ++ ++ offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base); ++ if (len) { + int j; + +- for (j = 0; j < (fw->bss_len/4); j++, offset += 4) { ++ for (j = 0; j < (len / 4); j++, offset += 4) { + bnx2_reg_wr_ind(bp, offset, 0); + } + } + + /* Load the Read-Only area. */ +- offset = cpu_reg->spad_base + +- (fw->rodata_addr - cpu_reg->mips_view_base); +- if (fw->rodata) { ++ addr = be32_to_cpu(fw_entry->rodata.addr); ++ len = be32_to_cpu(fw_entry->rodata.len); ++ file_offset = be32_to_cpu(fw_entry->rodata.offset); ++ data = (u32 *)(bp->firmware->data + file_offset); ++ DPRINTK("load rodata section to %x with length %u from file offset %x\n", addr, len, file_offset); ++ ++ offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base); ++ if (len) { + int j; + +- for (j = 0; j < (fw->rodata_len / 4); j++, offset += 4) { +- bnx2_reg_wr_ind(bp, offset, fw->rodata[j]); ++ for (j = 0; j < (len / 4); j++, offset += 4) { ++ bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j])); + } + } + + /* Clear the pre-fetch instruction. */ + bnx2_reg_wr_ind(bp, cpu_reg->inst, 0); +- bnx2_reg_wr_ind(bp, cpu_reg->pc, fw->start_addr); ++ ++ val = be32_to_cpu(fw_entry->start_addr); ++ DPRINTK("starting cpu on %x\n", val); ++ bnx2_reg_wr_ind(bp, cpu_reg->pc, val); + + /* Start the CPU. */ + val = bnx2_reg_rd_ind(bp, cpu_reg->mode); +@@ -3280,39 +3322,14 @@ static int + bnx2_init_cpus(struct bnx2 *bp) + { + struct cpu_reg cpu_reg; +- struct fw_info *fw; +- int rc, rv2p_len; +- void *text, *rv2p; +- +- /* Initialize the RV2P processor. */ +- text = vmalloc(FW_BUF_SIZE); +- if (!text) +- return -ENOMEM; +- if (CHIP_NUM(bp) == CHIP_NUM_5709) { +- rv2p = bnx2_xi_rv2p_proc1; +- rv2p_len = sizeof(bnx2_xi_rv2p_proc1); +- } else { +- rv2p = bnx2_rv2p_proc1; +- rv2p_len = sizeof(bnx2_rv2p_proc1); +- } +- rc = zlib_inflate_blob(text, FW_BUF_SIZE, rv2p, rv2p_len); +- if (rc < 0) +- goto init_cpu_err; ++ const struct bnx2_fw_file *fw = NULL; ++ int rc; + +- load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC1); ++ fw = (struct bnx2_fw_file *)bp->firmware->data; + +- if (CHIP_NUM(bp) == CHIP_NUM_5709) { +- rv2p = bnx2_xi_rv2p_proc2; +- rv2p_len = sizeof(bnx2_xi_rv2p_proc2); +- } else { +- rv2p = bnx2_rv2p_proc2; +- rv2p_len = sizeof(bnx2_rv2p_proc2); +- } +- rc = zlib_inflate_blob(text, FW_BUF_SIZE, rv2p, rv2p_len); +- if (rc < 0) +- goto init_cpu_err; +- +- load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC2); ++ /* Initialize the RV2P processor. */ ++ load_rv2p_fw(bp, RV2P_PROC1, &fw->rv2p_proc1); ++ load_rv2p_fw(bp, RV2P_PROC2, &fw->rv2p_proc2); + + /* Initialize the RX Processor. */ + cpu_reg.mode = BNX2_RXP_CPU_MODE; +@@ -3328,15 +3345,9 @@ bnx2_init_cpus(struct bnx2 *bp) + cpu_reg.spad_base = BNX2_RXP_SCRATCH; + cpu_reg.mips_view_base = 0x8000000; + +- if (CHIP_NUM(bp) == CHIP_NUM_5709) +- fw = &bnx2_rxp_fw_09; +- else +- fw = &bnx2_rxp_fw_06; +- +- fw->text = text; +- rc = load_cpu_fw(bp, &cpu_reg, fw); ++ rc = load_cpu_fw(bp, &cpu_reg, &fw->rxp); + if (rc) +- goto init_cpu_err; ++ return rc; + + /* Initialize the TX Processor. */ + cpu_reg.mode = BNX2_TXP_CPU_MODE; +@@ -3352,15 +3363,9 @@ bnx2_init_cpus(struct bnx2 *bp) + cpu_reg.spad_base = BNX2_TXP_SCRATCH; + cpu_reg.mips_view_base = 0x8000000; + +- if (CHIP_NUM(bp) == CHIP_NUM_5709) +- fw = &bnx2_txp_fw_09; +- else +- fw = &bnx2_txp_fw_06; +- +- fw->text = text; +- rc = load_cpu_fw(bp, &cpu_reg, fw); ++ rc = load_cpu_fw(bp, &cpu_reg, &fw->txp); + if (rc) +- goto init_cpu_err; ++ return rc; + + /* Initialize the TX Patch-up Processor. */ + cpu_reg.mode = BNX2_TPAT_CPU_MODE; +@@ -3376,15 +3381,9 @@ bnx2_init_cpus(struct bnx2 *bp) + cpu_reg.spad_base = BNX2_TPAT_SCRATCH; + cpu_reg.mips_view_base = 0x8000000; + +- if (CHIP_NUM(bp) == CHIP_NUM_5709) +- fw = &bnx2_tpat_fw_09; +- else +- fw = &bnx2_tpat_fw_06; +- +- fw->text = text; +- rc = load_cpu_fw(bp, &cpu_reg, fw); ++ rc = load_cpu_fw(bp, &cpu_reg, &fw->tpat); + if (rc) +- goto init_cpu_err; ++ return rc; + + /* Initialize the Completion Processor. */ + cpu_reg.mode = BNX2_COM_CPU_MODE; +@@ -3400,15 +3399,9 @@ bnx2_init_cpus(struct bnx2 *bp) + cpu_reg.spad_base = BNX2_COM_SCRATCH; + cpu_reg.mips_view_base = 0x8000000; + +- if (CHIP_NUM(bp) == CHIP_NUM_5709) +- fw = &bnx2_com_fw_09; +- else +- fw = &bnx2_com_fw_06; +- +- fw->text = text; +- rc = load_cpu_fw(bp, &cpu_reg, fw); ++ rc = load_cpu_fw(bp, &cpu_reg, &fw->com); + if (rc) +- goto init_cpu_err; ++ return rc; + + /* Initialize the Command Processor. */ + cpu_reg.mode = BNX2_CP_CPU_MODE; +@@ -3424,17 +3417,7 @@ bnx2_init_cpus(struct bnx2 *bp) + cpu_reg.spad_base = BNX2_CP_SCRATCH; + cpu_reg.mips_view_base = 0x8000000; + +- if (CHIP_NUM(bp) == CHIP_NUM_5709) +- fw = &bnx2_cp_fw_09; +- else +- fw = &bnx2_cp_fw_06; +- +- fw->text = text; +- rc = load_cpu_fw(bp, &cpu_reg, fw); +- +-init_cpu_err: +- vfree(text); +- return rc; ++ return load_cpu_fw(bp, &cpu_reg, &fw->cp); + } + + static int +@@ -7456,6 +7439,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + struct bnx2 *bp; + int rc; + char str[40]; ++ const char *fw_file; + DECLARE_MAC_BUF(mac); + + if (version_printed++ == 0) +@@ -7497,6 +7481,23 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + + pci_set_drvdata(pdev, dev); + ++ if (CHIP_NUM(bp) == CHIP_NUM_5709) ++ fw_file = FW_FILE_09; ++ else ++ fw_file = FW_FILE_06; ++ ++ rc = request_firmware(&bp->firmware, fw_file, &pdev->dev); ++ if (rc) { ++ printk(KERN_ERR PFX "Can't load firmware file %s\n", fw_file); ++ goto error; ++ } ++ ++ if (bp->firmware->size < sizeof(struct bnx2_fw_file)) { ++ printk(KERN_ERR PFX "Firmware file too small\n"); ++ rc = -EINVAL; ++ goto error; ++ } ++ + memcpy(dev->dev_addr, bp->mac_addr, 6); + memcpy(dev->perm_addr, bp->mac_addr, 6); + bp->name = board_info[ent->driver_data].name; +@@ -7514,13 +7515,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + + if ((rc = register_netdev(dev))) { + dev_err(&pdev->dev, "Cannot register net device\n"); +- if (bp->regview) +- iounmap(bp->regview); +- pci_release_regions(pdev); +- pci_disable_device(pdev); +- pci_set_drvdata(pdev, NULL); +- free_netdev(dev); +- return rc; ++ goto error; + } + + printk(KERN_INFO "%s: %s (%c%d) %s found at mem %lx, " +@@ -7534,6 +7529,15 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + bp->pdev->irq, print_mac(mac, dev->dev_addr)); + + return 0; ++ ++error: ++ if (bp->regview) ++ iounmap(bp->regview); ++ pci_release_regions(pdev); ++ pci_disable_device(pdev); ++ pci_set_drvdata(pdev, NULL); ++ free_netdev(dev); ++ return rc; + } + + static void __devexit +@@ -7549,6 +7553,8 @@ bnx2_remove_one(struct pci_dev *pdev) + if (bp->regview) + iounmap(bp->regview); + ++ release_firmware(bp->firmware); ++ + free_netdev(dev); + pci_release_regions(pdev); + pci_disable_device(pdev); +diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h +index 3aa0364..b9a052f 100644 +--- a/drivers/net/bnx2.h ++++ b/drivers/net/bnx2.h +@@ -6812,6 +6812,8 @@ struct bnx2 { + + struct bnx2_irq irq_tbl[BNX2_MAX_MSIX_VEC]; + int irq_nvecs; ++ ++ const struct firmware *firmware; + }; + + #define REG_RD(bp, offset) \ +@@ -6842,44 +6844,6 @@ struct cpu_reg { + u32 mips_view_base; + }; + +-struct fw_info { +- const u32 ver_major; +- const u32 ver_minor; +- const u32 ver_fix; +- +- const u32 start_addr; +- +- /* Text section. */ +- const u32 text_addr; +- const u32 text_len; +- const u32 text_index; +- __le32 *text; +- u8 *gz_text; +- const u32 gz_text_len; +- +- /* Data section. */ +- const u32 data_addr; +- const u32 data_len; +- const u32 data_index; +- const u32 *data; +- +- /* SBSS section. */ +- const u32 sbss_addr; +- const u32 sbss_len; +- const u32 sbss_index; +- +- /* BSS section. */ +- const u32 bss_addr; +- const u32 bss_len; +- const u32 bss_index; +- +- /* Read-only section. */ +- const u32 rodata_addr; +- const u32 rodata_len; +- const u32 rodata_index; +- const u32 *rodata; +-}; +- + #define RV2P_PROC1 0 + #define RV2P_PROC2 1 + +diff --git a/drivers/net/bnx2_fw_file.h b/drivers/net/bnx2_fw_file.h +new file mode 100644 +index 0000000..06c003c +--- /dev/null ++++ b/drivers/net/bnx2_fw_file.h +@@ -0,0 +1,25 @@ ++struct bnx2_fw_file_section { ++ uint32_t addr; ++ uint32_t len; ++ uint32_t offset; ++}; ++ ++struct bnx2_fw_file_entry { ++ uint32_t start_addr; ++ struct bnx2_fw_file_section text; ++ struct bnx2_fw_file_section data; ++ struct bnx2_fw_file_section sbss; ++ struct bnx2_fw_file_section bss; ++ struct bnx2_fw_file_section rodata; ++}; ++ ++struct bnx2_fw_file { ++ struct bnx2_fw_file_entry com; ++ struct bnx2_fw_file_entry cp; ++ struct bnx2_fw_file_entry rxp; ++ struct bnx2_fw_file_entry tpat; ++ struct bnx2_fw_file_entry txp; ++ struct bnx2_fw_file_section rv2p_proc1; ++ struct bnx2_fw_file_section rv2p_proc2; ++}; ++ +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -2327,3 +2327,3 @@ config BNX2 + tristate "Broadcom NetXtremeII support" +- depends on BROKEN ++ select FW_LOADER + depends on PCI diff --git a/debian/patches/series/1~experimental.1 b/debian/patches/series/1~experimental.1 index 7e690bd7b..dd7c42de2 100644 --- a/debian/patches/series/1~experimental.1 +++ b/debian/patches/series/1~experimental.1 @@ -7,6 +7,7 @@ + debian/drivers-ata-ata_piix-postpone-pata.patch + debian/dfsg/drivers-net-tg3-fix-simple.patch ++ debian/dfsg/drivers-net-bnx2-request_firmware-1.patch + features/all/export-gfs2-locking-symbols.patch + features/all/export-unionfs-symbols.patch