Commit cac925a4 authored by Jeff Garzik's avatar Jeff Garzik

Merge branch 'upstream' of git://lost.foo-projects.org/~ahkok/git/netdev-2.6 into tmp

parents bcd618e4 6224e01d
This diff is collapsed.
......@@ -2780,6 +2780,80 @@ static void e100_shutdown(struct pci_dev *pdev)
DPRINTK(PROBE,ERR, "Error enabling wake\n");
}
/* ------------------ PCI Error Recovery infrastructure -------------- */
/**
* e100_io_error_detected - called when PCI error is detected.
* @pdev: Pointer to PCI device
* @state: The current pci conneection state
*/
static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
/* Similar to calling e100_down(), but avoids adpater I/O. */
netdev->stop(netdev);
/* Detach; put netif into state similar to hotplug unplug. */
netif_poll_enable(netdev);
netif_device_detach(netdev);
/* Request a slot reset. */
return PCI_ERS_RESULT_NEED_RESET;
}
/**
* e100_io_slot_reset - called after the pci bus has been reset.
* @pdev: Pointer to PCI device
*
* Restart the card from scratch.
*/
static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct nic *nic = netdev_priv(netdev);
if (pci_enable_device(pdev)) {
printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n");
return PCI_ERS_RESULT_DISCONNECT;
}
pci_set_master(pdev);
/* Only one device per card can do a reset */
if (0 != PCI_FUNC(pdev->devfn))
return PCI_ERS_RESULT_RECOVERED;
e100_hw_reset(nic);
e100_phy_init(nic);
return PCI_ERS_RESULT_RECOVERED;
}
/**
* e100_io_resume - resume normal operations
* @pdev: Pointer to PCI device
*
* Resume normal operations after an error recovery
* sequence has been completed.
*/
static void e100_io_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct nic *nic = netdev_priv(netdev);
/* ack any pending wake events, disable PME */
pci_enable_wake(pdev, 0, 0);
netif_device_attach(netdev);
if (netif_running(netdev)) {
e100_open(netdev);
mod_timer(&nic->watchdog, jiffies);
}
}
static struct pci_error_handlers e100_err_handler = {
.error_detected = e100_io_error_detected,
.slot_reset = e100_io_slot_reset,
.resume = e100_io_resume,
};
static struct pci_driver e100_driver = {
.name = DRV_NAME,
......@@ -2791,6 +2865,7 @@ static struct pci_driver e100_driver = {
.resume = e100_resume,
#endif
.shutdown = e100_shutdown,
.err_handler = &e100_err_handler,
};
static int __init e100_init_module(void)
......
......@@ -189,6 +189,16 @@ static void e1000_shutdown(struct pci_dev *pdev);
static void e1000_netpoll (struct net_device *netdev);
#endif
static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
pci_channel_state_t state);
static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev);
static void e1000_io_resume(struct pci_dev *pdev);
static struct pci_error_handlers e1000_err_handler = {
.error_detected = e1000_io_error_detected,
.slot_reset = e1000_io_slot_reset,
.resume = e1000_io_resume,
};
static struct pci_driver e1000_driver = {
.name = e1000_driver_name,
......@@ -200,7 +210,8 @@ static struct pci_driver e1000_driver = {
.suspend = e1000_suspend,
.resume = e1000_resume,
#endif
.shutdown = e1000_shutdown
.shutdown = e1000_shutdown,
.err_handler = &e1000_err_handler
};
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
......@@ -3039,6 +3050,10 @@ e1000_update_stats(struct e1000_adapter *adapter)
#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
/* Prevent stats update while adapter is being reset */
if (adapter->link_speed == 0)
return;
spin_lock_irqsave(&adapter->stats_lock, flags);
/* these counters are modified from e1000_adjust_tbi_stats,
......@@ -4590,4 +4605,101 @@ e1000_netpoll(struct net_device *netdev)
}
#endif
/**
* e1000_io_error_detected - called when PCI error is detected
* @pdev: Pointer to PCI device
* @state: The current pci conneection state
*
* This function is called after a PCI bus error affecting
* this device has been detected.
*/
static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
netif_device_detach(netdev);
if (netif_running(netdev))
e1000_down(adapter);
/* Request a slot slot reset. */
return PCI_ERS_RESULT_NEED_RESET;
}
/**
* e1000_io_slot_reset - called after the pci bus has been reset.
* @pdev: Pointer to PCI device
*
* Restart the card from scratch, as if from a cold-boot. Implementation
* resembles the first-half of the e1000_resume routine.
*/
static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
if (pci_enable_device(pdev)) {
printk(KERN_ERR "e1000: Cannot re-enable PCI device after reset.\n");
return PCI_ERS_RESULT_DISCONNECT;
}
pci_set_master(pdev);
pci_enable_wake(pdev, 3, 0);
pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
/* Perform card reset only on one instance of the card */
if (PCI_FUNC (pdev->devfn) != 0)
return PCI_ERS_RESULT_RECOVERED;
e1000_reset(adapter);
E1000_WRITE_REG(&adapter->hw, WUS, ~0);
return PCI_ERS_RESULT_RECOVERED;
}
/**
* e1000_io_resume - called when traffic can start flowing again.
* @pdev: Pointer to PCI device
*
* This callback is called when the error recovery driver tells us that
* its OK to resume normal operation. Implementation resembles the
* second-half of the e1000_resume routine.
*/
static void e1000_io_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
uint32_t manc, swsm;
if (netif_running(netdev)) {
if (e1000_up(adapter)) {
printk("e1000: can't bring device back up after reset\n");
return;
}
}
netif_device_attach(netdev);
if (adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper) {
manc = E1000_READ_REG(&adapter->hw, MANC);
manc &= ~(E1000_MANC_ARP_EN);
E1000_WRITE_REG(&adapter->hw, MANC, manc);
}
switch (adapter->hw.mac_type) {
case e1000_82573:
swsm = E1000_READ_REG(&adapter->hw, SWSM);
E1000_WRITE_REG(&adapter->hw, SWSM,
swsm | E1000_SWSM_DRV_LOAD);
break;
default:
break;
}
if (netif_running(netdev))
mod_timer(&adapter->watchdog_timer, jiffies);
}
/* e1000_main.c */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment