diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index e2ca6be86244..1c28215f8bed 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1812,7 +1812,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) { if (ha->fw_attributes & BIT_4) { - int prot = 0; + int prot = 0, guard; vha->flags.difdix_supported = 1; ql_dbg(ql_dbg_user, vha, 0x7082, "Registered for DIF/DIX type 1 and 3 protection.\n"); @@ -1825,7 +1825,14 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) | SHOST_DIX_TYPE1_PROTECTION | SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION); - scsi_host_set_guard(vha->host, SHOST_DIX_GUARD_CRC); + + guard = SHOST_DIX_GUARD_CRC; + + if (IS_PI_IPGUARD_CAPABLE(ha) && + (ql2xenabledif > 1 || IS_PI_DIFB_DIX0_CAPABLE(ha))) + guard |= SHOST_DIX_GUARD_IP; + + scsi_host_set_guard(vha->host, guard); } else vha->flags.difdix_supported = 0; } diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 3e081bd8d34e..44efe3cc79e6 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -17,7 +17,8 @@ * | | | 0x113a | * | Device Discovery | 0x2087 | 0x2020-0x2022, | * | | | 0x2016 | - * | Queue Command and IO tracing | 0x3030 | 0x3006,0x3008 | + * | Queue Command and IO tracing | 0x3030 | 0x3006-0x300b | + * | | | 0x3027-0x3028 | * | | | 0x302d-0x302e | * | DPC Thread | 0x401d | 0x4002,0x4013 | * | Async Events | 0x5071 | 0x502b-0x502f | diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index b214fd816135..a9725bf5527b 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1468,9 +1468,10 @@ typedef struct { } cont_a64_entry_t; #define PO_MODE_DIF_INSERT 0 -#define PO_MODE_DIF_REMOVE BIT_0 -#define PO_MODE_DIF_PASS BIT_1 -#define PO_MODE_DIF_REPLACE (BIT_0 + BIT_1) +#define PO_MODE_DIF_REMOVE 1 +#define PO_MODE_DIF_PASS 2 +#define PO_MODE_DIF_REPLACE 3 +#define PO_MODE_DIF_TCP_CKSUM 6 #define PO_ENABLE_DIF_BUNDLING BIT_8 #define PO_ENABLE_INCR_GUARD_SEED BIT_3 #define PO_DISABLE_INCR_REF_TAG BIT_5 @@ -2781,6 +2782,12 @@ struct qla_hw_data { /* Bit 21 of fw_attributes decides the MCTP capabilities */ #define IS_MCTP_CAPABLE(ha) (IS_QLA2031(ha) && \ ((ha)->fw_attributes_ext[0] & BIT_0)) +#define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha)) +#define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha)) +#define IS_PI_DIFB_DIX0_CAPABLE(ha) (0) +#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha)) +#define IS_PI_SPLIT_DET_CAPABLE(ha) (IS_PI_SPLIT_DET_CAPABLE_HBA(ha) && \ + (((ha)->fw_attributes_h << 16 | (ha)->fw_attributes) & BIT_22)) /* HBA serial number */ uint8_t serial0; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 62081cf4d824..799a58bb9859 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5498,6 +5498,9 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) rval = 1; } + if (IS_T10_PI_CAPABLE(ha)) + nv->frame_payload_size &= ~7; + /* Reset Initialization control block */ memset(icb, 0, ha->init_cb_size); diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index f58b2b23fb89..03b752632839 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -147,13 +147,6 @@ qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts) struct scsi_cmnd *cmd = GET_CMD_SP(sp); uint8_t guard = scsi_host_get_guard(cmd->device->host); - /* We only support T10 DIF right now */ - if (guard != SHOST_DIX_GUARD_CRC) { - ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3007, - "Unsupported guard: %d for cmd=%p.\n", guard, cmd); - return 0; - } - /* We always use DIFF Bundling for best performance */ *fw_prot_opts = 0; @@ -172,10 +165,11 @@ qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts) *fw_prot_opts |= PO_MODE_DIF_REMOVE; break; case SCSI_PROT_READ_PASS: - *fw_prot_opts |= PO_MODE_DIF_PASS; - break; case SCSI_PROT_WRITE_PASS: - *fw_prot_opts |= PO_MODE_DIF_PASS; + if (guard & SHOST_DIX_GUARD_IP) + *fw_prot_opts |= PO_MODE_DIF_TCP_CKSUM; + else + *fw_prot_opts |= PO_MODE_DIF_PASS; break; default: /* Normal Request */ *fw_prot_opts |= PO_MODE_DIF_PASS; @@ -821,7 +815,6 @@ qla24xx_set_t10dif_tags(srb_t *sp, struct fw_dif_context *pkt, unsigned int protcnt) { struct scsi_cmnd *cmd = GET_CMD_SP(sp); - scsi_qla_host_t *vha = shost_priv(cmd->device->host); switch (scsi_get_prot_type(cmd)) { case SCSI_PROT_DIF_TYPE0: @@ -891,12 +884,6 @@ qla24xx_set_t10dif_tags(srb_t *sp, struct fw_dif_context *pkt, pkt->ref_tag_mask[3] = 0xff; break; } - - 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 { @@ -1068,9 +1055,6 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, int i; uint16_t used_dsds = tot_dsds; struct scsi_cmnd *cmd = GET_CMD_SP(sp); - scsi_qla_host_t *vha = shost_priv(cmd->device->host); - - uint8_t *cp; scsi_for_each_sg(cmd, sg, tot_dsds, i) { dma_addr_t sle_dma; @@ -1113,19 +1097,12 @@ 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); - ql_dbg(ql_dbg_io, vha, 0x300a, - "sg entry %d - addr=0x%x 0x%x, " "len=%d for cmd=%p.\n", - i, LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg), 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)); avail_dsds--; - if (scsi_get_prot_op(cmd) == SCSI_PROT_WRITE_PASS) { - cp = page_address(sg_page(sg)) + sg->offset; - ql_dbg(ql_dbg_io, vha, 0x300b, - "User data buffer=%p for cmd=%p.\n", cp, cmd); - } } /* Null termination */ *cur_dsd++ = 0; @@ -1148,8 +1125,6 @@ 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; cmd = GET_CMD_SP(sp); scsi_for_each_prot_sg(cmd, sg, tot_dsds, i) { @@ -1193,23 +1168,11 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, cur_dsd = (uint32_t *)next_dsd; } sle_dma = sg_dma_address(sg); - if (scsi_get_prot_op(cmd) == SCSI_PROT_WRITE_PASS) { - 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)); *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); - if (scsi_get_prot_op(cmd) == SCSI_PROT_WRITE_PASS) { - cp = page_address(sg_page(sg)) + sg->offset; - ql_dbg(ql_dbg_io, vha, 0x3028, - "%s(): Protection Data buffer = %p.\n", __func__, - cp); - } avail_dsds--; } /* Null termination */ @@ -1386,6 +1349,16 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, if (!qla2x00_hba_err_chk_enabled(sp)) fw_prot_opts |= 0x10; /* Disable Guard tag checking */ + /* HBA error checking enabled */ + else if (IS_PI_UNINIT_CAPABLE(ha)) { + if ((scsi_get_prot_type(GET_CMD_SP(sp)) == SCSI_PROT_DIF_TYPE1) + || (scsi_get_prot_type(GET_CMD_SP(sp)) == + SCSI_PROT_DIF_TYPE2)) + fw_prot_opts |= BIT_10; + else if (scsi_get_prot_type(GET_CMD_SP(sp)) == + SCSI_PROT_DIF_TYPE3) + fw_prot_opts |= BIT_11; + } if (!bundling) { cur_dsd = (uint32_t *) &crc_ctx_pkt->u.nobundling.data_address; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index f01be76ebecf..7614e14def92 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -2163,6 +2163,19 @@ check_scsi_status: case CS_DIF_ERROR: logit = qla2x00_handle_dif_error(sp, sts24); break; + + case CS_TRANSPORT: + res = DID_ERROR << 16; + + if (!IS_PI_SPLIT_DET_CAPABLE(ha)) + break; + + if (state_flags & BIT_4) + scmd_printk(KERN_WARNING, cp, + "Unsupported device '%s' found.\n", + cp->device->vendor); + break; + default: res = DID_ERROR << 16; break; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 1020db5c33f9..ec7cefcb6722 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -116,9 +116,8 @@ MODULE_PARM_DESC(ql2xmaxqdepth, "Maximum queue depth to set for each LUN. " "Default is 32."); -/* Do not change the value of this after module load */ -int ql2xenabledif = 0; -module_param(ql2xenabledif, int, S_IRUGO|S_IWUSR); +int ql2xenabledif = 2; +module_param(ql2xenabledif, int, S_IRUGO); MODULE_PARM_DESC(ql2xenabledif, " Enable T10-CRC-DIF " " Default is 0 - No DIF Support. 1 - Enable it" @@ -1358,6 +1357,9 @@ qla2xxx_slave_configure(struct scsi_device *sdev) scsi_qla_host_t *vha = shost_priv(sdev->host); struct req_que *req = vha->req; + if (IS_T10_PI_CAPABLE(vha->hw)) + blk_queue_update_dma_alignment(sdev->request_queue, 0x7); + if (sdev->tagged_supported) scsi_activate_tcq(sdev, req->max_q_depth); else @@ -2574,7 +2576,7 @@ skip_dpc: if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) { if (ha->fw_attributes & BIT_4) { - int prot = 0; + int prot = 0, guard; base_vha->flags.difdix_supported = 1; ql_dbg(ql_dbg_init, base_vha, 0x00f1, "Registering for DIF/DIX type 1 and 3 protection.\n"); @@ -2587,7 +2589,14 @@ skip_dpc: | SHOST_DIX_TYPE1_PROTECTION | SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION); - scsi_host_set_guard(host, SHOST_DIX_GUARD_CRC); + + guard = SHOST_DIX_GUARD_CRC; + + if (IS_PI_IPGUARD_CAPABLE(ha) && + (ql2xenabledif > 1 || IS_PI_DIFB_DIX0_CAPABLE(ha))) + guard |= SHOST_DIX_GUARD_IP; + + scsi_host_set_guard(host, guard); } else base_vha->flags.difdix_supported = 0; }