]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.drivers/netxen-fix-ipv6-offload-and-tx-cleanup.patch
Fix oinkmaster patch.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.drivers / netxen-fix-ipv6-offload-and-tx-cleanup.patch
CommitLineData
2cb7cef9
BS
1From 391587c3447d99b842a647f8e701895c9eea050b Mon Sep 17 00:00:00 2001
2From: Dhananjay Phadke <dhananjay@netxen.com>
3Date: Wed, 14 Jan 2009 20:48:11 -0800
4Subject: netxen: fix ipv6 offload and tx cleanup
5Acked-by: Karsten Keil <kkeil@novell.com>
6Reference: bnc#472416
7
8o fix the ip/tcp hdr offset in tx descriptors for ipv6.
9o cleanup xmit function, move the tso checks into separate function,
10 this reduces unnecessary endian conversions back and forth.
11o optimize macros to initialize tx descriptors.
12
13Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
14Signed-off-by: David S. Miller <davem@davemloft.net>
15---
16 drivers/net/netxen/netxen_nic.h | 43 ++++----------
17 drivers/net/netxen/netxen_nic_hw.c | 4 -
18 drivers/net/netxen/netxen_nic_main.c | 101 +++++++++++++++-------------------
19 3 files changed, 57 insertions(+), 91 deletions(-)
20
21Index: linux-2.6.27-kketmp/drivers/net/netxen/netxen_nic.h
22===================================================================
23--- linux-2.6.27-kketmp.orig/drivers/net/netxen/netxen_nic.h
24+++ linux-2.6.27-kketmp/drivers/net/netxen/netxen_nic.h
25@@ -308,27 +308,16 @@ struct netxen_ring_ctx {
26 #define netxen_set_cmd_desc_ctxid(cmd_desc, var) \
27 ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
28
29-#define netxen_set_cmd_desc_flags(cmd_desc, val) \
30- (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \
31- ~cpu_to_le16(0x7f)) | cpu_to_le16((val) & 0x7f)
32-#define netxen_set_cmd_desc_opcode(cmd_desc, val) \
33- (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \
34- ~cpu_to_le16((u16)0x3f << 7)) | cpu_to_le16(((val) & 0x3f) << 7)
35-
36-#define netxen_set_cmd_desc_num_of_buff(cmd_desc, val) \
37- (cmd_desc)->num_of_buffers_total_length = \
38- ((cmd_desc)->num_of_buffers_total_length & \
39- ~cpu_to_le32(0xff)) | cpu_to_le32((val) & 0xff)
40-#define netxen_set_cmd_desc_totallength(cmd_desc, val) \
41- (cmd_desc)->num_of_buffers_total_length = \
42- ((cmd_desc)->num_of_buffers_total_length & \
43- ~cpu_to_le32((u32)0xffffff << 8)) | \
44- cpu_to_le32(((val) & 0xffffff) << 8)
45-
46-#define netxen_get_cmd_desc_opcode(cmd_desc) \
47- ((le16_to_cpu((cmd_desc)->flags_opcode) >> 7) & 0x003f)
48-#define netxen_get_cmd_desc_totallength(cmd_desc) \
49- ((le32_to_cpu((cmd_desc)->num_of_buffers_total_length) >> 8) & 0xffffff)
50+#define netxen_set_tx_port(_desc, _port) \
51+ (_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0)
52+
53+#define netxen_set_tx_flags_opcode(_desc, _flags, _opcode) \
54+ (_desc)->flags_opcode = \
55+ cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7))
56+
57+#define netxen_set_tx_frags_len(_desc, _frags, _len) \
58+ (_desc)->num_of_buffers_total_length = \
59+ cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8))
60
61 struct cmd_desc_type0 {
62 u8 tcp_hdr_offset; /* For LSO only */
63@@ -757,7 +746,7 @@ extern char netxen_nic_driver_name[];
64 */
65 struct netxen_skb_frag {
66 u64 dma;
67- u32 length;
68+ ulong length;
69 };
70
71 #define _netxen_set_bits(config_word, start, bits, val) {\
72@@ -783,13 +772,7 @@ struct netxen_skb_frag {
73 struct netxen_cmd_buffer {
74 struct sk_buff *skb;
75 struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1];
76- u32 total_length;
77- u32 mss;
78- u16 port;
79- u8 cmd;
80- u8 frag_count;
81- unsigned long time_stamp;
82- u32 state;
83+ u32 frag_count;
84 };
85
86 /* In rx_buffer, we do not need multiple fragments as is a single buffer */
87@@ -1486,8 +1469,6 @@ void netxen_release_tx_buffers(struct ne
88
89 void netxen_initialize_adapter_ops(struct netxen_adapter *adapter);
90 int netxen_init_firmware(struct netxen_adapter *adapter);
91-void netxen_tso_check(struct netxen_adapter *adapter,
92- struct cmd_desc_type0 *desc, struct sk_buff *skb);
93 void netxen_nic_clear_stats(struct netxen_adapter *adapter);
94 void netxen_watchdog_task(struct work_struct *work);
95 void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
96Index: linux-2.6.27-kketmp/drivers/net/netxen/netxen_nic_hw.c
97===================================================================
98--- linux-2.6.27-kketmp.orig/drivers/net/netxen/netxen_nic_hw.c
99+++ linux-2.6.27-kketmp/drivers/net/netxen/netxen_nic_hw.c
100@@ -508,12 +508,8 @@ netxen_send_cmd_descs(struct netxen_adap
101 cmd_desc = &cmd_desc_arr[i];
102
103 pbuf = &adapter->cmd_buf_arr[producer];
104- pbuf->mss = 0;
105- pbuf->total_length = 0;
106 pbuf->skb = NULL;
107- pbuf->cmd = 0;
108 pbuf->frag_count = 0;
109- pbuf->port = 0;
110
111 /* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */
112 memcpy(&adapter->ahw.cmd_desc_head[producer],
113Index: linux-2.6.27-kketmp/drivers/net/netxen/netxen_nic_main.c
114===================================================================
115--- linux-2.6.27-kketmp.orig/drivers/net/netxen/netxen_nic_main.c
116+++ linux-2.6.27-kketmp/drivers/net/netxen/netxen_nic_main.c
117@@ -39,6 +39,7 @@
118 #include "netxen_nic_phan_reg.h"
119
120 #include <linux/dma-mapping.h>
121+#include <linux/if_vlan.h>
122 #include <net/ip.h>
123
124 MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver");
125@@ -1126,29 +1127,46 @@ static int netxen_nic_close(struct net_d
126 return 0;
127 }
128
129-void netxen_tso_check(struct netxen_adapter *adapter,
130+static bool netxen_tso_check(struct net_device *netdev,
131 struct cmd_desc_type0 *desc, struct sk_buff *skb)
132 {
133- if (desc->mss) {
134- desc->total_hdr_length = (sizeof(struct ethhdr) +
135- ip_hdrlen(skb) + tcp_hdrlen(skb));
136-
137- if ((NX_IS_REVISION_P3(adapter->ahw.revision_id)) &&
138- (skb->protocol == htons(ETH_P_IPV6)))
139- netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO6);
140- else
141- netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
142+ bool tso = false;
143+ u8 opcode = TX_ETHER_PKT;
144+
145+ if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
146+ skb_shinfo(skb)->gso_size > 0) {
147+
148+ desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
149+ desc->total_hdr_length =
150+ skb_transport_offset(skb) + tcp_hdrlen(skb);
151+
152+ opcode = (skb->protocol == htons(ETH_P_IPV6)) ?
153+ TX_TCP_LSO6 : TX_TCP_LSO;
154+ tso = true;
155
156 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
157- if (ip_hdr(skb)->protocol == IPPROTO_TCP)
158- netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
159- else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
160- netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
161- else
162- return;
163+ u8 l4proto;
164+
165+ if (skb->protocol == htons(ETH_P_IP)) {
166+ l4proto = ip_hdr(skb)->protocol;
167+
168+ if (l4proto == IPPROTO_TCP)
169+ opcode = TX_TCP_PKT;
170+ else if(l4proto == IPPROTO_UDP)
171+ opcode = TX_UDP_PKT;
172+ } else if (skb->protocol == htons(ETH_P_IPV6)) {
173+ l4proto = ipv6_hdr(skb)->nexthdr;
174+
175+ if (l4proto == IPPROTO_TCP)
176+ opcode = TX_TCPV6_PKT;
177+ else if(l4proto == IPPROTO_UDP)
178+ opcode = TX_UDPV6_PKT;
179+ }
180 }
181 desc->tcp_hdr_offset = skb_transport_offset(skb);
182 desc->ip_hdr_offset = skb_network_offset(skb);
183+ netxen_set_tx_flags_opcode(desc, 0, opcode);
184+ return tso;
185 }
186
187 static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
188@@ -1156,33 +1174,20 @@ static int netxen_nic_xmit_frame(struct
189 struct netxen_adapter *adapter = netdev_priv(netdev);
190 struct netxen_hardware_context *hw = &adapter->ahw;
191 unsigned int first_seg_len = skb->len - skb->data_len;
192+ struct netxen_cmd_buffer *pbuf;
193 struct netxen_skb_frag *buffrag;
194- unsigned int i;
195+ struct cmd_desc_type0 *hwdesc;
196+ int i, k;
197
198 u32 producer, consumer;
199- u32 saved_producer = 0;
200- struct cmd_desc_type0 *hwdesc;
201- int k;
202- struct netxen_cmd_buffer *pbuf = NULL;
203- int frag_count;
204- int no_of_desc;
205+ int frag_count, no_of_desc;
206 u32 num_txd = adapter->max_tx_desc_count;
207+ bool is_tso = false;
208
209 frag_count = skb_shinfo(skb)->nr_frags + 1;
210
211 /* There 4 fragments per descriptor */
212 no_of_desc = (frag_count + 3) >> 2;
213- if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) {
214- if (skb_shinfo(skb)->gso_size > 0) {
215-
216- no_of_desc++;
217- if ((ip_hdrlen(skb) + tcp_hdrlen(skb) +
218- sizeof(struct ethhdr)) >
219- (sizeof(struct cmd_desc_type0) - 2)) {
220- no_of_desc++;
221- }
222- }
223- }
224
225 producer = adapter->cmd_producer;
226 smp_mb();
227@@ -1194,34 +1199,22 @@ static int netxen_nic_xmit_frame(struct
228 }
229
230 /* Copy the descriptors into the hardware */
231- saved_producer = producer;
232 hwdesc = &hw->cmd_desc_head[producer];
233 memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
234 /* Take skb->data itself */
235 pbuf = &adapter->cmd_buf_arr[producer];
236- if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
237- skb_shinfo(skb)->gso_size > 0) {
238- pbuf->mss = skb_shinfo(skb)->gso_size;
239- hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
240- } else {
241- pbuf->mss = 0;
242- hwdesc->mss = 0;
243- }
244- pbuf->total_length = skb->len;
245+
246+ is_tso = netxen_tso_check(netdev, hwdesc, skb);
247+
248 pbuf->skb = skb;
249- pbuf->cmd = TX_ETHER_PKT;
250 pbuf->frag_count = frag_count;
251- pbuf->port = adapter->portnum;
252 buffrag = &pbuf->frag_array[0];
253 buffrag->dma = pci_map_single(adapter->pdev, skb->data, first_seg_len,
254 PCI_DMA_TODEVICE);
255 buffrag->length = first_seg_len;
256- netxen_set_cmd_desc_totallength(hwdesc, skb->len);
257- netxen_set_cmd_desc_num_of_buff(hwdesc, frag_count);
258- netxen_set_cmd_desc_opcode(hwdesc, TX_ETHER_PKT);
259+ netxen_set_tx_frags_len(hwdesc, frag_count, skb->len);
260+ netxen_set_tx_port(hwdesc, adapter->portnum);
261
262- netxen_set_cmd_desc_port(hwdesc, adapter->portnum);
263- netxen_set_cmd_desc_ctxid(hwdesc, adapter->portnum);
264 hwdesc->buffer1_length = cpu_to_le16(first_seg_len);
265 hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
266
267@@ -1274,16 +1267,12 @@ static int netxen_nic_xmit_frame(struct
268 }
269 producer = get_next_index(producer, num_txd);
270
271- /* might change opcode to TX_TCP_LSO */
272- netxen_tso_check(adapter, &hw->cmd_desc_head[saved_producer], skb);
273-
274 /* For LSO, we need to copy the MAC/IP/TCP headers into
275 * the descriptor ring
276 */
277- if (netxen_get_cmd_desc_opcode(&hw->cmd_desc_head[saved_producer])
278- == TX_TCP_LSO) {
279+ if (is_tso) {
280 int hdr_len, first_hdr_len, more_hdr;
281- hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length;
282+ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
283 if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) {
284 first_hdr_len = sizeof(struct cmd_desc_type0) - 2;
285 more_hdr = 1;