diff options
author | Armen Baloyan <armen.baloyan@qlogic.com> | 2014-02-26 04:15:17 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2014-03-15 13:18:52 -0400 |
commit | faef62d134631c1f390006d51d49c76033f9504f (patch) | |
tree | 6da279f1d08a7be4a7a1c0995b5d1a1f653a1e22 /drivers/scsi/qla2xxx | |
parent | 43a9c38bf3867f4626107e17255db8c6a4bb16fc (diff) |
[SCSI] qla2xxx: Fix Task Management command asynchronous handling
- Fix interpreting the wrong IOCB type for task management
functions in the response path.
- Merge the task management function handling for various adapters.
Signed-off-by: Armen Baloyan <armen.baloyan@qlogic.com>
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 1 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 79 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 46 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mr.c | 66 |
4 files changed, 69 insertions, 123 deletions
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index c68b60051dfb..97255f7c3975 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c | |||
@@ -34,6 +34,7 @@ | |||
34 | * | | | 0x5047,0x5052 | | 34 | * | | | 0x5047,0x5052 | |
35 | * | | | 0x5084,0x5075 | | 35 | * | | | 0x5084,0x5075 | |
36 | * | | | 0x503d,0x5044 | | 36 | * | | | 0x503d,0x5044 | |
37 | * | | | 0x507b | | ||
37 | * | Timer Routines | 0x6012 | | | 38 | * | Timer Routines | 0x6012 | | |
38 | * | User Space Interactions | 0x70e2 | 0x7018,0x702e | | 39 | * | User Space Interactions | 0x70e2 | 0x7018,0x702e | |
39 | * | | | 0x7020,0x7024 | | 40 | * | | | 0x7020,0x7024 | |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index f75d19f497fe..27248425f86c 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -271,56 +271,46 @@ done: | |||
271 | } | 271 | } |
272 | 272 | ||
273 | static void | 273 | static void |
274 | qla2x00_async_tm_cmd_done(void *data, void *ptr, int res) | 274 | qla2x00_tmf_iocb_timeout(void *data) |
275 | { | 275 | { |
276 | srb_t *sp = (srb_t *)ptr; | 276 | srb_t *sp = (srb_t *)data; |
277 | struct srb_iocb *iocb = &sp->u.iocb_cmd; | 277 | struct srb_iocb *tmf = &sp->u.iocb_cmd; |
278 | struct scsi_qla_host *vha = (scsi_qla_host_t *)data; | ||
279 | uint32_t flags; | ||
280 | uint16_t lun; | ||
281 | int rval; | ||
282 | |||
283 | if (!test_bit(UNLOADING, &vha->dpc_flags)) { | ||
284 | flags = iocb->u.tmf.flags; | ||
285 | lun = (uint16_t)iocb->u.tmf.lun; | ||
286 | 278 | ||
287 | /* Issue Marker IOCB */ | 279 | tmf->u.tmf.comp_status = CS_TIMEOUT; |
288 | rval = qla2x00_marker(vha, vha->hw->req_q_map[0], | 280 | complete(&tmf->u.tmf.comp); |
289 | vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun, | 281 | } |
290 | flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID); | ||
291 | 282 | ||
292 | if ((rval != QLA_SUCCESS) || iocb->u.tmf.data) { | 283 | static void |
293 | ql_dbg(ql_dbg_taskm, vha, 0x8030, | 284 | qla2x00_tmf_sp_done(void *data, void *ptr, int res) |
294 | "TM IOCB failed (%x).\n", rval); | 285 | { |
295 | } | 286 | srb_t *sp = (srb_t *)ptr; |
296 | } | 287 | struct srb_iocb *tmf = &sp->u.iocb_cmd; |
297 | sp->free(sp->fcport->vha, sp); | 288 | complete(&tmf->u.tmf.comp); |
298 | } | 289 | } |
299 | 290 | ||
300 | int | 291 | int |
301 | qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t tm_flags, uint32_t lun, | 292 | qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, |
302 | uint32_t tag) | 293 | uint32_t tag) |
303 | { | 294 | { |
304 | struct scsi_qla_host *vha = fcport->vha; | 295 | struct scsi_qla_host *vha = fcport->vha; |
296 | struct srb_iocb *tm_iocb; | ||
305 | srb_t *sp; | 297 | srb_t *sp; |
306 | struct srb_iocb *tcf; | 298 | int rval = QLA_FUNCTION_FAILED; |
307 | int rval; | ||
308 | 299 | ||
309 | rval = QLA_FUNCTION_FAILED; | ||
310 | sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); | 300 | sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); |
311 | if (!sp) | 301 | if (!sp) |
312 | goto done; | 302 | goto done; |
313 | 303 | ||
304 | tm_iocb = &sp->u.iocb_cmd; | ||
314 | sp->type = SRB_TM_CMD; | 305 | sp->type = SRB_TM_CMD; |
315 | sp->name = "tmf"; | 306 | sp->name = "tmf"; |
316 | qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2); | 307 | qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)); |
317 | 308 | tm_iocb->u.tmf.flags = flags; | |
318 | tcf = &sp->u.iocb_cmd; | 309 | tm_iocb->u.tmf.lun = lun; |
319 | tcf->u.tmf.flags = tm_flags; | 310 | tm_iocb->u.tmf.data = tag; |
320 | tcf->u.tmf.lun = lun; | 311 | sp->done = qla2x00_tmf_sp_done; |
321 | tcf->u.tmf.data = tag; | 312 | tm_iocb->timeout = qla2x00_tmf_iocb_timeout; |
322 | tcf->timeout = qla2x00_async_iocb_timeout; | 313 | init_completion(&tm_iocb->u.tmf.comp); |
323 | sp->done = qla2x00_async_tm_cmd_done; | ||
324 | 314 | ||
325 | rval = qla2x00_start_sp(sp); | 315 | rval = qla2x00_start_sp(sp); |
326 | if (rval != QLA_SUCCESS) | 316 | if (rval != QLA_SUCCESS) |
@@ -330,10 +320,29 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t tm_flags, uint32_t lun, | |||
330 | "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n", | 320 | "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n", |
331 | sp->handle, fcport->loop_id, fcport->d_id.b.domain, | 321 | sp->handle, fcport->loop_id, fcport->d_id.b.domain, |
332 | fcport->d_id.b.area, fcport->d_id.b.al_pa); | 322 | fcport->d_id.b.area, fcport->d_id.b.al_pa); |
333 | return rval; | 323 | |
324 | wait_for_completion(&tm_iocb->u.tmf.comp); | ||
325 | |||
326 | rval = tm_iocb->u.tmf.comp_status == CS_COMPLETE ? | ||
327 | QLA_SUCCESS : QLA_FUNCTION_FAILED; | ||
328 | |||
329 | if ((rval != QLA_SUCCESS) || tm_iocb->u.tmf.data) { | ||
330 | ql_dbg(ql_dbg_taskm, vha, 0x8030, | ||
331 | "TM IOCB failed (%x).\n", rval); | ||
332 | } | ||
333 | |||
334 | if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) { | ||
335 | flags = tm_iocb->u.tmf.flags; | ||
336 | lun = (uint16_t)tm_iocb->u.tmf.lun; | ||
337 | |||
338 | /* Issue Marker IOCB */ | ||
339 | qla2x00_marker(vha, vha->hw->req_q_map[0], | ||
340 | vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun, | ||
341 | flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID); | ||
342 | } | ||
334 | 343 | ||
335 | done_free_sp: | 344 | done_free_sp: |
336 | sp->free(fcport->vha, sp); | 345 | sp->free(vha, sp); |
337 | done: | 346 | done: |
338 | return rval; | 347 | return rval; |
339 | } | 348 | } |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index c2aaf6a93cc1..293dbd565840 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -1498,8 +1498,7 @@ logio_done: | |||
1498 | } | 1498 | } |
1499 | 1499 | ||
1500 | static void | 1500 | static void |
1501 | qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, | 1501 | qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) |
1502 | struct tsk_mgmt_entry *tsk) | ||
1503 | { | 1502 | { |
1504 | const char func[] = "TMF-IOCB"; | 1503 | const char func[] = "TMF-IOCB"; |
1505 | const char *type; | 1504 | const char *type; |
@@ -1507,7 +1506,6 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
1507 | srb_t *sp; | 1506 | srb_t *sp; |
1508 | struct srb_iocb *iocb; | 1507 | struct srb_iocb *iocb; |
1509 | struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk; | 1508 | struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk; |
1510 | int error = 1; | ||
1511 | 1509 | ||
1512 | sp = qla2x00_get_sp_from_handle(vha, func, req, tsk); | 1510 | sp = qla2x00_get_sp_from_handle(vha, func, req, tsk); |
1513 | if (!sp) | 1511 | if (!sp) |
@@ -1516,37 +1514,35 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
1516 | iocb = &sp->u.iocb_cmd; | 1514 | iocb = &sp->u.iocb_cmd; |
1517 | type = sp->name; | 1515 | type = sp->name; |
1518 | fcport = sp->fcport; | 1516 | fcport = sp->fcport; |
1517 | iocb->u.tmf.data = QLA_SUCCESS; | ||
1519 | 1518 | ||
1520 | if (sts->entry_status) { | 1519 | if (sts->entry_status) { |
1521 | ql_log(ql_log_warn, fcport->vha, 0x5038, | 1520 | ql_log(ql_log_warn, fcport->vha, 0x5038, |
1522 | "Async-%s error - hdl=%x entry-status(%x).\n", | 1521 | "Async-%s error - hdl=%x entry-status(%x).\n", |
1523 | type, sp->handle, sts->entry_status); | 1522 | type, sp->handle, sts->entry_status); |
1523 | iocb->u.tmf.data = QLA_FUNCTION_FAILED; | ||
1524 | } else if (sts->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { | 1524 | } else if (sts->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { |
1525 | ql_log(ql_log_warn, fcport->vha, 0x5039, | 1525 | ql_log(ql_log_warn, fcport->vha, 0x5039, |
1526 | "Async-%s error - hdl=%x completion status(%x).\n", | 1526 | "Async-%s error - hdl=%x completion status(%x).\n", |
1527 | type, sp->handle, sts->comp_status); | 1527 | type, sp->handle, sts->comp_status); |
1528 | } else if (!(le16_to_cpu(sts->scsi_status) & | 1528 | iocb->u.tmf.data = QLA_FUNCTION_FAILED; |
1529 | } else if ((le16_to_cpu(sts->scsi_status) & | ||
1529 | SS_RESPONSE_INFO_LEN_VALID)) { | 1530 | SS_RESPONSE_INFO_LEN_VALID)) { |
1530 | ql_log(ql_log_warn, fcport->vha, 0x503a, | 1531 | if (le32_to_cpu(sts->rsp_data_len) < 4) { |
1531 | "Async-%s error - hdl=%x no response info(%x).\n", | 1532 | ql_log(ql_log_warn, fcport->vha, 0x503b, |
1532 | type, sp->handle, sts->scsi_status); | 1533 | "Async-%s error - hdl=%x not enough response(%d).\n", |
1533 | } else if (le32_to_cpu(sts->rsp_data_len) < 4) { | 1534 | type, sp->handle, sts->rsp_data_len); |
1534 | ql_log(ql_log_warn, fcport->vha, 0x503b, | 1535 | } else if (sts->data[3]) { |
1535 | "Async-%s error - hdl=%x not enough response(%d).\n", | 1536 | ql_log(ql_log_warn, fcport->vha, 0x503c, |
1536 | type, sp->handle, sts->rsp_data_len); | 1537 | "Async-%s error - hdl=%x response(%x).\n", |
1537 | } else if (sts->data[3]) { | 1538 | type, sp->handle, sts->data[3]); |
1538 | ql_log(ql_log_warn, fcport->vha, 0x503c, | 1539 | iocb->u.tmf.data = QLA_FUNCTION_FAILED; |
1539 | "Async-%s error - hdl=%x response(%x).\n", | 1540 | } |
1540 | type, sp->handle, sts->data[3]); | ||
1541 | } else { | ||
1542 | error = 0; | ||
1543 | } | 1541 | } |
1544 | 1542 | ||
1545 | if (error) { | 1543 | if (iocb->u.tmf.data != QLA_SUCCESS) |
1546 | iocb->u.tmf.data = error; | ||
1547 | ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5055, | 1544 | ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5055, |
1548 | (uint8_t *)sts, sizeof(*sts)); | 1545 | (uint8_t *)sts, sizeof(*sts)); |
1549 | } | ||
1550 | 1546 | ||
1551 | sp->done(vha, sp, 0); | 1547 | sp->done(vha, sp, 0); |
1552 | } | 1548 | } |
@@ -2026,6 +2022,12 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
2026 | return; | 2022 | return; |
2027 | } | 2023 | } |
2028 | 2024 | ||
2025 | /* Task Management completion. */ | ||
2026 | if (sp->type == SRB_TM_CMD) { | ||
2027 | qla24xx_tm_iocb_entry(vha, req, pkt); | ||
2028 | return; | ||
2029 | } | ||
2030 | |||
2029 | /* Fast path completion. */ | 2031 | /* Fast path completion. */ |
2030 | if (comp_status == CS_COMPLETE && scsi_status == 0) { | 2032 | if (comp_status == CS_COMPLETE && scsi_status == 0) { |
2031 | qla2x00_process_completed_request(vha, req, handle); | 2033 | qla2x00_process_completed_request(vha, req, handle); |
@@ -2475,10 +2477,6 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, | |||
2475 | qla24xx_logio_entry(vha, rsp->req, | 2477 | qla24xx_logio_entry(vha, rsp->req, |
2476 | (struct logio_entry_24xx *)pkt); | 2478 | (struct logio_entry_24xx *)pkt); |
2477 | break; | 2479 | break; |
2478 | case TSK_MGMT_IOCB_TYPE: | ||
2479 | qla24xx_tm_iocb_entry(vha, rsp->req, | ||
2480 | (struct tsk_mgmt_entry *)pkt); | ||
2481 | break; | ||
2482 | case CT_IOCB_TYPE: | 2480 | case CT_IOCB_TYPE: |
2483 | qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); | 2481 | qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); |
2484 | break; | 2482 | break; |
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 046a1699cb79..165db12580af 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c | |||
@@ -685,78 +685,16 @@ qlafx00_disable_intrs(struct qla_hw_data *ha) | |||
685 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 685 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
686 | } | 686 | } |
687 | 687 | ||
688 | static void | ||
689 | qlafx00_tmf_iocb_timeout(void *data) | ||
690 | { | ||
691 | srb_t *sp = (srb_t *)data; | ||
692 | struct srb_iocb *tmf = &sp->u.iocb_cmd; | ||
693 | |||
694 | tmf->u.tmf.comp_status = cpu_to_le16((uint16_t)CS_TIMEOUT); | ||
695 | complete(&tmf->u.tmf.comp); | ||
696 | } | ||
697 | |||
698 | static void | ||
699 | qlafx00_tmf_sp_done(void *data, void *ptr, int res) | ||
700 | { | ||
701 | srb_t *sp = (srb_t *)ptr; | ||
702 | struct srb_iocb *tmf = &sp->u.iocb_cmd; | ||
703 | |||
704 | complete(&tmf->u.tmf.comp); | ||
705 | } | ||
706 | |||
707 | static int | ||
708 | qlafx00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, | ||
709 | uint32_t lun, uint32_t tag) | ||
710 | { | ||
711 | scsi_qla_host_t *vha = fcport->vha; | ||
712 | struct srb_iocb *tm_iocb; | ||
713 | srb_t *sp; | ||
714 | int rval = QLA_FUNCTION_FAILED; | ||
715 | |||
716 | sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); | ||
717 | if (!sp) | ||
718 | goto done; | ||
719 | |||
720 | tm_iocb = &sp->u.iocb_cmd; | ||
721 | sp->type = SRB_TM_CMD; | ||
722 | sp->name = "tmf"; | ||
723 | qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)); | ||
724 | tm_iocb->u.tmf.flags = flags; | ||
725 | tm_iocb->u.tmf.lun = lun; | ||
726 | tm_iocb->u.tmf.data = tag; | ||
727 | sp->done = qlafx00_tmf_sp_done; | ||
728 | tm_iocb->timeout = qlafx00_tmf_iocb_timeout; | ||
729 | init_completion(&tm_iocb->u.tmf.comp); | ||
730 | |||
731 | rval = qla2x00_start_sp(sp); | ||
732 | if (rval != QLA_SUCCESS) | ||
733 | goto done_free_sp; | ||
734 | |||
735 | ql_dbg(ql_dbg_async, vha, 0x507b, | ||
736 | "Task management command issued target_id=%x\n", | ||
737 | fcport->tgt_id); | ||
738 | |||
739 | wait_for_completion(&tm_iocb->u.tmf.comp); | ||
740 | |||
741 | rval = tm_iocb->u.tmf.comp_status == CS_COMPLETE ? | ||
742 | QLA_SUCCESS : QLA_FUNCTION_FAILED; | ||
743 | |||
744 | done_free_sp: | ||
745 | sp->free(vha, sp); | ||
746 | done: | ||
747 | return rval; | ||
748 | } | ||
749 | |||
750 | int | 688 | int |
751 | qlafx00_abort_target(fc_port_t *fcport, unsigned int l, int tag) | 689 | qlafx00_abort_target(fc_port_t *fcport, unsigned int l, int tag) |
752 | { | 690 | { |
753 | return qlafx00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag); | 691 | return qla2x00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag); |
754 | } | 692 | } |
755 | 693 | ||
756 | int | 694 | int |
757 | qlafx00_lun_reset(fc_port_t *fcport, unsigned int l, int tag) | 695 | qlafx00_lun_reset(fc_port_t *fcport, unsigned int l, int tag) |
758 | { | 696 | { |
759 | return qlafx00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag); | 697 | return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag); |
760 | } | 698 | } |
761 | 699 | ||
762 | int | 700 | int |