mirror of
https://github.com/torvalds/linux
synced 2024-09-25 14:01:32 +00:00
[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: Arun Easi <arun.easi@qlogic.com> Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
8cb2049c74
commit
e02587d777
|
@ -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 @@
|
||||||
/*
|
/*
|
||||||
* 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 {
|
||||||
#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 {
|
||||||
#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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
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,
|
||||||
*/
|
*/
|
||||||
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,
|
||||||
* 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,
|
||||||
* 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,
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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,6 +1534,16 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check ref tag */
|
||||||
|
if (e_ref_tag != a_ref_tag) {
|
||||||
|
scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
|
||||||
|
0x10, 0x3);
|
||||||
|
set_driver_byte(cmd, DRIVER_SENSE);
|
||||||
|
set_host_byte(cmd, DID_ABORT);
|
||||||
|
cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* check appl tag */
|
/* check appl tag */
|
||||||
if (e_app_tag != a_app_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,
|
||||||
|
@ -1544,15 +1554,6 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check ref tag */
|
|
||||||
if (e_ref_tag != a_ref_tag) {
|
|
||||||
scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
|
|
||||||
0x10, 0x3);
|
|
||||||
set_driver_byte(cmd, DRIVER_SENSE);
|
|
||||||
set_host_byte(cmd, DID_ABORT);
|
|
||||||
cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
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)
|
||||||
"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;
|
||||||
|
|
Loading…
Reference in a new issue