[686] in linux-net channel archive
Re: Checksum problem fixed
daemon@ATHENA.MIT.EDU (Temptation)
Sat Jul 15 00:34:56 1995
Date: Fri, 14 Jul 1995 17:31:58 -0400 (EDT)
From: Temptation <temp@temptation.interlog.com>
To: Paul Gortmaker <gpg109@rsphy1.anu.edu.au>
cc: Alan Cox <iialan@iifeak.swan.ac.uk>, linux-net@vger.rutgers.edu
In-Reply-To: <9507132049.AA21300@rsphy9.anu.edu.au>
While your fixing network drivers, can you fix the SMC EtherPower(DEC
chipset) as well? it only crashes when ftping files larger then 1meg.
Chris
On Fri, 14 Jul 1995, Paul Gortmaker wrote:
>
> > > Now that eth_copy_and_sum() works, I will work on converting shared
> > > memory 8390 cards to use it. The only snag will be if the packet
> > > is wrapped around the Rx ring boundary (and thus in 2 chunks) then
> > > we won't be able to use eth_copy_and_sum(). In that case, the csum
> > > will be done later by the upper layers as it is now.
> >
> > Benchmark it if you do. Its a win on a 386 lance as the bus mastering
> > DMA means the packet isn't cached.
>
> Got an ultra card? :-) I just took a quick swipe at it and have all
> the changes into the 8390 core and the ultra driver, and it even works.
> I don't have any useful net benchmarks other than ftp installed here.
>
> Of course I still have to do the other 7 or so 8390 card-specific
> drivers now. :-( The wd and 3c503 will be next. Stay tuned.
>
> Paul.
>
>
> diff -ur /var/tmp/linux/drivers/net/8390.c linux/drivers/net/8390.c
> --- /var/tmp/linux/drivers/net/8390.c Wed Jul 5 20:06:26 1995
> +++ linux/drivers/net/8390.c Fri Jul 14 05:45:36 1995
> @@ -19,6 +19,7 @@
> Changelog:
>
> Paul Gortmaker : remove set_bit lock, other cleanups.
> + Paul Gortmaker : support for eth_copy_and_sum() for shmem cards.
>
> */
>
> @@ -70,15 +71,18 @@
> int start_page)
> Write the COUNT bytes of BUF to the packet buffer at START_PAGE. The
> "page" value uses the 8390's 256-byte pages.
> - int block_input(struct device *dev, int count, char *buf, int ring_offset)
> - Read COUNT bytes from the packet buffer into BUF. Start reading from
> - RING_OFFSET, the address as the 8390 sees it. The first read will
> - always be the 4 byte, page aligned 8390 header. *If* there is a
> + void get_8390_hdr(struct device *dev, struct e8390_hdr *hdr, int ring_offset)
> + Read the 4 byte, page aligned 8390 header. *If* there is a
> subsequent read, it will be of the rest of the packet.
> + int block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
> + Read COUNT bytes from the packet buffer into the skb data area. Start
> + reading from RING_OFFSET, the address as the 8390 sees it. This will always
> + follow the read of the 8390 header.
> */
> #define ei_reset_8390 (ei_local->reset_8390)
> #define ei_block_output (ei_local->block_output)
> #define ei_block_input (ei_local->block_input)
> +#define ei_get_8390_hdr (ei_local->get_8390_hdr)
>
> /* use 0 for production, 1 for verification, >2 for debug */
> #ifdef EI_DEBUG
> @@ -426,8 +430,7 @@
> break; /* Done for now */
>
> current_offset = this_frame << 8;
> - ei_block_input(dev, sizeof(rx_frame), (char *)&rx_frame,
> - current_offset);
> + ei_get_8390_hdr(dev, &rx_frame, current_offset);
>
> pkt_len = rx_frame.count - sizeof(rx_frame);
>
> @@ -465,9 +468,8 @@
> } else {
> skb_reserve(skb,2); /* IP headers on 16 byte boundaries */
> skb->dev = dev;
> -
> - ei_block_input(dev, pkt_len, skb_put(skb,pkt_len),
> - current_offset + sizeof(rx_frame));
> + skb_put(skb,pkt_len); /* Make room */
> + ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
> skb->protocol=eth_type_trans(skb,dev);
> netif_rx(skb);
> ei_local->stat.rx_packets++;
> diff -ur /var/tmp/linux/drivers/net/8390.h linux/drivers/net/8390.h
> --- /var/tmp/linux/drivers/net/8390.h Mon Jun 19 01:11:37 1995
> +++ linux/drivers/net/8390.h Fri Jul 14 05:57:01 1995
> @@ -9,6 +9,7 @@
>
> #include <linux/if_ether.h>
> #include <linux/ioport.h>
> +#include <linux/skbuff.h>
>
> #define TX_2X_PAGES 12
> #define TX_1X_PAGES 6
> @@ -16,6 +17,13 @@
>
> #define ETHER_ADDR_LEN 6
>
> +/* The 8390 specific per-packet-header format. */
> +struct e8390_pkt_hdr {
> + unsigned char status; /* status */
> + unsigned char next; /* pointer to next packet. */
> + unsigned short count; /* header + packet length in bytes */
> +};
> +
> /* From 8390.c */
> extern int ei_debug;
> extern struct sigaction ei_sigaction;
> @@ -39,8 +47,9 @@
> struct ei_device {
> char *name;
> void (*reset_8390)(struct device *);
> + void (*get_8390_hdr)(struct device *, struct e8390_pkt_hdr *, int);
> void (*block_output)(struct device *, int, const unsigned char *, int);
> - int (*block_input)(struct device *, int, char *, int);
> + int (*block_input)(struct device *, int, struct sk_buff *, int);
> unsigned open:1;
> unsigned word16:1; /* We have the 16-bit (vs 8-bit) version of the card. */
> unsigned txing:1; /* Transmit Active */
> @@ -155,10 +164,4 @@
> #define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */
> #define ENTSR_OWC 0x80 /* There was an out-of-window collision. */
>
> -/* The per-packet-header format. */
> -struct e8390_pkt_hdr {
> - unsigned char status; /* status */
> - unsigned char next; /* pointer to next packet. */
> - unsigned short count; /* header + packet length in bytes */
> -};
> #endif /* _8390_h */
> diff -ur /var/tmp/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c
> --- /var/tmp/linux/drivers/net/smc-ultra.c Fri Jan 20 20:34:39 1995
> +++ linux/drivers/net/smc-ultra.c Fri Jul 14 06:02:31 1995
> @@ -48,6 +48,7 @@
> #include <asm/system.h>
>
> #include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> #include "8390.h"
> extern struct device *init_etherdev(struct device *dev, int sizeof_private,
> unsigned long *mem_startp);
> @@ -61,8 +62,10 @@
>
> static int ultra_open(struct device *dev);
> static void ultra_reset_8390(struct device *dev);
> +static void ultra_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
> + int ring_offset);
> static int ultra_block_input(struct device *dev, int count,
> - char *buf, int ring_offset);
> + struct sk_buff *skb, int ring_offset);
> static void ultra_block_output(struct device *dev, int count,
> const unsigned char *buf, const start_page);
> static int ultra_close_card(struct device *dev);
> @@ -204,6 +207,7 @@
> ei_status.reset_8390 = &ultra_reset_8390;
> ei_status.block_input = &ultra_block_input;
> ei_status.block_output = &ultra_block_output;
> + ei_status.get_8390_hdr = &ultra_get_8390_hdr;
> dev->open = &ultra_open;
> dev->stop = &ultra_close_card;
> NS8390_init(dev, 0);
> @@ -240,11 +244,26 @@
> return;
> }
>
> +/* Grab the 8390 specific header. Similar to the block_input routine, but
> + we don't need to be concerned with ring wrap as the header will be at
> + the start of a page, so we optimize accordingly */
> +
> +static void
> +ultra_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_offset)
> +{
> +
> + void *hdr_start = (void *)(dev->mem_start + ring_offset - (START_PG<<8));
> +
> + outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem on */
> + memcpy(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
> + outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem off */
> +}
> +
> /* Block input and output are easy on shared memory ethercards, the only
> complication is when the ring buffer wraps. */
>
> static int
> -ultra_block_input(struct device *dev, int count, char *buf, int ring_offset)
> +ultra_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
> {
> void *xfer_start = (void *)(dev->mem_start + ring_offset
> - (START_PG<<8));
> @@ -255,13 +274,14 @@
> if (xfer_start + count > (void*) dev->rmem_end) {
> /* We must wrap the input move. */
> int semi_count = (void*)dev->rmem_end - xfer_start;
> + void *buf = (void*)skb->data;
> memcpy(buf, xfer_start, semi_count);
> count -= semi_count;
> memcpy(buf + semi_count, (char *)dev->rmem_start, count);
> outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */
> return dev->rmem_start + count;
> }
> - memcpy(buf, xfer_start, count);
> + eth_copy_and_sum(skb, xfer_start, count, 0); /* Copy and csum it */
>
> outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */
> return ring_offset + count;
>