aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/sd.c29
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
107static DEFINE_IDR(sd_index_idr); 108static 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