diff options
| author | Tejun Heo <htejun@gmail.com> | 2006-01-06 03:53:52 -0500 | 
|---|---|---|
| committer | Jens Axboe <axboe@suse.de> | 2006-01-06 03:53:52 -0500 | 
| commit | 007365ad60387df30f02f01fdc2b6e6432f6c265 (patch) | |
| tree | 5fa1f755011cc026d2096b6bc5aa83712ab9a32a | |
| parent | 461d4e90c8cd049718884cd17c955e231140d3be (diff) | |
[BLOCK] scsi: add FUA support to sd
Add FUA support for barriers to SCSI disk.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jens Axboe <axboe@suse.de>
| -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 | ||
