aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlcnic
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
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')
-rw-r--r--drivers/net/qlcnic/qlcnic.h1
-rw-r--r--drivers/net/qlcnic/qlcnic_init.c59
-rw-r--r--drivers/net/qlcnic/qlcnic_main.c10
3 files changed, 44 insertions, 26 deletions
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index cc8385a6727e..c8caec90b31b 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -1013,6 +1013,7 @@ struct qlcnic_adapter {
1013 1013
1014 u64 dev_rst_time; 1014 u64 dev_rst_time;
1015 1015
1016 struct vlan_group *vlgrp;
1016 struct qlcnic_npar_info *npars; 1017 struct qlcnic_npar_info *npars;
1017 struct qlcnic_eswitch *eswitch; 1018 struct qlcnic_eswitch *eswitch;
1018 struct qlcnic_nic_template *nic_ops; 1019 struct qlcnic_nic_template *nic_ops;
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;
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 5fd2abd1eb67..9eb0ced1ffab 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -371,6 +371,13 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
371 return 0; 371 return 0;
372} 372}
373 373
374static void qlcnic_vlan_rx_register(struct net_device *netdev,
375 struct vlan_group *grp)
376{
377 struct qlcnic_adapter *adapter = netdev_priv(netdev);
378 adapter->vlgrp = grp;
379}
380
374static const struct net_device_ops qlcnic_netdev_ops = { 381static const struct net_device_ops qlcnic_netdev_ops = {
375 .ndo_open = qlcnic_open, 382 .ndo_open = qlcnic_open,
376 .ndo_stop = qlcnic_close, 383 .ndo_stop = qlcnic_close,
@@ -381,6 +388,7 @@ static const struct net_device_ops qlcnic_netdev_ops = {
381 .ndo_set_mac_address = qlcnic_set_mac, 388 .ndo_set_mac_address = qlcnic_set_mac,
382 .ndo_change_mtu = qlcnic_change_mtu, 389 .ndo_change_mtu = qlcnic_change_mtu,
383 .ndo_tx_timeout = qlcnic_tx_timeout, 390 .ndo_tx_timeout = qlcnic_tx_timeout,
391 .ndo_vlan_rx_register = qlcnic_vlan_rx_register,
384#ifdef CONFIG_NET_POLL_CONTROLLER 392#ifdef CONFIG_NET_POLL_CONTROLLER
385 .ndo_poll_controller = qlcnic_poll_controller, 393 .ndo_poll_controller = qlcnic_poll_controller,
386#endif 394#endif
@@ -1446,7 +1454,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
1446 SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops); 1454 SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
1447 1455
1448 netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | 1456 netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
1449 NETIF_F_IPV6_CSUM | NETIF_F_GRO); 1457 NETIF_F_IPV6_CSUM | NETIF_F_GRO | NETIF_F_HW_VLAN_RX);
1450 netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | 1458 netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
1451 NETIF_F_IPV6_CSUM); 1459 NETIF_F_IPV6_CSUM);
1452 1460