diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_iocb.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 396 |
1 files changed, 285 insertions, 111 deletions
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 7bac3cd109d..dbec89622a0 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -150,7 +150,8 @@ qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts) /* We only support T10 DIF right now */ if (guard != SHOST_DIX_GUARD_CRC) { - DEBUG2(printk(KERN_ERR "Unsupported guard: %d\n", guard)); + ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3007, + "Unsupported guard: %d for cmd=%p.\n", guard, sp->cmd); return 0; } @@ -343,9 +344,10 @@ qla2x00_start_scsi(srb_t *sp) /* Send marker if required */ if (vha->marker_needed != 0) { - if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) - != QLA_SUCCESS) + if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) != + QLA_SUCCESS) { return (QLA_FUNCTION_FAILED); + } vha->marker_needed = 0; } @@ -490,8 +492,8 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, mrk24 = NULL; mrk = (mrk_entry_t *)qla2x00_alloc_iocbs(vha, 0); if (mrk == NULL) { - DEBUG2_3(printk("%s(%ld): failed to allocate Marker IOCB.\n", - __func__, base_vha->host_no)); + ql_log(ql_log_warn, base_vha, 0x3026, + "Failed to allocate Marker IOCB.\n"); return (QLA_FUNCTION_FAILED); } @@ -547,9 +549,10 @@ qla2x00_isp_cmd(struct scsi_qla_host *vha, struct req_que *req) device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp; - DEBUG5(printk("%s(): IOCB data:\n", __func__)); - DEBUG5(qla2x00_dump_buffer( - (uint8_t *)req->ring_ptr, REQUEST_ENTRY_SIZE)); + ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x302d, + "IOCB data:\n"); + ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302e, + (uint8_t *)req->ring_ptr, REQUEST_ENTRY_SIZE); /* Adjust ring index. */ req->ring_index++; @@ -604,7 +607,7 @@ qla2x00_isp_cmd(struct scsi_qla_host *vha, struct req_que *req) * Returns the number of IOCB entries needed to store @dsds. */ inline uint16_t -qla24xx_calc_iocbs(uint16_t dsds) +qla24xx_calc_iocbs(scsi_qla_host_t *vha, uint16_t dsds) { uint16_t iocbs; @@ -614,8 +617,6 @@ qla24xx_calc_iocbs(uint16_t dsds) if ((dsds - 1) % 5) iocbs++; } - DEBUG3(printk(KERN_DEBUG "%s(): Required PKT(s) = %d\n", - __func__, iocbs)); return iocbs; } @@ -708,19 +709,28 @@ struct fw_dif_context { * */ static inline void -qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt, +qla24xx_set_t10dif_tags(srb_t *sp, struct fw_dif_context *pkt, unsigned int protcnt) { - struct sd_dif_tuple *spt; - unsigned char op = scsi_get_prot_op(cmd); + struct scsi_cmnd *cmd = sp->cmd; + scsi_qla_host_t *vha = shost_priv(cmd->device->host); switch (scsi_get_prot_type(cmd)) { - /* For TYPE 0 protection: no checking */ case SCSI_PROT_DIF_TYPE0: - pkt->ref_tag_mask[0] = 0x00; - pkt->ref_tag_mask[1] = 0x00; - pkt->ref_tag_mask[2] = 0x00; - pkt->ref_tag_mask[3] = 0x00; + /* + * No check for ql2xenablehba_err_chk, as it would be an + * I/O error if hba tag generation is not done. + */ + pkt->ref_tag = cpu_to_le32((uint32_t) + (0xffffffff & scsi_get_lba(cmd))); + + if (!qla2x00_hba_err_chk_enabled(sp)) + break; + + pkt->ref_tag_mask[0] = 0xff; + pkt->ref_tag_mask[1] = 0xff; + pkt->ref_tag_mask[2] = 0xff; + pkt->ref_tag_mask[3] = 0xff; break; /* @@ -728,20 +738,16 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt, * match LBA in CDB + N */ case SCSI_PROT_DIF_TYPE2: - if (!ql2xenablehba_err_chk) - break; - - if (scsi_prot_sg_count(cmd)) { - spt = page_address(sg_page(scsi_prot_sglist(cmd))) + - scsi_prot_sglist(cmd)[0].offset; - pkt->app_tag = swab32(spt->app_tag); - pkt->app_tag_mask[0] = 0xff; - pkt->app_tag_mask[1] = 0xff; - } + pkt->app_tag = __constant_cpu_to_le16(0); + pkt->app_tag_mask[0] = 0x0; + pkt->app_tag_mask[1] = 0x0; pkt->ref_tag = cpu_to_le32((uint32_t) (0xffffffff & scsi_get_lba(cmd))); + if (!qla2x00_hba_err_chk_enabled(sp)) + break; + /* enable ALL bytes of the ref tag */ pkt->ref_tag_mask[0] = 0xff; pkt->ref_tag_mask[1] = 0xff; @@ -761,26 +767,15 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt, * 16 bit app tag. */ case SCSI_PROT_DIF_TYPE1: - if (!ql2xenablehba_err_chk) + pkt->ref_tag = cpu_to_le32((uint32_t) + (0xffffffff & scsi_get_lba(cmd))); + pkt->app_tag = __constant_cpu_to_le16(0); + pkt->app_tag_mask[0] = 0x0; + pkt->app_tag_mask[1] = 0x0; + + if (!qla2x00_hba_err_chk_enabled(sp)) break; - if (protcnt && (op == SCSI_PROT_WRITE_STRIP || - op == SCSI_PROT_WRITE_PASS)) { - spt = page_address(sg_page(scsi_prot_sglist(cmd))) + - scsi_prot_sglist(cmd)[0].offset; - DEBUG18(printk(KERN_DEBUG - "%s(): LBA from user %p, lba = 0x%x\n", - __func__, spt, (int)spt->ref_tag)); - pkt->ref_tag = swab32(spt->ref_tag); - pkt->app_tag_mask[0] = 0x0; - pkt->app_tag_mask[1] = 0x0; - } else { - pkt->ref_tag = cpu_to_le32((uint32_t) - (0xffffffff & scsi_get_lba(cmd))); - pkt->app_tag = __constant_cpu_to_le16(0); - pkt->app_tag_mask[0] = 0x0; - pkt->app_tag_mask[1] = 0x0; - } /* enable ALL bytes of the ref tag */ pkt->ref_tag_mask[0] = 0xff; pkt->ref_tag_mask[1] = 0xff; @@ -789,15 +784,169 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt, break; } - DEBUG18(printk(KERN_DEBUG - "%s(): Setting protection Tags: (BIG) ref tag = 0x%x," - " app tag = 0x%x, prot SG count %d , cmd lba 0x%x," - " prot_type=%u\n", __func__, pkt->ref_tag, pkt->app_tag, protcnt, - (int)scsi_get_lba(cmd), scsi_get_prot_type(cmd))); + ql_dbg(ql_dbg_io, vha, 0x3009, + "Setting protection Tags: (BIG) ref tag = 0x%x, app tag = 0x%x, " + "prot SG count %d, cmd lba 0x%x, prot_type=%u cmd=%p.\n", + pkt->ref_tag, pkt->app_tag, protcnt, (int)scsi_get_lba(cmd), + scsi_get_prot_type(cmd), cmd); } +struct qla2_sgx { + dma_addr_t dma_addr; /* OUT */ + uint32_t dma_len; /* OUT */ + + uint32_t tot_bytes; /* IN */ + struct scatterlist *cur_sg; /* IN */ + + /* for book keeping, bzero on initial invocation */ + uint32_t bytes_consumed; + uint32_t num_bytes; + uint32_t tot_partial; + + /* for debugging */ + uint32_t num_sg; + srb_t *sp; +}; + +static int +qla24xx_get_one_block_sg(uint32_t blk_sz, struct qla2_sgx *sgx, + uint32_t *partial) +{ + struct scatterlist *sg; + uint32_t cumulative_partial, sg_len; + dma_addr_t sg_dma_addr; + + if (sgx->num_bytes == sgx->tot_bytes) + return 0; + + sg = sgx->cur_sg; + cumulative_partial = sgx->tot_partial; + + sg_dma_addr = sg_dma_address(sg); + sg_len = sg_dma_len(sg); + + sgx->dma_addr = sg_dma_addr + sgx->bytes_consumed; + + if ((cumulative_partial + (sg_len - sgx->bytes_consumed)) >= blk_sz) { + sgx->dma_len = (blk_sz - cumulative_partial); + sgx->tot_partial = 0; + sgx->num_bytes += blk_sz; + *partial = 0; + } else { + sgx->dma_len = sg_len - sgx->bytes_consumed; + sgx->tot_partial += sgx->dma_len; + *partial = 1; + } + + sgx->bytes_consumed += sgx->dma_len; + + if (sg_len == sgx->bytes_consumed) { + sg = sg_next(sg); + sgx->num_sg++; + sgx->cur_sg = sg; + sgx->bytes_consumed = 0; + } + + return 1; +} static int +qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp, + uint32_t *dsd, uint16_t tot_dsds) +{ + void *next_dsd; + uint8_t avail_dsds = 0; + uint32_t dsd_list_len; + struct dsd_dma *dsd_ptr; + struct scatterlist *sg_prot; + uint32_t *cur_dsd = dsd; + uint16_t used_dsds = tot_dsds; + + uint32_t prot_int; + uint32_t partial; + struct qla2_sgx sgx; + dma_addr_t sle_dma; + uint32_t sle_dma_len, tot_prot_dma_len = 0; + struct scsi_cmnd *cmd = sp->cmd; + + prot_int = cmd->device->sector_size; + + memset(&sgx, 0, sizeof(struct qla2_sgx)); + sgx.tot_bytes = scsi_bufflen(sp->cmd); + sgx.cur_sg = scsi_sglist(sp->cmd); + sgx.sp = sp; + + sg_prot = scsi_prot_sglist(sp->cmd); + + while (qla24xx_get_one_block_sg(prot_int, &sgx, &partial)) { + + sle_dma = sgx.dma_addr; + sle_dma_len = sgx.dma_len; +alloc_and_fill: + /* Allocate additional continuation packets? */ + if (avail_dsds == 0) { + avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ? + QLA_DSDS_PER_IOCB : used_dsds; + dsd_list_len = (avail_dsds + 1) * 12; + used_dsds -= avail_dsds; + + /* allocate tracking DS */ + dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC); + if (!dsd_ptr) + return 1; + + /* allocate new list */ + dsd_ptr->dsd_addr = next_dsd = + dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC, + &dsd_ptr->dsd_list_dma); + + if (!next_dsd) { + /* + * Need to cleanup only this dsd_ptr, rest + * will be done by sp_free_dma() + */ + kfree(dsd_ptr); + return 1; + } + + list_add_tail(&dsd_ptr->list, + &((struct crc_context *)sp->ctx)->dsd_list); + + sp->flags |= SRB_CRC_CTX_DSD_VALID; + + /* add new list to cmd iocb or last list */ + *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); + *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); + *cur_dsd++ = dsd_list_len; + cur_dsd = (uint32_t *)next_dsd; + } + *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); + *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); + *cur_dsd++ = cpu_to_le32(sle_dma_len); + avail_dsds--; + + if (partial == 0) { + /* Got a full protection interval */ + sle_dma = sg_dma_address(sg_prot) + tot_prot_dma_len; + sle_dma_len = 8; + + tot_prot_dma_len += sle_dma_len; + if (tot_prot_dma_len == sg_dma_len(sg_prot)) { + tot_prot_dma_len = 0; + sg_prot = sg_next(sg_prot); + } + + partial = 1; /* So as to not re-enter this block */ + goto alloc_and_fill; + } + } + /* Null termination */ + *cur_dsd++ = 0; + *cur_dsd++ = 0; + *cur_dsd++ = 0; + return 0; +} +static int qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, uint16_t tot_dsds) { @@ -809,6 +958,7 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, uint32_t *cur_dsd = dsd; int i; uint16_t used_dsds = tot_dsds; + scsi_qla_host_t *vha = shost_priv(sp->cmd->device->host); uint8_t *cp; @@ -853,9 +1003,10 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, cur_dsd = (uint32_t *)next_dsd; } sle_dma = sg_dma_address(sg); - DEBUG18(printk("%s(): %p, sg entry %d - addr =0x%x 0x%x," - " len =%d\n", __func__ , cur_dsd, i, LSD(sle_dma), - MSD(sle_dma), sg_dma_len(sg))); + ql_dbg(ql_dbg_io, vha, 0x300a, + "sg entry %d - addr=0x%x 0x%x, " "len=%d for cmd=%p.\n", + cur_dsd, i, LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg), + sp->cmd); *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); @@ -863,8 +1014,8 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) { cp = page_address(sg_page(sg)) + sg->offset; - DEBUG18(printk("%s(): User Data buffer= %p:\n", - __func__ , cp)); + ql_dbg(ql_dbg_io, vha, 0x300b, + "User data buffer=%p for cmd=%p.\n", cp, sp->cmd); } } /* Null termination */ @@ -888,7 +1039,7 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, struct scsi_cmnd *cmd; uint32_t *cur_dsd = dsd; uint16_t used_dsds = tot_dsds; - + scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); uint8_t *cp; @@ -935,10 +1086,11 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, } sle_dma = sg_dma_address(sg); if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) { - DEBUG18(printk(KERN_DEBUG - "%s(): %p, sg entry %d - addr =0x%x" - "0x%x, len =%d\n", __func__ , cur_dsd, i, - LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg))); + ql_dbg(ql_dbg_io, vha, 0x3027, + "%s(): %p, sg_entry %d - " + "addr=0x%x0x%x, len=%d.\n", + __func__, cur_dsd, i, + LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg)); } *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); @@ -946,8 +1098,9 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) { cp = page_address(sg_page(sg)) + sg->offset; - DEBUG18(printk("%s(): Protection Data buffer = %p:\n", - __func__ , cp)); + ql_dbg(ql_dbg_io, vha, 0x3028, + "%s(): Protection Data buffer = %p.\n", __func__, + cp); } avail_dsds--; } @@ -975,7 +1128,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, struct scsi_cmnd *cmd; struct scatterlist *cur_seg; int sgc; - uint32_t total_bytes; + uint32_t total_bytes = 0; uint32_t data_bytes; uint32_t dif_bytes; uint8_t bundling = 1; @@ -996,22 +1149,16 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, *((uint32_t *)(&cmd_pkt->entry_type)) = __constant_cpu_to_le32(COMMAND_TYPE_CRC_2); + vha = sp->fcport->vha; + ha = vha->hw; + /* No data transfer */ data_bytes = scsi_bufflen(cmd); if (!data_bytes || cmd->sc_data_direction == DMA_NONE) { - DEBUG18(printk(KERN_INFO "%s: Zero data bytes or DMA-NONE %d\n", - __func__, data_bytes)); cmd_pkt->byte_count = __constant_cpu_to_le32(0); return QLA_SUCCESS; } - vha = sp->fcport->vha; - ha = vha->hw; - - DEBUG18(printk(KERN_DEBUG - "%s(%ld): Executing cmd sp %p, prot_op=%u.\n", __func__, - vha->host_no, sp, scsi_get_prot_op(sp->cmd))); - cmd_pkt->vp_index = sp->fcport->vp_idx; /* Set transfer direction */ @@ -1023,8 +1170,10 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, __constant_cpu_to_le16(CF_READ_DATA); } - tot_prot_dsds = scsi_prot_sg_count(cmd); - if (!tot_prot_dsds) + if ((scsi_get_prot_op(sp->cmd) == SCSI_PROT_READ_INSERT) || + (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_STRIP) || + (scsi_get_prot_op(sp->cmd) == SCSI_PROT_READ_STRIP) || + (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_INSERT)) bundling = 0; /* Allocate CRC context from global pool */ @@ -1047,7 +1196,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, INIT_LIST_HEAD(&crc_ctx_pkt->dsd_list); - qla24xx_set_t10dif_tags(cmd, (struct fw_dif_context *) + qla24xx_set_t10dif_tags(sp, (struct fw_dif_context *) &crc_ctx_pkt->ref_tag, tot_prot_dsds); cmd_pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma)); @@ -1056,8 +1205,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, /* Determine SCSI command length -- align to 4 byte boundary */ if (cmd->cmd_len > 16) { - DEBUG18(printk(KERN_INFO "%s(): **** SCSI CMD > 16\n", - __func__)); additional_fcpcdb_len = cmd->cmd_len - 16; if ((cmd->cmd_len % 4) != 0) { /* SCSI cmd > 16 bytes must be multiple of 4 */ @@ -1078,7 +1225,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, fcp_cmnd->additional_cdb_len |= 2; int_to_scsilun(sp->cmd->device->lun, &fcp_cmnd->lun); - host_to_fcp_swap((uint8_t *)&fcp_cmnd->lun, sizeof(fcp_cmnd->lun)); memcpy(fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len); cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(fcp_cmnd_len); cmd_pkt->fcp_cmnd_dseg_address[0] = cpu_to_le32( @@ -1108,21 +1254,29 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */ - DEBUG18(printk(KERN_INFO "%s(%ld): Total SG(s) Entries %d, Data" - "entries %d, data bytes %d, Protection entries %d\n", - __func__, vha->host_no, tot_dsds, (tot_dsds-tot_prot_dsds), - data_bytes, tot_prot_dsds)); - /* Compute dif len and adjust data len to incude protection */ - total_bytes = data_bytes; dif_bytes = 0; blk_size = cmd->device->sector_size; - if (scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) { - dif_bytes = (data_bytes / blk_size) * 8; - total_bytes += dif_bytes; + dif_bytes = (data_bytes / blk_size) * 8; + + switch (scsi_get_prot_op(sp->cmd)) { + case SCSI_PROT_READ_INSERT: + case SCSI_PROT_WRITE_STRIP: + total_bytes = data_bytes; + data_bytes += dif_bytes; + break; + + case SCSI_PROT_READ_STRIP: + case SCSI_PROT_WRITE_INSERT: + case SCSI_PROT_READ_PASS: + case SCSI_PROT_WRITE_PASS: + total_bytes = data_bytes + dif_bytes; + break; + default: + BUG(); } - if (!ql2xenablehba_err_chk) + if (!qla2x00_hba_err_chk_enabled(sp)) fw_prot_opts |= 0x10; /* Disable Guard tag checking */ if (!bundling) { @@ -1150,14 +1304,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, additional_fcpcdb_len); *fcp_dl = htonl(total_bytes); - DEBUG18(printk(KERN_INFO "%s(%ld): dif bytes = 0x%x (%d), total bytes" - " = 0x%x (%d), dat block size =0x%x (%d)\n", __func__, - vha->host_no, dif_bytes, dif_bytes, total_bytes, total_bytes, - crc_ctx_pkt->blk_size, crc_ctx_pkt->blk_size)); - if (!data_bytes || cmd->sc_data_direction == DMA_NONE) { - DEBUG18(printk(KERN_INFO "%s: Zero data bytes or DMA-NONE %d\n", - __func__, data_bytes)); cmd_pkt->byte_count = __constant_cpu_to_le32(0); return QLA_SUCCESS; } @@ -1165,7 +1312,12 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, cmd_pkt->control_flags |= __constant_cpu_to_le16(CF_DATA_SEG_DESCR_ENABLE); - if (qla24xx_walk_and_build_sglist(ha, sp, cur_dsd, + + if (!bundling && tot_prot_dsds) { + if (qla24xx_walk_and_build_sglist_no_difb(ha, sp, + cur_dsd, tot_dsds)) + goto crc_queuing_error; + } else if (qla24xx_walk_and_build_sglist(ha, sp, cur_dsd, (tot_dsds - tot_prot_dsds))) goto crc_queuing_error; @@ -1182,8 +1334,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, return QLA_SUCCESS; crc_queuing_error: - DEBUG18(qla_printk(KERN_INFO, ha, - "CMD sent FAILED crc_q error:sp = %p\n", sp)); /* Cleanup will be performed by the caller */ return QLA_FUNCTION_FAILED; @@ -1225,8 +1375,8 @@ qla24xx_start_scsi(srb_t *sp) /* Send marker if required */ if (vha->marker_needed != 0) { - if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) - != QLA_SUCCESS) + if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) != + QLA_SUCCESS) return QLA_FUNCTION_FAILED; vha->marker_needed = 0; } @@ -1243,8 +1393,9 @@ qla24xx_start_scsi(srb_t *sp) if (!req->outstanding_cmds[handle]) break; } - if (index == MAX_OUTSTANDING_COMMANDS) + if (index == MAX_OUTSTANDING_COMMANDS) { goto queuing_error; + } /* Map the sg table so we have an accurate count of sg entries needed */ if (scsi_sg_count(cmd)) { @@ -1256,8 +1407,7 @@ qla24xx_start_scsi(srb_t *sp) nseg = 0; tot_dsds = nseg; - - req_cnt = qla24xx_calc_iocbs(tot_dsds); + req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); if (req->cnt < (req_cnt + 2)) { cnt = RD_REG_DWORD_RELAXED(req->req_q_out); @@ -1322,7 +1472,6 @@ qla24xx_start_scsi(srb_t *sp) /* Specify response queue number where completion should happen */ cmd_pkt->entry_status = (uint8_t) rsp->id; wmb(); - /* Adjust ring index. */ req->ring_index++; if (req->ring_index == req->length) { @@ -1431,6 +1580,22 @@ qla24xx_dif_start_scsi(srb_t *sp) goto queuing_error; else sp->flags |= SRB_DMA_VALID; + + if ((scsi_get_prot_op(cmd) == SCSI_PROT_READ_INSERT) || + (scsi_get_prot_op(cmd) == SCSI_PROT_WRITE_STRIP)) { + struct qla2_sgx sgx; + uint32_t partial; + + memset(&sgx, 0, sizeof(struct qla2_sgx)); + sgx.tot_bytes = scsi_bufflen(cmd); + sgx.cur_sg = scsi_sglist(cmd); + sgx.sp = sp; + + nseg = 0; + while (qla24xx_get_one_block_sg( + cmd->device->sector_size, &sgx, &partial)) + nseg++; + } } else nseg = 0; @@ -1445,6 +1610,11 @@ qla24xx_dif_start_scsi(srb_t *sp) goto queuing_error; else sp->flags |= SRB_CRC_PROT_DMA_VALID; + + if ((scsi_get_prot_op(cmd) == SCSI_PROT_READ_INSERT) || + (scsi_get_prot_op(cmd) == SCSI_PROT_WRITE_STRIP)) { + nseg = scsi_bufflen(cmd) / cmd->device->sector_size; + } } else { nseg = 0; } @@ -1471,6 +1641,7 @@ qla24xx_dif_start_scsi(srb_t *sp) /* Build header part of command packet (excluding the OPCODE). */ req->current_outstanding_cmd = handle; req->outstanding_cmds[handle] = sp; + sp->handle = handle; sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle; req->cnt -= req_cnt; @@ -1534,9 +1705,6 @@ queuing_error: /* Cleanup will be performed by the caller (queuecommand) */ spin_unlock_irqrestore(&ha->hardware_lock, flags); - - DEBUG18(qla_printk(KERN_INFO, ha, - "CMD sent FAILED SCSI prot_op:%02x\n", scsi_get_prot_op(cmd))); return QLA_FUNCTION_FAILED; } @@ -1581,8 +1749,11 @@ qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp) if (!req->outstanding_cmds[handle]) break; } - if (index == MAX_OUTSTANDING_COMMANDS) + if (index == MAX_OUTSTANDING_COMMANDS) { + ql_log(ql_log_warn, vha, 0x700b, + "No room on oustanding cmd array.\n"); goto queuing_error; + } /* Prep command array. */ req->current_outstanding_cmd = handle; @@ -1999,8 +2170,11 @@ qla2x00_start_sp(srb_t *sp) rval = QLA_FUNCTION_FAILED; spin_lock_irqsave(&ha->hardware_lock, flags); pkt = qla2x00_alloc_iocbs(sp->fcport->vha, sp); - if (!pkt) + if (!pkt) { + ql_log(ql_log_warn, sp->fcport->vha, 0x700c, + "qla2x00_alloc_iocbs failed.\n"); goto done; + } rval = QLA_SUCCESS; switch (ctx->type) { |