linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
       [not found] <200101242123.NAA00986@pizda.ninka.net>
@ 2001-01-25  1:40 ` Andrew Morton
  2001-01-25 19:29   ` kuznet
  2001-01-25  9:29 ` David S. Miller
  1 sibling, 1 reply; 27+ messages in thread
From: Andrew Morton @ 2001-01-25  1:40 UTC (permalink / raw)
  To: David S. Miller; +Cc: linux-kernel

"David S. Miller" wrote:
> 
> I'm back from OZ, and to help deal with my sudden lack of Victoria
> Bitter,

aww.. Poor Dave.  I'll have an extra one for you.

> ...
> There is one critical failure I saw reported with zerocopy, where all
> transmits basically failed using a 3c59x card.  This indicates that
> our driver checks thought the 3c59x you had supported TX checksumming
> in hardware, when in fact it does not.

I've tested the latest zc patch on:

3c905   (10b7/9050)
3c905B  (10b7/9055)
3c905C  (10b7/9200)
3c590   (10b7/5900)

no problems.  I simply mounted an NFS server with rsize=wsize=8192
and read a few files - I assume this is sufficient?

I can test a 3c575 later today.

What I suggest we do here is to add a new flag to the per-device
table `HAS_HWCKSM' and use that to set the device capabilities,
rather than using the IS_CYCLONE stuff.  Then we can add cards
individually as confirmation comes in.

I do have a 200-line 3c59x patch banked up - it does the following:

- fixes some interface selection problems with 3c590/3c900's
- fixes a PAGE_SIZE memory leak which occurs each time the
  driver is unloaded (pci_free_consistent needed).
- fixes the 3c556B's PM-resume behaviour

So...  How to coordinate these diffs?  I'd propose that I implement
the HAS_HWCKSM thing, test zerocopy with it on the five NICs which
I have.  Then what?  Ask Linus to merge the non-zc parts?

-
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
       [not found] <200101242123.NAA00986@pizda.ninka.net>
  2001-01-25  1:40 ` [UPDATE] Zerocopy patches, against 2.4.1-pre10 Andrew Morton
@ 2001-01-25  9:29 ` David S. Miller
  1 sibling, 0 replies; 27+ messages in thread
From: David S. Miller @ 2001-01-25  9:29 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel


Andrew Morton writes:
 > What I suggest we do here is to add a new flag to the per-device
 > table `HAS_HWCKSM' and use that to set the device capabilities,
 > rather than using the IS_CYCLONE stuff.  Then we can add cards
 > individually as confirmation comes in.

This idea sounds just fine.

 > I do have a 200-line 3c59x patch banked up - it does the following:
...
 > So...  How to coordinate these diffs?  I'd propose that I implement
 > the HAS_HWCKSM thing, test zerocopy with it on the five NICs which
 > I have.  Then what?  Ask Linus to merge the non-zc parts?

I have a better idea.  Look, all the dev->features and flag names are
in the kernel tree already.  The only thing which hasn't propagated
which the driver will reference are the skb frag things.  This code
referencing the skb frags in the 3c59x hard_start_xmit method you can
just protect with #ifdef MAX_SKB_FRAGS or similar.  See?

Later,
David S. Miller
davem@redhat.com

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-25  1:40 ` [UPDATE] Zerocopy patches, against 2.4.1-pre10 Andrew Morton
@ 2001-01-25 19:29   ` kuznet
  2001-01-25 20:28     ` Ion Badulescu
                       ` (2 more replies)
  0 siblings, 3 replies; 27+ messages in thread
From: kuznet @ 2001-01-25 19:29 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel

Hello!

> no problems.  I simply mounted an NFS server with rsize=wsize=8192
> and read a few files - I assume this is sufficient?

This is orthogonal.

Only TCP uses this and you need not to do something special
to test it. Any TCP connection going through 3c tests it.


> rather than using the IS_CYCLONE stuff.  Then we can add cards
> individually as confirmation comes in.

Seems, you meaned opposite way. To add this flag to all the chips,
except for several, and to remove it as soon as it is "confirmed"
that it does not work. 8)

Also, please, reset the state. Until this snapshot, hw checksumming
did not work due to bugs in netfilter, so that all the reports about
failures to checksum are dubious.

Alexey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-25 19:29   ` kuznet
@ 2001-01-25 20:28     ` Ion Badulescu
  2001-01-25 20:36       ` kuznet
  2001-01-25 20:43     ` David S. Miller
  2001-01-26  1:27     ` Andrew Morton
  2 siblings, 1 reply; 27+ messages in thread
From: Ion Badulescu @ 2001-01-25 20:28 UTC (permalink / raw)
  To: kuznet; +Cc: linux-kernel, Andrew Morton

On Thu, 25 Jan 2001 22:29:14 +0300 (MSK), kuznet@ms2.inr.ac.ru wrote:
> Hello!
> 
>> no problems.  I simply mounted an NFS server with rsize=wsize=8192
>> and read a few files - I assume this is sufficient?
> 
> This is orthogonal.
> 
> Only TCP uses this and you need not to do something special
> to test it. Any TCP connection going through 3c tests it.

Well, yes and no. It's not quite orthogonal, because normally TCP
will never transmit fragmented packets, and it's precisely fragmented
packets that make the interesting case with a card that supports
hardware TCP/UDP checksums.

If the packets are not fragmented, then the card can just verify the
checksums and be done with it. However, with fragments, all it can
do is report a partial checksum to the driver and let the driver
(or the stack) combine those partial checksums into one complete
checksum once all fragments have arrived. At least that's what the
Starfire card does, maybe the 3com is different. :-)

Are we even bothering with the partial checksums at this point, or
are we falling back to CPU checksumming if the packet is fragmented?

And, on a related note: what's involved in making a driver
zerocopy-aware? I haven't looked too closely to the current patch,
but I was thinking of playing with the starfire driver, since I
have all the chipset docs..

Thanks,
Ion

-- 
  It is better to keep your mouth shut and be thought a fool,
            than to open it and remove all doubt.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-25 20:28     ` Ion Badulescu
@ 2001-01-25 20:36       ` kuznet
  0 siblings, 0 replies; 27+ messages in thread
From: kuznet @ 2001-01-25 20:36 UTC (permalink / raw)
  To: Ion Badulescu; +Cc: linux-kernel, andrewm

Hello!

> Starfire card does, maybe the 3com is different. :-)

3com _is_ different. 8)

I is not an issue, we do not make zerocopy on IP fragments.


> Are we even bothering with the partial checksums at this point, or
> are we falling back to CPU checksumming if the packet is fragmented?

Of course, we are not bothering.



> And, on a related note: what's involved in making a driver
> zerocopy-aware? I haven't looked too closely to the current patch,
> but I was thinking of playing with the starfire driver, since I
> have all the chipset docs..

Nothing especially clever. Gather plus checksumming, as described
in comment in linux/netdevice.h. Well, just look into one of existing
drivers: better, sunhme. 3com and acenic are too stupid to learn something.

Alexey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-25 19:29   ` kuznet
  2001-01-25 20:28     ` Ion Badulescu
@ 2001-01-25 20:43     ` David S. Miller
  2001-01-25 21:11       ` Ion Badulescu
  2001-01-25 21:14       ` David S. Miller
  2001-01-26  1:27     ` Andrew Morton
  2 siblings, 2 replies; 27+ messages in thread
From: David S. Miller @ 2001-01-25 20:43 UTC (permalink / raw)
  To: Ion Badulescu; +Cc: kuznet, linux-kernel, Andrew Morton


Ion Badulescu writes:
 > Well, yes and no. It's not quite orthogonal, because normally TCP
 > will never transmit fragmented packets, and it's precisely fragmented
 > packets that make the interesting case with a card that supports
 > hardware TCP/UDP checksums.

No it is not the interesting case for such cards.  I have a feeling
you have no idea what you are talking about or who you are speaking
to.  Alexey bascially implemented all of the zerocopy stuff in that
patch, so it's a good bet that he has a good idea what is orthogonal
or not.

 > If the packets are not fragmented, then the card can just verify the
 > checksums and be done with it. However, with fragments, all it can
 > do is report a partial checksum to the driver and let the driver
 > (or the stack) combine those partial checksums into one complete
 > checksum once all fragments have arrived. At least that's what the
 > Starfire card does, maybe the 3com is different. :-)

On transmit, on transmit, that's all that matters on the hardware side
with these changes, where the card does the checksumming for us.
We've supported receive checksum verification from the hardware
forever, long before these changes.

The only interesting new thing on receive is that we do not linearize
a fragmented packet before passing it on to UDP etc.  And this has
nothing to do with what the card can or cannot do, it is purely a
software issue.

 > And, on a related note: what's involved in making a driver
 > zerocopy-aware? I haven't looked too closely to the current patch,

When you look closely at the current patch, you will see exactly what
is required.  3 hardware drivers are ported there, and are to be used
as examples.

Later,
David S. Miller
davem@redhat.com
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-25 20:43     ` David S. Miller
@ 2001-01-25 21:11       ` Ion Badulescu
  2001-01-26 19:43         ` kuznet
  2001-01-29 22:02         ` David S. Miller
  2001-01-25 21:14       ` David S. Miller
  1 sibling, 2 replies; 27+ messages in thread
From: Ion Badulescu @ 2001-01-25 21:11 UTC (permalink / raw)
  To: David S. Miller; +Cc: kuznet, linux-kernel, Andrew Morton

On Thu, 25 Jan 2001, David S. Miller wrote:

>
> Ion Badulescu writes:
>  > Well, yes and no. It's not quite orthogonal, because normally TCP
>  > will never transmit fragmented packets, and it's precisely fragmented
>  > packets that make the interesting case with a card that supports
>  > hardware TCP/UDP checksums.
>
> No it is not the interesting case for such cards.  I have a feeling
> you have no idea what you are talking about or who you are speaking
> to.  Alexey bascially implemented all of the zerocopy stuff in that
> patch, so it's a good bet that he has a good idea what is orthogonal
> or not.

Wrong feeling. :-) No, I know who Alexey is and I think I know what I'm
talking about, too. We're just talking about different things, RX vs TX.

Obviously there isn't much we can do with fragmented packets on TX. If
only the IP people had learned from Ethernet people about a good place for
a CRC/csum...

> On transmit, on transmit, that's all that matters on the hardware side
> with these changes, where the card does the checksumming for us.
> We've supported receive checksum verification from the hardware
> forever, long before these changes.

Hmm, I must have missed the CHECKSUM_HW stuff. Mea culpa. Not that many
drivers use it at this time, I see a grand total of 2 (hamachi and hme) in
2.4.0 -- and yes I know who wrote the hme driver, too. :)

>  > And, on a related note: what's involved in making a driver
>  > zerocopy-aware? I haven't looked too closely to the current patch,
>
> When you look closely at the current patch, you will see exactly what
> is required.  3 hardware drivers are ported there, and are to be used
> as examples.

Ok.

I'm just wondering, if a card supports sg but *not* TX csum, is it worth
it to make use of sg? eepro100 falls into this category..

Thanks,
Ion

-- 
  It is better to keep your mouth shut and be thought a fool,
            than to open it and remove all doubt.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-25 20:43     ` David S. Miller
  2001-01-25 21:11       ` Ion Badulescu
@ 2001-01-25 21:14       ` David S. Miller
  2001-01-25 21:29         ` Steve Whitehouse
                           ` (3 more replies)
  1 sibling, 4 replies; 27+ messages in thread
From: David S. Miller @ 2001-01-25 21:14 UTC (permalink / raw)
  To: Ion Badulescu; +Cc: kuznet, linux-kernel, Andrew Morton


Ion Badulescu writes:
 > I'm just wondering, if a card supports sg but *not* TX csum, is it worth
 > it to make use of sg? eepro100 falls into this category..

No, not worth it for now.  In fact I'm going to mark that combination
(sg without csum) as illegal in the final zerocopy patch I end up
sending to Linus.

Later,
David S. Miller
davem@redhat.com
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-25 21:14       ` David S. Miller
@ 2001-01-25 21:29         ` Steve Whitehouse
  2001-01-31 16:04           ` Alan Cox
  2001-01-25 21:38         ` [UPDATE] Zerocopy patches, against 2.4.1-pre10 David S. Miller
                           ` (2 subsequent siblings)
  3 siblings, 1 reply; 27+ messages in thread
From: Steve Whitehouse @ 2001-01-25 21:29 UTC (permalink / raw)
  To: David S. Miller; +Cc: Ion Badulescu, kuznet, linux-kernel, Andrew Morton

Hi,

Do you mean that devices will not be able to indicate support of SG seperately
from hw checksum or that the IP zerocopy will simply ignore devices which
do not have both ?

DECnet assumes that the mac level checksum will detect all errors and does
not have a checksum of its own on data, so it would only need SG to benefit
from the zerocopy framework,

Steve.

> 
> 
> Ion Badulescu writes:
>  > I'm just wondering, if a card supports sg but *not* TX csum, is it worth
>  > it to make use of sg? eepro100 falls into this category..
> 
> No, not worth it for now.  In fact I'm going to mark that combination
> (sg without csum) as illegal in the final zerocopy patch I end up
> sending to Linus.
> 
> Later,
> David S. Miller
> davem@redhat.com
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> Please read the FAQ at http://www.tux.org/lkml/
> 

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-25 21:14       ` David S. Miller
  2001-01-25 21:29         ` Steve Whitehouse
@ 2001-01-25 21:38         ` David S. Miller
  2001-01-26  6:06         ` Ion Badulescu
  2001-01-26 13:13         ` David S. Miller
  3 siblings, 0 replies; 27+ messages in thread
From: David S. Miller @ 2001-01-25 21:38 UTC (permalink / raw)
  To: Steve Whitehouse; +Cc: Ion Badulescu, kuznet, linux-kernel, Andrew Morton


Steve Whitehouse writes:
 > Do you mean that devices will not be able to indicate support of SG seperately
 > from hw checksum or that the IP zerocopy will simply ignore devices which
 > do not have both ?

