diff -ur linux.old/drivers/net/via-rhine.c linux.dev/drivers/net/via-rhine.c --- linux.old/drivers/net/via-rhine.c 2006-11-29 22:57:37.000000000 +0100 +++ linux.dev/drivers/net/via-rhine.c 2006-12-14 03:39:01.000000000 +0100 @@ -33,6 +33,7 @@ #define DRV_VERSION "1.4.3" #define DRV_RELDATE "2007-03-06" +#define PKT_ALIGN 1 /* A few user-configurable values. These may be modified when a driver module is loaded. */ @@ -40,9 +41,11 @@ static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ static int max_interrupt_work = 20; +#ifndef PKT_ALIGN /* Set the copy breakpoint for the copy-only-tiny-frames scheme. Setting to > 1518 effectively disables this feature. */ static int rx_copybreak; +#endif /* Work-around for broken BIOSes: they are unable to get the chip back out of power state D3 so PXE booting fails. bootparam(7): via-rhine.avoid_D3=1 */ @@ -105,6 +108,7 @@ #include #include #include +#include #include /* These identify the driver base version and may not be removed. */ @@ -124,12 +128,14 @@ module_param(max_interrupt_work, int, 0); module_param(debug, int, 0); -module_param(rx_copybreak, int, 0); module_param(avoid_D3, bool, 0); MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt"); MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)"); -MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames"); MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)"); +#ifndef PKT_ALIGN +module_param(rx_copybreak, int, 0); +MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames"); +#endif /* Theory of Operation @@ -924,7 +930,7 @@ /* Fill in the Rx buffers. Handle allocation failure gracefully. */ for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *skb = dev_alloc_skb(rp->rx_buf_sz); + struct sk_buff *skb = dev_alloc_skb(rp->rx_buf_sz + 4); rp->rx_skbuff[i] = skb; if (skb == NULL) break; @@ -1482,6 +1488,9 @@ /* Length should omit the CRC */ int pkt_len = data_size - 4; +#ifdef PKT_ALIGN + int i; +#else /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < rx_copybreak && @@ -1501,7 +1510,9 @@ rp->rx_skbuff_dma[entry], rp->rx_buf_sz, PCI_DMA_FROMDEVICE); - } else { + } else +#endif + { skb = rp->rx_skbuff[entry]; if (skb == NULL) { printk(KERN_ERR "%s: Inconsistent Rx " @@ -1515,6 +1526,14 @@ rp->rx_skbuff_dma[entry], rp->rx_buf_sz, PCI_DMA_FROMDEVICE); +#ifdef PKT_ALIGN + /* align the data to the ip header - should be faster than copying the entire packet */ + for (i = pkt_len - (pkt_len % 4); i >= 0; i -= 4) { + put_unaligned(*((u32 *) (skb->data + i)), (u32 *) (skb->data + i + 2)); + } + skb->data += 2; + skb->tail += 2; +#endif } skb->protocol = eth_type_trans(skb, dev); #ifdef CONFIG_VIA_RHINE_NAPI