All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] bnx2: Use request_firmware()
@ 2009-03-19 22:29 Ben Hutchings
  2009-03-19 23:04 ` Michael Chan
  0 siblings, 1 reply; 20+ messages in thread
From: Ben Hutchings @ 2009-03-19 22:29 UTC (permalink / raw)
  To: David Miller; +Cc: Michael Chan, Bastian Blank, netdev

[-- Attachment #1: Type: text/plain, Size: 16148 bytes --]

Based on a patch for Debian by Bastian Blank <waldi@debian.org>.

This patch contains the code changes for review, but should not be
applied.  The complete patch, which is about 1 MB in size and therefore
too large for the mailing list, is at:
<http://womble.decadent.org.uk/tmp/0001-bnx2-Use-request_firmware.patch>.

Ben.

---
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 45403e6..0769f09 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2206,6 +2206,7 @@ config BNX2
 	tristate "Broadcom NetXtremeII support"
 	depends on PCI
 	select CRC32
+	select FW_LOADER
 	select ZLIB_INFLATE
 	help
 	  This driver supports Broadcom NetXtremeII gigabit Ethernet cards.
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 8466d35..54e9c06 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -46,12 +46,11 @@
 #include <linux/crc32.h>
 #include <linux/prefetch.h>
 #include <linux/cache.h>
-#include <linux/zlib.h>
+#include <linux/firmware.h>
 #include <linux/log2.h>
 
 #include "bnx2.h"
 #include "bnx2_fw.h"
-#include "bnx2_fw2.h"
 
 #define FW_BUF_SIZE		0x10000
 
@@ -59,6 +58,8 @@
 #define PFX DRV_MODULE_NAME	": "
 #define DRV_MODULE_VERSION	"1.9.2"
 #define DRV_MODULE_RELDATE	"Feb 11, 2009"
+#define FW_FILE_06		"bnx2-06-4.6.16.fw"
+#define FW_FILE_09		"bnx2-09-4.6.15.fw"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -72,6 +73,8 @@ MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
 MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/5716 Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_FIRMWARE(FW_FILE_06);
+MODULE_FIRMWARE(FW_FILE_09);
 
 static int disable_msi = 0;
 
@@ -3391,24 +3394,91 @@ 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
+check_fw_section(const struct firmware *fw,
+		 const struct bnx2_fw_file_section *section,
+		 u32 alignment, bool non_empty)
+{
+	u32 offset = be32_to_cpu(section->offset);
+	u32 len = be32_to_cpu(section->len);
+
+	if ((offset == 0 && len != 0) || offset >= fw->size || offset & 3)
+		return -EINVAL;
+	if ((non_empty && len == 0) || len > fw->size - offset ||
+	    len & (alignment - 1))
+		return -EINVAL;
+	return 0;
+}
+
+static int
+check_fw_entry(const struct firmware *fw,
+	       const struct bnx2_fw_file_entry *entry)
+{
+	if (check_fw_section(fw, &entry->text, 4, false) ||
+	    check_fw_section(fw, &entry->data, 4, false) ||
+	    entry->bss.len & 3 ||
+	    entry->sbss.len & 3 ||
+	    check_fw_section(fw, &entry->rodata, 4, false))
+		return -EINVAL;
+	return 0;
+}
+
+static int
+bnx2_request_firmware(struct bnx2 *bp)
 {
+	const struct bnx2_fw_file *fw;
+	const char *fw_file;
+	int rc;
+
+	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, &bp->pdev->dev);
+	if (rc) {
+		printk(KERN_ERR PFX "Can't load firmware file \"%s\"\n",
+		       fw_file);
+		return rc;
+	}
+
+	fw = (const struct bnx2_fw_file *)bp->firmware->data;
+	if (bp->firmware->size < sizeof(*fw) ||
+	    check_fw_entry(bp->firmware, &fw->com) ||
+	    check_fw_entry(bp->firmware, &fw->cp) ||
+	    check_fw_entry(bp->firmware, &fw->rxp) ||
+	    check_fw_entry(bp->firmware, &fw->tpat) ||
+	    check_fw_entry(bp->firmware, &fw->txp) ||
+	    check_fw_section(bp->firmware, &fw->rv2p_proc1, 8, true) ||
+	    check_fw_section(bp->firmware, &fw->rv2p_proc2, 8, true)) {
+		printk(KERN_ERR PFX "Firmware file \"%s\" is invalid\n",
+		       fw_file);
+		release_firmware(bp->firmware);
+		bp->firmware = NULL;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+load_rv2p_fw(struct bnx2 *bp, u32 rv2p_proc,
+	     const struct bnx2_fw_file_section *fw_section)
+{
+	u32 rv2p_code_len, file_offset;
+	__be32 *rv2p_code;
 	int i;
 	u32 val;
 
-	if (rv2p_proc == RV2P_PROC2 && CHIP_NUM(bp) == CHIP_NUM_5709) {
-		val = le32_to_cpu(rv2p_code[XI_RV2P_PROC2_MAX_BD_PAGE_LOC]);
-		val &= ~XI_RV2P_PROC2_BD_PAGE_SIZE_MSK;
-		val |= XI_RV2P_PROC2_BD_PAGE_SIZE;
-		rv2p_code[XI_RV2P_PROC2_MAX_BD_PAGE_LOC] = cpu_to_le32(val);
-	}
+	rv2p_code_len = be32_to_cpu(fw_section->len);
+	file_offset = be32_to_cpu(fw_section->offset);
+
+	rv2p_code = (__be32 *)(bp->firmware->data + file_offset);
 
 	for (i = 0; i < rv2p_code_len; i += 8) {
-		REG_WR(bp, BNX2_RV2P_INSTR_HIGH, le32_to_cpu(*rv2p_code));
+		REG_WR(bp, BNX2_RV2P_INSTR_HIGH, be32_to_cpu(*rv2p_code));
 		rv2p_code++;
-		REG_WR(bp, BNX2_RV2P_INSTR_LOW, le32_to_cpu(*rv2p_code));
+		REG_WR(bp, BNX2_RV2P_INSTR_LOW, be32_to_cpu(*rv2p_code));
 		rv2p_code++;
 
 		if (rv2p_proc == RV2P_PROC1) {
@@ -3428,14 +3498,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, const struct cpu_reg *cpu_reg, struct fw_info *fw)
+load_cpu_fw(struct bnx2 *bp, const struct cpu_reg *cpu_reg,
+	    const struct bnx2_fw_file_entry *fw_entry)
 {
+	u32 addr, len, file_offset;
+	__be32 *data;
 	u32 offset;
 	u32 val;
-	int rc;
 
 	/* Halt the CPU. */
 	val = bnx2_reg_rd_ind(bp, cpu_reg->mode);
@@ -3444,64 +3518,81 @@ load_cpu_fw(struct bnx2 *bp, const 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) {
-		int j;
+	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 = (__be32 *)(bp->firmware->data + file_offset);
 
-		rc = zlib_inflate_blob(fw->text, FW_BUF_SIZE, fw->gz_text,
-				       fw->gz_text_len);
-		if (rc < 0)
-			return rc;
+	offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base);
+	if (len) {
+		int j;
 
-		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 = (__be32 *)(bp->firmware->data + 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);
+
+	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);
+
+	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 = (__be32 *)(bp->firmware->data + 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);
+	bnx2_reg_wr_ind(bp, cpu_reg->pc, val);
 
 	/* Start the CPU. */
 	val = bnx2_reg_rd_ind(bp, cpu_reg->mode);
@@ -3515,95 +3606,38 @@ load_cpu_fw(struct bnx2 *bp, const struct cpu_reg *cpu_reg, struct fw_info *fw)
 static int
 bnx2_init_cpus(struct bnx2 *bp)
 {
-	struct fw_info *fw;
-	int rc, rv2p_len;
-	void *text, *rv2p;
+	const struct bnx2_fw_file *fw =
+		(const struct bnx2_fw_file *)bp->firmware->data;
+	int rc;
 
 	/* 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;
-
-	load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC1);
-
-	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);
+	load_rv2p_fw(bp, RV2P_PROC1, &fw->rv2p_proc1);
+	load_rv2p_fw(bp, RV2P_PROC2, &fw->rv2p_proc2);
 
 	/* Initialize the RX Processor. */
-	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_rxp, fw);
+	rc = load_cpu_fw(bp, &cpu_reg_rxp, &fw->rxp);
 	if (rc)
 		goto init_cpu_err;
 
 	/* Initialize the TX Processor. */
-	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_txp, fw);
+	rc = load_cpu_fw(bp, &cpu_reg_txp, &fw->txp);
 	if (rc)
 		goto init_cpu_err;
 
 	/* Initialize the TX Patch-up Processor. */
-	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_tpat, fw);
+	rc = load_cpu_fw(bp, &cpu_reg_tpat, &fw->tpat);
 	if (rc)
 		goto init_cpu_err;
 
 	/* Initialize the Completion Processor. */
-	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_com, fw);
+	rc = load_cpu_fw(bp, &cpu_reg_com, &fw->com);
 	if (rc)
 		goto init_cpu_err;
 
 	/* Initialize the Command Processor. */
-	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_cp, fw);
+	rc = load_cpu_fw(bp, &cpu_reg_cp, &fw->cp);
 
 init_cpu_err:
-	vfree(text);
 	return rc;
 }
 
@@ -7807,6 +7841,10 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	pci_set_drvdata(pdev, dev);
 
+	rc = bnx2_request_firmware(bp);
+	if (rc)
+		goto error;
+
 	memcpy(dev->dev_addr, bp->mac_addr, 6);
 	memcpy(dev->perm_addr, bp->mac_addr, 6);
 
@@ -7823,13 +7861,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, "
@@ -7843,6 +7875,15 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		bp->pdev->irq, 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
@@ -7855,6 +7896,8 @@ bnx2_remove_one(struct pci_dev *pdev)
 
 	unregister_netdev(dev);
 
+	release_firmware(bp->firmware);
+
 	if (bp->regview)
 		iounmap(bp->regview);
 
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 704cbbc..e630ef3 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -6885,6 +6885,7 @@ struct bnx2 {
 
 	u32			idle_chk_status_idx;
 
+	const struct firmware	*firmware;
 };
 
 #define REG_RD(bp, offset)					\
@@ -6915,42 +6916,29 @@ 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;
+struct bnx2_fw_file_section {
+	__be32 addr;
+	__be32 len;
+	__be32 offset;
+};
+
+struct bnx2_fw_file_entry {
+	__be32 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;
 };
 
 #define RV2P_PROC1                              0
diff --git a/firmware/Makefile b/firmware/Makefile
index aa2e02d..3235d60 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -31,6 +31,7 @@ fw-shipped-$(CONFIG_ADAPTEC_STARFIRE) += adaptec/starfire_rx.bin \
 					 adaptec/starfire_tx.bin
 fw-shipped-$(CONFIG_ATARI_DSP56K) += dsp56k/bootstrap.bin
 fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw
+fw-shipped-$(CONFIG_BNX2) += bnx2-06-4.6.16.fw bnx2-09-4.6.15.fw
 fw-shipped-$(CONFIG_CASSINI) += sun/cassini.bin
 fw-shipped-$(CONFIG_COMPUTONE) += intelliport2.bin
 fw-shipped-$(CONFIG_CHELSIO_T3) += cxgb3/t3b_psram-1.1.0.bin \
diff --git a/firmware/WHENCE b/firmware/WHENCE
index ea4fc2e..f42e6ad 100644
--- a/firmware/WHENCE
+++ b/firmware/WHENCE
@@ -493,3 +493,21 @@ Licence:
 Found in hex form in kernel source.
 
 --------------------------------------------------------------------------
+
+Driver: BNX2 - Broadcom NetXtremeII
+
+File: bnx2-06-4.6.16.fw
+File: bnx2-09-4.6.15.fw
+
+Licence:
+
+ This file contains firmware data derived from proprietary unpublished
+ source code, Copyright (c) 2004, 2005, 2006, 2007 Broadcom Corporation.
+
+ Permission is hereby granted for the distribution of this firmware data
+ in hexadecimal or equivalent format, provided this copyright notice is
+ accompanying it.
+
+Found in hex form in kernel source.
+
+--------------------------------------------------------------------------


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-19 22:29 [PATCH] bnx2: Use request_firmware() Ben Hutchings
@ 2009-03-19 23:04 ` Michael Chan
  2009-03-19 23:25   ` Bastian Blank
  0 siblings, 1 reply; 20+ messages in thread
From: Michael Chan @ 2009-03-19 23:04 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: David Miller, Bastian Blank, netdev


On Thu, 2009-03-19 at 15:29 -0700, Ben Hutchings wrote:
> Based on a patch for Debian by Bastian Blank <waldi@debian.org>.
> 
> This patch contains the code changes for review, but should not be
> applied.  The complete patch, which is about 1 MB in size and therefore
> too large for the mailing list, is at:
> <http://womble.decadent.org.uk/tmp/0001-bnx2-Use-request_firmware.patch>.
> 


Thanks Ben and Bastian.  I will review this and test it out.  I think I
will add some logic to check firmware versions to guarantee some level
of compatibility.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-19 23:04 ` Michael Chan
@ 2009-03-19 23:25   ` Bastian Blank
  2009-03-20 22:50     ` David Miller
  0 siblings, 1 reply; 20+ messages in thread