IP will ignore devices which do not have both.

 > DECnet assumes that the mac level checksum will detect all errors and does
 > not have a checksum of its own on data, so it would only need SG to benefit
 > from the zerocopy framework,

Which is just fine.

Later,
David S. Miller
davem@redhat.com
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-25 19:29   ` kuznet
  2001-01-25 20:28     ` Ion Badulescu
  2001-01-25 20:43     ` David S. Miller
@ 2001-01-26  1:27     ` Andrew Morton
  2 siblings, 0 replies; 27+ messages in thread
From: Andrew Morton @ 2001-01-26  1:27 UTC (permalink / raw)
  To: kuznet; +Cc: linux-kernel

kuznet@ms2.inr.ac.ru wrote:
> 
> Hello!
> 
> > no problems.  I simply mounted an NFS server with rsize=wsize=8192
> > and read a few files - I assume this is sufficient?
> 
> This is orthogonal.
> 
> Only TCP uses this and you need not to do something special
> to test it. Any TCP connection going through 3c tests it.

OK.

> > rather than using the IS_CYCLONE stuff.  Then we can add cards
> > individually as confirmation comes in.
> 
> Seems, you meaned opposite way. To add this flag to all the chips,
> except for several, and to remove it as soon as it is "confirmed"
> that it does not work. 8)

errr..  Well that certainly ensures we'll hear about it quickly :)

Problem is, some of these NICs are very rare, and the driver could
be broken for quite some time before we hear about it.  Months.

I think what I'd prefer to do is this:

In vortex_close() we _know_ whether the NIC is doing hardware checksumming,
so we can add:

	if (rx_csumhits && (dev->drv_flags&HAS_HWCKSM) == 0)
		printk("this NIC supports hardware checksums!  Please see <some URL>")

This will work well - people are quite helpful.

> Also, please, reset the state. Until this snapshot, hw checksumming
> did not work due to bugs in netfilter, so that all the reports about
> failures to checksum are dubious.

That's good to hear.

It's possible that some devices in the device table are marked
as Cyclone when in fact they're Boomerangs.  It's pretty confusing.
So these will support scatter/gather but not checksumming.

Using rx_csumhits should be reliable.  It's a global counter at
present - I'll make it per-device.

