diff options
Diffstat (limited to 'drivers/scsi/sd.c')
| -rw-r--r-- | drivers/scsi/sd.c | 172 |
1 files changed, 141 insertions, 31 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 9d9872347f56..024ef86c5242 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -47,7 +47,6 @@ | |||
| 47 | #include <linux/init.h> | 47 | #include <linux/init.h> |
| 48 | #include <linux/blkdev.h> | 48 | #include <linux/blkdev.h> |
| 49 | #include <linux/blkpg.h> | 49 | #include <linux/blkpg.h> |
| 50 | #include <linux/kref.h> | ||
| 51 | #include <linux/delay.h> | 50 | #include <linux/delay.h> |
| 52 | #include <linux/mutex.h> | 51 | #include <linux/mutex.h> |
| 53 | #include <asm/uaccess.h> | 52 | #include <asm/uaccess.h> |
| @@ -71,6 +70,27 @@ | |||
| 71 | */ | 70 | */ |
| 72 | #define SD_MAJORS 16 | 71 | #define SD_MAJORS 16 |
| 73 | 72 | ||
| 73 | MODULE_AUTHOR("Eric Youngdale"); | ||
| 74 | MODULE_DESCRIPTION("SCSI disk (sd) driver"); | ||
| 75 | MODULE_LICENSE("GPL"); | ||
| 76 | |||
| 77 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK0_MAJOR); | ||
| 78 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK1_MAJOR); | ||
| 79 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK2_MAJOR); | ||
| 80 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK3_MAJOR); | ||
| 81 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK4_MAJOR); | ||
| 82 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK5_MAJOR); | ||
| 83 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK6_MAJOR); | ||
| 84 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK7_MAJOR); | ||
| 85 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK8_MAJOR); | ||
| 86 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK9_MAJOR); | ||
| 87 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK10_MAJOR); | ||
| 88 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK11_MAJOR); | ||
| 89 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK12_MAJOR); | ||
| 90 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK13_MAJOR); | ||
| 91 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK14_MAJOR); | ||
| 92 | MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK15_MAJOR); | ||
| 93 | |||
| 74 | /* | 94 | /* |
| 75 | * This is limited by the naming scheme enforced in sd_probe, | 95 | * This is limited by the naming scheme enforced in sd_probe, |
| 76 | * add another character to it if you really need more disks. | 96 | * add another character to it if you really need more disks. |
| @@ -94,12 +114,10 @@ | |||
| 94 | */ | 114 | */ |
| 95 | #define SD_BUF_SIZE 512 | 115 | #define SD_BUF_SIZE 512 |
| 96 | 116 | ||
| 97 | static void scsi_disk_release(struct kref *kref); | ||
| 98 | |||
| 99 | struct scsi_disk { | 117 | struct scsi_disk { |
| 100 | struct scsi_driver *driver; /* always &sd_template */ | 118 | struct scsi_driver *driver; /* always &sd_template */ |
| 101 | struct scsi_device *device; | 119 | struct scsi_device *device; |
| 102 | struct kref kref; | 120 | struct class_device cdev; |
| 103 | struct gendisk *disk; | 121 | struct gendisk *disk; |
| 104 | unsigned int openers; /* protected by BKL for now, yuck */ | 122 | unsigned int openers; /* protected by BKL for now, yuck */ |
| 105 | sector_t capacity; /* size in 512-byte sectors */ | 123 | sector_t capacity; /* size in 512-byte sectors */ |
| @@ -110,6 +128,7 @@ struct scsi_disk { | |||
| 110 | unsigned RCD : 1; /* state of disk RCD bit, unused */ | 128 | unsigned RCD : 1; /* state of disk RCD bit, unused */ |
| 111 | unsigned DPOFUA : 1; /* state of disk DPOFUA bit */ | 129 | unsigned DPOFUA : 1; /* state of disk DPOFUA bit */ |
| 112 | }; | 130 | }; |
| 131 | #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev) | ||
| 113 | 132 | ||
| 114 | static DEFINE_IDR(sd_index_idr); | 133 | static DEFINE_IDR(sd_index_idr); |
| 115 | static DEFINE_SPINLOCK(sd_index_lock); | 134 | static DEFINE_SPINLOCK(sd_index_lock); |
| @@ -131,6 +150,92 @@ static int sd_issue_flush(struct device *, sector_t *); | |||
| 131 | static void sd_prepare_flush(request_queue_t *, struct request *); | 150 | static void sd_prepare_flush(request_queue_t *, struct request *); |
| 132 | static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, | 151 | static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, |
| 133 | unsigned char *buffer); | 152 | unsigned char *buffer); |
| 153 | static void scsi_disk_release(struct class_device *cdev); | ||
| 154 | |||
| 155 | static const char *sd_cache_types[] = { | ||
| 156 | "write through", "none", "write back", | ||
| 157 | "write back, no read (daft)" | ||
| 158 | }; | ||
| 159 | |||
| 160 | static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf, | ||
| 161 | size_t count) | ||
| 162 | { | ||
| 163 | int i, ct = -1, rcd, wce, sp; | ||
| 164 | struct scsi_disk *sdkp = to_scsi_disk(cdev); | ||
| 165 | struct scsi_device *sdp = sdkp->device; | ||
| 166 | char buffer[64]; | ||
| 167 | char *buffer_data; | ||
| 168 | struct scsi_mode_data data; | ||
| 169 | struct scsi_sense_hdr sshdr; | ||
| 170 | int len; | ||
| 171 | |||
| 172 | if (sdp->type != TYPE_DISK) | ||
| 173 | /* no cache control on RBC devices; theoretically they | ||
| 174 | * can do it, but there's probably so many exceptions | ||
| 175 | * it's not worth the risk */ | ||
| 176 | return -EINVAL; | ||
| 177 | |||
| 178 | for (i = 0; i < sizeof(sd_cache_types)/sizeof(sd_cache_types[0]); i++) { | ||
| 179 | const int len = strlen(sd_cache_types[i]); | ||
| 180 | if (strncmp(sd_cache_types[i], buf, len) == 0 && | ||
| 181 | buf[len] == '\n') { | ||
| 182 | ct = i; | ||
| 183 | break; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | if (ct < 0) | ||
| 187 | return -EINVAL; | ||
| 188 | rcd = ct & 0x01 ? 1 : 0; | ||
| 189 | wce = ct & 0x02 ? 1 : 0; | ||
| 190 | if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT, | ||
| 191 | SD_MAX_RETRIES, &data, NULL)) | ||
| 192 | return -EINVAL; | ||
| 193 | len = min(sizeof(buffer), data.length - data.header_length - | ||
| 194 | data.block_descriptor_length); | ||
| 195 | buffer_data = buffer + data.header_length + | ||
| 196 | data.block_descriptor_length; | ||
| 197 | buffer_data[2] &= ~0x05; | ||
| 198 | buffer_data[2] |= wce << 2 | rcd; | ||
| 199 | sp = buffer_data[0] & 0x80 ? 1 : 0; | ||
| 200 | |||
| 201 | if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT, | ||
| 202 | SD_MAX_RETRIES, &data, &sshdr)) { | ||
| 203 | if (scsi_sense_valid(&sshdr)) | ||
| 204 | scsi_print_sense_hdr(sdkp->disk->disk_name, &sshdr); | ||
| 205 | return -EINVAL; | ||
| 206 | } | ||
| 207 | sd_revalidate_disk(sdkp->disk); | ||
| 208 | return count; | ||
| 209 | } | ||
| 210 | |||
| 211 | static ssize_t sd_show_cache_type(struct class_device *cdev, char *buf) | ||
| 212 | { | ||
| 213 | struct scsi_disk *sdkp = to_scsi_disk(cdev); | ||
| 214 | int ct = sdkp->RCD + 2*sdkp->WCE; | ||
| 215 | |||
| 216 | return snprintf(buf, 40, "%s\n", sd_cache_types[ct]); | ||
| 217 | } | ||
| 218 | |||
| 219 | static ssize_t sd_show_fua(struct class_device *cdev, char *buf) | ||
| 220 | { | ||
| 221 | struct scsi_disk *sdkp = to_scsi_disk(cdev); | ||
| 222 | |||
| 223 | return snprintf(buf, 20, "%u\n", sdkp->DPOFUA); | ||
| 224 | } | ||
| 225 | |||
| 226 | static struct class_device_attribute sd_disk_attrs[] = { | ||
| 227 | __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type, | ||
| 228 | sd_store_cache_type), | ||
| 229 | __ATTR(FUA, S_IRUGO, sd_show_fua, NULL), | ||
| 230 | __ATTR_NULL, | ||
| 231 | }; | ||
| 232 | |||
| 233 | static struct class sd_disk_class = { | ||
| 234 | .name = "scsi_disk", | ||
| 235 | .owner = THIS_MODULE, | ||
| 236 | .release = scsi_disk_release, | ||
| 237 | .class_dev_attrs = sd_disk_attrs, | ||
| 238 | }; | ||
| 134 | 239 | ||
| 135 | static struct scsi_driver sd_template = { | 240 | static struct scsi_driver sd_template = { |
| 136 | .owner = THIS_MODULE, | 241 | .owner = THIS_MODULE, |
| @@ -174,8 +279,6 @@ static int sd_major(int major_idx) | |||
| 174 | } | 279 | } |
| 175 | } | 280 | } |
| 176 | 281 | ||
| 177 | #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,kref) | ||
| 178 | |||
| 179 | static inline struct scsi_disk *scsi_disk(struct gendisk *disk) | 282 | static inline struct scsi_disk *scsi_disk(struct gendisk *disk) |
| 180 | { | 283 | { |
| 181 | return container_of(disk->private_data, struct scsi_disk, driver); | 284 | return container_of(disk->private_data, struct scsi_disk, driver); |
| @@ -188,7 +291,7 @@ static struct scsi_disk *__scsi_disk_get(struct gendisk *disk) | |||
| 188 | if (disk->private_data) { | 291 | if (disk->private_data) { |
| 189 | sdkp = scsi_disk(disk); | 292 | sdkp = scsi_disk(disk); |
| 190 | if (scsi_device_get(sdkp->device) == 0) | 293 | if (scsi_device_get(sdkp->device) == 0) |
| 191 | kref_get(&sdkp->kref); | 294 | class_device_get(&sdkp->cdev); |
| 192 | else | 295 | else |
| 193 | sdkp = NULL; | 296 | sdkp = NULL; |
| 194 | } | 297 | } |
| @@ -222,7 +325,7 @@ static void scsi_disk_put(struct scsi_disk *sdkp) | |||
| 222 | struct scsi_device *sdev = sdkp->device; | 325 | struct scsi_device *sdev = sdkp->device; |
| 223 | 326 | ||
| 224 | mutex_lock(&sd_ref_mutex); | 327 | mutex_lock(&sd_ref_mutex); |
| 225 | kref_put(&sdkp->kref, scsi_disk_release); | 328 | class_device_put(&sdkp->cdev); |
| 226 | scsi_device_put(sdev); | 329 | scsi_device_put(sdev); |
| 227 | mutex_unlock(&sd_ref_mutex); | 330 | mutex_unlock(&sd_ref_mutex); |
| 228 | } | 331 | } |
| @@ -1333,6 +1436,12 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, | |||
| 1333 | if (!scsi_status_is_good(res)) | 1436 | if (!scsi_status_is_good(res)) |
| 1334 | goto bad_sense; | 1437 | goto bad_sense; |
| 1335 | 1438 | ||
| 1439 | if (!data.header_length) { | ||
| 1440 | modepage = 6; | ||
| 1441 | printk(KERN_ERR "%s: missing header in MODE_SENSE response\n", | ||
| 1442 | diskname); | ||
| 1443 | } | ||
| 1444 | |||
| 1336 | /* that went OK, now ask for the proper length */ | 1445 | /* that went OK, now ask for the proper length */ |
| 1337 | len = data.length; | 1446 | len = data.length; |
| 1338 | 1447 | ||
| @@ -1354,10 +1463,6 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, | |||
| 1354 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); | 1463 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); |
| 1355 | 1464 | ||
| 1356 | if (scsi_status_is_good(res)) { | 1465 | if (scsi_status_is_good(res)) { |
| 1357 | const char *types[] = { | ||
| 1358 | "write through", "none", "write back", | ||
| 1359 | "write back, no read (daft)" | ||
| 1360 | }; | ||
| 1361 | int ct = 0; | 1466 | int ct = 0; |
| 1362 | int offset = data.header_length + data.block_descriptor_length; | 1467 | int offset = data.header_length + data.block_descriptor_length; |
| 1363 | 1468 | ||
| @@ -1390,7 +1495,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, | |||
| 1390 | ct = sdkp->RCD + 2*sdkp->WCE; | 1495 | ct = sdkp->RCD + 2*sdkp->WCE; |
| 1391 | 1496 | ||
| 1392 | printk(KERN_NOTICE "SCSI device %s: drive cache: %s%s\n", | 1497 | printk(KERN_NOTICE "SCSI device %s: drive cache: %s%s\n", |
| 1393 | diskname, types[ct], | 1498 | diskname, sd_cache_types[ct], |
| 1394 | sdkp->DPOFUA ? " w/ FUA" : ""); | 1499 | sdkp->DPOFUA ? " w/ FUA" : ""); |
| 1395 | 1500 | ||
| 1396 | return; | 1501 | return; |
| @@ -1517,13 +1622,10 @@ static int sd_probe(struct device *dev) | |||
| 1517 | "sd_attach\n")); | 1622 | "sd_attach\n")); |
| 1518 | 1623 | ||
| 1519 | error = -ENOMEM; | 1624 | error = -ENOMEM; |
| 1520 | sdkp = kmalloc(sizeof(*sdkp), GFP_KERNEL); | 1625 | sdkp = kzalloc(sizeof(*sdkp), GFP_KERNEL); |
| 1521 | if (!sdkp) | 1626 | if (!sdkp) |
| 1522 | goto out; | 1627 | goto out; |
| 1523 | 1628 | ||
| 1524 | memset (sdkp, 0, sizeof(*sdkp)); | ||
| 1525 | kref_init(&sdkp->kref); | ||
| 1526 | |||
| 1527 | gd = alloc_disk(16); | 1629 | gd = alloc_disk(16); |
| 1528 | if (!gd) | 1630 | if (!gd) |
| 1529 | goto out_free; | 1631 | goto out_free; |
| @@ -1540,7 +1642,16 @@ static int sd_probe(struct device *dev) | |||
| 1540 | if (error) | 1642 | if (error) |
| 1541 | goto out_put; | 1643 | goto out_put; |
| 1542 | 1644 | ||
| 1645 | class_device_initialize(&sdkp->cdev); | ||
| 1646 | sdkp->cdev.dev = &sdp->sdev_gendev; | ||
| 1647 | sdkp->cdev.class = &sd_disk_class; | ||
| 1648 | strncpy(sdkp->cdev.class_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE); | ||
| 1649 | |||
| 1650 | if (class_device_add(&sdkp->cdev)) | ||
| 1651 | goto out_put; | ||
| 1652 | |||
| 1543 | get_device(&sdp->sdev_gendev); | 1653 | get_device(&sdp->sdev_gendev); |
| 1654 | |||
| 1544 | sdkp->device = sdp; | 1655 | sdkp->device = sdp; |
| 1545 | sdkp->driver = &sd_template; | 1656 | sdkp->driver = &sd_template; |
| 1546 | sdkp->disk = gd; | 1657 | sdkp->disk = gd; |
| @@ -1572,8 +1683,6 @@ static int sd_probe(struct device *dev) | |||
| 1572 | 'a' + m1, 'a' + m2, 'a' + m3); | 1683 | 'a' + m1, 'a' + m2, 'a' + m3); |
| 1573 | } | 1684 | } |
| 1574 | 1685 | ||
| 1575 | strcpy(gd->devfs_name, sdp->devfs_name); | ||
| 1576 | |||
| 1577 | gd->private_data = &sdkp->driver; | 1686 | gd->private_data = &sdkp->driver; |
| 1578 | gd->queue = sdkp->device->request_queue; | 1687 | gd->queue = sdkp->device->request_queue; |
| 1579 | 1688 | ||
| @@ -1592,11 +1701,11 @@ static int sd_probe(struct device *dev) | |||
| 1592 | 1701 | ||
| 1593 | return 0; | 1702 | return 0; |
| 1594 | 1703 | ||
| 1595 | out_put: | 1704 | out_put: |
| 1596 | put_disk(gd); | 1705 | put_disk(gd); |
| 1597 | out_free: | 1706 | out_free: |
| 1598 | kfree(sdkp); | 1707 | kfree(sdkp); |
| 1599 | out: | 1708 | out: |
| 1600 | return error; | 1709 | return error; |
| 1601 | } | 1710 | } |
| 1602 | 1711 | ||
| @@ -1615,12 +1724,13 @@ static int sd_remove(struct device *dev) | |||
| 1615 | { | 1724 | { |
| 1616 | struct scsi_disk *sdkp = dev_get_drvdata(dev); | 1725 | struct scsi_disk *sdkp = dev_get_drvdata(dev); |
| 1617 | 1726 | ||
| 1727 | class_device_del(&sdkp->cdev); | ||
| 1618 | del_gendisk(sdkp->disk); | 1728 | del_gendisk(sdkp->disk); |
| 1619 | sd_shutdown(dev); | 1729 | sd_shutdown(dev); |
| 1620 | 1730 | ||
| 1621 | mutex_lock(&sd_ref_mutex); | 1731 | mutex_lock(&sd_ref_mutex); |
| 1622 | dev_set_drvdata(dev, NULL); | 1732 | dev_set_drvdata(dev, NULL); |
| 1623 | kref_put(&sdkp->kref, scsi_disk_release); | 1733 | class_device_put(&sdkp->cdev); |
| 1624 | mutex_unlock(&sd_ref_mutex); | 1734 | mutex_unlock(&sd_ref_mutex); |
| 1625 | 1735 | ||
| 1626 | return 0; | 1736 | return 0; |
| @@ -1628,16 +1738,16 @@ static int sd_remove(struct device *dev) | |||
| 1628 | 1738 | ||
| 1629 | /** | 1739 | /** |
| 1630 | * scsi_disk_release - Called to free the scsi_disk structure | 1740 | * scsi_disk_release - Called to free the scsi_disk structure |
| 1631 | * @kref: pointer to embedded kref | 1741 | * @cdev: pointer to embedded class device |
| 1632 | * | 1742 | * |
| 1633 | * sd_ref_mutex must be held entering this routine. Because it is | 1743 | * sd_ref_mutex must be held entering this routine. Because it is |
| 1634 | * called on last put, you should always use the scsi_disk_get() | 1744 | * called on last put, you should always use the scsi_disk_get() |
| 1635 | * scsi_disk_put() helpers which manipulate the semaphore directly | 1745 | * scsi_disk_put() helpers which manipulate the semaphore directly |
| 1636 | * and never do a direct kref_put(). | 1746 | * and never do a direct class_device_put(). |
| 1637 | **/ | 1747 | **/ |
| 1638 | static void scsi_disk_release(struct kref *kref) | 1748 | static void scsi_disk_release(struct class_device *cdev) |
| 1639 | { | 1749 | { |
| 1640 | struct scsi_disk *sdkp = to_scsi_disk(kref); | 1750 | struct scsi_disk *sdkp = to_scsi_disk(cdev); |
| 1641 | struct gendisk *disk = sdkp->disk; | 1751 | struct gendisk *disk = sdkp->disk; |
| 1642 | 1752 | ||
| 1643 | spin_lock(&sd_index_lock); | 1753 | spin_lock(&sd_index_lock); |
| @@ -1691,6 +1801,8 @@ static int __init init_sd(void) | |||
| 1691 | if (!majors) | 1801 | if (!majors) |
| 1692 | return -ENODEV; | 1802 | return -ENODEV; |
| 1693 | 1803 | ||
| 1804 | class_register(&sd_disk_class); | ||
| 1805 | |||
| 1694 | return scsi_register_driver(&sd_template.gendrv); | 1806 | return scsi_register_driver(&sd_template.gendrv); |
| 1695 | } | 1807 | } |
| 1696 | 1808 | ||
| @@ -1708,11 +1820,9 @@ static void __exit exit_sd(void) | |||
| 1708 | scsi_unregister_driver(&sd_template.gendrv); | 1820 | scsi_unregister_driver(&sd_template.gendrv); |
| 1709 | for (i = 0; i < SD_MAJORS; i++) | 1821 | for (i = 0; i < SD_MAJORS; i++) |
| 1710 | unregister_blkdev(sd_major(i), "sd"); | 1822 | unregister_blkdev(sd_major(i), "sd"); |
| 1711 | } | ||
| 1712 | 1823 | ||
| 1713 | MODULE_LICENSE("GPL"); | 1824 | class_unregister(&sd_disk_class); |
| 1714 | MODULE_AUTHOR("Eric Youngdale"); | 1825 | } |
| 1715 | MODULE_DESCRIPTION("SCSI disk (sd) driver"); | ||
| 1716 | 1826 | ||
| 1717 | module_init(init_sd); | 1827 | module_init(init_sd); |
| 1718 | module_exit(exit_sd); | 1828 | module_exit(exit_sd); |
