Skip to contentSkip to conversation

bnx2 dirver's firmware images

DISCUSSION Denys Vlasenko 8 participants 32 messages Sep 18, 2007 – Sep 21, 2007

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

Hi Michael,

In bnx2_fw.h I see the following:

static u32 bnx2_RXP_b06FwBss[(0x13dc/4) + 1] = { 0x0 };

static struct fw_info bnx2_rxp_fw_06 = {
...
.bss = bnx2_RXP_b06FwBss,
...
};

I grepped for the usage of .bss member (grepped for '[.>]bss[^_]') and it is used only here:

        if (fw->bss) {
                int j;

                for (j = 0; j < (fw->bss_len/4); j++, offset += 4) {
                        REG_WR_IND(bp, offset, fw->bss[j]);
                }
        }

If I understand it correctly, you read zero words one by one from bnx2_RXP_b06FwBss and writing them into the card. This is very suboptimal usage of nearly 5k of kernel unswappable memory.

Do you plan to fix it?

Do you have any plans to switch to request_firmware() interface, which will allow you to avoid keeping firmware in unswappable kernel memory and thus free ~80k?

$ size bnx2.o
   text    data     bss     dec     hex filename
  52255   81551    6360  140166   22386 bnx2.o
--
vda
#1 lore raw
Quoted 23 lines · Denys Vlasenko

Hi Michael,

In bnx2_fw.h I see the following:

static u32 bnx2_RXP_b06FwBss[(0x13dc/4) + 1] = { 0x0 };

static struct fw_info bnx2_rxp_fw_06 = {
...
.bss = bnx2_RXP_b06FwBss,
...
};

I grepped for the usage of .bss member (grepped for '[.>]bss[^_]') and it is used only here:

        if (fw->bss) {
                int j;

                for (j = 0; j < (fw->bss_len/4); j++, offset += 4) {
                        REG_WR_IND(bp, offset, fw->bss[j]);
                }
        }
Quoted 5 lines

If I understand it correctly, you read zero words one by one from bnx2_RXP_b06FwBss and writing them into the card. This is very suboptimal usage of nearly 5k of kernel unswappable memory.

Do you plan to fix it?

We can compress all the different sections of the firmware. Currently, we only compress the biggest chunks and the rest are uncompressed. These zeros should compress to almost nothing. But I agree that the firmware is still big.

Quoted 4 lines

Do you have any plans to switch to request_firmware() interface, which will allow you to avoid keeping firmware in unswappable kernel memory and thus free ~80k?

Matching the correct version of the firmware with the driver is the main issue.

David, what's your opinion on this?

Quoted 7 lines
$ size bnx2.o
   text    data     bss     dec     hex filename
  52255   81551    6360  140166   22386 bnx2.o
--
vda
#2 lore raw
Quoted 5 lines · Michael Chan

We can compress all the different sections of the firmware. Currently, we only compress the biggest chunks and the rest are uncompressed.

These zeros should compress to almost nothing. But I agree that the firmware is still big.

You don't need to store and fetch zeros at all. You *know* that they are zeros, right? So do this:

- REG_WR_IND(bp, offset, fw->bss[j]);
+ REG_WR_IND(bp, offset, 0);

--
vda

#3 lore raw

Review

Quoted 13 lines · Denys Vlasenko
Quoted 5 lines · Michael Chan

We can compress all the different sections of the firmware. Currently, we only compress the biggest chunks and the rest are uncompressed.

These zeros should compress to almost nothing. But I agree that the firmware is still big.

You don't need to store and fetch zeros at all. You *know* that they are zeros, right? So do this:

(quoted diff) +1 -1
-                         REG_WR_IND(bp, offset, fw->bss[j]);
+                         REG_WR_IND(bp, offset, 0);

Good point. We can do that. Looking at the file, there are other non- zero data that can be compressed to save some more room.

maintainer
#4 lore raw
In reply to Michael Chan

From: "Michael Chan" <[email protected]>
Date: Tue, 18 Sep 2007 11:45:14 -0700

Quoted 9 lines · Denys Vlasenko
Quoted 3 lines

Do you have any plans to switch to request_firmware() interface, which will allow you to avoid keeping firmware in unswappable kernel memory and thus free ~80k?

Matching the correct version of the firmware with the driver is the main issue.

David, what's your opinion on this?

I don't like it because it means people have to setup full initrd's in order to do network booting with such network cards.

But the days of my opinion mattering on that issue are long gone, the momentum is just too greatly behind using request_firmware() across the board, so there is no reason for bnx2 to be any different.

#5 lore raw
Quoted 4 lines · David Miller

I don't like it because it means people have to setup full initrd's in order to do network booting with such network cards.

klibc could help with that, if there is interest in exploring that avenue again.

-hpa

maintainer
#6 lore raw

From: "H. Peter Anvin" <[email protected]>
Date: Tue, 18 Sep 2007 11:41:34 -0700

Quoted 8 lines
Quoted 4 lines · David Miller

I don't like it because it means people have to setup full initrd's in order to do network booting with such network cards.

klibc could help with that, if there is interest in exploring that avenue again.

I appreciate the effort you put into klibc and the offer to make initrd's easier to build.

But the point is that the initrd shouldn't be necessary in the first place. There becomes zero point in building these drivers statically into the kernel, which many of us do specifically to avoid module loading, initrds, and all that fuss. Because the driver is totally crippled even though it's been fully built into the main kernel image.

I mean, it's so incredibly stupid and makes kernel development that much more difficult.

Every new dependency, be it requiring initrd or something else, is one more barrier added to kernel development.

I really pine for the days where everything was so simple, and initrd and modules were the odd ball cases, most developers built everything into their kernel image.

#7 lore raw
Quoted 22 lines · David Miller

From: "H. Peter Anvin" <[email protected]>
Date: Tue, 18 Sep 2007 11:41:34 -0700

Quoted 6 lines
Quoted 3 lines · David Miller

I don't like it because it means people have to setup full initrd's in order to do network booting with such network cards.

klibc could help with that, if there is interest in exploring that avenue again.

I appreciate the effort you put into klibc and the offer to make initrd's easier to build.

But the point is that the initrd shouldn't be necessary in the first place. There becomes zero point in building these drivers statically into the kernel, which many of us do specifically to avoid module loading, initrds, and all that fuss. Because the driver is totally crippled even though it's been fully built into the main kernel image.

I mean, it's so incredibly stupid and makes kernel development that much more difficult.

Quoted 6 lines

Every new dependency, be it requiring initrd or something else, is one more barrier added to kernel development.

I really pine for the days where everything was so simple, and initrd and modules were the odd ball cases, most developers built everything into their kernel image.

Well, what I was referring to here, of course, was the initramfs integrated in the kernel image, so it all comes out of the kernel build tree and produces a single bootable image. The fact that part of it contains userspace code is in that way invisible.

That was kind of the point here, and the only reason for pushing klibc into the kernel build tree at all. Under the "distros use external initrd anyway" school of thought, whatever libc used for that can be external anyway.

-hpa

maintainer
#8 lore raw

From: "H. Peter Anvin" <[email protected]>
Date: Tue, 18 Sep 2007 12:27:04 -0700

Quoted 9 lines

Well, what I was referring to here, of course, was the initramfs integrated in the kernel image, so it all comes out of the kernel build tree and produces a single bootable image. The fact that part of it contains userspace code is in that way invisible.

That was kind of the point here, and the only reason for pushing klibc into the kernel build tree at all. Under the "distros use external initrd anyway" school of thought, whatever libc used for that can be external anyway.

Sounds good to me :)

#9 lore raw
Quoted 8 lines · David Miller

From: "H. Peter Anvin" <[email protected]>
Date: Tue, 18 Sep 2007 12:27:04 -0700

Quoted 5 lines

Well, what I was referring to here, of course, was the initramfs integrated in the kernel image, so it all comes out of the kernel build tree and produces a single bootable image. The fact that part of it contains userspace code is in that way invisible.

Quoted 6 lines
Quoted 4 lines

That was kind of the point here, and the only reason for pushing klibc into the kernel build tree at all. Under the "distros use external initrd anyway" school of thought, whatever libc used for that can be external anyway.