-
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-25 21:14       ` David S. Miller
  2001-01-25 21:29         ` Steve Whitehouse
  2001-01-25 21:38         ` [UPDATE] Zerocopy patches, against 2.4.1-pre10 David S. Miller
@ 2001-01-26  6:06         ` Ion Badulescu
  2001-01-26 13:13         ` David S. Miller
  3 siblings, 0 replies; 27+ messages in thread
From: Ion Badulescu @ 2001-01-26  6:06 UTC (permalink / raw)
  To: David S. Miller; +Cc: kuznet, linux-kernel

On Thu, 25 Jan 2001, David S. Miller wrote:

> Ion Badulescu writes:
>  > I'm just wondering, if a card supports sg but *not* TX csum, is it worth
>  > it to make use of sg? eepro100 falls into this category..
>
> No, not worth it for now.  In fact I'm going to mark that combination
> (sg without csum) as illegal in the final zerocopy patch I end up
> sending to Linus.

Well, in the meantime I've ported the starfire driver to the zerocopy
framework, it now takes almost full advantage of the card sg+csum
capabilities. The patch is attached; I'd appreciate it if you could
include it into the main zerocopy patch.

I've tested the new driver using a dual-port starfire, and it survived all
my attempts to kill it with fragmented TCP, UDP and ICMP. More testers
would be welcome, though.

BTW, it looks like not many people are using this driver: the original had
a bug which made it spit out one printk per Tx packet, which was *not*
funny. Also, the module could not be unloaded and reloaded, as it failed
to release some of its resources (Alan already has a fix for that)..

Thanks,
Ion

-- 
  It is better to keep your mouth shut and be thought a fool,
            than to open it and remove all doubt.

--------------------------------------------------
diff -urNX diff_kernel_excludes /usr/src/local/linux-2.4/drivers/net/starfire.c linux-2.4/drivers/net/starfire.c
--- /usr/src/local/linux-2.4/drivers/net/starfire.c	Fri Jan 12 12:52:48 2001
+++ linux-2.4/drivers/net/starfire.c	Thu Jan 25 21:23:18 2001
@@ -34,6 +34,10 @@

 	LK1.1.4 (jgarzik):
 	- Merge Becker version 1.03
+
+	LK1.2.0 (Ion Badulescu <ionut@cs.columbia.edu>)
+	- Support hardware Rx/Tx checksumming
+	- Add GFP firmware taken from Adaptec's Netware driver
 */

 /* These identify the driver base version and may not be removed. */
@@ -43,7 +47,7 @@
 " Updates and info at http://www.scyld.com/network/starfire.html\n";

 static const char version3[] =
-" (unofficial 2.4.x kernel port, version 1.1.4, August 10, 2000)\n";
+" (unofficial 2.4.x kernel port, version 1.2.0, January 25, 2001)\n";

 /* The user-configurable values.
    These may be modified when a driver module is loaded.*/
@@ -117,6 +121,8 @@
 #include <asm/bitops.h>
 #include <asm/io.h>

+#include "starfire_firmware.h"
+
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
 MODULE_PARM(max_interrupt_work, "i");
@@ -256,10 +262,10 @@
 	TxThreshold=0x500B0,
 	CompletionHiAddr=0x500B4, TxCompletionAddr=0x500B8,
 	RxCompletionAddr=0x500BC, RxCompletionQ2Addr=0x500C0,
-	CompletionQConsumerIdx=0x500C4,
+	CompletionQConsumerIdx=0x500C4, RxDMACtrl=0x500D0,
 	RxDescQCtrl=0x500D4, RxDescQHiAddr=0x500DC, RxDescQAddr=0x500E0,
 	RxDescQIdx=0x500E8, RxDMAStatus=0x500F0, RxFilterMode=0x500F4,
-	TxMode=0x55000,
+	TxMode=0x55000, TxGfpMem=0x58000, RxGfpMem=0x5a000,
 };

 /* Bits in the interrupt status/mask registers. */
@@ -288,8 +294,12 @@
 /* Completion queue entry.
    You must update the page allocation, init_ring and the shift count in rx()
    if using a larger format. */
+#define csum_rx_status
 struct rx_done_desc {
 	u32 status;					/* Low 16 bits is length. */
+#ifdef csum_rx_status
+	u32 status2;				/* Low 16 bits is csum */
+#endif
 #ifdef full_rx_status
 	u32 status2;
 	u16 vlanid;
@@ -307,8 +317,9 @@
 	u32 addr;
 };
 enum tx_desc_bits {
-	TxDescID=0xB1010000,		/* Also marks single fragment, add CRC.  */
-	TxDescIntr=0x08000000, TxRingWrap=0x04000000,
+	TxDescID=0xB0000000,
+	TxCRCEn=0x01000000, TxDescIntr=0x08000000,
+	TxRingWrap=0x04000000, TxCalTCP=0x02000000,
 };
 struct tx_done_report {
 	u32 status;					/* timestamp, index. */
@@ -318,9 +329,14 @@
 };

 #define PRIV_ALIGN	15 	/* Required alignment mask */
-struct ring_info {
+struct rx_ring_info {
+	struct sk_buff *skb;
+	dma_addr_t mapping;
+};
+struct tx_ring_info {
 	struct sk_buff *skb;
 	dma_addr_t mapping;
+	int len;
 };

 struct netdev_private {
@@ -330,8 +346,8 @@
 	dma_addr_t rx_ring_dma;
 	dma_addr_t tx_ring_dma;
 	/* The addresses of rx/tx-in-place skbuffs. */
-	struct ring_info rx_info[RX_RING_SIZE];
-	struct ring_info tx_info[TX_RING_SIZE];
+	struct rx_ring_info rx_info[RX_RING_SIZE];
+	struct tx_ring_info tx_info[TX_RING_SIZE];
 	/* Pointers to completion queues (full pages).  I should cache line pad..*/
 	u8 pad0[100];
 	struct rx_done_desc *rx_done_q;
@@ -435,6 +451,9 @@
 	printk(KERN_INFO "%s: %s at 0x%lx, ",
 		   dev->name, netdrv_tbl[chip_idx].name, ioaddr);

+	/* Starfire can do SG and TCP/UDP checksumming */
+	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+
 	/* Serial EEPROM reads are hidden by the hardware. */
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = readb(ioaddr + EEPROMCtrl + 20-i);
@@ -565,7 +584,7 @@
 	if (np->tx_done_q == 0)
 		np->tx_done_q = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->tx_done_q_dma);
 	if (np->rx_done_q == 0)
-		np->rx_done_q = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->rx_done_q_dma);
+		np->rx_done_q = pci_alloc_consistent(np->pci_dev, sizeof(struct rx_done_desc) * DONE_Q_SIZE, &np->rx_done_q_dma);
 	if (np->tx_ring == 0)
 		np->tx_ring = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->tx_ring_dma);
 	if (np->rx_ring == 0)
@@ -576,7 +595,7 @@
 			pci_free_consistent(np->pci_dev, PAGE_SIZE,
 								np->tx_done_q, np->tx_done_q_dma);
 		if (np->rx_done_q)
-			pci_free_consistent(np->pci_dev, PAGE_SIZE,
+			pci_free_consistent(np->pci_dev, sizeof(struct rx_done_desc) * DONE_Q_SIZE,
 								np->rx_done_q, np->rx_done_q_dma);
 		if (np->tx_ring)
 			pci_free_consistent(np->pci_dev, PAGE_SIZE,
@@ -591,6 +610,8 @@
 	init_ring(dev);
 	/* Set the size of the Rx buffers. */
 	writel((np->rx_buf_sz<<16) | 0xA000, ioaddr + RxDescQCtrl);
+	/* Make the card reject bad csum TCP/UDP packets */
+	writel(0x03000604, ioaddr + RxDMACtrl);

 	/* Set Tx descriptor to type 1 and padding to 0 bytes. */
 	writel(0x02000401, ioaddr + TxDescCtrl);
@@ -608,7 +629,15 @@
 	writel(np->tx_ring_dma, ioaddr + TxRingPtr);

 	writel(np->tx_done_q_dma, ioaddr + TxCompletionAddr);
+#ifdef full_rx_status
+	writel(np->rx_done_q_dma | 0x30, ioaddr + RxCompletionAddr);
+#else
+#ifdef csum_rx_status
+	writel(np->rx_done_q_dma | 0x20, ioaddr + RxCompletionAddr);
+#else
 	writel(np->rx_done_q_dma, ioaddr + RxCompletionAddr);
+#endif
+#endif

 	if (debug > 1)
 		printk(KERN_DEBUG "%s:  Filling in the station address.\n", dev->name);
@@ -651,8 +680,13 @@
 	writel(0x00800000 | readl(ioaddr + PCIDeviceConfig),
 		   ioaddr + PCIDeviceConfig);

-	/* Enable the Rx and Tx units. */
-	writel(0x000F, ioaddr + GenCtrl);
+	/* Load Rx/Tx firmware into the frame processors */
+	for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
+		writel(cpu_to_le32(firmware_rx[i]), ioaddr + RxGfpMem + i * 4);
+	for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
+		writel(cpu_to_le32(firmware_tx[i]), ioaddr + TxGfpMem + i * 4);
+	/* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
+	writel(0x003F, ioaddr + GenCtrl);

 	if (debug > 2)
 		printk(KERN_DEBUG "%s: Done netdev_open().\n",
@@ -806,6 +840,7 @@
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		np->tx_info[i].skb = NULL;
 		np->tx_info[i].mapping = 0;
+		np->tx_info[i].len = 0;
 		np->tx_ring[i].status = 0;
 	}
 	return;
@@ -814,50 +849,79 @@
 static int start_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
-	unsigned entry;
+	unsigned entry, old_entry;
+	int frag;

 	/* Caution: the write order is important here, set the field
 	   with the "ownership" bits last. */

+	if (np->cur_tx + skb_shinfo(skb)->nr_frags - np->dirty_tx >= TX_RING_SIZE - 1) {
+		np->tx_full = 1;
+		netif_stop_queue(dev);
+		return 1;
+	}
+
 	/* Calculate the next Tx descriptor entry. */
-	entry = np->cur_tx % TX_RING_SIZE;
+	old_entry = entry = np->cur_tx % TX_RING_SIZE;

-	np->tx_info[entry].skb = skb;
+	if (skb_shinfo(skb)->nr_frags == 0)
+		np->tx_info[entry].skb = skb;
+	np->tx_info[entry].len = skb_headlen(skb);
 	np->tx_info[entry].mapping =
-		pci_map_single(np->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
+		pci_map_single(np->pci_dev, skb->data, np->tx_info[entry].len, PCI_DMA_TODEVICE);

 	np->tx_ring[entry].addr = cpu_to_le32(np->tx_info[entry].mapping);
 	/* Add  "| TxDescIntr" to generate Tx-done interrupts. */
-	np->tx_ring[entry].status = cpu_to_le32(skb->len | TxDescID);
+	np->tx_ring[entry].status = cpu_to_le32(np->tx_info[entry].len | TxDescID | TxCRCEn);
+	np->tx_ring[entry].status |= cpu_to_le32((skb_shinfo(skb)->nr_frags + 1) << 16);
+
+	if (skb->ip_summed == CHECKSUM_HW)
+		np->tx_ring[entry].status |= cpu_to_le32(TxCalTCP);
+
+	if (entry + skb_shinfo(skb)->nr_frags >= TX_RING_SIZE-1) {		 /* Wrap ring */
+		np->tx_ring[entry].status |= cpu_to_le32(TxRingWrap | TxDescIntr);
+		entry = -1;
+	}
+
 	if (debug > 5) {
 		printk(KERN_DEBUG "%s: Tx #%d slot %d  %8.8x %8.8x.\n",
-			   dev->name, np->cur_tx, entry,
-			   le32_to_cpu(np->tx_ring[entry].status),
-			   le32_to_cpu(np->tx_ring[entry].addr));
+			   dev->name, np->cur_tx, old_entry,
+			   le32_to_cpu(np->tx_ring[old_entry].status),
+			   le32_to_cpu(np->tx_ring[old_entry].addr));
 	}
+
 	np->cur_tx++;
-#if 1
-	if (entry >= TX_RING_SIZE-1) {		 /* Wrap ring */
-		np->tx_ring[entry].status |= cpu_to_le32(TxRingWrap | TxDescIntr);
-		entry = -1;
-	}
-#endif

 	/* Non-x86: explicitly flush descriptor cache lines here. */

 	/* Update the producer index. */
 	writel(++entry, dev->base_addr + TxProducerIdx);

-	if (np->cur_tx - np->dirty_tx >= TX_RING_SIZE - 1) {
-		np->tx_full = 1;
-		netif_stop_queue(dev);
+	for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
+		skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
+
+		/* we already have the proper value in entry */
+		if (skb_shinfo(skb)->nr_frags == frag + 1)
+			np->tx_info[entry].skb = skb;
+		np->tx_info[entry].mapping =
+			pci_map_single(np->pci_dev, page_address(this_frag->page) + this_frag->page_offset, this_frag->size, PCI_DMA_TODEVICE);
+		np->tx_info[entry].len = this_frag->size;
+
+		np->tx_ring[entry].addr = cpu_to_le32(np->tx_info[entry].mapping);
+		np->tx_ring[entry].status = cpu_to_le32(this_frag->size | TxDescID);
+		if (debug > 5) {
+			printk(KERN_DEBUG "%s: Tx #%d slot %d  %8.8x %8.8x.\n",
+				   dev->name, np->cur_tx, entry,
+				   le32_to_cpu(np->tx_ring[entry].status),
+				   le32_to_cpu(np->tx_ring[entry].addr));
+		}
+		np->cur_tx++;
+		/* Update the producer index. */
+		writel(++entry, dev->base_addr + TxProducerIdx);
 	}
+
 	dev->trans_start = jiffies;

-	if (debug > 4) {
-		printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n",
-			   dev->name, np->cur_tx, entry);
-	}
 	return 0;
 }

@@ -923,15 +987,18 @@
 					u16 entry = tx_status; 		/* Implicit truncate */
 					entry >>= 3;

-					skb = np->tx_info[entry].skb;
 					pci_unmap_single(np->pci_dev,
-							 np->tx_info[entry].mapping,
-							 skb->len, PCI_DMA_TODEVICE);
-
-					/* Scavenge the descriptor. */
-					dev_kfree_skb_irq(skb);
-					np->tx_info[entry].skb = NULL;
+									 np->tx_info[entry].mapping,
+									 np->tx_info[entry].len, PCI_DMA_TODEVICE);
 					np->tx_info[entry].mapping = 0;
+					np->tx_info[entry].len = 0;
+
+					skb = np->tx_info[entry].skb;
+					if (skb != NULL) {
+						/* Scavenge the descriptor. */
+						dev_kfree_skb_irq(skb);
+						np->tx_info[entry].skb = NULL;
+					}
 					np->dirty_tx++;
 				}
 				np->tx_done_q[np->tx_done].status = 0;
@@ -1038,14 +1105,16 @@
 				temp = skb_put(skb, pkt_len);
 				np->rx_info[entry].skb = NULL;
 				np->rx_info[entry].mapping = 0;
+#if 0
 #ifndef final_version				/* Remove after testing. */
-				if (le32_to_cpu(np->rx_ring[entry].rxaddr & ~3) != ((unsigned long) temp))
+				if ((le32_to_cpu(np->rx_ring[entry].rxaddr) & ~3) != ((unsigned long) temp))
 					printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
-						   "do not match in netdev_rx: %d vs. %p / %p.\n",
+						   "do not match in netdev_rx: %x vs. %p / %p.\n",
 						   dev->name,
 						   le32_to_cpu(np->rx_ring[entry].rxaddr),
 						   skb->head, temp);
 #endif
+#endif
 			}
 #ifndef final_version				/* Remove after testing. */
 			/* You will want this info for the initial debug. */
@@ -1061,9 +1130,23 @@
 					   skb->data[17]);
 #endif
 			skb->protocol = eth_type_trans(skb, dev);
-#ifdef full_rx_status
-			if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x01000000)
+#if defined(full_rx_status) || defined(csum_rx_status)
+			if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x01000000) {
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
+			}
+			/*
+			 * This feature doesn't seem to be working, at least
+			 * with the two firmware versions I have. If the GFP sees
+			 * a fragment, it either ignores it completely, or reports
+			 * "bad checksum" on it.
+			 *
+			 * Maybe I missed something -- corrections are welcome. -Ion
+			 */
+			else if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x00400000) {
+				skb->ip_summed = CHECKSUM_HW;
+				skb->csum = le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0xffff;
+				printk(KERN_DEBUG "sf: checksum_hw, status2 = %x\n", np->rx_done_q[np->rx_done].status2);
+			}
 #endif
 			netif_rx(skb);
 			dev->last_rx = jiffies;
@@ -1340,6 +1423,7 @@
 		}
 		np->tx_info[i].skb = NULL;
 		np->tx_info[i].mapping = 0;
+		np->tx_info[i].len = 0;
 	}

 	MOD_DEC_USE_COUNT;
diff -urNX diff_kernel_excludes /usr/src/local/linux-2.4/drivers/net/starfire_firmware.h linux-2.4/drivers/net/starfire_firmware.h
--- /usr/src/local/linux-2.4/drivers/net/starfire_firmware.h	Wed Dec 31 16:00:00 1969
+++ linux-2.4/drivers/net/starfire_firmware.h	Thu Jan 25 21:43:27 2001
@@ -0,0 +1,215 @@
+static u32 firmware_rx[] = {
+  0x010003dc, 0x00000000,
+  0x04000421, 0x00000086,
+  0x80000015, 0x0000180e,
+  0x81000015, 0x00006664,
+  0x1a0040ab, 0x00000b06,
+  0x14200011, 0x00000000,
+  0x14204022, 0x0000aaaa,
+  0x14204022, 0x00000300,
+  0x14204022, 0x00000000,
+  0x1a0040ab, 0x00000b14,
+  0x14200011, 0x00000000,
+  0x83000015, 0x00000002,
+  0x04000021, 0x00000000,
+  0x00000010, 0x00000000,
+  0x04000421, 0x00000087,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00008015, 0x00000000,
+  0x0000003e, 0x00000000,
+  0x00000010, 0x00000000,
+  0x82000015, 0x00004000,
+  0x009e8050, 0x00000000,
+  0x03008015, 0x00000000,
+  0x86008015, 0x00000000,
+  0x82000015, 0x00008000,
+  0x0100001c, 0x00000000,
+  0x000050a0, 0x0000010c,
+  0x4e20d011, 0x00006008,
+  0x1420d012, 0x00004008,
+  0x0000f090, 0x00007000,
+  0x0000c8b0, 0x00003000,
+  0x00004040, 0x00000000,
+  0x00108015, 0x00000000,
+  0x00a2c150, 0x00004000,
+  0x00a400b0, 0x00000014,
+  0x00000020, 0x00000000,
+  0x2500400d, 0x00002525,
+  0x00047220, 0x00003100,
+  0x00934070, 0x00000000,
+  0x00000020, 0x00000000,
+  0x00924460, 0x00000184,
+  0x2b20c011, 0x00000000,
+  0x0000c420, 0x00000540,
+  0x36014018, 0x0000422d,
+  0x14200011, 0x00000000,
+  0x00924460, 0x00000183,
+  0x3200001f, 0x00000034,
+  0x02ac0015, 0x00000002,
+  0x00a60110, 0x00000008,
+  0x42200011, 0x00000000,
+  0x00924060, 0x00000103,
+  0x0000001e, 0x00000000,
+  0x00000020, 0x00000100,
+  0x0000001e, 0x00000000,
+  0x00924460, 0x00000086,
+  0x00004080, 0x00000000,
+  0x0092c070, 0x00000000,
+  0x00924060, 0x00000100,
+  0x0000c890, 0x00005000,
+  0x00a6c110, 0x00000000,
+  0x00b0c090, 0x00000012,
+  0x021c0015, 0x00000000,
+  0x3200001f, 0x00000034,
+  0x00924460, 0x00000510,
+  0x44210011, 0x00000000,
+  0x42000011, 0x00000000,
+  0x83000015, 0x00000040,
+  0x00924460, 0x00000508,
+  0x45014018, 0x00004545,
+  0x00808050, 0x00000000,
+  0x83000015, 0x00000040,
+  0x62208012, 0x00000000,
+  0x82000015, 0x00000800,
+  0x15200011, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x80000015, 0x0000eea4,
+  0x81000015, 0x0000005f,
+  0x00000060, 0x00000000,
+  0x00004120, 0x00000000,
+  0x00004a00, 0x00004000,
+  0x00924460, 0x00000190,
+  0x5601401a, 0x00005956,
+  0x14000011, 0x00000000,
+  0x00934050, 0x00000018,
+  0x00930050, 0x00000018,
+  0x3601403a, 0x0000002d,
+  0x000643a9, 0x00000000,
+  0x0000c420, 0x00000140,
+  0x5601401a, 0x00005956,
+  0x14000011, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x000642a9, 0x00000000,
+  0x00024420, 0x00000183,
+  0x5601401a, 0x00005956,
+  0x82000015, 0x00002000,
+  0x15200011, 0x00000000,
+  0x82000015, 0x00000010,
+  0x15200011, 0x00000000,
+  0x82000015, 0x00000010,
+  0x15200011, 0x00000000,
+};	/* 104 Rx instructions */
+#define FIRMWARE_RX_SIZE 104
+
+static u32 firmware_tx[] = {
+  0x010003dc, 0x00000000,
+  0x04000421, 0x00000086,
+  0x80000015, 0x0000180e,
+  0x81000015, 0x00006664,
+  0x1a0040ab, 0x00000b06,
+  0x14200011, 0x00000000,
+  0x14204022, 0x0000aaaa,
+  0x14204022, 0x00000300,
+  0x14204022, 0x00000000,
+  0x1a0040ab, 0x00000b14,
+  0x14200011, 0x00000000,
+  0x83000015, 0x00000002,
+  0x04000021, 0x00000000,
+  0x00000010, 0x00000000,
+  0x14204022, 0x0000000c,
+  0x04000421, 0x00000087,
+  0x00000010, 0x00000000,
+  0x00008015, 0x00000000,
+  0x0000003e, 0x00000000,
+  0x00000010, 0x00000000,
+  0x82000015, 0x00004000,
+  0x009e8050, 0x00000000,
+  0x03008015, 0x00000000,
+  0x86008015, 0x00000000,
+  0x82000015, 0x00008000,
+  0x0100001c, 0x00000000,
+  0x000050a0, 0x0000010c,
+  0x4e20d011, 0x00006008,
+  0x1420d012, 0x00004008,
+  0x0000f090, 0x00007000,
+  0x0000c8b0, 0x00003000,
+  0x00004040, 0x00000000,
+  0x00108015, 0x00000000,
+  0x00a2c150, 0x00004000,
+  0x00a400b0, 0x00000014,
+  0x00000020, 0x00000000,
+  0x2500400d, 0x00002525,
+  0x00047220, 0x00003100,
+  0x00934070, 0x00000000,
+  0x00000020, 0x00000000,
+  0x00924460, 0x00000184,
+  0x2b20c011, 0x00000000,
+  0x0000c420, 0x00000540,
+  0x36014018, 0x00004b2d,
+  0x14200011, 0x00000000,
+  0x00924460, 0x00000183,
+  0x3200001f, 0x00000034,
+  0x02ac0015, 0x00000002,
+  0x00a60110, 0x00000008,
+  0x42200011, 0x00000000,
+  0x00924060, 0x00000103,
+  0x0000001e, 0x00000000,
+  0x00000020, 0x00000100,
+  0x0000001e, 0x00000000,
+  0x00924460, 0x00000086,
+  0x00004080, 0x00000000,
+  0x0092c070, 0x00000000,
+  0x00924060, 0x00000100,
+  0x0000c890, 0x00005000,
+  0x00a6c110, 0x00000000,
+  0x00b0c090, 0x00000012,
+  0x021c0015, 0x00000000,
+  0x3200001f, 0x00000034,
+  0x00924460, 0x00000510,
+  0x45210011, 0x00000000,
+  0x42000011, 0x00000000,
+  0x43014018, 0x00004343,
+  0x83000015, 0x00000040,
+  0x00924460, 0x00000508,
+  0x00808050, 0x00000000,
+  0x62208012, 0x00000000,
+  0x82000015, 0x00000800,
+  0x15200011, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000050, 0x00000000,
+  0x00070050, 0x00000000,
+  0x36014018, 0x0000422d,
+  0x80000015, 0x0000eea4,
+  0x81000015, 0x0000005f,
+  0x00000060, 0x00000000,
+  0x00004120, 0x00000000,
+  0x00004a00, 0x00004000,
+  0x00924460, 0x00000190,
+  0x5601401a, 0x00005956,
+  0x14000011, 0x00000000,
+  0x00934050, 0x00000018,
+  0x00930050, 0x00000018,
+  0x3601403a, 0x0000002d,
+  0x000643a9, 0x00000000,
+  0x0000c420, 0x00000140,
+  0x5601401a, 0x00005956,
+  0x14000011, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x000642a9, 0x00000000,
+  0x00024420, 0x00000183,
+  0x5601401a, 0x00005956,
+  0x82000015, 0x00002000,
+  0x15200011, 0x00000000,
+  0x82000015, 0x00000010,
+  0x15200011, 0x00000000,
+  0x82000015, 0x00000010,
+  0x15200011, 0x00000000,
+};	/* 104 Tx instructions */
+#define FIRMWARE_TX_SIZE 104
diff -urNX diff_kernel_excludes /usr/src/local/linux-2.4/drivers/net/starfire_firmware.pl linux-2.4/drivers/net/starfire_firmware.pl
--- /usr/src/local/linux-2.4/drivers/net/starfire_firmware.pl	Wed Dec 31 16:00:00 1969
+++ linux-2.4/drivers/net/starfire_firmware.pl	Thu Jan 25 21:43:27 2001
@@ -0,0 +1,31 @@
+#!/usr/bin/perl
+
+# This script can be used to generate a new starfire_firmware.h
+# from GFP_RX.DAT and GFP_TX.DAT, files included with the DDK
+# and also with the Novell drivers.
+
+open FW, "GFP_RX.DAT" || die;
+open FWH, ">starfire_firmware.h" || die;
+
+printf(FWH "static u32 firmware_rx[] = {\n");
+$counter = 0;
+while ($foo = <FW>) {
+  chomp;
+  printf(FWH "  0x%s, 0x0000%s,\n", substr($foo, 4, 8), substr($foo, 0, 4));
+  $counter++;
+}
+
+close FW;
+open FW, "GFP_TX.DAT" || die;
+
+printf(FWH "};\t/* %d Rx instructions */\n#define FIRMWARE_RX_SIZE %d\n\nstatic u32 firmware_tx[] = {\n", $counter, $counter);
+$counter = 0;
+while ($foo = <FW>) {
+  chomp;
+  printf(FWH "  0x%s, 0x0000%s,\n", substr($foo, 4, 8), substr($foo, 0, 4));
+  $counter++;
+}
+
+close FW;
+printf(FWH "};\t/* %d Tx instructions */\n#define FIRMWARE_TX_SIZE %d\n", $counter, $counter);
+close(FWH);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-25 21:14       ` David S. Miller
                           ` (2 preceding siblings ...)
  2001-01-26  6:06         ` Ion Badulescu
