aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlcnic/qlcnic_init.c
diff options
context:
space:
mode:
authorAmit Kumar Salecha <amit.salecha@qlogic.com>2010-09-16 15:14:39 -0400
committerDavid S. Miller <davem@davemloft.net>2010-09-17 14:26:09 -0400
commitd57906633efd58ccd93f056ed436ffde5cb31aa8 (patch)
tree59a319066931683e8b9ed0feeef0c483fcb5b068 /drivers/net/qlcnic/qlcnic_init.c
parent0c796f91a518480fd6696ba2affed1167e840823 (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.c59
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
1382static int 1382static int
1383qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb) 1383qlcnic_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
1403static struct qlcnic_rx_buffer * 1407static 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;