aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen
diff options
context:
space:
mode:
authorDhananjay Phadke <dhananjay@netxen.com>2009-01-14 23:48:11 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-14 23:48:11 -0500
commit391587c3447d99b842a647f8e701895c9eea050b (patch)
tree5acf2f1282d068195261216953a1b71f20fb1c9a /drivers/net/netxen
parent2edbb454428729f450f7a0aabbf95ac62b46b78a (diff)
netxen: fix ipv6 offload and tx cleanup
o fix the ip/tcp hdr offset in tx descriptors for ipv6. o cleanup xmit function, move the tso checks into separate function, this reduces unnecessary endian conversions back and forth. o optimize macros to initialize tx descriptors. Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netxen')
-rw-r--r--drivers/net/netxen/netxen_nic.h43
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c4
-rw-r--r--drivers/net/netxen/netxen_nic_main.c101
3 files changed, 57 insertions, 91 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 31311cc66d18..acb2ac971ca3 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -308,27 +308,16 @@ struct netxen_ring_ctx {
308#define netxen_set_cmd_desc_ctxid(cmd_desc, var) \ 308#define netxen_set_cmd_desc_ctxid(cmd_desc, var) \
309 ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0)) 309 ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
310 310
311#define netxen_set_cmd_desc_flags(cmd_desc, val) \ 311#define netxen_set_tx_port(_desc, _port) \
312 (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \ 312 (_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0)
313 ~cpu_to_le16(0x7f)) | cpu_to_le16((val) & 0x7f) 313
314#define netxen_set_cmd_desc_opcode(cmd_desc, val) \ 314#define netxen_set_tx_flags_opcode(_desc, _flags, _opcode) \
315 (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \ 315 (_desc)->flags_opcode = \
316 ~cpu_to_le16((u16)0x3f << 7)) | cpu_to_le16(((val) & 0x3f) << 7) 316 cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7))
317 317
318#define netxen_set_cmd_desc_num_of_buff(cmd_desc, val) \ 318#define netxen_set_tx_frags_len(_desc, _frags, _len) \
319 (cmd_desc)->num_of_buffers_total_length = \ 319 (_desc)->num_of_buffers_total_length = \
320 ((cmd_desc)->num_of_buffers_total_length & \ 320 cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8))
321 ~cpu_to_le32(0xff)) | cpu_to_le32((val) & 0xff)
322#define netxen_set_cmd_desc_totallength(cmd_desc, val) \
323 (cmd_desc)->num_of_buffers_total_length = \
324 ((cmd_desc)->num_of_buffers_total_length & \
325 ~cpu_to_le32((u32)0xffffff << 8)) | \
326 cpu_to_le32(((val) & 0xffffff) << 8)
327
328#define netxen_get_cmd_desc_opcode(cmd_desc) \
329 ((le16_to_cpu((cmd_desc)->flags_opcode) >> 7) & 0x003f)
330#define netxen_get_cmd_desc_totallength(cmd_desc) \
331 ((le32_to_cpu((cmd_desc)->num_of_buffers_total_length) >> 8) & 0xffffff)
332 321
333struct cmd_desc_type0 { 322struct cmd_desc_type0 {
334 u8 tcp_hdr_offset; /* For LSO only */ 323 u8 tcp_hdr_offset; /* For LSO only */
@@ -757,7 +746,7 @@ extern char netxen_nic_driver_name[];
757 */ 746 */
758struct netxen_skb_frag { 747struct netxen_skb_frag {
759 u64 dma; 748 u64 dma;
760 u32 length; 749 ulong length;
761}; 750};
762 751
763#define _netxen_set_bits(config_word, start, bits, val) {\ 752#define _netxen_set_bits(config_word, start, bits, val) {\
@@ -783,13 +772,7 @@ struct netxen_skb_frag {
783struct netxen_cmd_buffer { 772struct netxen_cmd_buffer {
784 struct sk_buff *skb; 773 struct sk_buff *skb;
785 struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1]; 774 struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1];
786 u32 total_length; 775 u32 frag_count;
787 u32 mss;
788 u16 port;
789 u8 cmd;
790 u8 frag_count;
791 unsigned long time_stamp;
792 u32 state;
793}; 776};
794 777
795/* In rx_buffer, we do not need multiple fragments as is a single buffer */ 778/* In rx_buffer, we do not need multiple fragments as is a single buffer */
@@ -1486,8 +1469,6 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter);
1486 1469
1487void netxen_initialize_adapter_ops(struct netxen_adapter *adapter); 1470void netxen_initialize_adapter_ops(struct netxen_adapter *adapter);
1488int netxen_init_firmware(struct netxen_adapter *adapter); 1471int netxen_init_firmware(struct netxen_adapter *adapter);
1489void netxen_tso_check(struct netxen_adapter *adapter,
1490 struct cmd_desc_type0 *desc, struct sk_buff *skb);
1491void netxen_nic_clear_stats(struct netxen_adapter *adapter); 1472void netxen_nic_clear_stats(struct netxen_adapter *adapter);
1492void netxen_watchdog_task(struct work_struct *work); 1473void netxen_watchdog_task(struct work_struct *work);
1493void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, 1474void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index e8a0eed0078e..98d0bcda5f4f 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -508,12 +508,8 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
508 cmd_desc = &cmd_desc_arr[i]; 508 cmd_desc = &cmd_desc_arr[i];
509 509
510 pbuf = &adapter->cmd_buf_arr[producer]; 510 pbuf = &adapter->cmd_buf_arr[producer];
511 pbuf->mss = 0;
512 pbuf->total_length = 0;
513 pbuf->skb = NULL; 511 pbuf->skb = NULL;
514 pbuf->cmd = 0;
515 pbuf->frag_count = 0; 512 pbuf->frag_count = 0;
516 pbuf->port = 0;
517 513
518 /* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */ 514 /* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */
519 memcpy(&adapter->ahw.cmd_desc_head[producer], 515 memcpy(&adapter->ahw.cmd_desc_head[producer],
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index ba01524b5531..cb3912381802 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -39,6 +39,7 @@
39#include "netxen_nic_phan_reg.h" 39#include "netxen_nic_phan_reg.h"
40 40
41#include <linux/dma-mapping.h> 41#include <linux/dma-mapping.h>
42#include <linux/if_vlan.h>
42#include <net/ip.h> 43#include <net/ip.h>
43 44
44MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); 45MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver");
@@ -1137,29 +1138,46 @@ static int netxen_nic_close(struct net_device *netdev)
1137 return 0; 1138 return 0;
1138} 1139}
1139 1140
1140void netxen_tso_check(struct netxen_adapter *adapter, 1141static bool netxen_tso_check(struct net_device *netdev,
1141 struct cmd_desc_type0 *desc, struct sk_buff *skb) 1142 struct cmd_desc_type0 *desc, struct sk_buff *skb)
1142{ 1143{
1143 if (desc->mss) { 1144 bool tso = false;
1144 desc->total_hdr_length = (sizeof(struct ethhdr) + 1145 u8 opcode = TX_ETHER_PKT;
1145 ip_hdrlen(skb) + tcp_hdrlen(skb));
1146 1146
1147 if ((NX_IS_REVISION_P3(adapter->ahw.revision_id)) && 1147 if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
1148 (skb->protocol == htons(ETH_P_IPV6))) 1148 skb_shinfo(skb)->gso_size > 0) {
1149 netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO6); 1149
1150 else 1150 desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
1151 netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO); 1151 desc->total_hdr_length =
1152 skb_transport_offset(skb) + tcp_hdrlen(skb);
1153
1154 opcode = (skb->protocol == htons(ETH_P_IPV6)) ?
1155 TX_TCP_LSO6 : TX_TCP_LSO;
1156 tso = true;
1152 1157
1153 } else if (skb->ip_summed == CHECKSUM_PARTIAL) { 1158 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
1154 if (ip_hdr(skb)->protocol == IPPROTO_TCP) 1159 u8 l4proto;
1155 netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT); 1160
1156 else if (ip_hdr(skb)->protocol == IPPROTO_UDP) 1161 if (skb->protocol == htons(ETH_P_IP)) {
1157 netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT); 1162 l4proto = ip_hdr(skb)->protocol;
1158 else 1163
1159 return; 1164 if (l4proto == IPPROTO_TCP)
1165 opcode = TX_TCP_PKT;
1166 else if(l4proto == IPPROTO_UDP)
1167 opcode = TX_UDP_PKT;
1168 } else if (skb->protocol == htons(ETH_P_IPV6)) {
1169 l4proto = ipv6_hdr(skb)->nexthdr;
1170
1171 if (l4proto == IPPROTO_TCP)
1172 opcode = TX_TCPV6_PKT;
1173 else if(l4proto == IPPROTO_UDP)
1174 opcode = TX_UDPV6_PKT;
1175 }
1160 } 1176 }
1161 desc->tcp_hdr_offset = skb_transport_offset(skb); 1177 desc->tcp_hdr_offset = skb_transport_offset(skb);
1162 desc->ip_hdr_offset = skb_network_offset(skb); 1178 desc->ip_hdr_offset = skb_network_offset(skb);
1179 netxen_set_tx_flags_opcode(desc, 0, opcode);
1180 return tso;
1163} 1181}
1164 1182
1165static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) 1183static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
@@ -1167,33 +1185,20 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1167 struct netxen_adapter *adapter = netdev_priv(netdev); 1185 struct netxen_adapter *adapter = netdev_priv(netdev);
1168 struct netxen_hardware_context *hw = &adapter->ahw; 1186 struct netxen_hardware_context *hw = &adapter->ahw;
1169 unsigned int first_seg_len = skb->len - skb->data_len; 1187 unsigned int first_seg_len = skb->len - skb->data_len;
1188 struct netxen_cmd_buffer *pbuf;
1170 struct netxen_skb_frag *buffrag; 1189 struct netxen_skb_frag *buffrag;
1171 unsigned int i; 1190 struct cmd_desc_type0 *hwdesc;
1191 int i, k;
1172 1192
1173 u32 producer, consumer; 1193 u32 producer, consumer;
1174 u32 saved_producer = 0; 1194 int frag_count, no_of_desc;
1175 struct cmd_desc_type0 *hwdesc;
1176 int k;
1177 struct netxen_cmd_buffer *pbuf = NULL;
1178 int frag_count;
1179 int no_of_desc;
1180 u32 num_txd = adapter->max_tx_desc_count; 1195 u32 num_txd = adapter->max_tx_desc_count;
1196 bool is_tso = false;
1181 1197
1182 frag_count = skb_shinfo(skb)->nr_frags + 1; 1198 frag_count = skb_shinfo(skb)->nr_frags + 1;
1183 1199
1184 /* There 4 fragments per descriptor */ 1200 /* There 4 fragments per descriptor */
1185 no_of_desc = (frag_count + 3) >> 2; 1201 no_of_desc = (frag_count + 3) >> 2;
1186 if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) {
1187 if (skb_shinfo(skb)->gso_size > 0) {
1188
1189 no_of_desc++;
1190 if ((ip_hdrlen(skb) + tcp_hdrlen(skb) +
1191 sizeof(struct ethhdr)) >
1192 (sizeof(struct cmd_desc_type0) - 2)) {
1193 no_of_desc++;
1194 }
1195 }
1196 }
1197 1202
1198 producer = adapter->cmd_producer; 1203 producer = adapter->cmd_producer;
1199 smp_mb(); 1204 smp_mb();
@@ -1205,34 +1210,22 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1205 } 1210 }
1206 1211
1207 /* Copy the descriptors into the hardware */ 1212 /* Copy the descriptors into the hardware */
1208 saved_producer = producer;
1209 hwdesc = &hw->cmd_desc_head[producer]; 1213 hwdesc = &hw->cmd_desc_head[producer];
1210 memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); 1214 memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
1211 /* Take skb->data itself */ 1215 /* Take skb->data itself */
1212 pbuf = &adapter->cmd_buf_arr[producer]; 1216 pbuf = &adapter->cmd_buf_arr[producer];
1213 if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && 1217
1214 skb_shinfo(skb)->gso_size > 0) { 1218 is_tso = netxen_tso_check(netdev, hwdesc, skb);
1215 pbuf->mss = skb_shinfo(skb)->gso_size; 1219
1216 hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
1217 } else {
1218 pbuf->mss = 0;
1219 hwdesc->mss = 0;
1220 }
1221 pbuf->total_length = skb->len;
1222 pbuf->skb = skb; 1220 pbuf->skb = skb;
1223 pbuf->cmd = TX_ETHER_PKT;
1224 pbuf->frag_count = frag_count; 1221 pbuf->frag_count = frag_count;
1225 pbuf->port = adapter->portnum;
1226 buffrag = &pbuf->frag_array[0]; 1222 buffrag = &pbuf->frag_array[0];
1227 buffrag->dma = pci_map_single(adapter->pdev, skb->data, first_seg_len, 1223 buffrag->dma = pci_map_single(adapter->pdev, skb->data, first_seg_len,
1228 PCI_DMA_TODEVICE); 1224 PCI_DMA_TODEVICE);
1229 buffrag->length = first_seg_len; 1225 buffrag->length = first_seg_len;
1230 netxen_set_cmd_desc_totallength(hwdesc, skb->len); 1226 netxen_set_tx_frags_len(hwdesc, frag_count, skb->len);
1231 netxen_set_cmd_desc_num_of_buff(hwdesc, frag_count); 1227 netxen_set_tx_port(hwdesc, adapter->portnum);
1232 netxen_set_cmd_desc_opcode(hwdesc, TX_ETHER_PKT);
1233 1228
1234 netxen_set_cmd_desc_port(hwdesc, adapter->portnum);
1235 netxen_set_cmd_desc_ctxid(hwdesc, adapter->portnum);
1236 hwdesc->buffer1_length = cpu_to_le16(first_seg_len); 1229 hwdesc->buffer1_length = cpu_to_le16(first_seg_len);
1237 hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); 1230 hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
1238 1231
@@ -1285,16 +1278,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1285 } 1278 }
1286 producer = get_next_index(producer, num_txd); 1279 producer = get_next_index(producer, num_txd);
1287 1280
1288 /* might change opcode to TX_TCP_LSO */
1289 netxen_tso_check(adapter, &hw->cmd_desc_head[saved_producer], skb);
1290
1291 /* For LSO, we need to copy the MAC/IP/TCP headers into 1281 /* For LSO, we need to copy the MAC/IP/TCP headers into
1292 * the descriptor ring 1282 * the descriptor ring
1293 */ 1283 */
1294 if (netxen_get_cmd_desc_opcode(&hw->cmd_desc_head[saved_producer]) 1284 if (is_tso) {
1295 == TX_TCP_LSO) {
1296 int hdr_len, first_hdr_len, more_hdr; 1285 int hdr_len, first_hdr_len, more_hdr;
1297 hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length; 1286 hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
1298 if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) { 1287 if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) {
1299 first_hdr_len = sizeof(struct cmd_desc_type0) - 2; 1288 first_hdr_len = sizeof(struct cmd_desc_type0) - 2;
1300 more_hdr = 1; 1289 more_hdr = 1;