Sounds good to me :)

Except there seems to be great resistance to include userland code in the kernel as demonstrated at last KS. Or this is maybe just a single vocal person and the topic were brought up late?

Anyway - if we again consider klibc I will do my best to make the build stuff as smooth as possible.

Sam

#10 lore raw
Quoted 8 lines · Sam Ravnborg

Except there seems to be great resistance to include userland code in the kernel as demonstrated at last KS. Or this is maybe just a single vocal person and the topic were brought up late?

Anyway - if we again consider klibc I will do my best to make the build stuff as smooth as possible.

At least as of the last merged tree it was very smooth indeed, thanks to your help.

-hpa

#11 lore raw
In reply to Sam Ravnborg
Quoted 4 lines · Sam Ravnborg

Anyway - if we again consider klibc I will do my best to make the build stuff as smooth as possible.

Sam

<nitpicking mode on>
currently klibc has tendency to rebuild a bit too much if you touch some part of it, seen in usr/utils
for the main klibc i agree that it makes sense

Signature · 1 line
maks
#12 lore raw
Quoted 5 lines · maximilian attems
Quoted 3 lines · Sam Ravnborg

Anyway - if we again consider klibc I will do my best to make the build stuff as smooth as possible.

Quoted 7 lines
Quoted 1 line

Sam

<nitpicking mode on>
currently klibc has tendency to rebuild a bit too much if you touch some part of it, seen in usr/utils
for the main klibc i agree that it makes sense

Could you give a concrete example?

-hpa

#13 lore raw
Quoted 4 lines · H. Peter Anvin

Could you give a concrete example?

-hpa

max@dual:~/src/klibc$ touch usr/utils/mount_main.c
max@dual:~/src/klibc$ make
  KLIBCCC usr/utils/mount_main.o
  KLIBCLD usr/utils/static/halt
  LN      usr/utils/static/reboot
  LN      usr/utils/static/poweroff
  KLIBCLD usr/utils/shared/halt
  LN      usr/utils/shared/reboot
  LN      usr/utils/shared/poweroff
  KLIBCLD usr/utils/static/chroot
  KLIBCLD usr/utils/static/dd
  <snipp>
Signature · 1 line
maks
#14 lore raw

Hi Maks.

Quoted 6 lines · maximilian attems
Quoted 4 lines · H. Peter Anvin

Could you give a concrete example?

-hpa

Quoted 12 lines
max@dual:~/src/klibc$ touch usr/utils/mount_main.c
max@dual:~/src/klibc$ make
  KLIBCCC usr/utils/mount_main.o
  KLIBCLD usr/utils/static/halt
  LN      usr/utils/static/reboot
  LN      usr/utils/static/poweroff
  KLIBCLD usr/utils/shared/halt
  LN      usr/utils/shared/reboot
  LN      usr/utils/shared/poweroff
  KLIBCLD usr/utils/static/chroot
  KLIBCLD usr/utils/static/dd
  <snipp>

I do not recall the details at the moment but I recall I had to do this tradeoff for some reasons.
I do not say it is not fixable but when I did the static-y support I recall I took a shortcut or two under the assumption that everything build by klibc was anyway so simple that compiling a bit too much was no harm.

Too buried with other stuff right now.
But feel free to poke me in roughly a month and I will take a deeper look.

Sam

#15 lore raw
In reply to David Miller
Quoted 7 lines · David Miller

I don't like it because it means people have to setup full initrd's in order to do network booting with such network cards.

But the days of my opinion mattering on that issue are long gone, the momentum is just too greatly behind using request_firmware() across the board, so there is no reason for bnx2 to be any different.

The bnx2 firmware changes quite frequently. A new driver quite often requires new firmware to work correctly. Splitting them up makes things difficult for the user.

The firmware in tg3 is a lot more mature and I don't expect it to change. I think tg3 is better suited for using request_firmware().

maintainer
#16 lore raw

From: "Michael Chan" <[email protected]>
Date: Tue, 18 Sep 2007 13:05:51 -0700

Quoted 6 lines

The bnx2 firmware changes quite frequently. A new driver quite often requires new firmware to work correctly. Splitting them up makes things difficult for the user.

The firmware in tg3 is a lot more mature and I don't expect it to change. I think tg3 is better suited for using request_firmware().

Like I said, I think neither should change and the driver should be fully functional when built statically into the kernel.

:-)

#17 lore raw
Quoted 7 lines · David Miller

From: "Michael Chan" <[email protected]>
Date: Tue, 18 Sep 2007 13:05:51 -0700

Quoted 4 lines

The bnx2 firmware changes quite frequently. A new driver quite often requires new firmware to work correctly. Splitting them up makes things difficult for the user.

Quoted 5 lines
Quoted 2 lines

The firmware in tg3 is a lot more mature and I don't expect it to change. I think tg3 is better suited for using request_firmware().

Like I said, I think neither should change and the driver should be fully functional when built statically into the kernel.

Michael, doesn't a functional-yet-suboptimal firmware exist ? I mean, just the same principle as we all have kernels, boot CDs, statically built tools, etc... which run everywhere. If you have such a beast, maybe it would be a good start to have it in the kernel, and provide the users with the ability to upgrade the firmware once the system is able to do more complex things.

Just a thought...

Regards,
Willy

maintainer
#18 lore raw

From: Willy Tarreau <[email protected]>
Date: Tue, 18 Sep 2007 23:30:25 +0200

Quoted 14 lines · David Miller
Quoted 7 lines

From: "Michael Chan" <[email protected]>
Date: Tue, 18 Sep 2007 13:05:51 -0700

Quoted 4 lines

The bnx2 firmware changes quite frequently. A new driver quite often requires new firmware to work correctly. Splitting them up makes things difficult for the user.

Quoted 5 lines
Quoted 2 lines

The firmware in tg3 is a lot more mature and I don't expect it to change. I think tg3 is better suited for using request_firmware().

Like I said, I think neither should change and the driver should be fully functional when built statically into the kernel.

Quoted 8 lines

Michael, doesn't a functional-yet-suboptimal firmware exist ? I mean, just the same principle as we all have kernels, boot CDs, statically built tools, etc... which run everywhere. If you have such a beast, maybe it would be a good start to have it in the kernel, and provide the users with the ability to upgrade the firmware once the system is able to do more complex things.

Just a thought...

So let's save 60K instead of 80K.

I mean, the entire discussion is just plain silly :)

#19 lore raw
Quoted 24 lines · David Miller

From: Willy Tarreau <[email protected]>
Date: Tue, 18 Sep 2007 23:30:25 +0200

Quoted 21 lines · David Miller
Quoted 7 lines

From: "Michael Chan" <[email protected]>
Date: Tue, 18 Sep 2007 13:05:51 -0700

Quoted 4 lines

The bnx2 firmware changes quite frequently. A new driver quite often requires new firmware to work correctly. Splitting them up makes things difficult for the user.

Quoted 5 lines
Quoted 2 lines

The firmware in tg3 is a lot more mature and I don't expect it to change. I think tg3 is better suited for using request_firmware().

Like I said, I think neither should change and the driver should be fully functional when built statically into the kernel.

Michael, doesn't a functional-yet-suboptimal firmware exist ? I mean, just the same principle as we all have kernels, boot CDs, statically built tools, etc... which run everywhere. If you have such a beast, maybe it would be a good start to have it in the kernel, and provide the users with the ability to upgrade the firmware once the system is able to do more complex things.

Quoted 3 lines
Quoted 1 line

Just a thought...

So let's save 60K instead of 80K.

That's not for this reason I said this. Michael said the firmware needs to be updated somewhat often. What I was wondering was if it was not possible to stick to a stable one (and hopefully small) so that the driver could require less frequent updates. Sorry if it's not the main point of the discussion, but I grepped on this :-)

Quoted 1 line

I mean, the entire discussion is just plain silly :)

yes, possibly :-)

Cheers,
Willy

#20 lore raw
Quoted 9 lines · Willy Tarreau
Quoted 9 lines
Quoted 8 lines

