diff options
author | Christoph Hellwig <hch@lst.de> | 2014-10-11 12:06:47 +0200 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2014-11-12 11:16:10 +0100 |
commit | 176aa9d6ee2db582e7e856dbe1983004a82869b4 (patch) | |
tree | 5c1e97cbdc98dd9162ef6f81af19eca932f8117e /drivers/scsi/scsi_error.c | |
parent | 1ee8e889d946b3b1c2cc8b99e29eac47d1581dfd (diff) | |
download | linux-176aa9d6ee2db582e7e856dbe1983004a82869b4.tar.gz linux-176aa9d6ee2db582e7e856dbe1983004a82869b4.tar.bz2 linux-176aa9d6ee2db582e7e856dbe1983004a82869b4.zip |
scsi: refactor scsi_reset_provider handling
Pull the common code from the two callers into the function,
and rename it to scsi_ioctl_reset.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r-- | drivers/scsi/scsi_error.c | 76 |
1 files changed, 36 insertions, 40 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 95c9abb64183..a6f6b9222b51 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -36,6 +36,7 @@ #include <scsi/scsi_transport.h> #include <scsi/scsi_host.h> #include <scsi/scsi_ioctl.h> +#include <scsi/sg.h> #include "scsi_priv.h" #include "scsi_logging.h" @@ -2311,39 +2312,36 @@ scsi_reset_provider_done_command(struct scsi_cmnd *scmd) { } -/* - * Function: scsi_reset_provider - * - * Purpose: Send requested reset to a bus or device at any phase. - * - * Arguments: device - device to send reset to - * flag - reset type (see scsi.h) - * - * Returns: SUCCESS/FAILURE. - * - * Notes: This is used by the SCSI Generic driver to provide - * Bus/Device reset capability. +/** + * scsi_ioctl_reset: explicitly reset a host/bus/target/device + * @dev: scsi_device to operate on + * @arg: reset type (see sg.h) */ int -scsi_reset_provider(struct scsi_device *dev, int flag) +scsi_ioctl_reset(struct scsi_device *dev, int __user *arg) { struct scsi_cmnd *scmd; struct Scsi_Host *shost = dev->host; struct request req; unsigned long flags; - int rtn; + int error = 0, rtn, val; + + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) + return -EACCES; + + error = get_user(val, arg); + if (error) + return error; if (scsi_autopm_get_host(shost) < 0) - return FAILED; + return -EIO; - if (!get_device(&dev->sdev_gendev)) { - rtn = FAILED; + error = -EIO; + if (!get_device(&dev->sdev_gendev)) goto out_put_autopm_host; - } scmd = scsi_get_command(dev, GFP_KERNEL); if (!scmd) { - rtn = FAILED; put_device(&dev->sdev_gendev); goto out_put_autopm_host; } @@ -2364,39 +2362,37 @@ scsi_reset_provider(struct scsi_device *dev, int flag) shost->tmf_in_progress = 1; spin_unlock_irqrestore(shost->host_lock, flags); - switch (flag) { - case SCSI_TRY_RESET_DEVICE: + switch (val & ~SG_SCSI_RESET_NO_ESCALATE) { + case SG_SCSI_RESET_NOTHING: + rtn = SUCCESS; + break; + case SG_SCSI_RESET_DEVICE: rtn = scsi_try_bus_device_reset(scmd); - if (rtn == SUCCESS) + if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE)) break; /* FALLTHROUGH */ - case SCSI_TRY_RESET_TARGET: + case SG_SCSI_RESET_TARGET: rtn = scsi_try_target_reset(scmd); - if (rtn == SUCCESS) + if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE)) break; /* FALLTHROUGH */ - case SCSI_TRY_RESET_BUS: + case SG_SCSI_RESET_BUS: rtn = scsi_try_bus_reset(scmd); - if (rtn == SUCCESS) + if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE)) break; /* FALLTHROUGH */ - case SCSI_TRY_RESET_HOST: - case SCSI_TRY_RESET_HOST | SCSI_TRY_RESET_NO_ESCALATE: + case SG_SCSI_RESET_HOST: rtn = scsi_try_host_reset(scmd); - break; - case SCSI_TRY_RESET_DEVICE | SCSI_TRY_RESET_NO_ESCALATE: - rtn = scsi_try_bus_device_reset(scmd); - break; - case SCSI_TRY_RESET_TARGET | SCSI_TRY_RESET_NO_ESCALATE: - rtn = scsi_try_target_reset(scmd); - break; - case SCSI_TRY_RESET_BUS | SCSI_TRY_RESET_NO_ESCALATE: - rtn = scsi_try_bus_reset(scmd); - break; + if (rtn == SUCCESS) + break; default: + /* FALLTHROUGH */ rtn = FAILED; + break; } + error = (rtn == SUCCESS) ? 0 : -EIO; + spin_lock_irqsave(shost->host_lock, flags); shost->tmf_in_progress = 0; spin_unlock_irqrestore(shost->host_lock, flags); @@ -2416,9 +2412,9 @@ scsi_reset_provider(struct scsi_device *dev, int flag) scsi_next_command(scmd); out_put_autopm_host: scsi_autopm_put_host(shost); - return rtn; + return error; } -EXPORT_SYMBOL(scsi_reset_provider); +EXPORT_SYMBOL(scsi_ioctl_reset); /** * scsi_normalize_sense - normalize main elements from either fixed or |