[673] in linux-net channel archive

home help back first fref pref prev next nref lref last post

Re: Checksum problem fixed

daemon@ATHENA.MIT.EDU (Paul Gortmaker)
Fri Jul 14 02:29:12 1995

From: Paul Gortmaker <gpg109@rsphy1.anu.edu.au>
To: iialan@iifeak.swan.ac.uk (Alan Cox)
Date: Fri, 14 Jul 1995 06:49:09 +1000 (EST)
Cc: linux-net@vger.rutgers.edu
In-Reply-To: <m0sWPac-00013zC@iiit.swan.ac.uk> from "Alan Cox" at Jul 13, 95 03:50:09 pm


> > 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;

home help back first fref pref prev next nref lref last post