aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorArun Easi <arun.easi@qlogic.com>2010-05-04 18:01:30 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-05-16 18:21:59 -0400
commitbad750028917a7b804623701d0674e46c6012c18 (patch)
treef8c4032b480e3c93b906e313eb6d371565b4b66d /drivers/scsi
parent3822263eb1e74821ad1ae886ddd2184ae9395ff7 (diff)
[SCSI] qla2xxx: T10 DIF support added.
Signed-off-by: Duane Grigsby <duane.grigsby@qlogic.com> Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c16
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c58
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.h10
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h84
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h47
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_inline.h16
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c678
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c77
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c75
10 files changed, 1053 insertions, 12 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 5c98b097cfda..62a22cfae20e 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1726,6 +1726,22 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
1726 fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); 1726 fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
1727 } 1727 }
1728 1728
1729 if (IS_QLA25XX(ha) && ql2xenabledif) {
1730 if (ha->fw_attributes & BIT_4) {
1731 vha->flags.difdix_supported = 1;
1732 DEBUG18(qla_printk(KERN_INFO, ha,
1733 "Registering for DIF/DIX type 1 and 3"
1734 " protection.\n"));
1735 scsi_host_set_prot(vha->host,
1736 SHOST_DIF_TYPE1_PROTECTION
1737 | SHOST_DIF_TYPE3_PROTECTION
1738 | SHOST_DIX_TYPE1_PROTECTION
1739 | SHOST_DIX_TYPE3_PROTECTION);
1740 scsi_host_set_guard(vha->host, SHOST_DIX_GUARD_CRC);
1741 } else
1742 vha->flags.difdix_supported = 0;
1743 }
1744
1729 if (scsi_add_host_with_dma(vha->host, &fc_vport->dev, 1745 if (scsi_add_host_with_dma(vha->host, &fc_vport->dev,
1730 &ha->pdev->dev)) { 1746 &ha->pdev->dev)) {
1731 DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n", 1747 DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n",
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 89bfc119010b..2afc8a362f2c 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1663,4 +1663,62 @@ qla2x00_dump_buffer(uint8_t * b, uint32_t size)
1663 printk("\n"); 1663 printk("\n");
1664} 1664}
1665 1665
1666void
1667qla2x00_dump_buffer_zipped(uint8_t *b, uint32_t size)
1668{
1669 uint32_t cnt;
1670 uint8_t c;
1671 uint8_t last16[16], cur16[16];
1672 uint32_t lc = 0, num_same16 = 0, j;
1673
1674 printk(KERN_DEBUG " 0 1 2 3 4 5 6 7 8 9 "
1675 "Ah Bh Ch Dh Eh Fh\n");
1676 printk(KERN_DEBUG "----------------------------------------"
1677 "----------------------\n");
1678
1679 for (cnt = 0; cnt < size;) {
1680 c = *b++;
1666 1681
1682 cur16[lc++] = c;
1683
1684 cnt++;
1685 if (cnt % 16)
1686 continue;
1687
1688 /* We have 16 now */
1689 lc = 0;
1690 if (num_same16 == 0) {
1691 memcpy(last16, cur16, 16);
1692 num_same16++;
1693 continue;
1694 }
1695 if (memcmp(cur16, last16, 16) == 0) {
1696 num_same16++;
1697 continue;
1698 }
1699 for (j = 0; j < 16; j++)
1700 printk(KERN_DEBUG "%02x ", (uint32_t)last16[j]);
1701 printk(KERN_DEBUG "\n");
1702
1703 if (num_same16 > 1)
1704 printk(KERN_DEBUG "> prev pattern repeats (%u)"
1705 "more times\n", num_same16-1);
1706 memcpy(last16, cur16, 16);
1707 num_same16 = 1;
1708 }
1709
1710 if (num_same16) {
1711 for (j = 0; j < 16; j++)
1712 printk(KERN_DEBUG "%02x ", (uint32_t)last16[j]);
1713 printk(KERN_DEBUG "\n");
1714
1715 if (num_same16 > 1)
1716 printk(KERN_DEBUG "> prev pattern repeats (%u)"
1717 "more times\n", num_same16-1);
1718 }
1719 if (lc) {
1720 for (j = 0; j < lc; j++)
1721 printk(KERN_DEBUG "%02x ", (uint32_t)cur16[j]);
1722 printk(KERN_DEBUG "\n");
1723 }
1724}
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index d6d9c86cb058..916c81f3f55d 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -27,6 +27,9 @@
27/* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */ 27/* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */
28/* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */ 28/* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */
29/* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */ 29/* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */
30/* #define QL_DEBUG_LEVEL_18 */ /* Output T10 CRC trace messages */
31
32/* #define QL_PRINTK_BUF */ /* Captures printk to buffer */
30 33
31/* 34/*
32* Macros use for debugging the driver. 35* Macros use for debugging the driver.
@@ -139,6 +142,13 @@
139#define DEBUG17(x) do {} while (0) 142#define DEBUG17(x) do {} while (0)
140#endif 143#endif
141 144
145#if defined(QL_DEBUG_LEVEL_18)
146#define DEBUG18(x) do {if (ql2xextended_error_logging) x; } while (0)
147#else
148#define DEBUG18(x) do {} while (0)
149#endif
150
151
142/* 152/*
143 * Firmware Dump structure definition 153 * Firmware Dump structure definition
144 */ 154 */
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 0d2cecbb8f47..4559f5c6c1ae 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -189,6 +189,16 @@
189struct req_que; 189struct req_que;
190 190
191/* 191/*
192 * (sd.h is not exported, hence local inclusion)
193 * Data Integrity Field tuple.
194 */
195struct sd_dif_tuple {
196 __be16 guard_tag; /* Checksum */
197 __be16 app_tag; /* Opaque storage */
198 __be32 ref_tag; /* Target LBA or indirect LBA */
199};
200
201/*
192 * SCSI Request Block 202 * SCSI Request Block
193 */ 203 */
194typedef struct srb { 204typedef struct srb {
@@ -208,8 +218,14 @@ typedef struct srb {
208/* 218/*
209 * SRB flag definitions 219 * SRB flag definitions
210 */ 220 */
211#define SRB_DMA_VALID BIT_0 /* Command sent to ISP */ 221#define SRB_DMA_VALID BIT_0 /* Command sent to ISP */
212#define SRB_FCP_CMND_DMA_VALID BIT_12 /* FCP command in IOCB */ 222#define SRB_FCP_CMND_DMA_VALID BIT_12 /* DIF: DSD List valid */
223#define SRB_CRC_CTX_DMA_VALID BIT_2 /* DIF: context DMA valid */
224#define SRB_CRC_PROT_DMA_VALID BIT_4 /* DIF: prot DMA valid */
225#define SRB_CRC_CTX_DSD_VALID BIT_5 /* DIF: dsd_list valid */
226
227/* To identify if a srb is of T10-CRC type. @sp => srb_t pointer */
228#define IS_PROT_IO(sp) (sp->flags & SRB_CRC_CTX_DSD_VALID)
213 229
214/* 230/*
215 * SRB extensions. 231 * SRB extensions.
@@ -1330,6 +1346,66 @@ typedef struct {
1330 uint32_t dseg_4_length; /* Data segment 4 length. */ 1346 uint32_t dseg_4_length; /* Data segment 4 length. */
1331} cont_a64_entry_t; 1347} cont_a64_entry_t;
1332 1348
1349#define PO_MODE_DIF_INSERT 0
1350#define PO_MODE_DIF_REMOVE BIT_0
1351#define PO_MODE_DIF_PASS BIT_1
1352#define PO_MODE_DIF_REPLACE (BIT_0 + BIT_1)
1353#define PO_ENABLE_DIF_BUNDLING BIT_8
1354#define PO_ENABLE_INCR_GUARD_SEED BIT_3
1355#define PO_DISABLE_INCR_REF_TAG BIT_5
1356#define PO_DISABLE_GUARD_CHECK BIT_4
1357/*
1358 * ISP queue - 64-Bit addressing, continuation crc entry structure definition.
1359 */
1360struct crc_context {
1361 uint32_t handle; /* System handle. */
1362 uint32_t ref_tag;
1363 uint16_t app_tag;
1364 uint8_t ref_tag_mask[4]; /* Validation/Replacement Mask*/
1365 uint8_t app_tag_mask[2]; /* Validation/Replacement Mask*/
1366 uint16_t guard_seed; /* Initial Guard Seed */
1367 uint16_t prot_opts; /* Requested Data Protection Mode */
1368 uint16_t blk_size; /* Data size in bytes */
1369 uint16_t runt_blk_guard; /* Guard value for runt block (tape
1370 * only) */
1371 uint32_t byte_count; /* Total byte count/ total data
1372 * transfer count */
1373 union {
1374 struct {
1375 uint32_t reserved_1;
1376 uint16_t reserved_2;
1377 uint16_t reserved_3;
1378 uint32_t reserved_4;
1379 uint32_t data_address[2];
1380 uint32_t data_length;
1381 uint32_t reserved_5[2];
1382 uint32_t reserved_6;
1383 } nobundling;
1384 struct {
1385 uint32_t dif_byte_count; /* Total DIF byte
1386 * count */
1387 uint16_t reserved_1;
1388 uint16_t dseg_count; /* Data segment count */
1389 uint32_t reserved_2;
1390 uint32_t data_address[2];
1391 uint32_t data_length;
1392 uint32_t dif_address[2];
1393 uint32_t dif_length; /* Data segment 0
1394 * length */
1395 } bundling;
1396 } u;
1397
1398 struct fcp_cmnd fcp_cmnd;
1399 dma_addr_t crc_ctx_dma;
1400 /* List of DMA context transfers */
1401 struct list_head dsd_list;
1402
1403 /* This structure should not exceed 512 bytes */
1404};
1405
1406#define CRC_CONTEXT_LEN_FW (offsetof(struct crc_context, fcp_cmnd.lun))
1407#define CRC_CONTEXT_FCPCMND_OFF (offsetof(struct crc_context, fcp_cmnd.lun))
1408
1333/* 1409/*
1334 * ISP queue - status entry structure definition. 1410 * ISP queue - status entry structure definition.
1335 */ 1411 */
@@ -1390,6 +1466,7 @@ typedef struct {
1390#define CS_ABORTED 0x5 /* System aborted command. */ 1466#define CS_ABORTED 0x5 /* System aborted command. */
1391#define CS_TIMEOUT 0x6 /* Timeout error. */ 1467#define CS_TIMEOUT 0x6 /* Timeout error. */
1392#define CS_DATA_OVERRUN 0x7 /* Data overrun. */ 1468#define CS_DATA_OVERRUN 0x7 /* Data overrun. */
1469#define CS_DIF_ERROR 0xC /* DIF error detected */
1393 1470
1394#define CS_DATA_UNDERRUN 0x15 /* Data Underrun. */ 1471#define CS_DATA_UNDERRUN 0x15 /* Data Underrun. */
1395#define CS_QUEUE_FULL 0x1C /* Queue Full. */ 1472#define CS_QUEUE_FULL 0x1C /* Queue Full. */
@@ -2732,6 +2809,7 @@ typedef struct scsi_qla_host {
2732 2809
2733 uint32_t management_server_logged_in :1; 2810 uint32_t management_server_logged_in :1;
2734 uint32_t process_response_queue :1; 2811 uint32_t process_response_queue :1;
2812 uint32_t difdix_supported:1;
2735 } flags; 2813 } flags;
2736 2814
2737 atomic_t loop_state; 2815 atomic_t loop_state;
@@ -2883,6 +2961,8 @@ typedef struct scsi_qla_host {
2883#define OPTROM_BURST_SIZE 0x1000 2961#define OPTROM_BURST_SIZE 0x1000
2884#define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4) 2962#define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4)
2885 2963
2964#define QLA_DSDS_PER_IOCB 37
2965
2886#include "qla_gbl.h" 2966#include "qla_gbl.h"
2887#include "qla_dbg.h" 2967#include "qla_dbg.h"
2888#include "qla_inline.h" 2968#include "qla_inline.h"
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index a77a2471eaff..93f833960147 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -400,6 +400,7 @@ struct cmd_type_6 {
400 struct scsi_lun lun; /* FCP LUN (BE). */ 400 struct scsi_lun lun; /* FCP LUN (BE). */
401 401
402 uint16_t control_flags; /* Control flags. */ 402 uint16_t control_flags; /* Control flags. */
403#define CF_DIF_SEG_DESCR_ENABLE BIT_3
403#define CF_DATA_SEG_DESCR_ENABLE BIT_2 404#define CF_DATA_SEG_DESCR_ENABLE BIT_2
404#define CF_READ_DATA BIT_1 405#define CF_READ_DATA BIT_1
405#define CF_WRITE_DATA BIT_0 406#define CF_WRITE_DATA BIT_0
@@ -466,6 +467,43 @@ struct cmd_type_7 {
466 uint32_t dseg_0_len; /* Data segment 0 length. */ 467 uint32_t dseg_0_len; /* Data segment 0 length. */
467}; 468};
468 469
470#define COMMAND_TYPE_CRC_2 0x6A /* Command Type CRC_2 (Type 6)
471 * (T10-DIF) */
472struct cmd_type_crc_2 {
473 uint8_t entry_type; /* Entry type. */
474 uint8_t entry_count; /* Entry count. */
475 uint8_t sys_define; /* System defined. */
476 uint8_t entry_status; /* Entry Status. */
477
478 uint32_t handle; /* System handle. */
479
480 uint16_t nport_handle; /* N_PORT handle. */
481 uint16_t timeout; /* Command timeout. */
482
483 uint16_t dseg_count; /* Data segment count. */
484
485 uint16_t fcp_rsp_dseg_len; /* FCP_RSP DSD length. */
486
487 struct scsi_lun lun; /* FCP LUN (BE). */
488
489 uint16_t control_flags; /* Control flags. */
490
491 uint16_t fcp_cmnd_dseg_len; /* Data segment length. */
492 uint32_t fcp_cmnd_dseg_address[2]; /* Data segment address. */
493
494 uint32_t fcp_rsp_dseg_address[2]; /* Data segment address. */
495
496 uint32_t byte_count; /* Total byte count. */
497
498 uint8_t port_id[3]; /* PortID of destination port. */
499 uint8_t vp_index;
500
501 uint32_t crc_context_address[2]; /* Data segment address. */
502 uint16_t crc_context_len; /* Data segment length. */
503 uint16_t reserved_1; /* MUST be set to 0. */
504};
505
506
469/* 507/*
470 * ISP queue - status entry structure definition. 508 * ISP queue - status entry structure definition.
471 */ 509 */
@@ -496,10 +534,17 @@ struct sts_entry_24xx {
496 534
497 uint32_t sense_len; /* FCP SENSE length. */ 535 uint32_t sense_len; /* FCP SENSE length. */
498 uint32_t rsp_data_len; /* FCP response data length. */ 536 uint32_t rsp_data_len; /* FCP response data length. */
499
500 uint8_t data[28]; /* FCP response/sense information. */ 537 uint8_t data[28]; /* FCP response/sense information. */
538 /*
539 * If DIF Error is set in comp_status, these additional fields are
540 * defined:
541 * &data[10] : uint8_t report_runt_bg[2]; - computed guard
542 * &data[12] : uint8_t actual_dif[8]; - DIF Data recieved
543 * &data[20] : uint8_t expected_dif[8]; - DIF Data computed
544 */
501}; 545};
502 546
547
503/* 548/*
504 * Status entry completion status 549 * Status entry completion status
505 */ 550 */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 3dbefe1a6b5f..3e946da74b96 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -94,6 +94,8 @@ extern int ql2xshiftctondsd;
94extern int ql2xdbwr; 94extern int ql2xdbwr;
95extern int ql2xdontresethba; 95extern int ql2xdontresethba;
96extern int ql2xasynctmfenable; 96extern int ql2xasynctmfenable;
97extern int ql2xenabledif;
98extern int ql2xenablehba_err_chk;
97 99
98extern int qla2x00_loop_reset(scsi_qla_host_t *); 100extern int qla2x00_loop_reset(scsi_qla_host_t *);
99extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); 101extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@@ -179,6 +181,7 @@ extern int qla2x00_start_sp(srb_t *);
179extern void qla2x00_ctx_sp_free(srb_t *); 181extern void qla2x00_ctx_sp_free(srb_t *);
180extern uint16_t qla24xx_calc_iocbs(uint16_t); 182extern uint16_t qla24xx_calc_iocbs(uint16_t);
181extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t); 183extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t);
184extern int qla24xx_dif_start_scsi(srb_t *);
182 185
183 186
184/* 187/*
@@ -423,6 +426,7 @@ extern void qla25xx_fw_dump(scsi_qla_host_t *, int);
423extern void qla81xx_fw_dump(scsi_qla_host_t *, int); 426extern void qla81xx_fw_dump(scsi_qla_host_t *, int);
424extern void qla2x00_dump_regs(scsi_qla_host_t *); 427extern void qla2x00_dump_regs(scsi_qla_host_t *);
425extern void qla2x00_dump_buffer(uint8_t *, uint32_t); 428extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
429extern void qla2x00_dump_buffer_zipped(uint8_t *, uint32_t);
426 430
427/* 431/*
428 * Global Function Prototypes in qla_gs.c source file. 432 * Global Function Prototypes in qla_gs.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index ad53c6455556..84c2fea154d2 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -67,3 +67,19 @@ qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id)
67 return ((loop_id > ha->max_loop_id && loop_id < SNS_FIRST_LOOP_ID) || 67 return ((loop_id > ha->max_loop_id && loop_id < SNS_FIRST_LOOP_ID) ||
68 loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST); 68 loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST);
69} 69}
70
71static inline void
72qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp)
73{
74 struct dsd_dma *dsd_ptr, *tdsd_ptr;
75
76 /* clean up allocated prev pool */
77 list_for_each_entry_safe(dsd_ptr, tdsd_ptr,
78 &((struct crc_context *)sp->ctx)->dsd_list, list) {
79 dma_pool_free(ha->dl_dma_pool, dsd_ptr->dsd_addr,
80 dsd_ptr->dsd_list_dma);
81 list_del(&dsd_ptr->list);
82 kfree(dsd_ptr);
83 }
84 INIT_LIST_HEAD(&((struct crc_context *)sp->ctx)->dsd_list);
85}
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index d7a9fff15ad5..8ef945365412 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -145,7 +145,49 @@ qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha)
145 return (cont_pkt); 145 return (cont_pkt);
146} 146}
147 147
148/** 148static inline int
149qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts)
150{
151 uint8_t guard = scsi_host_get_guard(sp->cmd->device->host);
152
153 /* We only support T10 DIF right now */
154 if (guard != SHOST_DIX_GUARD_CRC) {
155 DEBUG2(printk(KERN_ERR "Unsupported guard: %d\n", guard));
156 return 0;
157 }
158
159 /* We always use DIFF Bundling for best performance */
160 *fw_prot_opts = 0;
161
162 /* Translate SCSI opcode to a protection opcode */
163 switch (scsi_get_prot_op(sp->cmd)) {
164 case SCSI_PROT_READ_STRIP:
165 *fw_prot_opts |= PO_MODE_DIF_REMOVE;
166 break;
167 case SCSI_PROT_WRITE_INSERT:
168 *fw_prot_opts |= PO_MODE_DIF_INSERT;
169 break;
170 case SCSI_PROT_READ_INSERT:
171 *fw_prot_opts |= PO_MODE_DIF_INSERT;
172 break;
173 case SCSI_PROT_WRITE_STRIP:
174 *fw_prot_opts |= PO_MODE_DIF_REMOVE;
175 break;
176 case SCSI_PROT_READ_PASS:
177 *fw_prot_opts |= PO_MODE_DIF_PASS;
178 break;
179 case SCSI_PROT_WRITE_PASS:
180 *fw_prot_opts |= PO_MODE_DIF_PASS;
181 break;
182 default: /* Normal Request */
183 *fw_prot_opts |= PO_MODE_DIF_PASS;
184 break;
185 }
186
187 return scsi_prot_sg_count(sp->cmd);
188}
189
190/*
149 * qla2x00_build_scsi_iocbs_32() - Build IOCB command utilizing 32bit 191 * qla2x00_build_scsi_iocbs_32() - Build IOCB command utilizing 32bit
150 * capable IOCB types. 192 * capable IOCB types.
151 * 193 *
@@ -636,6 +678,8 @@ qla24xx_calc_iocbs(uint16_t dsds)
636 if ((dsds - 1) % 5) 678 if ((dsds - 1) % 5)
637 iocbs++; 679 iocbs++;
638 } 680 }
681 DEBUG3(printk(KERN_DEBUG "%s(): Required PKT(s) = %d\n",
682 __func__, iocbs));
639 return iocbs; 683 return iocbs;
640} 684}
641 685
@@ -716,6 +760,453 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt,
716 } 760 }
717} 761}
718 762
763struct fw_dif_context {
764 uint32_t ref_tag;
765 uint16_t app_tag;
766 uint8_t ref_tag_mask[4]; /* Validation/Replacement Mask*/
767 uint8_t app_tag_mask[2]; /* Validation/Replacement Mask*/
768};
769
770/*
771 * qla24xx_set_t10dif_tags_from_cmd - Extract Ref and App tags from SCSI command
772 *
773 */
774static inline void
775qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt,
776 unsigned int protcnt)
777{
778 struct sd_dif_tuple *spt;
779 unsigned char op = scsi_get_prot_op(cmd);
780
781 switch (scsi_get_prot_type(cmd)) {
782 /* For TYPE 0 protection: no checking */
783 case SCSI_PROT_DIF_TYPE0:
784 pkt->ref_tag_mask[0] = 0x00;
785 pkt->ref_tag_mask[1] = 0x00;
786 pkt->ref_tag_mask[2] = 0x00;
787 pkt->ref_tag_mask[3] = 0x00;
788 break;
789
790 /*
791 * For TYPE 2 protection: 16 bit GUARD + 32 bit REF tag has to
792 * match LBA in CDB + N
793 */
794 case SCSI_PROT_DIF_TYPE2:
795 break;
796
797 /* For Type 3 protection: 16 bit GUARD only */
798 case SCSI_PROT_DIF_TYPE3:
799 pkt->ref_tag_mask[0] = pkt->ref_tag_mask[1] =
800 pkt->ref_tag_mask[2] = pkt->ref_tag_mask[3] =
801 0x00;
802 break;
803
804 /*
805 * For TYpe 1 protection: 16 bit GUARD tag, 32 bit REF tag, and
806 * 16 bit app tag.
807 */
808 case SCSI_PROT_DIF_TYPE1:
809 if (!ql2xenablehba_err_chk)
810 break;
811
812 if (protcnt && (op == SCSI_PROT_WRITE_STRIP ||
813 op == SCSI_PROT_WRITE_PASS)) {
814 spt = page_address(sg_page(scsi_prot_sglist(cmd))) +
815 scsi_prot_sglist(cmd)[0].offset;
816 DEBUG18(printk(KERN_DEBUG
817 "%s(): LBA from user %p, lba = 0x%x\n",
818 __func__, spt, (int)spt->ref_tag));
819 pkt->ref_tag = swab32(spt->ref_tag);
820 pkt->app_tag_mask[0] = 0x0;
821 pkt->app_tag_mask[1] = 0x0;
822 } else {
823 pkt->ref_tag = cpu_to_le32((uint32_t)
824 (0xffffffff & scsi_get_lba(cmd)));
825 pkt->app_tag = __constant_cpu_to_le16(0);
826 pkt->app_tag_mask[0] = 0x0;
827 pkt->app_tag_mask[1] = 0x0;
828 }
829 /* enable ALL bytes of the ref tag */
830 pkt->ref_tag_mask[0] = 0xff;
831 pkt->ref_tag_mask[1] = 0xff;
832 pkt->ref_tag_mask[2] = 0xff;
833 pkt->ref_tag_mask[3] = 0xff;
834 break;
835 }
836
837 DEBUG18(printk(KERN_DEBUG
838 "%s(): Setting protection Tags: (BIG) ref tag = 0x%x,"
839 " app tag = 0x%x, prot SG count %d , cmd lba 0x%x,"
840 " prot_type=%u\n", __func__, pkt->ref_tag, pkt->app_tag, protcnt,
841 (int)scsi_get_lba(cmd), scsi_get_prot_type(cmd)));
842}
843
844
845static int
846qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
847 uint16_t tot_dsds)
848{
849 void *next_dsd;
850 uint8_t avail_dsds = 0;
851 uint32_t dsd_list_len;
852 struct dsd_dma *dsd_ptr;
853 struct scatterlist *sg;
854 uint32_t *cur_dsd = dsd;
855 int i;
856 uint16_t used_dsds = tot_dsds;
857
858 uint8_t *cp;
859
860 scsi_for_each_sg(sp->cmd, sg, tot_dsds, i) {
861 dma_addr_t sle_dma;
862
863 /* Allocate additional continuation packets? */
864 if (avail_dsds == 0) {
865 avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ?
866 QLA_DSDS_PER_IOCB : used_dsds;
867 dsd_list_len = (avail_dsds + 1) * 12;
868 used_dsds -= avail_dsds;
869
870 /* allocate tracking DS */
871 dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC);
872 if (!dsd_ptr)
873 return 1;
874
875 /* allocate new list */
876 dsd_ptr->dsd_addr = next_dsd =
877 dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC,
878 &dsd_ptr->dsd_list_dma);
879
880 if (!next_dsd) {
881 /*
882 * Need to cleanup only this dsd_ptr, rest
883 * will be done by sp_free_dma()
884 */
885 kfree(dsd_ptr);
886 return 1;
887 }
888
889 list_add_tail(&dsd_ptr->list,
890 &((struct crc_context *)sp->ctx)->dsd_list);
891
892 sp->flags |= SRB_CRC_CTX_DSD_VALID;
893
894 /* add new list to cmd iocb or last list */
895 *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
896 *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
897 *cur_dsd++ = dsd_list_len;
898 cur_dsd = (uint32_t *)next_dsd;
899 }
900 sle_dma = sg_dma_address(sg);
901 DEBUG18(printk("%s(): %p, sg entry %d - addr =0x%x 0x%x,"
902 " len =%d\n", __func__ , cur_dsd, i, LSD(sle_dma),
903 MSD(sle_dma), sg_dma_len(sg)));
904 *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
905 *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
906 *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
907 avail_dsds--;
908
909 if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) {
910 cp = page_address(sg_page(sg)) + sg->offset;
911 DEBUG18(printk("%s(): User Data buffer= %p:\n",
912 __func__ , cp));
913 }
914 }
915 /* Null termination */
916 *cur_dsd++ = 0;
917 *cur_dsd++ = 0;
918 *cur_dsd++ = 0;
919 return 0;
920}
921
922static int
923qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
924 uint32_t *dsd,
925 uint16_t tot_dsds)
926{
927 void *next_dsd;
928 uint8_t avail_dsds = 0;
929 uint32_t dsd_list_len;
930 struct dsd_dma *dsd_ptr;
931 struct scatterlist *sg;
932 int i;
933 struct scsi_cmnd *cmd;
934 uint32_t *cur_dsd = dsd;
935 uint16_t used_dsds = tot_dsds;
936
937 uint8_t *cp;
938
939
940 cmd = sp->cmd;
941 scsi_for_each_prot_sg(cmd, sg, tot_dsds, i) {
942 dma_addr_t sle_dma;
943
944 /* Allocate additional continuation packets? */
945 if (avail_dsds == 0) {
946 avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ?
947 QLA_DSDS_PER_IOCB : used_dsds;
948 dsd_list_len = (avail_dsds + 1) * 12;
949 used_dsds -= avail_dsds;
950
951 /* allocate tracking DS */
952 dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC);
953 if (!dsd_ptr)
954 return 1;
955
956 /* allocate new list */
957 dsd_ptr->dsd_addr = next_dsd =
958 dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC,
959 &dsd_ptr->dsd_list_dma);
960
961 if (!next_dsd) {
962 /*
963 * Need to cleanup only this dsd_ptr, rest
964 * will be done by sp_free_dma()
965 */
966 kfree(dsd_ptr);
967 return 1;
968 }
969
970 list_add_tail(&dsd_ptr->list,
971 &((struct crc_context *)sp->ctx)->dsd_list);
972
973 sp->flags |= SRB_CRC_CTX_DSD_VALID;
974
975 /* add new list to cmd iocb or last list */
976 *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
977 *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
978 *cur_dsd++ = dsd_list_len;
979 cur_dsd = (uint32_t *)next_dsd;
980 }
981 sle_dma = sg_dma_address(sg);
982 if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) {
983 DEBUG18(printk(KERN_DEBUG
984 "%s(): %p, sg entry %d - addr =0x%x"
985 "0x%x, len =%d\n", __func__ , cur_dsd, i,
986 LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg)));
987 }
988 *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
989 *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
990 *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
991
992 if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) {
993 cp = page_address(sg_page(sg)) + sg->offset;
994 DEBUG18(printk("%s(): Protection Data buffer = %p:\n",
995 __func__ , cp));
996 }
997 avail_dsds--;
998 }
999 /* Null termination */
1000 *cur_dsd++ = 0;
1001 *cur_dsd++ = 0;
1002 *cur_dsd++ = 0;
1003 return 0;
1004}
1005
1006/**
1007 * qla24xx_build_scsi_crc_2_iocbs() - Build IOCB command utilizing Command
1008 * Type 6 IOCB types.
1009 *
1010 * @sp: SRB command to process
1011 * @cmd_pkt: Command type 3 IOCB
1012 * @tot_dsds: Total number of segments to transfer
1013 */
1014static inline int
1015qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
1016 uint16_t tot_dsds, uint16_t tot_prot_dsds, uint16_t fw_prot_opts)
1017{
1018 uint32_t *cur_dsd, *fcp_dl;
1019 scsi_qla_host_t *vha;
1020 struct scsi_cmnd *cmd;
1021 struct scatterlist *cur_seg;
1022 int sgc;
1023 uint32_t total_bytes;
1024 uint32_t data_bytes;
1025 uint32_t dif_bytes;
1026 uint8_t bundling = 1;
1027 uint16_t blk_size;
1028 uint8_t *clr_ptr;
1029 struct crc_context *crc_ctx_pkt = NULL;
1030 struct qla_hw_data *ha;
1031 uint8_t additional_fcpcdb_len;
1032 uint16_t fcp_cmnd_len;
1033 struct fcp_cmnd *fcp_cmnd;
1034 dma_addr_t crc_ctx_dma;
1035
1036 cmd = sp->cmd;
1037
1038 sgc = 0;
1039 /* Update entry type to indicate Command Type CRC_2 IOCB */
1040 *((uint32_t *)(&cmd_pkt->entry_type)) =
1041 __constant_cpu_to_le32(COMMAND_TYPE_CRC_2);
1042
1043 /* No data transfer */
1044 data_bytes = scsi_bufflen(cmd);
1045 if (!data_bytes || cmd->sc_data_direction == DMA_NONE) {
1046 DEBUG18(printk(KERN_INFO "%s: Zero data bytes or DMA-NONE %d\n",
1047 __func__, data_bytes));
1048 cmd_pkt->byte_count = __constant_cpu_to_le32(0);
1049 return QLA_SUCCESS;
1050 }
1051
1052 vha = sp->fcport->vha;
1053 ha = vha->hw;
1054
1055 DEBUG18(printk(KERN_DEBUG
1056 "%s(%ld): Executing cmd sp %p, pid=%ld, prot_op=%u.\n", __func__,
1057 vha->host_no, sp, cmd->serial_number, scsi_get_prot_op(sp->cmd)));
1058
1059 cmd_pkt->vp_index = sp->fcport->vp_idx;
1060
1061 /* Set transfer direction */
1062 if (cmd->sc_data_direction == DMA_TO_DEVICE) {
1063 cmd_pkt->control_flags =
1064 __constant_cpu_to_le16(CF_WRITE_DATA);
1065 } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
1066 cmd_pkt->control_flags =
1067 __constant_cpu_to_le16(CF_READ_DATA);
1068 }
1069
1070 tot_prot_dsds = scsi_prot_sg_count(cmd);
1071 if (!tot_prot_dsds)
1072 bundling = 0;
1073
1074 /* Allocate CRC context from global pool */
1075 crc_ctx_pkt = sp->ctx = dma_pool_alloc(ha->dl_dma_pool,
1076 GFP_ATOMIC, &crc_ctx_dma);
1077
1078 if (!crc_ctx_pkt)
1079 goto crc_queuing_error;
1080
1081 /* Zero out CTX area. */
1082 clr_ptr = (uint8_t *)crc_ctx_pkt;
1083 memset(clr_ptr, 0, sizeof(*crc_ctx_pkt));
1084
1085 crc_ctx_pkt->crc_ctx_dma = crc_ctx_dma;
1086
1087 sp->flags |= SRB_CRC_CTX_DMA_VALID;
1088
1089 /* Set handle */
1090 crc_ctx_pkt->handle = cmd_pkt->handle;
1091
1092 INIT_LIST_HEAD(&crc_ctx_pkt->dsd_list);
1093
1094 qla24xx_set_t10dif_tags(cmd, (struct fw_dif_context *)
1095 &crc_ctx_pkt->ref_tag, tot_prot_dsds);
1096
1097 cmd_pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma));
1098 cmd_pkt->crc_context_address[1] = cpu_to_le32(MSD(crc_ctx_dma));
1099 cmd_pkt->crc_context_len = CRC_CONTEXT_LEN_FW;
1100
1101 /* Determine SCSI command length -- align to 4 byte boundary */
1102 if (cmd->cmd_len > 16) {
1103 DEBUG18(printk(KERN_INFO "%s(): **** SCSI CMD > 16\n",
1104 __func__));
1105 additional_fcpcdb_len = cmd->cmd_len - 16;
1106 if ((cmd->cmd_len % 4) != 0) {
1107 /* SCSI cmd > 16 bytes must be multiple of 4 */
1108 goto crc_queuing_error;
1109 }
1110 fcp_cmnd_len = 12 + cmd->cmd_len + 4;
1111 } else {
1112 additional_fcpcdb_len = 0;
1113 fcp_cmnd_len = 12 + 16 + 4;
1114 }
1115
1116 fcp_cmnd = &crc_ctx_pkt->fcp_cmnd;
1117
1118 fcp_cmnd->additional_cdb_len = additional_fcpcdb_len;
1119 if (cmd->sc_data_direction == DMA_TO_DEVICE)
1120 fcp_cmnd->additional_cdb_len |= 1;
1121 else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
1122 fcp_cmnd->additional_cdb_len |= 2;
1123
1124 int_to_scsilun(sp->cmd->device->lun, &fcp_cmnd->lun);
1125 memcpy(fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len);
1126 cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(fcp_cmnd_len);
1127 cmd_pkt->fcp_cmnd_dseg_address[0] = cpu_to_le32(
1128 LSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF));
1129 cmd_pkt->fcp_cmnd_dseg_address[1] = cpu_to_le32(
1130 MSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF));
1131 fcp_cmnd->task_attribute = 0;
1132 fcp_cmnd->task_managment = 0;
1133
1134 cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */
1135
1136 DEBUG18(printk(KERN_INFO "%s(%ld): Total SG(s) Entries %d, Data"
1137 "entries %d, data bytes %d, Protection entries %d\n",
1138 __func__, vha->host_no, tot_dsds, (tot_dsds-tot_prot_dsds),
1139 data_bytes, tot_prot_dsds));
1140
1141 /* Compute dif len and adjust data len to incude protection */
1142 total_bytes = data_bytes;
1143 dif_bytes = 0;
1144 blk_size = cmd->device->sector_size;
1145 if (scsi_get_prot_type(cmd) == SCSI_PROT_DIF_TYPE1) {
1146 dif_bytes = (data_bytes / blk_size) * 8;
1147 total_bytes += dif_bytes;
1148 }
1149
1150 if (!ql2xenablehba_err_chk)
1151 fw_prot_opts |= 0x10; /* Disable Guard tag checking */
1152
1153 if (!bundling) {
1154 cur_dsd = (uint32_t *) &crc_ctx_pkt->u.nobundling.data_address;
1155 } else {
1156 /*
1157 * Configure Bundling if we need to fetch interlaving
1158 * protection PCI accesses
1159 */
1160 fw_prot_opts |= PO_ENABLE_DIF_BUNDLING;
1161 crc_ctx_pkt->u.bundling.dif_byte_count = cpu_to_le32(dif_bytes);
1162 crc_ctx_pkt->u.bundling.dseg_count = cpu_to_le16(tot_dsds -
1163 tot_prot_dsds);
1164 cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.data_address;
1165 }
1166
1167 /* Finish the common fields of CRC pkt */
1168 crc_ctx_pkt->blk_size = cpu_to_le16(blk_size);
1169 crc_ctx_pkt->prot_opts = cpu_to_le16(fw_prot_opts);
1170 crc_ctx_pkt->byte_count = cpu_to_le32(data_bytes);
1171 crc_ctx_pkt->guard_seed = __constant_cpu_to_le16(0);
1172 /* Fibre channel byte count */
1173 cmd_pkt->byte_count = cpu_to_le32(total_bytes);
1174 fcp_dl = (uint32_t *)(crc_ctx_pkt->fcp_cmnd.cdb + 16 +
1175 additional_fcpcdb_len);
1176 *fcp_dl = htonl(total_bytes);
1177
1178 DEBUG18(printk(KERN_INFO "%s(%ld): dif bytes = 0x%x (%d), total bytes"
1179 " = 0x%x (%d), dat block size =0x%x (%d)\n", __func__,
1180 vha->host_no, dif_bytes, dif_bytes, total_bytes, total_bytes,
1181 crc_ctx_pkt->blk_size, crc_ctx_pkt->blk_size));
1182
1183 /* Walks data segments */
1184
1185 cmd_pkt->control_flags |=
1186 __constant_cpu_to_le16(CF_DATA_SEG_DESCR_ENABLE);
1187 if (qla24xx_walk_and_build_sglist(ha, sp, cur_dsd,
1188 (tot_dsds - tot_prot_dsds)))
1189 goto crc_queuing_error;
1190
1191 if (bundling && tot_prot_dsds) {
1192 /* Walks dif segments */
1193 cur_seg = scsi_prot_sglist(cmd);
1194 cmd_pkt->control_flags |=
1195 __constant_cpu_to_le16(CF_DIF_SEG_DESCR_ENABLE);
1196 cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address;
1197 if (qla24xx_walk_and_build_prot_sglist(ha, sp, cur_dsd,
1198 tot_prot_dsds))
1199 goto crc_queuing_error;
1200 }
1201 return QLA_SUCCESS;
1202
1203crc_queuing_error:
1204 DEBUG18(qla_printk(KERN_INFO, ha,
1205 "CMD sent FAILED crc_q error:sp = %p\n", sp));
1206 /* Cleanup will be performed by the caller */
1207
1208 return QLA_FUNCTION_FAILED;
1209}
719 1210
720/** 1211/**
721 * qla24xx_start_scsi() - Send a SCSI command to the ISP 1212 * qla24xx_start_scsi() - Send a SCSI command to the ISP
@@ -869,6 +1360,191 @@ queuing_error:
869 return QLA_FUNCTION_FAILED; 1360 return QLA_FUNCTION_FAILED;
870} 1361}
871 1362
1363
1364/**
1365 * qla24xx_dif_start_scsi() - Send a SCSI command to the ISP
1366 * @sp: command to send to the ISP
1367 *
1368 * Returns non-zero if a failure occurred, else zero.
1369 */
1370int
1371qla24xx_dif_start_scsi(srb_t *sp)
1372{
1373 int nseg;
1374 unsigned long flags;
1375 uint32_t *clr_ptr;
1376 uint32_t index;
1377 uint32_t handle;
1378 uint16_t cnt;
1379 uint16_t req_cnt = 0;
1380 uint16_t tot_dsds;
1381 uint16_t tot_prot_dsds;
1382 uint16_t fw_prot_opts = 0;
1383 struct req_que *req = NULL;
1384 struct rsp_que *rsp = NULL;
1385 struct scsi_cmnd *cmd = sp->cmd;
1386 struct scsi_qla_host *vha = sp->fcport->vha;
1387 struct qla_hw_data *ha = vha->hw;
1388 struct cmd_type_crc_2 *cmd_pkt;
1389 uint32_t status = 0;
1390
1391#define QDSS_GOT_Q_SPACE BIT_0
1392
1393 /* Only process protection in this routine */
1394 if (scsi_get_prot_op(cmd) == SCSI_PROT_NORMAL)
1395 return qla24xx_start_scsi(sp);
1396
1397 /* Setup device pointers. */
1398
1399 qla25xx_set_que(sp, &rsp);
1400 req = vha->req;
1401
1402 /* So we know we haven't pci_map'ed anything yet */
1403 tot_dsds = 0;
1404
1405 /* Send marker if required */
1406 if (vha->marker_needed != 0) {
1407 if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
1408 QLA_SUCCESS)
1409 return QLA_FUNCTION_FAILED;
1410 vha->marker_needed = 0;
1411 }
1412
1413 /* Acquire ring specific lock */
1414 spin_lock_irqsave(&ha->hardware_lock, flags);
1415
1416 /* Check for room in outstanding command list. */
1417 handle = req->current_outstanding_cmd;
1418 for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
1419 handle++;
1420 if (handle == MAX_OUTSTANDING_COMMANDS)
1421 handle = 1;
1422 if (!req->outstanding_cmds[handle])
1423 break;
1424 }
1425
1426 if (index == MAX_OUTSTANDING_COMMANDS)
1427 goto queuing_error;
1428
1429 /* Compute number of required data segments */
1430 /* Map the sg table so we have an accurate count of sg entries needed */
1431 if (scsi_sg_count(cmd)) {
1432 nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd),
1433 scsi_sg_count(cmd), cmd->sc_data_direction);
1434 if (unlikely(!nseg))
1435 goto queuing_error;
1436 else
1437 sp->flags |= SRB_DMA_VALID;
1438 } else
1439 nseg = 0;
1440
1441 /* number of required data segments */
1442 tot_dsds = nseg;
1443
1444 /* Compute number of required protection segments */
1445 if (qla24xx_configure_prot_mode(sp, &fw_prot_opts)) {
1446 nseg = dma_map_sg(&ha->pdev->dev, scsi_prot_sglist(cmd),
1447 scsi_prot_sg_count(cmd), cmd->sc_data_direction);
1448 if (unlikely(!nseg))
1449 goto queuing_error;
1450 else
1451 sp->flags |= SRB_CRC_PROT_DMA_VALID;
1452 } else {
1453 nseg = 0;
1454 }
1455
1456 req_cnt = 1;
1457 /* Total Data and protection sg segment(s) */
1458 tot_prot_dsds = nseg;
1459 tot_dsds += nseg;
1460 if (req->cnt < (req_cnt + 2)) {
1461 cnt = RD_REG_DWORD_RELAXED(req->req_q_out);
1462
1463 if (req->ring_index < cnt)
1464 req->cnt = cnt - req->ring_index;
1465 else
1466 req->cnt = req->length -
1467 (req->ring_index - cnt);
1468 }
1469
1470 if (req->cnt < (req_cnt + 2))
1471 goto queuing_error;
1472
1473 status |= QDSS_GOT_Q_SPACE;
1474
1475 /* Build header part of command packet (excluding the OPCODE). */
1476 req->current_outstanding_cmd = handle;
1477 req->outstanding_cmds[handle] = sp;
1478 sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle;
1479 req->cnt -= req_cnt;
1480
1481 /* Fill-in common area */
1482 cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr;
1483 cmd_pkt->handle = MAKE_HANDLE(req->id, handle);
1484
1485 clr_ptr = (uint32_t *)cmd_pkt + 2;
1486 memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8);
1487
1488 /* Set NPORT-ID and LUN number*/
1489 cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id);
1490 cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa;
1491 cmd_pkt->port_id[1] = sp->fcport->d_id.b.area;
1492 cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
1493
1494 int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
1495 host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
1496
1497 /* Total Data and protection segment(s) */
1498 cmd_pkt->dseg_count = cpu_to_le16(tot_dsds);
1499
1500 /* Build IOCB segments and adjust for data protection segments */
1501 if (qla24xx_build_scsi_crc_2_iocbs(sp, (struct cmd_type_crc_2 *)
1502 req->ring_ptr, tot_dsds, tot_prot_dsds, fw_prot_opts) !=
1503 QLA_SUCCESS)
1504 goto queuing_error;
1505
1506 cmd_pkt->entry_count = (uint8_t)req_cnt;
1507 /* Specify response queue number where completion should happen */
1508 cmd_pkt->entry_status = (uint8_t) rsp->id;
1509 cmd_pkt->timeout = __constant_cpu_to_le16(0);
1510 wmb();
1511
1512 /* Adjust ring index. */
1513 req->ring_index++;
1514 if (req->ring_index == req->length) {
1515 req->ring_index = 0;
1516 req->ring_ptr = req->ring;
1517 } else
1518 req->ring_ptr++;
1519
1520 /* Set chip new ring index. */
1521 WRT_REG_DWORD(req->req_q_in, req->ring_index);
1522 RD_REG_DWORD_RELAXED(&ha->iobase->isp24.hccr);
1523
1524 /* Manage unprocessed RIO/ZIO commands in response queue. */
1525 if (vha->flags.process_response_queue &&
1526 rsp->ring_ptr->signature != RESPONSE_PROCESSED)
1527 qla24xx_process_response_queue(vha, rsp);
1528
1529 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1530
1531 return QLA_SUCCESS;
1532
1533queuing_error:
1534 if (status & QDSS_GOT_Q_SPACE) {
1535 req->outstanding_cmds[handle] = NULL;
1536 req->cnt += req_cnt;
1537 }
1538 /* Cleanup will be performed by the caller (queuecommand) */
1539
1540 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1541
1542 DEBUG18(qla_printk(KERN_INFO, ha,
1543 "CMD sent FAILED SCSI prot_op:%02x\n", scsi_get_prot_op(cmd)));
1544 return QLA_FUNCTION_FAILED;
1545}
1546
1547
872static void qla25xx_set_que(srb_t *sp, struct rsp_que **rsp) 1548static void qla25xx_set_que(srb_t *sp, struct rsp_que **rsp)
873{ 1549{
874 struct scsi_cmnd *cmd = sp->cmd; 1550 struct scsi_cmnd *cmd = sp->cmd;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index eed71ea1d947..be3d8bed2ecf 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -10,6 +10,7 @@
10#include <linux/slab.h> 10#include <linux/slab.h>
11#include <scsi/scsi_tcq.h> 11#include <scsi/scsi_tcq.h>
12#include <scsi/scsi_bsg_fc.h> 12#include <scsi/scsi_bsg_fc.h>
13#include <scsi/scsi_eh.h>
13 14
14static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); 15static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
15static void qla2x00_process_completed_request(struct scsi_qla_host *, 16static void qla2x00_process_completed_request(struct scsi_qla_host *,
@@ -1364,6 +1365,78 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len,
1364 DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, sense_len)); 1365 DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, sense_len));
1365} 1366}
1366 1367
1368struct scsi_dif_tuple {
1369 __be16 guard; /* Checksum */
1370 __be16 app_tag; /* APPL identifer */
1371 __be32 ref_tag; /* Target LBA or indirect LBA */
1372};
1373
1374/*
1375 * Checks the guard or meta-data for the type of error
1376 * detected by the HBA. In case of errors, we set the
1377 * ASC/ASCQ fields in the sense buffer with ILLEGAL_REQUEST
1378 * to indicate to the kernel that the HBA detected error.
1379 */
1380static inline void
1381qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
1382{
1383 struct scsi_cmnd *cmd = sp->cmd;
1384 struct scsi_dif_tuple *ep =
1385 (struct scsi_dif_tuple *)&sts24->data[20];
1386 struct scsi_dif_tuple *ap =
1387 (struct scsi_dif_tuple *)&sts24->data[12];
1388 uint32_t e_ref_tag, a_ref_tag;
1389 uint16_t e_app_tag, a_app_tag;
1390 uint16_t e_guard, a_guard;
1391
1392 e_ref_tag = be32_to_cpu(ep->ref_tag);
1393 a_ref_tag = be32_to_cpu(ap->ref_tag);
1394 e_app_tag = be16_to_cpu(ep->app_tag);
1395 a_app_tag = be16_to_cpu(ap->app_tag);
1396 e_guard = be16_to_cpu(ep->guard);
1397 a_guard = be16_to_cpu(ap->guard);
1398
1399 DEBUG18(printk(KERN_DEBUG
1400 "%s(): iocb(s) %p Returned STATUS\n", __func__, sts24));
1401
1402 DEBUG18(printk(KERN_ERR "DIF ERROR in cmd 0x%x lba 0x%llx act ref"
1403 " tag=0x%x, exp ref_tag=0x%x, act app tag=0x%x, exp app"
1404 " tag=0x%x, act guard=0x%x, exp guard=0x%x\n",
1405 cmd->cmnd[0], (u64)scsi_get_lba(cmd), a_ref_tag, e_ref_tag,
1406 a_app_tag, e_app_tag, a_guard, e_guard));
1407
1408
1409 /* check guard */
1410 if (e_guard != a_guard) {
1411 scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
1412 0x10, 0x1);
1413 set_driver_byte(cmd, DRIVER_SENSE);
1414 set_host_byte(cmd, DID_ABORT);
1415 cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
1416 return;
1417 }
1418
1419 /* check appl tag */
1420 if (e_app_tag != a_app_tag) {
1421 scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
1422 0x10, 0x2);
1423 set_driver_byte(cmd, DRIVER_SENSE);
1424 set_host_byte(cmd, DID_ABORT);
1425 cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
1426 return;
1427 }
1428
1429 /* check ref tag */
1430 if (e_ref_tag != a_ref_tag) {
1431 scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
1432 0x10, 0x3);
1433 set_driver_byte(cmd, DRIVER_SENSE);
1434 set_host_byte(cmd, DID_ABORT);
1435 cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
1436 return;
1437 }
1438}
1439
1367/** 1440/**
1368 * qla2x00_status_entry() - Process a Status IOCB entry. 1441 * qla2x00_status_entry() - Process a Status IOCB entry.
1369 * @ha: SCSI driver HA context 1442 * @ha: SCSI driver HA context
@@ -1630,6 +1703,10 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
1630 case CS_ABORTED: 1703 case CS_ABORTED:
1631 cp->result = DID_RESET << 16; 1704 cp->result = DID_RESET << 16;
1632 break; 1705 break;
1706
1707 case CS_DIF_ERROR:
1708 qla2x00_handle_dif_error(sp, sts24);
1709 break;
1633 default: 1710 default:
1634 cp->result = DID_ERROR << 16; 1711 cp->result = DID_ERROR << 16;
1635 break; 1712 break;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 523d414b59af..5104aefdc7e6 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -92,6 +92,19 @@ module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR);
92MODULE_PARM_DESC(ql2xmaxqdepth, 92MODULE_PARM_DESC(ql2xmaxqdepth,
93 "Maximum queue depth to report for target devices."); 93 "Maximum queue depth to report for target devices.");
94 94
95/* Do not change the value of this after module load */
96int ql2xenabledif = 1;
97module_param(ql2xenabledif, int, S_IRUGO|S_IWUSR);
98MODULE_PARM_DESC(ql2xenabledif,
99 " Enable T10-CRC-DIF "
100 " Default is 0 - No DIF Support. 1 - Enable it");
101
102int ql2xenablehba_err_chk;
103module_param(ql2xenablehba_err_chk, int, S_IRUGO|S_IWUSR);
104MODULE_PARM_DESC(ql2xenablehba_err_chk,
105 " Enable T10-CRC-DIF Error isolation by HBA"
106 " Default is 0 - Error isolation disabled, 1 - Enable it");
107
95int ql2xiidmaenable=1; 108int ql2xiidmaenable=1;
96module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR); 109module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR);
97MODULE_PARM_DESC(ql2xiidmaenable, 110MODULE_PARM_DESC(ql2xiidmaenable,
@@ -537,6 +550,14 @@ qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
537 if (fcport->drport) 550 if (fcport->drport)
538 goto qc24_target_busy; 551 goto qc24_target_busy;
539 552
553 if (!vha->flags.difdix_supported &&
554 scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) {
555 DEBUG2(qla_printk(KERN_ERR, ha,
556 "DIF Cap Not Reg, fail DIF capable cmd's:%x\n",
557 cmd->cmnd[0]));
558 cmd->result = DID_NO_CONNECT << 16;
559 goto qc24_fail_command;
560 }
540 if (atomic_read(&fcport->state) != FCS_ONLINE) { 561 if (atomic_read(&fcport->state) != FCS_ONLINE) {
541 if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || 562 if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
542 atomic_read(&base_vha->loop_state) == LOOP_DEAD) { 563 atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
@@ -776,7 +797,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
776 797
777 if (sp == NULL) 798 if (sp == NULL)
778 continue; 799 continue;
779 if ((sp->ctx) && !(sp->flags & SRB_FCP_CMND_DMA_VALID)) 800 if ((sp->ctx) && !(sp->flags & SRB_FCP_CMND_DMA_VALID) &&
801 !IS_PROT_IO(sp))
780 continue; 802 continue;
781 if (sp->cmd != cmd) 803 if (sp->cmd != cmd)
782 continue; 804 continue;
@@ -842,7 +864,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
842 sp = req->outstanding_cmds[cnt]; 864 sp = req->outstanding_cmds[cnt];
843 if (!sp) 865 if (!sp)
844 continue; 866 continue;
845 if (sp->ctx) 867 if ((sp->ctx) && !IS_PROT_IO(sp))
846 continue; 868 continue;
847 if (vha->vp_idx != sp->fcport->vha->vp_idx) 869 if (vha->vp_idx != sp->fcport->vha->vp_idx)
848 continue; 870 continue;
@@ -1189,7 +1211,8 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
1189 if (sp) { 1211 if (sp) {
1190 req->outstanding_cmds[cnt] = NULL; 1212 req->outstanding_cmds[cnt] = NULL;
1191 if (!sp->ctx || 1213 if (!sp->ctx ||
1192 (sp->flags & SRB_FCP_CMND_DMA_VALID)) { 1214 (sp->flags & SRB_FCP_CMND_DMA_VALID) ||
1215 IS_PROT_IO(sp)) {
1193 sp->cmd->result = res; 1216 sp->cmd->result = res;
1194 qla2x00_sp_compl(ha, sp); 1217 qla2x00_sp_compl(ha, sp);
1195 } else { 1218 } else {
@@ -1553,7 +1576,7 @@ static struct isp_operations qla25xx_isp_ops = {
1553 .read_optrom = qla25xx_read_optrom_data, 1576 .read_optrom = qla25xx_read_optrom_data,
1554 .write_optrom = qla24xx_write_optrom_data, 1577 .write_optrom = qla24xx_write_optrom_data,
1555 .get_flash_version = qla24xx_get_flash_version, 1578 .get_flash_version = qla24xx_get_flash_version,
1556 .start_scsi = qla24xx_start_scsi, 1579 .start_scsi = qla24xx_dif_start_scsi,
1557 .abort_isp = qla2x00_abort_isp, 1580 .abort_isp = qla2x00_abort_isp,
1558}; 1581};
1559 1582
@@ -2185,6 +2208,22 @@ skip_dpc:
2185 DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n", 2208 DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n",
2186 base_vha->host_no, ha)); 2209 base_vha->host_no, ha));
2187 2210
2211 if (IS_QLA25XX(ha) && ql2xenabledif) {
2212 if (ha->fw_attributes & BIT_4) {
2213 base_vha->flags.difdix_supported = 1;
2214 DEBUG18(qla_printk(KERN_INFO, ha,
2215 "Registering for DIF/DIX type 1 and 3"
2216 " protection.\n"));
2217 scsi_host_set_prot(host,
2218 SHOST_DIF_TYPE1_PROTECTION
2219 | SHOST_DIF_TYPE3_PROTECTION
2220 | SHOST_DIX_TYPE1_PROTECTION
2221 | SHOST_DIX_TYPE3_PROTECTION);
2222 scsi_host_set_guard(host, SHOST_DIX_GUARD_CRC);
2223 } else
2224 base_vha->flags.difdix_supported = 0;
2225 }
2226
2188 ha->isp_ops->enable_intrs(ha); 2227 ha->isp_ops->enable_intrs(ha);
2189 2228
2190 ret = scsi_add_host(host, &pdev->dev); 2229 ret = scsi_add_host(host, &pdev->dev);
@@ -2546,7 +2585,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
2546 if (!ha->s_dma_pool) 2585 if (!ha->s_dma_pool)
2547 goto fail_free_nvram; 2586 goto fail_free_nvram;
2548 2587
2549 if (IS_QLA82XX(ha)) { 2588 if (IS_QLA82XX(ha) || ql2xenabledif) {
2550 ha->dl_dma_pool = dma_pool_create(name, &ha->pdev->dev, 2589 ha->dl_dma_pool = dma_pool_create(name, &ha->pdev->dev,
2551 DSD_LIST_DMA_POOL_SIZE, 8, 0); 2590 DSD_LIST_DMA_POOL_SIZE, 8, 0);
2552 if (!ha->dl_dma_pool) { 2591 if (!ha->dl_dma_pool) {
@@ -2678,12 +2717,12 @@ fail_free_ms_iocb:
2678 ha->ms_iocb = NULL; 2717 ha->ms_iocb = NULL;
2679 ha->ms_iocb_dma = 0; 2718 ha->ms_iocb_dma = 0;
2680fail_dma_pool: 2719fail_dma_pool:
2681 if (IS_QLA82XX(ha)) { 2720 if (IS_QLA82XX(ha) || ql2xenabledif) {
2682 dma_pool_destroy(ha->fcp_cmnd_dma_pool); 2721 dma_pool_destroy(ha->fcp_cmnd_dma_pool);
2683 ha->fcp_cmnd_dma_pool = NULL; 2722 ha->fcp_cmnd_dma_pool = NULL;
2684 } 2723 }
2685fail_dl_dma_pool: 2724fail_dl_dma_pool:
2686 if (IS_QLA82XX(ha)) { 2725 if (IS_QLA82XX(ha) || ql2xenabledif) {
2687 dma_pool_destroy(ha->dl_dma_pool); 2726 dma_pool_destroy(ha->dl_dma_pool);
2688 ha->dl_dma_pool = NULL; 2727 ha->dl_dma_pool = NULL;
2689 } 2728 }
@@ -3346,11 +3385,31 @@ static void
3346qla2x00_sp_free_dma(srb_t *sp) 3385qla2x00_sp_free_dma(srb_t *sp)
3347{ 3386{
3348 struct scsi_cmnd *cmd = sp->cmd; 3387 struct scsi_cmnd *cmd = sp->cmd;
3388 struct qla_hw_data *ha = sp->fcport->vha->hw;
3349 3389
3350 if (sp->flags & SRB_DMA_VALID) { 3390 if (sp->flags & SRB_DMA_VALID) {
3351 scsi_dma_unmap(cmd); 3391 scsi_dma_unmap(cmd);
3352 sp->flags &= ~SRB_DMA_VALID; 3392 sp->flags &= ~SRB_DMA_VALID;
3353 } 3393 }
3394
3395 if (sp->flags & SRB_CRC_PROT_DMA_VALID) {
3396 dma_unmap_sg(&ha->pdev->dev, scsi_prot_sglist(cmd),
3397 scsi_prot_sg_count(cmd), cmd->sc_data_direction);
3398 sp->flags &= ~SRB_CRC_PROT_DMA_VALID;
3399 }
3400
3401 if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
3402 /* List assured to be having elements */
3403 qla2x00_clean_dsd_pool(ha, sp);
3404 sp->flags &= ~SRB_CRC_CTX_DSD_VALID;
3405 }
3406
3407 if (sp->flags & SRB_CRC_CTX_DMA_VALID) {
3408 dma_pool_free(ha->dl_dma_pool, sp->ctx,
3409 ((struct crc_context *)sp->ctx)->crc_ctx_dma);
3410 sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
3411 }
3412
3354 CMD_SP(cmd) = NULL; 3413 CMD_SP(cmd) = NULL;
3355} 3414}
3356 3415
@@ -3464,7 +3523,7 @@ qla2x00_timer(scsi_qla_host_t *vha)
3464 sp = req->outstanding_cmds[index]; 3523 sp = req->outstanding_cmds[index];
3465 if (!sp) 3524 if (!sp)
3466 continue; 3525 continue;
3467 if (sp->ctx) 3526 if (sp->ctx && !IS_PROT_IO(sp))
3468 continue; 3527 continue;
3469 sfcp = sp->fcport; 3528 sfcp = sp->fcport;
3470 if (!(sfcp->flags & FCF_FCP2_DEVICE)) 3529 if (!(sfcp->flags & FCF_FCP2_DEVICE))