From: Bastian Blank @ 2009-03-19 23:25 UTC (permalink / raw)
  To: Michael Chan; +Cc: Ben Hutchings, David Miller, netdev

On Thu, Mar 19, 2009 at 04:04:44PM -0700, Michael Chan wrote:
> Thanks Ben and Bastian.  I will review this and test it out.  I think I
> will add some logic to check firmware versions to guarantee some level
> of compatibility.

The firmware version is coded into the filenames.

Bastian

-- 
Violence in reality is quite different from theory.
		-- Spock, "The Cloud Minders", stardate 5818.4

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-19 23:25   ` Bastian Blank
@ 2009-03-20 22:50     ` David Miller
  2009-03-23 21:47       ` Michael Chan
  0 siblings, 1 reply; 20+ messages in thread
From: David Miller @ 2009-03-20 22:50 UTC (permalink / raw)
  To: waldi; +Cc: mchan, ben, davem, netdev

From: Bastian Blank <waldi@debian.org>
Date: Fri, 20 Mar 2009 00:25:41 +0100

> On Thu, Mar 19, 2009 at 04:04:44PM -0700, Michael Chan wrote:
> > Thanks Ben and Bastian.  I will review this and test it out.  I think I
> > will add some logic to check firmware versions to guarantee some level
> > of compatibility.
> 
> The firmware version is coded into the filenames.

Michael and co. please do not make such a big deal about
this.

This patch is perfectly fine as-is.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-20 22:50     ` David Miller
@ 2009-03-23 21:47       ` Michael Chan
  2009-03-23 22:02         ` David Miller
                           ` (2 more replies)
  0 siblings, 3 replies; 20+ messages in thread
From: Michael Chan @ 2009-03-23 21:47 UTC (permalink / raw)
  To: David Miller; +Cc: waldi, ben, davem, netdev


On Fri, 2009-03-20 at 15:50 -0700, David Miller wrote:
> From: Bastian Blank <waldi@debian.org>
> Date: Fri, 20 Mar 2009 00:25:41 +0100
> 
> > On Thu, Mar 19, 2009 at 04:04:44PM -0700, Michael Chan wrote:
> > > Thanks Ben and Bastian.  I will review this and test it out.  I think I
> > > will add some logic to check firmware versions to guarantee some level
> > > of compatibility.
> > 
> > The firmware version is coded into the filenames.
> 
> Michael and co. please do not make such a big deal about
> this.
> 
> This patch is perfectly fine as-is.
> 

Yes, the patch looks good.  I just noticed one problem while reviewing.
The following logic to let the firmware know about the host CPU's page
size is missing and I'll need to add it back.  Otherwise it will only
work on CPUs with 4K page size.

+static int
+load_rv2p_fw(struct bnx2 *bp, u32 rv2p_proc,
+            const struct bnx2_fw_file_section *fw_section)
+{
+       u32 rv2p_code_len, file_offset;
+       __be32 *rv2p_code;
        int i;
        u32 val;
 
-       if (rv2p_proc == RV2P_PROC2 && CHIP_NUM(bp) == CHIP_NUM_5709) {
-               val = le32_to_cpu(rv2p_code[XI_RV2P_PROC2_MAX_BD_PAGE_LOC]);
-               val &= ~XI_RV2P_PROC2_BD_PAGE_SIZE_MSK;
-               val |= XI_RV2P_PROC2_BD_PAGE_SIZE;
-               rv2p_code[XI_RV2P_PROC2_MAX_BD_PAGE_LOC] = cpu_to_le32(val);
-       }
+       rv2p_code_len = be32_to_cpu(fw_section->len);
+       file_offset = be32_to_cpu(fw_section->offset);
+
+       rv2p_code = (__be32 *)(bp->firmware->data + file_offset);


I'd also like to add the version information to the bnx2_fw_file_entry
struct instead of embedding it in the file name.  It is more flexible
this way as each section can have different versions and can be updated
separately.  So it will look something like:

struct bnx2_fw_file_entry {
	__be32 start_addr;
	__be32 version;
	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;
};


I'll generate an incremental patch on top of this one for review.
Thanks.

 



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-23 21:47       ` Michael Chan
@ 2009-03-23 22:02         ` David Miller
  2009-03-23 22:29         ` Bastian Blank
  2009-03-23 22:32         ` Bastian Blank
  2 siblings, 0 replies; 20+ messages in thread
From: David Miller @ 2009-03-23 22:02 UTC (permalink / raw)
  To: mchan; +Cc: waldi, ben, davem, netdev

From: "Michael Chan" <mchan@broadcom.com>
Date: Mon, 23 Mar 2009 14:47:59 -0700

> Yes, the patch looks good.  I just noticed one problem while reviewing.
> The following logic to let the firmware know about the host CPU's page
> size is missing and I'll need to add it back.  Otherwise it will only
> work on CPUs with 4K page size.

Ok.

> I'd also like to add the version information to the bnx2_fw_file_entry
> struct instead of embedding it in the file name.  It is more flexible
> this way as each section can have different versions and can be updated
> separately.  So it will look something like:

Fair enough.

> I'll generate an incremental patch on top of this one for review.

Thanks.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-23 21:47       ` Michael Chan
  2009-03-23 22:02         ` David Miller
@ 2009-03-23 22:29         ` Bastian Blank
  2009-03-23 23:24           ` Michael Chan
  2009-03-23 22:32         ` Bastian Blank
  2 siblings, 1 reply; 20+ messages in thread
From: Bastian Blank @ 2009-03-23 22:29 UTC (permalink / raw)
  To: netdev

On Mon, Mar 23, 2009 at 02:47:59PM -0700, Michael Chan wrote:
> I'd also like to add the version information to the bnx2_fw_file_entry
> struct instead of embedding it in the file name.  It is more flexible
> this way as each section can have different versions and can be updated
> separately.  So it will look something like:
> 
> struct bnx2_fw_file_entry {
> 	__be32 start_addr;
> 	__be32 version;
> 	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;
> };

And how do you want to handle the compatibility? One firmware file have
to work with many kernels, which was always described as impossible.

Bastian

-- 
Women are more easily and more deeply terrified ... generating more
sheer horror than the male of the species.
		-- Spock, "Wolf in the Fold", stardate 3615.4

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-23 21:47       ` Michael Chan
  2009-03-23 22:02         ` David Miller
  2009-03-23 22:29         ` Bastian Blank
@ 2009-03-23 22:32         ` Bastian Blank
  2009-03-23 23:28           ` Michael Chan
  2 siblings, 1 reply; 20+ messages in thread
From: Bastian Blank @ 2009-03-23 22:32 UTC (permalink / raw)
  To: Michael Chan; +Cc: David Miller, ben, davem, netdev

On Mon, Mar 23, 2009 at 02:47:59PM -0700, Michael Chan wrote:
> I'd also like to add the version information to the bnx2_fw_file_entry
> struct instead of embedding it in the file name.  It is more flexible
> this way as each section can have different versions and can be updated
> separately.

Only if the firmwares are compatible enough. Can I pull the firmwares from a
2.6.21 kernel and ask a .29 to use them? One argument was always that
the firmware is coupled with the code.

Bastian

-- 
Worlds are conquered, galaxies destroyed -- but a woman is always a woman.
		-- Kirk, "The Conscience of the King", stardate 2818.9

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-23 22:29         ` Bastian Blank
@ 2009-03-23 23:24           ` Michael Chan
  2009-03-24  0:14             ` Rick Jones
  0 siblings, 1 reply; 20+ messages in thread
