aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r--drivers/scsi/sd.c61
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
373static 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,
1267disable: 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
1271static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, 1294static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,