@ 2001-01-26 13:13         ` David S. Miller
  2001-01-26 20:43           ` Ion Badulescu
  3 siblings, 1 reply; 27+ messages in thread
From: David S. Miller @ 2001-01-26 13:13 UTC (permalink / raw)
  To: Ion Badulescu; +Cc: kuznet, linux-kernel


Ion Badulescu writes:
 > Well, in the meantime I've ported the starfire driver to the zerocopy
 > framework, it now takes almost full advantage of the card sg+csum
 > capabilities. The patch is attached; I'd appreciate it if you could
 > include it into the main zerocopy patch.

Great, some commentary, see below.

 > BTW, it looks like not many people are using this driver: the original had
 > a bug which made it spit out one printk per Tx packet, which was *not*
 > funny. Also, the module could not be unloaded and reloaded, as it failed
 > to release some of its resources (Alan already has a fix for that)..

Indeed.

Firstly, I would not configure the card to drop packets with bad
checksums.  If you do this, the errors do not propagate into the
correct ipv4 snmp tables, which is bad.  Also consider the case where
the card has some bug and it erroneously verifies rx checksums in some
strange cases, we would be hard pressed to find out with how you are
configuring it in this way.

Next, please remove the unconditional:

+				printk(KERN_DEBUG "sf: checksum_hw, status2 = %x\n", np->rx_done_q[np->rx_done].status2);

or at the very least make it print out netdev->name instead of the
cryptic "sf: " prefix.

Finally, what are the listed distribution terms of this firmware?
I want to make sure it is legal to distribute it.

Deal with these three issues, and I'll stick this into my zerocopy
patch sets.  Thanks again.

Later,
David S. Miller
davem@redhat.com
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-25 21:11       ` Ion Badulescu
@ 2001-01-26 19:43         ` kuznet
  2001-01-29 22:02         ` David S. Miller
  1 sibling, 0 replies; 27+ messages in thread
From: kuznet @ 2001-01-26 19:43 UTC (permalink / raw)
  To: Ion Badulescu, Dave Miller; +Cc: linux-kernel

Hello!

> drivers use it at this time, I see a grand total of 2 (hamachi and hme) in

Plus acenic in zerocopy.
Plus patch to do this is available for eepro100.


> I'm just wondering, if a card supports sg but *not* TX csum, is it worth
> it to make use of sg? eepro100 falls into this category..

This is simply not permitted just now.

Mea culpa...

Dave, seems, it is better to repair this. Code really assumes
that SG cannot be used without one of CSUM flags...

Actually, drivers which are able to SG without checksumming
should do this. Even though just this minute this feature
has no applications. Next minute it will. Not only with decnet,
but for IP too.

Alexey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-26 13:13         ` David S. Miller
@ 2001-01-26 20:43           ` Ion Badulescu
  2001-01-27  0:55             ` Ion Badulescu
  0 siblings, 1 reply; 27+ messages in thread
From: Ion Badulescu @ 2001-01-26 20:43 UTC (permalink / raw)
  To: David S. Miller; +Cc: kuznet, linux-kernel

On Fri, 26 Jan 2001, David S. Miller wrote:

> Firstly, I would not configure the card to drop packets with bad
> checksums.  If you do this, the errors do not propagate into the
> correct ipv4 snmp tables, which is bad.  Also consider the case where
> the card has some bug and it erroneously verifies rx checksums in some
> strange cases, we would be hard pressed to find out with how you are
> configuring it in this way.

Ok. Makes sense. Consider it done.

> Next, please remove the unconditional:
>
> +				printk(KERN_DEBUG "sf: checksum_hw, status2 = %x\n", np->rx_done_q[np->rx_done].status2);
>
> or at the very least make it print out netdev->name instead of the
> cryptic "sf: " prefix.

I'll change the prefix, but I want to leave it there, because it never
triggered in my testing. And I'd really like it to annoy people so much
when it does trigger, that they report it back. :-)

> Finally, what are the listed distribution terms of this firmware?
> I want to make sure it is legal to distribute it.

Hmm, that's a very good question. I got the two firmware files from
Adaptec's Netware driver, and there is nothing in the archive or in those
files even remotely similar to a license or distribution terms. I guess
the best way to go about it would be to get an official answer from
Adaptec. Is there anybody out there with some Adaptec contacts who is
willing to step in and help with this?

In any case, I have the architecture description and instruction set of
the frame processor, so in the worst case I could simply reimplement the
code. It wouldn't be much different than the Adaptec aic7xxx sequencer
case.

Besides, I've done some more testing last night, and there are some
problems. The FP doesn't seem to like tinygrams too much, every once in a
while (but *not* always) it decides to send one with a bad checksum. I'm
talking especially about telnet tinygrams, where the second fragment is 1
byte. What's worse, it will also resend it with a bad checksum,
effectively killing the connection.

Could this be a bug in the upper layers, instead? How would I go about to
verify this? The only way I can think of is to verify that the checksum
field is zero initially, correct?

Also, after putting some more stress on the card, I managed to get it to
generate an abnormal interrupt (the "Something Wicked happened" thing),
and the error code translates to "GFP unable to calculate the checksum
(???) or not responding for 16 transmit cycles". And, since the reset
procedure is not implemented in the driver, this is quite deadly.

So I want to try and switch the transmit descriptor to the one used by
Netware, maybe the firmware was only tested with that descriptor. It also
fits the new Linux model a bit better, as it has one descriptor per
packet, not one per fragment (like the current implementation).

Thanks,
Ion

-- 
  It is better to keep your mouth shut and be thought a fool,
            than to open it and remove all doubt.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-26 20:43           ` Ion Badulescu
@ 2001-01-27  0:55             ` Ion Badulescu
  2001-01-27 18:39               ` kuznet
  0 siblings, 1 reply; 27+ messages in thread
From: Ion Badulescu @ 2001-01-27  0:55 UTC (permalink / raw)
  To: David S. Miller; +Cc: kuznet, linux-kernel

On Fri, 26 Jan 2001, Ion Badulescu wrote:

> Besides, I've done some more testing last night, and there are some
> problems. The FP doesn't seem to like tinygrams too much, every once in a
> while (but *not* always) it decides to send one with a bad checksum. I'm
> talking especially about telnet tinygrams, where the second fragment is 1
> byte. What's worse, it will also resend it with a bad checksum,
> effectively killing the connection.
>
> Could this be a bug in the upper layers, instead? How would I go about to
> verify this? The only way I can think of is to verify that the checksum
> field is zero initially, correct?

[...]

> So I want to try and switch the transmit descriptor to the one used by
> Netware, maybe the firmware was only tested with that descriptor. It also
> fits the new Linux model a bit better, as it has one descriptor per
> packet, not one per fragment (like the current implementation).

So, I've re-implemented the Tx code to use the type0 Tx descriptor, and
the code is definitely cleaner. However, the card still has an issue with
tinygrams. A TCP packet whose second fragment is 1-byte long usually goes
over the wire with the wrong checksum. If the second fragment is 3-byte
long, it is checksummed correctly (so it's not an even/odd problem).

Any ideas? Is there even the slightest chance that something might not be
ok in the skb received from above?

Thanks,
Ion

-- 
  It is better to keep your mouth shut and be thought a fool,
            than to open it and remove all doubt.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-27  0:55             ` Ion Badulescu
@ 2001-01-27 18:39               ` kuznet
  2001-01-27 21:18                 ` Ion Badulescu
  2001-01-30  6:02                 ` David S. Miller
  0 siblings, 2 replies; 27+ messages in thread
From: kuznet @ 2001-01-27 18:39 UTC (permalink / raw)
  To: Ion Badulescu; +Cc: davem, linux-kernel

Hello!

> verify this? The only way I can think of is to verify that the checksum
> field is zero initially, correct?

It is not zero. It contains checksum of pseudoheader.


> fits the new Linux model a bit better, as it has one descriptor per
> packet, not one per fragment (like the current implementation).

Yes. Absence of such mode with acenic is big pain in ass.


> tinygrams. A TCP packet whose second fragment is 1-byte long usually goes
> over the wire with the wrong checksum. If the second fragment is 3-byte
> long, it is checksummed correctly (so it's not an even/odd problem).

Seems, this is pretty common bug. At least, perfect checksumming
of chunks with any size and alignment is so big boast of
alteon people, that it is clearly rather exception than rule. 8)8)

I think you have to check for wrong combination of alignment/size and
to call skb_checksum_help() and to disable checksumming if combination
is bad.

Alexey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-27 18:39               ` kuznet
@ 2001-01-27 21:18                 ` Ion Badulescu
  2001-01-30  6:02                 ` David S. Miller
  1 sibling, 0 replies; 27+ messages in thread
From: Ion Badulescu @ 2001-01-27 21:18 UTC (permalink / raw)
  To: kuznet; +Cc: davem, linux-kernel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 2173 bytes --]

Hi Alexey,

On Sat, 27 Jan 2001 kuznet@ms2.inr.ac.ru wrote:

> > fits the new Linux model a bit better, as it has one descriptor per
> > packet, not one per fragment (like the current implementation).
>
> Yes. Absence of such mode with acenic is big pain in ass.

And, at least for the starfire, using buffer descriptors eats up more
resources than using packet descriptors. So buffer descriptors are gone,
forever.

> Seems, this is pretty common bug. At least, perfect checksumming
> of chunks with any size and alignment is so big boast of
> alteon people, that it is clearly rather exception than rule. 8)8)

Oh well. Don't we wish hardware were perfect.. :-)

It's not too bad for the starfire, either, as it doesn't appear to suffer
from any alignment issues, and the only fragments it has problem with are
1-byte fragments (2-byte and larger are ok). And I'm still hoping that
Adaptec will release updated firmware (and that they will also approve the
inclusion of their firmware with the Linux driver).

If they don't approve it, maybe I'll add a config option so that the user
can download their own copy of the firmware from Adaptec's site, place it
in /etc somewhere, give the location to the driver and have the driver
open the files from kernel space and process them. It would be ugly
though, and a big PITA.

> I think you have to check for wrong combination of alignment/size and
> to call skb_checksum_help() and to disable checksumming if combination
> is bad.

Good, thanks a lot for the pointer. Maybe I went a bit overboard with my
fix, as I revert to CPU checksumming if *any* fragment (not just the last
one in the chain) has only 1 byte. But it seems to work well now.

I've attached a diff for the latest driver (and firmware) version, against
2.4.1pre10+zerocopy. Sorry about MIME, but my pine is currently broken
(strips trailing spaces/tabs).

And, one final question: is it worth it for me to extract just the Rx
checksumming changes and send them to Linux/Alan, or should I just wait
for zerocopy to be included?

Thanks,
Ion

-- 
  It is better to keep your mouth shut and be thought a fool,
            than to open it and remove all doubt.