From: Michael Chan @ 2009-03-23 23:24 UTC (permalink / raw)
  To: Bastian Blank; +Cc: netdev


On Mon, 2009-03-23 at 15:29 -0700, Bastian Blank wrote:
> On Mon, Mar 23, 2009 at 02:47:59PM -0700, Michael Chan wrote:
> > I'd also like to add the version information to the bnx2_fw_file_entry
> > struct instead of embedding it in the file name.  It is more flexible
> > this way as each section can have different versions and can be updated
> > separately.  So it will look something like:
> > 
> > struct bnx2_fw_file_entry {
> > 	__be32 start_addr;
> > 	__be32 version;
> > 	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;
> > };
> 
> And how do you want to handle the compatibility? One firmware file have
> to work with many kernels, which was always described as impossible.
> 

I see your point.  May be I'll break up each firmware section into a
different file and the file name will be updated with each version.
This will allow different sections to be updated separately and older
kernels will still have access to the older firmware.



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-23 22:32         ` Bastian Blank
@ 2009-03-23 23:28           ` Michael Chan
  2009-04-01 18:01             ` Michael Chan
  0 siblings, 1 reply; 20+ messages in thread
From: Michael Chan @ 2009-03-23 23:28 UTC (permalink / raw)
  To: Bastian Blank; +Cc: David Miller, ben, davem, netdev


On Mon, 2009-03-23 at 15:32 -0700, Bastian Blank wrote:
> On Mon, Mar 23, 2009 at 02:47:59PM -0700, Michael Chan wrote:
> > I'd also like to add the version information to the
> bnx2_fw_file_entry
> > struct instead of embedding it in the file name.  It is more
> flexible
> > this way as each section can have different versions and can be
> updated
> > separately.
> 
> Only if the firmwares are compatible enough. Can I pull the firmwares
> from a
> 2.6.21 kernel and ask a .29 to use them? One argument was always that
> the firmware is coupled with the code.

No, this won't work.  Please see new proposal to breakup firmware into
multiple files.



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-23 23:24           ` Michael Chan
@ 2009-03-24  0:14             ` Rick Jones
  2009-03-24  1:11               ` Michael Chan
  0 siblings, 1 reply; 20+ messages in thread
From: Rick Jones @ 2009-03-24  0:14 UTC (permalink / raw)
  To: Michael Chan; +Cc: Bastian Blank, netdev

Michael Chan wrote:
> May be I'll break up each firmware section into a
> different file and the file name will be updated with each version.
> This will allow different sections to be updated separately and older
> kernels will still have access to the older firmware.

Is that really necessary?  It is enough "fun" finding just the one firmware file 
as it is.

rick jones

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-24  0:14             ` Rick Jones
@ 2009-03-24  1:11               ` Michael Chan
  2009-03-24  1:26                 ` Rick Jones
  2009-03-24  7:42                 ` Bastian Blank
  0 siblings, 2 replies; 20+ messages in thread
From: Michael Chan @ 2009-03-24  1:11 UTC (permalink / raw)
  To: Rick Jones; +Cc: Bastian Blank, netdev


On Mon, 2009-03-23 at 17:14 -0700, Rick Jones wrote:
> Michael Chan wrote:
> > May be I'll break up each firmware section into a
> > different file and the file name will be updated with each version.
> > This will allow different sections to be updated separately and older
> > kernels will still have access to the older firmware.
> 
> Is that really necessary?  It is enough "fun" finding just the one firmware file 
> as it is.

If all the firmware sections are in the same file, much of the firmware
file will be duplicated in a new file when we update just one section.



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-24  1:11               ` Michael Chan
@ 2009-03-24  1:26                 ` Rick Jones
  2009-03-24  1:44                   ` Michael Chan
  2009-03-24  4:27                   ` Ben Hutchings
  2009-03-24  7:42                 ` Bastian Blank
  1 sibling, 2 replies; 20+ messages in thread
From: Rick Jones @ 2009-03-24  1:26 UTC (permalink / raw)
  To: Michael Chan; +Cc: Bastian Blank, netdev

Michael Chan wrote:
> On Mon, 2009-03-23 at 17:14 -0700, Rick Jones wrote:
> 
>>Michael Chan wrote:
>>
>>>May be I'll break up each firmware section into a
>>>different file and the file name will be updated with each version.
>>>This will allow different sections to be updated separately and older
>>>kernels will still have access to the older firmware.
>>
>>Is that really necessary?  It is enough "fun" finding just the one firmware file 
>>as it is.
> 
> 
> If all the firmware sections are in the same file, much of the firmware
> file will be duplicated in a new file when we update just one section.

So?  Perhaps I'm just experiencing distro pain which may not continue to exist or 
which may not matter to netdev, but when one is installing to a system that uses 
a core NIC which has firmware cast-out into "non-free" siberia, life is "fun" 
enough making sure one has the one firmware file let alone N of them.  If I now 
have to make sure I have all N firmware files, and they are to be updated 
separately, either that means I have to find N packages, or the distros are going 
to package them into one "uber" package that might as well be a single firmware 
file anyway.

rick jones


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-24  1:26                 ` Rick Jones
@ 2009-03-24  1:44                   ` Michael Chan
  2009-03-24  4:27                   ` Ben Hutchings
  1 sibling, 0 replies; 20+ messages in thread
