]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From 391587c3447d99b842a647f8e701895c9eea050b Mon Sep 17 00:00:00 2001 |
2 | From: Dhananjay Phadke <dhananjay@netxen.com> | |
3 | Date: Wed, 14 Jan 2009 20:48:11 -0800 | |
4 | Subject: netxen: fix ipv6 offload and tx cleanup | |
5 | Acked-by: Karsten Keil <kkeil@novell.com> | |
6 | Reference: bnc#472416 | |
7 | ||
8 | o fix the ip/tcp hdr offset in tx descriptors for ipv6. | |
9 | o cleanup xmit function, move the tso checks into separate function, | |
10 | this reduces unnecessary endian conversions back and forth. | |
11 | o optimize macros to initialize tx descriptors. | |
12 | ||
13 | Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> | |
14 | Signed-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 | ||
21 | Index: 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, | |
96 | Index: 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], | |
113 | Index: 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; |