[-- Attachment #2: Type: TEXT/PLAIN, Size: 29627 bytes --]

diff -urNX diff_kernel_excludes /usr/src/local/linux-2.4.vanilla/drivers/net/starfire.c linux-2.4/drivers/net/starfire.c
--- /usr/src/local/linux-2.4.vanilla/drivers/net/starfire.c	Fri Aug 11 15:57:58 2000
+++ linux-2.4/drivers/net/starfire.c	Sat Jan 27 12:44:35 2001
@@ -34,6 +34,10 @@
 	
 	LK1.1.4 (jgarzik):
 	- Merge Becker version 1.03
+
+	LK1.2.0 (Ion Badulescu <ionut@cs.columbia.edu>)
+	- Support hardware Rx/Tx checksumming
+	- Add GFP firmware taken from Adaptec's Netware driver
 */
 
 /* These identify the driver base version and may not be removed. */
@@ -43,11 +47,17 @@
 " Updates and info at http://www.scyld.com/network/starfire.html\n";
 
 static const char version3[] =
-" (unofficial 2.4.x kernel port, version 1.1.4, August 10, 2000)\n";
+" (unofficial 2.4.x kernel port, version 1.2.0, January 25, 2001)\n";
 
 /* The user-configurable values.
    These may be modified when a driver module is loaded.*/
 
+/*
+ * The current frame processor firmware fails to checksum a fragment
+ * of length 1. If and when this is fixed, the #define below can be removed.
+ */
+#define HAS_BROKEN_FIRMWARE
+
 /* Used for tuning interrupt latency vs. overhead. */
 static int interrupt_mitigation = 0x0;
 
@@ -117,12 +127,15 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 
+#include "starfire_firmware.h"
+
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(mtu, "i");
 MODULE_PARM(debug, "i");
 MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(interrupt_mitigation, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 
@@ -256,19 +269,31 @@
 	TxThreshold=0x500B0,
 	CompletionHiAddr=0x500B4, TxCompletionAddr=0x500B8,
 	RxCompletionAddr=0x500BC, RxCompletionQ2Addr=0x500C0,
-	CompletionQConsumerIdx=0x500C4,
+	CompletionQConsumerIdx=0x500C4, RxDMACtrl=0x500D0,
 	RxDescQCtrl=0x500D4, RxDescQHiAddr=0x500DC, RxDescQAddr=0x500E0,
 	RxDescQIdx=0x500E8, RxDMAStatus=0x500F0, RxFilterMode=0x500F4,
-	TxMode=0x55000,
+	TxMode=0x55000, TxGfpMem=0x58000, RxGfpMem=0x5a000,
 };
 
 /* Bits in the interrupt status/mask registers. */
 enum intr_status_bits {
-	IntrNormalSummary=0x8000,	IntrAbnormalSummary=0x02000000,
-	IntrRxDone=0x0300, IntrRxEmpty=0x10040, IntrRxPCIErr=0x80000,
-	IntrTxDone=0x4000, IntrTxEmpty=0x1000, IntrTxPCIErr=0x80000,
-	StatsMax=0x08000000, LinkChange=0xf0000000,
-	IntrTxDataLow=0x00040000,
+	IntrLinkChange=0xf0000000, IntrStatsMax=0x08000000,
+	IntrAbnormalSummary=0x02000000, IntrGeneralTimer=0x01000000,
+	IntrSoftware=0x800000, IntrRxComplQ1Low=0x400000,
+	IntrTxComplQLow=0x200000, IntrPCI=0x100000,
+	IntrDMAErr=0x080000, IntrTxDataLow=0x040000,
+	IntrRxComplQ2Low=0x020000, IntrRxDescQ1Low=0x010000,
+	IntrNormalSummary=0x8000, IntrTxDone=0x4000,
+	IntrTxDMADone=0x2000, IntrTxEmpty=0x1000,
+	IntrEarlyRxQ2=0x0800, IntrEarlyRxQ1=0x0400,
+	IntrRxQ2Done=0x0200, IntrRxQ1Done=0x0100,
+	IntrRxGFPDead=0x80, IntrRxDescQ2Low=0x40,
+	IntrNoTxCsum=0x20, IntrTxBadID=0x10,
+	IntrHiPriTxBadID=0x08, IntrRxGfp=0x04,
+	IntrTxGfp=0x02, IntrPCIPad=0x01,
+	/* not quite bits */
+	IntrRxDone=IntrRxQ2Done | IntrRxQ1Done,
+	IntrRxEmpty=IntrRxDescQ1Low | IntrRxDescQ2Low,
 };
 
 /* Bits in the RxFilterMode register. */
@@ -277,6 +302,37 @@
 	AcceptMulticast=0x10, AcceptMyPhys=0xE040,
 };
 
+/* Bits in the TxDescCtrl register. */
+enum tx_ctrl_bits {
+	TxDescSpaceUnlim=0x00, TxDescSpace32=0x10, TxDescSpace64=0x20,
+	TxDescSpace128=0x30, TxDescSpace256=0x40,
+	TxDescType0=0x00, TxDescType1=0x01, TxDescType2=0x02,
+	TxDescType3=0x03, TxDescType4=0x04,
+	TxNoDMACompletion=0x08, TxDescQ64bit=0x80,
+	TxHiPriFIFOThreshShift=24, TxPadLenShift=16,
+	TxDMABurstSizeShift=8,
+};
+
+/* Bits in the RxDescQCtrl register. */
+enum rx_ctrl_bits {
+	RxBufferLenShift=16, RxMinDescrThreshShift=0,
+	RxPrefetchMode=0x8000, Rx2048QEntries=0x4000,
+	RxVariableQ=0x2000, RxDesc64bit=0x1000,
+	RxDescQAddr64bit=0x0100,
+	RxDescSpace4=0x000, RxDescSpace8=0x100,
+	RxDescSpace16=0x200, RxDescSpace32=0x300,
+	RxDescSpace64=0x400, RxDescSpace128=0x500,
+	RxConsumerWrEn=0x80,
+};
+
+/* Bits in the RxCompletionAddr register */
+enum rx_compl_bits {
+	RxComplQAddr64bit=0x80, TxComplProducerWrEn=0x40,
+	RxComplType0=0x00, RxComplType1=0x10,
+	RxComplType2=0x20, RxComplType3=0x30,
+	RxComplThreshShift=0,
+};
+
 /* The Rx and Tx buffer descriptors. */
 struct starfire_rx_desc {
 	u32 rxaddr;					/* Optionally 64 bits. */
@@ -288,8 +344,12 @@
 /* Completion queue entry.
    You must update the page allocation, init_ring and the shift count in rx()
    if using a larger format. */
+#define csum_rx_status
 struct rx_done_desc {
 	u32 status;					/* Low 16 bits is length. */
+#ifdef csum_rx_status
+	u32 status2;				/* Low 16 bits is csum */
+#endif
 #ifdef full_rx_status
 	u32 status2;
 	u16 vlanid;
@@ -301,14 +361,24 @@
 	RxOK=0x20000000, RxFIFOErr=0x10000000, RxBufQ2=0x08000000,
 };
 
-/* Type 1 Tx descriptor. */
+/* Type 0 Tx descriptor. */
+/* If more fragments are needed, don't forget to change the
+   descriptor spacing as well! */
 struct starfire_tx_desc {
-	u32 status;					/* Upper bits are status, lower 16 length. */
-	u32 addr;
+	u32 status;
+	u32 nbufs;
+	u32 first_addr;
+	u16 first_len;
+	u16 total_len;
+	struct {
+		u32 addr;
+		u32 len;
+	} frag[6];
 };
 enum tx_desc_bits {
-	TxDescID=0xB1010000,		/* Also marks single fragment, add CRC.  */
-	TxDescIntr=0x08000000, TxRingWrap=0x04000000,
+	TxDescID=0xB0000000,
+	TxCRCEn=0x01000000, TxDescIntr=0x08000000,
+	TxRingWrap=0x04000000, TxCalTCP=0x02000000,
 };
 struct tx_done_report {
 	u32 status;					/* timestamp, index. */
@@ -318,10 +388,15 @@
 };
 
 #define PRIV_ALIGN	15 	/* Required alignment mask */
-struct ring_info {
+struct rx_ring_info {
 	struct sk_buff *skb;
 	dma_addr_t mapping;
 };
+struct tx_ring_info {
+	struct sk_buff *skb;
+	dma_addr_t first_mapping;
+	dma_addr_t frag_mapping[6];
+};
 
 struct netdev_private {
 	/* Descriptor rings first for alignment. */
@@ -330,8 +405,8 @@
 	dma_addr_t rx_ring_dma;
 	dma_addr_t tx_ring_dma;
 	/* The addresses of rx/tx-in-place skbuffs. */
-	struct ring_info rx_info[RX_RING_SIZE];
-	struct ring_info tx_info[TX_RING_SIZE];
+	struct rx_ring_info rx_info[RX_RING_SIZE];
+	struct tx_ring_info tx_info[TX_RING_SIZE];
 	/* Pointers to completion queues (full pages).  I should cache line pad..*/
 	u8 pad0[100];
 	struct rx_done_desc *rx_done_q;
@@ -390,16 +465,17 @@
 	static int card_idx = -1;
 	static int printed_version = 0;
 	long ioaddr;
-	int drv_flags, io_size = netdrv_tbl[chip_idx].io_size;
+	int drv_flags, io_size;
 
 	card_idx++;
 	option = card_idx < MAX_UNITS ? options[card_idx] : 0;
-	
+
 	if (!printed_version++)
 		printk(KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s",
 		       version1, version2, version3);
 
 	ioaddr = pci_resource_start (pdev, 0);
+	io_size = pci_resource_len (pdev, 0);
 	if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_MEM) == 0)) {
 		printk (KERN_ERR "starfire %d: no PCI MEM resources, aborting\n", card_idx);
 		return -ENODEV;
@@ -410,6 +486,7 @@
 		printk (KERN_ERR "starfire %d: cannot alloc etherdev, aborting\n", card_idx);
 		return -ENOMEM;
 	}
+	SET_MODULE_OWNER(dev);
 	
 	irq = pdev->irq; 
 
@@ -434,6 +511,9 @@
 	printk(KERN_INFO "%s: %s at 0x%lx, ",
 		   dev->name, netdrv_tbl[chip_idx].name, ioaddr);
 
+	/* Starfire can do SG and TCP/UDP checksumming */
+	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+
 	/* Serial EEPROM reads are hidden by the hardware. */
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = readb(ioaddr + EEPROMCtrl + 20-i);
@@ -546,13 +626,9 @@
 
 	/* Do we ever need to reset the chip??? */
 
-	MOD_INC_USE_COUNT;
-
 	retval = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);
-	if (retval) {
-		MOD_DEC_USE_COUNT;
+	if (retval)
 		return retval;
-	}
 
 	/* Disable the Rx and Tx, and reset the chip. */
 	writel(0, ioaddr + GenCtrl);
@@ -564,7 +640,7 @@
 	if (np->tx_done_q == 0)
 		np->tx_done_q = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->tx_done_q_dma);
 	if (np->rx_done_q == 0)
-		np->rx_done_q = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->rx_done_q_dma);
+		np->rx_done_q = pci_alloc_consistent(np->pci_dev, sizeof(struct rx_done_desc) * DONE_Q_SIZE, &np->rx_done_q_dma);
 	if (np->tx_ring == 0)
 		np->tx_ring = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->tx_ring_dma);
 	if (np->rx_ring == 0)
@@ -575,7 +651,7 @@
 			pci_free_consistent(np->pci_dev, PAGE_SIZE,
 								np->tx_done_q, np->tx_done_q_dma);
 		if (np->rx_done_q)