From: Michael Chan @ 2009-03-24  1:44 UTC (permalink / raw)
  To: Rick Jones; +Cc: Bastian Blank, netdev


On Mon, 2009-03-23 at 18:26 -0700, Rick Jones wrote:
> Michael Chan wrote:
> > On Mon, 2009-03-23 at 17:14 -0700, Rick Jones wrote:
> > 
> >>Michael Chan wrote:
> >>
> >>>May be I'll break up each firmware section into a
> >>>different file and the file name will be updated with each version.
> >>>This will allow different sections to be updated separately and older
> >>>kernels will still have access to the older firmware.
> >>
> >>Is that really necessary?  It is enough "fun" finding just the one firmware file 
> >>as it is.
> > 
> > 
> > If all the firmware sections are in the same file, much of the firmware
> > file will be duplicated in a new file when we update just one section.
> 
> So?  Perhaps I'm just experiencing distro pain which may not continue to exist or 
> which may not matter to netdev, but when one is installing to a system that uses 
> a core NIC which has firmware cast-out into "non-free" siberia, life is "fun" 
> enough making sure one has the one firmware file let alone N of them.  If I now 
> have to make sure I have all N firmware files, and they are to be updated 
> separately, either that means I have to find N packages, or the distros are going 
> to package them into one "uber" package that might as well be a single firmware 
> file anyway.
> 

I think we can assume that distros will package firmware files (make
firmware_install) properly and not require users to install these
firmware files on their own.



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-24  1:26                 ` Rick Jones
  2009-03-24  1:44                   ` Michael Chan
@ 2009-03-24  4:27                   ` Ben Hutchings
  1 sibling, 0 replies; 20+ messages in thread
From: Ben Hutchings @ 2009-03-24  4:27 UTC (permalink / raw)
  To: Rick Jones; +Cc: Michael Chan, Bastian Blank, netdev

[-- Attachment #1: Type: text/plain, Size: 1436 bytes --]

On Mon, 2009-03-23 at 18:26 -0700, Rick Jones wrote:
> Michael Chan wrote:
> > On Mon, 2009-03-23 at 17:14 -0700, Rick Jones wrote:
> > 
> >>Michael Chan wrote:
> >>
> >>>May be I'll break up each firmware section into a
> >>>different file and the file name will be updated with each version.
> >>>This will allow different sections to be updated separately and older
> >>>kernels will still have access to the older firmware.
> >>
> >>Is that really necessary?  It is enough "fun" finding just the one firmware file 
> >>as it is.
> > 
> > 
> > If all the firmware sections are in the same file, much of the firmware
> > file will be duplicated in a new file when we update just one section.
> 
> So?  Perhaps I'm just experiencing distro pain which may not continue to exist or 
> which may not matter to netdev, but when one is installing to a system that uses 
> a core NIC which has firmware cast-out into "non-free" siberia, life is "fun" 
> enough making sure one has the one firmware file let alone N of them.
[...]

If you're referring to Debian, that is exactly what Bastian and I are
working on.  Sourceless firmware is considered non-free, but it can
still be packaged, as the bnx2 firmware already has been.  We've also
had some discussions with David Woodhouse about semi-automatically
packaging all of the firmware that's now in the firmware subdirectory
and is clearly licensed.

Ben.


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-24  1:11               ` Michael Chan
  2009-03-24  1:26                 ` Rick Jones
@ 2009-03-24  7:42                 ` Bastian Blank
  2009-03-24 15:27                   ` Michael Chan
  1 sibling, 1 reply; 20+ messages in thread
From: Bastian Blank @ 2009-03-24  7:42 UTC (permalink / raw)
  To: Michael Chan; +Cc: Rick Jones, netdev

On Mon, Mar 23, 2009 at 06:11:25PM -0700, Michael Chan wrote:
> On Mon, 2009-03-23 at 17:14 -0700, Rick Jones wrote:
> > Michael Chan wrote:
> > > May be I'll break up each firmware section into a
> > > different file and the file name will be updated with each version.
> > > This will allow different sections to be updated separately and older
> > > kernels will still have access to the older firmware.
> > Is that really necessary?  It is enough "fun" finding just the one firmware file 
> > as it is.
> If all the firmware sections are in the same file, much of the firmware
> file will be duplicated in a new file when we update just one section.

What is the advantage of this? I always saw updates to more than one
firmware at once in the past. The question is not: is it possible, but:
it is necessary.

Bastian

-- 
Our way is peace.
		-- Septimus, the Son Worshiper, "Bread and Circuses",
		   stardate 4040.7.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-24  7:42                 ` Bastian Blank
@ 2009-03-24 15:27                   ` Michael Chan
  0 siblings, 0 replies; 20+ messages in thread
From: Michael Chan @ 2009-03-24 15:27 UTC (permalink / raw)
  To: 'Bastian Blank'; +Cc: Rick Jones, netdev

Bastian Blank wrote:

> What is the advantage of this? I always saw updates to more than one
> firmware at once in the past. The question is not: is it
> possible, but:
> it is necessary.
>

Looking at the git history, about 3 out of 7 times, bnx2_fw.h was
partially updated.  About 2 out of 8 times bnx2_fw2.h was partially
updated.  The next planned update for net-next is a partial update.

Either way will work.  Using separate files will reduce the amount
of patch churn during partial updates.  That's the advantage.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-03-23 23:28           ` Michael Chan
@ 2009-04-01 18:01             ` Michael Chan
  2009-04-02  8:05               ` David Miller
  0 siblings, 1 reply; 20+ messages in thread
