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

[SCSI] qla2xxx: T10 DIF support added.

parent 3822263e
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -1726,6 +1726,22 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
			fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
	}

	if (IS_QLA25XX(ha) && ql2xenabledif) {
		if (ha->fw_attributes & BIT_4) {
			vha->flags.difdix_supported = 1;
			DEBUG18(qla_printk(KERN_INFO, ha,
			    "Registering for DIF/DIX type 1 and 3"
			    " protection.\n"));
			scsi_host_set_prot(vha->host,
			    SHOST_DIF_TYPE1_PROTECTION
			    | SHOST_DIF_TYPE3_PROTECTION
			    | SHOST_DIX_TYPE1_PROTECTION
			    | SHOST_DIX_TYPE3_PROTECTION);
			scsi_host_set_guard(vha->host, SHOST_DIX_GUARD_CRC);
		} else
			vha->flags.difdix_supported = 0;
	}

	if (scsi_add_host_with_dma(vha->host, &fc_vport->dev,
				   &ha->pdev->dev)) {
		DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n",
+58 −0
Original line number Diff line number Diff line
@@ -1663,4 +1663,62 @@ qla2x00_dump_buffer(uint8_t * b, uint32_t size)
		printk("\n");
}

void
qla2x00_dump_buffer_zipped(uint8_t *b, uint32_t size)
{
	uint32_t cnt;
	uint8_t c;
	uint8_t  last16[16], cur16[16];
	uint32_t lc = 0, num_same16 = 0, j;

	printk(KERN_DEBUG " 0   1   2   3   4   5   6   7   8   9  "
	    "Ah  Bh  Ch  Dh  Eh  Fh\n");
	printk(KERN_DEBUG "----------------------------------------"
	    "----------------------\n");

	for (cnt = 0; cnt < size;) {
		c = *b++;

		cur16[lc++] = c;

		cnt++;
		if (cnt % 16)
			continue;

		/* We have 16 now */
		lc = 0;
		if (num_same16 == 0) {
			memcpy(last16, cur16, 16);
			num_same16++;
			continue;
		}
		if (memcmp(cur16, last16, 16) == 0) {
			num_same16++;
			continue;
		}
		for (j = 0; j < 16; j++)
			printk(KERN_DEBUG "%02x  ", (uint32_t)last16[j]);
		printk(KERN_DEBUG "\n");

		if (num_same16 > 1)
			printk(KERN_DEBUG "> prev pattern repeats (%u)"
			    "more times\n", num_same16-1);
		memcpy(last16, cur16, 16);
		num_same16 = 1;
	}

	if (num_same16) {
		for (j = 0; j < 16; j++)
			printk(KERN_DEBUG "%02x  ", (uint32_t)last16[j]);
		printk(KERN_DEBUG "\n");

		if (num_same16 > 1)
			printk(KERN_DEBUG "> prev pattern repeats (%u)"
			    "more times\n", num_same16-1);
	}
	if (lc) {
		for (j = 0; j < lc; j++)
			printk(KERN_DEBUG "%02x  ", (uint32_t)cur16[j]);
		printk(KERN_DEBUG "\n");
	}
}
+10 −0
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@
/* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */
/* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */
/* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */
/* #define QL_DEBUG_LEVEL_18 */ /* Output T10 CRC trace messages */

/* #define QL_PRINTK_BUF */ /* Captures printk to buffer */

/*
* Macros use for debugging the driver.
@@ -139,6 +142,13 @@
#define DEBUG17(x)	do {} while (0)
#endif

#if defined(QL_DEBUG_LEVEL_18)
#define DEBUG18(x)	do {if (ql2xextended_error_logging) x; } while (0)
#else
#define DEBUG18(x)	do {} while (0)
#endif


/*
 * Firmware Dump structure definition
 */
+82 −2
Original line number Diff line number Diff line
@@ -188,6 +188,16 @@

struct req_que;

/*
 * (sd.h is not exported, hence local inclusion)
 * Data Integrity Field tuple.
 */
struct sd_dif_tuple {
	__be16 guard_tag;	/* Checksum */
	__be16 app_tag;		/* Opaque storage */
	__be32 ref_tag;		/* Target LBA or indirect LBA */
};

/*
 * SCSI Request Block
 */
@@ -209,7 +219,13 @@ typedef struct srb {
 * SRB flag definitions
 */
#define SRB_DMA_VALID			BIT_0	/* Command sent to ISP */
#define SRB_FCP_CMND_DMA_VALID	BIT_12  /* FCP command in IOCB */
#define SRB_FCP_CMND_DMA_VALID		BIT_12	/* DIF: DSD List valid */
#define SRB_CRC_CTX_DMA_VALID		BIT_2	/* DIF: context DMA valid */
#define SRB_CRC_PROT_DMA_VALID		BIT_4	/* DIF: prot DMA valid */
#define SRB_CRC_CTX_DSD_VALID		BIT_5	/* DIF: dsd_list valid */

/* To identify if a srb is of T10-CRC type. @sp => srb_t pointer */
#define IS_PROT_IO(sp)	(sp->flags & SRB_CRC_CTX_DSD_VALID)

/*
 * SRB extensions.
@@ -1330,6 +1346,66 @@ typedef struct {
	uint32_t dseg_4_length;		/* Data segment 4 length. */
} 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_ENABLE_DIF_BUNDLING	BIT_8
#define PO_ENABLE_INCR_GUARD_SEED	BIT_3
#define PO_DISABLE_INCR_REF_TAG	BIT_5
#define PO_DISABLE_GUARD_CHECK	BIT_4
/*
 * ISP queue - 64-Bit addressing, continuation crc entry structure definition.
 */