Michael, doesn't a functional-yet-suboptimal firmware exist ? I mean, just the same principle as we all have kernels, boot CDs, statically built tools, etc... which run everywhere. If you have such a beast, maybe it would be a good start to have it in the kernel, and provide the users with the ability to upgrade the firmware once the system is able to do more complex things.

Just a thought...

Quoted 8 lines
Quoted 1 line

So let's save 60K instead of 80K.

That's not for this reason I said this. Michael said the firmware needs to be updated somewhat often. What I was wondering was if it was not possible to stick to a stable one (and hopefully small) so that the driver could require less frequent updates. Sorry if it's not the main point of the discussion, but I grepped on this :-)

The bnx2 chip requires a lot of firmware to begin with, so it won't save much space no matter what version is used in the kernel. We update the firmware to fix bugs and sometimes to add new features. New features often require matching changes in the driver. For example, we're planning to add S/G support for jumbo rx frames and this requires changes in both driver and firmware.

It's possible to make the driver work with multiple firmware versions, but that adds complexity to enable/disable certain features. Testing also becomes more difficult as it has to cover different combinations.

#21 lore raw
In reply to David Miller
Quoted 7 lines · David Miller

From: "Michael Chan" <[email protected]>
Date: Tue, 18 Sep 2007 13:05:51 -0700

Quoted 4 lines

The bnx2 firmware changes quite frequently. A new driver quite often requires new firmware to work correctly. Splitting them up makes things difficult for the user.

Quoted 6 lines
Quoted 2 lines

The firmware in tg3 is a lot more mature and I don't expect it to change. I think tg3 is better suited for using request_firmware().

Like I said, I think neither should change and the driver should be fully functional when built statically into the kernel.

Is that a suggestion that the driver work differently when built as a module or built in? I've seen that behavior many time over the years, but it usually not deliberate. ;-)

Signature · 3 lines
Bill Davidsen <[email protected]>
  "We have more to fear from the bungling of the incompetent than from
the machinations of the wicked."  - from Slashdot
maintainer
#22 lore raw

From: Bill Davidsen <[email protected]>
Date: Wed, 19 Sep 2007 09:40:14 -0400

Quoted 2 lines

Is that a suggestion that the driver work differently when built as a module or built in?

Absolutely.

#23 lore raw
In reply to Michael Chan
Quoted 3 lines · Michael Chan

The bnx2 firmware changes quite frequently. A new driver quite often requires new firmware to work correctly. Splitting them up makes things difficult for the user.

sounds reasonable.

I see that bnx2 has support for unpacking gzipped binary blobs, and it it the only such net driver (maybe the only such driver in the entire tree, I didn't check).

This can be very useful for all other firmware images in other drivers.

Last night I prepared a patch which basically separates unpacking function from bnx2-related code. Can you run-test attached patch?

Meanwhile I will prepare follow-on patch which actually moves this function out of the driver and into lib/*.

Size difference:

# size */bn*.o
   text    data     bss     dec     hex filename
  54884   81689    6424  142997   22e95 net/bnx2.o
  55276   81823    6424  143523   230a3 net.org/bnx2.o

--
vda

drivers/net/bnx2.c +57 -102
@@ -2767,93 +2767,61 @@
 	spin_unlock_bh(&bp->phy_lock);
 }
 
-#define FW_BUF_SIZE	0x8000
-
+/* To be moved to generic lib/ */
 static int
-bnx2_gunzip_init(struct bnx2 *bp)
+bnx2_gunzip(u8 *zbuf, int len, void **outbuf)
 {
-	if ((bp->gunzip_buf = vmalloc(FW_BUF_SIZE)) == NULL)
-		goto gunzip_nomem1;
+	struct z_stream_s *strm;
+	void *gunzip_buf;
+	int rc;
+	int sz;
 
-	if ((bp->strm = kmalloc(sizeof(*bp->strm), GFP_KERNEL)) == NULL)
-		goto gunzip_nomem2;
+	/* gzip header (1f,8b,08... 10 bytes total + possible asciz filename)
+	 * is stripped, 32-bit unpacked size (LE) is prepended instead */
+	sz = *zbuf++;
+	sz = (sz << 8) + *zbuf++;
+	sz = (sz << 8) + *zbuf++;
+	sz = (sz << 8) + *zbuf++;
 
-	bp->strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
-	if (bp->strm->workspace == NULL)
+	rc = -ENOMEM;
+	gunzip_buf = vmalloc(sz);
+	if (gunzip_buf == NULL)
+		goto gunzip_nomem1;
+	strm = kmalloc(sizeof(*strm), GFP_KERNEL);
+	if (strm == NULL)
+		goto gunzip_nomem2;
+	strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
+	if (strm->workspace == NULL)
 		goto gunzip_nomem3;
 
-	return 0;
+	strm->next_in = zbuf;
+	strm->avail_in = len;
+	strm->next_out = gunzip_buf;
+	strm->avail_out = sz;
 
-gunzip_nomem3:
-	kfree(bp->strm);
-	bp->strm = NULL;
+	rc = zlib_inflateInit2(strm, -MAX_WBITS);
+	if (rc == Z_OK) {
+		rc = zlib_inflate(strm, Z_FINISH);
+		if (rc == Z_OK) {
+			rc = sz - strm->avail_out;
+			*outbuf = gunzip_buf;
+		} else
+			rc = -EINVAL;
+		zlib_inflateEnd(strm);
+	} else
+		rc = -EINVAL;
 
+	kfree(strm->workspace);
+gunzip_nomem3:
+	kfree(strm);
 gunzip_nomem2:
-	vfree(bp->gunzip_buf);
-	bp->gunzip_buf = NULL;
-
+	if (rc != Z_OK)
+		vfree(gunzip_buf);
 gunzip_nomem1:
-	printk(KERN_ERR PFX "%s: Cannot allocate firmware buffer for "
-			    "uncompression.\n", bp->dev->name);
-	return -ENOMEM;
+	return rc; /* returns Z_OK (0) if successful */
 }
 
 static void
-bnx2_gunzip_end(struct bnx2 *bp)
-{
-	kfree(bp->strm->workspace);
-
-	kfree(bp->strm);
-	bp->strm = NULL;
-
-	if (bp->gunzip_buf) {
-		vfree(bp->gunzip_buf);
-		bp->gunzip_buf = NULL;
-	}
-}
-
-static int
-bnx2_gunzip(struct bnx2 *bp, u8 *zbuf, int len, void **outbuf, int *outlen)
-{
-	int n, rc;
-
-	/* check gzip header */
-	if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED))
-		return -EINVAL;
-
-	n = 10;
-
-#define FNAME	0x8
-	if (zbuf[3] & FNAME)
-		while ((zbuf[n++] != 0) && (n < len));
-
-	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;
-
-	rc = zlib_inflateInit2(bp->strm, -MAX_WBITS);
-	if (rc != Z_OK)
-		return rc;
-
-	rc = zlib_inflate(bp->strm, Z_FINISH);
-
-	*outlen = FW_BUF_SIZE - bp->strm->avail_out;
-	*outbuf = bp->gunzip_buf;
-
-	if ((rc != Z_OK) && (rc != Z_STREAM_END))
-		printk(KERN_ERR PFX "%s: Firmware decompression error: %s\n",
-		       bp->dev->name, bp->strm->msg);
-
-	zlib_inflateEnd(bp->strm);
-
-	if (rc == Z_STREAM_END)
-		return 0;
-
-	return rc;
-}
-
-static void
 load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len,
 	u32 rv2p_proc)
 {
@@ -2902,22 +2870,16 @@
 	/* Load the Text area. */
 	offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
 	if (fw->gz_text) {
-		u32 text_len;
-		void *text;
-
-		rc = bnx2_gunzip(bp, fw->gz_text, fw->gz_text_len, &text,
-				 &text_len);
-		if (rc)
-			return rc;
-
-		fw->text = text;
-	}
-	if (fw->gz_text) {
+		u32 *text;
 		int j;
 
+		rc = bnx2_gunzip(fw->gz_text, fw->gz_text_len, (void*) &text);
+		if (rc < 0)
+			return rc;
 		for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
-			REG_WR_IND(bp, offset, cpu_to_le32(fw->text[j]));
+			REG_WR_IND(bp, offset, cpu_to_le32(text[j]));
 	        }
+		vfree(text);
 	}
 
 	/* Load the Data area. */
@@ -2979,28 +2941,22 @@
 {
 	struct cpu_reg cpu_reg;
 	struct fw_info *fw;
-	int rc = 0;
+	int rc;
 	void *text;
-	u32 text_len;
 
-	if ((rc = bnx2_gunzip_init(bp)) != 0)
-		return rc;
-
 	/* Initialize the RV2P processor. */
-	rc = bnx2_gunzip(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), &text,
-			 &text_len);
-	if (rc)
+	rc = bnx2_gunzip(bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), &text);
+	if (rc < 0)
 		goto init_cpu_err;
+	load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC1);
+	vfree(text);
 
-	load_rv2p_fw(bp, text, text_len, RV2P_PROC1);
-
-	rc = bnx2_gunzip(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), &text,
-			 &text_len);
-	if (rc)
+	rc = bnx2_gunzip(bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), &text);
+	if (rc < 0)
 		goto init_cpu_err;
+	load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC2);
+	vfree(text);
 
-	load_rv2p_fw(bp, text, text_len, RV2P_PROC2);
-
 	/* Initialize the RX Processor. */
 	cpu_reg.mode = BNX2_RXP_CPU_MODE;
 	cpu_reg.mode_value_halt = BNX2_RXP_CPU_MODE_SOFT_HALT;
@@ -3115,7 +3071,6 @@
 			goto init_cpu_err;
 	}
 init_cpu_err:
-	bnx2_gunzip_end(bp);
 	return rc;
 }
 
drivers/net/bnx2.h +1 -4
@@ -6679,9 +6679,6 @@
 	u32			flash_size;
 
 	int			status_stats_size;
-
-	struct z_stream_s	*strm;
-	void			*gunzip_buf;
 };
 
 static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset);
@@ -6739,7 +6736,7 @@
 	const u32 text_addr;
 	const u32 text_len;
 	const u32 text_index;
-	u32 *text;
+/*	u32 *text;*/
 	u8 *gz_text;
 	const u32 gz_text_len;
 
