aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlge
diff options
context:
space:
mode:
authorJiri Pirko <jpirko@redhat.com>2011-07-20 23:24:11 -0400
committerDavid S. Miller <davem@davemloft.net>2011-07-21 16:47:55 -0400
commit18c49b91777c66265d640f8fb221039bdf46b2d3 (patch)
treef245cc6eb83402897abd60d22a9fac59fdbe973a /drivers/net/qlge
parentf1b553fbe73bfad38f41269d1c7a7ce3176d9539 (diff)
qlge: do vlan cleanup
- unify vlan and nonvlan path - kill qdev->vlgrp and qlge_vlan_rx_register - allow to turn on/off rx/tx vlan accel via ethtool (set_features) Signed-off-by: Jiri Pirko <jpirko@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/qlge')
-rw-r--r--drivers/net/qlge/qlge.h3
-rw-r--r--drivers/net/qlge/qlge_main.c161
2 files changed, 93 insertions, 71 deletions
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index 794252c0aedd..8731f79c9efc 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -11,6 +11,7 @@
11#include <linux/pci.h> 11#include <linux/pci.h>
12#include <linux/netdevice.h> 12#include <linux/netdevice.h>
13#include <linux/rtnetlink.h> 13#include <linux/rtnetlink.h>
14#include <linux/if_vlan.h>
14 15
15/* 16/*
16 * General definitions... 17 * General definitions...
@@ -2052,7 +2053,7 @@ struct ql_adapter {
2052 2053
2053 struct nic_stats nic_stats; 2054 struct nic_stats nic_stats;
2054 2055
2055 struct vlan_group *vlgrp; 2056 unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
2056 2057
2057 /* PCI Configuration information for this device */ 2058 /* PCI Configuration information for this device */
2058 struct pci_dev *pdev; 2059 struct pci_dev *pdev;
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 68fbfac7a3bf..743e3ec729c2 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -7,6 +7,7 @@
7 */ 7 */
8#include <linux/kernel.h> 8#include <linux/kernel.h>
9#include <linux/init.h> 9#include <linux/init.h>
10#include <linux/bitops.h>
10#include <linux/types.h> 11#include <linux/types.h>
11#include <linux/module.h> 12#include <linux/module.h>
12#include <linux/list.h> 13#include <linux/list.h>
@@ -33,6 +34,7 @@
33#include <linux/netdevice.h> 34#include <linux/netdevice.h>
34#include <linux/etherdevice.h> 35#include <linux/etherdevice.h>
35#include <linux/ethtool.h> 36#include <linux/ethtool.h>
37#include <linux/if_vlan.h>
36#include <linux/skbuff.h> 38#include <linux/skbuff.h>
37#include <linux/if_vlan.h> 39#include <linux/if_vlan.h>
38#include <linux/delay.h> 40#include <linux/delay.h>
@@ -415,7 +417,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
415 (qdev-> 417 (qdev->
416 func << CAM_OUT_FUNC_SHIFT) | 418 func << CAM_OUT_FUNC_SHIFT) |
417 (0 << CAM_OUT_CQ_ID_SHIFT)); 419 (0 << CAM_OUT_CQ_ID_SHIFT));
418 if (qdev->vlgrp) 420 if (qdev->ndev->features & NETIF_F_HW_VLAN_RX)
419 cam_output |= CAM_OUT_RV; 421 cam_output |= CAM_OUT_RV;
420 /* route to NIC core */ 422 /* route to NIC core */
421 ql_write32(qdev, MAC_ADDR_DATA, cam_output); 423 ql_write32(qdev, MAC_ADDR_DATA, cam_output);
@@ -1507,10 +1509,9 @@ static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev,
1507 rx_ring->rx_bytes += length; 1509 rx_ring->rx_bytes += length;
1508 skb->ip_summed = CHECKSUM_UNNECESSARY; 1510 skb->ip_summed = CHECKSUM_UNNECESSARY;
1509 skb_record_rx_queue(skb, rx_ring->cq_id); 1511 skb_record_rx_queue(skb, rx_ring->cq_id);
1510 if (qdev->vlgrp && (vlan_id != 0xffff)) 1512 if (vlan_id != 0xffff)
1511 vlan_gro_frags(&rx_ring->napi, qdev->vlgrp, vlan_id); 1513 __vlan_hwaccel_put_tag(skb, vlan_id);
1512 else 1514 napi_gro_frags(napi);
1513 napi_gro_frags(napi);
1514} 1515}
1515 1516
1516/* Process an inbound completion from an rx ring. */ 1517/* Process an inbound completion from an rx ring. */
@@ -1594,17 +1595,12 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev,
1594 } 1595 }
1595 1596
1596 skb_record_rx_queue(skb, rx_ring->cq_id); 1597 skb_record_rx_queue(skb, rx_ring->cq_id);
1597 if (skb->ip_summed == CHECKSUM_UNNECESSARY) { 1598 if (vlan_id != 0xffff)
1598 if (qdev->vlgrp && (vlan_id != 0xffff)) 1599 __vlan_hwaccel_put_tag(skb, vlan_id);
1599 vlan_gro_receive(napi, qdev->vlgrp, vlan_id, skb); 1600 if (skb->ip_summed == CHECKSUM_UNNECESSARY)
1600 else 1601 napi_gro_receive(napi, skb);
1601 napi_gro_receive(napi, skb); 1602 else
1602 } else { 1603 netif_receive_skb(skb);
1603 if (qdev->vlgrp && (vlan_id != 0xffff))
1604 vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id);
1605 else
1606 netif_receive_skb(skb);
1607 }
1608 return; 1604 return;
1609err_out: 1605err_out:
1610 dev_kfree_skb_any(skb); 1606 dev_kfree_skb_any(skb);
@@ -1707,18 +1703,12 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev,
1707 } 1703 }
1708 1704
1709 skb_record_rx_queue(skb, rx_ring->cq_id); 1705 skb_record_rx_queue(skb, rx_ring->cq_id);
1710 if (skb->ip_summed == CHECKSUM_UNNECESSARY) { 1706 if (vlan_id != 0xffff)
1711 if (qdev->vlgrp && (vlan_id != 0xffff)) 1707 __vlan_hwaccel_put_tag(skb, vlan_id);
1712 vlan_gro_receive(&rx_ring->napi, qdev->vlgrp, 1708 if (skb->ip_summed == CHECKSUM_UNNECESSARY)
1713 vlan_id, skb); 1709 napi_gro_receive(&rx_ring->napi, skb);
1714 else 1710 else
1715 napi_gro_receive(&rx_ring->napi, skb); 1711 netif_receive_skb(skb);
1716 } else {
1717 if (qdev->vlgrp && (vlan_id != 0xffff))
1718 vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id);
1719 else
1720 netif_receive_skb(skb);
1721 }
1722} 1712}
1723 1713
1724static void ql_realign_skb(struct sk_buff *skb, int len) 1714static void ql_realign_skb(struct sk_buff *skb, int len)
@@ -2028,22 +2018,12 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev,
2028 rx_ring->rx_packets++; 2018 rx_ring->rx_packets++;
2029 rx_ring->rx_bytes += skb->len; 2019 rx_ring->rx_bytes += skb->len;
2030 skb_record_rx_queue(skb, rx_ring->cq_id); 2020 skb_record_rx_queue(skb, rx_ring->cq_id);
2031 if (skb->ip_summed == CHECKSUM_UNNECESSARY) { 2021 if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) && (vlan_id != 0))
2032 if (qdev->vlgrp && 2022 __vlan_hwaccel_put_tag(skb, vlan_id);
2033 (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) && 2023 if (skb->ip_summed == CHECKSUM_UNNECESSARY)
2034 (vlan_id != 0)) 2024 napi_gro_receive(&rx_ring->napi, skb);
2035 vlan_gro_receive(&rx_ring->napi, qdev->vlgrp, 2025 else
2036 vlan_id, skb); 2026 netif_receive_skb(skb);
2037 else
2038 napi_gro_receive(&rx_ring->napi, skb);
2039 } else {
2040 if (qdev->vlgrp &&
2041 (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) &&
2042 (vlan_id != 0))
2043 vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id);
2044 else
2045 netif_receive_skb(skb);
2046 }
2047} 2027}
2048 2028
2049/* Process an inbound completion from an rx ring. */ 2029/* Process an inbound completion from an rx ring. */
@@ -2334,71 +2314,111 @@ static int ql_napi_poll_msix(struct napi_struct *napi, int budget)
2334 return work_done; 2314 return work_done;
2335} 2315}
2336 2316
2337static void qlge_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp) 2317static void qlge_vlan_mode(struct net_device *ndev, u32 features)
2338{ 2318{
2339 struct ql_adapter *qdev = netdev_priv(ndev); 2319 struct ql_adapter *qdev = netdev_priv(ndev);
2340 2320
2341 qdev->vlgrp = grp; 2321 if (features & NETIF_F_HW_VLAN_RX) {
2342 if (grp) { 2322 netif_printk(qdev, ifup, KERN_DEBUG, ndev,
2343 netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
2344 "Turning on VLAN in NIC_RCV_CFG.\n"); 2323 "Turning on VLAN in NIC_RCV_CFG.\n");
2345 ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK | 2324 ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK |
2346 NIC_RCV_CFG_VLAN_MATCH_AND_NON); 2325 NIC_RCV_CFG_VLAN_MATCH_AND_NON);
2347 } else { 2326 } else {
2348 netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, 2327 netif_printk(qdev, ifup, KERN_DEBUG, ndev,
2349 "Turning off VLAN in NIC_RCV_CFG.\n"); 2328 "Turning off VLAN in NIC_RCV_CFG.\n");
2350 ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK); 2329 ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK);
2351 } 2330 }
2352} 2331}
2353 2332
2354static void qlge_vlan_rx_add_vid(struct net_device *ndev, u16 vid) 2333static u32 qlge_fix_features(struct net_device *ndev, u32 features)
2334{
2335 /*
2336 * Since there is no support for separate rx/tx vlan accel
2337 * enable/disable make sure tx flag is always in same state as rx.
2338 */
2339 if (features & NETIF_F_HW_VLAN_RX)
2340 features |= NETIF_F_HW_VLAN_TX;
2341 else
2342 features &= ~NETIF_F_HW_VLAN_TX;
2343
2344 return features;
2345}
2346
2347static int qlge_set_features(struct net_device *ndev, u32 features)
2348{
2349 u32 changed = ndev->features ^ features;
2350
2351 if (changed & NETIF_F_HW_VLAN_RX)
2352 qlge_vlan_mode(ndev, features);
2353
2354 return 0;
2355}
2356
2357static void __qlge_vlan_rx_add_vid(struct ql_adapter *qdev, u16 vid)
2355{ 2358{
2356 struct ql_adapter *qdev = netdev_priv(ndev);
2357 u32 enable_bit = MAC_ADDR_E; 2359 u32 enable_bit = MAC_ADDR_E;
2358 int status;
2359 2360
2360 status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
2361 if (status)
2362 return;
2363 if (ql_set_mac_addr_reg 2361 if (ql_set_mac_addr_reg
2364 (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) { 2362 (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) {
2365 netif_err(qdev, ifup, qdev->ndev, 2363 netif_err(qdev, ifup, qdev->ndev,
2366 "Failed to init vlan address.\n"); 2364 "Failed to init vlan address.\n");
2367 } 2365 }
2368 ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
2369} 2366}
2370 2367
2371static void qlge_vlan_rx_kill_vid(struct net_device *ndev, u16 vid) 2368static void qlge_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
2372{ 2369{
2373 struct ql_adapter *qdev = netdev_priv(ndev); 2370 struct ql_adapter *qdev = netdev_priv(ndev);
2374 u32 enable_bit = 0;
2375 int status; 2371 int status;
2376 2372
2377 status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); 2373 status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
2378 if (status) 2374 if (status)
2379 return; 2375 return;
2380 2376
2377 __qlge_vlan_rx_add_vid(qdev, vid);
2378 set_bit(vid, qdev->active_vlans);
2379
2380 ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
2381}
2382
2383static void __qlge_vlan_rx_kill_vid(struct ql_adapter *qdev, u16 vid)
2384{
2385 u32 enable_bit = 0;
2386
2381 if (ql_set_mac_addr_reg 2387 if (ql_set_mac_addr_reg
2382 (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) { 2388 (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) {
2383 netif_err(qdev, ifup, qdev->ndev, 2389 netif_err(qdev, ifup, qdev->ndev,
2384 "Failed to clear vlan address.\n"); 2390 "Failed to clear vlan address.\n");
2385 } 2391 }
2386 ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); 2392}
2393
2394static void qlge_vlan_rx_kill_vid(struct net_device *ndev, u16 vid)
2395{
2396 struct ql_adapter *qdev = netdev_priv(ndev);
2397 int status;
2398
2399 status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
2400 if (status)
2401 return;
2402
2403 __qlge_vlan_rx_kill_vid(qdev, vid);
2404 clear_bit(vid, qdev->active_vlans);
2387 2405
2406 ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
2388} 2407}
2389 2408
2390static void qlge_restore_vlan(struct ql_adapter *qdev) 2409static void qlge_restore_vlan(struct ql_adapter *qdev)
2391{ 2410{
2392 qlge_vlan_rx_register(qdev->ndev, qdev->vlgrp); 2411 int status;
2412 u16 vid;
2393 2413
2394 if (qdev->vlgrp) { 2414 status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
2395 u16 vid; 2415 if (status)
2396 for (vid = 0; vid < VLAN_N_VID; vid++) { 2416 return;
2397 if (!vlan_group_get_device(qdev->vlgrp, vid)) 2417
2398 continue; 2418 for_each_set_bit(vid, qdev->active_vlans, VLAN_N_VID)
2399 qlge_vlan_rx_add_vid(qdev->ndev, vid); 2419 __qlge_vlan_rx_add_vid(qdev, vid);
2400 } 2420
2401 } 2421 ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
2402} 2422}
2403 2423
2404/* MSI-X Multiple Vector Interrupt Handler for inbound completions. */ 2424/* MSI-X Multiple Vector Interrupt Handler for inbound completions. */
@@ -4661,7 +4681,8 @@ static const struct net_device_ops qlge_netdev_ops = {
4661 .ndo_set_mac_address = qlge_set_mac_address, 4681 .ndo_set_mac_address = qlge_set_mac_address,
4662 .ndo_validate_addr = eth_validate_addr, 4682 .ndo_validate_addr = eth_validate_addr,
4663 .ndo_tx_timeout = qlge_tx_timeout, 4683 .ndo_tx_timeout = qlge_tx_timeout,
4664 .ndo_vlan_rx_register = qlge_vlan_rx_register, 4684 .ndo_fix_features = qlge_fix_features,
4685 .ndo_set_features = qlge_set_features,
4665 .ndo_vlan_rx_add_vid = qlge_vlan_rx_add_vid, 4686 .ndo_vlan_rx_add_vid = qlge_vlan_rx_add_vid,
4666 .ndo_vlan_rx_kill_vid = qlge_vlan_rx_kill_vid, 4687 .ndo_vlan_rx_kill_vid = qlge_vlan_rx_kill_vid,
4667}; 4688};