Skip to content

Commit 5c50d84

Browse files
abattersbymartinkpetersen
authored andcommitted
scsi: qla2xxx: target: Improve checks in qlt_xmit_response() / qlt_rdy_to_xfer()
Similar fixes to both functions: qlt_xmit_response: - If the cmd cannot be processed, remember to call ->free_cmd() to prevent the target-mode midlevel from seeing a cmd lockup. - Do not try to send the response if the exchange has been terminated. - Check for chip reset once after lock instead of both before and after lock. - Give errors from qlt_pre_xmit_response() a lower priority to compensate for removing the first check for chip reset. qlt_rdy_to_xfer: - Check for chip reset after lock instead of before lock to avoid races. - Do not try to receive data if the exchange has been terminated. - Give errors from qlt_pci_map_calc_cnt() a lower priority to compensate for moving the check for chip reset. Signed-off-by: Tony Battersby <tonyb@cybernetics.com> Link: https://patch.msgid.link/cd6ccd31-33fa-4454-be36-507bf578a546@cybernetics.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 17488f1 commit 5c50d84

1 file changed

Lines changed: 48 additions & 38 deletions

File tree

drivers/scsi/qla2xxx/qla_target.c

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3206,46 +3206,47 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
32063206
uint32_t full_req_cnt = 0;
32073207
unsigned long flags = 0;
32083208
int res;
3209-
3210-
if (!qpair->fw_started || (cmd->reset_count != qpair->chip_reset) ||
3211-
(cmd->sess && cmd->sess->deleted)) {
3212-
cmd->state = QLA_TGT_STATE_PROCESSED;
3213-
return 0;
3214-
}
3209+
int pre_xmit_res;
32153210

32163211
ql_dbg_qp(ql_dbg_tgt, qpair, 0xe018,
32173212
"is_send_status=%d, cmd->bufflen=%d, cmd->sg_cnt=%d, cmd->dma_data_direction=%d se_cmd[%p] qp %d\n",
32183213
(xmit_type & QLA_TGT_XMIT_STATUS) ?
32193214
1 : 0, cmd->bufflen, cmd->sg_cnt, cmd->dma_data_direction,
32203215
&cmd->se_cmd, qpair->id);
32213216

3222-
res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status,
3217+
pre_xmit_res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status,
32233218
&full_req_cnt);
3224-
if (unlikely(res != 0)) {
3225-
return res;
3226-
}
3219+
/*
3220+
* Check pre_xmit_res later because we want to check other errors
3221+
* first.
3222+
*/
32273223

32283224
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
32293225

3226+
if (unlikely(cmd->sent_term_exchg ||
3227+
cmd->sess->deleted ||
3228+
!qpair->fw_started ||
3229+
cmd->reset_count != qpair->chip_reset)) {
3230+
ql_dbg(ql_dbg_tgt_mgt, vha, 0xe101,
3231+
"qla_target(%d): tag %lld: skipping send response for aborted cmd\n",
3232+
vha->vp_idx, cmd->se_cmd.tag);
3233+
qlt_unmap_sg(vha, cmd);
3234+
cmd->state = QLA_TGT_STATE_PROCESSED;
3235+
vha->hw->tgt.tgt_ops->free_cmd(cmd);
3236+
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
3237+
return 0;
3238+
}
3239+
3240+
/* Check for errors from qlt_pre_xmit_response(). */
3241+
res = pre_xmit_res;
3242+
if (unlikely(res))
3243+
goto out_unmap_unlock;
3244+
32303245
if (xmit_type == QLA_TGT_XMIT_STATUS)
32313246
qpair->tgt_counters.core_qla_snd_status++;
32323247
else
32333248
qpair->tgt_counters.core_qla_que_buf++;
32343249

3235-
if (!qpair->fw_started || cmd->reset_count != qpair->chip_reset) {
3236-
/*
3237-
* Either the port is not online or this request was from
3238-
* previous life, just abort the processing.
3239-
*/
3240-
cmd->state = QLA_TGT_STATE_PROCESSED;
3241-
ql_dbg_qp(ql_dbg_async, qpair, 0xe101,
3242-
"RESET-RSP online/active/old-count/new-count = %d/%d/%d/%d.\n",
3243-
vha->flags.online, qla2x00_reset_active(vha),
3244-
cmd->reset_count, qpair->chip_reset);
3245-
res = 0;
3246-
goto out_unmap_unlock;
3247-
}
3248-
32493250
/* Does F/W have an IOCBs for this request */
32503251
res = qlt_check_reserve_free_req(qpair, full_req_cnt);
32513252
if (unlikely(res))
@@ -3360,6 +3361,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
33603361
struct qla_tgt_prm prm;
33613362
unsigned long flags = 0;
33623363
int res = 0;
3364+
int pci_map_res;
33633365
struct qla_qpair *qpair = cmd->qpair;
33643366

33653367
memset(&prm, 0, sizeof(prm));
@@ -3368,28 +3370,36 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
33683370
prm.sg = NULL;
33693371
prm.req_cnt = 1;
33703372

3371-
if (!qpair->fw_started || (cmd->reset_count != qpair->chip_reset) ||
3372-
(cmd->sess && cmd->sess->deleted)) {
3373-
/*
3374-
* Either the port is not online or this request was from
3375-
* previous life, just abort the processing.
3376-
*/
3373+
/* Calculate number of entries and segments required */
3374+
pci_map_res = qlt_pci_map_calc_cnt(&prm);
3375+
/*
3376+
* Check pci_map_res later because we want to check other errors first.
3377+
*/
3378+
3379+
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
3380+
3381+
if (unlikely(cmd->sent_term_exchg ||
3382+
cmd->sess->deleted ||
3383+
!qpair->fw_started ||
3384+
cmd->reset_count != qpair->chip_reset)) {
3385+
ql_dbg(ql_dbg_tgt_mgt, vha, 0xe102,
3386+
"qla_target(%d): tag %lld: skipping data-out for aborted cmd\n",
3387+
vha->vp_idx, cmd->se_cmd.tag);
3388+
qlt_unmap_sg(vha, cmd);
33773389
cmd->aborted = 1;
33783390
cmd->write_data_transferred = 0;
33793391
cmd->state = QLA_TGT_STATE_DATA_IN;
33803392
vha->hw->tgt.tgt_ops->handle_data(cmd);
3381-
ql_dbg_qp(ql_dbg_async, qpair, 0xe102,
3382-
"RESET-XFR online/active/old-count/new-count = %d/%d/%d/%d.\n",
3383-
vha->flags.online, qla2x00_reset_active(vha),
3384-
cmd->reset_count, qpair->chip_reset);
3393+
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
33853394
return 0;
33863395
}
33873396

3388-
/* Calculate number of entries and segments required */
3389-
if (qlt_pci_map_calc_cnt(&prm) != 0)
3390-
return -EAGAIN;
3397+
/* Check for errors from qlt_pci_map_calc_cnt(). */
3398+
if (unlikely(pci_map_res != 0)) {
3399+
res = -EAGAIN;
3400+
goto out_unlock_free_unmap;
3401+
}
33913402

3392-
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
33933403
/* Does F/W have an IOCBs for this request */
33943404
res = qlt_check_reserve_free_req(qpair, prm.req_cnt);
33953405
if (res != 0)

0 commit comments

Comments
 (0)