diff options
| author | Quinn Tran <quinn.tran@cavium.com> | 2017-03-15 12:48:49 -0400 |
|---|---|---|
| committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2017-03-18 20:28:36 -0400 |
| commit | be25152c0d9e236076323abbe9def9714234b761 (patch) | |
| tree | fcdda94e20887fafd1e405b08734ffd2e04749e1 | |
| parent | 5b33469a055c77001fd2c62b0f985c991b0e5b65 (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.h | 1 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 10 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 6 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 13 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_target.c | 540 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_target.h | 38 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/tcm_qla2xxx.c | 49 |
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 | ||
| 352 | extern int qla27xx_dump_mpi_ram(struct qla_hw_data *, uint32_t, uint32_t *, | 353 | extern 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 | ||
| 3130 | struct 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 *); | |||
| 256 | extern void *qla2x00_alloc_iocbs(scsi_qla_host_t *, srb_t *); | 256 | extern void *qla2x00_alloc_iocbs(scsi_qla_host_t *, srb_t *); |
| 257 | extern int qla2x00_issue_marker(scsi_qla_host_t *, int); | 257 | extern int qla2x00_issue_marker(scsi_qla_host_t *, int); |
| 258 | extern int qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *, srb_t *, | 258 | extern 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 *); |
| 260 | extern int qla24xx_walk_and_build_sglist(struct qla_hw_data *, srb_t *, | 260 | extern 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 *); |
| 262 | extern int qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *, srb_t *, | 262 | extern 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 *); |
| 264 | extern int qla24xx_get_one_block_sg(uint32_t, struct qla2_sgx *, uint32_t *); | 264 | extern int qla24xx_get_one_block_sg(uint32_t, struct qla2_sgx *, uint32_t *); |
| 265 | extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *); | 265 | extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *); |
| 266 | extern int qla24xx_build_scsi_crc_2_iocbs(srb_t *, | 266 | extern 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 | ||
| 890 | int | 890 | int |
| 891 | qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp, | 891 | qla24xx_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 | ||
| 1006 | int | 1005 | int |
| 1007 | qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, | 1006 | qla24xx_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 | ||
| 1093 | int | 1092 | int |
| 1094 | qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, | 1093 | qla24xx_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; | |||
| 143 | static DEFINE_MUTEX(qla_tgt_mutex); | 143 | static DEFINE_MUTEX(qla_tgt_mutex); |
| 144 | static LIST_HEAD(qla_tgt_glist); | 144 | static LIST_HEAD(qla_tgt_glist); |
| 145 | 145 | ||
| 146 | static 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 */ |
| 148 | void qlt_do_generation_tick(struct scsi_qla_host *vha, int *dest) | 162 | void 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 | } |
| 2023 | EXPORT_SYMBOL(qlt_free_mcmd); | 2037 | EXPORT_SYMBOL(qlt_free_mcmd); |
| 2024 | 2038 | ||
| 2039 | /* | ||
| 2040 | * ha->hardware_lock supposed to be held on entry. Might drop it, then | ||
| 2041 | * reacquire | ||
| 2042 | */ | ||
| 2043 | void 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); | ||
| 2099 | out: | ||
| 2100 | return; | ||
| 2101 | } | ||
| 2102 | |||
| 2025 | /* callback from target fabric module code */ | 2103 | /* callback from target fabric module code */ |
| 2026 | void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd) | 2104 | void 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 | ||
| 2481 | static 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 */ | ||
| 2552 | static inline int | 2662 | static inline int |
| 2553 | qlt_hba_err_chk_enabled(struct se_cmd *se_cmd) | 2663 | qlt_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 | ||
| 2685 | static inline int | ||
| 2686 | qla_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 | */ |
| 2586 | static inline void | 2705 | static void |
| 2587 | qlt_set_t10dif_tags(struct se_cmd *se_cmd, struct crc_context *ctx) | 2706 | qla_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 | |||
| 2658 | static inline int | 2791 | static inline int |
| 2659 | qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha) | 2792 | qlt_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 | ||
| 2862 | crc_queuing_error: | 2998 | crc_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 | */ |
| 3119 | static inline int | 3254 | static void |
| 3120 | qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd, | 3255 | qlt_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 | } |
| 3245 | out: | 3335 | out: |
| 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 | } |
| 3820 | skip_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 | ||
| 381 | static 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 | ||
| 689 | int qla2x00_wait_for_hba_online(struct scsi_qla_host *); | 698 | int 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 | ||
| 850 | struct qla_tgt_cmd { | 860 | struct 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 *); | |||
| 1053 | extern void qlt_logo_completion_handler(fc_port_t *, int); | 1076 | extern void qlt_logo_completion_handler(fc_port_t *, int); |
| 1054 | extern void qlt_do_generation_tick(struct scsi_qla_host *, int *); | 1077 | extern void qlt_do_generation_tick(struct scsi_qla_host *, int *); |
| 1055 | 1078 | ||
| 1079 | void 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 | ||
| 558 | static void tcm_qla2xxx_handle_dif_work(struct work_struct *work) | 576 | static 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 | /* | 581 | static 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 | */ | ||
| 573 | static 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, | |||
| 1610 | static struct qla_tgt_func_tmpl tcm_qla2xxx_template = { | 1626 | static 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 | ||
| 1627 | static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport) | 1644 | static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport) |
