|
11 | 11 |
|
12 | 12 | #include <scsi/scsi_tcq.h>
|
13 | 13 |
|
| 14 | +static int qla_start_scsi_type6(srb_t *sp); |
14 | 15 | /**
|
15 | 16 | * qla2x00_get_cmd_direction() - Determine control_flag data direction.
|
16 | 17 | * @sp: SCSI command
|
@@ -1721,6 +1722,8 @@ qla24xx_dif_start_scsi(srb_t *sp)
|
1721 | 1722 | if (scsi_get_prot_op(cmd) == SCSI_PROT_NORMAL) {
|
1722 | 1723 | if (cmd->cmd_len <= 16)
|
1723 | 1724 | return qla24xx_start_scsi(sp);
|
| 1725 | + else |
| 1726 | + return qla_start_scsi_type6(sp); |
1724 | 1727 | }
|
1725 | 1728 |
|
1726 | 1729 | /* Setup device pointers. */
|
@@ -2100,6 +2103,8 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp)
|
2100 | 2103 | if (scsi_get_prot_op(cmd) == SCSI_PROT_NORMAL) {
|
2101 | 2104 | if (cmd->cmd_len <= 16)
|
2102 | 2105 | return qla2xxx_start_scsi_mq(sp);
|
| 2106 | + else |
| 2107 | + return qla_start_scsi_type6(sp); |
2103 | 2108 | }
|
2104 | 2109 |
|
2105 | 2110 | 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)
|
4197 | 4202 |
|
4198 | 4203 | return rval;
|
4199 | 4204 | }
|
| 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 | +} |
0 commit comments