Commit e02587d7 authored by Arun Easi's avatar Arun Easi Committed by James Bottomley

[SCSI] qla2xxx: T10 DIF - Fix incorrect error reporting.

This fix:
    - Disables app tag peeking; correct tag check will be added when the
      SCSI API is available.
    - Always derive ref_tag from scsi_get_lba()
    - Removes incorrect swap of FCP_LUN in FCP_CMND
    - Moves app-tag error check before ref-tag check. The reason being,
      currently there is no interface in SCSI to retrieve the app-tag
      for protection I/Os, so driver puts zero for app-tag in the
      firmware interface, but requests not to validate it, but when a
      ref-tag error is detected by firmware, it would put
      expected/actual tags for all the protection tags (guard/app/ref).
      As driver checks for app tag error first, a ref-tag error is
      incorrectly flagged as app-tag error.
    - Convert HBA specific checks to capability based.
Signed-off-by: default avatarArun Easi <arun.easi@qlogic.com>
Signed-off-by: default avatarChad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 8cb2049c
...@@ -1786,7 +1786,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) ...@@ -1786,7 +1786,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
} }
if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif) { if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) {
if (ha->fw_attributes & BIT_4) { if (ha->fw_attributes & BIT_4) {
int prot = 0; int prot = 0;
vha->flags.difdix_supported = 1; vha->flags.difdix_supported = 1;
......
...@@ -8,24 +8,24 @@ ...@@ -8,24 +8,24 @@
/* /*
* Table for showing the current message id in use for particular level * Table for showing the current message id in use for particular level
* Change this table for addition of log/debug messages. * Change this table for addition of log/debug messages.
* ----------------------------------------------------- * ----------------------------------------------------------------------
* | Level | Last Value Used | * | Level | Last Value Used | Holes |
* ----------------------------------------------------- * ----------------------------------------------------------------------
* | Module Init and Probe | 0x0116 | * | Module Init and Probe | 0x0116 | |
* | Mailbox commands | 0x111e | * | Mailbox commands | 0x1126 | |
* | Device Discovery | 0x2083 | * | Device Discovery | 0x2083 | |
* | Queue Command and IO tracing | 0x302e | * | Queue Command and IO tracing | 0x302e | 0x3008 |
* | DPC Thread | 0x401c | * | DPC Thread | 0x401c | |
* | Async Events | 0x5059 | * | Async Events | 0x5059 | |
* | Timer Routines | 0x600d | * | Timer Routines | 0x600d | |
* | User Space Interactions | 0x709c | * | User Space Interactions | 0x709d | |
* | Task Management | 0x8043 | * | Task Management | 0x8041 | |
* | AER/EEH | 0x900f | * | AER/EEH | 0x900f | |
* | Virtual Port | 0xa007 | * | Virtual Port | 0xa007 | |
* | ISP82XX Specific | 0xb027 | * | ISP82XX Specific | 0xb04f | |
* | MultiQ | 0xc00b | * | MultiQ | 0xc00b | |
* | Misc | 0xd00b | * | Misc | 0xd00b | |
* ----------------------------------------------------- * ----------------------------------------------------------------------
*/ */
#include "qla_def.h" #include "qla_def.h"
......
...@@ -2529,6 +2529,7 @@ struct qla_hw_data { ...@@ -2529,6 +2529,7 @@ struct qla_hw_data {
#define DT_ISP8021 BIT_14 #define DT_ISP8021 BIT_14
#define DT_ISP_LAST (DT_ISP8021 << 1) #define DT_ISP_LAST (DT_ISP8021 << 1)
#define DT_T10_PI BIT_25
#define DT_IIDMA BIT_26 #define DT_IIDMA BIT_26
#define DT_FWI2 BIT_27 #define DT_FWI2 BIT_27
#define DT_ZIO_SUPPORTED BIT_28 #define DT_ZIO_SUPPORTED BIT_28
...@@ -2572,6 +2573,7 @@ struct qla_hw_data { ...@@ -2572,6 +2573,7 @@ struct qla_hw_data {
#define IS_NOCACHE_VPD_TYPE(ha) (IS_QLA81XX(ha)) #define IS_NOCACHE_VPD_TYPE(ha) (IS_QLA81XX(ha))
#define IS_ALOGIO_CAPABLE(ha) (IS_QLA23XX(ha) || IS_FWI2_CAPABLE(ha)) #define IS_ALOGIO_CAPABLE(ha) (IS_QLA23XX(ha) || IS_FWI2_CAPABLE(ha))
#define IS_T10_PI_CAPABLE(ha) ((ha)->device_type & DT_T10_PI)
#define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA) #define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA)
#define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2) #define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2)
#define IS_ZIO_SUPPORTED(ha) ((ha)->device_type & DT_ZIO_SUPPORTED) #define IS_ZIO_SUPPORTED(ha) ((ha)->device_type & DT_ZIO_SUPPORTED)
......
...@@ -104,9 +104,17 @@ qla2x00_set_fcport_state(fc_port_t *fcport, int state) ...@@ -104,9 +104,17 @@ qla2x00_set_fcport_state(fc_port_t *fcport, int state)
} }
static inline int static inline int
qla2x00_hba_err_chk_enabled(unsigned char op) qla2x00_hba_err_chk_enabled(srb_t *sp)
{ {
switch (op) { /*
* Uncomment when corresponding SCSI changes are done.
*
if (!sp->cmd->prot_chk)
return 0;
*
*/
switch (scsi_get_prot_op(sp->cmd)) {
case SCSI_PROT_READ_STRIP: case SCSI_PROT_READ_STRIP:
case SCSI_PROT_WRITE_INSERT: case SCSI_PROT_WRITE_INSERT:
if (ql2xenablehba_err_chk >= 1) if (ql2xenablehba_err_chk >= 1)
......
...@@ -709,12 +709,11 @@ struct fw_dif_context { ...@@ -709,12 +709,11 @@ struct fw_dif_context {
* *
*/ */
static inline void 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) unsigned int protcnt)
{ {
struct sd_dif_tuple *spt; struct scsi_cmnd *cmd = sp->cmd;
scsi_qla_host_t *vha = shost_priv(cmd->device->host); scsi_qla_host_t *vha = shost_priv(cmd->device->host);
unsigned char op = scsi_get_prot_op(cmd);
switch (scsi_get_prot_type(cmd)) { switch (scsi_get_prot_type(cmd)) {
case SCSI_PROT_DIF_TYPE0: case SCSI_PROT_DIF_TYPE0:
...@@ -724,6 +723,10 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt, ...@@ -724,6 +723,10 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt,
*/ */
pkt->ref_tag = cpu_to_le32((uint32_t) pkt->ref_tag = cpu_to_le32((uint32_t)
(0xffffffff & scsi_get_lba(cmd))); (0xffffffff & scsi_get_lba(cmd)));
if (!qla2x00_hba_err_chk_enabled(sp))
break;
pkt->ref_tag_mask[0] = 0xff; pkt->ref_tag_mask[0] = 0xff;
pkt->ref_tag_mask[1] = 0xff; pkt->ref_tag_mask[1] = 0xff;
pkt->ref_tag_mask[2] = 0xff; pkt->ref_tag_mask[2] = 0xff;
...@@ -735,20 +738,16 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt, ...@@ -735,20 +738,16 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt,
* match LBA in CDB + N * match LBA in CDB + N
*/ */
case SCSI_PROT_DIF_TYPE2: case SCSI_PROT_DIF_TYPE2:
if (!qla2x00_hba_err_chk_enabled(op)) pkt->app_tag = __constant_cpu_to_le16(0);
break; pkt->app_tag_mask[0] = 0x0;
pkt->app_tag_mask[1] = 0x0;
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->ref_tag = cpu_to_le32((uint32_t) pkt->ref_tag = cpu_to_le32((uint32_t)
(0xffffffff & scsi_get_lba(cmd))); (0xffffffff & scsi_get_lba(cmd)));
if (!qla2x00_hba_err_chk_enabled(sp))
break;
/* enable ALL bytes of the ref tag */ /* enable ALL bytes of the ref tag */
pkt->ref_tag_mask[0] = 0xff; pkt->ref_tag_mask[0] = 0xff;
pkt->ref_tag_mask[1] = 0xff; pkt->ref_tag_mask[1] = 0xff;
...@@ -768,26 +767,15 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt, ...@@ -768,26 +767,15 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt,
* 16 bit app tag. * 16 bit app tag.
*/ */
case SCSI_PROT_DIF_TYPE1: case SCSI_PROT_DIF_TYPE1:
if (!qla2x00_hba_err_chk_enabled(op)) 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; 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;
ql_dbg(ql_dbg_io, vha, 0x3008,
"LBA from user %p, lba = 0x%x for cmd=%p.\n",
spt, (int)spt->ref_tag, cmd);
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 */ /* enable ALL bytes of the ref tag */
pkt->ref_tag_mask[0] = 0xff; pkt->ref_tag_mask[0] = 0xff;
pkt->ref_tag_mask[1] = 0xff; pkt->ref_tag_mask[1] = 0xff;
...@@ -1208,7 +1196,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, ...@@ -1208,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); 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); &crc_ctx_pkt->ref_tag, tot_prot_dsds);
cmd_pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma)); cmd_pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma));
...@@ -1237,7 +1225,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, ...@@ -1237,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; fcp_cmnd->additional_cdb_len |= 2;
int_to_scsilun(sp->cmd->device->lun, &fcp_cmnd->lun); 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); 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_len = cpu_to_le16(fcp_cmnd_len);
cmd_pkt->fcp_cmnd_dseg_address[0] = cpu_to_le32( cmd_pkt->fcp_cmnd_dseg_address[0] = cpu_to_le32(
...@@ -1289,7 +1276,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, ...@@ -1289,7 +1276,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
BUG(); BUG();
} }
if (!qla2x00_hba_err_chk_enabled(scsi_get_prot_op(cmd))) if (!qla2x00_hba_err_chk_enabled(sp))
fw_prot_opts |= 0x10; /* Disable Guard tag checking */ fw_prot_opts |= 0x10; /* Disable Guard tag checking */
if (!bundling) { if (!bundling) {
......
...@@ -1534,25 +1534,26 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24) ...@@ -1534,25 +1534,26 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
return 1; return 1;
} }
/* check appl tag */ /* check ref tag */
if (e_app_tag != a_app_tag) { if (e_ref_tag != a_ref_tag) {
scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
0x10, 0x2); 0x10, 0x3);
set_driver_byte(cmd, DRIVER_SENSE); set_driver_byte(cmd, DRIVER_SENSE);
set_host_byte(cmd, DID_ABORT); set_host_byte(cmd, DID_ABORT);
cmd->result |= SAM_STAT_CHECK_CONDITION << 1; cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
return 1; return 1;
} }
/* check ref tag */ /* check appl tag */
if (e_ref_tag != a_ref_tag) { if (e_app_tag != a_app_tag) {
scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
0x10, 0x3); 0x10, 0x2);
set_driver_byte(cmd, DRIVER_SENSE); set_driver_byte(cmd, DRIVER_SENSE);
set_host_byte(cmd, DID_ABORT); set_host_byte(cmd, DID_ABORT);
cmd->result |= SAM_STAT_CHECK_CONDITION << 1; cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
return 1; return 1;
} }
return 1; return 1;
} }
......
...@@ -472,7 +472,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) ...@@ -472,7 +472,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
host->can_queue = base_vha->req->length + 128; host->can_queue = base_vha->req->length + 128;
host->this_id = 255; host->this_id = 255;
host->cmd_per_lun = 3; host->cmd_per_lun = 3;
if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif) if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif)
host->max_cmd_len = 32; host->max_cmd_len = 32;
else else
host->max_cmd_len = MAX_CMDSZ; host->max_cmd_len = MAX_CMDSZ;
......
...@@ -2255,7 +2255,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2255,7 +2255,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
host->this_id = 255; host->this_id = 255;
host->cmd_per_lun = 3; host->cmd_per_lun = 3;
host->unique_id = host->host_no; host->unique_id = host->host_no;
if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif) if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif)
host->max_cmd_len = 32; host->max_cmd_len = 32;
else else
host->max_cmd_len = MAX_CMDSZ; host->max_cmd_len = MAX_CMDSZ;
...@@ -2382,7 +2382,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2382,7 +2382,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
"Detected hba at address=%p.\n", "Detected hba at address=%p.\n",
ha); ha);
if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif) { if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) {
if (ha->fw_attributes & BIT_4) { if (ha->fw_attributes & BIT_4) {
int prot = 0; int prot = 0;
base_vha->flags.difdix_supported = 1; base_vha->flags.difdix_supported = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment