diff options
author | Martin K. Petersen <martin.petersen@oracle.com> | 2019-01-15 19:50:00 -0500 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2019-01-22 21:18:27 -0500 |
commit | 78a02f49d0eb978b5eb85ffdf5f11582ac83c754 (patch) | |
tree | 50a241151a1ee3e1240e18ff9f1d1cab9b0b6193 /drivers/scsi/sd.c | |
parent | ec029758a10095c66fd24398f742c695c2e6ec2c (diff) |
scsi: sd: Create helper functions for read/write commands
Create a helper function for each of the 6, 10, 16 and 32-byte READ/WRITE
variants and use those when setting up reads and writes.
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
[ bvanassche: ported this patch from kernel v4.11 to kernel v5.0 and made
function names shorter. ]
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 167 |
1 files changed, 92 insertions, 75 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 13d2137b94b1..53093a34b1fc 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -1072,6 +1072,83 @@ static blk_status_t sd_setup_flush_cmnd(struct scsi_cmnd *cmd) | |||
1072 | return BLK_STS_OK; | 1072 | return BLK_STS_OK; |
1073 | } | 1073 | } |
1074 | 1074 | ||
1075 | static blk_status_t sd_setup_rw32_cmnd(struct scsi_cmnd *cmd, bool write, | ||
1076 | sector_t lba, unsigned int nr_blocks, | ||
1077 | unsigned char flags) | ||
1078 | { | ||
1079 | cmd->cmnd = mempool_alloc(sd_cdb_pool, GFP_ATOMIC); | ||
1080 | if (unlikely(cmd->cmnd == NULL)) | ||
1081 | return BLK_STS_RESOURCE; | ||
1082 | |||
1083 | cmd->cmd_len = SD_EXT_CDB_SIZE; | ||
1084 | memset(cmd->cmnd, 0, cmd->cmd_len); | ||
1085 | |||
1086 | cmd->cmnd[0] = VARIABLE_LENGTH_CMD; | ||
1087 | cmd->cmnd[7] = 0x18; /* Additional CDB len */ | ||
1088 | cmd->cmnd[9] = write ? WRITE_32 : READ_32; | ||
1089 | cmd->cmnd[10] = flags; | ||
1090 | put_unaligned_be64(lba, &cmd->cmnd[12]); | ||
1091 | put_unaligned_be32(lba, &cmd->cmnd[20]); /* Expected Indirect LBA */ | ||
1092 | put_unaligned_be32(nr_blocks, &cmd->cmnd[28]); | ||
1093 | |||
1094 | return BLK_STS_OK; | ||
1095 | } | ||
1096 | |||
1097 | static blk_status_t sd_setup_rw16_cmnd(struct scsi_cmnd *cmd, bool write, | ||
1098 | sector_t lba, unsigned int nr_blocks, | ||
1099 | unsigned char flags) | ||
1100 | { | ||
1101 | cmd->cmd_len = 16; | ||
1102 | cmd->cmnd[0] = write ? WRITE_16 : READ_16; | ||
1103 | cmd->cmnd[1] = flags; | ||
1104 | cmd->cmnd[14] = 0; | ||
1105 | cmd->cmnd[15] = 0; | ||
1106 | put_unaligned_be64(lba, &cmd->cmnd[2]); | ||
1107 | put_unaligned_be32(nr_blocks, &cmd->cmnd[10]); | ||
1108 | |||
1109 | return BLK_STS_OK; | ||
1110 | } | ||
1111 | |||
1112 | static blk_status_t sd_setup_rw10_cmnd(struct scsi_cmnd *cmd, bool write, | ||
1113 | sector_t lba, unsigned int nr_blocks, | ||
1114 | unsigned char flags) | ||
1115 | { | ||
1116 | cmd->cmd_len = 10; | ||
1117 | cmd->cmnd[0] = write ? WRITE_10 : READ_10; | ||
1118 | cmd->cmnd[1] = flags; | ||
1119 | cmd->cmnd[6] = 0; | ||
1120 | cmd->cmnd[9] = 0; | ||
1121 | put_unaligned_be32(lba, &cmd->cmnd[2]); | ||
1122 | put_unaligned_be16(nr_blocks, &cmd->cmnd[7]); | ||
1123 | |||
1124 | return BLK_STS_OK; | ||
1125 | } | ||
1126 | |||
1127 | static blk_status_t sd_setup_rw6_cmnd(struct scsi_cmnd *cmd, bool write, | ||
1128 | sector_t lba, unsigned int nr_blocks, | ||
1129 | unsigned char flags) | ||
1130 | { | ||
1131 | if (unlikely(flags & 0x8)) { | ||
1132 | /* | ||
1133 | * This happens only if this drive failed 10byte rw | ||
1134 | * command with ILLEGAL_REQUEST during operation and | ||
1135 | * thus turned off use_10_for_rw. | ||
1136 | */ | ||
1137 | scmd_printk(KERN_ERR, cmd, "FUA write on READ/WRITE(6) drive\n"); | ||
1138 | return BLK_STS_IOERR; | ||
1139 | } | ||
1140 | |||
1141 | cmd->cmd_len = 6; | ||
1142 | cmd->cmnd[0] = write ? WRITE_6 : READ_6; | ||
1143 | cmd->cmnd[1] = (lba >> 16) & 0x1f; | ||
1144 | cmd->cmnd[2] = (lba >> 8) & 0xff; | ||
1145 | cmd->cmnd[3] = lba & 0xff; | ||
1146 | cmd->cmnd[4] = nr_blocks; | ||
1147 | cmd->cmnd[5] = 0; | ||
1148 | |||
1149 | return BLK_STS_OK; | ||
1150 | } | ||
1151 | |||
1075 | static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) | 1152 | static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) |
1076 | { | 1153 | { |
1077 | struct request *rq = SCpnt->request; | 1154 | struct request *rq = SCpnt->request; |
@@ -1083,7 +1160,8 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) | |||
1083 | unsigned int nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); | 1160 | unsigned int nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); |
1084 | unsigned int dif, dix; | 1161 | unsigned int dif, dix; |
1085 | unsigned int mask = logical_to_sectors(sdp, 1) - 1; | 1162 | unsigned int mask = logical_to_sectors(sdp, 1) - 1; |
1086 | unsigned char protect; | 1163 | bool write = rq_data_dir(rq) == WRITE; |
1164 | unsigned char protect, fua; | ||
1087 | blk_status_t ret; | 1165 | blk_status_t ret; |
1088 | 1166 | ||
1089 | ret = scsi_init_io(SCpnt); | 1167 | ret = scsi_init_io(SCpnt); |
@@ -1158,6 +1236,7 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) | |||
1158 | "writing" : "reading", nr_blocks, | 1236 | "writing" : "reading", nr_blocks, |
1159 | blk_rq_sectors(rq))); | 1237 | blk_rq_sectors(rq))); |
1160 | 1238 | ||
1239 | fua = rq->cmd_flags & REQ_FUA ? 0x8 : 0; | ||
1161 | dix = scsi_prot_sg_count(SCpnt); | 1240 | dix = scsi_prot_sg_count(SCpnt); |
1162 | dif = scsi_host_dif_capable(SCpnt->device->host, sdkp->protection_type); | 1241 | dif = scsi_host_dif_capable(SCpnt->device->host, sdkp->protection_type); |
1163 | 1242 | ||
@@ -1167,86 +1246,24 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) | |||
1167 | protect = 0; | 1246 | protect = 0; |
1168 | 1247 | ||
1169 | if (protect && sdkp->protection_type == T10_PI_TYPE2_PROTECTION) { | 1248 | if (protect && sdkp->protection_type == T10_PI_TYPE2_PROTECTION) { |
1170 | SCpnt->cmnd = mempool_alloc(sd_cdb_pool, GFP_ATOMIC); | 1249 | ret = sd_setup_rw32_cmnd(SCpnt, write, lba, nr_blocks, |
1171 | 1250 | protect | fua); | |
1172 | if (unlikely(!SCpnt->cmnd)) | ||
1173 | return BLK_STS_RESOURCE; | ||
1174 | |||
1175 | SCpnt->cmd_len = SD_EXT_CDB_SIZE; | ||
1176 | memset(SCpnt->cmnd, 0, SCpnt->cmd_len); | ||
1177 | SCpnt->cmnd[0] = VARIABLE_LENGTH_CMD; | ||
1178 | SCpnt->cmnd[7] = 0x18; | ||
1179 | SCpnt->cmnd[9] = (rq_data_dir(rq) == READ) ? READ_32 : WRITE_32; | ||
1180 | SCpnt->cmnd[10] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); | ||
1181 | |||
1182 | /* LBA */ | ||
1183 | SCpnt->cmnd[12] = sizeof(lba) > 4 ? (unsigned char) (lba >> 56) & 0xff : 0; | ||
1184 | SCpnt->cmnd[13] = sizeof(lba) > 4 ? (unsigned char) (lba >> 48) & 0xff : 0; | ||
1185 | SCpnt->cmnd[14] = sizeof(lba) > 4 ? (unsigned char) (lba >> 40) & 0xff : 0; | ||
1186 | SCpnt->cmnd[15] = sizeof(lba) > 4 ? (unsigned char) (lba >> 32) & 0xff : 0; | ||
1187 | SCpnt->cmnd[16] = (unsigned char) (lba >> 24) & 0xff; | ||
1188 | SCpnt->cmnd[17] = (unsigned char) (lba >> 16) & 0xff; | ||
1189 | SCpnt->cmnd[18] = (unsigned char) (lba >> 8) & 0xff; | ||
1190 | SCpnt->cmnd[19] = (unsigned char) lba & 0xff; | ||
1191 | |||
1192 | /* Expected Indirect LBA */ | ||
1193 | SCpnt->cmnd[20] = (unsigned char) (lba >> 24) & 0xff; | ||
1194 | SCpnt->cmnd[21] = (unsigned char) (lba >> 16) & 0xff; | ||
1195 | SCpnt->cmnd[22] = (unsigned char) (lba >> 8) & 0xff; | ||
1196 | SCpnt->cmnd[23] = (unsigned char) lba & 0xff; | ||
1197 | |||
1198 | /* Transfer length */ | ||
1199 | SCpnt->cmnd[28] = (unsigned char) (nr_blocks >> 24) & 0xff; | ||
1200 | SCpnt->cmnd[29] = (unsigned char) (nr_blocks >> 16) & 0xff; | ||
1201 | SCpnt->cmnd[30] = (unsigned char) (nr_blocks >> 8) & 0xff; | ||
1202 | SCpnt->cmnd[31] = (unsigned char) nr_blocks & 0xff; | ||
1203 | } else if (sdp->use_16_for_rw || (nr_blocks > 0xffff)) { | 1251 | } else if (sdp->use_16_for_rw || (nr_blocks > 0xffff)) { |
1204 | SCpnt->cmnd[0] += READ_16 - READ_6; | 1252 | ret = sd_setup_rw16_cmnd(SCpnt, write, lba, nr_blocks, |
1205 | SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); | 1253 | protect | fua); |
1206 | SCpnt->cmnd[2] = sizeof(lba) > 4 ? (unsigned char) (lba >> 56) & 0xff : 0; | ||
1207 | SCpnt->cmnd[3] = sizeof(lba) > 4 ? (unsigned char) (lba >> 48) & 0xff : 0; | ||
1208 | SCpnt->cmnd[4] = sizeof(lba) > 4 ? (unsigned char) (lba >> 40) & 0xff : 0; | ||
1209 | SCpnt->cmnd[5] = sizeof(lba) > 4 ? (unsigned char) (lba >> 32) & 0xff : 0; | ||
1210 | SCpnt->cmnd[6] = (unsigned char) (lba >> 24) & 0xff; | ||
1211 | SCpnt->cmnd[7] = (unsigned char) (lba >> 16) & 0xff; | ||
1212 | SCpnt->cmnd[8] = (unsigned char) (lba >> 8) & 0xff; | ||
1213 | SCpnt->cmnd[9] = (unsigned char) lba & 0xff; | ||
1214 | SCpnt->cmnd[10] = (unsigned char) (nr_blocks >> 24) & 0xff; | ||
1215 | SCpnt->cmnd[11] = (unsigned char) (nr_blocks >> 16) & 0xff; | ||
1216 | SCpnt->cmnd[12] = (unsigned char) (nr_blocks >> 8) & 0xff; | ||
1217 | SCpnt->cmnd[13] = (unsigned char) nr_blocks & 0xff; | ||
1218 | SCpnt->cmnd[14] = SCpnt->cmnd[15] = 0; | ||
1219 | } else if ((nr_blocks > 0xff) || (lba > 0x1fffff) || | 1254 | } else if ((nr_blocks > 0xff) || (lba > 0x1fffff) || |
1220 | scsi_device_protection(SCpnt->device) || | 1255 | scsi_device_protection(SCpnt->device) || |
1221 | SCpnt->device->use_10_for_rw) { | 1256 | SCpnt->device->use_10_for_rw) { |
1222 | SCpnt->cmnd[0] += READ_10 - READ_6; | 1257 | ret = sd_setup_rw10_cmnd(SCpnt, write, lba, nr_blocks, |
1223 | SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); | 1258 | protect | fua); |
1224 | SCpnt->cmnd[2] = (unsigned char) (lba >> 24) & 0xff; | ||
1225 | SCpnt->cmnd[3] = (unsigned char) (lba >> 16) & 0xff; | ||
1226 | SCpnt->cmnd[4] = (unsigned char) (lba >> 8) & 0xff; | ||
1227 | SCpnt->cmnd[5] = (unsigned char) lba & 0xff; | ||
1228 | SCpnt->cmnd[6] = SCpnt->cmnd[9] = 0; | ||
1229 | SCpnt->cmnd[7] = (unsigned char) (nr_blocks >> 8) & 0xff; | ||
1230 | SCpnt->cmnd[8] = (unsigned char) nr_blocks & 0xff; | ||
1231 | } else { | 1259 | } else { |
1232 | if (unlikely(rq->cmd_flags & REQ_FUA)) { | 1260 | ret = sd_setup_rw6_cmnd(SCpnt, write, lba, nr_blocks, |
1233 | /* | 1261 | protect | fua); |
1234 | * This happens only if this drive failed | ||
1235 | * 10byte rw command with ILLEGAL_REQUEST | ||
1236 | * during operation and thus turned off | ||
1237 | * use_10_for_rw. | ||
1238 | */ | ||
1239 | scmd_printk(KERN_ERR, SCpnt, | ||
1240 | "FUA write on READ/WRITE(6) drive\n"); | ||
1241 | return BLK_STS_IOERR; | ||
1242 | } | ||
1243 | |||
1244 | SCpnt->cmnd[1] |= (unsigned char) ((lba >> 16) & 0x1f); | ||
1245 | SCpnt->cmnd[2] = (unsigned char) ((lba >> 8) & 0xff); | ||
1246 | SCpnt->cmnd[3] = (unsigned char) lba & 0xff; | ||
1247 | SCpnt->cmnd[4] = (unsigned char) nr_blocks; | ||
1248 | SCpnt->cmnd[5] = 0; | ||
1249 | } | 1262 | } |
1263 | |||
1264 | if (unlikely(ret != BLK_STS_OK)) | ||
1265 | return ret; | ||
1266 | |||
1250 | SCpnt->sdb.length = nr_blocks * sdp->sector_size; | 1267 | SCpnt->sdb.length = nr_blocks * sdp->sector_size; |
1251 | 1268 | ||
1252 | /* | 1269 | /* |