struct crc_context {
	uint32_t handle;		/* System handle. */
	uint32_t ref_tag;
	uint16_t app_tag;
	uint8_t ref_tag_mask[4];	/* Validation/Replacement Mask*/
	uint8_t app_tag_mask[2];	/* Validation/Replacement Mask*/
	uint16_t guard_seed;		/* Initial Guard Seed */
	uint16_t prot_opts;		/* Requested Data Protection Mode */
	uint16_t blk_size;		/* Data size in bytes */
	uint16_t runt_blk_guard;	/* Guard value for runt block (tape
					 * only) */
	uint32_t byte_count;		/* Total byte count/ total data
					 * transfer count */
	union {
		struct {
			uint32_t	reserved_1;
			uint16_t	reserved_2;
			uint16_t	reserved_3;
			uint32_t	reserved_4;
			uint32_t	data_address[2];
			uint32_t	data_length;
			uint32_t	reserved_5[2];
			uint32_t	reserved_6;
		} nobundling;
		struct {
			uint32_t	dif_byte_count;	/* Total DIF byte
							 * count */
			uint16_t	reserved_1;
			uint16_t	dseg_count;	/* Data segment count */
			uint32_t	reserved_2;
			uint32_t	data_address[2];
			uint32_t	data_length;
			uint32_t	dif_address[2];
			uint32_t	dif_length;	/* Data segment 0
							 * length */
		} bundling;
	} u;

	struct fcp_cmnd	fcp_cmnd;
	dma_addr_t	crc_ctx_dma;
	/* List of DMA context transfers */
	struct list_head dsd_list;

	/* This structure should not exceed 512 bytes */
};

#define CRC_CONTEXT_LEN_FW	(offsetof(struct crc_context, fcp_cmnd.lun))
#define CRC_CONTEXT_FCPCMND_OFF	(offsetof(struct crc_context, fcp_cmnd.lun))

/*
 * ISP queue - status entry structure definition.
 */
@@ -1390,6 +1466,7 @@ typedef struct {
#define CS_ABORTED		0x5	/* System aborted command. */
#define CS_TIMEOUT		0x6	/* Timeout error. */
#define CS_DATA_OVERRUN		0x7	/* Data overrun. */
#define CS_DIF_ERROR		0xC	/* DIF error detected  */

#define CS_DATA_UNDERRUN	0x15	/* Data Underrun. */
#define CS_QUEUE_FULL		0x1C	/* Queue Full. */
@@ -2732,6 +2809,7 @@ typedef struct scsi_qla_host {

		uint32_t	management_server_logged_in :1;
		uint32_t	process_response_queue	:1;
		uint32_t	difdix_supported:1;
	} flags;

	atomic_t	loop_state;
@@ -2883,6 +2961,8 @@ typedef struct scsi_qla_host {
#define OPTROM_BURST_SIZE	0x1000
#define OPTROM_BURST_DWORDS	(OPTROM_BURST_SIZE / 4)

#define	QLA_DSDS_PER_IOCB	37

#include "qla_gbl.h"
#include "qla_dbg.h"
#include "qla_inline.h"
+46 −1
Original line number Diff line number Diff line
@@ -400,6 +400,7 @@ struct cmd_type_6 {
	struct scsi_lun lun;		/* FCP LUN (BE). */

	uint16_t control_flags;		/* Control flags. */
#define CF_DIF_SEG_DESCR_ENABLE		BIT_3
#define CF_DATA_SEG_DESCR_ENABLE	BIT_2
#define CF_READ_DATA			BIT_1
#define CF_WRITE_DATA			BIT_0
@@ -466,6 +467,43 @@ struct cmd_type_7 {
	uint32_t dseg_0_len;		/* Data segment 0 length. */
};

#define COMMAND_TYPE_CRC_2	0x6A	/* Command Type CRC_2 (Type 6)
					 * (T10-DIF) */
struct cmd_type_crc_2 {
	uint8_t entry_type;		/* Entry type. */
	uint8_t entry_count;		/* Entry count. */
	uint8_t sys_define;		/* System defined. */
	uint8_t entry_status;		/* Entry Status. */

	uint32_t handle;		/* System handle. */

	uint16_t nport_handle;		/* N_PORT handle. */
	uint16_t timeout;		/* Command timeout. */

	uint16_t dseg_count;		/* Data segment count. */

	uint16_t fcp_rsp_dseg_len;	/* FCP_RSP DSD length. */

	struct scsi_lun lun;		/* FCP LUN (BE). */

	uint16_t control_flags;		/* Control flags. */

	uint16_t fcp_cmnd_dseg_len;		/* Data segment length. */
	uint32_t fcp_cmnd_dseg_address[2];	/* Data segment address. */

	uint32_t fcp_rsp_dseg_address[2];	/* Data segment address. */

	uint32_t byte_count;		/* Total byte count. */

	uint8_t port_id[3];		/* PortID of destination port. */
	uint8_t vp_index;

	uint32_t crc_context_address[2];	/* Data segment address. */
	uint16_t crc_context_len;		/* Data segment length. */
	uint16_t reserved_1;			/* MUST be set to 0. */
};


/*
 * ISP queue - status entry structure definition.
 */
@@ -496,10 +534,17 @@ struct sts_entry_24xx {

	uint32_t sense_len;		/* FCP SENSE length. */
	uint32_t rsp_data_len;		/* FCP response data length. */

	uint8_t data[28];		/* FCP response/sense information. */
	/*
	 * If DIF Error is set in comp_status, these additional fields are
	 * defined:
	 * &data[10] : uint8_t report_runt_bg[2];	- computed guard
	 * &data[12] : uint8_t actual_dif[8];		- DIF Data recieved
	 * &data[20] : uint8_t expected_dif[8];		- DIF Data computed
	*/
};


/*
 * Status entry completion status
 */
Loading