drivers/net/bnx2_fw.h +23 -11
@@ -15,7 +15,9 @@
  */
 
 static u8 bnx2_COM_b06FwText[] = {
-	0x1f, 0x8b, 0x08, 0x00, 0x45, 0x30, 0xe7, 0x45, 0x00, 0x03, 0xdc, 0x5a,
+	0x00, 0x80, 0x00, 0x00, /* unpack buf size = 0x8000 */
+/*	0x1f, 0x8b, 0x08, 0x00, 0x45, 0x30, 0xe7, 0x45, 0x00, 0x03, */
+								    0xdc, 0x5a,
 	0x6b, 0x6c, 0x1c, 0xd7, 0x75, 0x3e, 0x33, 0x3b, 0x4b, 0xae, 0xc8, 0x15,
 	0x35, 0xa2, 0xc6, 0xf4, 0x5a, 0xa2, 0xed, 0x5d, 0x72, 0x28, 0x12, 0x96,
 	0xec, 0x6e, 0x68, 0xda, 0x62, 0x8c, 0x8d, 0xb4, 0xd9, 0xa5, 0x0c, 0xa1,
@@ -1085,8 +1087,10 @@
 };
 
 static u8 bnx2_RXP_b06FwText[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0xcb, 0xa3, 0x46, 0x45, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5c, 0x6f, 0x6c,
+	0x00, 0x80, 0x00, 0x00, /* unpack buf size = 0x8000 */
+/*	0x1f, 0x8b, 0x08, 0x08, 0xcb, 0xa3, 0x46, 0x45, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, */
+							0xec, 0x5c, 0x6f, 0x6c,
 	0x1c, 0xc7, 0x75, 0x7f, 0x3b, 0xbb, 0xa4, 0x4e, 0xd4, 0x91, 0x5c, 0x1e,
 	0x4f, 0xf4, 0x49, 0x66, 0x94, 0x5d, 0x71, 0x25, 0x5e, 0x2d, 0xc6, 0x5d,
 	0x31, 0x57, 0x9b, 0x08, 0xce, 0xf1, 0x79, 0xef, 0x64, 0xb1, 0x86, 0x0a,
@@ -1798,8 +1802,10 @@
 };
 
 static u8 bnx2_rv2p_proc1[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0x5e, 0xd0, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x56, 0xcf, 0x6b,
+	0x00, 0x80, 0x00, 0x00, /* unpack buf size = 0x8000 */
+/*	0x1f, 0x8b, 0x08, 0x08, 0x5e, 0xd0, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, */
+							0xc5, 0x56, 0xcf, 0x6b,
 	0x13, 0x51, 0x10, 0x9e, 0xec, 0x6e, 0xb2, 0xdb, 0x74, 0xbb, 0x1b, 0x2b,
 	0xda, 0xa0, 0xb1, 0x8d, 0x51, 0x6a, 0x7f, 0xa4, 0xb4, 0x11, 0x0f, 0x82,
 	0x42, 0x25, 0x3d, 0x04, 0x54, 0x44, 0x7a, 0x28, 0x22, 0x82, 0x36, 0x8a,
@@ -1877,8 +1883,10 @@
 	0x12, 0x3d, 0x80, 0x0b, 0x00, 0x00, 0x00 };
 
 static u8 bnx2_rv2p_proc2[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0x7e, 0xd1, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xcd, 0x58, 0x5b, 0x6c,
+	0x00, 0x80, 0x00, 0x00, /* unpack buf size = 0x8000 */
+/*	0x1f, 0x8b, 0x08, 0x08, 0x7e, 0xd1, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, */
+							0xcd, 0x58, 0x5b, 0x6c,
 	0x54, 0x55, 0x14, 0x3d, 0xf3, 0xe8, 0xcc, 0x9d, 0xe9, 0xed, 0x9d, 0xf2,
 	0xb2, 0x03, 0xad, 0x08, 0xe5, 0xd1, 0x56, 0x29, 0xe8, 0x54, 0xab, 0x18,
 	0x15, 0x2c, 0x5a, 0x8c, 0x26, 0x68, 0xf0, 0xf9, 0x63, 0x14, 0x04, 0xda,
@@ -2057,8 +2065,10 @@
 	0x17, 0x00, 0x00, 0x00 };
 
 static u8 bnx2_TPAT_b06FwText[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0x47, 0xd2, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x57, 0x4d, 0x68,
+	0x00, 0x80, 0x00, 0x00, /* unpack buf size = 0x8000 */
+/*	0x1f, 0x8b, 0x08, 0x08, 0x47, 0xd2, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, */
+							0xc5, 0x57, 0x4d, 0x68,
 	0x1c, 0xe7, 0x19, 0x7e, 0xe7, 0x77, 0x47, 0x62, 0x25, 0x8d, 0x93, 0x3d,
 	0xac, 0x5d, 0xa5, 0x99, 0x91, 0x46, 0x3f, 0x54, 0x26, 0x9e, 0x84, 0xa5,
 	0x56, 0x61, 0x20, 0xe3, 0x99, 0x95, 0x2c, 0x0c, 0x05, 0x07, 0x42, 0x08,
@@ -2290,8 +2300,10 @@
 };
 
 static u8 bnx2_TXP_b06FwText[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0x21, 0xd3, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xed, 0x5c, 0x6d, 0x6c,
+	0x00, 0x80, 0x00, 0x00, /* unpack buf size = 0x8000 */
+/*	0x1f, 0x8b, 0x08, 0x08, 0x21, 0xd3, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, */
+							0xed, 0x5c, 0x6d, 0x6c,
 	0x1b, 0xf7, 0x79, 0x7f, 0xee, 0x85, 0xd2, 0x51, 0x96, 0xe9, 0x93, 0xc2,
 	0x78, 0x6c, 0xc0, 0xa6, 0x77, 0xd6, 0x51, 0x66, 0x20, 0xb5, 0xa0, 0x05,
 	0x36, 0x55, 0x87, 0x43, 0x73, 0x3e, 0x52, 0x2f, 0x4e, 0x5c, 0x57, 0x71,
drivers/net/bnx2_fw2.h +15 -5
@@ -15,7 +15,9 @@
  */
 
 static u8 bnx2_COM_b09FwText[] = {
-	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xdc, 0x5b,
+	0x00, 0x80, 0x00, 0x00, /* unpack buf size = 0x8000 */
+/*	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
+								    0xdc, 0x5b,
 	0x6d, 0x70, 0x5c, 0xd5, 0x79, 0x7e, 0xef, 0xd9, 0xbb, 0xf2, 0x5a, 0x92,
 	0xe5, 0x6b, 0x79, 0x23, 0x16, 0x4b, 0xc0, 0xae, 0x75, 0x6d, 0x69, 0xb0,
 	0x43, 0x16, 0xa1, 0x80, 0x9a, 0xd9, 0xc0, 0xb2, 0x2b, 0x33, 0x9e, 0x0c,
@@ -1083,7 +1085,9 @@
 };
 
 static u8 bnx2_CP_b09FwText[] = {
-	0x1f, 0x8b, 0x08, 0x00, 0x0f, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xbd, 0x7d,
+	0x00, 0x80, 0x00, 0x00, /* unpack buf size = 0x8000 */
+/*	0x1f, 0x8b, 0x08, 0x00, 0x0f, 0x34, 0xe7, 0x45, 0x00, 0x03, */
+								    0xbd, 0x7d,
 	0x0d, 0x74, 0x5c, 0x57, 0x7d, 0xe7, 0xff, 0xdd, 0x19, 0x49, 0x63, 0x59,
 	0x96, 0x9f, 0xe5, 0x89, 0x32, 0x51, 0x84, 0x3d, 0x23, 0x3d, 0xd9, 0x22,
 	0x12, 0xe1, 0xc5, 0x11, 0xac, 0xda, 0x2a, 0xe9, 0x30, 0x92, 0x3f, 0x12,
@@ -2279,7 +2283,9 @@
 };
 
 static u8 bnx2_RXP_b09FwText[] = {
-	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xec, 0x5c,
+	0x00, 0x80, 0x00, 0x00, /* unpack buf size = 0x8000 */
+/*	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
+								    0xec, 0x5c,
 	0x5d, 0x6c, 0x1c, 0xd7, 0x75, 0x3e, 0xf3, 0x43, 0x6a, 0x49, 0xf1, 0x67,
 	0xb8, 0x5c, 0xb1, 0x2b, 0x99, 0x96, 0x77, 0xc9, 0x91, 0xc8, 0x58, 0x8a,
 	0x31, 0xa2, 0x09, 0x5b, 0x48, 0x17, 0xf6, 0x76, 0x76, 0x25, 0xb1, 0xb1,
@@ -2988,7 +2994,9 @@
 };
 
 static u8 bnx2_TPAT_b09FwText[] = {
-	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xcd, 0x58,
+	0x00, 0x80, 0x00, 0x00, /* unpack buf size = 0x8000 */
+/*	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
+								    0xcd, 0x58,
 	0x5d, 0x68, 0x1c, 0xd7, 0x15, 0x3e, 0xf3, 0xb7, 0x3b, 0x52, 0x24, 0xeb,
 	0x5a, 0xd9, 0xa6, 0xeb, 0xa0, 0x34, 0x33, 0xda, 0x91, 0xac, 0x22, 0x13,
 	0x4f, 0x9d, 0x25, 0x16, 0x65, 0x21, 0x93, 0xd9, 0x91, 0xac, 0x98, 0x3c,
@@ -3279,7 +3287,9 @@
 };
 
 static u8 bnx2_TXP_b09FwText[] = {
-	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xcd, 0x7c,
+	0x00, 0x80, 0x00, 0x00, /* unpack buf size = 0x8000 */
+/*	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
+								    0xcd, 0x7c,
 	0x6f, 0x70, 0x5b, 0xd7, 0x95, 0xdf, 0x79, 0xef, 0x81, 0x24, 0x48, 0xd1,
 	0xd4, 0x13, 0x17, 0x56, 0x60, 0x87, 0x71, 0x00, 0xf1, 0x81, 0x66, 0x42,
 	0xae, 0x04, 0x2b, 0x4c, 0xc2, 0x6d, 0xd1, 0xf8, 0x05, 0x00, 0x29, 0x48,
#24 lore raw

On Wed, 2007-09-19 at 09:30 +0100, Denys Vlasenko wrote:
+ /* gzip header (1f,8b,08... 10 bytes total + possible asciz filename)
+ * is stripped, 32-bit unpacked size (LE) is prepended instead */

+       sz = *zbuf++;
+       sz = (sz << 8) + *zbuf++;
+       sz = (sz << 8) + *zbuf++;
+       sz = (sz << 8) + *zbuf++;

I don't have a problem with removing the gzip header. It doesn't contain very useful information other than a valid header for sanity check. But I don't think we need to arbitrarily add the unpacked size in front of the gzipped data. The driver knows the size (e.g. the size of RAM on the chip) and should pass it to the call. The driver should also allocate the memory for the unpacked data instead of allocating the memory inside the call and freeing it by the caller. For example, the driver may need to use pci_alloc_consistent() if the firmware is to be DMA'ed to the chip.

Other than that, everything else looks fine. Thanks.

#25 lore raw
Quoted 18 lines · Michael Chan

On Wed, 2007-09-19 at 09:30 +0100, Denys Vlasenko wrote:

drivers/net/bnx2.c +6 -0
+       /* gzip header (1f,8b,08... 10 bytes total + possible asciz filename)
+        * is stripped, 32-bit unpacked size (LE) is prepended instead */
+       sz = *zbuf++;
+       sz = (sz << 8) + *zbuf++;
+       sz = (sz << 8) + *zbuf++;
+       sz = (sz << 8) + *zbuf++;

I don't have a problem with removing the gzip header. It doesn't contain very useful information other than a valid header for sanity check. But I don't think we need to arbitrarily add the unpacked size in front of the gzipped data. The driver knows the size (e.g. the size of RAM on the chip) and should pass it to the call. The driver should also allocate the memory for the unpacked data instead of allocating the memory inside the call and freeing it by the caller. For example, the driver may need to use pci_alloc_consistent() if the firmware is to be DMA'ed to the chip.

Quoted 1 line

Other than that, everything else looks fine. Thanks.

Are you saying that you successfully run-tested it? --
vda

#26 lore raw
Quoted 1 line · Denys Vlasenko

Are you saying that you successfully run-tested it?

I've only reviewed the code. Let's resolve these issues first before testing the code.

#27 lore raw
Quoted 6 lines · Michael Chan
Quoted 1 line · Denys Vlasenko

Are you saying that you successfully run-tested it?

I've only reviewed the code. Let's resolve these issues first before testing the code.

Please test these two patches.
I updated them according to your comments.
--
vda

drivers/net/bnx2.c +57 -102
diff -urpN linux-2.6.23-rc6/drivers/net/bnx2.c linux-2.6.23-rc6.bnx2/drivers/net/bnx2.c
@@ -52,6 +52,8 @@
 #include "bnx2_fw.h"
 #include "bnx2_fw2.h"
 
+#define FW_BUF_SIZE		0x8000
+
 #define DRV_MODULE_NAME		"bnx2"
 #define PFX DRV_MODULE_NAME	": "
 #define DRV_MODULE_VERSION	"1.6.4"
@@ -2767,89 +2769,44 @@ bnx2_set_rx_mode(struct net_device *dev)
 	spin_unlock_bh(&bp->phy_lock);
 }
 
-#define FW_BUF_SIZE	0x8000
-
+/* To be moved to generic lib/ */
 static int
-bnx2_gunzip_init(struct bnx2 *bp)
+bnx2_gunzip(void *gunzip_buf, unsigned sz, u8 *zbuf, int len, void **outbuf)
 {
-	if ((bp->gunzip_buf = vmalloc(FW_BUF_SIZE)) == NULL)
-		goto gunzip_nomem1;
+	struct z_stream_s *strm;
+	int rc;
 
-	if ((bp->strm = kmalloc(sizeof(*bp->strm), GFP_KERNEL)) == NULL)
-		goto gunzip_nomem2;
+	/* gzip header (1f,8b,08... 10 bytes total + possible asciz filename)
+	 * is stripped */
 
-	bp->strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
-	if (bp->strm->workspace == NULL)
+	rc = -ENOMEM;
+	strm = kmalloc(sizeof(*strm), GFP_KERNEL);
+	if (strm == NULL)
+		goto gunzip_nomem2;
+	strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
+	if (strm->workspace == NULL)
 		goto gunzip_nomem3;
 
-	return 0;
+	strm->next_in = zbuf;
+	strm->avail_in = len;
+	strm->next_out = gunzip_buf;
+	strm->avail_out = sz;
+
+	rc = zlib_inflateInit2(strm, -MAX_WBITS);
+	if (rc == Z_OK) {
+		rc = zlib_inflate(strm, Z_FINISH);
+		if (rc == Z_OK)
+			rc = sz - strm->avail_out;
+		else
+			rc = -EINVAL;
+		zlib_inflateEnd(strm);
+	} else
+		rc = -EINVAL;
 
+	kfree(strm->workspace);
 gunzip_nomem3:
-	kfree(bp->strm);
-	bp->strm = NULL;
-
+	kfree(strm);
 gunzip_nomem2:
-	vfree(bp->gunzip_buf);
-	bp->gunzip_buf = NULL;
-
-gunzip_nomem1:
-	printk(KERN_ERR PFX "%s: Cannot allocate firmware buffer for "
-			    "uncompression.\n", bp->dev->name);
-	return -ENOMEM;
-}
-
-static void
-bnx2_gunzip_end(struct bnx2 *bp)
-{
-	kfree(bp->strm->workspace);
-
-	kfree(bp->strm);
-	bp->strm = NULL;
-
-	if (bp->gunzip_buf) {
-		vfree(bp->gunzip_buf);
-		bp->gunzip_buf = NULL;
-	}
-}
-
-static int
-bnx2_gunzip(struct bnx2 *bp, u8 *zbuf, int len, void **outbuf, int *outlen)
-{
-	int n, rc;
-
-	/* check gzip header */
-	if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED))
-		return -EINVAL;
-
-	n = 10;
-
-#define FNAME	0x8
-	if (zbuf[3] & FNAME)
-		while ((zbuf[n++] != 0) && (n < len));
-
-	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;
-
-	rc = zlib_inflateInit2(bp->strm, -MAX_WBITS);
-	if (rc != Z_OK)
-		return rc;
-
-	rc = zlib_inflate(bp->strm, Z_FINISH);
-
-	*outlen = FW_BUF_SIZE - bp->strm->avail_out;
-	*outbuf = bp->gunzip_buf;
-
-	if ((rc != Z_OK) && (rc != Z_STREAM_END))
-		printk(KERN_ERR PFX "%s: Firmware decompression error: %s\n",
-		       bp->dev->name, bp->strm->msg);
-
-	zlib_inflateEnd(bp->strm);
-
-	if (rc == Z_STREAM_END)
-		return 0;
-
 	return rc;
 }
 
