diff options
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 61 |
1 files changed, 42 insertions, 19 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8dd96dcd716c..1e0a0b07dab6 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -370,6 +370,31 @@ static void scsi_disk_put(struct scsi_disk *sdkp) | |||
370 | mutex_unlock(&sd_ref_mutex); | 370 | mutex_unlock(&sd_ref_mutex); |
371 | } | 371 | } |
372 | 372 | ||
373 | static void sd_prot_op(struct scsi_cmnd *scmd, unsigned int dif) | ||
374 | { | ||
375 | unsigned int prot_op = SCSI_PROT_NORMAL; | ||
376 | unsigned int dix = scsi_prot_sg_count(scmd); | ||
377 | |||
378 | if (scmd->sc_data_direction == DMA_FROM_DEVICE) { | ||
379 | if (dif && dix) | ||
380 | prot_op = SCSI_PROT_READ_PASS; | ||
381 | else if (dif && !dix) | ||
382 | prot_op = SCSI_PROT_READ_STRIP; | ||
383 | else if (!dif && dix) | ||
384 | prot_op = SCSI_PROT_READ_INSERT; | ||
385 | } else { | ||
386 | if (dif && dix) | ||
387 | prot_op = SCSI_PROT_WRITE_PASS; | ||
388 | else if (dif && !dix) | ||
389 | prot_op = SCSI_PROT_WRITE_INSERT; | ||
390 | else if (!dif && dix) | ||
391 | prot_op = SCSI_PROT_WRITE_STRIP; | ||
392 | } | ||
393 | |||
394 | scsi_set_prot_op(scmd, prot_op); | ||
395 | scsi_set_prot_type(scmd, dif); | ||
396 | } | ||
397 | |||
373 | /** | 398 | /** |
374 | * sd_init_command - build a scsi (read or write) command from | 399 | * sd_init_command - build a scsi (read or write) command from |
375 | * information in the request structure. | 400 | * information in the request structure. |
@@ -578,8 +603,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
578 | 603 | ||
579 | /* If DIF or DIX is enabled, tell HBA how to handle request */ | 604 | /* If DIF or DIX is enabled, tell HBA how to handle request */ |
580 | if (host_dif || scsi_prot_sg_count(SCpnt)) | 605 | if (host_dif || scsi_prot_sg_count(SCpnt)) |
581 | sd_dif_op(SCpnt, host_dif, scsi_prot_sg_count(SCpnt), | 606 | sd_prot_op(SCpnt, host_dif); |
582 | sdkp->protection_type); | ||
583 | 607 | ||
584 | /* | 608 | /* |
585 | * We shouldn't disconnect in the middle of a sector, so with a dumb | 609 | * We shouldn't disconnect in the middle of a sector, so with a dumb |
@@ -1238,34 +1262,33 @@ void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
1238 | u8 type; | 1262 | u8 type; |
1239 | 1263 | ||
1240 | if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) | 1264 | if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) |
1241 | type = 0; | 1265 | return; |
1242 | else | 1266 | |
1243 | type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ | 1267 | type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ |
1268 | |||
1269 | if (type == sdkp->protection_type || !sdkp->first_scan) | ||
1270 | return; | ||
1244 | 1271 | ||
1245 | sdkp->protection_type = type; | 1272 | sdkp->protection_type = type; |
1246 | 1273 | ||
1247 | switch (type) { | 1274 | switch (type) { |
1248 | case SD_DIF_TYPE0_PROTECTION: | ||
1249 | case SD_DIF_TYPE1_PROTECTION: | 1275 | case SD_DIF_TYPE1_PROTECTION: |
1250 | case SD_DIF_TYPE3_PROTECTION: | 1276 | case SD_DIF_TYPE3_PROTECTION: |
1251 | break; | 1277 | break; |
1252 | 1278 | ||
1253 | case SD_DIF_TYPE2_PROTECTION: | ||
1254 | sd_printk(KERN_ERR, sdkp, "formatted with DIF Type 2 " \ | ||
1255 | "protection which is currently unsupported. " \ | ||
1256 | "Disabling disk!\n"); | ||
1257 | goto disable; | ||
1258 | |||
1259 | default: | 1279 | default: |
1260 | sd_printk(KERN_ERR, sdkp, "formatted with unknown " \ | 1280 | sd_printk(KERN_ERR, sdkp, "formatted with unsupported " \ |
1261 | "protection type %d. Disabling disk!\n", type); | 1281 | "protection type %u. Disabling disk!\n", type); |
1262 | goto disable; | 1282 | sdkp->capacity = 0; |
1283 | return; | ||
1263 | } | 1284 | } |
1264 | 1285 | ||
1265 | return; | 1286 | if (scsi_host_dif_capable(sdp->host, type)) |
1266 | 1287 | sd_printk(KERN_NOTICE, sdkp, | |
1267 | disable: | 1288 | "Enabling DIF Type %u protection\n", type); |
1268 | sdkp->capacity = 0; | 1289 | else |
1290 | sd_printk(KERN_NOTICE, sdkp, | ||
1291 | "Disabling DIF Type %u protection\n", type); | ||
1269 | } | 1292 | } |
1270 | 1293 | ||
1271 | static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, | 1294 | static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, |