aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_iocb.c
diff options
context:
space:
mode:
authorQuinn Tran <quinn.tran@qlogic.com>2014-04-11 16:54:43 -0400
committerChristoph Hellwig <hch@lst.de>2014-05-19 07:31:05 -0400
commitf83adb617f55be13046191d83fa9110ff0689406 (patch)
tree79975dd317761859016a96e573f0fde2ff82b1c6 /drivers/scsi/qla2xxx/qla_iocb.c
parent5921cda6c1a402bacbfa5c97bbb7039eb0fd9dd8 (diff)
qla2xxx: T10-Dif: add T10-PI support
Add support for T10-Dif for Target Mode to qla driver. The driver will look for firmware attribute that support this feature. When the feature is present, the capabilities will be report to TCM layer. Add CTIO CRC2 iocb to build T10-Dif commands. Add support routines to process good & error cases. Signed-off-by: Quinn Tran <quinn.tran@qlogic.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org> Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_iocb.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c134
1 files changed, 99 insertions, 35 deletions
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index af83132141f7..760931529592 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -936,9 +936,9 @@ qla24xx_get_one_block_sg(uint32_t blk_sz, struct qla2_sgx *sgx,
936 return 1; 936 return 1;
937} 937}
938 938
939static int 939int
940qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp, 940qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp,
941 uint32_t *dsd, uint16_t tot_dsds) 941 uint32_t *dsd, uint16_t tot_dsds, struct qla_tgt_cmd *tc)
942{ 942{
943 void *next_dsd; 943 void *next_dsd;
944 uint8_t avail_dsds = 0; 944 uint8_t avail_dsds = 0;
@@ -948,21 +948,35 @@ qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp,
948 uint32_t *cur_dsd = dsd; 948 uint32_t *cur_dsd = dsd;
949 uint16_t used_dsds = tot_dsds; 949 uint16_t used_dsds = tot_dsds;
950 950
951 uint32_t prot_int; 951 uint32_t prot_int; /* protection interval */
952 uint32_t partial; 952 uint32_t partial;
953 struct qla2_sgx sgx; 953 struct qla2_sgx sgx;
954 dma_addr_t sle_dma; 954 dma_addr_t sle_dma;
955 uint32_t sle_dma_len, tot_prot_dma_len = 0; 955 uint32_t sle_dma_len, tot_prot_dma_len = 0;
956 struct scsi_cmnd *cmd = GET_CMD_SP(sp); 956 struct scsi_cmnd *cmd;
957 957 struct scsi_qla_host *vha;
958 prot_int = cmd->device->sector_size;
959 958
960 memset(&sgx, 0, sizeof(struct qla2_sgx)); 959 memset(&sgx, 0, sizeof(struct qla2_sgx));
961 sgx.tot_bytes = scsi_bufflen(cmd); 960 if (sp) {
962 sgx.cur_sg = scsi_sglist(cmd); 961 vha = sp->fcport->vha;
963 sgx.sp = sp; 962 cmd = GET_CMD_SP(sp);
964 963 prot_int = cmd->device->sector_size;
965 sg_prot = scsi_prot_sglist(cmd); 964
965 sgx.tot_bytes = scsi_bufflen(cmd);
966 sgx.cur_sg = scsi_sglist(cmd);
967 sgx.sp = sp;
968
969 sg_prot = scsi_prot_sglist(cmd);
970 } else if (tc) {
971 vha = tc->vha;
972 prot_int = tc->blk_sz;
973 sgx.tot_bytes = tc->bufflen;
974 sgx.cur_sg = tc->sg;
975 sg_prot = tc->prot_sg;
976 } else {
977 BUG();
978 return 1;
979 }
966 980
967 while (qla24xx_get_one_block_sg(prot_int, &sgx, &partial)) { 981 while (qla24xx_get_one_block_sg(prot_int, &sgx, &partial)) {
968 982
@@ -995,10 +1009,18 @@ alloc_and_fill:
995 return 1; 1009 return 1;
996 } 1010 }
997 1011
998 list_add_tail(&dsd_ptr->list, 1012 if (sp) {
999 &((struct crc_context *)sp->u.scmd.ctx)->dsd_list); 1013 list_add_tail(&dsd_ptr->list,
1014 &((struct crc_context *)
1015 sp->u.scmd.ctx)->dsd_list);
1016
1017 sp->flags |= SRB_CRC_CTX_DSD_VALID;
1018 } else {
1019 list_add_tail(&dsd_ptr->list,
1020 &(tc->ctx->dsd_list));
1021 tc->ctx_dsd_alloced = 1;
1022 }
1000 1023
1001 sp->flags |= SRB_CRC_CTX_DSD_VALID;
1002 1024
1003 /* add new list to cmd iocb or last list */ 1025 /* add new list to cmd iocb or last list */
1004 *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); 1026 *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
@@ -1033,21 +1055,35 @@ alloc_and_fill:
1033 return 0; 1055 return 0;
1034} 1056}
1035 1057
1036static int 1058int
1037qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, 1059qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
1038 uint16_t tot_dsds) 1060 uint16_t tot_dsds, struct qla_tgt_cmd *tc)
1039{ 1061{
1040 void *next_dsd; 1062 void *next_dsd;
1041 uint8_t avail_dsds = 0; 1063 uint8_t avail_dsds = 0;
1042 uint32_t dsd_list_len; 1064 uint32_t dsd_list_len;
1043 struct dsd_dma *dsd_ptr; 1065 struct dsd_dma *dsd_ptr;
1044 struct scatterlist *sg; 1066 struct scatterlist *sg, *sgl;
1045 uint32_t *cur_dsd = dsd; 1067 uint32_t *cur_dsd = dsd;
1046 int i; 1068 int i;
1047 uint16_t used_dsds = tot_dsds; 1069 uint16_t used_dsds = tot_dsds;
1048 struct scsi_cmnd *cmd = GET_CMD_SP(sp); 1070 struct scsi_cmnd *cmd;
1071 struct scsi_qla_host *vha;
1072
1073 if (sp) {
1074 cmd = GET_CMD_SP(sp);
1075 sgl = scsi_sglist(cmd);
1076 vha = sp->fcport->vha;
1077 } else if (tc) {
1078 sgl = tc->sg;
1079 vha = tc->vha;
1080 } else {
1081 BUG();
1082 return 1;
1083 }
1049 1084
1050 scsi_for_each_sg(cmd, sg, tot_dsds, i) { 1085
1086 for_each_sg(sgl, sg, tot_dsds, i) {
1051 dma_addr_t sle_dma; 1087 dma_addr_t sle_dma;
1052 1088
1053 /* Allocate additional continuation packets? */ 1089 /* Allocate additional continuation packets? */
@@ -1076,10 +1112,17 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
1076 return 1; 1112 return 1;
1077 } 1113 }
1078 1114
1079 list_add_tail(&dsd_ptr->list, 1115 if (sp) {
1080 &((struct crc_context *)sp->u.scmd.ctx)->dsd_list); 1116 list_add_tail(&dsd_ptr->list,
1117 &((struct crc_context *)
1118 sp->u.scmd.ctx)->dsd_list);
1081 1119
1082 sp->flags |= SRB_CRC_CTX_DSD_VALID; 1120 sp->flags |= SRB_CRC_CTX_DSD_VALID;
1121 } else {
1122 list_add_tail(&dsd_ptr->list,
1123 &(tc->ctx->dsd_list));
1124 tc->ctx_dsd_alloced = 1;
1125 }
1083 1126
1084 /* add new list to cmd iocb or last list */ 1127 /* add new list to cmd iocb or last list */
1085 *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); 1128 *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
@@ -1102,23 +1145,37 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
1102 return 0; 1145 return 0;
1103} 1146}
1104 1147
1105static int 1148int
1106qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, 1149qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
1107 uint32_t *dsd, 1150 uint32_t *dsd, uint16_t tot_dsds, struct qla_tgt_cmd *tc)
1108 uint16_t tot_dsds)
1109{ 1151{
1110 void *next_dsd; 1152 void *next_dsd;
1111 uint8_t avail_dsds = 0; 1153 uint8_t avail_dsds = 0;
1112 uint32_t dsd_list_len; 1154 uint32_t dsd_list_len;
1113 struct dsd_dma *dsd_ptr; 1155 struct dsd_dma *dsd_ptr;
1114 struct scatterlist *sg; 1156 struct scatterlist *sg, *sgl;
1115 int i; 1157 int i;
1116 struct scsi_cmnd *cmd; 1158 struct scsi_cmnd *cmd;
1117 uint32_t *cur_dsd = dsd; 1159 uint32_t *cur_dsd = dsd;
1118 uint16_t used_dsds = tot_dsds; 1160 uint16_t used_dsds = tot_dsds;
1161 struct scsi_qla_host *vha;
1162
1163 if (sp) {
1164 cmd = GET_CMD_SP(sp);
1165 sgl = scsi_prot_sglist(cmd);
1166 vha = sp->fcport->vha;
1167 } else if (tc) {
1168 vha = tc->vha;
1169 sgl = tc->prot_sg;
1170 } else {
1171 BUG();
1172 return 1;
1173 }
1119 1174
1120 cmd = GET_CMD_SP(sp); 1175 ql_dbg(ql_dbg_tgt, vha, 0xe021,
1121 scsi_for_each_prot_sg(cmd, sg, tot_dsds, i) { 1176 "%s: enter\n", __func__);
1177
1178 for_each_sg(sgl, sg, tot_dsds, i) {
1122 dma_addr_t sle_dma; 1179 dma_addr_t sle_dma;
1123 1180
1124 /* Allocate additional continuation packets? */ 1181 /* Allocate additional continuation packets? */
@@ -1147,10 +1204,17 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
1147 return 1; 1204 return 1;
1148 } 1205 }
1149 1206
1150 list_add_tail(&dsd_ptr->list, 1207 if (sp) {
1151 &((struct crc_context *)sp->u.scmd.ctx)->dsd_list); 1208 list_add_tail(&dsd_ptr->list,
1209 &((struct crc_context *)
1210 sp->u.scmd.ctx)->dsd_list);
1152 1211
1153 sp->flags |= SRB_CRC_CTX_DSD_VALID; 1212 sp->flags |= SRB_CRC_CTX_DSD_VALID;
1213 } else {
1214 list_add_tail(&dsd_ptr->list,
1215 &(tc->ctx->dsd_list));
1216 tc->ctx_dsd_alloced = 1;
1217 }
1154 1218
1155 /* add new list to cmd iocb or last list */ 1219 /* add new list to cmd iocb or last list */
1156 *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); 1220 *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
@@ -1386,10 +1450,10 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
1386 1450
1387 if (!bundling && tot_prot_dsds) { 1451 if (!bundling && tot_prot_dsds) {
1388 if (qla24xx_walk_and_build_sglist_no_difb(ha, sp, 1452 if (qla24xx_walk_and_build_sglist_no_difb(ha, sp,
1389 cur_dsd, tot_dsds)) 1453 cur_dsd, tot_dsds, NULL))
1390 goto crc_queuing_error; 1454 goto crc_queuing_error;
1391 } else if (qla24xx_walk_and_build_sglist(ha, sp, cur_dsd, 1455 } else if (qla24xx_walk_and_build_sglist(ha, sp, cur_dsd,
1392 (tot_dsds - tot_prot_dsds))) 1456 (tot_dsds - tot_prot_dsds), NULL))
1393 goto crc_queuing_error; 1457 goto crc_queuing_error;
1394 1458
1395 if (bundling && tot_prot_dsds) { 1459 if (bundling && tot_prot_dsds) {
@@ -1398,7 +1462,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
1398 __constant_cpu_to_le16(CF_DIF_SEG_DESCR_ENABLE); 1462 __constant_cpu_to_le16(CF_DIF_SEG_DESCR_ENABLE);
1399 cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address; 1463 cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address;
1400 if (qla24xx_walk_and_build_prot_sglist(ha, sp, cur_dsd, 1464 if (qla24xx_walk_and_build_prot_sglist(ha, sp, cur_dsd,
1401 tot_prot_dsds)) 1465 tot_prot_dsds, NULL))
1402 goto crc_queuing_error; 1466 goto crc_queuing_error;
1403 } 1467 }
1404 return QLA_SUCCESS; 1468 return QLA_SUCCESS;