@@ -2902,22 +2859,21 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_
 	/* Load the Text area. */
 	offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
 	if (fw->gz_text) {
-		u32 text_len;
-		void *text;
-
-		rc = bnx2_gunzip(bp, fw->gz_text, fw->gz_text_len, &text,
-				 &text_len);
-		if (rc)
-			return rc;
-
-		fw->text = text;
-	}
-	if (fw->gz_text) {
+		u32 *text;
 		int j;
 
+		text = vmalloc(FW_BUF_SIZE);
+		if (!text)
+			return -ENOMEM;
+		rc = bnx2_gunzip(text, FW_BUF_SIZE, fw->gz_text, fw->gz_text_len);
+		if (rc < 0) {
+			vfree(text);
+			return rc;
+		}
 		for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
-			REG_WR_IND(bp, offset, cpu_to_le32(fw->text[j]));
+			REG_WR_IND(bp, offset, cpu_to_le32(text[j]));
 	        }
+		vfree(text);
 	}
 
 	/* Load the Data area. */
@@ -2979,27 +2935,27 @@ bnx2_init_cpus(struct bnx2 *bp)
 {
 	struct cpu_reg cpu_reg;
 	struct fw_info *fw;
-	int rc = 0;
+	int rc;
 	void *text;
-	u32 text_len;
-
-	if ((rc = bnx2_gunzip_init(bp)) != 0)
-		return rc;
 
 	/* Initialize the RV2P processor. */
-	rc = bnx2_gunzip(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), &text,
-			 &text_len);
-	if (rc)
+	text = vmalloc(FW_BUF_SIZE);
+	if (!text)
+		return -ENOMEM;
+	rc = bnx2_gunzip(text, FW_BUF_SIZE, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1));
+	if (rc < 0) {
+		vfree(text);
 		goto init_cpu_err;
+	}
+	load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC1);
 
-	load_rv2p_fw(bp, text, text_len, RV2P_PROC1);
-
-	rc = bnx2_gunzip(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), &text,
-			 &text_len);
-	if (rc)
+	rc = bnx2_gunzip(text, FW_BUF_SIZE, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2));
+	if (rc < 0) {
+		vfree(text);
 		goto init_cpu_err;
-
-	load_rv2p_fw(bp, text, text_len, RV2P_PROC2);
+	}
+	load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC2);
+	vfree(text);
 
 	/* Initialize the RX Processor. */
 	cpu_reg.mode = BNX2_RXP_CPU_MODE;
@@ -3115,7 +3071,6 @@ bnx2_init_cpus(struct bnx2 *bp)
 			goto init_cpu_err;
 	}
 init_cpu_err:
-	bnx2_gunzip_end(bp);
 	return rc;
 }
 
drivers/net/bnx2.h +1 -4
diff -urpN linux-2.6.23-rc6/drivers/net/bnx2.h linux-2.6.23-rc6.bnx2/drivers/net/bnx2.h
@@ -6679,9 +6679,6 @@ struct bnx2 {
 	u32			flash_size;
 
 	int			status_stats_size;
-
-	struct z_stream_s	*strm;
-	void			*gunzip_buf;
 };
 
 static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset);
