diff options
author | Alexander Duyck <alexander.h.duyck@intel.com> | 2008-09-11 23:04:56 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-09-24 18:55:05 -0400 |
commit | b3c8b4ba619f3d461e01c27cdda02adcd48f02d4 (patch) | |
tree | 34750ff003507fb278cd548dabf178de53d62212 /drivers/net/ixgbe/ixgbe_main.c | |
parent | b46172402f39719e97b921cc3ca85141f3e8b1c2 (diff) |
ixgbe: correctly add and remove napi queues
This patch corrects support for NAPI so that queues are correctly added and
removed during suspend/resume in the event that the number of MSI-X vectors
changes.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_main.c')
-rw-r--r-- | drivers/net/ixgbe/ixgbe_main.c | 230 |
1 files changed, 130 insertions, 100 deletions
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 2980a3736457..a8edbad0335e 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
@@ -2023,43 +2023,6 @@ void ixgbe_reset(struct ixgbe_adapter *adapter) | |||
2023 | 2023 | ||
2024 | } | 2024 | } |
2025 | 2025 | ||
2026 | #ifdef CONFIG_PM | ||
2027 | static int ixgbe_resume(struct pci_dev *pdev) | ||
2028 | { | ||
2029 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
2030 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
2031 | u32 err; | ||
2032 | |||
2033 | pci_set_power_state(pdev, PCI_D0); | ||
2034 | pci_restore_state(pdev); | ||
2035 | err = pci_enable_device(pdev); | ||
2036 | if (err) { | ||
2037 | printk(KERN_ERR "ixgbe: Cannot enable PCI device from " \ | ||
2038 | "suspend\n"); | ||
2039 | return err; | ||
2040 | } | ||
2041 | pci_set_master(pdev); | ||
2042 | |||
2043 | pci_enable_wake(pdev, PCI_D3hot, 0); | ||
2044 | pci_enable_wake(pdev, PCI_D3cold, 0); | ||
2045 | |||
2046 | if (netif_running(netdev)) { | ||
2047 | err = ixgbe_request_irq(adapter); | ||
2048 | if (err) | ||
2049 | return err; | ||
2050 | } | ||
2051 | |||
2052 | ixgbe_reset(adapter); | ||
2053 | |||
2054 | if (netif_running(netdev)) | ||
2055 | ixgbe_up(adapter); | ||
2056 | |||
2057 | netif_device_attach(netdev); | ||
2058 | |||
2059 | return 0; | ||
2060 | } | ||
2061 | #endif | ||
2062 | |||
2063 | /** | 2026 | /** |
2064 | * ixgbe_clean_rx_ring - Free Rx Buffers per Queue | 2027 | * ixgbe_clean_rx_ring - Free Rx Buffers per Queue |
2065 | * @adapter: board private structure | 2028 | * @adapter: board private structure |
@@ -2230,44 +2193,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter) | |||
2230 | #endif | 2193 | #endif |
2231 | } | 2194 | } |
2232 | 2195 | ||
2233 | static int ixgbe_suspend(struct pci_dev *pdev, pm_message_t state) | ||
2234 | { | ||
2235 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
2236 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
2237 | #ifdef CONFIG_PM | ||
2238 | int retval = 0; | ||
2239 | #endif | ||
2240 | |||
2241 | netif_device_detach(netdev); | ||
2242 | |||
2243 | if (netif_running(netdev)) { | ||
2244 | ixgbe_down(adapter); | ||
2245 | ixgbe_free_irq(adapter); | ||
2246 | } | ||
2247 | |||
2248 | #ifdef CONFIG_PM | ||
2249 | retval = pci_save_state(pdev); | ||
2250 | if (retval) | ||
2251 | return retval; | ||
2252 | #endif | ||
2253 | |||
2254 | pci_enable_wake(pdev, PCI_D3hot, 0); | ||
2255 | pci_enable_wake(pdev, PCI_D3cold, 0); | ||
2256 | |||
2257 | ixgbe_release_hw_control(adapter); | ||
2258 | |||
2259 | pci_disable_device(pdev); | ||
2260 | |||
2261 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
2262 | |||
2263 | return 0; | ||
2264 | } | ||
2265 | |||
2266 | static void ixgbe_shutdown(struct pci_dev *pdev) | ||
2267 | { | ||
2268 | ixgbe_suspend(pdev, PMSG_SUSPEND); | ||
2269 | } | ||
2270 | |||
2271 | /** | 2196 | /** |
2272 | * ixgbe_poll - NAPI Rx polling callback | 2197 | * ixgbe_poll - NAPI Rx polling callback |
2273 | * @napi: structure for representing this polling device | 2198 | * @napi: structure for representing this polling device |
@@ -3023,6 +2948,135 @@ static int ixgbe_close(struct net_device *netdev) | |||
3023 | } | 2948 | } |
3024 | 2949 | ||
3025 | /** | 2950 | /** |
2951 | * ixgbe_napi_add_all - prep napi structs for use | ||
2952 | * @adapter: private struct | ||
2953 | * helper function to napi_add each possible q_vector->napi | ||
2954 | */ | ||
2955 | static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter) | ||
2956 | { | ||
2957 | int q_idx, q_vectors; | ||
2958 | int (*poll)(struct napi_struct *, int); | ||
2959 | |||
2960 | if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { | ||
2961 | poll = &ixgbe_clean_rxonly; | ||
2962 | /* Only enable as many vectors as we have rx queues. */ | ||
2963 | q_vectors = adapter->num_rx_queues; | ||
2964 | } else { | ||
2965 | poll = &ixgbe_poll; | ||
2966 | /* only one q_vector for legacy modes */ | ||
2967 | q_vectors = 1; | ||
2968 | } | ||
2969 | |||
2970 | for (q_idx = 0; q_idx < q_vectors; q_idx++) { | ||
2971 | struct ixgbe_q_vector *q_vector = &adapter->q_vector[q_idx]; | ||
2972 | netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64); | ||
2973 | } | ||
2974 | } | ||
2975 | |||
2976 | static void ixgbe_napi_del_all(struct ixgbe_adapter *adapter) | ||
2977 | { | ||
2978 | int q_idx; | ||
2979 | int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; | ||
2980 | |||
2981 | /* legacy and MSI only use one vector */ | ||
2982 | if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) | ||
2983 | q_vectors = 1; | ||
2984 | |||
2985 | for (q_idx = 0; q_idx < q_vectors; q_idx++) { | ||
2986 | struct ixgbe_q_vector *q_vector = &adapter->q_vector[q_idx]; | ||
2987 | if (!q_vector->rxr_count) | ||
2988 | continue; | ||
2989 | netif_napi_del(&q_vector->napi); | ||
2990 | } | ||
2991 | } | ||
2992 | |||
2993 | #ifdef CONFIG_PM | ||
2994 | static int ixgbe_resume(struct pci_dev *pdev) | ||
2995 | { | ||
2996 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
2997 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
2998 | u32 err; | ||
2999 | |||
3000 | pci_set_power_state(pdev, PCI_D0); | ||
3001 | pci_restore_state(pdev); | ||
3002 | err = pci_enable_device(pdev); | ||
3003 | if (err) { | ||
3004 | printk(KERN_ERR "ixgbe: Cannot enable PCI device from " \ | ||
3005 | "suspend\n"); | ||
3006 | return err; | ||
3007 | } | ||
3008 | pci_set_master(pdev); | ||
3009 | |||
3010 | pci_enable_wake(pdev, PCI_D3hot, 0); | ||
3011 | pci_enable_wake(pdev, PCI_D3cold, 0); | ||
3012 | |||
3013 | err = ixgbe_init_interrupt_scheme(adapter); | ||
3014 | if (err) { | ||
3015 | printk(KERN_ERR "ixgbe: Cannot initialize interrupts for " | ||
3016 | "device\n"); | ||
3017 | return err; | ||
3018 | } | ||
3019 | |||
3020 | ixgbe_napi_add_all(adapter); | ||
3021 | ixgbe_reset(adapter); | ||
3022 | |||
3023 | if (netif_running(netdev)) { | ||
3024 | err = ixgbe_open(adapter->netdev); | ||
3025 | if (err) | ||
3026 | return err; | ||
3027 | } | ||
3028 | |||
3029 | netif_device_attach(netdev); | ||
3030 | |||
3031 | return 0; | ||
3032 | } | ||
3033 | |||
3034 | #endif /* CONFIG_PM */ | ||
3035 | static int ixgbe_suspend(struct pci_dev *pdev, pm_message_t state) | ||
3036 | { | ||
3037 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
3038 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
3039 | #ifdef CONFIG_PM | ||
3040 | int retval = 0; | ||
3041 | #endif | ||
3042 | |||
3043 | netif_device_detach(netdev); | ||
3044 | |||
3045 | if (netif_running(netdev)) { | ||
3046 | ixgbe_down(adapter); | ||
3047 | ixgbe_free_irq(adapter); | ||
3048 | ixgbe_free_all_tx_resources(adapter); | ||
3049 | ixgbe_free_all_rx_resources(adapter); | ||
3050 | } | ||
3051 | ixgbe_reset_interrupt_capability(adapter); | ||
3052 | ixgbe_napi_del_all(adapter); | ||
3053 | kfree(adapter->tx_ring); | ||
3054 | kfree(adapter->rx_ring); | ||
3055 | |||
3056 | #ifdef CONFIG_PM | ||
3057 | retval = pci_save_state(pdev); | ||
3058 | if (retval) | ||
3059 | return retval; | ||
3060 | #endif | ||
3061 | |||
3062 | pci_enable_wake(pdev, PCI_D3hot, 0); | ||
3063 | pci_enable_wake(pdev, PCI_D3cold, 0); | ||
3064 | |||
3065 | ixgbe_release_hw_control(adapter); | ||
3066 | |||
3067 | pci_disable_device(pdev); | ||
3068 | |||
3069 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
3070 | |||
3071 | return 0; | ||
3072 | } | ||
3073 | |||
3074 | static void ixgbe_shutdown(struct pci_dev *pdev) | ||
3075 | { | ||
3076 | ixgbe_suspend(pdev, PMSG_SUSPEND); | ||
3077 | } | ||
3078 | |||
3079 | /** | ||
3026 | * ixgbe_update_stats - Update the board statistics counters. | 3080 | * ixgbe_update_stats - Update the board statistics counters. |
3027 | * @adapter: board private structure | 3081 | * @adapter: board private structure |
3028 | **/ | 3082 | **/ |
@@ -3657,31 +3711,6 @@ static int ixgbe_link_config(struct ixgbe_hw *hw) | |||
3657 | } | 3711 | } |
3658 | 3712 | ||
3659 | /** | 3713 | /** |
3660 | * ixgbe_napi_add_all - prep napi structs for use | ||
3661 | * @adapter: private struct | ||
3662 | * helper function to napi_add each possible q_vector->napi | ||
3663 | */ | ||
3664 | static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter) | ||
3665 | { | ||
3666 | int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; | ||
3667 | int (*poll)(struct napi_struct *, int); | ||
3668 | |||
3669 | if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { | ||
3670 | poll = &ixgbe_clean_rxonly; | ||
3671 | } else { | ||
3672 | poll = &ixgbe_poll; | ||
3673 | /* only one q_vector for legacy modes */ | ||
3674 | q_vectors = 1; | ||
3675 | } | ||
3676 | |||
3677 | for (i = 0; i < q_vectors; i++) { | ||
3678 | struct ixgbe_q_vector *q_vector = &adapter->q_vector[i]; | ||
3679 | netif_napi_add(adapter->netdev, &q_vector->napi, | ||
3680 | (*poll), 64); | ||
3681 | } | ||
3682 | } | ||
3683 | |||
3684 | /** | ||
3685 | * ixgbe_probe - Device Initialization Routine | 3714 | * ixgbe_probe - Device Initialization Routine |
3686 | * @pdev: PCI device information struct | 3715 | * @pdev: PCI device information struct |
3687 | * @ent: entry in ixgbe_pci_tbl | 3716 | * @ent: entry in ixgbe_pci_tbl |
@@ -3977,6 +4006,7 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) | |||
3977 | pci_release_regions(pdev); | 4006 | pci_release_regions(pdev); |
3978 | 4007 | ||
3979 | DPRINTK(PROBE, INFO, "complete\n"); | 4008 | DPRINTK(PROBE, INFO, "complete\n"); |
4009 | ixgbe_napi_del_all(adapter); | ||
3980 | kfree(adapter->tx_ring); | 4010 | kfree(adapter->tx_ring); |
3981 | kfree(adapter->rx_ring); | 4011 | kfree(adapter->rx_ring); |
3982 | 4012 | ||