diff options
author | John Soni Jose <sony.john-n@emulex.com> | 2012-10-19 19:15:51 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-11-26 23:59:42 -0500 |
commit | 7a15800357e382b095b5dcb8edf79c3b2c8317e4 (patch) | |
tree | d9d6ab86b14a5e16a443504cc39d1742047a0fa1 /drivers | |
parent | e175defea7b2019613765fee63afcca354e0041d (diff) |
[SCSI] be2iscsi: Fix Unrecoverable Error Detection
Driver periodically checks adapter state,is up fine or not.
Based on the value updates the internal structures of driver.
Signed-off-by: John Soni Jose <sony.john-n@emulex.com>
Signed-off-by: Jayamohan Kallickal <jayamohan.kallickal@emulex.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/be2iscsi/be_cmds.c | 10 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 26 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.h | 5 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.c | 132 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.h | 7 |
5 files changed, 178 insertions, 2 deletions
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 352fc53e91b8..5c87768c109c 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c | |||
@@ -157,6 +157,9 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, | |||
157 | struct be_cmd_req_hdr *ioctl_hdr; | 157 | struct be_cmd_req_hdr *ioctl_hdr; |
158 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | 158 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; |
159 | 159 | ||
160 | if (beiscsi_error(phba)) | ||
161 | return -EIO; | ||
162 | |||
160 | /* wait for the mccq completion */ | 163 | /* wait for the mccq completion */ |
161 | rc = wait_event_interruptible_timeout( | 164 | rc = wait_event_interruptible_timeout( |
162 | phba->ctrl.mcc_wait[tag], | 165 | phba->ctrl.mcc_wait[tag], |
@@ -423,7 +426,7 @@ static int be_mcc_wait_compl(struct beiscsi_hba *phba) | |||
423 | { | 426 | { |
424 | int i, status; | 427 | int i, status; |
425 | for (i = 0; i < mcc_timeout; i++) { | 428 | for (i = 0; i < mcc_timeout; i++) { |
426 | if (phba->fw_timeout) | 429 | if (beiscsi_error(phba)) |
427 | return -EIO; | 430 | return -EIO; |
428 | 431 | ||
429 | status = beiscsi_process_mcc(phba); | 432 | status = beiscsi_process_mcc(phba); |
@@ -439,6 +442,7 @@ static int be_mcc_wait_compl(struct beiscsi_hba *phba) | |||
439 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | 442 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, |
440 | "BC_%d : FW Timed Out\n"); | 443 | "BC_%d : FW Timed Out\n"); |
441 | phba->fw_timeout = true; | 444 | phba->fw_timeout = true; |
445 | beiscsi_ue_detect(phba); | ||
442 | return -EBUSY; | 446 | return -EBUSY; |
443 | } | 447 | } |
444 | return 0; | 448 | return 0; |
@@ -479,7 +483,8 @@ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) | |||
479 | u32 ready; | 483 | u32 ready; |
480 | 484 | ||
481 | do { | 485 | do { |
482 | if (phba->fw_timeout) | 486 | |
487 | if (beiscsi_error(phba)) | ||
483 | return -EIO; | 488 | return -EIO; |
484 | 489 | ||
485 | ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; | 490 | ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; |
@@ -491,6 +496,7 @@ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) | |||
491 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | 496 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, |
492 | "BC_%d : FW Timed Out\n"); | 497 | "BC_%d : FW Timed Out\n"); |
493 | phba->fw_timeout = true; | 498 | phba->fw_timeout = true; |
499 | beiscsi_ue_detect(phba); | ||
494 | return -EBUSY; | 500 | return -EBUSY; |
495 | } | 501 | } |
496 | 502 | ||
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 73a29b2c18ba..48d37dded8f1 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c | |||
@@ -4717,6 +4717,8 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba) | |||
4717 | phba->ctrl.mbox_mem_alloced.size, | 4717 | phba->ctrl.mbox_mem_alloced.size, |
4718 | phba->ctrl.mbox_mem_alloced.va, | 4718 | phba->ctrl.mbox_mem_alloced.va, |
4719 | phba->ctrl.mbox_mem_alloced.dma); | 4719 | phba->ctrl.mbox_mem_alloced.dma); |
4720 | |||
4721 | cancel_delayed_work_sync(&phba->beiscsi_hw_check_task); | ||
4720 | } | 4722 | } |
4721 | 4723 | ||
4722 | static void beiscsi_remove(struct pci_dev *pcidev) | 4724 | static void beiscsi_remove(struct pci_dev *pcidev) |
@@ -4769,6 +4771,25 @@ static void beiscsi_msix_enable(struct beiscsi_hba *phba) | |||
4769 | return; | 4771 | return; |
4770 | } | 4772 | } |
4771 | 4773 | ||
4774 | /* | ||
4775 | * beiscsi_hw_health_check()- Check adapter health | ||
4776 | * @work: work item to check HW health | ||
4777 | * | ||
4778 | * Check if adapter in an unrecoverable state or not. | ||
4779 | **/ | ||
4780 | static void | ||
4781 | beiscsi_hw_health_check(struct work_struct *work) | ||
4782 | { | ||
4783 | struct beiscsi_hba *phba = | ||
4784 | container_of(work, struct beiscsi_hba, | ||
4785 | beiscsi_hw_check_task.work); | ||
4786 | |||
4787 | beiscsi_ue_detect(phba); | ||
4788 | |||
4789 | schedule_delayed_work(&phba->beiscsi_hw_check_task, | ||
4790 | msecs_to_jiffies(1000)); | ||
4791 | } | ||
4792 | |||
4772 | static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | 4793 | static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, |
4773 | const struct pci_device_id *id) | 4794 | const struct pci_device_id *id) |
4774 | { | 4795 | { |
@@ -4892,6 +4913,8 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | |||
4892 | goto free_twq; | 4913 | goto free_twq; |
4893 | } | 4914 | } |
4894 | 4915 | ||
4916 | INIT_DELAYED_WORK(&phba->beiscsi_hw_check_task, | ||
4917 | beiscsi_hw_health_check); | ||
4895 | 4918 | ||
4896 | phwi_ctrlr = phba->phwi_ctrlr; | 4919 | phwi_ctrlr = phba->phwi_ctrlr; |
4897 | phwi_context = phwi_ctrlr->phwi_ctxt; | 4920 | phwi_context = phwi_ctrlr->phwi_ctxt; |
@@ -4941,6 +4964,9 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | |||
4941 | "iSCSI boot info.\n"); | 4964 | "iSCSI boot info.\n"); |
4942 | 4965 | ||
4943 | beiscsi_create_def_ifaces(phba); | 4966 | beiscsi_create_def_ifaces(phba); |
4967 | schedule_delayed_work(&phba->beiscsi_hw_check_task, | ||
4968 | msecs_to_jiffies(1000)); | ||
4969 | |||
4944 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | 4970 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, |
4945 | "\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n"); | 4971 | "\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n"); |
4946 | return 0; | 4972 | return 0; |
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 033c053d9471..5b27275cc811 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h | |||
@@ -750,6 +750,11 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle); | |||
750 | 750 | ||
751 | void beiscsi_process_all_cqs(struct work_struct *work); | 751 | void beiscsi_process_all_cqs(struct work_struct *work); |
752 | 752 | ||
753 | static inline bool beiscsi_error(struct beiscsi_hba *phba) | ||
754 | { | ||
755 | return phba->ue_detected || phba->fw_timeout; | ||
756 | } | ||
757 | |||
753 | struct pdu_nop_out { | 758 | struct pdu_nop_out { |
754 | u32 dw[12]; | 759 | u32 dw[12]; |
755 | }; | 760 | }; |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 688bf64741e5..a6c2fe4b4d65 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c | |||
@@ -22,6 +22,138 @@ | |||
22 | #include <scsi/scsi_bsg_iscsi.h> | 22 | #include <scsi/scsi_bsg_iscsi.h> |
23 | #include "be_mgmt.h" | 23 | #include "be_mgmt.h" |
24 | #include "be_iscsi.h" | 24 | #include "be_iscsi.h" |
25 | #include "be_main.h" | ||
26 | |||
27 | /* UE Status Low CSR */ | ||
28 | static const char * const desc_ue_status_low[] = { | ||
29 | "CEV", | ||
30 | "CTX", | ||
31 | "DBUF", | ||
32 | "ERX", | ||
33 | "Host", | ||
34 | "MPU", | ||
35 | "NDMA", | ||
36 | "PTC ", | ||
37 | "RDMA ", | ||
38 | "RXF ", | ||
39 | "RXIPS ", | ||
40 | "RXULP0 ", | ||
41 | "RXULP1 ", | ||
42 | "RXULP2 ", | ||
43 | "TIM ", | ||
44 | "TPOST ", | ||
45 | "TPRE ", | ||
46 | "TXIPS ", | ||
47 | "TXULP0 ", | ||
48 | "TXULP1 ", | ||
49 | "UC ", | ||
50 | "WDMA ", | ||
51 | "TXULP2 ", | ||
52 | "HOST1 ", | ||
53 | "P0_OB_LINK ", | ||
54 | "P1_OB_LINK ", | ||
55 | "HOST_GPIO ", | ||
56 | "MBOX ", | ||
57 | "AXGMAC0", | ||
58 | "AXGMAC1", | ||
59 | "JTAG", | ||
60 | "MPU_INTPEND" | ||
61 | }; | ||
62 | |||
63 | /* UE Status High CSR */ | ||
64 | static const char * const desc_ue_status_hi[] = { | ||
65 | "LPCMEMHOST", | ||
66 | "MGMT_MAC", | ||
67 | "PCS0ONLINE", | ||
68 | "MPU_IRAM", | ||
69 | "PCS1ONLINE", | ||
70 | "PCTL0", | ||
71 | "PCTL1", | ||
72 | "PMEM", | ||
73 | "RR", | ||
74 | "TXPB", | ||
75 | "RXPP", | ||
76 | "XAUI", | ||
77 | "TXP", | ||
78 | "ARM", | ||
79 | "IPC", | ||
80 | "HOST2", | ||
81 | "HOST3", | ||
82 | "HOST4", | ||
83 | "HOST5", | ||
84 | "HOST6", | ||
85 | "HOST7", | ||
86 | "HOST8", | ||
87 | "HOST9", | ||
88 | "NETC", | ||
89 | "Unknown", | ||
90 | "Unknown", | ||
91 | "Unknown", | ||
92 | "Unknown", | ||
93 | "Unknown", | ||
94 | "Unknown", | ||
95 | "Unknown", | ||
96 | "Unknown" | ||
97 | }; | ||
98 | |||
99 | /* | ||
100 | * beiscsi_ue_detec()- Detect Unrecoverable Error on adapter | ||
101 | * @phba: Driver priv structure | ||
102 | * | ||
103 | * Read registers linked to UE and check for the UE status | ||
104 | **/ | ||
105 | void beiscsi_ue_detect(struct beiscsi_hba *phba) | ||
106 | { | ||
107 | uint32_t ue_hi = 0, ue_lo = 0; | ||
108 | uint32_t ue_mask_hi = 0, ue_mask_lo = 0; | ||
109 | uint8_t i = 0; | ||
110 | |||
111 | if (phba->ue_detected) | ||
112 | return; | ||
113 | |||
114 | pci_read_config_dword(phba->pcidev, | ||
115 | PCICFG_UE_STATUS_LOW, &ue_lo); | ||
116 | pci_read_config_dword(phba->pcidev, | ||
117 | PCICFG_UE_STATUS_MASK_LOW, | ||
118 | &ue_mask_lo); | ||
119 | pci_read_config_dword(phba->pcidev, | ||
120 | PCICFG_UE_STATUS_HIGH, | ||
121 | &ue_hi); | ||
122 | pci_read_config_dword(phba->pcidev, | ||
123 | PCICFG_UE_STATUS_MASK_HI, | ||
124 | &ue_mask_hi); | ||
125 | |||
126 | ue_lo = (ue_lo & ~ue_mask_lo); | ||
127 | ue_hi = (ue_hi & ~ue_mask_hi); | ||
128 | |||
129 | |||
130 | if (ue_lo || ue_hi) { | ||
131 | phba->ue_detected = true; | ||
132 | beiscsi_log(phba, KERN_ERR, | ||
133 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | ||
134 | "BG_%d : Error detected on the adapter\n"); | ||
135 | } | ||
136 | |||
137 | if (ue_lo) { | ||
138 | for (i = 0; ue_lo; ue_lo >>= 1, i++) { | ||
139 | if (ue_lo & 1) | ||
140 | beiscsi_log(phba, KERN_ERR, | ||
141 | BEISCSI_LOG_CONFIG, | ||
142 | "BG_%d : UE_LOW %s bit set\n", | ||
143 | desc_ue_status_low[i]); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | if (ue_hi) { | ||
148 | for (i = 0; ue_hi; ue_hi >>= 1, i++) { | ||
149 | if (ue_hi & 1) | ||
150 | beiscsi_log(phba, KERN_ERR, | ||
151 | BEISCSI_LOG_CONFIG, | ||
152 | "BG_%d : UE_HIGH %s bit set\n", | ||
153 | desc_ue_status_hi[i]); | ||
154 | } | ||
155 | } | ||
156 | } | ||
25 | 157 | ||
26 | /** | 158 | /** |
27 | * mgmt_reopen_session()- Reopen a session based on reopen_type | 159 | * mgmt_reopen_session()- Reopen a session based on reopen_type |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h index 88a8ed21d7f6..2e4968add799 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.h +++ b/drivers/scsi/be2iscsi/be_mgmt.h | |||
@@ -30,6 +30,12 @@ | |||
30 | #define IP_V6_LEN 16 | 30 | #define IP_V6_LEN 16 |
31 | #define IP_V4_LEN 4 | 31 | #define IP_V4_LEN 4 |
32 | 32 | ||
33 | /* UE Status and Mask register */ | ||
34 | #define PCICFG_UE_STATUS_LOW 0xA0 | ||
35 | #define PCICFG_UE_STATUS_HIGH 0xA4 | ||
36 | #define PCICFG_UE_STATUS_MASK_LOW 0xA8 | ||
37 | #define PCICFG_UE_STATUS_MASK_HI 0xAC | ||
38 | |||
33 | /** | 39 | /** |
34 | * Pseudo amap definition in which each bit of the actual structure is defined | 40 | * Pseudo amap definition in which each bit of the actual structure is defined |
35 | * as a byte: used to calculate offset/shift/mask of each field | 41 | * as a byte: used to calculate offset/shift/mask of each field |
@@ -314,5 +320,6 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, | |||
314 | 320 | ||
315 | void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, | 321 | void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, |
316 | struct wrb_handle *pwrb_handle); | 322 | struct wrb_handle *pwrb_handle); |
323 | void beiscsi_ue_detect(struct beiscsi_hba *phba); | ||
317 | 324 | ||
318 | #endif | 325 | #endif |