Skip to content

Commit ae25f65

Browse files
Quinn Tranmartinkpetersen
authored andcommitted
scsi: qla2xxx: Allow 32-byte CDBs
System crashes when a 32-byte CDB was sent to a non T10 PI disk: [ 177.143279] ? qla2xxx_dif_start_scsi_mq+0xcd8/0xce0 [qla2xxx] [ 177.149165] ? internal_add_timer+0x42/0x70 [ 177.153372] qla2xxx_mqueuecommand+0x207/0x2b0 [qla2xxx] [ 177.158730] scsi_queue_rq+0x2b7/0xc00 [ 177.162501] blk_mq_dispatch_rq_list+0x3ea/0x7e0 Current code attempted to use CRC IOCB to send the command but failed. Instead, type 6 IOCB should be used to send the I/O. Clone existing type 6 IOCB code with addition of MQ support to allow 32-byte CDBs to go through. Signed-off-by: Quinn Tran <qutran@marvell.com> Cc: Laurence Oberman <loberman@redhat.com> Signed-off-by: Nilesh Javali <njavali@marvell.com> Link: https://lore.kernel.org/r/20230817063132.21900-3-njavali@marvell.com Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent efeda3b commit ae25f65

File tree

2 files changed

+272
-1
lines changed

2 files changed

+272
-1
lines changed

drivers/scsi/qla2xxx/qla_iocb.c

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include <scsi/scsi_tcq.h>
1313

14+
static int qla_start_scsi_type6(srb_t *sp);
1415
/**
1516
* qla2x00_get_cmd_direction() - Determine control_flag data direction.
1617
* @sp: SCSI command
@@ -1721,6 +1722,8 @@ qla24xx_dif_start_scsi(srb_t *sp)
17211722
if (scsi_get_prot_op(cmd) == SCSI_PROT_NORMAL) {
17221723
if (cmd->cmd_len <= 16)
17231724
return qla24xx_start_scsi(sp);
1725+
else
1726+
return qla_start_scsi_type6(sp);
17241727
}
17251728

17261729
/* Setup device pointers. */
@@ -2100,6 +2103,8 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp)
21002103
if (scsi_get_prot_op(cmd) == SCSI_PROT_NORMAL) {
21012104
if (cmd->cmd_len <= 16)
21022105
return qla2xxx_start_scsi_mq(sp);
2106+
else
2107+
return qla_start_scsi_type6(sp);
21032108
}
21042109

21052110
spin_lock_irqsave(&qpair->qp_lock, flags);
@@ -4197,3 +4202,267 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds)
41974202

