diff options
author | Dimitris Michailidis <dm@chelsio.com> | 2010-06-18 06:05:29 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-19 01:08:36 -0400 |
commit | 204dc3c0b1bea10a7d811970fd41ceabaef31267 (patch) | |
tree | e2d3879455ff3c6226ffea439275a21f4edefb39 /drivers/net/cxgb4/cxgb4_main.c | |
parent | 02b5fb8e14923ff9111de1a00004ccd593adaedb (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.c | 108 |
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 | |||
2913 | static 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); | ||
2935 | out: return state == pci_channel_io_perm_failure ? | ||
2936 | PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET; | ||
2937 | } | ||
2938 | |||
2939 | static 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 | |||
2986 | static 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 | |||
3007 | static struct pci_error_handlers cxgb4_eeh = { | ||
3008 | .error_detected = eeh_err_detected, | ||
3009 | .slot_reset = eeh_slot_reset, | ||
3010 | .resume = eeh_resume, | ||
3011 | }; | ||
3012 | |||
2910 | static inline bool is_10g_port(const struct link_config *lc) | 3013 | static 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 | ||
3401 | static int __init cxgb4_init_module(void) | 3507 | static int __init cxgb4_init_module(void) |