diff options
author | Dhananjay Phadke <dhananjay@netxen.com> | 2009-07-26 16:07:45 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-07-27 14:15:31 -0400 |
commit | 028afe719855a157e32450c36b7a12e1f9e85abe (patch) | |
tree | 5aac51f5fd2def91942bf7b9b46040aeb7d4b503 /drivers/net/netxen/netxen_nic_main.c | |
parent | 9b08beba2d1bf7e4598deba2800a9ea5e5c3a282 (diff) |
netxen: add vlan tx acceleration support
Enable vlan tx acceleration for NX3031 if firmware advertises
capability.
Signed-off-by: Amit Kumar Salecha <amit@netxen.com>
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netxen/netxen_nic_main.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 52 |
1 files changed, 47 insertions, 5 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 43a99f6a23df..ff7ee9c43ef5 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
@@ -1016,6 +1016,9 @@ netxen_setup_netdev(struct netxen_adapter *adapter, | |||
1016 | netdev->vlan_features |= NETIF_F_HIGHDMA; | 1016 | netdev->vlan_features |= NETIF_F_HIGHDMA; |
1017 | } | 1017 | } |
1018 | 1018 | ||
1019 | if (adapter->capabilities & NX_FW_CAPABILITY_FVLANTX) | ||
1020 | netdev->features |= (NETIF_F_HW_VLAN_TX); | ||
1021 | |||
1019 | netdev->irq = adapter->msix_entries[0].vector; | 1022 | netdev->irq = adapter->msix_entries[0].vector; |
1020 | 1023 | ||
1021 | err = netxen_napi_add(adapter, netdev); | 1024 | err = netxen_napi_add(adapter, netdev); |
@@ -1333,15 +1336,24 @@ netxen_tso_check(struct net_device *netdev, | |||
1333 | { | 1336 | { |
1334 | u8 opcode = TX_ETHER_PKT; | 1337 | u8 opcode = TX_ETHER_PKT; |
1335 | __be16 protocol = skb->protocol; | 1338 | __be16 protocol = skb->protocol; |
1336 | u16 flags = 0; | 1339 | u16 flags = 0, vid = 0; |
1337 | u32 producer; | 1340 | u32 producer; |
1338 | int copied, offset, copy_len, hdr_len = 0, tso = 0; | 1341 | int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0; |
1339 | struct cmd_desc_type0 *hwdesc; | 1342 | struct cmd_desc_type0 *hwdesc; |
1343 | struct vlan_ethhdr *vh; | ||
1340 | 1344 | ||
1341 | if (protocol == cpu_to_be16(ETH_P_8021Q)) { | 1345 | if (protocol == cpu_to_be16(ETH_P_8021Q)) { |
1342 | struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data; | 1346 | |
1347 | vh = (struct vlan_ethhdr *)skb->data; | ||
1343 | protocol = vh->h_vlan_encapsulated_proto; | 1348 | protocol = vh->h_vlan_encapsulated_proto; |
1344 | flags = FLAGS_VLAN_TAGGED; | 1349 | flags = FLAGS_VLAN_TAGGED; |
1350 | |||
1351 | } else if (vlan_tx_tag_present(skb)) { | ||
1352 | |||
1353 | flags = FLAGS_VLAN_OOB; | ||
1354 | vid = vlan_tx_tag_get(skb); | ||
1355 | netxen_set_tx_vlan_tci(first_desc, vid); | ||
1356 | vlan_oob = 1; | ||
1345 | } | 1357 | } |
1346 | 1358 | ||
1347 | if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && | 1359 | if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && |
@@ -1351,6 +1363,13 @@ netxen_tso_check(struct net_device *netdev, | |||
1351 | 1363 | ||
1352 | first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); | 1364 | first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); |
1353 | first_desc->total_hdr_length = hdr_len; | 1365 | first_desc->total_hdr_length = hdr_len; |
1366 | if (vlan_oob) { | ||
1367 | first_desc->total_hdr_length += VLAN_HLEN; | ||
1368 | first_desc->tcp_hdr_offset = VLAN_HLEN; | ||
1369 | first_desc->ip_hdr_offset = VLAN_HLEN; | ||
1370 | /* Only in case of TSO on vlan device */ | ||
1371 | flags |= FLAGS_VLAN_TAGGED; | ||
1372 | } | ||
1354 | 1373 | ||
1355 | opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ? | 1374 | opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ? |
1356 | TX_TCP_LSO6 : TX_TCP_LSO; | 1375 | TX_TCP_LSO6 : TX_TCP_LSO; |
@@ -1375,8 +1394,9 @@ netxen_tso_check(struct net_device *netdev, | |||
1375 | opcode = TX_UDPV6_PKT; | 1394 | opcode = TX_UDPV6_PKT; |
1376 | } | 1395 | } |
1377 | } | 1396 | } |
1378 | first_desc->tcp_hdr_offset = skb_transport_offset(skb); | 1397 | |
1379 | first_desc->ip_hdr_offset = skb_network_offset(skb); | 1398 | first_desc->tcp_hdr_offset += skb_transport_offset(skb); |
1399 | first_desc->ip_hdr_offset += skb_network_offset(skb); | ||
1380 | netxen_set_tx_flags_opcode(first_desc, flags, opcode); | 1400 | netxen_set_tx_flags_opcode(first_desc, flags, opcode); |
1381 | 1401 | ||
1382 | if (!tso) | 1402 | if (!tso) |
@@ -1389,6 +1409,28 @@ netxen_tso_check(struct net_device *netdev, | |||
1389 | copied = 0; | 1409 | copied = 0; |
1390 | offset = 2; | 1410 | offset = 2; |
1391 | 1411 | ||
1412 | if (vlan_oob) { | ||
1413 | /* Create a TSO vlan header template for firmware */ | ||
1414 | |||
1415 | hwdesc = &tx_ring->desc_head[producer]; | ||
1416 | tx_ring->cmd_buf_arr[producer].skb = NULL; | ||
1417 | |||
1418 | copy_len = min((int)sizeof(struct cmd_desc_type0) - offset, | ||
1419 | hdr_len + VLAN_HLEN); | ||
1420 | |||
1421 | vh = (struct vlan_ethhdr *)((char *)hwdesc + 2); | ||
1422 | skb_copy_from_linear_data(skb, vh, 12); | ||
1423 | vh->h_vlan_proto = htons(ETH_P_8021Q); | ||
1424 | vh->h_vlan_TCI = htons(vid); | ||
1425 | skb_copy_from_linear_data_offset(skb, 12, | ||
1426 | (char *)vh + 16, copy_len - 16); | ||
1427 | |||
1428 | copied = copy_len; | ||
1429 | offset = 0; | ||
1430 | |||
1431 | producer = get_next_index(producer, tx_ring->num_desc); | ||
1432 | } | ||
1433 | |||
1392 | while (copied < hdr_len) { | 1434 | while (copied < hdr_len) { |
1393 | 1435 | ||
1394 | copy_len = min((int)sizeof(struct cmd_desc_type0) - offset, | 1436 | copy_len = min((int)sizeof(struct cmd_desc_type0) - offset, |