diff options
Diffstat (limited to 'drivers/net/e1000/e1000_main.c')
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 114 |
1 files changed, 113 insertions, 1 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index bd709e562778..564fab4914e1 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -189,6 +189,16 @@ static void e1000_shutdown(struct pci_dev *pdev); | |||
189 | static void e1000_netpoll (struct net_device *netdev); | 189 | static void e1000_netpoll (struct net_device *netdev); |
190 | #endif | 190 | #endif |
191 | 191 | ||
192 | static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, | ||
193 | pci_channel_state_t state); | ||
194 | static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev); | ||
195 | static void e1000_io_resume(struct pci_dev *pdev); | ||
196 | |||
197 | static struct pci_error_handlers e1000_err_handler = { | ||
198 | .error_detected = e1000_io_error_detected, | ||
199 | .slot_reset = e1000_io_slot_reset, | ||
200 | .resume = e1000_io_resume, | ||
201 | }; | ||
192 | 202 | ||
193 | static struct pci_driver e1000_driver = { | 203 | static struct pci_driver e1000_driver = { |
194 | .name = e1000_driver_name, | 204 | .name = e1000_driver_name, |
@@ -200,7 +210,8 @@ static struct pci_driver e1000_driver = { | |||
200 | .suspend = e1000_suspend, | 210 | .suspend = e1000_suspend, |
201 | .resume = e1000_resume, | 211 | .resume = e1000_resume, |
202 | #endif | 212 | #endif |
203 | .shutdown = e1000_shutdown | 213 | .shutdown = e1000_shutdown, |
214 | .err_handler = &e1000_err_handler | ||
204 | }; | 215 | }; |
205 | 216 | ||
206 | MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); | 217 | MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); |
@@ -3039,6 +3050,10 @@ e1000_update_stats(struct e1000_adapter *adapter) | |||
3039 | 3050 | ||
3040 | #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF | 3051 | #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF |
3041 | 3052 | ||
3053 | /* Prevent stats update while adapter is being reset */ | ||
3054 | if (adapter->link_speed == 0) | ||
3055 | return; | ||
3056 | |||
3042 | spin_lock_irqsave(&adapter->stats_lock, flags); | 3057 | spin_lock_irqsave(&adapter->stats_lock, flags); |
3043 | 3058 | ||
3044 | /* these counters are modified from e1000_adjust_tbi_stats, | 3059 | /* these counters are modified from e1000_adjust_tbi_stats, |
@@ -4594,4 +4609,101 @@ e1000_netpoll(struct net_device *netdev) | |||
4594 | } | 4609 | } |
4595 | #endif | 4610 | #endif |
4596 | 4611 | ||
4612 | /** | ||
4613 | * e1000_io_error_detected - called when PCI error is detected | ||
4614 | * @pdev: Pointer to PCI device | ||
4615 | * @state: The current pci conneection state | ||
4616 | * | ||
4617 | * This function is called after a PCI bus error affecting | ||
4618 | * this device has been detected. | ||
4619 | */ | ||
4620 | static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) | ||
4621 | { | ||
4622 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
4623 | struct e1000_adapter *adapter = netdev->priv; | ||
4624 | |||
4625 | netif_device_detach(netdev); | ||
4626 | |||
4627 | if (netif_running(netdev)) | ||
4628 | e1000_down(adapter); | ||
4629 | |||
4630 | /* Request a slot slot reset. */ | ||
4631 | return PCI_ERS_RESULT_NEED_RESET; | ||
4632 | } | ||
4633 | |||
4634 | /** | ||
4635 | * e1000_io_slot_reset - called after the pci bus has been reset. | ||
4636 | * @pdev: Pointer to PCI device | ||
4637 | * | ||
4638 | * Restart the card from scratch, as if from a cold-boot. Implementation | ||
4639 | * resembles the first-half of the e1000_resume routine. | ||
4640 | */ | ||
4641 | static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) | ||
4642 | { | ||
4643 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
4644 | struct e1000_adapter *adapter = netdev->priv; | ||
4645 | |||
4646 | if (pci_enable_device(pdev)) { | ||
4647 | printk(KERN_ERR "e1000: Cannot re-enable PCI device after reset.\n"); | ||
4648 | return PCI_ERS_RESULT_DISCONNECT; | ||
4649 | } | ||
4650 | pci_set_master(pdev); | ||
4651 | |||
4652 | pci_enable_wake(pdev, 3, 0); | ||
4653 | pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */ | ||
4654 | |||
4655 | /* Perform card reset only on one instance of the card */ | ||
4656 | if (PCI_FUNC (pdev->devfn) != 0) | ||
4657 | return PCI_ERS_RESULT_RECOVERED; | ||
4658 | |||
4659 | e1000_reset(adapter); | ||
4660 | E1000_WRITE_REG(&adapter->hw, WUS, ~0); | ||
4661 | |||
4662 | return PCI_ERS_RESULT_RECOVERED; | ||
4663 | } | ||
4664 | |||
4665 | /** | ||
4666 | * e1000_io_resume - called when traffic can start flowing again. | ||
4667 | * @pdev: Pointer to PCI device | ||
4668 | * | ||
4669 | * This callback is called when the error recovery driver tells us that | ||
4670 | * its OK to resume normal operation. Implementation resembles the | ||
4671 | * second-half of the e1000_resume routine. | ||
4672 | */ | ||
4673 | static void e1000_io_resume(struct pci_dev *pdev) | ||
4674 | { | ||
4675 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
4676 | struct e1000_adapter *adapter = netdev->priv; | ||
4677 | uint32_t manc, swsm; | ||
4678 | |||
4679 | if (netif_running(netdev)) { | ||
4680 | if (e1000_up(adapter)) { | ||
4681 | printk("e1000: can't bring device back up after reset\n"); | ||
4682 | return; | ||
4683 | } | ||
4684 | } | ||
4685 | |||
4686 | netif_device_attach(netdev); | ||
4687 | |||
4688 | if (adapter->hw.mac_type >= e1000_82540 && | ||
4689 | adapter->hw.media_type == e1000_media_type_copper) { | ||
4690 | manc = E1000_READ_REG(&adapter->hw, MANC); | ||
4691 | manc &= ~(E1000_MANC_ARP_EN); | ||
4692 | E1000_WRITE_REG(&adapter->hw, MANC, manc); | ||
4693 | } | ||
4694 | |||
4695 | switch (adapter->hw.mac_type) { | ||
4696 | case e1000_82573: | ||
4697 | swsm = E1000_READ_REG(&adapter->hw, SWSM); | ||
4698 | E1000_WRITE_REG(&adapter->hw, SWSM, | ||
4699 | swsm | E1000_SWSM_DRV_LOAD); | ||
4700 | break; | ||
4701 | default: | ||
4702 | break; | ||
4703 | } | ||
4704 | |||
4705 | if (netif_running(netdev)) | ||
4706 | mod_timer(&adapter->watchdog_timer, jiffies); | ||
4707 | } | ||
4708 | |||
4597 | /* e1000_main.c */ | 4709 | /* e1000_main.c */ |