diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 1 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_nvme.c | 34 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_nvme.h | 1 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 150 |
4 files changed, 55 insertions, 131 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 6dd2d41713c9..8acaeba98da1 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
| @@ -546,7 +546,6 @@ typedef struct srb { | |||
| 546 | int rc; | 546 | int rc; |
| 547 | int retry_count; | 547 | int retry_count; |
| 548 | struct completion *comp; | 548 | struct completion *comp; |
| 549 | wait_queue_head_t *cwaitq; | ||
| 550 | union { | 549 | union { |
| 551 | struct srb_iocb iocb_cmd; | 550 | struct srb_iocb iocb_cmd; |
| 552 | struct bsg_job *bsg_job; | 551 | struct bsg_job *bsg_job; |
diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 5d9191278f41..0829ab7f0d54 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c | |||
| @@ -137,8 +137,7 @@ static void qla_nvme_sp_ls_done(void *ptr, int res) | |||
| 137 | return; | 137 | return; |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | if (!atomic_dec_and_test(&sp->ref_count)) | 140 | atomic_dec(&sp->ref_count); |
| 141 | return; | ||
| 142 | 141 | ||
| 143 | if (res) | 142 | if (res) |
| 144 | res = -EINVAL; | 143 | res = -EINVAL; |
| @@ -161,8 +160,7 @@ static void qla_nvme_sp_done(void *ptr, int res) | |||
| 161 | nvme = &sp->u.iocb_cmd; | 160 | nvme = &sp->u.iocb_cmd; |
| 162 | fd = nvme->u.nvme.desc; | 161 | fd = nvme->u.nvme.desc; |
| 163 | 162 | ||
| 164 | if (!atomic_dec_and_test(&sp->ref_count)) | 163 | atomic_dec(&sp->ref_count); |
| 165 | return; | ||
| 166 | 164 | ||
| 167 | if (res == QLA_SUCCESS) { | 165 | if (res == QLA_SUCCESS) { |
| 168 | fd->rcv_rsplen = nvme->u.nvme.rsp_pyld_len; | 166 | fd->rcv_rsplen = nvme->u.nvme.rsp_pyld_len; |
| @@ -599,34 +597,6 @@ static struct nvme_fc_port_template qla_nvme_fc_transport = { | |||
| 599 | .fcprqst_priv_sz = sizeof(struct nvme_private), | 597 | .fcprqst_priv_sz = sizeof(struct nvme_private), |
| 600 | }; | 598 | }; |
| 601 | 599 | ||
| 602 | #define NVME_ABORT_POLLING_PERIOD 2 | ||
| 603 | static int qla_nvme_wait_on_command(srb_t *sp) | ||
| 604 | { | ||
| 605 | int ret = QLA_SUCCESS; | ||
| 606 | |||
| 607 | wait_event_timeout(sp->nvme_ls_waitq, (atomic_read(&sp->ref_count) > 1), | ||
| 608 | NVME_ABORT_POLLING_PERIOD*HZ); | ||
| 609 | |||
| 610 | if (atomic_read(&sp->ref_count) > 1) | ||
| 611 | ret = QLA_FUNCTION_FAILED; | ||
| 612 | |||
| 613 | return ret; | ||
| 614 | } | ||
| 615 | |||
| 616 | void qla_nvme_abort(struct qla_hw_data *ha, struct srb *sp, int res) | ||
| 617 | { | ||
| 618 | int rval; | ||
| 619 | |||
| 620 | if (ha->flags.fw_started) { | ||
| 621 | rval = ha->isp_ops->abort_command(sp); | ||
| 622 | if (!rval && !qla_nvme_wait_on_command(sp)) | ||
| 623 | ql_log(ql_log_warn, NULL, 0x2112, | ||
| 624 | "timed out waiting on sp=%p\n", sp); | ||
| 625 | } else { | ||
| 626 | sp->done(sp, res); | ||
| 627 | } | ||
| 628 | } | ||
| 629 | |||
| 630 | static void qla_nvme_unregister_remote_port(struct work_struct *work) | 600 | static void qla_nvme_unregister_remote_port(struct work_struct *work) |
| 631 | { | 601 | { |
| 632 | struct fc_port *fcport = container_of(work, struct fc_port, | 602 | struct fc_port *fcport = container_of(work, struct fc_port, |
diff --git a/drivers/scsi/qla2xxx/qla_nvme.h b/drivers/scsi/qla2xxx/qla_nvme.h index da8dad5ad693..0db04f0a4d5d 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.h +++ b/drivers/scsi/qla2xxx/qla_nvme.h | |||
| @@ -145,7 +145,6 @@ struct pt_ls4_rx_unsol { | |||
| 145 | int qla_nvme_register_hba(struct scsi_qla_host *); | 145 | int qla_nvme_register_hba(struct scsi_qla_host *); |
| 146 | int qla_nvme_register_remote(struct scsi_qla_host *, struct fc_port *); | 146 | int qla_nvme_register_remote(struct scsi_qla_host *, struct fc_port *); |
| 147 | void qla_nvme_delete(struct scsi_qla_host *); | 147 | void qla_nvme_delete(struct scsi_qla_host *); |
| 148 | void qla_nvme_abort(struct qla_hw_data *, struct srb *sp, int res); | ||
| 149 | void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *, struct pt_ls4_request *, | 148 | void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *, struct pt_ls4_request *, |
| 150 | struct req_que *); | 149 | struct req_que *); |
| 151 | void qla24xx_async_gffid_sp_done(void *, int); | 150 | void qla24xx_async_gffid_sp_done(void *, int); |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index a41aaf071b52..35f62f171b20 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
| @@ -714,7 +714,7 @@ qla2x00_sp_compl(void *ptr, int res) | |||
| 714 | { | 714 | { |
| 715 | srb_t *sp = ptr; | 715 | srb_t *sp = ptr; |
| 716 | struct scsi_cmnd *cmd = GET_CMD_SP(sp); | 716 | struct scsi_cmnd *cmd = GET_CMD_SP(sp); |
| 717 | wait_queue_head_t *cwaitq = sp->cwaitq; | 717 | struct completion *comp = sp->comp; |
| 718 | 718 | ||
| 719 | if (atomic_read(&sp->ref_count) == 0) { | 719 | if (atomic_read(&sp->ref_count) == 0) { |
| 720 | ql_dbg(ql_dbg_io, sp->vha, 0x3015, | 720 | ql_dbg(ql_dbg_io, sp->vha, 0x3015, |
| @@ -724,15 +724,15 @@ qla2x00_sp_compl(void *ptr, int res) | |||
| 724 | WARN_ON(atomic_read(&sp->ref_count) == 0); | 724 | WARN_ON(atomic_read(&sp->ref_count) == 0); |
| 725 | return; | 725 | return; |
| 726 | } | 726 | } |
| 727 | if (!atomic_dec_and_test(&sp->ref_count)) | 727 | |
| 728 | return; | 728 | atomic_dec(&sp->ref_count); |
| 729 | 729 | ||
| 730 | sp->free(sp); | 730 | sp->free(sp); |
| 731 | cmd->result = res; | 731 | cmd->result = res; |
| 732 | CMD_SP(cmd) = NULL; | 732 | CMD_SP(cmd) = NULL; |
| 733 | cmd->scsi_done(cmd); | 733 | cmd->scsi_done(cmd); |
| 734 | if (cwaitq) | 734 | if (comp) |
| 735 | wake_up(cwaitq); | 735 | complete(comp); |
| 736 | qla2x00_rel_sp(sp); | 736 | qla2x00_rel_sp(sp); |
| 737 | } | 737 | } |
| 738 | 738 | ||
| @@ -825,7 +825,7 @@ qla2xxx_qpair_sp_compl(void *ptr, int res) | |||
| 825 | { | 825 | { |
| 826 | srb_t *sp = ptr; | 826 | srb_t *sp = ptr; |
| 827 | struct scsi_cmnd *cmd = GET_CMD_SP(sp); | 827 | struct scsi_cmnd *cmd = GET_CMD_SP(sp); |
| 828 | wait_queue_head_t *cwaitq = sp->cwaitq; | 828 | struct completion *comp = sp->comp; |
| 829 | 829 | ||
| 830 | if (atomic_read(&sp->ref_count) == 0) { | 830 | if (atomic_read(&sp->ref_count) == 0) { |
| 831 | ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3079, | 831 | ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3079, |
| @@ -835,15 +835,15 @@ qla2xxx_qpair_sp_compl(void *ptr, int res) | |||
| 835 | WARN_ON(atomic_read(&sp->ref_count) == 0); | 835 | WARN_ON(atomic_read(&sp->ref_count) == 0); |
| 836 | return; | 836 | return; |
| 837 | } | 837 | } |
| 838 | if (!atomic_dec_and_test(&sp->ref_count)) | 838 | |
| 839 | return; | 839 | atomic_dec(&sp->ref_count); |
| 840 | 840 | ||
| 841 | sp->free(sp); | 841 | sp->free(sp); |
| 842 | cmd->result = res; | 842 | cmd->result = res; |
| 843 | CMD_SP(cmd) = NULL; | 843 | CMD_SP(cmd) = NULL; |
| 844 | cmd->scsi_done(cmd); | 844 | cmd->scsi_done(cmd); |
| 845 | if (cwaitq) | 845 | if (comp) |
| 846 | wake_up(cwaitq); | 846 | complete(comp); |
| 847 | qla2xxx_rel_qpair_sp(sp->qpair, sp); | 847 | qla2xxx_rel_qpair_sp(sp->qpair, sp); |
| 848 | } | 848 | } |
| 849 | 849 | ||
| @@ -1286,7 +1286,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
| 1286 | unsigned int id; | 1286 | unsigned int id; |
| 1287 | uint64_t lun; | 1287 | uint64_t lun; |
| 1288 | unsigned long flags; | 1288 | unsigned long flags; |
| 1289 | int rval, wait = 0; | 1289 | int rval; |
| 1290 | struct qla_hw_data *ha = vha->hw; | 1290 | struct qla_hw_data *ha = vha->hw; |
| 1291 | struct qla_qpair *qpair; | 1291 | struct qla_qpair *qpair; |
| 1292 | 1292 | ||
| @@ -1299,7 +1299,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
| 1299 | ret = fc_block_scsi_eh(cmd); | 1299 | ret = fc_block_scsi_eh(cmd); |
| 1300 | if (ret != 0) | 1300 | if (ret != 0) |
| 1301 | return ret; | 1301 | return ret; |
| 1302 | ret = SUCCESS; | ||
| 1303 | 1302 | ||
| 1304 | sp = (srb_t *) CMD_SP(cmd); | 1303 | sp = (srb_t *) CMD_SP(cmd); |
| 1305 | if (!sp) | 1304 | if (!sp) |
| @@ -1310,7 +1309,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
| 1310 | return SUCCESS; | 1309 | return SUCCESS; |
| 1311 | 1310 | ||
| 1312 | spin_lock_irqsave(qpair->qp_lock_ptr, flags); | 1311 | spin_lock_irqsave(qpair->qp_lock_ptr, flags); |
| 1313 | if (!CMD_SP(cmd)) { | 1312 | if (sp->type != SRB_SCSI_CMD || GET_CMD_SP(sp) != cmd) { |
| 1314 | /* there's a chance an interrupt could clear | 1313 | /* there's a chance an interrupt could clear |
| 1315 | the ptr as part of done & free */ | 1314 | the ptr as part of done & free */ |
| 1316 | spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); | 1315 | spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); |
| @@ -1331,66 +1330,31 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
| 1331 | "Aborting from RISC nexus=%ld:%d:%llu sp=%p cmd=%p handle=%x\n", | 1330 | "Aborting from RISC nexus=%ld:%d:%llu sp=%p cmd=%p handle=%x\n", |
| 1332 | vha->host_no, id, lun, sp, cmd, sp->handle); | 1331 | vha->host_no, id, lun, sp, cmd, sp->handle); |
| 1333 | 1332 | ||
| 1334 | /* Get a reference to the sp and drop the lock.*/ | ||
| 1335 | rval = ha->isp_ops->abort_command(sp); | 1333 | rval = ha->isp_ops->abort_command(sp); |
| 1336 | if (rval) { | 1334 | ql_dbg(ql_dbg_taskm, vha, 0x8003, |
| 1337 | if (rval == QLA_FUNCTION_PARAMETER_ERROR) | 1335 | "Abort command mbx cmd=%p, rval=%x.\n", cmd, rval); |
| 1338 | ret = SUCCESS; | ||
| 1339 | else | ||
| 1340 | ret = FAILED; | ||
| 1341 | |||
| 1342 | ql_dbg(ql_dbg_taskm, vha, 0x8003, | ||
| 1343 | "Abort command mbx failed cmd=%p, rval=%x.\n", cmd, rval); | ||
| 1344 | } else { | ||
| 1345 | ql_dbg(ql_dbg_taskm, vha, 0x8004, | ||
| 1346 | "Abort command mbx success cmd=%p.\n", cmd); | ||
| 1347 | wait = 1; | ||
| 1348 | } | ||
| 1349 | 1336 | ||
| 1350 | spin_lock_irqsave(qpair->qp_lock_ptr, flags); | 1337 | switch (rval) { |
| 1351 | 1338 | case QLA_SUCCESS: | |
| 1352 | /* | ||
| 1353 | * Releasing of the SRB and associated command resources | ||
| 1354 | * is managed through ref_count. | ||
| 1355 | * Whether we need to wait for the abort completion or complete | ||
| 1356 | * the abort handler should be based on the ref_count. | ||
| 1357 | */ | ||
| 1358 | if (atomic_read(&sp->ref_count) > 1) { | ||
| 1359 | /* | 1339 | /* |
| 1360 | * The command is not yet completed. We need to wait for either | 1340 | * The command has been aborted. That means that the firmware |
| 1361 | * command completion or abort completion. | 1341 | * won't report a completion. |
| 1362 | */ | 1342 | */ |
| 1363 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(eh_waitq); | 1343 | sp->done(sp, DID_ABORT << 16); |
| 1364 | uint32_t ratov = ha->r_a_tov/10; | 1344 | ret = SUCCESS; |
| 1365 | 1345 | break; | |
| 1366 | /* Go ahead and release the extra ref_count obtained earlier */ | 1346 | default: |
| 1367 | sp->done(sp, DID_RESET << 16); | 1347 | /* |
| 1368 | sp->cwaitq = &eh_waitq; | 1348 | * Either abort failed or abort and completion raced. Let |
| 1369 | 1349 | * the SCSI core retry the abort in the former case. | |
| 1370 | if (!wait_event_lock_irq_timeout(eh_waitq, | 1350 | */ |
| 1371 | CMD_SP(cmd) == NULL, *qpair->qp_lock_ptr, | 1351 | ret = FAILED; |
| 1372 | msecs_to_jiffies(4 * ratov * 1000))) { | 1352 | break; |
| 1373 | /* | ||
| 1374 | * The abort got dropped, LOGO will be sent and the | ||
| 1375 | * original command will be completed with CS_TIMEOUT | ||
| 1376 | * completion | ||
| 1377 | */ | ||
| 1378 | ql_dbg(ql_dbg_taskm, vha, 0xffff, | ||
| 1379 | "%s: Abort wait timer (4 * R_A_TOV[%d]) expired\n", | ||
| 1380 | __func__, ha->r_a_tov); | ||
| 1381 | sp->cwaitq = NULL; | ||
| 1382 | ret = FAILED; | ||
| 1383 | goto end; | ||
| 1384 | } | ||
| 1385 | } else { | ||
| 1386 | /* Command completed while processing the abort */ | ||
| 1387 | sp->done(sp, DID_RESET << 16); | ||
| 1388 | } | 1353 | } |
| 1389 | end: | 1354 | |
| 1390 | spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); | ||
| 1391 | ql_log(ql_log_info, vha, 0x801c, | 1355 | ql_log(ql_log_info, vha, 0x801c, |
| 1392 | "Abort command issued nexus=%ld:%d:%llu -- %d %x.\n", | 1356 | "Abort command issued nexus=%ld:%d:%llu -- %x.\n", |
| 1393 | vha->host_no, id, lun, wait, ret); | 1357 | vha->host_no, id, lun, ret); |
| 1394 | 1358 | ||
| 1395 | return ret; | 1359 | return ret; |
| 1396 | } | 1360 | } |
| @@ -1766,42 +1730,34 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, | |||
| 1766 | __releases(qp->qp_lock_ptr) | 1730 | __releases(qp->qp_lock_ptr) |
| 1767 | __acquires(qp->qp_lock_ptr) | 1731 | __acquires(qp->qp_lock_ptr) |
| 1768 | { | 1732 | { |
| 1733 | DECLARE_COMPLETION_ONSTACK(comp); | ||
| 1769 | scsi_qla_host_t *vha = qp->vha; | 1734 | scsi_qla_host_t *vha = qp->vha; |
| 1770 | struct qla_hw_data *ha = vha->hw; | 1735 | struct qla_hw_data *ha = vha->hw; |
| 1736 | int rval; | ||
| 1771 | 1737 | ||
| 1772 | if (sp->type == SRB_NVME_CMD || sp->type == SRB_NVME_LS) { | 1738 | if (sp_get(sp)) |
| 1773 | if (!sp_get(sp)) { | 1739 | return; |
| 1774 | /* got sp */ | ||
| 1775 | spin_unlock_irqrestore(qp->qp_lock_ptr, *flags); | ||
| 1776 | qla_nvme_abort(ha, sp, res); | ||
| 1777 | spin_lock_irqsave(qp->qp_lock_ptr, *flags); | ||
| 1778 | } | ||
| 1779 | } else if (GET_CMD_SP(sp) && !ha->flags.eeh_busy && | ||
| 1780 | !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && | ||
| 1781 | !qla2x00_isp_reg_stat(ha) && sp->type == SRB_SCSI_CMD) { | ||
| 1782 | /* | ||
| 1783 | * Don't abort commands in adapter during EEH recovery as it's | ||
| 1784 | * not accessible/responding. | ||
| 1785 | * | ||
| 1786 | * Get a reference to the sp and drop the lock. The reference | ||
| 1787 | * ensures this sp->done() call and not the call in | ||
| 1788 | * qla2xxx_eh_abort() ends the SCSI cmd (with result 'res'). | ||
| 1789 | */ | ||
| 1790 | if (!sp_get(sp)) { | ||
| 1791 | int status; | ||
| 1792 | 1740 | ||
| 1793 | spin_unlock_irqrestore(qp->qp_lock_ptr, *flags); | 1741 | if (sp->type == SRB_NVME_CMD || sp->type == SRB_NVME_LS || |
| 1794 | status = qla2xxx_eh_abort(GET_CMD_SP(sp)); | 1742 | (sp->type == SRB_SCSI_CMD && !ha->flags.eeh_busy && |
| 1795 | spin_lock_irqsave(qp->qp_lock_ptr, *flags); | 1743 | !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && |
| 1796 | /* | 1744 | !qla2x00_isp_reg_stat(ha))) { |
| 1797 | * Get rid of extra reference caused | 1745 | sp->comp = ∁ |
| 1798 | * by early exit from qla2xxx_eh_abort | 1746 | rval = ha->isp_ops->abort_command(sp); |
| 1799 | */ | 1747 | spin_unlock_irqrestore(qp->qp_lock_ptr, *flags); |
| 1800 | if (status == FAST_IO_FAIL) | 1748 | |
| 1801 | atomic_dec(&sp->ref_count); | 1749 | switch (rval) { |
| 1750 | case QLA_SUCCESS: | ||
| 1751 | sp->done(sp, res); | ||
| 1752 | break; | ||
| 1753 | case QLA_FUNCTION_PARAMETER_ERROR: | ||
| 1754 | wait_for_completion(&comp); | ||
| 1755 | break; | ||
| 1802 | } | 1756 | } |
| 1757 | |||
| 1758 | spin_lock_irqsave(qp->qp_lock_ptr, *flags); | ||
| 1759 | sp->comp = NULL; | ||
| 1803 | } | 1760 | } |
| 1804 | sp->done(sp, res); | ||
| 1805 | } | 1761 | } |
| 1806 | 1762 | ||
| 1807 | static void | 1763 | static void |
