summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_ioctl.c')
-rw-r--r--drivers/scsi/scsi_ioctl.c74
1 files changed, 14 insertions, 60 deletions
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 1aaaf43c680..c4f7b56fa6f 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -126,7 +126,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
sdev_printk(KERN_INFO, sdev,
"ioctl_internal_command return code = %x\n",
result);
- scsi_print_sense_hdr(" ", &sshdr);
+ scsi_print_sense_hdr(sdev, NULL, &sshdr);
break;
}
}
@@ -200,19 +200,6 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
{
char scsi_cmd[MAX_COMMAND_SIZE];
- /* No idea how this happens.... */
- if (!sdev)
- return -ENXIO;
-
- /*
- * If we are in the middle of error recovery, don't let anyone
- * else try and use this device. Also, if error recovery fails, it
- * may try and take the device offline, in which case all further
- * access to the device is prohibited.
- */
- if (!scsi_block_when_processing_errors(sdev))
- return -ENODEV;
-
/* Check for deprecated ioctls ... all the ioctls which don't
* follow the new unique numbering scheme are deprecated */
switch (cmd) {
@@ -273,6 +260,8 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
START_STOP_TIMEOUT, NORMAL_RETRIES);
case SCSI_IOCTL_GET_PCI:
return scsi_ioctl_get_pci(sdev, arg);
+ case SG_SCSI_RESET:
+ return scsi_ioctl_reset(sdev, arg);
default:
if (sdev->host->hostt->ioctl)
return sdev->host->hostt->ioctl(sdev, cmd, arg);
@@ -281,55 +270,20 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
}
EXPORT_SYMBOL(scsi_ioctl);
-/**
- * scsi_nonblockable_ioctl() - Handle SG_SCSI_RESET
- * @sdev: scsi device receiving ioctl
- * @cmd: Must be SC_SCSI_RESET
- * @arg: pointer to int containing SG_SCSI_RESET_{DEVICE,BUS,HOST}
- * @ndelay: file mode O_NDELAY flag
+/*
+ * We can process a reset even when a device isn't fully operable.
*/
-int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
- void __user *arg, int ndelay)
+int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev, int cmd,
+ bool ndelay)
{
- int val, result;
-
- /* The first set of iocts may be executed even if we're doing
- * error processing, as long as the device was opened
- * non-blocking */
- if (ndelay) {
+ if (cmd == SG_SCSI_RESET && ndelay) {
if (scsi_host_in_recovery(sdev->host))
+ return -EAGAIN;
+ } else {
+ if (!scsi_block_when_processing_errors(sdev))
return -ENODEV;
- } else if (!scsi_block_when_processing_errors(sdev))
- return -ENODEV;
-
- switch (cmd) {
- case SG_SCSI_RESET:
- result = get_user(val, (int __user *)arg);
- if (result)
- return result;
- if (val == SG_SCSI_RESET_NOTHING)
- return 0;
- switch (val) {
- case SG_SCSI_RESET_DEVICE:
- val = SCSI_TRY_RESET_DEVICE;
- break;
- case SG_SCSI_RESET_TARGET:
- val = SCSI_TRY_RESET_TARGET;
- break;
- case SG_SCSI_RESET_BUS:
- val = SCSI_TRY_RESET_BUS;
- break;
- case SG_SCSI_RESET_HOST:
- val = SCSI_TRY_RESET_HOST;
- break;
- default:
- return -EINVAL;
- }
- if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
- return -EACCES;
- return (scsi_reset_provider(sdev, val) ==
- SUCCESS) ? 0 : -EIO;
}
- return -ENODEV;
+
+ return 0;
}
-EXPORT_SYMBOL(scsi_nonblockable_ioctl);
+EXPORT_SYMBOL_GPL(scsi_ioctl_block_when_processing_errors);