aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_os.c
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2009-12-16 00:29:46 -0500
committerJames Bottomley <James.Bottomley@suse.de>2009-12-30 12:09:49 -0500
commit858808019313f217d63ec4ad26686e6fb7b08c19 (patch)
treec54623c8b4154a23ddb679c76819e3b32b6638b6 /drivers/scsi/qla2xxx/qla_os.c
parent5c66f5d193f68c2a7da0f2ad3535ed30ab14307b (diff)
[SCSI] qla2xxx: Extend base EEH support in qla2xxx.
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c83
1 files changed, 75 insertions, 8 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 2f873d237325..1ab358210c6a 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -475,11 +475,11 @@ qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
475 srb_t *sp; 475 srb_t *sp;
476 int rval; 476 int rval;
477 477
478 if (unlikely(pci_channel_offline(ha->pdev))) { 478 if (ha->flags.eeh_busy) {
479 if (ha->pdev->error_state == pci_channel_io_frozen) 479 if (ha->flags.pci_channel_io_perm_failure)
480 cmd->result = DID_REQUEUE << 16;
481 else
482 cmd->result = DID_NO_CONNECT << 16; 480 cmd->result = DID_NO_CONNECT << 16;
481 else
482 cmd->result = DID_REQUEUE << 16;
483 goto qc24_fail_command; 483 goto qc24_fail_command;
484 } 484 }
485 485
@@ -552,8 +552,15 @@ qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd)
552#define ABORT_POLLING_PERIOD 1000 552#define ABORT_POLLING_PERIOD 1000
553#define ABORT_WAIT_ITER ((10 * 1000) / (ABORT_POLLING_PERIOD)) 553#define ABORT_WAIT_ITER ((10 * 1000) / (ABORT_POLLING_PERIOD))
554 unsigned long wait_iter = ABORT_WAIT_ITER; 554 unsigned long wait_iter = ABORT_WAIT_ITER;
555 scsi_qla_host_t *vha = shost_priv(cmd->device->host);
556 struct qla_hw_data *ha = vha->hw;
555 int ret = QLA_SUCCESS; 557 int ret = QLA_SUCCESS;
556 558
559 if (unlikely(pci_channel_offline(ha->pdev)) || ha->flags.eeh_busy) {
560 DEBUG17(qla_printk(KERN_WARNING, ha, "return:eh_wait\n"));
561 return ret;
562 }
563
557 while (CMD_SP(cmd) && wait_iter--) { 564 while (CMD_SP(cmd) && wait_iter--) {
558 msleep(ABORT_POLLING_PERIOD); 565 msleep(ABORT_POLLING_PERIOD);
559 } 566 }
@@ -2174,6 +2181,24 @@ qla2x00_free_device(scsi_qla_host_t *vha)
2174{ 2181{
2175 struct qla_hw_data *ha = vha->hw; 2182 struct qla_hw_data *ha = vha->hw;
2176 2183
2184 qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
2185
2186 /* Disable timer */
2187 if (vha->timer_active)
2188 qla2x00_stop_timer(vha);
2189
2190 /* Kill the kernel thread for this host */
2191 if (ha->dpc_thread) {
2192 struct task_struct *t = ha->dpc_thread;
2193
2194 /*
2195 * qla2xxx_wake_dpc checks for ->dpc_thread
2196 * so we need to zero it out.
2197 */
2198 ha->dpc_thread = NULL;
2199 kthread_stop(t);
2200 }
2201
2177 qla25xx_delete_queues(vha); 2202 qla25xx_delete_queues(vha);
2178 2203
2179 if (ha->flags.fce_enabled) 2204 if (ha->flags.fce_enabled)
@@ -2185,6 +2210,8 @@ qla2x00_free_device(scsi_qla_host_t *vha)
2185 /* Stop currently executing firmware. */ 2210 /* Stop currently executing firmware. */
2186 qla2x00_try_to_stop_firmware(vha); 2211 qla2x00_try_to_stop_firmware(vha);
2187 2212
2213 vha->flags.online = 0;
2214
2188 /* turn-off interrupts on the card */ 2215 /* turn-off interrupts on the card */
2189 if (ha->interrupts_on) 2216 if (ha->interrupts_on)
2190 ha->isp_ops->disable_intrs(ha); 2217 ha->isp_ops->disable_intrs(ha);
@@ -2859,6 +2886,13 @@ qla2x00_do_dpc(void *data)
2859 if (!base_vha->flags.init_done) 2886 if (!base_vha->flags.init_done)
2860 continue; 2887 continue;
2861 2888
2889 if (ha->flags.eeh_busy) {
2890 DEBUG17(qla_printk(KERN_WARNING, ha,
2891 "qla2x00_do_dpc: dpc_flags: %lx\n",
2892 base_vha->dpc_flags));
2893 continue;
2894 }
2895
2862 DEBUG3(printk("scsi(%ld): DPC handler\n", base_vha->host_no)); 2896 DEBUG3(printk("scsi(%ld): DPC handler\n", base_vha->host_no));
2863 2897
2864 ha->dpc_active = 1; 2898 ha->dpc_active = 1;
@@ -3049,8 +3083,13 @@ qla2x00_timer(scsi_qla_host_t *vha)
3049 int index; 3083 int index;
3050 srb_t *sp; 3084 srb_t *sp;
3051 int t; 3085 int t;
3086 uint16_t w;
3052 struct qla_hw_data *ha = vha->hw; 3087 struct qla_hw_data *ha = vha->hw;
3053 struct req_que *req; 3088 struct req_que *req;
3089
3090 /* Hardware read to raise pending EEH errors during mailbox waits. */
3091 if (!pci_channel_offline(ha->pdev))
3092 pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
3054 /* 3093 /*
3055 * Ports - Port down timer. 3094 * Ports - Port down timer.
3056 * 3095 *
@@ -3252,16 +3291,23 @@ qla2x00_release_firmware(void)
3252static pci_ers_result_t 3291static pci_ers_result_t
3253qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) 3292qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
3254{ 3293{
3255 scsi_qla_host_t *base_vha = pci_get_drvdata(pdev); 3294 scsi_qla_host_t *vha = pci_get_drvdata(pdev);
3295 struct qla_hw_data *ha = vha->hw;
3296
3297 DEBUG2(qla_printk(KERN_WARNING, ha, "error_detected:state %x\n",
3298 state));
3256 3299
3257 switch (state) { 3300 switch (state) {
3258 case pci_channel_io_normal: 3301 case pci_channel_io_normal:
3302 ha->flags.eeh_busy = 0;
3259 return PCI_ERS_RESULT_CAN_RECOVER; 3303 return PCI_ERS_RESULT_CAN_RECOVER;
3260 case pci_channel_io_frozen: 3304 case pci_channel_io_frozen:
3305 ha->flags.eeh_busy = 1;
3261 pci_disable_device(pdev); 3306 pci_disable_device(pdev);
3262 return PCI_ERS_RESULT_NEED_RESET; 3307 return PCI_ERS_RESULT_NEED_RESET;
3263 case pci_channel_io_perm_failure: 3308 case pci_channel_io_perm_failure:
3264 qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16); 3309 ha->flags.pci_channel_io_perm_failure = 1;
3310 qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
3265 return PCI_ERS_RESULT_DISCONNECT; 3311 return PCI_ERS_RESULT_DISCONNECT;
3266 } 3312 }
3267 return PCI_ERS_RESULT_NEED_RESET; 3313 return PCI_ERS_RESULT_NEED_RESET;
@@ -3312,6 +3358,8 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
3312 struct qla_hw_data *ha = base_vha->hw; 3358 struct qla_hw_data *ha = base_vha->hw;
3313 int rc; 3359 int rc;
3314 3360
3361 DEBUG17(qla_printk(KERN_WARNING, ha, "slot_reset\n"));
3362
3315 if (ha->mem_only) 3363 if (ha->mem_only)
3316 rc = pci_enable_device_mem(pdev); 3364 rc = pci_enable_device_mem(pdev);
3317 else 3365 else
@@ -3320,19 +3368,33 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
3320 if (rc) { 3368 if (rc) {
3321 qla_printk(KERN_WARNING, ha, 3369 qla_printk(KERN_WARNING, ha,
3322 "Can't re-enable PCI device after reset.\n"); 3370 "Can't re-enable PCI device after reset.\n");
3323
3324 return ret; 3371 return ret;
3325 } 3372 }
3326 pci_set_master(pdev);
3327 3373
3328 if (ha->isp_ops->pci_config(base_vha)) 3374 if (ha->isp_ops->pci_config(base_vha))
3329 return ret; 3375 return ret;
3330 3376
3377#ifdef QL_DEBUG_LEVEL_17
3378 {
3379 uint8_t b;
3380 uint32_t i;
3381
3382 printk("slot_reset_1: ");
3383 for (i = 0; i < 256; i++) {
3384 pci_read_config_byte(ha->pdev, i, &b);
3385 printk("%s%02x", (i%16) ? " " : "\n", b);
3386 }
3387 printk("\n");
3388 }
3389#endif
3331 set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); 3390 set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
3332 if (qla2x00_abort_isp(base_vha) == QLA_SUCCESS) 3391 if (qla2x00_abort_isp(base_vha) == QLA_SUCCESS)
3333 ret = PCI_ERS_RESULT_RECOVERED; 3392 ret = PCI_ERS_RESULT_RECOVERED;
3334 clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); 3393 clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
3335 3394
3395 DEBUG17(qla_printk(KERN_WARNING, ha,
3396 "slot_reset-return:ret=%x\n", ret));
3397
3336 return ret; 3398 return ret;
3337} 3399}
3338 3400
@@ -3343,12 +3405,17 @@ qla2xxx_pci_resume(struct pci_dev *pdev)
3343 struct qla_hw_data *ha = base_vha->hw; 3405 struct qla_hw_data *ha = base_vha->hw;
3344 int ret; 3406 int ret;
3345 3407
3408 DEBUG17(qla_printk(KERN_WARNING, ha, "pci_resume\n"));
3409
3346 ret = qla2x00_wait_for_hba_online(base_vha); 3410 ret = qla2x00_wait_for_hba_online(base_vha);
3347 if (ret != QLA_SUCCESS) { 3411 if (ret != QLA_SUCCESS) {
3348 qla_printk(KERN_ERR, ha, 3412 qla_printk(KERN_ERR, ha,
3349 "the device failed to resume I/O " 3413 "the device failed to resume I/O "
3350 "from slot/link_reset"); 3414 "from slot/link_reset");
3351 } 3415 }
3416
3417 ha->flags.eeh_busy = 0;
3418
3352 pci_cleanup_aer_uncorrect_error_status(pdev); 3419 pci_cleanup_aer_uncorrect_error_status(pdev);
3353} 3420}
3354 3421