-			pci_free_consistent(np->pci_dev, PAGE_SIZE,
+			pci_free_consistent(np->pci_dev, sizeof(struct rx_done_desc) * DONE_Q_SIZE,
 								np->rx_done_q, np->rx_done_q_dma);
 		if (np->tx_ring)
 			pci_free_consistent(np->pci_dev, PAGE_SIZE,
@@ -583,16 +659,23 @@
 		if (np->rx_ring)
 			pci_free_consistent(np->pci_dev, PAGE_SIZE,
 								np->rx_ring, np->rx_ring_dma);
-		MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 
 	init_ring(dev);
 	/* Set the size of the Rx buffers. */
-	writel((np->rx_buf_sz<<16) | 0xA000, ioaddr + RxDescQCtrl);
-
-	/* Set Tx descriptor to type 1 and padding to 0 bytes. */
-	writel(0x02000401, ioaddr + TxDescCtrl);
+	writel((np->rx_buf_sz << RxBufferLenShift) |
+		   (0 << RxMinDescrThreshShift) |
+		   RxPrefetchMode | RxVariableQ |
+		   RxDescSpace4,
+		   ioaddr + RxDescQCtrl);
+
+	/* Set Tx descriptor to type 0 and spacing to 64 bytes. */
+	writel((2 << TxHiPriFIFOThreshShift) |
+	       (0 << TxPadLenShift) |
+	       (4 << TxDMABurstSizeShift) |
+	       TxDescSpace64 | TxDescType0,
+	       ioaddr + TxDescCtrl);
 
 #if defined(ADDR_64BITS) && defined(__alpha__)
 	/* XXX We really need a 64-bit PCI dma interfaces too... -DaveM */
@@ -607,7 +690,24 @@
 	writel(np->tx_ring_dma, ioaddr + TxRingPtr);
 
 	writel(np->tx_done_q_dma, ioaddr + TxCompletionAddr);
-	writel(np->rx_done_q_dma, ioaddr + RxCompletionAddr);
+#ifdef full_rx_status
+	writel(np->rx_done_q_dma |
+		   RxComplType3 |
+		   (0 << RxComplThreshShift),
+		   ioaddr + RxCompletionAddr);
+#else
+#ifdef csum_rx_status
+	writel(np->rx_done_q_dma |
+		   RxComplType2 |
+		   (0 << RxComplThreshShift),
+		   ioaddr + RxCompletionAddr);
+#else
+	writel(np->rx_done_q_dma |
+		   RxComplType0 |
+		   (0 << RxComplThreshShift),
+		   ioaddr + RxCompletionAddr);
+#endif
+#endif
 
 	if (debug > 1)
 		printk(KERN_DEBUG "%s:  Filling in the station address.\n", dev->name);
@@ -643,15 +743,21 @@
 	check_duplex(dev, 1);
 
 	/* Set the interrupt mask and enable PCI interrupts. */
-	writel(IntrRxDone | IntrRxEmpty | IntrRxPCIErr |
-		   IntrTxDone | IntrTxEmpty | IntrTxPCIErr |
-		   StatsMax | LinkChange | IntrNormalSummary | IntrAbnormalSummary
-		   | 0x0010 , ioaddr + IntrEnable);
+	writel(IntrRxDone | IntrRxEmpty | IntrDMAErr |
+	       IntrTxDone | IntrStatsMax | IntrLinkChange |
+	       IntrNormalSummary | IntrAbnormalSummary |
+	       IntrRxGFPDead | IntrNoTxCsum | IntrTxBadID,
+	       ioaddr + IntrEnable);
 	writel(0x00800000 | readl(ioaddr + PCIDeviceConfig),
 		   ioaddr + PCIDeviceConfig);
 
-	/* Enable the Rx and Tx units. */
-	writel(0x000F, ioaddr + GenCtrl);
+	/* Load Rx/Tx firmware into the frame processors */
+	for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
+		writel(cpu_to_le32(firmware_rx[i]), ioaddr + RxGfpMem + i * 4);
+	for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
+		writel(cpu_to_le32(firmware_tx[i]), ioaddr + TxGfpMem + i * 4);
+	/* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
+	writel(0x003F, ioaddr + GenCtrl);
 
 	if (debug > 2)
 		printk(KERN_DEBUG "%s: Done netdev_open().\n",
@@ -765,7 +871,7 @@
 static void init_ring(struct net_device *dev)
 {
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
-	int i;
+	int i, j;
 
 	np->tx_full = 0;
 	np->cur_rx = np->cur_tx = 0;
@@ -804,7 +910,9 @@
 
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		np->tx_info[i].skb = NULL;
-		np->tx_info[i].mapping = 0;
+		np->tx_info[i].first_mapping = 0;
+		for (j = 0; j < 6; j++)
+			np->tx_info[i].frag_mapping[j] = 0;
 		np->tx_ring[i].status = 0;
 	}
 	return;
@@ -814,6 +922,7 @@
 {
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	unsigned entry;
+	int i;
 
 	/* Caution: the write order is important here, set the field
 	   with the "ownership" bits last. */
@@ -821,42 +930,87 @@
 	/* Calculate the next Tx descriptor entry. */
 	entry = np->cur_tx % TX_RING_SIZE;
 
+#ifdef HAS_BROKEN_FIRMWARE
+	{
+		int has_bad_length = 0;
+
+		if (skb_headlen(skb) == 1)
+			has_bad_length = 1;
+		else {
+			for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+				if (skb_shinfo(skb)->frags[i].size == 1) {
+					has_bad_length = 1;
+					break;
+				}
+		}
+
+		if (has_bad_length)
+			skb_checksum_help(skb);
+	}
+#endif /* HAS_BROKEN_FIRMWARE */
+
 	np->tx_info[entry].skb = skb;
-	np->tx_info[entry].mapping =
-		pci_map_single(np->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
+	np->tx_info[entry].first_mapping =
+		pci_map_single(np->pci_dev, skb->data, skb_headlen(skb), PCI_DMA_TODEVICE);
 
-	np->tx_ring[entry].addr = cpu_to_le32(np->tx_info[entry].mapping);
+	np->tx_ring[entry].first_addr = cpu_to_le32(np->tx_info[entry].first_mapping);
+	np->tx_ring[entry].first_len = cpu_to_le32(skb_headlen(skb));
+	np->tx_ring[entry].total_len = cpu_to_le32(skb->len);
 	/* Add  "| TxDescIntr" to generate Tx-done interrupts. */
-	np->tx_ring[entry].status = cpu_to_le32(skb->len | TxDescID);
+	np->tx_ring[entry].status = cpu_to_le32(TxDescID | TxCRCEn);
+	if (entry >= TX_RING_SIZE-1)		 /* Wrap ring */
+		np->tx_ring[entry].status |= cpu_to_le32(TxRingWrap | TxDescIntr);
+	np->tx_ring[entry].nbufs = cpu_to_le32(skb_shinfo(skb)->nr_frags + 1);
+
+	if (skb->ip_summed == CHECKSUM_HW)
+		np->tx_ring[entry].status |= cpu_to_le32(TxCalTCP);
+
 	if (debug > 5) {
-		printk(KERN_DEBUG "%s: Tx #%d slot %d  %8.8x %8.8x.\n",
+		printk(KERN_DEBUG "%s: Tx #%d slot %d status %8.8x nbufs %d len %4.4x/%4.4x.\n",
 			   dev->name, np->cur_tx, entry,
 			   le32_to_cpu(np->tx_ring[entry].status),
-			   le32_to_cpu(np->tx_ring[entry].addr));
+			   le32_to_cpu(np->tx_ring[entry].nbufs),
+			   le32_to_cpu(np->tx_ring[entry].first_len),
+			   le32_to_cpu(np->tx_ring[entry].total_len));
+	}
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		skb_frag_t *this_frag = &skb_shinfo(skb)->frags[i];
+
+		/* we already have the proper value in entry */
+		np->tx_info[entry].frag_mapping[i] =
+			pci_map_single(np->pci_dev, page_address(this_frag->page) + this_frag->page_offset, this_frag->size, PCI_DMA_TODEVICE);
+
+		np->tx_ring[entry].frag[i].addr = cpu_to_le32(np->tx_info[entry].frag_mapping[i]);
+		np->tx_ring[entry].frag[i].len = cpu_to_le32(this_frag->size);
+		if (debug > 5) {
+			printk(KERN_DEBUG "%s: Tx #%d frag %d len %4.4x.\n",
+				   dev->name, np->cur_tx, i,
+				   le32_to_cpu(np->tx_ring[entry].frag[i].len));
+		}
 	}
+
 	np->cur_tx++;
-#if 1
-	if (entry >= TX_RING_SIZE-1) {		 /* Wrap ring */
-		np->tx_ring[entry].status |= cpu_to_le32(TxRingWrap | TxDescIntr);
+
+	if (entry >= TX_RING_SIZE-1)		 /* Wrap ring */
 		entry = -1;
-	}
-#endif
+	entry++;
 
 	/* Non-x86: explicitly flush descriptor cache lines here. */
+	/* Ensure everything is written back above before the transmit is
+	   initiated. - Jes */
+	wmb();
 
 	/* Update the producer index. */
-	writel(++entry, dev->base_addr + TxProducerIdx);
+	writel(entry * (sizeof(struct starfire_tx_desc) / 8), dev->base_addr + TxProducerIdx);
 
 	if (np->cur_tx - np->dirty_tx >= TX_RING_SIZE - 1) {
 		np->tx_full = 1;
 		netif_stop_queue(dev);
 	}
+
 	dev->trans_start = jiffies;
 
-	if (debug > 4) {
-		printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n",
-			   dev->name, np->cur_tx, entry);
-	}
 	return 0;
 }
 
@@ -919,18 +1073,29 @@
 					np->stats.tx_packets++;
 				} else if ((tx_status & 0xe0000000) == 0x80000000) {
 					struct sk_buff *skb;
+					int i;
 					u16 entry = tx_status; 		/* Implicit truncate */
-					entry >>= 3;
+					entry /= sizeof(struct starfire_tx_desc);
 
 					skb = np->tx_info[entry].skb;
+					np->tx_info[entry].skb = NULL;
 					pci_unmap_single(np->pci_dev,
-							 np->tx_info[entry].mapping,
-							 skb->len, PCI_DMA_TODEVICE);
+									 np->tx_info[entry].first_mapping,
+									 skb_headlen(skb),
+									 PCI_DMA_TODEVICE);
+					np->tx_info[entry].first_mapping = 0;
+
+					for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+						pci_unmap_single(np->pci_dev,
+										 np->tx_info[entry].frag_mapping[i],
+										 skb_shinfo(skb)->frags[i].size,
+										 PCI_DMA_TODEVICE);
+						np->tx_info[entry].frag_mapping[i] = 0;
+					}
 
 					/* Scavenge the descriptor. */
 					dev_kfree_skb_irq(skb);
-					np->tx_info[entry].skb = NULL;
-					np->tx_info[entry].mapping = 0;
+
 					np->dirty_tx++;
 				}
 				np->tx_done_q[np->tx_done].status = 0;
@@ -1037,14 +1202,6 @@
 				temp = skb_put(skb, pkt_len);
 				np->rx_info[entry].skb = NULL;
 				np->rx_info[entry].mapping = 0;
-#ifndef final_version				/* Remove after testing. */
-				if (le32_to_cpu(np->rx_ring[entry].rxaddr & ~3) != ((unsigned long) temp))
-					printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
-						   "do not match in netdev_rx: %d vs. %p / %p.\n",
-						   dev->name,
-						   le32_to_cpu(np->rx_ring[entry].rxaddr),
-						   skb->head, temp);
-#endif
 			}
 #ifndef final_version				/* Remove after testing. */
 			/* You will want this info for the initial debug. */
@@ -1060,9 +1217,23 @@
 					   skb->data[17]);
 #endif
 			skb->protocol = eth_type_trans(skb, dev);
-#ifdef full_rx_status
-			if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x01000000)
+#if defined(full_rx_status) || defined(csum_rx_status)
+			if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x01000000) {
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
+			}
+			/*
+			 * This feature doesn't seem to be working, at least
+			 * with the two firmware versions I have. If the GFP sees
+			 * a fragment, it either ignores it completely, or reports
+			 * "bad checksum" on it.
+			 *
+			 * Maybe I missed something -- corrections are welcome. -Ion
+			 */
+			else if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x00400000) {
+				skb->ip_summed = CHECKSUM_HW;
+				skb->csum = le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0xffff;
+				printk(KERN_DEBUG "%s: checksum_hw, status2 = %x\n", dev->name, np->rx_done_q[np->rx_done].status2);
+			}
 #endif
 			netif_rx(skb);
 			dev->last_rx = jiffies;
@@ -1109,28 +1280,26 @@
 {
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 
-	if (intr_status & LinkChange) {
+	if (intr_status & IntrLinkChange) {
 		printk(KERN_NOTICE "%s: Link changed: Autonegotiation advertising"
 			   " %4.4x  partner %4.4x.\n", dev->name,
 			   mdio_read(dev, np->phys[0], 4),
 			   mdio_read(dev, np->phys[0], 5));
 		check_duplex(dev, 0);
 	}
-	if (intr_status & StatsMax) {
+	if (intr_status & IntrStatsMax) {
 		get_stats(dev);
 	}
 	/* Came close to underrunning the Tx FIFO, increase threshold. */
 	if (intr_status & IntrTxDataLow)
 		writel(++np->tx_threshold, dev->base_addr + TxThreshold);
 	if ((intr_status &
-		 ~(IntrAbnormalSummary|LinkChange|StatsMax|IntrTxDataLow|1)) && debug)
+		 ~(IntrAbnormalSummary|IntrLinkChange|IntrStatsMax|IntrTxDataLow|1)) && debug)
 		printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n",
 			   dev->name, intr_status);
-	/* Hmmmmm, it's not clear how to recover from PCI faults. */
-	if (intr_status & IntrTxPCIErr)
+	/* Hmmmmm, it's not clear how to recover from DMA faults. */
+	if (intr_status & IntrDMAErr)
 		np->stats.tx_fifo_errors++;
-	if (intr_status & IntrRxPCIErr)
-		np->stats.rx_fifo_errors++;
 }
 
 static struct net_device_stats *get_stats(struct net_device *dev)
@@ -1280,7 +1449,7 @@
 {
 	long ioaddr = dev->base_addr;
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
-	int i;
+	int i, j;
 
 	netif_stop_queue(dev);
 
@@ -1305,7 +1474,7 @@
 		for (i = 0; i < 8 /* TX_RING_SIZE is huge! */; i++)
 			printk(KERN_DEBUG " #%d desc. %8.8x %8.8x -> %8.8x.\n",
 				   i, le32_to_cpu(np->tx_ring[i].status),
-				   le32_to_cpu(np->tx_ring[i].addr),
+				   le32_to_cpu(np->tx_ring[i].first_addr),
 				   le32_to_cpu(np->tx_done_q[i].status));
 		printk(KERN_DEBUG "  Rx ring at %8.8x -> %p:\n",
 			   np->rx_ring_dma, np->rx_done_q);
@@ -1333,16 +1502,23 @@
 		struct sk_buff *skb = np->tx_info[i].skb;
 		if (skb != NULL) {
 			pci_unmap_single(np->pci_dev,
-					 np->tx_info[i].mapping,
-					 skb->len, PCI_DMA_TODEVICE);
+					 np->tx_info[i].first_mapping,
+					 skb_headlen(skb), PCI_DMA_TODEVICE);
+			np->tx_info[i].first_mapping = 0;
 			dev_kfree_skb(skb);
+			np->tx_info[i].skb = NULL;
+			for (j = 0; j < 6; j++)
+				if (np->tx_info[i].frag_mapping[j]) {
+					pci_unmap_single(np->pci_dev,
+									 np->tx_info[i].frag_mapping[j],
+									 skb_shinfo(skb)->frags[j].size,
+									 PCI_DMA_TODEVICE);
+					np->tx_info[i].frag_mapping[j] = 0;
+				} else
+					break;
 		}
-		np->tx_info[i].skb = NULL;
-		np->tx_info[i].mapping = 0;
 	}
 
-	MOD_DEC_USE_COUNT;
-
 	return 0;
 }
 
@@ -1359,6 +1535,9 @@
 
 	unregister_netdev(dev);
 	iounmap((char *)dev->base_addr);
