Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1786,7 +1786,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
			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) {
			int prot = 0;
			vha->flags.difdix_supported = 1;
+18 −18
Original line number Diff line number Diff line
@@ -8,24 +8,24 @@
/*
 * Table for showing the current message id in use for particular level
 * Change this table for addition of log/debug messages.
 * -----------------------------------------------------
 * |             Level            |   Last Value Used  |
 * -----------------------------------------------------
 * | Module Init and Probe        |       0x0116       |
 * | Mailbox commands             |       0x111e       |
 * | Device Discovery             |       0x2083       |
 * | Queue Command and IO tracing |       0x302e       |
 * | DPC Thread                   |       0x401c       |
 * | Async Events                 |       0x5059       |
 * | Timer Routines               |       0x600d       |
 * | User Space Interactions      |       0x709c       |
 * | Task Management              |       0x8043       |
 * | AER/EEH                      |       0x900f       |
 * | Virtual Port                 |       0xa007       |
 * | ISP82XX Specific             |       0xb027       |
 * | MultiQ                       |       0xc00b       |
 * | Misc                         |       0xd00b       |
 * -----------------------------------------------------
 * ----------------------------------------------------------------------
 * |             Level            |   Last Value Used  |     Holes	|
 * ----------------------------------------------------------------------
 * | Module Init and Probe        |       0x0116       |  		|
 * | Mailbox commands             |       0x1126       |		|
 * | Device Discovery             |       0x2083       |		|
 * | Queue Command and IO tracing |       0x302e       |     0x3008     |
 * | DPC Thread                   |       0x401c       |		|
 * | Async Events                 |       0x5059       |		|
 * | Timer Routines               |       0x600d       |		|
 * | User Space Interactions      |       0x709d       |		|
 * | Task Management              |       0x8041       |    		|
 * | AER/EEH                      |       0x900f       |		|
 * | Virtual Port                 |       0xa007       |		|
 * | ISP82XX Specific             |       0xb04f       |    		|
 * | MultiQ                       |       0xc00b       |		|
 * | Misc                         |       0xd00b       |		|
 * ----------------------------------------------------------------------
 */

#include "qla_def.h"
+2 −0
Original line number Diff line number Diff line
@@ -2529,6 +2529,7 @@ struct qla_hw_data {
#define DT_ISP8021			BIT_14
#define DT_ISP_LAST			(DT_ISP8021 << 1)

#define DT_T10_PI                       BIT_25
#define DT_IIDMA                        BIT_26
#define DT_FWI2                         BIT_27
#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_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_FWI2_CAPABLE(ha)     ((ha)->device_type & DT_FWI2)
#define IS_ZIO_SUPPORTED(ha)    ((ha)->device_type & DT_ZIO_SUPPORTED)
+10 −2
Original line number Diff line number Diff line
@@ -104,9 +104,17 @@ qla2x00_set_fcport_state(fc_port_t *fcport, int state)
}

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_WRITE_INSERT:
		if (ql2xenablehba_err_chk >= 1)
+21 −34
Original line number Diff line number Diff line
@@ -709,12 +709,11 @@ 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;
	struct scsi_cmnd *cmd = sp->cmd;
	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
	unsigned char op = scsi_get_prot_op(cmd);

	switch (scsi_get_prot_type(cmd)) {
	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)
		    (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;
@@ -735,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 (!qla2x00_hba_err_chk_enabled(op))
			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;
@@ -768,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 (!qla2x00_hba_err_chk_enabled(op))
			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;
		}

		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;
@@ -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);

	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));
@@ -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;

	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(
@@ -1289,7 +1276,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
	    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 */

	if (!bundling) {
Loading