diff options
-rw-r--r-- | drivers/scsi/sd.c | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 2eefc9eb5da6..32d4d8d7b9f3 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -102,6 +102,7 @@ struct scsi_disk { | |||
102 | u8 write_prot; | 102 | u8 write_prot; |
103 | unsigned WCE : 1; /* state of disk WCE bit */ | 103 | unsigned WCE : 1; /* state of disk WCE bit */ |
104 | unsigned RCD : 1; /* state of disk RCD bit, unused */ | 104 | unsigned RCD : 1; /* state of disk RCD bit, unused */ |
105 | unsigned DPOFUA : 1; /* state of disk DPOFUA bit */ | ||
105 | }; | 106 | }; |
106 | 107 | ||
107 | static DEFINE_IDR(sd_index_idr); | 108 | static DEFINE_IDR(sd_index_idr); |
@@ -343,6 +344,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
343 | 344 | ||
344 | if (block > 0xffffffff) { | 345 | if (block > 0xffffffff) { |
345 | SCpnt->cmnd[0] += READ_16 - READ_6; | 346 | SCpnt->cmnd[0] += READ_16 - READ_6; |
347 | SCpnt->cmnd[1] |= blk_fua_rq(rq) ? 0x8 : 0; | ||
346 | SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; | 348 | SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; |
347 | SCpnt->cmnd[3] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0; | 349 | SCpnt->cmnd[3] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0; |
348 | SCpnt->cmnd[4] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0; | 350 | SCpnt->cmnd[4] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0; |
@@ -362,6 +364,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
362 | this_count = 0xffff; | 364 | this_count = 0xffff; |
363 | 365 | ||
364 | SCpnt->cmnd[0] += READ_10 - READ_6; | 366 | SCpnt->cmnd[0] += READ_10 - READ_6; |
367 | SCpnt->cmnd[1] |= blk_fua_rq(rq) ? 0x8 : 0; | ||
365 | SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; | 368 | SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; |
366 | SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; | 369 | SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; |
367 | SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; | 370 | SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; |
@@ -370,6 +373,17 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
370 | SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; | 373 | SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; |
371 | SCpnt->cmnd[8] = (unsigned char) this_count & 0xff; | 374 | SCpnt->cmnd[8] = (unsigned char) this_count & 0xff; |
372 | } else { | 375 | } else { |
376 | if (unlikely(blk_fua_rq(rq))) { | ||
377 | /* | ||
378 | * This happens only if this drive failed | ||
379 | * 10byte rw command with ILLEGAL_REQUEST | ||
380 | * during operation and thus turned off | ||
381 | * use_10_for_rw. | ||
382 | */ | ||
383 | printk(KERN_ERR "sd: FUA write on READ/WRITE(6) drive\n"); | ||
384 | return 0; | ||
385 | } | ||
386 | |||
373 | SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f); | 387 | SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f); |
374 | SCpnt->cmnd[2] = (unsigned char) ((block >> 8) & 0xff); | 388 | SCpnt->cmnd[2] = (unsigned char) ((block >> 8) & 0xff); |
375 | SCpnt->cmnd[3] = (unsigned char) block & 0xff; | 389 | SCpnt->cmnd[3] = (unsigned char) block & 0xff; |
@@ -1395,10 +1409,18 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, | |||
1395 | sdkp->RCD = 0; | 1409 | sdkp->RCD = 0; |
1396 | } | 1410 | } |
1397 | 1411 | ||
1412 | sdkp->DPOFUA = (data.device_specific & 0x10) != 0; | ||
1413 | if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) { | ||
1414 | printk(KERN_NOTICE "SCSI device %s: uses " | ||
1415 | "READ/WRITE(6), disabling FUA\n", diskname); | ||
1416 | sdkp->DPOFUA = 0; | ||
1417 | } | ||
1418 | |||
1398 | ct = sdkp->RCD + 2*sdkp->WCE; | 1419 | ct = sdkp->RCD + 2*sdkp->WCE; |
1399 | 1420 | ||
1400 | printk(KERN_NOTICE "SCSI device %s: drive cache: %s\n", | 1421 | printk(KERN_NOTICE "SCSI device %s: drive cache: %s%s\n", |
1401 | diskname, types[ct]); | 1422 | diskname, types[ct], |
1423 | sdkp->DPOFUA ? " w/ FUA" : ""); | ||
1402 | 1424 | ||
1403 | return; | 1425 | return; |
1404 | } | 1426 | } |
@@ -1475,7 +1497,8 @@ static int sd_revalidate_disk(struct gendisk *disk) | |||
1475 | * QUEUE_ORDERED_TAG_* even when ordered tag is supported. | 1497 | * QUEUE_ORDERED_TAG_* even when ordered tag is supported. |
1476 | */ | 1498 | */ |
1477 | if (sdkp->WCE) | 1499 | if (sdkp->WCE) |
1478 | ordered = QUEUE_ORDERED_DRAIN_FLUSH; | 1500 | ordered = sdkp->DPOFUA |
1501 | ? QUEUE_ORDERED_DRAIN_FUA : QUEUE_ORDERED_DRAIN_FLUSH; | ||
1479 | else | 1502 | else |
1480 | ordered = QUEUE_ORDERED_DRAIN; | 1503 | ordered = QUEUE_ORDERED_DRAIN; |
1481 | 1504 | ||