diff options
author | Amit Kumar Salecha <amit.salecha@qlogic.com> | 2010-09-16 15:14:39 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-09-17 14:26:09 -0400 |
commit | d57906633efd58ccd93f056ed436ffde5cb31aa8 (patch) | |
tree | 59a319066931683e8b9ed0feeef0c483fcb5b068 /drivers/net/qlcnic/qlcnic_init.c | |
parent | 0c796f91a518480fd6696ba2affed1167e840823 (diff) |
qlcnic: support vlan rx accleration
Implemented vlan rx accleration in driver.
This helps in increasing significant performance and
reduces cpu utilization with GRO and LRO.
Eric Dumazet:
"Its a bit strange you use dev_kfree_skb_any(skb) here."
"We run in NAPI mode, so you can use dev_kfree_skb()."
Amit:
Done. Using dev_kfree_skb();
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/qlcnic/qlcnic_init.c')
-rw-r--r-- | drivers/net/qlcnic/qlcnic_init.c | 59 |
1 files changed, 34 insertions, 25 deletions
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 26a7d6bca5c7..10cebb15ccd4 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c | |||
@@ -1380,24 +1380,28 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, | |||
1380 | } | 1380 | } |
1381 | 1381 | ||
1382 | static int | 1382 | static int |
1383 | qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb) | 1383 | qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb, |
1384 | u16 *vlan_tag) | ||
1384 | { | 1385 | { |
1385 | u16 vlan_tag; | ||
1386 | struct ethhdr *eth_hdr; | 1386 | struct ethhdr *eth_hdr; |
1387 | 1387 | ||
1388 | if (!__vlan_get_tag(skb, &vlan_tag)) { | 1388 | if (!__vlan_get_tag(skb, vlan_tag)) { |
1389 | if (vlan_tag == adapter->pvid) { | 1389 | eth_hdr = (struct ethhdr *) skb->data; |
1390 | /* strip the tag from the packet and send it up */ | 1390 | memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2); |
1391 | eth_hdr = (struct ethhdr *) skb->data; | 1391 | skb_pull(skb, VLAN_HLEN); |
1392 | memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2); | 1392 | } |
1393 | skb_pull(skb, VLAN_HLEN); | 1393 | if (!adapter->pvid) |
1394 | return 0; | 1394 | return 0; |
1395 | } | 1395 | |
1396 | if (*vlan_tag == adapter->pvid) { | ||
1397 | /* Outer vlan tag. Packet should follow non-vlan path */ | ||
1398 | *vlan_tag = 0xffff; | ||
1399 | return 0; | ||
1396 | } | 1400 | } |
1397 | if (adapter->flags & QLCNIC_TAGGING_ENABLED) | 1401 | if (adapter->flags & QLCNIC_TAGGING_ENABLED) |
1398 | return 0; | 1402 | return 0; |
1399 | 1403 | ||
1400 | return -EIO; | 1404 | return -EINVAL; |
1401 | } | 1405 | } |
1402 | 1406 | ||
1403 | static struct qlcnic_rx_buffer * | 1407 | static struct qlcnic_rx_buffer * |
@@ -1411,6 +1415,7 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter, | |||
1411 | struct sk_buff *skb; | 1415 | struct sk_buff *skb; |
1412 | struct qlcnic_host_rds_ring *rds_ring; | 1416 | struct qlcnic_host_rds_ring *rds_ring; |
1413 | int index, length, cksum, pkt_offset; | 1417 | int index, length, cksum, pkt_offset; |
1418 | u16 vid = 0xffff; | ||
1414 | 1419 | ||
1415 | if (unlikely(ring >= adapter->max_rds_rings)) | 1420 | if (unlikely(ring >= adapter->max_rds_rings)) |
1416 | return NULL; | 1421 | return NULL; |
@@ -1441,17 +1446,18 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter, | |||
1441 | 1446 | ||
1442 | skb->truesize = skb->len + sizeof(struct sk_buff); | 1447 | skb->truesize = skb->len + sizeof(struct sk_buff); |
1443 | 1448 | ||
1444 | if (unlikely(adapter->pvid)) { | 1449 | if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { |
1445 | if (qlcnic_check_rx_tagging(adapter, skb)) { | 1450 | adapter->stats.rxdropped++; |
1446 | adapter->stats.rxdropped++; | 1451 | dev_kfree_skb(skb); |
1447 | dev_kfree_skb_any(skb); | 1452 | return buffer; |
1448 | return buffer; | ||
1449 | } | ||
1450 | } | 1453 | } |
1451 | 1454 | ||
1452 | skb->protocol = eth_type_trans(skb, netdev); | 1455 | skb->protocol = eth_type_trans(skb, netdev); |
1453 | 1456 | ||
1454 | napi_gro_receive(&sds_ring->napi, skb); | 1457 | if ((vid != 0xffff) && adapter->vlgrp) |
1458 | vlan_hwaccel_receive_skb(skb, adapter->vlgrp, vid); | ||
1459 | else | ||
1460 | napi_gro_receive(&sds_ring->napi, skb); | ||
1455 | 1461 | ||
1456 | adapter->stats.rx_pkts++; | 1462 | adapter->stats.rx_pkts++; |
1457 | adapter->stats.rxbytes += length; | 1463 | adapter->stats.rxbytes += length; |
@@ -1480,6 +1486,7 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, | |||
1480 | int index; | 1486 | int index; |
1481 | u16 lro_length, length, data_offset; | 1487 | u16 lro_length, length, data_offset; |
1482 | u32 seq_number; | 1488 | u32 seq_number; |
1489 | u16 vid = 0xffff; | ||
1483 | 1490 | ||
1484 | if (unlikely(ring > adapter->max_rds_rings)) | 1491 | if (unlikely(ring > adapter->max_rds_rings)) |
1485 | return NULL; | 1492 | return NULL; |
@@ -1514,13 +1521,12 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, | |||
1514 | 1521 | ||
1515 | skb_pull(skb, l2_hdr_offset); | 1522 | skb_pull(skb, l2_hdr_offset); |
1516 | 1523 | ||
1517 | if (unlikely(adapter->pvid)) { | 1524 | if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { |
1518 | if (qlcnic_check_rx_tagging(adapter, skb)) { | 1525 | adapter->stats.rxdropped++; |
1519 | adapter->stats.rxdropped++; | 1526 | dev_kfree_skb(skb); |
1520 | dev_kfree_skb_any(skb); | 1527 | return buffer; |
1521 | return buffer; | ||
1522 | } | ||
1523 | } | 1528 | } |
1529 | |||
1524 | skb->protocol = eth_type_trans(skb, netdev); | 1530 | skb->protocol = eth_type_trans(skb, netdev); |
1525 | 1531 | ||
1526 | iph = (struct iphdr *)skb->data; | 1532 | iph = (struct iphdr *)skb->data; |
@@ -1535,7 +1541,10 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, | |||
1535 | 1541 | ||
1536 | length = skb->len; | 1542 | length = skb->len; |
1537 | 1543 | ||
1538 | netif_receive_skb(skb); | 1544 | if ((vid != 0xffff) && adapter->vlgrp) |
1545 | vlan_hwaccel_receive_skb(skb, adapter->vlgrp, vid); | ||
1546 | else | ||
1547 | netif_receive_skb(skb); | ||
1539 | 1548 | ||
1540 | adapter->stats.lro_pkts++; | 1549 | adapter->stats.lro_pkts++; |
1541 | adapter->stats.lrobytes += length; | 1550 | adapter->stats.lrobytes += length; |