diff options
| -rw-r--r-- | drivers/net/qlcnic/qlcnic.h | 1 | ||||
| -rw-r--r-- | drivers/net/qlcnic/qlcnic_init.c | 59 | ||||
| -rw-r--r-- | drivers/net/qlcnic/qlcnic_main.c | 10 |
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 | ||
| 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; |
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 | ||
| 374 | static 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 | |||
| 374 | static const struct net_device_ops qlcnic_netdev_ops = { | 381 | static 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 | ||
