aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ixgb/ixgb_main.c
diff options
context:
space:
mode:
authorLinas Vepstas <linas@austin.ibm.com>2006-08-31 17:27:52 -0400
committerAuke Kok <juke-jan.h.kok@intel.com>2006-08-31 17:27:52 -0400
commit01748fbb413d6f3b36c330544969d1d7254ee509 (patch)
tree1148455cf4d76d0b4bc17186790710282339449c /drivers/net/ixgb/ixgb_main.c
parentadc5413965e6ca2cd18f0ec89933f762b5605574 (diff)
ixgb: Add PCI Error recovery callbacks
Adds PCI Error recovery callbacks to the Intel 10-gigabit ethernet ixgb device driver. Lightly tested, works. "Zhang, Yanmin" <yanmin_zhang@linux.intel.com> wrote: Both pci_disable_device and ixgb_down would access the device. It doesn't follow Documentation/pci-error-recovery.txt that error_detected shouldn't do any access to the device. Signed-off-by: Linas Vepstas <linas@austin.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>
Diffstat (limited to 'drivers/net/ixgb/ixgb_main.c')
-rw-r--r--drivers/net/ixgb/ixgb_main.c112
1 files changed, 111 insertions, 1 deletions
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index a5da48a1fca0..abca75fd2892 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -118,15 +118,26 @@ static void ixgb_restore_vlan(struct ixgb_adapter *adapter);
118static void ixgb_netpoll(struct net_device *dev); 118static void ixgb_netpoll(struct net_device *dev);
119#endif 119#endif
120 120
121/* Exported from other modules */ 121static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev,
122 enum pci_channel_state state);
123static pci_ers_result_t ixgb_io_slot_reset (struct pci_dev *pdev);
124static void ixgb_io_resume (struct pci_dev *pdev);
122 125
126/* Exported from other modules */
123extern void ixgb_check_options(struct ixgb_adapter *adapter); 127extern void ixgb_check_options(struct ixgb_adapter *adapter);
124 128
129static struct pci_error_handlers ixgb_err_handler = {
130 .error_detected = ixgb_io_error_detected,
131 .slot_reset = ixgb_io_slot_reset,
132 .resume = ixgb_io_resume,
133};
134
125static struct pci_driver ixgb_driver = { 135static struct pci_driver ixgb_driver = {
126 .name = ixgb_driver_name, 136 .name = ixgb_driver_name,
127 .id_table = ixgb_pci_tbl, 137 .id_table = ixgb_pci_tbl,
128 .probe = ixgb_probe, 138 .probe = ixgb_probe,
129 .remove = __devexit_p(ixgb_remove), 139 .remove = __devexit_p(ixgb_remove),
140 .err_handler = &ixgb_err_handler
130}; 141};
131 142
132MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); 143MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
@@ -1550,6 +1561,11 @@ void
1550ixgb_update_stats(struct ixgb_adapter *adapter) 1561ixgb_update_stats(struct ixgb_adapter *adapter)
1551{ 1562{
1552 struct net_device *netdev = adapter->netdev; 1563 struct net_device *netdev = adapter->netdev;
1564 struct pci_dev *pdev = adapter->pdev;
1565
1566 /* Prevent stats update while adapter is being reset */
1567 if (pdev->error_state && pdev->error_state != pci_channel_io_normal)
1568 return;
1553 1569
1554 if((netdev->flags & IFF_PROMISC) || (netdev->flags & IFF_ALLMULTI) || 1570 if((netdev->flags & IFF_PROMISC) || (netdev->flags & IFF_ALLMULTI) ||
1555 (netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES)) { 1571 (netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES)) {
@@ -2205,4 +2221,98 @@ static void ixgb_netpoll(struct net_device *dev)
2205} 2221}
2206#endif 2222#endif
2207 2223
2224/**
2225 * ixgb_io_error_detected() - called when PCI error is detected
2226 * @pdev pointer to pci device with error
2227 * @state pci channel state after error
2228 *
2229 * This callback is called by the PCI subsystem whenever
2230 * a PCI bus error is detected.
2231 */
2232static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev,
2233 enum pci_channel_state state)
2234{
2235 struct net_device *netdev = pci_get_drvdata(pdev);
2236 struct ixgb_adapter *adapter = netdev->priv;
2237
2238 if(netif_running(netdev))
2239 ixgb_down(adapter, TRUE);
2240
2241 pci_disable_device(pdev);
2242
2243 /* Request a slot reset. */
2244 return PCI_ERS_RESULT_NEED_RESET;
2245}
2246
2247/**
2248 * ixgb_io_slot_reset - called after the pci bus has been reset.
2249 * @pdev pointer to pci device with error
2250 *
2251 * This callback is called after the PCI buss has been reset.
2252 * Basically, this tries to restart the card from scratch.
2253 * This is a shortened version of the device probe/discovery code,
2254 * it resembles the first-half of the ixgb_probe() routine.
2255 */
2256static pci_ers_result_t ixgb_io_slot_reset (struct pci_dev *pdev)
2257{
2258 struct net_device *netdev = pci_get_drvdata(pdev);
2259 struct ixgb_adapter *adapter = netdev->priv;
2260
2261 if(pci_enable_device(pdev)) {
2262 DPRINTK(PROBE, ERR, "Cannot re-enable PCI device after reset.\n");
2263 return PCI_ERS_RESULT_DISCONNECT;
2264 }
2265
2266 /* Perform card reset only on one instance of the card */
2267 if (0 != PCI_FUNC (pdev->devfn))
2268 return PCI_ERS_RESULT_RECOVERED;
2269
2270 pci_set_master(pdev);
2271
2272 netif_carrier_off(netdev);
2273 netif_stop_queue(netdev);
2274 ixgb_reset(adapter);
2275
2276 /* Make sure the EEPROM is good */
2277 if(!ixgb_validate_eeprom_checksum(&adapter->hw)) {
2278 DPRINTK(PROBE, ERR, "After reset, the EEPROM checksum is not valid.\n");
2279 return PCI_ERS_RESULT_DISCONNECT;
2280 }
2281 ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);
2282 memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
2283
2284 if(!is_valid_ether_addr(netdev->perm_addr)) {
2285 DPRINTK(PROBE, ERR, "After reset, invalid MAC address.\n");
2286 return PCI_ERS_RESULT_DISCONNECT;
2287 }
2288
2289 return PCI_ERS_RESULT_RECOVERED;
2290}
2291
2292/**
2293 * ixgb_io_resume - called when its OK to resume normal operations
2294 * @pdev pointer to pci device with error
2295 *
2296 * The error recovery driver tells us that its OK to resume
2297 * normal operation. Implementation resembles the second-half
2298 * of the ixgb_probe() routine.
2299 */
2300static void ixgb_io_resume (struct pci_dev *pdev)
2301{
2302 struct net_device *netdev = pci_get_drvdata(pdev);
2303 struct ixgb_adapter *adapter = netdev->priv;
2304
2305 pci_set_master(pdev);
2306
2307 if(netif_running(netdev)) {
2308 if(ixgb_up(adapter)) {
2309 printk ("ixgb: can't bring device back up after reset\n");
2310 return;
2311 }
2312 }
2313
2314 netif_device_attach(netdev);
2315 mod_timer(&adapter->watchdog_timer, jiffies);
2316}
2317
2208/* ixgb_main.c */ 2318/* ixgb_main.c */