From: Michael Chan @ 2009-04-01 18:01 UTC (permalink / raw)
  To: Bastian Blank; +Cc: David Miller, ben, davem, netdev

I've made some minor changes to Bastian and Ben's patch.  I've separated
the mips firmware from the non-mips firmware, added code to fix up the
non-mips firmware with the host CPU's page size, and other minor
changes.  If there are no issues, I'll send the entire patch with the
ihex files when net-next opens up.

Thanks again to Bastian and Ben.  Here's the new patch that excludes the
firmware ihex files for review.

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index ad446db..fed551b 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -46,19 +46,20 @@
 #include <linux/crc32.h>
 #include <linux/prefetch.h>
 #include <linux/cache.h>
-#include <linux/zlib.h>
+#include <linux/firmware.h>
 #include <linux/log2.h>
 
 #include "bnx2.h"
 #include "bnx2_fw.h"
-#include "bnx2_fw2.h"
-
-#define FW_BUF_SIZE		0x10000
 
 #define DRV_MODULE_NAME		"bnx2"
 #define PFX DRV_MODULE_NAME	": "
 #define DRV_MODULE_VERSION	"1.9.3"
 #define DRV_MODULE_RELDATE	"March 17, 2009"
+#define FW_MIPS_FILE_06		"bnx2-mips-06-4.6.16.fw"
+#define FW_RV2P_FILE_06		"bnx2-rv2p-06-4.6.16.fw"
+#define FW_MIPS_FILE_09		"bnx2-mips-09-4.6.15.fw"
+#define FW_RV2P_FILE_09		"bnx2-rv2p-09-4.6.15.fw"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -72,6 +73,10 @@ MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
 MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/5716 Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_FIRMWARE(FW_MIPS_FILE_06);
+MODULE_FIRMWARE(FW_RV2P_FILE_06);
+MODULE_FIRMWARE(FW_MIPS_FILE_09);
+MODULE_FIRMWARE(FW_RV2P_FILE_09);
 
 static int disable_msi = 0;
 