41984203
return rval;
41994204
}
4205+
4206+
/**
4207+
* qla_start_scsi_type6() - Send a SCSI command to the ISP
4208+
* @sp: command to send to the ISP
4209+
*
4210+
* Returns non-zero if a failure occurred, else zero.
4211+
*/
4212+
static int
4213+
qla_start_scsi_type6(srb_t *sp)
4214+
{
4215+
int nseg;
4216+
unsigned long flags;
4217+
uint32_t *clr_ptr;
4218+
uint32_t handle;
4219+
struct cmd_type_6 *cmd_pkt;
4220+
uint16_t cnt;
4221+
uint16_t req_cnt;
4222+
uint16_t tot_dsds;
4223+
struct req_que *req = NULL;
4224+
struct rsp_que *rsp;
4225+
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
4226+
struct scsi_qla_host *vha = sp->fcport->vha;
4227+
struct qla_hw_data *ha = vha->hw;
4228+
struct qla_qpair *qpair = sp->qpair;
4229+
uint16_t more_dsd_lists = 0;
4230+
struct dsd_dma *dsd_ptr;
4231+
uint16_t i;
4232+
__be32 *fcp_dl;
4233+
uint8_t additional_cdb_len;
4234+
struct ct6_dsd *ctx;
4235+
4236+
/* Acquire qpair specific lock */
4237+
spin_lock_irqsave(&qpair->qp_lock, flags);
4238+
4239+
/* Setup qpair pointers */
4240+
req = qpair->req;
4241+
rsp = qpair->rsp;
4242+
4243+
/* So we know we haven't pci_map'ed anything yet */
4244+
tot_dsds = 0;
4245+
4246+
/* Send marker if required */
4247+
if (vha->marker_needed != 0) {
4248+
if (__qla2x00_marker(vha, qpair, 0, 0, MK_SYNC_ALL) != QLA_SUCCESS) {
4249+
spin_unlock_irqrestore(&qpair->qp_lock, flags);
4250+
return QLA_FUNCTION_FAILED;
4251+
}
4252+
vha->marker_needed = 0;
4253+
}
4254+
4255+
handle = qla2xxx_get_next_handle(req);
4256+
if (handle == 0)
4257+
goto queuing_error;
4258+
4259+
/* Map the sg table so we have an accurate count of sg entries needed */
4260+
if (scsi_sg_count(cmd)) {
4261+
nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd),
4262+
scsi_sg_count(cmd), cmd->sc_data_direction);
4263+
if (unlikely(!nseg))
4264+
goto queuing_error;
4265+
} else {
4266+
nseg = 0;
4267+
}
4268+
4269+
tot_dsds = nseg;
4270+
4271+
/* eventhough driver only need 1 T6 IOCB, FW still convert DSD to Continueation IOCB */
4272+
req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
4273+
4274+
sp->iores.res_type = RESOURCE_IOCB | RESOURCE_EXCH;
4275+
sp->iores.exch_cnt = 1;
4276+
sp->iores.iocb_cnt = req_cnt;
4277+
4278+
if (qla_get_fw_resources(sp->qpair, &sp->iores))
4279+
goto queuing_error;
4280+
4281+
more_dsd_lists = qla24xx_calc_dsd_lists(tot_dsds);
4282+
if ((more_dsd_lists + qpair->dsd_inuse) >= NUM_DSD_CHAIN) {
4283+
ql_dbg(ql_dbg_io, vha, 0x3028,
4284+
"Num of DSD list %d is than %d for cmd=%p.\n",
4285+
more_dsd_lists + qpair->dsd_inuse, NUM_DSD_CHAIN, cmd);
4286+
goto queuing_error;
4287+
}
4288+
4289+
if (more_dsd_lists <= qpair->dsd_avail)
4290+
goto sufficient_dsds;
4291+
else
4292+
more_dsd_lists -= qpair->dsd_avail;
4293+
4294+
for (i = 0; i < more_dsd_lists; i++) {
4295+
dsd_ptr = kzalloc(sizeof(*dsd_ptr), GFP_ATOMIC);
4296+
if (!dsd_ptr) {
4297+
ql_log(ql_log_fatal, vha, 0x3029,
4298+
"Failed to allocate memory for dsd_dma for cmd=%p.\n", cmd);
4299+
goto queuing_error;
4300+
}
4301+
INIT_LIST_HEAD(&dsd_ptr->list);
4302+
4303+
dsd_ptr->dsd_addr = dma_pool_alloc(ha->dl_dma_pool,
4304+
GFP_ATOMIC, &dsd_ptr->dsd_list_dma);
4305+
if (!dsd_ptr->dsd_addr) {
4306+
kfree(dsd_ptr);
4307+
ql_log(ql_log_fatal, vha, 0x302a,
4308+
"Failed to allocate memory for dsd_addr for cmd=%p.\n", cmd);
4309+
goto queuing_error;
4310+
}
4311+
list_add_tail(&dsd_ptr->list, &qpair->dsd_list);
4312+
qpair->dsd_avail++;
4313+
}
4314+
4315+
sufficient_dsds:
4316+
req_cnt = 1;
4317+
4318+
if (req->cnt < (req_cnt + 2)) {
4319+
if (IS_SHADOW_REG_CAPABLE(ha)) {
4320+
cnt = *req->out_ptr;
4321+
} else {
4322+
cnt = (uint16_t)rd_reg_dword_relaxed(req->req_q_out);
4323+
if (qla2x00_check_reg16_for_disconnect(vha, cnt))
4324+
goto queuing_error;
4325+
}
4326+
4327+
if (req->ring_index < cnt)
4328+
req->cnt = cnt - req->ring_index;
4329+
else
4330+
req->cnt = req->length - (req->ring_index - cnt);
4331+
if (req->cnt < (req_cnt + 2))
4332+
goto queuing_error;
4333+
}
4334+
4335+
ctx = &sp->u.scmd.ct6_ctx;
4336+
4337+
memset(ctx, 0, sizeof(struct ct6_dsd));
4338+
ctx->fcp_cmnd = dma_pool_zalloc(ha->fcp_cmnd_dma_pool,
4339+
GFP_ATOMIC, &ctx->fcp_cmnd_dma);
4340+
if (!ctx->fcp_cmnd) {
4341+
ql_log(ql_log_fatal, vha, 0x3031,
4342+
"Failed to allocate fcp_cmnd for cmd=%p.\n", cmd);
4343+
goto queuing_error;
4344+
}
4345+
4346+
/* Initialize the DSD list and dma handle */
4347+
INIT_LIST_HEAD(&ctx->dsd_list);
4348+
ctx->dsd_use_cnt = 0;
4349+
4350+
if (cmd->cmd_len > 16) {
4351+
additional_cdb_len = cmd->cmd_len - 16;
4352+
if (cmd->cmd_len % 4 ||
4353+
cmd->cmd_len > QLA_CDB_BUF_SIZE) {
4354+
/*
4355+
* SCSI command bigger than 16 bytes must be
4356+
* multiple of 4 or too big.
4357+
*/
4358+
ql_log(ql_log_warn, vha, 0x3033,
4359+
"scsi cmd len %d not multiple of 4 for cmd=%p.\n",
4360+
cmd->cmd_len, cmd);
4361+
goto queuing_error_fcp_cmnd;
4362+
}
4363+
ctx->fcp_cmnd_len = 12 + cmd->cmd_len + 4;
4364+
} else {
4365+
additional_cdb_len = 0;
4366+
ctx->fcp_cmnd_len = 12 + 16 + 4;
4367+
}
4368+
4369+
/* Build command packet. */
4370+
req->current_outstanding_cmd = handle;
4371+
req->outstanding_cmds[handle] = sp;
4372+
sp->handle = handle;
4373+
cmd->host_scribble = (unsigned char *)(unsigned long)handle;
4374+
req->cnt -= req_cnt;
4375+
4376+
cmd_pkt = (struct cmd_type_6 *)req->ring_ptr;
4377+
cmd_pkt->handle = make_handle(req->id, handle);
4378+
4379+
/* tagged queuing modifier -- default is TSK_SIMPLE (0). */
4380+
clr_ptr = (uint32_t *)cmd_pkt + 2;
4381+
memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8);
4382+
cmd_pkt->dseg_count = cpu_to_le16(tot_dsds);
4383+
4384+
/* Set NPORT-ID and LUN number */
4385+
cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id);
4386+
cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa;
4387+
cmd_pkt->port_id[1] = sp->fcport->d_id.b.area;
4388+
cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
4389+
cmd_pkt->vp_index = sp->vha->vp_idx;
4390+
4391+
/* Build IOCB segments */
4392+
qla24xx_build_scsi_type_6_iocbs(sp, cmd_pkt, tot_dsds);
4393+
4394+
int_to_scsilun(cmd->device->lun, &cmd_pkt->lun);
4395+
host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
4396+
4397+
/* build FCP_CMND IU */
4398+
int_to_scsilun(cmd->device->lun, &ctx->fcp_cmnd->lun);
4399+
ctx->fcp_cmnd->additional_cdb_len = additional_cdb_len;
4400+
4401+
if (cmd->sc_data_direction == DMA_TO_DEVICE)
4402+
ctx->fcp_cmnd->additional_cdb_len |= 1;
4403+
else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
4404+
ctx->fcp_cmnd->additional_cdb_len |= 2;
4405+
4406+
/* Populate the FCP_PRIO. */
4407+
if (ha->flags.fcp_prio_enabled)
4408+
ctx->fcp_cmnd->task_attribute |=
4409+
sp->fcport->fcp_prio << 3;
4410+
4411+
memcpy(ctx->fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len);
4412+
4413+
fcp_dl = (__be32 *)(ctx->fcp_cmnd->cdb + 16 +
4414+
additional_cdb_len);
4415+
*fcp_dl = htonl((uint32_t)scsi_bufflen(cmd));
4416+
4417+
cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(ctx->fcp_cmnd_len);
4418+
put_unaligned_le64(ctx->fcp_cmnd_dma,
4419+
&cmd_pkt->fcp_cmnd_dseg_address);
4420+
4421+
sp->flags |= SRB_FCP_CMND_DMA_VALID;
4422+
cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
4423+
/* Set total data segment count. */
4424+
cmd_pkt->entry_count = (uint8_t)req_cnt;
4425+
4426+
wmb();
4427+
/* Adjust ring index. */
4428+
req->ring_index++;
4429+
if (req->ring_index == req->length) {
4430+
req->ring_index = 0;
4431+
req->ring_ptr = req->ring;
4432+
} else {
4433+
req->ring_ptr++;
4434+
}
4435+
4436+
sp->qpair->cmd_cnt++;
4437+
sp->flags |= SRB_DMA_VALID;
4438+
4439+
/* Set chip new ring index. */
4440+
wrt_reg_dword(req->req_q_in, req->ring_index);
4441+
4442+
/* Manage unprocessed RIO/ZIO commands in response queue. */
4443+
if (vha->flags.process_response_queue &&
4444+
rsp->ring_ptr->signature != RESPONSE_PROCESSED)
4445+
qla24xx_process_response_queue(vha, rsp);
4446+
4447+
spin_unlock_irqrestore(&qpair->qp_lock, flags);
4448+
4449+
return QLA_SUCCESS;
4450+
4451+
queuing_error_fcp_cmnd:
4452+
dma_pool_free(ha->fcp_cmnd_dma_pool, ctx->fcp_cmnd, ctx->fcp_cmnd_dma);
4453+
4454+
queuing_error:
4455+
if (tot_dsds)
4456+
scsi_dma_unmap(cmd);
4457+
4458+
qla_put_fw_resources(sp->qpair, &sp->iores);
4459+
4460+
if (sp->u.scmd.crc_ctx) {
4461+
mempool_free(sp->u.scmd.crc_ctx, ha->ctx_mempool);
4462+
sp->u.scmd.crc_ctx = NULL;
4463+
}
4464+
4465+
spin_unlock_irqrestore(&qpair->qp_lock, flags);
4466+
4467+
return QLA_FUNCTION_FAILED;
4468+
}

drivers/scsi/qla2xxx/qla_nx.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,9 @@ struct fcp_cmnd {
857857
uint8_t task_attribute;
858858
uint8_t task_management;
859859
uint8_t additional_cdb_len;
860-
uint8_t cdb[260]; /* 256 for CDB len and 4 for FCP_DL */
860+
#define QLA_CDB_BUF_SIZE 256
861+
#define QLA_FCP_DL_SIZE 4
862+
uint8_t cdb[QLA_CDB_BUF_SIZE + QLA_FCP_DL_SIZE]; /* 256 for CDB len and 4 for FCP_DL */
861863
};
862864

863865
struct dsd_dma {

0 commit comments

Comments
 (0)