+
+	release_mem_region(pci_resource_start (pdev, 0),
+					   pci_resource_len (pdev, 0));
 
 	if (np->tx_done_q)
 		pci_free_consistent(np->pci_dev, PAGE_SIZE,
diff -urNX diff_kernel_excludes /usr/src/local/linux-2.4.vanilla/drivers/net/starfire_firmware.h linux-2.4/drivers/net/starfire_firmware.h
--- /usr/src/local/linux-2.4.vanilla/drivers/net/starfire_firmware.h	Wed Dec 31 16:00:00 1969
+++ linux-2.4/drivers/net/starfire_firmware.h	Sat Jan 27 13:03:06 2001
@@ -0,0 +1,215 @@
+static u32 firmware_rx[] = {
+  0x010003dc, 0x00000000,
+  0x04000421, 0x00000086,
+  0x80000015, 0x0000180e,
+  0x81000015, 0x00006664,
+  0x1a0040ab, 0x00000b06,
+  0x14200011, 0x00000000,
+  0x14204022, 0x0000aaaa,
+  0x14204022, 0x00000300,
+  0x14204022, 0x00000000,
+  0x1a0040ab, 0x00000b14,
+  0x14200011, 0x00000000,
+  0x83000015, 0x00000002,
+  0x04000021, 0x00000000,
+  0x00000010, 0x00000000,
+  0x04000421, 0x00000087,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00008015, 0x00000000,
+  0x0000003e, 0x00000000,
+  0x00000010, 0x00000000,
+  0x82000015, 0x00004000,
+  0x009e8050, 0x00000000,
+  0x03008015, 0x00000000,
+  0x86008015, 0x00000000,
+  0x82000015, 0x00008000,
+  0x0100001c, 0x00000000,
+  0x000050a0, 0x0000010c,
+  0x4e20d011, 0x00006008,
+  0x1420d012, 0x00004008,
+  0x0000f090, 0x00007000,
+  0x0000c8b0, 0x00003000,
+  0x00004040, 0x00000000,
+  0x00108015, 0x00000000,
+  0x00a2c150, 0x00004000,
+  0x00a400b0, 0x00000014,
+  0x00000020, 0x00000000,
+  0x2500400d, 0x00002525,
+  0x00047220, 0x00003100,
+  0x00934070, 0x00000000,
+  0x00000020, 0x00000000,
+  0x00924460, 0x00000184,
+  0x2b20c011, 0x00000000,
+  0x0000c420, 0x00000540,
+  0x36014018, 0x0000422d,
+  0x14200011, 0x00000000,
+  0x00924460, 0x00000183,
+  0x3200001f, 0x00000034,
+  0x02ac0015, 0x00000002,
+  0x00a60110, 0x00000008,
+  0x42200011, 0x00000000,
+  0x00924060, 0x00000103,
+  0x0000001e, 0x00000000,
+  0x00000020, 0x00000100,
+  0x0000001e, 0x00000000,
+  0x00924460, 0x00000086,
+  0x00004080, 0x00000000,
+  0x0092c070, 0x00000000,
+  0x00924060, 0x00000100,
+  0x0000c890, 0x00005000,
+  0x00a6c110, 0x00000000,
+  0x00b0c090, 0x00000012,
+  0x021c0015, 0x00000000,
+  0x3200001f, 0x00000034,
+  0x00924460, 0x00000510,
+  0x44210011, 0x00000000,
+  0x42000011, 0x00000000,
+  0x83000015, 0x00000040,
+  0x00924460, 0x00000508,
+  0x45014018, 0x00004545,
+  0x00808050, 0x00000000,
+  0x62208012, 0x00000000,
+  0x82000015, 0x00000800,
+  0x15200011, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x80000015, 0x0000eea4,
+  0x81000015, 0x0000005f,
+  0x00000060, 0x00000000,
+  0x00004120, 0x00000000,
+  0x00004a00, 0x00004000,
+  0x00924460, 0x00000190,
+  0x5601401a, 0x00005956,
+  0x14000011, 0x00000000,
+  0x00934050, 0x00000018,
+  0x00930050, 0x00000018,
+  0x3601403a, 0x0000002d,
+  0x000643a9, 0x00000000,
+  0x0000c420, 0x00000140,
+  0x5601401a, 0x00005956,
+  0x14000011, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x000642a9, 0x00000000,
+  0x00024420, 0x00000183,
+  0x5601401a, 0x00005956,
+  0x82000015, 0x00002000,
+  0x15200011, 0x00000000,
+  0x82000015, 0x00000010,
+  0x15200011, 0x00000000,
+  0x82000015, 0x00000010,
+  0x15200011, 0x00000000,
+};	/* 104 Rx instructions */
+#define FIRMWARE_RX_SIZE 104
+
+static u32 firmware_tx[] = {
+  0x010003dc, 0x00000000,
+  0x04000421, 0x00000086,
+  0x80000015, 0x0000180e,
+  0x81000015, 0x00006664,
+  0x1a0040ab, 0x00000b06,
+  0x14200011, 0x00000000,
+  0x14204022, 0x0000aaaa,
+  0x14204022, 0x00000300,
+  0x14204022, 0x00000000,
+  0x1a0040ab, 0x00000b14,
+  0x14200011, 0x00000000,
+  0x83000015, 0x00000002,
+  0x04000021, 0x00000000,
+  0x00000010, 0x00000000,
+  0x04000421, 0x00000087,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00008015, 0x00000000,
+  0x0000003e, 0x00000000,
+  0x00000010, 0x00000000,
+  0x82000015, 0x00004000,
+  0x009e8050, 0x00000000,
+  0x03008015, 0x00000000,
+  0x86008015, 0x00000000,
+  0x82000015, 0x00008000,
+  0x0100001c, 0x00000000,
+  0x000050a0, 0x0000010c,
+  0x4e20d011, 0x00006008,
+  0x1420d012, 0x00004008,
+  0x0000f090, 0x00007000,
+  0x0000c8b0, 0x00003000,
+  0x00004040, 0x00000000,
+  0x00108015, 0x00000000,
+  0x00a2c150, 0x00004000,
+  0x00a400b0, 0x00000014,
+  0x00000020, 0x00000000,
+  0x2500400d, 0x00002525,
+  0x00047220, 0x00003100,
+  0x00934070, 0x00000000,
+  0x00000020, 0x00000000,
+  0x00924460, 0x00000184,
+  0x2b20c011, 0x00000000,
+  0x0000c420, 0x00000540,
+  0x36014018, 0x0000422d,
+  0x14200011, 0x00000000,
+  0x00924460, 0x00000183,
+  0x3200001f, 0x00000034,
+  0x02ac0015, 0x00000002,
+  0x00a60110, 0x00000008,
+  0x42200011, 0x00000000,
+  0x00924060, 0x00000103,
+  0x0000001e, 0x00000000,
+  0x00000020, 0x00000100,
+  0x0000001e, 0x00000000,
+  0x00924460, 0x00000086,
+  0x00004080, 0x00000000,
+  0x0092c070, 0x00000000,
+  0x00924060, 0x00000100,
+  0x0000c890, 0x00005000,
+  0x00a6c110, 0x00000000,
+  0x00b0c090, 0x00000012,
+  0x021c0015, 0x00000000,
+  0x3200001f, 0x00000034,
+  0x00924460, 0x00000510,
+  0x44210011, 0x00000000,
+  0x42000011, 0x00000000,
+  0x83000015, 0x00000040,
+  0x00924460, 0x00000508,
+  0x45014018, 0x00004545,
+  0x00808050, 0x00000000,
+  0x62208012, 0x00000000,
+  0x82000015, 0x00000800,
+  0x15200011, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x80000015, 0x0000eea4,
+  0x81000015, 0x0000005f,
+  0x00000060, 0x00000000,
+  0x00004120, 0x00000000,
+  0x00004a00, 0x00004000,
+  0x00924460, 0x00000190,
+  0x5601401a, 0x00005956,
+  0x14000011, 0x00000000,
+  0x00934050, 0x00000018,
+  0x00930050, 0x00000018,
+  0x3601403a, 0x0000002d,
+  0x000643a9, 0x00000000,
+  0x0000c420, 0x00000140,
+  0x5601401a, 0x00005956,
+  0x14000011, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x000642a9, 0x00000000,
+  0x00024420, 0x00000183,
+  0x5601401a, 0x00005956,
+  0x82000015, 0x00002000,
+  0x15200011, 0x00000000,
+  0x82000015, 0x00000010,
+  0x15200011, 0x00000000,
+  0x82000015, 0x00000010,
+  0x15200011, 0x00000000,
+};	/* 104 Tx instructions */
+#define FIRMWARE_TX_SIZE 104
diff -urNX diff_kernel_excludes /usr/src/local/linux-2.4.vanilla/drivers/net/starfire_firmware.pl linux-2.4/drivers/net/starfire_firmware.pl
--- /usr/src/local/linux-2.4.vanilla/drivers/net/starfire_firmware.pl	Wed Dec 31 16:00:00 1969
+++ linux-2.4/drivers/net/starfire_firmware.pl	Thu Jan 25 21:43:27 2001
@@ -0,0 +1,31 @@
+#!/usr/bin/perl
+
+# This script can be used to generate a new starfire_firmware.h
+# from GFP_RX.DAT and GFP_TX.DAT, files included with the DDK
+# and also with the Novell drivers.
+
+open FW, "GFP_RX.DAT" || die;
+open FWH, ">starfire_firmware.h" || die;
+
+printf(FWH "static u32 firmware_rx[] = {\n");
+$counter = 0;
+while ($foo = <FW>) {
+  chomp;
+  printf(FWH "  0x%s, 0x0000%s,\n", substr($foo, 4, 8), substr($foo, 0, 4));
+  $counter++;
+}
+
+close FW;
+open FW, "GFP_TX.DAT" || die;
+
+printf(FWH "};\t/* %d Rx instructions */\n#define FIRMWARE_RX_SIZE %d\n\nstatic u32 firmware_tx[] = {\n", $counter, $counter);
+$counter = 0;
+while ($foo = <FW>) {
+  chomp;
+  printf(FWH "  0x%s, 0x0000%s,\n", substr($foo, 4, 8), substr($foo, 0, 4));
+  $counter++;
+}
+
+close FW;
+printf(FWH "};\t/* %d Tx instructions */\n#define FIRMWARE_TX_SIZE %d\n", $counter, $counter);
+close(FWH);

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-25 21:11       ` Ion Badulescu
  2001-01-26 19:43         ` kuznet
@ 2001-01-29 22:02         ` David S. Miller
  1 sibling, 0 replies; 27+ messages in thread
From: David S. Miller @ 2001-01-29 22:02 UTC (permalink / raw)
  To: kuznet; +Cc: Ion Badulescu, linux-kernel


kuznet@ms2.inr.ac.ru writes:
 > Dave, seems, it is better to repair this. Code really assumes
 > that SG cannot be used without one of CSUM flags...

SG+CSUM requirement is enforced now in my tree, I will publish a newer
zerocopy patch later today.

Later,
David S. Miller
davem@redhat.com
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-27 18:39               ` kuznet
  2001-01-27 21:18                 ` Ion Badulescu
@ 2001-01-30  6:02                 ` David S. Miller
  1 sibling, 0 replies; 27+ messages in thread
From: David S. Miller @ 2001-01-30  6:02 UTC (permalink / raw)
  To: Ion Badulescu; +Cc: kuznet, linux-kernel


Ion Badulescu writes:
 > I've attached a diff for the latest driver (and firmware) version, against
 > 2.4.1pre10+zerocopy. Sorry about MIME, but my pine is currently broken
 > (strips trailing spaces/tabs).

Ok.

Ion, I'll start to include your Starfire changes once the
firmware distribution issue is worked out, so please get it
resolved for me as I want to include your work, ok?

Thanks.

Later,
David S. Miller
davem@redhat.com
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-25 21:29         ` Steve Whitehouse
@ 2001-01-31 16:04           ` Alan Cox
  2001-03-11 20:55             ` NBD Fix (attempt #2) Steve Whitehouse
  0 siblings, 1 reply; 27+ messages in thread
From: Alan Cox @ 2001-01-31 16:04 UTC (permalink / raw)
  To: Steve; +Cc: David S. Miller, Ion Badulescu, kuznet, linux-kernel, Andrew Morton

> Do you mean that devices will not be able to indicate support of SG seperately
> from hw checksum or that the IP zerocopy will simply ignore devices which
> do not have both ?
> 
> DECnet assumes that the mac level checksum will detect all errors and does
> not have a checksum of its own on data, so it would only need SG to benefit
> from the zerocopy framework,

Ditto IPX

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* NBD Fix (attempt #2)
  2001-01-31 16:04           ` Alan Cox
@ 2001-03-11 20:55             ` Steve Whitehouse
  0 siblings, 0 replies; 27+ messages in thread
From: Steve Whitehouse @ 2001-03-11 20:55 UTC (permalink / raw)
  To: Alan Cox; +Cc: pavel, torvalds, axboe, linux-kernel

Hi,

Below is a patch which I think fixes the NBD hangs properly. It works for
me and doesn't need any changes to ll_rw_blk.c like my last patch did. I've
shown it to Pavel Machek who has approved it. The patch is against 2.4.2-ac18.

Pavel: I've made the change you requested and also added a flag I forgot before.
Alan: Please apply this patch to your kernel tree.

If memory serves correctly the MSG_MORE flag only appeared in 2.4.2-ac and
isn't in the standard 2.4.2 kernel so I'll prepare a separate patch for
2.4.2 if there are no plans to merge the ZC patches for a while. Is there
a timescale for this or some criteria by which the ZC changes will be judged 
ready for merging ?

The one other change which might be required is a userland change. The
buffer size used for I/O by the nbd-server program is not large enough
in the case that a lot of buffers get merged into a single request, this
is easy to change though. If you get a message in your syslog on your
server machine complaining of a request thats too large, then this is 
what has happened,

Steve.

------------------------------------------------------------------------------

diff -r -u linux-2.4.2-ac18/drivers/block/nbd.c linux/drivers/block/nbd.c
--- linux-2.4.2-ac18/drivers/block/nbd.c	Sun Mar 11 21:35:14 2001
+++ linux/drivers/block/nbd.c	Sun Mar 11 20:18:36 2001
@@ -26,7 +26,6 @@
  *          structure with userland
  */
 
-#undef	NBD_PLUGGABLE
 #define PARANOIA
 #include <linux/major.h>
 
@@ -68,8 +67,6 @@
 static int requests_out;
 #endif
 
-static void nbd_plug_device(request_queue_t *q, kdev_t dev) { }
-
 static int nbd_open(struct inode *inode, struct file *file)
 {
 	int dev;
@@ -88,7 +85,7 @@
 /*
  *  Send or receive packet.
  */
-static int nbd_xmit(int send, struct socket *sock, char *buf, int size)
+static int nbd_xmit(int send, struct socket *sock, char *buf, int size, int msg_flags)
 {
 	mm_segment_t oldfs;
 	int result;
@@ -118,7 +115,7 @@
 		msg.msg_control = NULL;
 		msg.msg_controllen = 0;
 		msg.msg_namelen = 0;
-		msg.msg_flags = 0;
+		msg.msg_flags = msg_flags | MSG_NOSIGNAL;
 
 		if (send)
 			result = sock_sendmsg(sock, &msg, size);
@@ -151,7 +148,7 @@
 {
 	int result;
 	struct nbd_request request;
-	unsigned long size = req->current_nr_sectors << 9;
+	unsigned long size = req->nr_sectors << 9;
 
 	DEBUG("NBD: sending control, ");
 	request.magic = htonl(NBD_REQUEST_MAGIC);
@@ -160,15 +157,19 @@
 	request.len = htonl(size);
 	memcpy(request.handle, &req, sizeof(req));
 
-	result = nbd_xmit(1, sock, (char *) &request, sizeof(request));
+	result = nbd_xmit(1, sock, (char *) &request, sizeof(request), req->cmd == WRITE ? MSG_MORE : 0);
 	if (result <= 0)
 		FAIL("Sendmsg failed for control.");
 
 	if (req->cmd == WRITE) {
+		struct buffer_head *bh = req->bh;
 		DEBUG("data, ");
-		result = nbd_xmit(1, sock, req->buffer, size);
-		if (result <= 0)
-			FAIL("Send data failed.");
+		do {
+			result = nbd_xmit(1, sock, bh->b_data, bh->b_size, bh->b_reqnext == NULL ? 0 : MSG_MORE);
+			if (result <= 0)
+				FAIL("Send data failed.");
+			bh = bh->b_reqnext;
+		} while(bh);
 	}
 	return;
 
@@ -186,7 +187,7 @@
 
 	DEBUG("reading control, ");
 	reply.magic = 0;
-	result = nbd_xmit(0, lo->sock, (char *) &reply, sizeof(reply));
+	result = nbd_xmit(0, lo->sock, (char *) &reply, sizeof(reply), MSG_WAITALL);
 	if (result <= 0)
 		HARDFAIL("Recv control failed.");
 	memcpy(&xreq, reply.handle, sizeof(xreq));
@@ -201,10 +202,14 @@
 	if (ntohl(reply.error))
 		FAIL("Other side returned error.");
 	if (req->cmd == READ) {
+		struct buffer_head *bh = req->bh;
 		DEBUG("data, ");
-		result = nbd_xmit(0, lo->sock, req->buffer, req->current_nr_sectors << 9);
-		if (result <= 0)
-			HARDFAIL("Recv data failed.");
+		do {
+			result = nbd_xmit(0, lo->sock, bh->b_data, bh->b_size, MSG_WAITALL);
+			if (result <= 0)
+				HARDFAIL("Recv data failed.");
+			bh = bh->b_reqnext;
+		} while(bh);
 	}
 	DEBUG("done.\n");
 	return req;
@@ -218,7 +223,6 @@
 void nbd_do_it(struct nbd_device *lo)
 {
 	struct request *req;
-	int dequeued;
 
 	down (&lo->queue_lock);
 	while (1) {
@@ -246,11 +250,9 @@
 		list_del(&req->queue);
 		up (&lo->queue_lock);
 		
-		dequeued = nbd_end_request(req);
+		nbd_end_request(req);
 
 		down (&lo->queue_lock);
-		if (!dequeued)
-			list_add(&req->queue, &lo->queue_head);
 	}
  out:
 	up (&lo->queue_lock);
@@ -259,7 +261,6 @@
 void nbd_clear_que(struct nbd_device *lo)
 {
 	struct request *req;
-	int dequeued;
 
 #ifdef PARANOIA
 	if (lo->magic != LO_MAGIC) {
@@ -284,11 +285,9 @@
 		list_del(&req->queue);
 		up(&lo->queue_lock);
 
-		dequeued = nbd_end_request(req);
+		nbd_end_request(req);
 
 		down(&lo->queue_lock);
-		if (!dequeued)
-			list_add(&req->queue, &lo->queue_head);
 	}
 }
 
@@ -498,9 +497,6 @@
 	blksize_size[MAJOR_NR] = nbd_blksizes;
 	blk_size[MAJOR_NR] = nbd_sizes;
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_nbd_request);
-#ifndef NBD_PLUGGABLE
-	blk_queue_pluggable(BLK_DEFAULT_QUEUE(MAJOR_NR), nbd_plug_device);
-#endif
 	blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
 	for (i = 0; i < MAX_NBD; i++) {
 		nbd_dev[i].refcnt = 0;
diff -r -u linux-2.4.2-ac18/include/linux/blk.h linux/include/linux/blk.h
--- linux-2.4.2-ac18/include/linux/blk.h	Sun Mar 11 21:35:17 2001
+++ linux/include/linux/blk.h	Sun Mar 11 20:20:08 2001
@@ -42,7 +42,6 @@
 extern int swimiop_init(void);
 extern int amiga_floppy_init(void);
 extern int atari_floppy_init(void);
-extern int nbd_init(void);
 extern int ez_init(void);
 extern int bpcd_init(void);
 extern int ps2esdi_init(void);
diff -r -u linux-2.4.2-ac18/include/linux/nbd.h linux/include/linux/nbd.h
--- linux-2.4.2-ac18/include/linux/nbd.h	Mon Dec 11 20:50:42 2000
+++ linux/include/linux/nbd.h	Sun Mar 11 20:23:48 2001
@@ -31,35 +31,27 @@
 extern int requests_out;
 #endif
 
-static int 
+static void
 nbd_end_request(struct request *req)
 {
+	struct buffer_head *bh;
+	unsigned nsect;
 	unsigned long flags;
-	int ret = 0;
+	int uptodate = (req->errors == 0) ? 1 : 0;
 
 #ifdef PARANOIA
 	requests_out++;
 #endif
-	/*
-	 * This is a very dirty hack that we have to do to handle
-	 * merged requests because end_request stuff is a bit
-	 * broken. The fact we have to do this only if there
-	 * aren't errors looks even more silly.
-	 */
-	if (!req->errors) {
-		req->sector += req->current_nr_sectors;
-		req->nr_sectors -= req->current_nr_sectors;
-	}
-
 	spin_lock_irqsave(&io_request_lock, flags);
-	if (end_that_request_first( req, !req->errors, "nbd" ))
-		goto out;
-	ret = 1;
-	end_that_request_last( req );
-
-out:
+	while((bh = req->bh) != NULL) {
+		nsect = bh->b_size >> 9;
+		blk_finished_io(nsect);
+		req->bh = bh->b_reqnext;
+		bh->b_reqnext = NULL;
+		bh->b_end_io(bh, uptodate);
+	}
+	blkdev_release_request(req);
 	spin_unlock_irqrestore(&io_request_lock, flags);
-	return ret;
 }
 
 #define MAX_NBD 128

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-24 21:45 ` Mathieu Chouquet-Stringer
@ 2001-01-31 22:42   ` Rogerio Brito
  0 siblings, 0 replies; 27+ messages in thread
From: Rogerio Brito @ 2001-01-31 22:42 UTC (permalink / raw)
  To: linux-kernel

On Jan 24 2001, Mathieu Chouquet-Stringer wrote:
> Moreover, few ethernet cards are able to compute the ip checksum so
> linux doesn't need anymore to do that.

	I'm very ignorant when it comes to Ethernet, but I'd like to
	know which cards have this feature, as I'm planning on buying
	a new one for my small home LAN (if they aren't expensive
	enough). And, of course, cards whose Linux drivers are able to
	use this feature...

	Any comments are more than welcome.


	Thanks in advance, Roger...

-- 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  Rogerio Brito - rbrito@iname.com - http://www.ime.usp.br/~rbrito/
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-24 21:52 Jonathan Earle
@ 2001-01-24 23:33 ` Peter Samuelson
  0 siblings, 0 replies; 27+ messages in thread
From: Peter Samuelson @ 2001-01-24 23:33 UTC (permalink / raw)
  To: Jonathan Earle; +Cc: 'Mathieu Chouquet-Stringer', linux-kernel


[Jonathan Earle]
> Hmm.. so things like routing should be faster then?

Other network traffic too.  Say you have an FTP server running and it
wants to send a file out to a client.  The old way was for it to read()
the file into memory and then write() it to the network socket.  To
avoid having to copy all that data into the userspace buffer during
read(), you can use mmap() instead.  In Linux 2.1.1xx we gained a new
syscall sendfile() which works like mmap()+write(), except faster since
the necessary kernel memory management is a lot simpler.  Using either
sendfile() or mmap(), the userspace program (ftpd) doesn't have to
touch the memory involved, just send it on to the socket.  That was the
first optimization relevant here, and it's been around awhile now.

Now with mmap()+write() or sendfile(), the kernel reads the data off
the disk using the page cache, then the network stack copies it to
other buffers, doing the TCP checksum in the process, and eventually
the Ethernet card does a DMA transfer of some sort and sends it out the
wire.  Notice that the CPU has to copy the data from the disk DMA
buffer to the network card DMA buffer, checksumming it somewhere along
the way.  Depending on circumstance, of course, there may be other
copying involved as well.

With zerocopy, when you issue sendfile(), the kernel does the network
DMA straight from the page cache, avoiding that extra copy.  In the
case where the network card is capable of doing the TCP checksum in
hardware (as a lot of newer cards can), the kernel doesn't even have to
look at the data between the disk DMA and the network DMA.  This can
save memory accesses and CPU data cache pollution.  The only way to get
a more direct route would be to do the DMA from disk controller to
network card without touching main memory at all, but this can have a
lot of complications and is probably not worth it in general -- see a
recent discussion on this list.

> What caveats should one watch for (ie: what functionalities will not
> work as before - if any)?

Ideally as a regular user you don't notice anything except things go
perhaps a bit faster.  I have no idea whether Davem's patch achieves
this yet..

Peter
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* RE: [UPDATE] Zerocopy patches, against 2.4.1-pre10
@ 2001-01-24 21:52 Jonathan Earle
  2001-01-24 23:33 ` Peter Samuelson
  0 siblings, 1 reply; 27+ messages in thread
From: Jonathan Earle @ 2001-01-24 21:52 UTC (permalink / raw)
  To: 'Mathieu Chouquet-Stringer', linux-kernel

> > What are "zerocopy patch set"s?
> 
> Basically, if you want to send something to the network, the 
> kernel has to
> copy your data to its memory space. It is an overhead and with these
> patches, the kernel doesn't has to do it. So it is faster. 
> Moreover, few
> ethernet cards are able to compute the ip checksum so linux 
> doesn't need
> anymore to do that.

Hmm.. so things like routing should be faster then?  What caveats should one
watch for (ie: what functionalities will not work as before - if any)?

Cheers!
Jon
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* Re: [UPDATE] Zerocopy patches, against 2.4.1-pre10
  2001-01-24 21:34 Jonathan Earle
@ 2001-01-24 21:45 ` Mathieu Chouquet-Stringer
  2001-01-31 22:42   ` Rogerio Brito
  0 siblings, 1 reply; 27+ messages in thread
From: Mathieu Chouquet-Stringer @ 2001-01-24 21:45 UTC (permalink / raw)
  To: linux-kernel

jearle@nortelnetworks.com ("Jonathan Earle") writes:

> > I'm back from OZ, and to help deal with my sudden lack of Victoria
> > Bitter, I've made a new zerocopy patch set.
> 
> What are "zerocopy patch set"s?

Basically, if you want to send something to the network, the kernel has to
copy your data to its memory space. It is an overhead and with these
patches, the kernel doesn't has to do it. So it is faster. Moreover, few
ethernet cards are able to compute the ip checksum so linux doesn't need
anymore to do that.
-- 
Mathieu CHOUQUET-STRINGER              E-Mail : mchouque@e-steel.com
     Learning French is trivial: the word for horse is cheval, and
               everything else follows in the same way.
                        -- Alan J. Perlis
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

* RE: [UPDATE] Zerocopy patches, against 2.4.1-pre10
@ 2001-01-24 21:34 Jonathan Earle
  2001-01-24 21:45 ` Mathieu Chouquet-Stringer
  0 siblings, 1 reply; 27+ messages in thread
From: Jonathan Earle @ 2001-01-24 21:34 UTC (permalink / raw)
  To: 'David S. Miller', linux-kernel

> I'm back from OZ, and to help deal with my sudden lack of Victoria
> Bitter, I've made a new zerocopy patch set.

What are "zerocopy patch set"s?

Cheers!
Jon
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

end of thread, other threads:[~2001-03-11 21:00 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <200101242123.NAA00986@pizda.ninka.net>
2001-01-25  1:40 ` [UPDATE] Zerocopy patches, against 2.4.1-pre10 Andrew Morton
2001-01-25 19:29   ` kuznet
2001-01-25 20:28     ` Ion Badulescu
2001-01-25 20:36       ` kuznet
2001-01-25 20:43     ` David S. Miller
2001-01-25 21:11       ` Ion Badulescu
2001-01-26 19:43         ` kuznet
2001-01-29 22:02         ` David S. Miller
2001-01-25 21:14       ` David S. Miller
2001-01-25 21:29         ` Steve Whitehouse
2001-01-31 16:04           ` Alan Cox
2001-03-11 20:55             ` NBD Fix (attempt #2) Steve Whitehouse
2001-01-25 21:38         ` [UPDATE] Zerocopy patches, against 2.4.1-pre10 David S. Miller
2001-01-26  6:06         ` Ion Badulescu
2001-01-26 13:13         ` David S. Miller
2001-01-26 20:43           ` Ion Badulescu
2001-01-27  0:55             ` Ion Badulescu
2001-01-27 18:39               ` kuznet
2001-01-27 21:18                 ` Ion Badulescu
2001-01-30  6:02                 ` David S. Miller
2001-01-26  1:27     ` Andrew Morton
2001-01-25  9:29 ` David S. Miller
2001-01-24 21:52 Jonathan Earle
2001-01-24 23:33 ` Peter Samuelson
  -- strict thread matches above, loose matches on Subject: below --
2001-01-24 21:34 Jonathan Earle
2001-01-24 21:45 ` Mathieu Chouquet-Stringer
2001-01-31 22:42   ` Rogerio Brito

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).