diff options
Diffstat (limited to 'drivers/scsi/scsi_ioctl.c')
-rw-r--r-- | drivers/scsi/scsi_ioctl.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 1aaaf43..12fe676 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -285,13 +285,14 @@ 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} + * @arg: pointer to int containing SG_SCSI_RESET_{DEVICE,TARGET,BUS,HOST} + * possibly OR-ed with SG_SCSI_RESET_NO_ESCALATE * @ndelay: file mode O_NDELAY flag */ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, void __user *arg, int ndelay) { - int val, result; + int val, val2, result; /* The first set of iocts may be executed even if we're doing * error processing, as long as the device was opened @@ -307,27 +308,32 @@ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, result = get_user(val, (int __user *)arg); if (result) return result; + if (val & SG_SCSI_RESET_NO_ESCALATE) { + val &= ~SG_SCSI_RESET_NO_ESCALATE; + val2 = SCSI_TRY_RESET_NO_ESCALATE; + } else + val2 = 0; if (val == SG_SCSI_RESET_NOTHING) return 0; switch (val) { case SG_SCSI_RESET_DEVICE: - val = SCSI_TRY_RESET_DEVICE; + val2 |= SCSI_TRY_RESET_DEVICE; break; case SG_SCSI_RESET_TARGET: - val = SCSI_TRY_RESET_TARGET; + val2 |= SCSI_TRY_RESET_TARGET; break; case SG_SCSI_RESET_BUS: - val = SCSI_TRY_RESET_BUS; + val2 |= SCSI_TRY_RESET_BUS; break; case SG_SCSI_RESET_HOST: - val = SCSI_TRY_RESET_HOST; + val2 |= 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) == + return (scsi_reset_provider(sdev, val2) == SUCCESS) ? 0 : -EIO; } return -ENODEV; |