@@ -3391,33 +3396,143 @@ 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 __devinit
+check_fw_section(const struct firmware *fw,
+		 const struct bnx2_fw_file_section *section,
+		 u32 alignment, bool non_empty)
+{
+	u32 offset = be32_to_cpu(section->offset);
+	u32 len = be32_to_cpu(section->len);
+
+	if ((offset == 0 && len != 0) || offset >= fw->size || offset & 3)
+		return -EINVAL;
+	if ((non_empty && len == 0) || len > fw->size - offset ||
+	    len & (alignment - 1))
+		return -EINVAL;
+	return 0;
+}
+
+static int __devinit
+check_mips_fw_entry(const struct firmware *fw,
+		    const struct bnx2_mips_fw_file_entry *entry)
+{
+	if (check_fw_section(fw, &entry->text, 4, true) ||
+	    check_fw_section(fw, &entry->data, 4, false) ||
+	    check_fw_section(fw, &entry->rodata, 4, false))
+		return -EINVAL;
+	return 0;
+}
+
+static int __devinit
+bnx2_request_firmware(struct bnx2 *bp)
 {
+	const char *mips_fw_file, *rv2p_fw_file;
+	const struct bnx2_mips_fw_file *mips;
+	const struct bnx2_rv2p_fw_file *rv2p;
+	int rc;
+
+	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+		mips_fw_file = FW_MIPS_FILE_09;
+		rv2p_fw_file = FW_RV2P_FILE_09;
+	} else {
+		mips_fw_file = FW_MIPS_FILE_06;
+		rv2p_fw_file = FW_RV2P_FILE_06;
+	}
+
+	rc = request_firmware(&bp->mips_firmware, mips_fw_file, &bp->pdev->dev);
+	if (rc) {
+		printk(KERN_ERR PFX "Can't load firmware file \"%s\"\n",
+		       mips_fw_file);
+		return rc;
+	}
+
+	rc = request_firmware(&bp->rv2p_firmware, rv2p_fw_file, &bp->pdev->dev);
+	if (rc) {
+		printk(KERN_ERR PFX "Can't load firmware file \"%s\"\n",
+		       rv2p_fw_file);
+		return rc;
+	}
+	mips = (const struct bnx2_mips_fw_file *) bp->mips_firmware->data;
+	rv2p = (const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data;
+	if (bp->mips_firmware->size < sizeof(*mips) ||
+	    check_mips_fw_entry(bp->mips_firmware, &mips->com) ||
+	    check_mips_fw_entry(bp->mips_firmware, &mips->cp) ||
+	    check_mips_fw_entry(bp->mips_firmware, &mips->rxp) ||
+	    check_mips_fw_entry(bp->mips_firmware, &mips->tpat) ||
+	    check_mips_fw_entry(bp->mips_firmware, &mips->txp)) {
+		printk(KERN_ERR PFX "Firmware file \"%s\" is invalid\n",
+		       mips_fw_file);
+		return -EINVAL;
+	}
+	if (bp->rv2p_firmware->size < sizeof(*rv2p) ||
+	    check_fw_section(bp->rv2p_firmware, &rv2p->proc1.rv2p, 8, true) ||
+	    check_fw_section(bp->rv2p_firmware, &rv2p->proc2.rv2p, 8, true)) {
+		printk(KERN_ERR PFX "Firmware file \"%s\" is invalid\n",
+		       rv2p_fw_file);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static u32
+rv2p_fw_fixup(u32 rv2p_proc, int idx, u32 loc, u32 rv2p_code)
+{
+	switch (idx) {
+	case RV2P_P1_FIXUP_PAGE_SIZE_IDX:
+		rv2p_code &= ~RV2P_BD_PAGE_SIZE_MSK;
+		rv2p_code |= RV2P_BD_PAGE_SIZE;
+		break;
+	}
+	return rv2p_code;
+}
+
+static int
+load_rv2p_fw(struct bnx2 *bp, u32 rv2p_proc,
+	     const struct bnx2_rv2p_fw_file_entry *fw_entry)
+{
+	u32 rv2p_code_len, file_offset;
+	__be32 *rv2p_code;
 	int i;
-	u32 val;
+	u32 val, cmd, addr;
+
+	rv2p_code_len = be32_to_cpu(fw_entry->rv2p.len);
+	file_offset = be32_to_cpu(fw_entry->rv2p.offset);
+
+	rv2p_code = (__be32 *)(bp->rv2p_firmware->data + file_offset);
 
-	if (rv2p_proc == RV2P_PROC2 && CHIP_NUM(bp) == CHIP_NUM_5709) {
-		val = le32_to_cpu(rv2p_code[XI_RV2P_PROC2_MAX_BD_PAGE_LOC]);
-		val &= ~XI_RV2P_PROC2_BD_PAGE_SIZE_MSK;
-		val |= XI_RV2P_PROC2_BD_PAGE_SIZE;
-		rv2p_code[XI_RV2P_PROC2_MAX_BD_PAGE_LOC] = cpu_to_le32(val);
+	if (rv2p_proc == RV2P_PROC1) {
+		cmd = BNX2_RV2P_PROC1_ADDR_CMD_RDWR;
+		addr = BNX2_RV2P_PROC1_ADDR_CMD;
+	} else {
+		cmd = BNX2_RV2P_PROC2_ADDR_CMD_RDWR;
+		addr = BNX2_RV2P_PROC2_ADDR_CMD;
 	}
 
 	for (i = 0; i < rv2p_code_len; i += 8) {
-		REG_WR(bp, BNX2_RV2P_INSTR_HIGH, le32_to_cpu(*rv2p_code));
+		REG_WR(bp, BNX2_RV2P_INSTR_HIGH, be32_to_cpu(*rv2p_code));
 		rv2p_code++;
-		REG_WR(bp, BNX2_RV2P_INSTR_LOW, le32_to_cpu(*rv2p_code));
+		REG_WR(bp, BNX2_RV2P_INSTR_LOW, be32_to_cpu(*rv2p_code));
 		rv2p_code++;
 
-		if (rv2p_proc == RV2P_PROC1) {
-			val = (i / 8) | 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;
-			REG_WR(bp, BNX2_RV2P_PROC2_ADDR_CMD, val);
+		val = (i / 8) | cmd;
+		REG_WR(bp, addr, val);
+	}
+
+	rv2p_code = (__be32 *)(bp->rv2p_firmware->data + file_offset);
+	for (i = 0; i < 8; i++) {
+		u32 loc, code;
+
+		loc = be32_to_cpu(fw_entry->fixup[i]);
+		if (loc && ((loc * 4) < rv2p_code_len)) {
+			code = be32_to_cpu(*(rv2p_code + loc - 1));
+			REG_WR(bp, BNX2_RV2P_INSTR_HIGH, code);
+			code = be32_to_cpu(*(rv2p_code + loc));
+			code = rv2p_fw_fixup(rv2p_proc, i, loc, code);
+			REG_WR(bp, BNX2_RV2P_INSTR_LOW, code);
+
+			val = (loc / 2) | cmd;
+			REG_WR(bp, addr, val);
 		}
 	}
 
@@ -3428,14 +3543,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, const struct cpu_reg *cpu_reg, struct fw_info *fw)
+load_cpu_fw(struct bnx2 *bp, const struct cpu_reg *cpu_reg,
+	    const struct bnx2_mips_fw_file_entry *fw_entry)
 {
+	u32 addr, len, file_offset;
+	__be32 *data;
 	u32 offset;
 	u32 val;
-	int rc;
 
 	/* Halt the CPU. */
 	val = bnx2_reg_rd_ind(bp, cpu_reg->mode);
@@ -3444,64 +3563,52 @@ load_cpu_fw(struct bnx2 *bp, const 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) {
-		int j;
-
-		rc = zlib_inflate_blob(fw->text, FW_BUF_SIZE, fw->gz_text,
-				       fw->gz_text_len);
-		if (rc < 0)
-			return rc;
+	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 = (__be32 *)(bp->mips_firmware->data + file_offset);
 
-		for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
-			bnx2_reg_wr_ind(bp, offset, le32_to_cpu(fw->text[j]));
-	        }
-	}
-
-	/* Load the Data area. */
-	offset = cpu_reg->spad_base + (fw->data_addr - cpu_reg->mips_view_base);
-	if (fw->data) {
+	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) {
-		int j;
-
-		for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4) {
-			bnx2_reg_wr_ind(bp, offset, 0);
-		}
-	}
+	/* Load the Data area. */
+	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 = (__be32 *)(bp->mips_firmware->data + file_offset);
 
-	/* Load the BSS area. */
-	offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base);
-	if (fw->bss_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) {
-			bnx2_reg_wr_ind(bp, offset, 0);
-		}
+		for (j = 0; j < (len / 4); j++, offset += 4)
+			bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j]));
 	}
 
 	/* 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 = (__be32 *)(bp->mips_firmware->data + 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);
+	bnx2_reg_wr_ind(bp, cpu_reg->pc, val);
 
 	/* Start the CPU. */
 	val = bnx2_reg_rd_ind(bp, cpu_reg->mode);
@@ -3515,95 +3622,40 @@ load_cpu_fw(struct bnx2 *bp, const struct cpu_reg *cpu_reg, struct fw_info *fw)
 static int
 bnx2_init_cpus(struct bnx2 *bp)
 {
-	struct fw_info *fw;
-	int rc, rv2p_len;
-	void *text, *rv2p;
+	const struct bnx2_mips_fw_file *mips_fw =
+		(const struct bnx2_mips_fw_file *) bp->mips_firmware->data;
+	const struct bnx2_rv2p_fw_file *rv2p_fw =
+		(const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data;
+	int rc;
 
 	/* 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;
-
-	load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC1);
-
-	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);
+	load_rv2p_fw(bp, RV2P_PROC1, &rv2p_fw->proc1);
+	load_rv2p_fw(bp, RV2P_PROC2, &rv2p_fw->proc2);
 
 	/* Initialize the RX Processor. */
-	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_rxp, fw);
+	rc = load_cpu_fw(bp, &cpu_reg_rxp, &mips_fw->rxp);
 	if (rc)
 		goto init_cpu_err;
 
 	/* Initialize the TX Processor. */
-	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_txp, fw);
+	rc = load_cpu_fw(bp, &cpu_reg_txp, &mips_fw->txp);
 	if (rc)
 		goto init_cpu_err;
 
 	/* Initialize the TX Patch-up Processor. */
-	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_tpat, fw);
+	rc = load_cpu_fw(bp, &cpu_reg_tpat, &mips_fw->tpat);
 	if (rc)
 		goto init_cpu_err;
 
 	/* Initialize the Completion Processor. */
