diff options
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 85 |
1 files changed, 45 insertions, 40 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 3d3ad7d1b779..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); |
@@ -121,8 +122,7 @@ static void sd_shutdown(struct device *dev); | |||
121 | static void sd_rescan(struct device *); | 122 | static void sd_rescan(struct device *); |
122 | static int sd_init_command(struct scsi_cmnd *); | 123 | static int sd_init_command(struct scsi_cmnd *); |
123 | static int sd_issue_flush(struct device *, sector_t *); | 124 | static int sd_issue_flush(struct device *, sector_t *); |
124 | static void sd_end_flush(request_queue_t *, struct request *); | 125 | static void sd_prepare_flush(request_queue_t *, struct request *); |
125 | static int sd_prepare_flush(request_queue_t *, struct request *); | ||
126 | static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, | 126 | static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, |
127 | unsigned char *buffer); | 127 | unsigned char *buffer); |
128 | 128 | ||
@@ -137,8 +137,6 @@ static struct scsi_driver sd_template = { | |||
137 | .rescan = sd_rescan, | 137 | .rescan = sd_rescan, |
138 | .init_command = sd_init_command, | 138 | .init_command = sd_init_command, |
139 | .issue_flush = sd_issue_flush, | 139 | .issue_flush = sd_issue_flush, |
140 | .prepare_flush = sd_prepare_flush, | ||
141 | .end_flush = sd_end_flush, | ||
142 | }; | 140 | }; |
143 | 141 | ||
144 | /* | 142 | /* |
@@ -346,6 +344,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
346 | 344 | ||
347 | if (block > 0xffffffff) { | 345 | if (block > 0xffffffff) { |
348 | 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; | ||
349 | 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; |
350 | 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; |
351 | 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; |
@@ -365,6 +364,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
365 | this_count = 0xffff; | 364 | this_count = 0xffff; |
366 | 365 | ||
367 | 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; | ||
368 | SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; | 368 | SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; |
369 | SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; | 369 | SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; |
370 | SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; | 370 | SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; |
@@ -373,6 +373,17 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
373 | SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; | 373 | SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; |
374 | SCpnt->cmnd[8] = (unsigned char) this_count & 0xff; | 374 | SCpnt->cmnd[8] = (unsigned char) this_count & 0xff; |
375 | } 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 | |||
376 | SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f); | 387 | SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f); |
377 | SCpnt->cmnd[2] = (unsigned char) ((block >> 8) & 0xff); | 388 | SCpnt->cmnd[2] = (unsigned char) ((block >> 8) & 0xff); |
378 | SCpnt->cmnd[3] = (unsigned char) block & 0xff; | 389 | SCpnt->cmnd[3] = (unsigned char) block & 0xff; |
@@ -729,42 +740,13 @@ static int sd_issue_flush(struct device *dev, sector_t *error_sector) | |||
729 | return ret; | 740 | return ret; |
730 | } | 741 | } |
731 | 742 | ||
732 | static void sd_end_flush(request_queue_t *q, struct request *flush_rq) | 743 | static void sd_prepare_flush(request_queue_t *q, struct request *rq) |
733 | { | ||
734 | struct request *rq = flush_rq->end_io_data; | ||
735 | struct scsi_cmnd *cmd = rq->special; | ||
736 | unsigned int bytes = rq->hard_nr_sectors << 9; | ||
737 | |||
738 | if (!flush_rq->errors) { | ||
739 | spin_unlock(q->queue_lock); | ||
740 | scsi_io_completion(cmd, bytes, 0); | ||
741 | spin_lock(q->queue_lock); | ||
742 | } else if (blk_barrier_postflush(rq)) { | ||
743 | spin_unlock(q->queue_lock); | ||
744 | scsi_io_completion(cmd, 0, bytes); | ||
745 | spin_lock(q->queue_lock); | ||
746 | } else { | ||
747 | /* | ||
748 | * force journal abort of barriers | ||
749 | */ | ||
750 | end_that_request_first(rq, -EOPNOTSUPP, rq->hard_nr_sectors); | ||
751 | end_that_request_last(rq); | ||
752 | } | ||
753 | } | ||
754 | |||
755 | static int sd_prepare_flush(request_queue_t *q, struct request *rq) | ||
756 | { | 744 | { |
757 | struct scsi_device *sdev = q->queuedata; | ||
758 | struct scsi_disk *sdkp = dev_get_drvdata(&sdev->sdev_gendev); | ||
759 | |||
760 | if (!sdkp || !sdkp->WCE) | ||
761 | return 0; | ||
762 | |||
763 | memset(rq->cmd, 0, sizeof(rq->cmd)); | 745 | memset(rq->cmd, 0, sizeof(rq->cmd)); |
764 | rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER; | 746 | rq->flags |= REQ_BLOCK_PC; |
765 | rq->timeout = SD_TIMEOUT; | 747 | rq->timeout = SD_TIMEOUT; |
766 | rq->cmd[0] = SYNCHRONIZE_CACHE; | 748 | rq->cmd[0] = SYNCHRONIZE_CACHE; |
767 | return 1; | 749 | rq->cmd_len = 10; |
768 | } | 750 | } |
769 | 751 | ||
770 | static void sd_rescan(struct device *dev) | 752 | static void sd_rescan(struct device *dev) |
@@ -1427,10 +1409,18 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, | |||
1427 | sdkp->RCD = 0; | 1409 | sdkp->RCD = 0; |
1428 | } | 1410 | } |
1429 | 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 | |||
1430 | ct = sdkp->RCD + 2*sdkp->WCE; | 1419 | ct = sdkp->RCD + 2*sdkp->WCE; |
1431 | 1420 | ||
1432 | printk(KERN_NOTICE "SCSI device %s: drive cache: %s\n", | 1421 | printk(KERN_NOTICE "SCSI device %s: drive cache: %s%s\n", |
1433 | diskname, types[ct]); | 1422 | diskname, types[ct], |
1423 | sdkp->DPOFUA ? " w/ FUA" : ""); | ||
1434 | 1424 | ||
1435 | return; | 1425 | return; |
1436 | } | 1426 | } |
@@ -1462,6 +1452,7 @@ static int sd_revalidate_disk(struct gendisk *disk) | |||
1462 | struct scsi_disk *sdkp = scsi_disk(disk); | 1452 | struct scsi_disk *sdkp = scsi_disk(disk); |
1463 | struct scsi_device *sdp = sdkp->device; | 1453 | struct scsi_device *sdp = sdkp->device; |
1464 | unsigned char *buffer; | 1454 | unsigned char *buffer; |
1455 | unsigned ordered; | ||
1465 | 1456 | ||
1466 | SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name)); | 1457 | SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name)); |
1467 | 1458 | ||
@@ -1498,7 +1489,21 @@ static int sd_revalidate_disk(struct gendisk *disk) | |||
1498 | sd_read_write_protect_flag(sdkp, disk->disk_name, buffer); | 1489 | sd_read_write_protect_flag(sdkp, disk->disk_name, buffer); |
1499 | sd_read_cache_type(sdkp, disk->disk_name, buffer); | 1490 | sd_read_cache_type(sdkp, disk->disk_name, buffer); |
1500 | } | 1491 | } |
1501 | 1492 | ||
1493 | /* | ||
1494 | * We now have all cache related info, determine how we deal | ||
1495 | * with ordered requests. Note that as the current SCSI | ||
1496 | * dispatch function can alter request order, we cannot use | ||
1497 | * QUEUE_ORDERED_TAG_* even when ordered tag is supported. | ||
1498 | */ | ||
1499 | if (sdkp->WCE) | ||
1500 | ordered = sdkp->DPOFUA | ||
1501 | ? QUEUE_ORDERED_DRAIN_FUA : QUEUE_ORDERED_DRAIN_FLUSH; | ||
1502 | else | ||
1503 | ordered = QUEUE_ORDERED_DRAIN; | ||
1504 | |||
1505 | blk_queue_ordered(sdkp->disk->queue, ordered, sd_prepare_flush); | ||
1506 | |||
1502 | set_capacity(disk, sdkp->capacity); | 1507 | set_capacity(disk, sdkp->capacity); |
1503 | kfree(buffer); | 1508 | kfree(buffer); |
1504 | 1509 | ||
@@ -1598,6 +1603,7 @@ static int sd_probe(struct device *dev) | |||
1598 | strcpy(gd->devfs_name, sdp->devfs_name); | 1603 | strcpy(gd->devfs_name, sdp->devfs_name); |
1599 | 1604 | ||
1600 | gd->private_data = &sdkp->driver; | 1605 | gd->private_data = &sdkp->driver; |
1606 | gd->queue = sdkp->device->request_queue; | ||
1601 | 1607 | ||
1602 | sd_revalidate_disk(gd); | 1608 | sd_revalidate_disk(gd); |
1603 | 1609 | ||
@@ -1605,7 +1611,6 @@ static int sd_probe(struct device *dev) | |||
1605 | gd->flags = GENHD_FL_DRIVERFS; | 1611 | gd->flags = GENHD_FL_DRIVERFS; |
1606 | if (sdp->removable) | 1612 | if (sdp->removable) |
1607 | gd->flags |= GENHD_FL_REMOVABLE; | 1613 | gd->flags |= GENHD_FL_REMOVABLE; |
1608 | gd->queue = sdkp->device->request_queue; | ||
1609 | 1614 | ||
1610 | dev_set_drvdata(dev, sdkp); | 1615 | dev_set_drvdata(dev, sdkp); |
1611 | add_disk(gd); | 1616 | add_disk(gd); |