1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -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 @@ static int rx_copybreak = 1518;
#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 @@ static const int multicast_filter_limit
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
+#include <asm/unaligned.h>
#include <linux/dmi.h>
/* These identify the driver base version and may not be removed. */
@@ -130,12 +135,14 @@ MODULE_LICENSE("GPL");
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
@@ -922,7 +929,7 @@ static void alloc_rbufs(struct net_devic
/* 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;
@@ -1485,7 +1492,9 @@ static int rhine_rx(struct net_device *d
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 &&
@@ -1504,7 +1513,9 @@ static int rhine_rx(struct net_device *d
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 "
@@ -1518,6 +1529,14 @@ static int rhine_rx(struct net_device *d
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
|