@@ -6739,7 +6736,7 @@ struct fw_info {
 	const u32 text_addr;
 	const u32 text_len;
 	const u32 text_index;
-	u32 *text;
+/*	u32 *text;*/
 	u8 *gz_text;
 	const u32 gz_text_len;
 
drivers/net/bnx2_fw.h +17 -11
diff -urpN linux-2.6.23-rc6/drivers/net/bnx2_fw.h linux-2.6.23-rc6.bnx2/drivers/net/bnx2_fw.h
@@ -15,7 +15,8 @@
  */
 
 static u8 bnx2_COM_b06FwText[] = {
-	0x1f, 0x8b, 0x08, 0x00, 0x45, 0x30, 0xe7, 0x45, 0x00, 0x03, 0xdc, 0x5a,
+/*	0x1f, 0x8b, 0x08, 0x00, 0x45, 0x30, 0xe7, 0x45, 0x00, 0x03, */
+								    0xdc, 0x5a,
 	0x6b, 0x6c, 0x1c, 0xd7, 0x75, 0x3e, 0x33, 0x3b, 0x4b, 0xae, 0xc8, 0x15,
 	0x35, 0xa2, 0xc6, 0xf4, 0x5a, 0xa2, 0xed, 0x5d, 0x72, 0x28, 0x12, 0x96,
 	0xec, 0x6e, 0x68, 0xda, 0x62, 0x8c, 0x8d, 0xb4, 0xd9, 0xa5, 0x0c, 0xa1,
@@ -1085,8 +1086,9 @@ static struct fw_info bnx2_com_fw_06 = {
 };
 
 static u8 bnx2_RXP_b06FwText[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0xcb, 0xa3, 0x46, 0x45, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5c, 0x6f, 0x6c,
+/*	0x1f, 0x8b, 0x08, 0x08, 0xcb, 0xa3, 0x46, 0x45, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, */
+							0xec, 0x5c, 0x6f, 0x6c,
 	0x1c, 0xc7, 0x75, 0x7f, 0x3b, 0xbb, 0xa4, 0x4e, 0xd4, 0x91, 0x5c, 0x1e,
 	0x4f, 0xf4, 0x49, 0x66, 0x94, 0x5d, 0x71, 0x25, 0x5e, 0x2d, 0xc6, 0x5d,
 	0x31, 0x57, 0x9b, 0x08, 0xce, 0xf1, 0x79, 0xef, 0x64, 0xb1, 0x86, 0x0a,
@@ -1798,8 +1800,9 @@ static struct fw_info bnx2_rxp_fw_06 = {
 };
 
 static u8 bnx2_rv2p_proc1[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0x5e, 0xd0, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x56, 0xcf, 0x6b,
+/*	0x1f, 0x8b, 0x08, 0x08, 0x5e, 0xd0, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, */
+							0xc5, 0x56, 0xcf, 0x6b,
 	0x13, 0x51, 0x10, 0x9e, 0xec, 0x6e, 0xb2, 0xdb, 0x74, 0xbb, 0x1b, 0x2b,
 	0xda, 0xa0, 0xb1, 0x8d, 0x51, 0x6a, 0x7f, 0xa4, 0xb4, 0x11, 0x0f, 0x82,
 	0x42, 0x25, 0x3d, 0x04, 0x54, 0x44, 0x7a, 0x28, 0x22, 0x82, 0x36, 0x8a,
@@ -1877,8 +1880,9 @@ static u8 bnx2_rv2p_proc1[] = {
 	0x12, 0x3d, 0x80, 0x0b, 0x00, 0x00, 0x00 };
 
 static u8 bnx2_rv2p_proc2[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0x7e, 0xd1, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xcd, 0x58, 0x5b, 0x6c,
+/*	0x1f, 0x8b, 0x08, 0x08, 0x7e, 0xd1, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, */
+							0xcd, 0x58, 0x5b, 0x6c,
 	0x54, 0x55, 0x14, 0x3d, 0xf3, 0xe8, 0xcc, 0x9d, 0xe9, 0xed, 0x9d, 0xf2,
 	0xb2, 0x03, 0xad, 0x08, 0xe5, 0xd1, 0x56, 0x29, 0xe8, 0x54, 0xab, 0x18,
 	0x15, 0x2c, 0x5a, 0x8c, 0x26, 0x68, 0xf0, 0xf9, 0x63, 0x14, 0x04, 0xda,
@@ -2057,8 +2061,9 @@ static u8 bnx2_rv2p_proc2[] = {
 	0x17, 0x00, 0x00, 0x00 };
 
 static u8 bnx2_TPAT_b06FwText[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0x47, 0xd2, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x57, 0x4d, 0x68,
+/*	0x1f, 0x8b, 0x08, 0x08, 0x47, 0xd2, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, */
+							0xc5, 0x57, 0x4d, 0x68,
 	0x1c, 0xe7, 0x19, 0x7e, 0xe7, 0x77, 0x47, 0x62, 0x25, 0x8d, 0x93, 0x3d,
 	0xac, 0x5d, 0xa5, 0x99, 0x91, 0x46, 0x3f, 0x54, 0x26, 0x9e, 0x84, 0xa5,
 	0x56, 0x61, 0x20, 0xe3, 0x99, 0x95, 0x2c, 0x0c, 0x05, 0x07, 0x42, 0x08,
@@ -2290,8 +2295,9 @@ static struct fw_info bnx2_tpat_fw_06 = 
 };
 
 static u8 bnx2_TXP_b06FwText[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0x21, 0xd3, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xed, 0x5c, 0x6d, 0x6c,
+/*	0x1f, 0x8b, 0x08, 0x08, 0x21, 0xd3, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, */
+							0xed, 0x5c, 0x6d, 0x6c,
 	0x1b, 0xf7, 0x79, 0x7f, 0xee, 0x85, 0xd2, 0x51, 0x96, 0xe9, 0x93, 0xc2,
 	0x78, 0x6c, 0xc0, 0xa6, 0x77, 0xd6, 0x51, 0x66, 0x20, 0xb5, 0xa0, 0x05,
 	0x36, 0x55, 0x87, 0x43, 0x73, 0x3e, 0x52, 0x2f, 0x4e, 0x5c, 0x57, 0x71,
drivers/net/bnx2_fw2.h +10 -5
diff -urpN linux-2.6.23-rc6/drivers/net/bnx2_fw2.h linux-2.6.23-rc6.bnx2/drivers/net/bnx2_fw2.h
@@ -15,7 +15,8 @@
  */
 
 static u8 bnx2_COM_b09FwText[] = {
-	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xdc, 0x5b,
+/*	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
+								    0xdc, 0x5b,
 	0x6d, 0x70, 0x5c, 0xd5, 0x79, 0x7e, 0xef, 0xd9, 0xbb, 0xf2, 0x5a, 0x92,
 	0xe5, 0x6b, 0x79, 0x23, 0x16, 0x4b, 0xc0, 0xae, 0x75, 0x6d, 0x69, 0xb0,
 	0x43, 0x16, 0xa1, 0x80, 0x9a, 0xd9, 0xc0, 0xb2, 0x2b, 0x33, 0x9e, 0x0c,
@@ -1083,7 +1084,8 @@ static struct fw_info bnx2_com_fw_09 = {
 };
 
 static u8 bnx2_CP_b09FwText[] = {
-	0x1f, 0x8b, 0x08, 0x00, 0x0f, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xbd, 0x7d,
+/*	0x1f, 0x8b, 0x08, 0x00, 0x0f, 0x34, 0xe7, 0x45, 0x00, 0x03, */
+								    0xbd, 0x7d,
 	0x0d, 0x74, 0x5c, 0x57, 0x7d, 0xe7, 0xff, 0xdd, 0x19, 0x49, 0x63, 0x59,
 	0x96, 0x9f, 0xe5, 0x89, 0x32, 0x51, 0x84, 0x3d, 0x23, 0x3d, 0xd9, 0x22,
 	0x12, 0xe1, 0xc5, 0x11, 0xac, 0xda, 0x2a, 0xe9, 0x30, 0x92, 0x3f, 0x12,
@@ -2279,7 +2281,8 @@ static struct fw_info bnx2_cp_fw_09 = {
 };
 
 static u8 bnx2_RXP_b09FwText[] = {
-	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xec, 0x5c,
+/*	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
+								    0xec, 0x5c,
 	0x5d, 0x6c, 0x1c, 0xd7, 0x75, 0x3e, 0xf3, 0x43, 0x6a, 0x49, 0xf1, 0x67,
 	0xb8, 0x5c, 0xb1, 0x2b, 0x99, 0x96, 0x77, 0xc9, 0x91, 0xc8, 0x58, 0x8a,
 	0x31, 0xa2, 0x09, 0x5b, 0x48, 0x17, 0xf6, 0x76, 0x76, 0x25, 0xb1, 0xb1,
@@ -2988,7 +2991,8 @@ static struct fw_info bnx2_rxp_fw_09 = {
 };
 
 static u8 bnx2_TPAT_b09FwText[] = {
-	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xcd, 0x58,
+/*	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
+								    0xcd, 0x58,
 	0x5d, 0x68, 0x1c, 0xd7, 0x15, 0x3e, 0xf3, 0xb7, 0x3b, 0x52, 0x24, 0xeb,
 	0x5a, 0xd9, 0xa6, 0xeb, 0xa0, 0x34, 0x33, 0xda, 0x91, 0xac, 0x22, 0x13,
 	0x4f, 0x9d, 0x25, 0x16, 0x65, 0x21, 0x93, 0xd9, 0x91, 0xac, 0x98, 0x3c,
@@ -3279,7 +3283,8 @@ static struct fw_info bnx2_tpat_fw_09 = 
 };
 
 static u8 bnx2_TXP_b09FwText[] = {
-	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xcd, 0x7c,
+/*	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, */
+								    0xcd, 0x7c,
 	0x6f, 0x70, 0x5b, 0xd7, 0x95, 0xdf, 0x79, 0xef, 0x81, 0x24, 0x48, 0xd1,
 	0xd4, 0x13, 0x17, 0x56, 0x60, 0x87, 0x71, 0x00, 0xf1, 0x81, 0x66, 0x42,
 	0xae, 0x04, 0x2b, 0x4c, 0xc2, 0x6d, 0xd1, 0xf8, 0x05, 0x00, 0x29, 0x48,
drivers/net/bnx2.c +3 -44

71 lines not on this page · raw message

include/linux/zlib.h +5 -1
diff -urp linux-2.6.23-rc6.bnx2/include/linux/zlib.h linux-2.6.23-rc6.bnx2_2/include/linux/zlib.h
@@ -82,7 +82,7 @@
 struct internal_state;
 
 typedef struct z_stream_s {
-    Byte    *next_in;   /* next input byte */
+    const Byte *next_in;   /* next input byte */
     uInt     avail_in;  /* number of bytes available at next_in */
     uLong    total_in;  /* total nb of input bytes read so far */
 
@@ -699,4 +699,8 @@ extern int zlib_inflateInit2(z_streamp s
     struct internal_state {int dummy;}; /* hack for buggy compilers */
 #endif
 
+/* Utility function: initialize zlib, unpack binary blob, clean up zlib,
+ * return len or negative error code. */
+extern int zlib_inflate_blob(void *dst, unsigned dst_sz, const void *src, unsigned src_sz);
+
 #endif /* _ZLIB_H */
lib/zlib_inflate/inffast.c +9 -9
diff -urp linux-2.6.23-rc6.bnx2/lib/zlib_inflate/inffast.c linux-2.6.23-rc6.bnx2_2/lib/zlib_inflate/inffast.c
@@ -69,22 +69,22 @@
 void inflate_fast(z_streamp strm, unsigned start)
 {
     struct inflate_state *state;
-    unsigned char *in;      /* local strm->next_in */
-    unsigned char *last;    /* while in < last, enough input available */
-    unsigned char *out;     /* local strm->next_out */
-    unsigned char *beg;     /* inflate()'s initial strm->next_out */
-    unsigned char *end;     /* while out < end, enough space available */
+    const unsigned char *in;    /* local strm->next_in */
+    const unsigned char *last;  /* while in < last, enough input available */
+    unsigned char *out;         /* local strm->next_out */
+    unsigned char *beg;         /* inflate()'s initial strm->next_out */
+    unsigned char *end;         /* while out < end, enough space available */
 #ifdef INFLATE_STRICT
     unsigned dmax;              /* maximum distance from zlib header */
 #endif
     unsigned wsize;             /* window size or zero if not using window */
     unsigned whave;             /* valid bytes in the window */
     unsigned write;             /* window write index */
-    unsigned char *window;  /* allocated sliding window, if wsize != 0 */
+    unsigned char *window;      /* allocated sliding window, if wsize != 0 */
     unsigned long hold;         /* local strm->hold */
     unsigned bits;              /* local strm->bits */
-    code const *lcode;      /* local strm->lencode */
-    code const *dcode;      /* local strm->distcode */
+    code const *lcode;          /* local strm->lencode */
+    code const *dcode;          /* local strm->distcode */
     unsigned lmask;             /* mask for first level of length codes */
     unsigned dmask;             /* mask for first level of distance codes */
     code this;                  /* retrieved table entry */
@@ -92,7 +92,7 @@ void inflate_fast(z_streamp strm, unsign
                                 /*  window position, window bytes to copy */
     unsigned len;               /* match length, unused bytes */
     unsigned dist;              /* match distance */
-    unsigned char *from;    /* where to copy match from */
+    unsigned char *from;        /* where to copy match from */
 
     /* copy state to local variables */
     state = (struct inflate_state *)strm->state;
lib/zlib_inflate/inflate.c +50 -4

74 lines not on this page · raw message

lib/zlib_inflate/inflate_syms.c +1 -0
diff -urp linux-2.6.23-rc6.bnx2/lib/zlib_inflate/inflate_syms.c linux-2.6.23-rc6.bnx2_2/lib/zlib_inflate/inflate_syms.c
@@ -16,4 +16,5 @@ EXPORT_SYMBOL(zlib_inflateInit2);
 EXPORT_SYMBOL(zlib_inflateEnd);
 EXPORT_SYMBOL(zlib_inflateReset);
 EXPORT_SYMBOL(zlib_inflateIncomp); 
+EXPORT_SYMBOL(zlib_inflate_blob);
 MODULE_LICENSE("GPL");
#28 lore raw
Quoted 6 lines · Denys Vlasenko

Please test these two patches.
I updated them according to your comments.

I've only tested patch #1. It worked after some minor modifications below.

Quoted 13 lines

plain text
document
attachment
(linux-2.6.23-
rc6.bnx2-1.patch)

drivers/net/bnx2.c bnx2_set_rx_mode(struct net_device *dev) · line 2774

Quoted 9 lines
drivers/net/bnx2.c +2 -3
@@ -2767,89 +2769,44 @@ bnx2_set_rx_mode(struct net_device *dev)
        spin_unlock_bh(&bp->phy_lock);
 }
 
-#define FW_BUF_SIZE    0x8000
-
+/* To be moved to generic lib/ */
 static int
-bnx2_gunzip_init(struct bnx2 *bp)
+bnx2_gunzip(void *gunzip_buf, unsigned sz, u8 *zbuf, int len, void **outbuf)

outbuf is no longer needed.

drivers/net/bnx2.c bnx2_set_rx_mode(struct net_device *dev) · line 2798

Quoted 4 lines
drivers/net/bnx2.c +4 -0
+       rc = zlib_inflateInit2(strm, -MAX_WBITS);
+       if (rc == Z_OK) {
+               rc = zlib_inflate(strm, Z_FINISH);
+               if (rc == Z_OK)

rc will always be Z_STREAM_END in this case since we provide a big enough gunzip_buf for the whole blob.

#29 lore raw
In reply to Michael Chan
Quoted 3 lines · Michael Chan

The bnx2 firmware changes quite frequently. A new driver quite often requires new firmware to work correctly. Splitting them up makes things difficult for the user.

sorry didn't check, what's the license of the firmware?

Quoted 2 lines

The firmware in tg3 is a lot more mature and I don't expect it to change. I think tg3 is better suited for using request_firmware().

well thanks that would help us a lot,
we have to strip the firmware for Debian for the upcoming Lenny release. as the shipping exception for the previous 2 releases will not be granted again. so a separate firmware would be great. also afaik only some boards need it. it is a pressing need for us as tg3 with stripped firmware of course doesn't build.

Signature · 1 line
maks
maintainer
#30 lore raw

From: maximilian attems <[email protected]>
Date: Wed, 19 Sep 2007 18:33:18 +0200

Quoted 1 line

we have to strip the firmware for Debian for the upcoming Lenny release.

Why do you "have to"? The vendor has given you explicit rights to distribute it:

* Firmware is:
* Derived from proprietary unpublished source code,
* Copyright (C) 2000-2003 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.

This whole firmware stripping thing in debian is beyond rediculious and only serves to hurt users.

#31 lore raw

hello dave,

i appreciate a lot your opinon, but please cool down. this is not a four spin on your beloved pipe. :)

Quoted 8 lines · David Miller

From: maximilian attems <[email protected]>
Date: Wed, 19 Sep 2007 18:33:18 +0200

Quoted 1 line

we have to strip the firmware for Debian for the upcoming Lenny release.

Why do you "have to"? The vendor has given you explicit rights to distribute it:

Quoted 7 lines

* Firmware is:
* Derived from proprietary unpublished source code,
* Copyright (C) 2000-2003 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.

afair the trouble is that it does not give permission to change unlike some other gpl or bsd licensed blob.
so it is dfsg non-free and not suitable for main distribution.

Quoted 2 lines

This whole firmware stripping thing in debian is beyond rediculious and only serves to hurt users.

i'm not of the d-legal department,
but seeing free firmwares would be cool.

Signature · 1 line
maks