diff options
author | Jiri Pirko <jpirko@redhat.com> | 2011-07-20 23:24:11 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-07-21 16:47:55 -0400 |
commit | 18c49b91777c66265d640f8fb221039bdf46b2d3 (patch) | |
tree | f245cc6eb83402897abd60d22a9fac59fdbe973a /drivers/net/qlge | |
parent | f1b553fbe73bfad38f41269d1c7a7ce3176d9539 (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.h | 3 | ||||
-rw-r--r-- | drivers/net/qlge/qlge_main.c | 161 |
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; |
1609 | err_out: | 1605 | err_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 | ||
1724 | static void ql_realign_skb(struct sk_buff *skb, int len) | 1714 | static 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 | ||
2337 | static void qlge_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp) | 2317 | static 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 | ||
2354 | static void qlge_vlan_rx_add_vid(struct net_device *ndev, u16 vid) | 2333 | static 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 | |||
2347 | static 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 | |||
2357 | static 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 | ||
2371 | static void qlge_vlan_rx_kill_vid(struct net_device *ndev, u16 vid) | 2368 | static 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 | |||
2383 | static 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 | |||
2394 | static 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 | ||
2390 | static void qlge_restore_vlan(struct ql_adapter *qdev) | 2409 | static 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 | }; |