-	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_com, fw);
+	rc = load_cpu_fw(bp, &cpu_reg_com, &mips_fw->com);
 	if (rc)
 		goto init_cpu_err;
 
 	/* Initialize the Command Processor. */
-	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_cp, fw);
+	rc = load_cpu_fw(bp, &cpu_reg_cp, &mips_fw->cp);
 
 init_cpu_err:
-	vfree(text);
 	return rc;
 }
 
@@ -7807,6 +7859,10 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	pci_set_drvdata(pdev, dev);
 
+	rc = bnx2_request_firmware(bp);
+	if (rc)
+		goto error;
+
 	memcpy(dev->dev_addr, bp->mac_addr, 6);
 	memcpy(dev->perm_addr, bp->mac_addr, 6);
 
@@ -7823,13 +7879,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, "
@@ -7843,6 +7893,20 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		bp->pdev->irq, dev->dev_addr);
 
 	return 0;
+
+error:
+	if (bp->mips_firmware)
+		release_firmware(bp->mips_firmware);
+	if (bp->rv2p_firmware)
+		release_firmware(bp->rv2p_firmware);
+
+	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
@@ -7855,6 +7919,11 @@ bnx2_remove_one(struct pci_dev *pdev)
 
 	unregister_netdev(dev);
 
+	if (bp->mips_firmware)
+		release_firmware(bp->mips_firmware);
+	if (bp->rv2p_firmware)
+		release_firmware(bp->rv2p_firmware);
+
 	if (bp->regview)
 		iounmap(bp->regview);
 
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 704cbbc..5b570e1 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -6885,6 +6885,8 @@ struct bnx2 {
 
 	u32			idle_chk_status_idx;
 
+	const struct firmware	*mips_firmware;
+	const struct firmware	*rv2p_firmware;
 };
 
 #define REG_RD(bp, offset)					\
@@ -6915,44 +6917,41 @@ 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;
+struct bnx2_fw_file_section {
+	__be32 addr;
+	__be32 len;
+	__be32 offset;
 };
 
+struct bnx2_mips_fw_file_entry {
+	__be32 start_addr;
+	struct bnx2_fw_file_section text;
+	struct bnx2_fw_file_section data;
+	struct bnx2_fw_file_section rodata;
+};
+
+struct bnx2_rv2p_fw_file_entry {
+	struct bnx2_fw_file_section rv2p;
+	__be32 fixup[8];
+};
+
+struct bnx2_mips_fw_file {
+	struct bnx2_mips_fw_file_entry com;
+	struct bnx2_mips_fw_file_entry cp;
+	struct bnx2_mips_fw_file_entry rxp;
+	struct bnx2_mips_fw_file_entry tpat;
+	struct bnx2_mips_fw_file_entry txp;
+};
+
+struct bnx2_rv2p_fw_file {
+	struct bnx2_rv2p_fw_file_entry proc1;
+	struct bnx2_rv2p_fw_file_entry proc2;
+};
+
+#define RV2P_P1_FIXUP_PAGE_SIZE_IDX		0
+#define RV2P_BD_PAGE_SIZE_MSK			0xffff
+#define RV2P_BD_PAGE_SIZE			((BCM_PAGE_SIZE / 16) - 1)
+
 #define RV2P_PROC1                              0
 #define RV2P_PROC2                              1
 




^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
  2009-04-01 18:01             ` Michael Chan
@ 2009-04-02  8:05               ` David Miller
  0 siblings, 0 replies; 20+ messages in thread
From: David Miller @ 2009-04-02  8:05 UTC (permalink / raw)
  To: mchan; +Cc: waldi, ben, davem, netdev

From: "Michael Chan" <mchan@broadcom.com>
Date: Wed, 01 Apr 2009 11:01:45 -0700

> I've made some minor changes to Bastian and Ben's patch.  I've separated
> the mips firmware from the non-mips firmware, added code to fix up the
> non-mips firmware with the host CPU's page size, and other minor
> changes.  If there are no issues, I'll send the entire patch with the
> ihex files when net-next opens up.
> 
> Thanks again to Bastian and Ben.  Here's the new patch that excludes the
> firmware ihex files for review.

I think I'm even willing to apply this for 2.6.30, let me know when
the final version is ready.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] bnx2: Use request_firmware()
       [not found] <1238778120-8132-1-git-send-email-mchan@broadcom.com>
@ 2009-04-04 23:51 ` David Miller
  0 siblings, 0 replies; 20+ messages in thread
From: David Miller @ 2009-04-04 23:51 UTC (permalink / raw)
  To: mchan; +Cc: netdev

From: "Michael Chan" <mchan@broadcom.com>
Date: Fri,  3 Apr 2009 09:02:00 -0800

> Based on original patch by Ben Hutchings <ben@decadent.org.uk> and
> Bastian Blank <waldi@debian.org>, with the following main changes:
> 
> Separated the mips firmware and rv2p firmware into different files
> to make it easier to update them separately.
> 
> Added some code to fixup the rv2p code with run-time information
> such as PAGE_SIZE.
> 
> Update version to 2.0.0.
> 
> Signed-off-by: Michael Chan <mchan@broadcom.com>

Applied, thanks Michael.

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2009-04-04 23:51 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-19 22:29 [PATCH] bnx2: Use request_firmware() Ben Hutchings
2009-03-19 23:04 ` Michael Chan
2009-03-19 23:25   ` Bastian Blank
2009-03-20 22:50     ` David Miller
2009-03-23 21:47       ` Michael Chan
2009-03-23 22:02         ` David Miller
2009-03-23 22:29         ` Bastian Blank
2009-03-23 23:24           ` Michael Chan
2009-03-24  0:14             ` Rick Jones
2009-03-24  1:11               ` Michael Chan
2009-03-24  1:26                 ` Rick Jones
2009-03-24  1:44                   ` Michael Chan
2009-03-24  4:27                   ` Ben Hutchings
2009-03-24  7:42                 ` Bastian Blank
2009-03-24 15:27                   ` Michael Chan
2009-03-23 22:32         ` Bastian Blank
2009-03-23 23:28           ` Michael Chan
2009-04-01 18:01             ` Michael Chan
2009-04-02  8:05               ` David Miller
     [not found] <1238778120-8132-1-git-send-email-mchan@broadcom.com>
2009-04-04 23:51 ` David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.