aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cxgb4/cxgb4_main.c
diff options
context:
space:
mode:
authorDimitris Michailidis <dm@chelsio.com>2010-06-18 06:05:29 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-19 01:08:36 -0400
commit204dc3c0b1bea10a7d811970fd41ceabaef31267 (patch)
treee2d3879455ff3c6226ffea439275a21f4edefb39 /drivers/net/cxgb4/cxgb4_main.c
parent02b5fb8e14923ff9111de1a00004ccd593adaedb (diff)
cxgb4: implement EEH
Implement the pci_error_handlers methods for EEH. Signed-off-by: Dimitris Michailidis <dm@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/cxgb4/cxgb4_main.c')
-rw-r--r--drivers/net/cxgb4/cxgb4_main.c108
1 files changed, 107 insertions, 1 deletions
diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
index 60f6ea05167a..baf4f0a31362 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/cxgb4/cxgb4_main.c
@@ -2483,6 +2483,7 @@ static void cxgb_down(struct adapter *adapter)
2483 t4_intr_disable(adapter); 2483 t4_intr_disable(adapter);
2484 cancel_work_sync(&adapter->tid_release_task); 2484 cancel_work_sync(&adapter->tid_release_task);
2485 adapter->tid_release_task_busy = false; 2485 adapter->tid_release_task_busy = false;
2486 adapter->tid_release_head = NULL;
2486 2487
2487 if (adapter->flags & USING_MSIX) { 2488 if (adapter->flags & USING_MSIX) {
2488 free_msix_queue_irqs(adapter); 2489 free_msix_queue_irqs(adapter);
@@ -2907,6 +2908,108 @@ bye: if (ret != -ETIMEDOUT && ret != -EIO)
2907 return ret; 2908 return ret;
2908} 2909}
2909 2910
2911/* EEH callbacks */
2912
2913static pci_ers_result_t eeh_err_detected(struct pci_dev *pdev,
2914 pci_channel_state_t state)
2915{
2916 int i;
2917 struct adapter *adap = pci_get_drvdata(pdev);
2918
2919 if (!adap)
2920 goto out;
2921
2922 rtnl_lock();
2923 adap->flags &= ~FW_OK;
2924 notify_ulds(adap, CXGB4_STATE_START_RECOVERY);
2925 for_each_port(adap, i) {
2926 struct net_device *dev = adap->port[i];
2927
2928 netif_device_detach(dev);
2929 netif_carrier_off(dev);
2930 }
2931 if (adap->flags & FULL_INIT_DONE)
2932 cxgb_down(adap);
2933 rtnl_unlock();
2934 pci_disable_device(pdev);
2935out: return state == pci_channel_io_perm_failure ?
2936 PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;
2937}
2938
2939static pci_ers_result_t eeh_slot_reset(struct pci_dev *pdev)
2940{
2941 int i, ret;
2942 struct fw_caps_config_cmd c;
2943 struct adapter *adap = pci_get_drvdata(pdev);
2944
2945 if (!adap) {
2946 pci_restore_state(pdev);
2947 pci_save_state(pdev);
2948 return PCI_ERS_RESULT_RECOVERED;
2949 }
2950
2951 if (pci_enable_device(pdev)) {
2952 dev_err(&pdev->dev, "cannot reenable PCI device after reset\n");
2953 return PCI_ERS_RESULT_DISCONNECT;
2954 }
2955
2956 pci_set_master(pdev);
2957 pci_restore_state(pdev);
2958 pci_save_state(pdev);
2959 pci_cleanup_aer_uncorrect_error_status(pdev);
2960
2961 if (t4_wait_dev_ready(adap) < 0)
2962 return PCI_ERS_RESULT_DISCONNECT;
2963 if (t4_fw_hello(adap, 0, 0, MASTER_MUST, NULL))
2964 return PCI_ERS_RESULT_DISCONNECT;
2965 adap->flags |= FW_OK;
2966 if (adap_init1(adap, &c))
2967 return PCI_ERS_RESULT_DISCONNECT;
2968
2969 for_each_port(adap, i) {
2970 struct port_info *p = adap2pinfo(adap, i);
2971
2972 ret = t4_alloc_vi(adap, 0, p->tx_chan, 0, 0, 1, NULL, NULL);
2973 if (ret < 0)
2974 return PCI_ERS_RESULT_DISCONNECT;
2975 p->viid = ret;
2976 p->xact_addr_filt = -1;
2977 }
2978
2979 t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
2980 adap->params.b_wnd);
2981 if (cxgb_up(adap))
2982 return PCI_ERS_RESULT_DISCONNECT;
2983 return PCI_ERS_RESULT_RECOVERED;
2984}
2985
2986static void eeh_resume(struct pci_dev *pdev)
2987{
2988 int i;
2989 struct adapter *adap = pci_get_drvdata(pdev);
2990
2991 if (!adap)
2992 return;
2993
2994 rtnl_lock();
2995 for_each_port(adap, i) {
2996 struct net_device *dev = adap->port[i];
2997
2998 if (netif_running(dev)) {
2999 link_start(dev);
3000 cxgb_set_rxmode(dev);
3001 }
3002 netif_device_attach(dev);
3003 }
3004 rtnl_unlock();
3005}
3006
3007static struct pci_error_handlers cxgb4_eeh = {
3008 .error_detected = eeh_err_detected,
3009 .slot_reset = eeh_slot_reset,
3010 .resume = eeh_resume,
3011};
3012
2910static inline bool is_10g_port(const struct link_config *lc) 3013static inline bool is_10g_port(const struct link_config *lc)
2911{ 3014{
2912 return (lc->supported & FW_PORT_CAP_SPEED_10G) != 0; 3015 return (lc->supported & FW_PORT_CAP_SPEED_10G) != 0;
@@ -3154,8 +3257,10 @@ static int __devinit init_one(struct pci_dev *pdev,
3154 3257
3155 /* We control everything through PF 0 */ 3258 /* We control everything through PF 0 */
3156 func = PCI_FUNC(pdev->devfn); 3259 func = PCI_FUNC(pdev->devfn);
3157 if (func > 0) 3260 if (func > 0) {
3261 pci_save_state(pdev); /* to restore SR-IOV later */
3158 goto sriov; 3262 goto sriov;
3263 }
3159 3264
3160 err = pci_enable_device(pdev); 3265 err = pci_enable_device(pdev);
3161 if (err) { 3266 if (err) {
@@ -3396,6 +3501,7 @@ static struct pci_driver cxgb4_driver = {
3396 .id_table = cxgb4_pci_tbl, 3501 .id_table = cxgb4_pci_tbl,
3397 .probe = init_one, 3502 .probe = init_one,
3398 .remove = __devexit_p(remove_one), 3503 .remove = __devexit_p(remove_one),
3504 .err_handler = &cxgb4_eeh,
3399}; 3505};
3400 3506
3401static int __init cxgb4_init_module(void) 3507static int __init cxgb4_init_module(void)