Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bnx2x: Add PCIE EEH support

Add PCI recovery functions to the driver. The initial PCI state is
also saved so the MSI state can be restored during PCI recovery.

Signed-off-by: Wendy Xiong <wendyx@us.ibm.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Wendy Xiong and committed by
David S. Miller
493adb1f f3c87cdd

+95 -6
+95 -6
drivers/net/bnx2x_main.c
··· 10181 10181 return rc; 10182 10182 } 10183 10183 10184 + /** 10185 + * bnx2x_io_error_detected - called when PCI error is detected 10186 + * @pdev: Pointer to PCI device 10187 + * @state: The current pci connection state 10188 + * 10189 + * This function is called after a PCI bus error affecting 10190 + * this device has been detected. 10191 + */ 10192 + static pci_ers_result_t bnx2x_io_error_detected(struct pci_dev *pdev, 10193 + pci_channel_state_t state) 10194 + { 10195 + struct net_device *dev = pci_get_drvdata(pdev); 10196 + struct bnx2x *bp = netdev_priv(dev); 10197 + 10198 + rtnl_lock(); 10199 + 10200 + netif_device_detach(dev); 10201 + 10202 + if (netif_running(dev)) 10203 + bnx2x_nic_unload(bp, UNLOAD_CLOSE); 10204 + 10205 + pci_disable_device(pdev); 10206 + 10207 + rtnl_unlock(); 10208 + 10209 + /* Request a slot reset */ 10210 + return PCI_ERS_RESULT_NEED_RESET; 10211 + } 10212 + 10213 + /** 10214 + * bnx2x_io_slot_reset - called after the PCI bus has been reset 10215 + * @pdev: Pointer to PCI device 10216 + * 10217 + * Restart the card from scratch, as if from a cold-boot. 10218 + */ 10219 + static pci_ers_result_t bnx2x_io_slot_reset(struct pci_dev *pdev) 10220 + { 10221 + struct net_device *dev = pci_get_drvdata(pdev); 10222 + struct bnx2x *bp = netdev_priv(dev); 10223 + 10224 + rtnl_lock(); 10225 + 10226 + if (pci_enable_device(pdev)) { 10227 + dev_err(&pdev->dev, 10228 + "Cannot re-enable PCI device after reset\n"); 10229 + rtnl_unlock(); 10230 + return PCI_ERS_RESULT_DISCONNECT; 10231 + } 10232 + 10233 + pci_set_master(pdev); 10234 + pci_restore_state(pdev); 10235 + 10236 + if (netif_running(dev)) 10237 + bnx2x_set_power_state(bp, PCI_D0); 10238 + 10239 + rtnl_unlock(); 10240 + 10241 + return PCI_ERS_RESULT_RECOVERED; 10242 + } 10243 + 10244 + /** 10245 + * bnx2x_io_resume - called when traffic can start flowing again 10246 + * @pdev: Pointer to PCI device 10247 + * 10248 + * This callback is called when the error recovery driver tells us that 10249 + * its OK to resume normal operation. 10250 + */ 10251 + static void bnx2x_io_resume(struct pci_dev *pdev) 10252 + { 10253 + struct net_device *dev = pci_get_drvdata(pdev); 10254 + struct bnx2x *bp = netdev_priv(dev); 10255 + 10256 + rtnl_lock(); 10257 + 10258 + if (netif_running(dev)) 10259 + bnx2x_nic_load(bp, LOAD_OPEN); 10260 + 10261 + netif_device_attach(dev); 10262 + 10263 + rtnl_unlock(); 10264 + } 10265 + 10266 + static struct pci_error_handlers bnx2x_err_handler = { 10267 + .error_detected = bnx2x_io_error_detected, 10268 + .slot_reset = bnx2x_io_slot_reset, 10269 + .resume = bnx2x_io_resume, 10270 + }; 10271 + 10184 10272 static struct pci_driver bnx2x_pci_driver = { 10185 - .name = DRV_MODULE_NAME, 10186 - .id_table = bnx2x_pci_tbl, 10187 - .probe = bnx2x_init_one, 10188 - .remove = __devexit_p(bnx2x_remove_one), 10189 - .suspend = bnx2x_suspend, 10190 - .resume = bnx2x_resume, 10273 + .name = DRV_MODULE_NAME, 10274 + .id_table = bnx2x_pci_tbl, 10275 + .probe = bnx2x_init_one, 10276 + .remove = __devexit_p(bnx2x_remove_one), 10277 + .suspend = bnx2x_suspend, 10278 + .resume = bnx2x_resume, 10279 + .err_handler = &bnx2x_err_handler, 10191 10280 }; 10192 10281 10193 10282 static int __init bnx2x_init(void)