--- linux-2.6.23.12/drivers/net/via-rhine.c 2007-12-18 22:55:57.000000000 +0100 +++ linux-2.6.23.12.new/drivers/net/via-rhine.c 2008-01-11 08:58:58.000000000 +0100 @@ -33,6 +33,8 @@ #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,6 +42,7 @@ 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. */ #if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \ @@ -49,6 +52,7 @@ #else static int rx_copybreak; #endif +#endif /* PKT_ALIGN */ /* 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 */ @@ -111,6 +115,7 @@ #include #include #include +#include #include /* These identify the driver base version and may not be removed. */ @@ -130,12 +135,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 @@ -927,7 +934,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; @@ -1484,7 +1491,9 @@ struct sk_buff *skb; /* 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 && @@ -1503,7 +1512,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 " @@ -1517,6 +1528,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