-static void scsi_disk_release(struct class_device *cdev);
-
-static const char *sd_cache_types[] = {
- "write through", "none", "write back",
- "write back, no read (daft)"
-};
-
-static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf,
- size_t count)
-{
- int i, ct = -1, rcd, wce, sp;
- struct scsi_disk *sdkp = to_scsi_disk(cdev);
- struct scsi_device *sdp = sdkp->device;
- char buffer[64];
- char *buffer_data;
- struct scsi_mode_data data;
- struct scsi_sense_hdr sshdr;
- int len;
-
- if (sdp->type != TYPE_DISK)
- /* no cache control on RBC devices; theoretically they
- * can do it, but there's probably so many exceptions
- * it's not worth the risk */
- return -EINVAL;
-
- for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) {
- const int len = strlen(sd_cache_types[i]);
- if (strncmp(sd_cache_types[i], buf, len) == 0 &&
- buf[len] == '\n') {
- ct = i;
- break;
- }
- }
- if (ct < 0)
- return -EINVAL;
- rcd = ct & 0x01 ? 1 : 0;
- wce = ct & 0x02 ? 1 : 0;
- if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT,
- SD_MAX_RETRIES, &data, NULL))
- return -EINVAL;
- len = min_t(size_t, sizeof(buffer), data.length - data.header_length -
- data.block_descriptor_length);
- buffer_data = buffer + data.header_length +
- data.block_descriptor_length;
- buffer_data[2] &= ~0x05;
- buffer_data[2] |= wce << 2 | rcd;
- sp = buffer_data[0] & 0x80 ? 1 : 0;
-
- if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT,
- SD_MAX_RETRIES, &data, &sshdr)) {
- if (scsi_sense_valid(&sshdr))
- scsi_print_sense_hdr(sdkp->disk->disk_name, &sshdr);
- return -EINVAL;
- }
- sd_revalidate_disk(sdkp->disk);
- return count;
-}
-
-static ssize_t sd_store_allow_restart(struct class_device *cdev, const char *buf,
- size_t count)
-{
- struct scsi_disk *sdkp = to_scsi_disk(cdev);
- struct scsi_device *sdp = sdkp->device;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-
- if (sdp->type != TYPE_DISK)
- return -EINVAL;
-
- sdp->allow_restart = simple_strtoul(buf, NULL, 10);
-
- return count;
-}
-
-static ssize_t sd_show_cache_type(struct class_device *cdev, char *buf)
-{
- struct scsi_disk *sdkp = to_scsi_disk(cdev);
- int ct = sdkp->RCD + 2*sdkp->WCE;
-
- return snprintf(buf, 40, "%s\n", sd_cache_types[ct]);
-}
-
-static ssize_t sd_show_fua(struct class_device *cdev, char *buf)
-{
- struct scsi_disk *sdkp = to_scsi_disk(cdev);
-
- return snprintf(buf, 20, "%u\n", sdkp->DPOFUA);
-}
-
-static ssize_t sd_show_allow_restart(struct class_device *cdev, char *buf)
-{
- struct scsi_disk *sdkp = to_scsi_disk(cdev);
-
- return snprintf(buf, 40, "%d\n", sdkp->device->allow_restart);
-}
-
-static struct class_device_attribute sd_disk_attrs[] = {
- __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
- sd_store_cache_type),
- __ATTR(FUA, S_IRUGO, sd_show_fua, NULL),
- __ATTR(allow_restart, S_IRUGO|S_IWUSR, sd_show_allow_restart,
- sd_store_allow_restart),
- __ATTR_NULL,
-};
-
-static struct class sd_disk_class = {
- .name = "scsi_disk",
- .owner = THIS_MODULE,
- .release = scsi_disk_release,
- .class_dev_attrs = sd_disk_attrs,
-};