diff options
Diffstat (limited to 'drivers/net/forcedeth.c')
| -rw-r--r-- | drivers/net/forcedeth.c | 82 |
1 files changed, 62 insertions, 20 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 20d4fe96a81c..4ed89fa9ae46 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
| @@ -426,6 +426,7 @@ union ring_type { | |||
| 426 | #define NV_PCI_REGSZ_VER1 0x270 | 426 | #define NV_PCI_REGSZ_VER1 0x270 |
| 427 | #define NV_PCI_REGSZ_VER2 0x2d4 | 427 | #define NV_PCI_REGSZ_VER2 0x2d4 |
| 428 | #define NV_PCI_REGSZ_VER3 0x604 | 428 | #define NV_PCI_REGSZ_VER3 0x604 |
| 429 | #define NV_PCI_REGSZ_MAX 0x604 | ||
| 429 | 430 | ||
| 430 | /* various timeout delays: all in usec */ | 431 | /* various timeout delays: all in usec */ |
| 431 | #define NV_TXRX_RESET_DELAY 4 | 432 | #define NV_TXRX_RESET_DELAY 4 |
| @@ -784,6 +785,9 @@ struct fe_priv { | |||
| 784 | 785 | ||
| 785 | /* flow control */ | 786 | /* flow control */ |
| 786 | u32 pause_flags; | 787 | u32 pause_flags; |
| 788 | |||
| 789 | /* power saved state */ | ||
| 790 | u32 saved_config_space[NV_PCI_REGSZ_MAX/4]; | ||
| 787 | }; | 791 | }; |
| 788 | 792 | ||
| 789 | /* | 793 | /* |
| @@ -2827,6 +2831,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) | |||
| 2827 | */ | 2831 | */ |
| 2828 | nv_disable_irq(dev); | 2832 | nv_disable_irq(dev); |
| 2829 | netif_tx_lock_bh(dev); | 2833 | netif_tx_lock_bh(dev); |
| 2834 | netif_addr_lock(dev); | ||
| 2830 | spin_lock(&np->lock); | 2835 | spin_lock(&np->lock); |
| 2831 | /* stop engines */ | 2836 | /* stop engines */ |
| 2832 | nv_stop_rxtx(dev); | 2837 | nv_stop_rxtx(dev); |
| @@ -2851,6 +2856,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) | |||
| 2851 | /* restart rx engine */ | 2856 | /* restart rx engine */ |
| 2852 | nv_start_rxtx(dev); | 2857 | nv_start_rxtx(dev); |
| 2853 | spin_unlock(&np->lock); | 2858 | spin_unlock(&np->lock); |
| 2859 | netif_addr_unlock(dev); | ||
| 2854 | netif_tx_unlock_bh(dev); | 2860 | netif_tx_unlock_bh(dev); |
| 2855 | nv_enable_irq(dev); | 2861 | nv_enable_irq(dev); |
| 2856 | } | 2862 | } |
| @@ -2887,6 +2893,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr) | |||
| 2887 | 2893 | ||
| 2888 | if (netif_running(dev)) { | 2894 | if (netif_running(dev)) { |
| 2889 | netif_tx_lock_bh(dev); | 2895 | netif_tx_lock_bh(dev); |
| 2896 | netif_addr_lock(dev); | ||
| 2890 | spin_lock_irq(&np->lock); | 2897 | spin_lock_irq(&np->lock); |
| 2891 | 2898 | ||
| 2892 | /* stop rx engine */ | 2899 | /* stop rx engine */ |
| @@ -2898,6 +2905,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr) | |||
| 2898 | /* restart rx engine */ | 2905 | /* restart rx engine */ |
| 2899 | nv_start_rx(dev); | 2906 | nv_start_rx(dev); |
| 2900 | spin_unlock_irq(&np->lock); | 2907 | spin_unlock_irq(&np->lock); |
| 2908 | netif_addr_unlock(dev); | ||
| 2901 | netif_tx_unlock_bh(dev); | 2909 | netif_tx_unlock_bh(dev); |
| 2902 | } else { | 2910 | } else { |
| 2903 | nv_copy_mac_to_hw(dev); | 2911 | nv_copy_mac_to_hw(dev); |
| @@ -3967,6 +3975,7 @@ static void nv_do_nic_poll(unsigned long data) | |||
| 3967 | printk(KERN_INFO "forcedeth: MAC in recoverable error state\n"); | 3975 | printk(KERN_INFO "forcedeth: MAC in recoverable error state\n"); |
| 3968 | if (netif_running(dev)) { | 3976 | if (netif_running(dev)) { |
| 3969 | netif_tx_lock_bh(dev); | 3977 | netif_tx_lock_bh(dev); |
| 3978 | netif_addr_lock(dev); | ||
| 3970 | spin_lock(&np->lock); | 3979 | spin_lock(&np->lock); |
| 3971 | /* stop engines */ | 3980 | /* stop engines */ |
| 3972 | nv_stop_rxtx(dev); | 3981 | nv_stop_rxtx(dev); |
| @@ -3991,6 +4000,7 @@ static void nv_do_nic_poll(unsigned long data) | |||
| 3991 | /* restart rx engine */ | 4000 | /* restart rx engine */ |
| 3992 | nv_start_rxtx(dev); | 4001 | nv_start_rxtx(dev); |
| 3993 | spin_unlock(&np->lock); | 4002 | spin_unlock(&np->lock); |
| 4003 | netif_addr_unlock(dev); | ||
| 3994 | netif_tx_unlock_bh(dev); | 4004 | netif_tx_unlock_bh(dev); |
| 3995 | } | 4005 | } |
| 3996 | } | 4006 | } |
| @@ -4198,6 +4208,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
| 4198 | 4208 | ||
| 4199 | nv_disable_irq(dev); | 4209 | nv_disable_irq(dev); |
| 4200 | netif_tx_lock_bh(dev); | 4210 | netif_tx_lock_bh(dev); |
| 4211 | netif_addr_lock(dev); | ||
| 4201 | /* with plain spinlock lockdep complains */ | 4212 | /* with plain spinlock lockdep complains */ |
| 4202 | spin_lock_irqsave(&np->lock, flags); | 4213 | spin_lock_irqsave(&np->lock, flags); |
| 4203 | /* stop engines */ | 4214 | /* stop engines */ |
| @@ -4211,6 +4222,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
| 4211 | */ | 4222 | */ |
| 4212 | nv_stop_rxtx(dev); | 4223 | nv_stop_rxtx(dev); |
| 4213 | spin_unlock_irqrestore(&np->lock, flags); | 4224 | spin_unlock_irqrestore(&np->lock, flags); |
| 4225 | netif_addr_unlock(dev); | ||
| 4214 | netif_tx_unlock_bh(dev); | 4226 | netif_tx_unlock_bh(dev); |
| 4215 | } | 4227 | } |
| 4216 | 4228 | ||
| @@ -4356,10 +4368,12 @@ static int nv_nway_reset(struct net_device *dev) | |||
| 4356 | if (netif_running(dev)) { | 4368 | if (netif_running(dev)) { |
| 4357 | nv_disable_irq(dev); | 4369 | nv_disable_irq(dev); |
| 4358 | netif_tx_lock_bh(dev); | 4370 | netif_tx_lock_bh(dev); |
| 4371 | netif_addr_lock(dev); | ||
| 4359 | spin_lock(&np->lock); | 4372 | spin_lock(&np->lock); |
| 4360 | /* stop engines */ | 4373 | /* stop engines */ |
| 4361 | nv_stop_rxtx(dev); | 4374 | nv_stop_rxtx(dev); |
| 4362 | spin_unlock(&np->lock); | 4375 | spin_unlock(&np->lock); |
| 4376 | netif_addr_unlock(dev); | ||
| 4363 | netif_tx_unlock_bh(dev); | 4377 | netif_tx_unlock_bh(dev); |
| 4364 | printk(KERN_INFO "%s: link down.\n", dev->name); | 4378 | printk(KERN_INFO "%s: link down.\n", dev->name); |
| 4365 | } | 4379 | } |
| @@ -4467,6 +4481,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri | |||
| 4467 | if (netif_running(dev)) { | 4481 | if (netif_running(dev)) { |
| 4468 | nv_disable_irq(dev); | 4482 | nv_disable_irq(dev); |
| 4469 | netif_tx_lock_bh(dev); | 4483 | netif_tx_lock_bh(dev); |
| 4484 | netif_addr_lock(dev); | ||
| 4470 | spin_lock(&np->lock); | 4485 | spin_lock(&np->lock); |
| 4471 | /* stop engines */ | 4486 | /* stop engines */ |
| 4472 | nv_stop_rxtx(dev); | 4487 | nv_stop_rxtx(dev); |
| @@ -4515,6 +4530,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri | |||
| 4515 | /* restart engines */ | 4530 | /* restart engines */ |
| 4516 | nv_start_rxtx(dev); | 4531 | nv_start_rxtx(dev); |
| 4517 | spin_unlock(&np->lock); | 4532 | spin_unlock(&np->lock); |
| 4533 | netif_addr_unlock(dev); | ||
| 4518 | netif_tx_unlock_bh(dev); | 4534 | netif_tx_unlock_bh(dev); |
| 4519 | nv_enable_irq(dev); | 4535 | nv_enable_irq(dev); |
| 4520 | } | 4536 | } |
| @@ -4552,10 +4568,12 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam* | |||
| 4552 | if (netif_running(dev)) { | 4568 | if (netif_running(dev)) { |
| 4553 | nv_disable_irq(dev); | 4569 | nv_disable_irq(dev); |
| 4554 | netif_tx_lock_bh(dev); | 4570 | netif_tx_lock_bh(dev); |
| 4571 | netif_addr_lock(dev); | ||
| 4555 | spin_lock(&np->lock); | 4572 | spin_lock(&np->lock); |
| 4556 | /* stop engines */ | 4573 | /* stop engines */ |
| 4557 | nv_stop_rxtx(dev); | 4574 | nv_stop_rxtx(dev); |
| 4558 | spin_unlock(&np->lock); | 4575 | spin_unlock(&np->lock); |
| 4576 | netif_addr_unlock(dev); | ||
| 4559 | netif_tx_unlock_bh(dev); | 4577 | netif_tx_unlock_bh(dev); |
| 4560 | } | 4578 | } |
| 4561 | 4579 | ||
| @@ -4942,6 +4960,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64 | |||
| 4942 | napi_disable(&np->napi); | 4960 | napi_disable(&np->napi); |
| 4943 | #endif | 4961 | #endif |
| 4944 | netif_tx_lock_bh(dev); | 4962 | netif_tx_lock_bh(dev); |
| 4963 | netif_addr_lock(dev); | ||
| 4945 | spin_lock_irq(&np->lock); | 4964 | spin_lock_irq(&np->lock); |
| 4946 | nv_disable_hw_interrupts(dev, np->irqmask); | 4965 | nv_disable_hw_interrupts(dev, np->irqmask); |
| 4947 | if (!(np->msi_flags & NV_MSI_X_ENABLED)) { | 4966 | if (!(np->msi_flags & NV_MSI_X_ENABLED)) { |
| @@ -4955,6 +4974,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64 | |||
| 4955 | /* drain rx queue */ | 4974 | /* drain rx queue */ |
| 4956 | nv_drain_rxtx(dev); | 4975 | nv_drain_rxtx(dev); |
| 4957 | spin_unlock_irq(&np->lock); | 4976 | spin_unlock_irq(&np->lock); |
| 4977 | netif_addr_unlock(dev); | ||
| 4958 | netif_tx_unlock_bh(dev); | 4978 | netif_tx_unlock_bh(dev); |
| 4959 | } | 4979 | } |
| 4960 | 4980 | ||
| @@ -5566,6 +5586,11 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
| 5566 | /* set mac address */ | 5586 | /* set mac address */ |
| 5567 | nv_copy_mac_to_hw(dev); | 5587 | nv_copy_mac_to_hw(dev); |
| 5568 | 5588 | ||
| 5589 | /* Workaround current PCI init glitch: wakeup bits aren't | ||
| 5590 | * being set from PCI PM capability. | ||
| 5591 | */ | ||
| 5592 | device_init_wakeup(&pci_dev->dev, 1); | ||
| 5593 | |||
| 5569 | /* disable WOL */ | 5594 | /* disable WOL */ |
| 5570 | writel(0, base + NvRegWakeUpFlags); | 5595 | writel(0, base + NvRegWakeUpFlags); |
| 5571 | np->wolenabled = 0; | 5596 | np->wolenabled = 0; |
| @@ -5816,50 +5841,66 @@ static int nv_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 5816 | { | 5841 | { |
| 5817 | struct net_device *dev = pci_get_drvdata(pdev); | 5842 | struct net_device *dev = pci_get_drvdata(pdev); |
| 5818 | struct fe_priv *np = netdev_priv(dev); | 5843 | struct fe_priv *np = netdev_priv(dev); |
| 5844 | u8 __iomem *base = get_hwbase(dev); | ||
| 5845 | int i; | ||
| 5819 | 5846 | ||
| 5820 | if (!netif_running(dev)) | 5847 | if (netif_running(dev)) { |
| 5821 | goto out; | 5848 | // Gross. |
| 5822 | 5849 | nv_close(dev); | |
| 5850 | } | ||
| 5823 | netif_device_detach(dev); | 5851 | netif_device_detach(dev); |
| 5824 | 5852 | ||
| 5825 | // Gross. | 5853 | /* save non-pci configuration space */ |
| 5826 | nv_close(dev); | 5854 | for (i = 0;i <= np->register_size/sizeof(u32); i++) |
| 5855 | np->saved_config_space[i] = readl(base + i*sizeof(u32)); | ||
| 5827 | 5856 | ||
| 5828 | pci_save_state(pdev); | 5857 | pci_save_state(pdev); |
| 5829 | pci_enable_wake(pdev, pci_choose_state(pdev, state), np->wolenabled); | 5858 | pci_enable_wake(pdev, pci_choose_state(pdev, state), np->wolenabled); |
| 5859 | pci_disable_device(pdev); | ||
| 5830 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | 5860 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); |
| 5831 | out: | ||
| 5832 | return 0; | 5861 | return 0; |
| 5833 | } | 5862 | } |
| 5834 | 5863 | ||
| 5835 | static int nv_resume(struct pci_dev *pdev) | 5864 | static int nv_resume(struct pci_dev *pdev) |
| 5836 | { | 5865 | { |
| 5837 | struct net_device *dev = pci_get_drvdata(pdev); | 5866 | struct net_device *dev = pci_get_drvdata(pdev); |
| 5867 | struct fe_priv *np = netdev_priv(dev); | ||
| 5838 | u8 __iomem *base = get_hwbase(dev); | 5868 | u8 __iomem *base = get_hwbase(dev); |
| 5839 | int rc = 0; | 5869 | int i, rc = 0; |
| 5840 | u32 txreg; | ||
| 5841 | |||
| 5842 | if (!netif_running(dev)) | ||
| 5843 | goto out; | ||
| 5844 | |||
| 5845 | netif_device_attach(dev); | ||
| 5846 | 5870 | ||
| 5847 | pci_set_power_state(pdev, PCI_D0); | 5871 | pci_set_power_state(pdev, PCI_D0); |
| 5848 | pci_restore_state(pdev); | 5872 | pci_restore_state(pdev); |
| 5873 | /* ack any pending wake events, disable PME */ | ||
| 5849 | pci_enable_wake(pdev, PCI_D0, 0); | 5874 | pci_enable_wake(pdev, PCI_D0, 0); |
| 5850 | 5875 | ||
| 5851 | /* restore mac address reverse flag */ | 5876 | /* restore non-pci configuration space */ |
| 5852 | txreg = readl(base + NvRegTransmitPoll); | 5877 | for (i = 0;i <= np->register_size/sizeof(u32); i++) |
| 5853 | txreg |= NVREG_TRANSMITPOLL_MAC_ADDR_REV; | 5878 | writel(np->saved_config_space[i], base+i*sizeof(u32)); |
| 5854 | writel(txreg, base + NvRegTransmitPoll); | ||
| 5855 | 5879 | ||
| 5856 | rc = nv_open(dev); | 5880 | netif_device_attach(dev); |
| 5857 | nv_set_multicast(dev); | 5881 | if (netif_running(dev)) { |
| 5858 | out: | 5882 | rc = nv_open(dev); |
| 5883 | nv_set_multicast(dev); | ||
| 5884 | } | ||
| 5859 | return rc; | 5885 | return rc; |
| 5860 | } | 5886 | } |
| 5887 | |||
| 5888 | static void nv_shutdown(struct pci_dev *pdev) | ||
| 5889 | { | ||
| 5890 | struct net_device *dev = pci_get_drvdata(pdev); | ||
| 5891 | struct fe_priv *np = netdev_priv(dev); | ||
| 5892 | |||
| 5893 | if (netif_running(dev)) | ||
| 5894 | nv_close(dev); | ||
| 5895 | |||
| 5896 | pci_enable_wake(pdev, PCI_D3hot, np->wolenabled); | ||
| 5897 | pci_enable_wake(pdev, PCI_D3cold, np->wolenabled); | ||
| 5898 | pci_disable_device(pdev); | ||
| 5899 | pci_set_power_state(pdev, PCI_D3hot); | ||
| 5900 | } | ||
| 5861 | #else | 5901 | #else |
| 5862 | #define nv_suspend NULL | 5902 | #define nv_suspend NULL |
| 5903 | #define nv_shutdown NULL | ||
| 5863 | #define nv_resume NULL | 5904 | #define nv_resume NULL |
| 5864 | #endif /* CONFIG_PM */ | 5905 | #endif /* CONFIG_PM */ |
| 5865 | 5906 | ||
| @@ -6030,6 +6071,7 @@ static struct pci_driver driver = { | |||
| 6030 | .remove = __devexit_p(nv_remove), | 6071 | .remove = __devexit_p(nv_remove), |
| 6031 | .suspend = nv_suspend, | 6072 | .suspend = nv_suspend, |
| 6032 | .resume = nv_resume, | 6073 | .resume = nv_resume, |
| 6074 | .shutdown = nv_shutdown, | ||
| 6033 | }; | 6075 | }; |
| 6034 | 6076 | ||
| 6035 | static int __init init_nic(void) | 6077 | static int __init init_nic(void) |
