aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuinn Tran <quinn.tran@cavium.com>2017-03-15 12:48:49 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2017-03-18 20:28:36 -0400
commitbe25152c0d9e236076323abbe9def9714234b761 (patch)
treefcdda94e20887fafd1e405b08734ffd2e04749e1
parent5b33469a055c77001fd2c62b0f985c991b0e5b65 (diff)
qla2xxx: Improve T10-DIF/PI handling in driver.
Add routines to support T10 DIF tag. Signed-off-by: Quinn Tran <quinn.tran@cavium.com> Signed-off-by: Anil Gurumurthy <anil.gurumurthy@cavium.com> Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h10
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h6
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c13
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c540
-rw-r--r--drivers/scsi/qla2xxx/qla_target.h38
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c49
7 files changed, 406 insertions, 251 deletions
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index e1fc4e66966a..c6bffe929fe7 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -348,6 +348,7 @@ ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...);
348#define ql_dbg_tgt 0x00004000 /* Target mode */ 348#define ql_dbg_tgt 0x00004000 /* Target mode */
349#define ql_dbg_tgt_mgt 0x00002000 /* Target mode management */ 349#define ql_dbg_tgt_mgt 0x00002000 /* Target mode management */
350#define ql_dbg_tgt_tmr 0x00001000 /* Target mode task management */ 350#define ql_dbg_tgt_tmr 0x00001000 /* Target mode task management */
351#define ql_dbg_tgt_dif 0x00000800 /* Target mode dif */
351 352
352extern int qla27xx_dump_mpi_ram(struct qla_hw_data *, uint32_t, uint32_t *, 353extern int qla27xx_dump_mpi_ram(struct qla_hw_data *, uint32_t, uint32_t *,
353 uint32_t, void **); 354 uint32_t, void **);
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 56cd45fc600a..9d1d3dcf1c87 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3127,6 +3127,16 @@ struct bidi_statistics {
3127 unsigned long long transfer_bytes; 3127 unsigned long long transfer_bytes;
3128}; 3128};
3129 3129
3130struct qla_tc_param {
3131 struct scsi_qla_host *vha;
3132 uint32_t blk_sz;
3133 uint32_t bufflen;
3134 struct scatterlist *sg;
3135 struct scatterlist *prot_sg;
3136 struct crc_context *ctx;
3137 uint8_t *ctx_dsd_alloced;
3138};
3139
3130/* Multi queue support */ 3140/* Multi queue support */
3131#define MBC_INITIALIZE_MULTIQ 0x1f 3141#define MBC_INITIALIZE_MULTIQ 0x1f
3132#define QLA_QUE_PAGE 0X1000 3142#define QLA_QUE_PAGE 0X1000
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index b3d6441d1d90..ca6f122e5865 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -256,11 +256,11 @@ extern unsigned long qla2x00_get_async_timeout(struct scsi_qla_host *);
256extern void *qla2x00_alloc_iocbs(scsi_qla_host_t *, srb_t *); 256extern void *qla2x00_alloc_iocbs(scsi_qla_host_t *, srb_t *);
257extern int qla2x00_issue_marker(scsi_qla_host_t *, int); 257extern int qla2x00_issue_marker(scsi_qla_host_t *, int);
258extern int qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *, srb_t *, 258extern int qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *, srb_t *,
259 uint32_t *, uint16_t, struct qla_tgt_cmd *); 259 uint32_t *, uint16_t, struct qla_tc_param *);
260extern int qla24xx_walk_and_build_sglist(struct qla_hw_data *, srb_t *, 260extern int qla24xx_walk_and_build_sglist(struct qla_hw_data *, srb_t *,
261 uint32_t *, uint16_t, struct qla_tgt_cmd *); 261 uint32_t *, uint16_t, struct qla_tc_param *);
262extern int qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *, srb_t *, 262extern int qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *, srb_t *,
263 uint32_t *, uint16_t, struct qla_tgt_cmd *); 263 uint32_t *, uint16_t, struct qla_tc_param *);
264extern int qla24xx_get_one_block_sg(uint32_t, struct qla2_sgx *, uint32_t *); 264extern int qla24xx_get_one_block_sg(uint32_t, struct qla2_sgx *, uint32_t *);
265extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *); 265extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *);
266extern int qla24xx_build_scsi_crc_2_iocbs(srb_t *, 266extern int qla24xx_build_scsi_crc_2_iocbs(srb_t *,
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 535079280288..ea027f6a7fd4 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -889,7 +889,7 @@ qla24xx_get_one_block_sg(uint32_t blk_sz, struct qla2_sgx *sgx,
889 889
890int 890int
891qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp, 891qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp,
892 uint32_t *dsd, uint16_t tot_dsds, struct qla_tgt_cmd *tc) 892 uint32_t *dsd, uint16_t tot_dsds, struct qla_tc_param *tc)
893{ 893{
894 void *next_dsd; 894 void *next_dsd;
895 uint8_t avail_dsds = 0; 895 uint8_t avail_dsds = 0;
@@ -898,7 +898,6 @@ qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp,
898 struct scatterlist *sg_prot; 898 struct scatterlist *sg_prot;
899 uint32_t *cur_dsd = dsd; 899 uint32_t *cur_dsd = dsd;
900 uint16_t used_dsds = tot_dsds; 900 uint16_t used_dsds = tot_dsds;
901
902 uint32_t prot_int; /* protection interval */ 901 uint32_t prot_int; /* protection interval */
903 uint32_t partial; 902 uint32_t partial;
904 struct qla2_sgx sgx; 903 struct qla2_sgx sgx;
@@ -966,7 +965,7 @@ alloc_and_fill:
966 } else { 965 } else {
967 list_add_tail(&dsd_ptr->list, 966 list_add_tail(&dsd_ptr->list,
968 &(tc->ctx->dsd_list)); 967 &(tc->ctx->dsd_list));
969 tc->ctx_dsd_alloced = 1; 968 *tc->ctx_dsd_alloced = 1;
970 } 969 }
971 970
972 971
@@ -1005,7 +1004,7 @@ alloc_and_fill:
1005 1004
1006int 1005int
1007qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, 1006qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
1008 uint16_t tot_dsds, struct qla_tgt_cmd *tc) 1007 uint16_t tot_dsds, struct qla_tc_param *tc)
1009{ 1008{
1010 void *next_dsd; 1009 void *next_dsd;
1011 uint8_t avail_dsds = 0; 1010 uint8_t avail_dsds = 0;
@@ -1066,7 +1065,7 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
1066 } else { 1065 } else {
1067 list_add_tail(&dsd_ptr->list, 1066 list_add_tail(&dsd_ptr->list,
1068 &(tc->ctx->dsd_list)); 1067 &(tc->ctx->dsd_list));
1069 tc->ctx_dsd_alloced = 1; 1068 *tc->ctx_dsd_alloced = 1;
1070 } 1069 }
1071 1070
1072 /* add new list to cmd iocb or last list */ 1071 /* add new list to cmd iocb or last list */
@@ -1092,7 +1091,7 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
1092 1091
1093int 1092int
1094qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, 1093qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
1095 uint32_t *dsd, uint16_t tot_dsds, struct qla_tgt_cmd *tc) 1094 uint32_t *dsd, uint16_t tot_dsds, struct qla_tc_param *tc)
1096{ 1095{
1097 void *next_dsd; 1096 void *next_dsd;
1098 uint8_t avail_dsds = 0; 1097 uint8_t avail_dsds = 0;
@@ -1158,7 +1157,7 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
1158 } else { 1157 } else {
1159 list_add_tail(&dsd_ptr->list, 1158 list_add_tail(&dsd_ptr->list,
1160 &(tc->ctx->dsd_list)); 1159 &(tc->ctx->dsd_list));
1161 tc->ctx_dsd_alloced = 1; 1160 *tc->ctx_dsd_alloced = 1;
1162 } 1161 }
1163 1162
1164 /* add new list to cmd iocb or last list */ 1163 /* add new list to cmd iocb or last list */
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 925d9b858b24..532004981dbd 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -143,6 +143,20 @@ static struct workqueue_struct *qla_tgt_wq;
143static DEFINE_MUTEX(qla_tgt_mutex); 143static DEFINE_MUTEX(qla_tgt_mutex);
144static LIST_HEAD(qla_tgt_glist); 144static LIST_HEAD(qla_tgt_glist);
145 145
146static const char *prot_op_str(u32 prot_op)
147{
148 switch (prot_op) {
149 case TARGET_PROT_NORMAL: return "NORMAL";
150 case TARGET_PROT_DIN_INSERT: return "DIN_INSERT";
151 case TARGET_PROT_DOUT_INSERT: return "DOUT_INSERT";
152 case TARGET_PROT_DIN_STRIP: return "DIN_STRIP";
153 case TARGET_PROT_DOUT_STRIP: return "DOUT_STRIP";
154 case TARGET_PROT_DIN_PASS: return "DIN_PASS";
155 case TARGET_PROT_DOUT_PASS: return "DOUT_PASS";
156 default: return "UNKNOWN";
157 }
158}
159
146/* This API intentionally takes dest as a parameter, rather than returning 160/* This API intentionally takes dest as a parameter, rather than returning
147 * int value to avoid caller forgetting to issue wmb() after the store */ 161 * int value to avoid caller forgetting to issue wmb() after the store */
148void qlt_do_generation_tick(struct scsi_qla_host *vha, int *dest) 162void qlt_do_generation_tick(struct scsi_qla_host *vha, int *dest)
@@ -2022,6 +2036,70 @@ void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd)
2022} 2036}
2023EXPORT_SYMBOL(qlt_free_mcmd); 2037EXPORT_SYMBOL(qlt_free_mcmd);
2024 2038
2039/*
2040 * ha->hardware_lock supposed to be held on entry. Might drop it, then
2041 * reacquire
2042 */
2043void qlt_send_resp_ctio(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
2044 uint8_t scsi_status, uint8_t sense_key, uint8_t asc, uint8_t ascq)
2045{
2046 struct atio_from_isp *atio = &cmd->atio;
2047 struct ctio7_to_24xx *ctio;
2048 uint16_t temp;
2049
2050 ql_dbg(ql_dbg_tgt_dif, vha, 0x3066,
2051 "Sending response CTIO7 (vha=%p, atio=%p, scsi_status=%02x, "
2052 "sense_key=%02x, asc=%02x, ascq=%02x",
2053 vha, atio, scsi_status, sense_key, asc, ascq);
2054
2055 ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs(vha, NULL);
2056 if (!ctio) {
2057 ql_dbg(ql_dbg_async, vha, 0x3067,
2058 "qla2x00t(%ld): %s failed: unable to allocate request packet",
2059 vha->host_no, __func__);
2060 goto out;
2061 }
2062
2063 ctio->entry_type = CTIO_TYPE7;
2064 ctio->entry_count = 1;
2065 ctio->handle = QLA_TGT_SKIP_HANDLE;
2066 ctio->nport_handle = cmd->sess->loop_id;
2067 ctio->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
2068 ctio->vp_index = vha->vp_idx;
2069 ctio->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
2070 ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
2071 ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
2072 ctio->exchange_addr = atio->u.isp24.exchange_addr;
2073 ctio->u.status1.flags = (atio->u.isp24.attr << 9) |
2074 cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS);
2075 temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
2076 ctio->u.status1.ox_id = cpu_to_le16(temp);
2077 ctio->u.status1.scsi_status =
2078 cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID | scsi_status);
2079 ctio->u.status1.response_len = cpu_to_le16(18);
2080 ctio->u.status1.residual = cpu_to_le32(get_datalen_for_atio(atio));
2081
2082 if (ctio->u.status1.residual != 0)
2083 ctio->u.status1.scsi_status |=
2084 cpu_to_le16(SS_RESIDUAL_UNDER);
2085
2086 /* Response code and sense key */
2087 put_unaligned_le32(((0x70 << 24) | (sense_key << 8)),
2088 (&ctio->u.status1.sense_data)[0]);
2089 /* Additional sense length */
2090 put_unaligned_le32(0x0a, (&ctio->u.status1.sense_data)[1]);
2091 /* ASC and ASCQ */
2092 put_unaligned_le32(((asc << 24) | (ascq << 16)),
2093 (&ctio->u.status1.sense_data)[3]);
2094
2095 /* Memory Barrier */
2096 wmb();
2097
2098 qla2x00_start_iocbs(vha, vha->req);
2099out:
2100 return;
2101}
2102
2025/* callback from target fabric module code */ 2103/* callback from target fabric module code */
2026void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd) 2104void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd)
2027{ 2105{
@@ -2270,7 +2348,7 @@ static int qlt_24xx_build_ctio_pkt(struct qla_tgt_prm *prm,
2270 */ 2348 */
2271 return -EAGAIN; 2349 return -EAGAIN;
2272 } else 2350 } else
2273 ha->tgt.cmds[h-1] = prm->cmd; 2351 ha->tgt.cmds[h - 1] = prm->cmd;
2274 2352
2275 pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK; 2353 pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK;
2276 pkt->nport_handle = prm->cmd->loop_id; 2354 pkt->nport_handle = prm->cmd->loop_id;
@@ -2400,6 +2478,50 @@ static inline int qlt_has_data(struct qla_tgt_cmd *cmd)
2400 return cmd->bufflen > 0; 2478 return cmd->bufflen > 0;
2401} 2479}
2402 2480
2481static void qlt_print_dif_err(struct qla_tgt_prm *prm)
2482{
2483 struct qla_tgt_cmd *cmd;
2484 struct scsi_qla_host *vha;
2485
2486 /* asc 0x10=dif error */
2487 if (prm->sense_buffer && (prm->sense_buffer[12] == 0x10)) {
2488 cmd = prm->cmd;
2489 vha = cmd->vha;
2490 /* ASCQ */
2491 switch (prm->sense_buffer[13]) {
2492 case 1:
2493 ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
2494 "BE detected Guard TAG ERR: lba[0x%llx|%lld] len[0x%x] "
2495 "se_cmd=%p tag[%x]",
2496 cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
2497 cmd->atio.u.isp24.exchange_addr);
2498 break;
2499 case 2:
2500 ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
2501 "BE detected APP TAG ERR: lba[0x%llx|%lld] len[0x%x] "
2502 "se_cmd=%p tag[%x]",
2503 cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
2504 cmd->atio.u.isp24.exchange_addr);
2505 break;
2506 case 3:
2507 ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
2508 "BE detected REF TAG ERR: lba[0x%llx|%lld] len[0x%x] "
2509 "se_cmd=%p tag[%x]",
2510 cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
2511 cmd->atio.u.isp24.exchange_addr);
2512 break;
2513 default:
2514 ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
2515 "BE detected Dif ERR: lba[%llx|%lld] len[%x] "
2516 "se_cmd=%p tag[%x]",
2517 cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
2518 cmd->atio.u.isp24.exchange_addr);
2519 break;
2520 }
2521 ql_dump_buffer(ql_dbg_tgt_dif, vha, 0xffff, cmd->cdb, 16);
2522 }
2523}
2524
2403/* 2525/*
2404 * Called without ha->hardware_lock held 2526 * Called without ha->hardware_lock held
2405 */ 2527 */
@@ -2521,18 +2643,9 @@ skip_explict_conf:
2521 for (i = 0; i < prm->sense_buffer_len/4; i++) 2643 for (i = 0; i < prm->sense_buffer_len/4; i++)
2522 ((uint32_t *)ctio->u.status1.sense_data)[i] = 2644 ((uint32_t *)ctio->u.status1.sense_data)[i] =
2523 cpu_to_be32(((uint32_t *)prm->sense_buffer)[i]); 2645 cpu_to_be32(((uint32_t *)prm->sense_buffer)[i]);
2524#if 0 2646
2525 if (unlikely((prm->sense_buffer_len % 4) != 0)) { 2647 qlt_print_dif_err(prm);
2526 static int q; 2648
2527 if (q < 10) {
2528 ql_dbg(ql_dbg_tgt, vha, 0xe04f,
2529 "qla_target(%d): %d bytes of sense "
2530 "lost", prm->tgt->ha->vp_idx,
2531 prm->sense_buffer_len % 4);
2532 q++;
2533 }
2534 }
2535#endif
2536 } else { 2649 } else {
2537 ctio->u.status1.flags &= 2650 ctio->u.status1.flags &=
2538 ~cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0); 2651 ~cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0);
@@ -2546,19 +2659,9 @@ skip_explict_conf:
2546 /* Sense with len > 24, is it possible ??? */ 2659 /* Sense with len > 24, is it possible ??? */
2547} 2660}
2548 2661
2549
2550
2551/* diff */
2552static inline int 2662static inline int
2553qlt_hba_err_chk_enabled(struct se_cmd *se_cmd) 2663qlt_hba_err_chk_enabled(struct se_cmd *se_cmd)
2554{ 2664{
2555 /*
2556 * Uncomment when corresponding SCSI changes are done.
2557 *
2558 if (!sp->cmd->prot_chk)
2559 return 0;
2560 *
2561 */
2562 switch (se_cmd->prot_op) { 2665 switch (se_cmd->prot_op) {
2563 case TARGET_PROT_DOUT_INSERT: 2666 case TARGET_PROT_DOUT_INSERT:
2564 case TARGET_PROT_DIN_STRIP: 2667 case TARGET_PROT_DIN_STRIP:
@@ -2579,16 +2682,38 @@ qlt_hba_err_chk_enabled(struct se_cmd *se_cmd)
2579 return 0; 2682 return 0;
2580} 2683}
2581 2684
2685static inline int
2686qla_tgt_ref_mask_check(struct se_cmd *se_cmd)
2687{
2688 switch (se_cmd->prot_op) {
2689 case TARGET_PROT_DIN_INSERT:
2690 case TARGET_PROT_DOUT_INSERT:
2691 case TARGET_PROT_DIN_STRIP:
2692 case TARGET_PROT_DOUT_STRIP:
2693 case TARGET_PROT_DIN_PASS:
2694 case TARGET_PROT_DOUT_PASS:
2695 return 1;
2696 default:
2697 return 0;
2698 }
2699 return 0;
2700}
2701
2582/* 2702/*
2583 * qla24xx_set_t10dif_tags_from_cmd - Extract Ref and App tags from SCSI command 2703 * qla_tgt_set_dif_tags - Extract Ref and App tags from SCSI command
2584 *
2585 */ 2704 */
2586static inline void 2705static void
2587qlt_set_t10dif_tags(struct se_cmd *se_cmd, struct crc_context *ctx) 2706qla_tgt_set_dif_tags(struct qla_tgt_cmd *cmd, struct crc_context *ctx,
2707 uint16_t *pfw_prot_opts)
2588{ 2708{
2709 struct se_cmd *se_cmd = &cmd->se_cmd;
2589 uint32_t lba = 0xffffffff & se_cmd->t_task_lba; 2710 uint32_t lba = 0xffffffff & se_cmd->t_task_lba;
2711 scsi_qla_host_t *vha = cmd->tgt->vha;
2712 struct qla_hw_data *ha = vha->hw;
2713 uint32_t t32 = 0;
2590 2714
2591 /* wait til Mode Sense/Select cmd, modepage Ah, subpage 2 2715 /*
2716 * wait till Mode Sense/Select cmd, modepage Ah, subpage 2
2592 * have been immplemented by TCM, before AppTag is avail. 2717 * have been immplemented by TCM, before AppTag is avail.
2593 * Look for modesense_handlers[] 2718 * Look for modesense_handlers[]
2594 */ 2719 */
@@ -2596,65 +2721,73 @@ qlt_set_t10dif_tags(struct se_cmd *se_cmd, struct crc_context *ctx)
2596 ctx->app_tag_mask[0] = 0x0; 2721 ctx->app_tag_mask[0] = 0x0;
2597 ctx->app_tag_mask[1] = 0x0; 2722 ctx->app_tag_mask[1] = 0x0;
2598 2723
2724 if (IS_PI_UNINIT_CAPABLE(ha)) {
2725 if ((se_cmd->prot_type == TARGET_DIF_TYPE1_PROT) ||
2726 (se_cmd->prot_type == TARGET_DIF_TYPE2_PROT))
2727 *pfw_prot_opts |= PO_DIS_VALD_APP_ESC;
2728 else if (se_cmd->prot_type == TARGET_DIF_TYPE3_PROT)
2729 *pfw_prot_opts |= PO_DIS_VALD_APP_REF_ESC;
2730 }
2731
2732 t32 = ha->tgt.tgt_ops->get_dif_tags(cmd, pfw_prot_opts);
2733
2599 switch (se_cmd->prot_type) { 2734 switch (se_cmd->prot_type) {
2600 case TARGET_DIF_TYPE0_PROT: 2735 case TARGET_DIF_TYPE0_PROT:
2601 /* 2736 /*
2602 * No check for ql2xenablehba_err_chk, as it would be an 2737 * No check for ql2xenablehba_err_chk, as it
2603 * I/O error if hba tag generation is not done. 2738 * would be an I/O error if hba tag generation
2739 * is not done.
2604 */ 2740 */
2605 ctx->ref_tag = cpu_to_le32(lba); 2741 ctx->ref_tag = cpu_to_le32(lba);
2606
2607 if (!qlt_hba_err_chk_enabled(se_cmd))
2608 break;
2609
2610 /* enable ALL bytes of the ref tag */ 2742 /* enable ALL bytes of the ref tag */
2611 ctx->ref_tag_mask[0] = 0xff; 2743 ctx->ref_tag_mask[0] = 0xff;
2612 ctx->ref_tag_mask[1] = 0xff; 2744 ctx->ref_tag_mask[1] = 0xff;
2613 ctx->ref_tag_mask[2] = 0xff; 2745 ctx->ref_tag_mask[2] = 0xff;
2614 ctx->ref_tag_mask[3] = 0xff; 2746 ctx->ref_tag_mask[3] = 0xff;
2615 break; 2747 break;
2616 /*
2617 * For TYpe 1 protection: 16 bit GUARD tag, 32 bit REF tag, and
2618 * 16 bit app tag.
2619 */
2620 case TARGET_DIF_TYPE1_PROT: 2748 case TARGET_DIF_TYPE1_PROT:
2621 ctx->ref_tag = cpu_to_le32(lba); 2749 /*
2622 2750 * For TYPE 1 protection: 16 bit GUARD tag, 32 bit
2623 if (!qlt_hba_err_chk_enabled(se_cmd)) 2751 * REF tag, and 16 bit app tag.
2624 break; 2752 */
2625 2753 ctx->ref_tag = cpu_to_le32(lba);
2626 /* enable ALL bytes of the ref tag */ 2754 if (!qla_tgt_ref_mask_check(se_cmd) ||
2627 ctx->ref_tag_mask[0] = 0xff; 2755 !(ha->tgt.tgt_ops->chk_dif_tags(t32))) {
2628 ctx->ref_tag_mask[1] = 0xff; 2756 *pfw_prot_opts |= PO_DIS_REF_TAG_VALD;
2629 ctx->ref_tag_mask[2] = 0xff; 2757 break;
2630 ctx->ref_tag_mask[3] = 0xff; 2758 }
2631 break; 2759 /* enable ALL bytes of the ref tag */
2632 /* 2760 ctx->ref_tag_mask[0] = 0xff;
2633 * For TYPE 2 protection: 16 bit GUARD + 32 bit REF tag has to 2761 ctx->ref_tag_mask[1] = 0xff;
2634 * match LBA in CDB + N 2762 ctx->ref_tag_mask[2] = 0xff;
2635 */ 2763 ctx->ref_tag_mask[3] = 0xff;
2764 break;
2636 case TARGET_DIF_TYPE2_PROT: 2765 case TARGET_DIF_TYPE2_PROT:
2637 ctx->ref_tag = cpu_to_le32(lba); 2766 /*
2638 2767 * For TYPE 2 protection: 16 bit GUARD + 32 bit REF
2639 if (!qlt_hba_err_chk_enabled(se_cmd)) 2768 * tag has to match LBA in CDB + N
2640 break; 2769 */
2641 2770 ctx->ref_tag = cpu_to_le32(lba);
2642 /* enable ALL bytes of the ref tag */ 2771 if (!qla_tgt_ref_mask_check(se_cmd) ||
2643 ctx->ref_tag_mask[0] = 0xff; 2772 !(ha->tgt.tgt_ops->chk_dif_tags(t32))) {
2644 ctx->ref_tag_mask[1] = 0xff; 2773 *pfw_prot_opts |= PO_DIS_REF_TAG_VALD;
2645 ctx->ref_tag_mask[2] = 0xff; 2774 break;
2646 ctx->ref_tag_mask[3] = 0xff; 2775 }
2647 break; 2776 /* enable ALL bytes of the ref tag */
2648 2777 ctx->ref_tag_mask[0] = 0xff;
2649 /* For Type 3 protection: 16 bit GUARD only */ 2778 ctx->ref_tag_mask[1] = 0xff;
2779 ctx->ref_tag_mask[2] = 0xff;
2780 ctx->ref_tag_mask[3] = 0xff;
2781 break;
2650 case TARGET_DIF_TYPE3_PROT: 2782 case TARGET_DIF_TYPE3_PROT:
2651 ctx->ref_tag_mask[0] = ctx->ref_tag_mask[1] = 2783 /* For TYPE 3 protection: 16 bit GUARD only */
2652 ctx->ref_tag_mask[2] = ctx->ref_tag_mask[3] = 0x00; 2784 *pfw_prot_opts |= PO_DIS_REF_TAG_VALD;
2653 break; 2785 ctx->ref_tag_mask[0] = ctx->ref_tag_mask[1] =
2786 ctx->ref_tag_mask[2] = ctx->ref_tag_mask[3] = 0x00;
2787 break;
2654 } 2788 }
2655} 2789}
2656 2790
2657
2658static inline int 2791static inline int
2659qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha) 2792qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
2660{ 2793{
@@ -2673,6 +2806,7 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
2673 struct se_cmd *se_cmd = &cmd->se_cmd; 2806 struct se_cmd *se_cmd = &cmd->se_cmd;
2674 uint32_t h; 2807 uint32_t h;
2675 struct atio_from_isp *atio = &prm->cmd->atio; 2808 struct atio_from_isp *atio = &prm->cmd->atio;
2809 struct qla_tc_param tc;
2676 uint16_t t16; 2810 uint16_t t16;
2677 2811
2678 ha = vha->hw; 2812 ha = vha->hw;
@@ -2698,16 +2832,15 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
2698 case TARGET_PROT_DIN_INSERT: 2832 case TARGET_PROT_DIN_INSERT:
2699 case TARGET_PROT_DOUT_STRIP: 2833 case TARGET_PROT_DOUT_STRIP:
2700 transfer_length = data_bytes; 2834 transfer_length = data_bytes;
2701 data_bytes += dif_bytes; 2835 if (cmd->prot_sg_cnt)
2836 data_bytes += dif_bytes;
2702 break; 2837 break;
2703
2704 case TARGET_PROT_DIN_STRIP: 2838 case TARGET_PROT_DIN_STRIP:
2705 case TARGET_PROT_DOUT_INSERT: 2839 case TARGET_PROT_DOUT_INSERT:
2706 case TARGET_PROT_DIN_PASS: 2840 case TARGET_PROT_DIN_PASS:
2707 case TARGET_PROT_DOUT_PASS: 2841 case TARGET_PROT_DOUT_PASS:
2708 transfer_length = data_bytes + dif_bytes; 2842 transfer_length = data_bytes + dif_bytes;
2709 break; 2843 break;
2710
2711 default: 2844 default:
2712 BUG(); 2845 BUG();
2713 break; 2846 break;
@@ -2743,7 +2876,6 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
2743 break; 2876 break;
2744 } 2877 }
2745 2878
2746
2747 /* ---- PKT ---- */ 2879 /* ---- PKT ---- */
2748 /* Update entry type to indicate Command Type CRC_2 IOCB */ 2880 /* Update entry type to indicate Command Type CRC_2 IOCB */
2749 pkt->entry_type = CTIO_CRC2; 2881 pkt->entry_type = CTIO_CRC2;
@@ -2761,9 +2893,8 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
2761 } else 2893 } else
2762 ha->tgt.cmds[h-1] = prm->cmd; 2894 ha->tgt.cmds[h-1] = prm->cmd;
2763 2895
2764
2765 pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK; 2896 pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK;
2766 pkt->nport_handle = prm->cmd->loop_id; 2897 pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id);
2767 pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); 2898 pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
2768 pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; 2899 pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
2769 pkt->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; 2900 pkt->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
@@ -2784,12 +2915,10 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
2784 else if (cmd->dma_data_direction == DMA_FROM_DEVICE) 2915 else if (cmd->dma_data_direction == DMA_FROM_DEVICE)
2785 pkt->flags = cpu_to_le16(CTIO7_FLAGS_DATA_OUT); 2916 pkt->flags = cpu_to_le16(CTIO7_FLAGS_DATA_OUT);
2786 2917
2787
2788 pkt->dseg_count = prm->tot_dsds; 2918 pkt->dseg_count = prm->tot_dsds;
2789 /* Fibre channel byte count */ 2919 /* Fibre channel byte count */
2790 pkt->transfer_length = cpu_to_le32(transfer_length); 2920 pkt->transfer_length = cpu_to_le32(transfer_length);
2791 2921
2792
2793 /* ----- CRC context -------- */ 2922 /* ----- CRC context -------- */
2794 2923
2795 /* Allocate CRC context from global pool */ 2924 /* Allocate CRC context from global pool */
@@ -2809,13 +2938,12 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
2809 /* Set handle */ 2938 /* Set handle */
2810 crc_ctx_pkt->handle = pkt->handle; 2939 crc_ctx_pkt->handle = pkt->handle;
2811 2940
2812 qlt_set_t10dif_tags(se_cmd, crc_ctx_pkt); 2941 qla_tgt_set_dif_tags(cmd, crc_ctx_pkt, &fw_prot_opts);
2813 2942
2814 pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma)); 2943 pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma));
2815 pkt->crc_context_address[1] = cpu_to_le32(MSD(crc_ctx_dma)); 2944 pkt->crc_context_address[1] = cpu_to_le32(MSD(crc_ctx_dma));
2816 pkt->crc_context_len = CRC_CONTEXT_LEN_FW; 2945 pkt->crc_context_len = CRC_CONTEXT_LEN_FW;
2817 2946
2818
2819 if (!bundling) { 2947 if (!bundling) {
2820 cur_dsd = (uint32_t *) &crc_ctx_pkt->u.nobundling.data_address; 2948 cur_dsd = (uint32_t *) &crc_ctx_pkt->u.nobundling.data_address;
2821 } else { 2949 } else {
@@ -2836,16 +2964,24 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
2836 crc_ctx_pkt->byte_count = cpu_to_le32(data_bytes); 2964 crc_ctx_pkt->byte_count = cpu_to_le32(data_bytes);
2837 crc_ctx_pkt->guard_seed = cpu_to_le16(0); 2965 crc_ctx_pkt->guard_seed = cpu_to_le16(0);
2838 2966
2967 memset((uint8_t *)&tc, 0 , sizeof(tc));
2968 tc.vha = vha;
2969 tc.blk_sz = cmd->blk_sz;
2970 tc.bufflen = cmd->bufflen;
2971 tc.sg = cmd->sg;
2972 tc.prot_sg = cmd->prot_sg;
2973 tc.ctx = crc_ctx_pkt;
2974 tc.ctx_dsd_alloced = &cmd->ctx_dsd_alloced;
2839 2975
2840 /* Walks data segments */ 2976 /* Walks data segments */
2841 pkt->flags |= cpu_to_le16(CTIO7_FLAGS_DSD_PTR); 2977 pkt->flags |= cpu_to_le16(CTIO7_FLAGS_DSD_PTR);
2842 2978
2843 if (!bundling && prm->prot_seg_cnt) { 2979 if (!bundling && prm->prot_seg_cnt) {
2844 if (qla24xx_walk_and_build_sglist_no_difb(ha, NULL, cur_dsd, 2980 if (qla24xx_walk_and_build_sglist_no_difb(ha, NULL, cur_dsd,
2845 prm->tot_dsds, cmd)) 2981 prm->tot_dsds, &tc))
2846 goto crc_queuing_error; 2982 goto crc_queuing_error;
2847 } else if (qla24xx_walk_and_build_sglist(ha, NULL, cur_dsd, 2983 } else if (qla24xx_walk_and_build_sglist(ha, NULL, cur_dsd,
2848 (prm->tot_dsds - prm->prot_seg_cnt), cmd)) 2984 (prm->tot_dsds - prm->prot_seg_cnt), &tc))
2849 goto crc_queuing_error; 2985 goto crc_queuing_error;
2850 2986
2851 if (bundling && prm->prot_seg_cnt) { 2987 if (bundling && prm->prot_seg_cnt) {
@@ -2854,18 +2990,18 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
2854 2990
2855 cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address; 2991 cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address;
2856 if (qla24xx_walk_and_build_prot_sglist(ha, NULL, cur_dsd, 2992 if (qla24xx_walk_and_build_prot_sglist(ha, NULL, cur_dsd,
2857 prm->prot_seg_cnt, cmd)) 2993 prm->prot_seg_cnt, &tc))
2858 goto crc_queuing_error; 2994 goto crc_queuing_error;
2859 } 2995 }
2860 return QLA_SUCCESS; 2996 return QLA_SUCCESS;
2861 2997
2862crc_queuing_error: 2998crc_queuing_error:
2863 /* Cleanup will be performed by the caller */ 2999 /* Cleanup will be performed by the caller */
3000 vha->hw->tgt.cmds[h - 1] = NULL;
2864 3001
2865 return QLA_FUNCTION_FAILED; 3002 return QLA_FUNCTION_FAILED;
2866} 3003}
2867 3004
2868
2869/* 3005/*
2870 * Callback to setup response of xmit_type of QLA_TGT_XMIT_DATA and * 3006 * Callback to setup response of xmit_type of QLA_TGT_XMIT_DATA and *
2871 * QLA_TGT_XMIT_STATUS for >= 24xx silicon 3007 * QLA_TGT_XMIT_STATUS for >= 24xx silicon
@@ -3113,139 +3249,113 @@ EXPORT_SYMBOL(qlt_rdy_to_xfer);
3113 3249
3114 3250
3115/* 3251/*
3116 * Checks the guard or meta-data for the type of error 3252 * it is assumed either hardware_lock or qpair lock is held.
3117 * detected by the HBA.
3118 */ 3253 */
3119static inline int 3254static void
3120qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd, 3255qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd,
3121 struct ctio_crc_from_fw *sts) 3256 struct ctio_crc_from_fw *sts)
3122{ 3257{
3123 uint8_t *ap = &sts->actual_dif[0]; 3258 uint8_t *ap = &sts->actual_dif[0];
3124 uint8_t *ep = &sts->expected_dif[0]; 3259 uint8_t *ep = &sts->expected_dif[0];
3125 uint32_t e_ref_tag, a_ref_tag;
3126 uint16_t e_app_tag, a_app_tag;
3127 uint16_t e_guard, a_guard;
3128 uint64_t lba = cmd->se_cmd.t_task_lba; 3260 uint64_t lba = cmd->se_cmd.t_task_lba;
3261 uint8_t scsi_status, sense_key, asc, ascq;
3262 unsigned long flags;
3129 3263
3130 a_guard = be16_to_cpu(*(uint16_t *)(ap + 0)); 3264 cmd->trc_flags |= TRC_DIF_ERR;
3131 a_app_tag = be16_to_cpu(*(uint16_t *)(ap + 2));
3132 a_ref_tag = be32_to_cpu(*(uint32_t *)(ap + 4));
3133
3134 e_guard = be16_to_cpu(*(uint16_t *)(ep + 0));
3135 e_app_tag = be16_to_cpu(*(uint16_t *)(ep + 2));
3136 e_ref_tag = be32_to_cpu(*(uint32_t *)(ep + 4));
3137
3138 ql_dbg(ql_dbg_tgt, vha, 0xe075,
3139 "iocb(s) %p Returned STATUS.\n", sts);
3140
3141 ql_dbg(ql_dbg_tgt, vha, 0xf075,
3142 "dif check TGT cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x]\n",
3143 cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba,
3144 a_ref_tag, e_ref_tag, a_app_tag, e_app_tag, a_guard, e_guard);
3145
3146 /*
3147 * Ignore sector if:
3148 * For type 3: ref & app tag is all 'f's
3149 * For type 0,1,2: app tag is all 'f's
3150 */
3151 if ((a_app_tag == 0xffff) &&
3152 ((cmd->se_cmd.prot_type != TARGET_DIF_TYPE3_PROT) ||
3153 (a_ref_tag == 0xffffffff))) {
3154 uint32_t blocks_done;
3155
3156 /* 2TB boundary case covered automatically with this */
3157 blocks_done = e_ref_tag - (uint32_t)lba + 1;
3158 cmd->se_cmd.bad_sector = e_ref_tag;
3159 cmd->se_cmd.pi_err = 0;
3160 ql_dbg(ql_dbg_tgt, vha, 0xf074,
3161 "need to return scsi good\n");
3162
3163 /* Update protection tag */
3164 if (cmd->prot_sg_cnt) {
3165 uint32_t i, k = 0, num_ent;
3166 struct scatterlist *sg, *sgl;
3167
3168 3265
3169 sgl = cmd->prot_sg; 3266 cmd->a_guard = be16_to_cpu(*(uint16_t *)(ap + 0));
3267 cmd->a_app_tag = be16_to_cpu(*(uint16_t *)(ap + 2));
3268 cmd->a_ref_tag = be32_to_cpu(*(uint32_t *)(ap + 4));
3170 3269
3171 /* Patch the corresponding protection tags */ 3270 cmd->e_guard = be16_to_cpu(*(uint16_t *)(ep + 0));
3172 for_each_sg(sgl, sg, cmd->prot_sg_cnt, i) { 3271 cmd->e_app_tag = be16_to_cpu(*(uint16_t *)(ep + 2));
3173 num_ent = sg_dma_len(sg) / 8; 3272 cmd->e_ref_tag = be32_to_cpu(*(uint32_t *)(ep + 4));
3174 if (k + num_ent < blocks_done) {
3175 k += num_ent;
3176 continue;
3177 }
3178 k = blocks_done;
3179 break;
3180 }
3181 3273
3182 if (k != blocks_done) { 3274 ql_dbg(ql_dbg_tgt_dif, vha, 0xf075,
3183 ql_log(ql_log_warn, vha, 0xf076, 3275 "%s: aborted %d state %d\n", __func__, cmd->aborted, cmd->state);
3184 "unexpected tag values tag:lba=%u:%llu)\n",
3185 e_ref_tag, (unsigned long long)lba);
3186 goto out;
3187 }
3188 3276
3189#if 0 3277 scsi_status = sense_key = asc = ascq = 0;
3190 struct sd_dif_tuple *spt;
3191 /* TODO:
3192 * This section came from initiator. Is it valid here?
3193 * should ulp be override with actual val???
3194 */
3195 spt = page_address(sg_page(sg)) + sg->offset;
3196 spt += j;
3197 3278
3198 spt->app_tag = 0xffff; 3279 /* check appl tag */
3199 if (cmd->se_cmd.prot_type == SCSI_PROT_DIF_TYPE3) 3280 if (cmd->e_app_tag != cmd->a_app_tag) {
3200 spt->ref_tag = 0xffffffff; 3281 ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
3201#endif 3282 "App Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] "
3202 } 3283 "Ref[%x|%x], App[%x|%x], "
3203 3284 "Guard [%x|%x] cmd=%p ox_id[%04x]",
3204 return 0; 3285 cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks,
3205 } 3286 cmd->a_ref_tag, cmd->e_ref_tag,
3206 3287 cmd->a_app_tag, cmd->e_app_tag,
3207 /* check guard */ 3288 cmd->a_guard, cmd->e_guard,
3208 if (e_guard != a_guard) { 3289 cmd, cmd->atio.u.isp24.fcp_hdr.ox_id);
3209 cmd->se_cmd.pi_err = TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED; 3290
3210 cmd->se_cmd.bad_sector = cmd->se_cmd.t_task_lba; 3291 cmd->dif_err_code = DIF_ERR_APP;
3211 3292 scsi_status = SAM_STAT_CHECK_CONDITION;
3212 ql_log(ql_log_warn, vha, 0xe076, 3293 sense_key = ABORTED_COMMAND;
3213 "Guard ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n", 3294 asc = 0x10;
3214 cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba, 3295 ascq = 0x2;
3215 a_ref_tag, e_ref_tag, a_app_tag, e_app_tag,
3216 a_guard, e_guard, cmd);
3217 goto out;
3218 } 3296 }
3219 3297
3220 /* check ref tag */ 3298 /* check ref tag */
3221 if (e_ref_tag != a_ref_tag) { 3299 if (cmd->e_ref_tag != cmd->a_ref_tag) {
3222 cmd->se_cmd.pi_err = TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED; 3300 ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
3223 cmd->se_cmd.bad_sector = e_ref_tag; 3301 "Ref Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] "
3224 3302 "Ref[%x|%x], App[%x|%x], "
3225 ql_log(ql_log_warn, vha, 0xe077, 3303 "Guard[%x|%x] cmd=%p ox_id[%04x] ",
3226 "Ref Tag ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n", 3304 cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks,
3227 cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba, 3305 cmd->a_ref_tag, cmd->e_ref_tag,
3228 a_ref_tag, e_ref_tag, a_app_tag, e_app_tag, 3306 cmd->a_app_tag, cmd->e_app_tag,
3229 a_guard, e_guard, cmd); 3307 cmd->a_guard, cmd->e_guard,
3308 cmd, cmd->atio.u.isp24.fcp_hdr.ox_id);
3309
3310 cmd->dif_err_code = DIF_ERR_REF;
3311 scsi_status = SAM_STAT_CHECK_CONDITION;
3312 sense_key = ABORTED_COMMAND;
3313 asc = 0x10;
3314 ascq = 0x3;
3230 goto out; 3315 goto out;
3231 } 3316 }
3232 3317
3233 /* check appl tag */ 3318 /* check guard */
3234 if (e_app_tag != a_app_tag) { 3319 if (cmd->e_guard != cmd->a_guard) {
3235 cmd->se_cmd.pi_err = TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED; 3320 ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
3236 cmd->se_cmd.bad_sector = cmd->se_cmd.t_task_lba; 3321 "Guard ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] "
3237 3322 "Ref[%x|%x], App[%x|%x], "
3238 ql_log(ql_log_warn, vha, 0xe078, 3323 "Guard [%x|%x] cmd=%p ox_id[%04x]",
3239 "App Tag ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n", 3324 cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks,
3240 cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba, 3325 cmd->a_ref_tag, cmd->e_ref_tag,
3241 a_ref_tag, e_ref_tag, a_app_tag, e_app_tag, 3326 cmd->a_app_tag, cmd->e_app_tag,
3242 a_guard, e_guard, cmd); 3327 cmd->a_guard, cmd->e_guard,
3243 goto out; 3328 cmd, cmd->atio.u.isp24.fcp_hdr.ox_id);
3329 cmd->dif_err_code = DIF_ERR_GRD;
3330 scsi_status = SAM_STAT_CHECK_CONDITION;
3331 sense_key = ABORTED_COMMAND;
3332 asc = 0x10;
3333 ascq = 0x1;
3244 } 3334 }
3245out: 3335out:
3246 return 1; 3336 switch (cmd->state) {
3247} 3337 case QLA_TGT_STATE_NEED_DATA:
3338 /* handle_data will load DIF error code */
3339 cmd->state = QLA_TGT_STATE_DATA_IN;
3340 vha->hw->tgt.tgt_ops->handle_data(cmd);
3341 break;
3342 default:
3343 spin_lock_irqsave(&cmd->cmd_lock, flags);
3344 if (cmd->aborted) {
3345 spin_unlock_irqrestore(&cmd->cmd_lock, flags);
3346 vha->hw->tgt.tgt_ops->free_cmd(cmd);
3347 break;
3348 }
3349 spin_unlock_irqrestore(&cmd->cmd_lock, flags);
3248 3350
3351 qlt_send_resp_ctio(vha, cmd, scsi_status, sense_key, asc, ascq);
3352 /* assume scsi status gets out on the wire.
3353 * Will not wait for completion.
3354 */
3355 vha->hw->tgt.tgt_ops->free_cmd(cmd);
3356 break;
3357 }
3358}
3249 3359
3250/* If hardware_lock held on entry, might drop it, then reaquire */ 3360/* If hardware_lock held on entry, might drop it, then reaquire */
3251/* This function sends the appropriate CTIO to ISP 2xxx or 24xx */ 3361/* This function sends the appropriate CTIO to ISP 2xxx or 24xx */
@@ -3552,6 +3662,16 @@ static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio,
3552{ 3662{
3553 int term = 0; 3663 int term = 0;
3554 3664
3665 if (cmd->se_cmd.prot_op)
3666 ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
3667 "Term DIF cmd: lba[0x%llx|%lld] len[0x%x] "
3668 "se_cmd=%p tag[%x] op %#x/%s",
3669 cmd->lba, cmd->lba,
3670 cmd->num_blks, &cmd->se_cmd,
3671 cmd->atio.u.isp24.exchange_addr,
3672 cmd->se_cmd.prot_op,
3673 prot_op_str(cmd->se_cmd.prot_op));
3674
3555 if (ctio != NULL) { 3675 if (ctio != NULL) {
3556 struct ctio7_from_24xx *c = (struct ctio7_from_24xx *)ctio; 3676 struct ctio7_from_24xx *c = (struct ctio7_from_24xx *)ctio;
3557 term = !(c->flags & 3677 term = !(c->flags &
@@ -3769,32 +3889,15 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
3769 struct ctio_crc_from_fw *crc = 3889 struct ctio_crc_from_fw *crc =
3770 (struct ctio_crc_from_fw *)ctio; 3890 (struct ctio_crc_from_fw *)ctio;
3771 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf073, 3891 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf073,
3772 "qla_target(%d): CTIO with DIF_ERROR status %x received (state %x, se_cmd %p) actual_dif[0x%llx] expect_dif[0x%llx]\n", 3892 "qla_target(%d): CTIO with DIF_ERROR status %x "
3893 "received (state %x, ulp_cmd %p) actual_dif[0x%llx] "
3894 "expect_dif[0x%llx]\n",
3773 vha->vp_idx, status, cmd->state, se_cmd, 3895 vha->vp_idx, status, cmd->state, se_cmd,
3774 *((u64 *)&crc->actual_dif[0]), 3896 *((u64 *)&crc->actual_dif[0]),
3775 *((u64 *)&crc->expected_dif[0])); 3897 *((u64 *)&crc->expected_dif[0]));
3776 3898
3777 if (qlt_handle_dif_error(vha, cmd, ctio)) { 3899 qlt_handle_dif_error(vha, cmd, ctio);
3778 if (cmd->state == QLA_TGT_STATE_NEED_DATA) { 3900 return;
3779 /* scsi Write/xfer rdy complete */
3780 goto skip_term;
3781 } else {
3782 /* scsi read/xmit respond complete
3783 * call handle dif to send scsi status
3784 * rather than terminate exchange.
3785 */
3786 cmd->state = QLA_TGT_STATE_PROCESSED;
3787 ha->tgt.tgt_ops->handle_dif_err(cmd);
3788 return;
3789 }
3790 } else {
3791 /* Need to generate a SCSI good completion.
3792 * because FW did not send scsi status.
3793 */
3794 status = 0;
3795 goto skip_term;
3796 }
3797 break;
3798 } 3901 }
3799 default: 3902 default:
3800 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05b, 3903 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05b,
@@ -3817,7 +3920,6 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
3817 return; 3920 return;
3818 } 3921 }
3819 } 3922 }
3820skip_term:
3821 3923
3822 if (cmd->state == QLA_TGT_STATE_PROCESSED) { 3924 if (cmd->state == QLA_TGT_STATE_PROCESSED) {
3823 cmd->trc_flags |= TRC_CTIO_DONE; 3925 cmd->trc_flags |= TRC_CTIO_DONE;
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index a7f90dcaae37..c35f889b94a6 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -378,6 +378,14 @@ static inline void adjust_corrupted_atio(struct atio_from_isp *atio)
378 atio->u.isp24.fcp_cmnd.add_cdb_len = 0; 378 atio->u.isp24.fcp_cmnd.add_cdb_len = 0;
379} 379}
380 380
381static inline int get_datalen_for_atio(struct atio_from_isp *atio)
382{
383 int len = atio->u.isp24.fcp_cmnd.add_cdb_len;
384
385 return (be32_to_cpu(get_unaligned((uint32_t *)
386 &atio->u.isp24.fcp_cmnd.add_cdb[len * 4])));
387}
388
381#define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */ 389#define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */
382 390
383/* 391/*
@@ -667,7 +675,6 @@ struct qla_tgt_func_tmpl {
667 int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *, 675 int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *,
668 unsigned char *, uint32_t, int, int, int); 676 unsigned char *, uint32_t, int, int, int);
669 void (*handle_data)(struct qla_tgt_cmd *); 677 void (*handle_data)(struct qla_tgt_cmd *);
670 void (*handle_dif_err)(struct qla_tgt_cmd *);
671 int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, uint32_t, uint16_t, 678 int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, uint32_t, uint16_t,
672 uint32_t); 679 uint32_t);
673 void (*free_cmd)(struct qla_tgt_cmd *); 680 void (*free_cmd)(struct qla_tgt_cmd *);
@@ -684,6 +691,8 @@ struct qla_tgt_func_tmpl {
684 void (*clear_nacl_from_fcport_map)(struct fc_port *); 691 void (*clear_nacl_from_fcport_map)(struct fc_port *);
685 void (*put_sess)(struct fc_port *); 692 void (*put_sess)(struct fc_port *);
686 void (*shutdown_sess)(struct fc_port *); 693 void (*shutdown_sess)(struct fc_port *);
694 int (*get_dif_tags)(struct qla_tgt_cmd *cmd, uint16_t *pfw_prot_opts);
695 int (*chk_dif_tags)(uint32_t tag);
687}; 696};
688 697
689int qla2x00_wait_for_hba_online(struct scsi_qla_host *); 698int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
@@ -720,8 +729,8 @@ int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
720#define QLA_TGT_ABORT_ALL 0xFFFE 729#define QLA_TGT_ABORT_ALL 0xFFFE
721#define QLA_TGT_NEXUS_LOSS_SESS 0xFFFD 730#define QLA_TGT_NEXUS_LOSS_SESS 0xFFFD
722#define QLA_TGT_NEXUS_LOSS 0xFFFC 731#define QLA_TGT_NEXUS_LOSS 0xFFFC
723#define QLA_TGT_ABTS 0xFFFB 732#define QLA_TGT_ABTS 0xFFFB
724#define QLA_TGT_2G_ABORT_TASK 0xFFFA 733#define QLA_TGT_2G_ABORT_TASK 0xFFFA
725 734
726/* Notify Acknowledge flags */ 735/* Notify Acknowledge flags */
727#define NOTIFY_ACK_RES_COUNT BIT_8 736#define NOTIFY_ACK_RES_COUNT BIT_8
@@ -845,6 +854,7 @@ enum trace_flags {
845 TRC_CMD_FREE = BIT_17, 854 TRC_CMD_FREE = BIT_17,
846 TRC_DATA_IN = BIT_18, 855 TRC_DATA_IN = BIT_18,
847 TRC_ABORT = BIT_19, 856 TRC_ABORT = BIT_19,
857 TRC_DIF_ERR = BIT_20,
848}; 858};
849 859
850struct qla_tgt_cmd { 860struct qla_tgt_cmd {
@@ -862,7 +872,6 @@ struct qla_tgt_cmd {
862 unsigned int sg_mapped:1; 872 unsigned int sg_mapped:1;
863 unsigned int free_sg:1; 873 unsigned int free_sg:1;
864 unsigned int write_data_transferred:1; 874 unsigned int write_data_transferred:1;
865 unsigned int ctx_dsd_alloced:1;
866 unsigned int q_full:1; 875 unsigned int q_full:1;
867 unsigned int term_exchg:1; 876 unsigned int term_exchg:1;
868 unsigned int cmd_sent_to_fw:1; 877 unsigned int cmd_sent_to_fw:1;
@@ -885,11 +894,25 @@ struct qla_tgt_cmd {
885 struct list_head cmd_list; 894 struct list_head cmd_list;
886 895
887 struct atio_from_isp atio; 896 struct atio_from_isp atio;
888 /* t10dif */ 897
898 uint8_t ctx_dsd_alloced;
899
900 /* T10-DIF */
901#define DIF_ERR_NONE 0
902#define DIF_ERR_GRD 1
903#define DIF_ERR_REF 2
904#define DIF_ERR_APP 3
905 int8_t dif_err_code;
889 struct scatterlist *prot_sg; 906 struct scatterlist *prot_sg;
890 uint32_t prot_sg_cnt; 907 uint32_t prot_sg_cnt;
891 uint32_t blk_sz; 908 uint32_t blk_sz, num_blks;
909 uint8_t scsi_status, sense_key, asc, ascq;
910
892 struct crc_context *ctx; 911 struct crc_context *ctx;
912 uint8_t *cdb;
913 uint64_t lba;
914 uint16_t a_guard, e_guard, a_app_tag, e_app_tag;
915 uint32_t a_ref_tag, e_ref_tag;
893 916
894 uint64_t jiffies_at_alloc; 917 uint64_t jiffies_at_alloc;
895 uint64_t jiffies_at_free; 918 uint64_t jiffies_at_free;
@@ -1053,4 +1076,7 @@ extern int qlt_free_qfull_cmds(struct scsi_qla_host *);
1053extern void qlt_logo_completion_handler(fc_port_t *, int); 1076extern void qlt_logo_completion_handler(fc_port_t *, int);
1054extern void qlt_do_generation_tick(struct scsi_qla_host *, int *); 1077extern void qlt_do_generation_tick(struct scsi_qla_host *, int *);
1055 1078
1079void qlt_send_resp_ctio(scsi_qla_host_t *, struct qla_tgt_cmd *, uint8_t,
1080 uint8_t, uint8_t, uint8_t);
1081
1056#endif /* __QLA_TARGET_H */ 1082#endif /* __QLA_TARGET_H */
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 8e8ab0fa9672..7443e4efa3ae 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -531,6 +531,24 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
531 return; 531 return;
532 } 532 }
533 533
534 switch (cmd->dif_err_code) {
535 case DIF_ERR_GRD:
536 cmd->se_cmd.pi_err =
537 TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED;
538 break;
539 case DIF_ERR_REF:
540 cmd->se_cmd.pi_err =
541 TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED;
542 break;
543 case DIF_ERR_APP:
544 cmd->se_cmd.pi_err =
545 TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED;
546 break;
547 case DIF_ERR_NONE:
548 default:
549 break;
550 }
551
534 if (cmd->se_cmd.pi_err) 552 if (cmd->se_cmd.pi_err)
535 transport_generic_request_failure(&cmd->se_cmd, 553 transport_generic_request_failure(&cmd->se_cmd,
536 cmd->se_cmd.pi_err); 554 cmd->se_cmd.pi_err);
@@ -555,25 +573,23 @@ static void tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd)
555 queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work); 573 queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work);
556} 574}
557 575
558static void tcm_qla2xxx_handle_dif_work(struct work_struct *work) 576static int tcm_qla2xxx_chk_dif_tags(uint32_t tag)
559{ 577{
560 struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); 578 return 0;
561
562 /* take an extra kref to prevent cmd free too early.
563 * need to wait for SCSI status/check condition to
564 * finish responding generate by transport_generic_request_failure.
565 */
566 kref_get(&cmd->se_cmd.cmd_kref);
567 transport_generic_request_failure(&cmd->se_cmd, cmd->se_cmd.pi_err);
568} 579}
569 580
570/* 581static int tcm_qla2xxx_dif_tags(struct qla_tgt_cmd *cmd,
571 * Called from qla_target.c:qlt_do_ctio_completion() 582 uint16_t *pfw_prot_opts)
572 */
573static void tcm_qla2xxx_handle_dif_err(struct qla_tgt_cmd *cmd)
574{ 583{
575 INIT_WORK(&cmd->work, tcm_qla2xxx_handle_dif_work); 584 struct se_cmd *se_cmd = &cmd->se_cmd;
576 queue_work(tcm_qla2xxx_free_wq, &cmd->work); 585
586 if (!(se_cmd->prot_checks & TARGET_DIF_CHECK_GUARD))
587 *pfw_prot_opts |= PO_DISABLE_GUARD_CHECK;
588
589 if (!(se_cmd->prot_checks & TARGET_DIF_CHECK_APPTAG))
590 *pfw_prot_opts |= PO_DIS_APP_TAG_VALD;
591
592 return 0;
577} 593}
578 594
579/* 595/*
@@ -1610,7 +1626,6 @@ static void tcm_qla2xxx_update_sess(struct fc_port *sess, port_id_t s_id,
1610static struct qla_tgt_func_tmpl tcm_qla2xxx_template = { 1626static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
1611 .handle_cmd = tcm_qla2xxx_handle_cmd, 1627 .handle_cmd = tcm_qla2xxx_handle_cmd,
1612 .handle_data = tcm_qla2xxx_handle_data, 1628 .handle_data = tcm_qla2xxx_handle_data,
1613 .handle_dif_err = tcm_qla2xxx_handle_dif_err,
1614 .handle_tmr = tcm_qla2xxx_handle_tmr, 1629 .handle_tmr = tcm_qla2xxx_handle_tmr,
1615 .free_cmd = tcm_qla2xxx_free_cmd, 1630 .free_cmd = tcm_qla2xxx_free_cmd,
1616 .free_mcmd = tcm_qla2xxx_free_mcmd, 1631 .free_mcmd = tcm_qla2xxx_free_mcmd,
@@ -1622,6 +1637,8 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
1622 .clear_nacl_from_fcport_map = tcm_qla2xxx_clear_nacl_from_fcport_map, 1637 .clear_nacl_from_fcport_map = tcm_qla2xxx_clear_nacl_from_fcport_map,
1623 .put_sess = tcm_qla2xxx_put_sess, 1638 .put_sess = tcm_qla2xxx_put_sess,
1624 .shutdown_sess = tcm_qla2xxx_shutdown_sess, 1639 .shutdown_sess = tcm_qla2xxx_shutdown_sess,
1640 .get_dif_tags = tcm_qla2xxx_dif_tags,
1641 .chk_dif_tags = tcm_qla2xxx_chk_dif_tags,
1625}; 1642};
1626 1643
1627static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport) 1644static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport)