summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2014-10-11 06:06:47 -0400
committerChristoph Hellwig <hch@lst.de>2014-11-12 05:16:10 -0500
commit176aa9d6ee2db582e7e856dbe1983004a82869b4 (patch)
tree5c1e97cbdc98dd9162ef6f81af19eca932f8117e /drivers/scsi
parent1ee8e889d946b3b1c2cc8b99e29eac47d1581dfd (diff)
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')
-rw-r--r--drivers/scsi/scsi_error.c76
-rw-r--r--drivers/scsi/scsi_ioctl.c33
-rw-r--r--drivers/scsi/sg.c34
3 files changed, 40 insertions, 103 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 @@
36#include <scsi/scsi_transport.h> 36#include <scsi/scsi_transport.h>
37#include <scsi/scsi_host.h> 37#include <scsi/scsi_host.h>
38#include <scsi/scsi_ioctl.h> 38#include <scsi/scsi_ioctl.h>
39#include <scsi/sg.h>
39 40
40#include "scsi_priv.h" 41#include "scsi_priv.h"
41#include "scsi_logging.h" 42#include "scsi_logging.h"
@@ -2311,39 +2312,36 @@ scsi_reset_provider_done_command(struct scsi_cmnd *scmd)
2311{ 2312{
2312} 2313}
2313 2314
2314/* 2315/**
2315 * Function: scsi_reset_provider 2316 * scsi_ioctl_reset: explicitly reset a host/bus/target/device
2316 * 2317 * @dev: scsi_device to operate on
2317 * Purpose: Send requested reset to a bus or device at any phase. 2318 * @arg: reset type (see sg.h)
2318 *
2319 * Arguments: device - device to send reset to
2320 * flag - reset type (see scsi.h)
2321 *
2322 * Returns: SUCCESS/FAILURE.
2323 *
2324 * Notes: This is used by the SCSI Generic driver to provide
2325 * Bus/Device reset capability.
2326 */ 2319 */
2327int 2320int
2328scsi_reset_provider(struct scsi_device *dev, int flag) 2321scsi_ioctl_reset(struct scsi_device *dev, int __user *arg)
2329{ 2322{
2330 struct scsi_cmnd *scmd; 2323 struct scsi_cmnd *scmd;
2331 struct Scsi_Host *shost = dev->host; 2324 struct Scsi_Host *shost = dev->host;
2332 struct request req; 2325 struct request req;
2333 unsigned long flags; 2326 unsigned long flags;
2334 int rtn; 2327 int error = 0, rtn, val;
2328
2329 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
2330 return -EACCES;
2331
2332 error = get_user(val, arg);
2333 if (error)
2334 return error;
2335 2335
2336 if (scsi_autopm_get_host(shost) < 0) 2336 if (scsi_autopm_get_host(shost) < 0)
2337 return FAILED; 2337 return -EIO;
2338 2338
2339 if (!get_device(&dev->sdev_gendev)) { 2339 error = -EIO;
2340 rtn = FAILED; 2340 if (!get_device(&dev->sdev_gendev))
2341 goto out_put_autopm_host; 2341 goto out_put_autopm_host;
2342 }
2343 2342
2344 scmd = scsi_get_command(dev, GFP_KERNEL); 2343 scmd = scsi_get_command(dev, GFP_KERNEL);
2345 if (!scmd) { 2344 if (!scmd) {
2346 rtn = FAILED;
2347 put_device(&dev->sdev_gendev); 2345 put_device(&dev->sdev_gendev);
2348 goto out_put_autopm_host; 2346 goto out_put_autopm_host;
2349 } 2347 }
@@ -2364,39 +2362,37 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
2364 shost->tmf_in_progress = 1; 2362 shost->tmf_in_progress = 1;
2365 spin_unlock_irqrestore(shost->host_lock, flags); 2363 spin_unlock_irqrestore(shost->host_lock, flags);
2366 2364
2367 switch (flag) { 2365 switch (val & ~SG_SCSI_RESET_NO_ESCALATE) {
2368 case SCSI_TRY_RESET_DEVICE: 2366 case SG_SCSI_RESET_NOTHING:
2367 rtn = SUCCESS;
2368 break;
2369 case SG_SCSI_RESET_DEVICE:
2369 rtn = scsi_try_bus_device_reset(scmd); 2370 rtn = scsi_try_bus_device_reset(scmd);
2370 if (rtn == SUCCESS) 2371 if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE))
2371 break; 2372 break;
2372 /* FALLTHROUGH */ 2373 /* FALLTHROUGH */
2373 case SCSI_TRY_RESET_TARGET: 2374 case SG_SCSI_RESET_TARGET:
2374 rtn = scsi_try_target_reset(scmd); 2375 rtn = scsi_try_target_reset(scmd);
2375 if (rtn == SUCCESS) 2376 if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE))
2376 break; 2377 break;
2377 /* FALLTHROUGH */ 2378 /* FALLTHROUGH */
2378 case SCSI_TRY_RESET_BUS: 2379 case SG_SCSI_RESET_BUS:
2379 rtn = scsi_try_bus_reset(scmd); 2380 rtn = scsi_try_bus_reset(scmd);
2380 if (rtn == SUCCESS) 2381 if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE))
2381 break; 2382 break;
2382 /* FALLTHROUGH */ 2383 /* FALLTHROUGH */
2383 case SCSI_TRY_RESET_HOST: 2384 case SG_SCSI_RESET_HOST:
2384 case SCSI_TRY_RESET_HOST | SCSI_TRY_RESET_NO_ESCALATE:
2385 rtn = scsi_try_host_reset(scmd); 2385 rtn = scsi_try_host_reset(scmd);
2386 break; 2386 if (rtn == SUCCESS)
2387 case SCSI_TRY_RESET_DEVICE | SCSI_TRY_RESET_NO_ESCALATE: 2387 break;
2388 rtn = scsi_try_bus_device_reset(scmd);
2389 break;
2390 case SCSI_TRY_RESET_TARGET | SCSI_TRY_RESET_NO_ESCALATE:
2391 rtn = scsi_try_target_reset(scmd);
2392 break;
2393 case SCSI_TRY_RESET_BUS | SCSI_TRY_RESET_NO_ESCALATE:
2394 rtn = scsi_try_bus_reset(scmd);
2395 break;
2396 default: 2388 default:
2389 /* FALLTHROUGH */
2397 rtn = FAILED; 2390 rtn = FAILED;
2391 break;
2398 } 2392 }
2399 2393
2394 error = (rtn == SUCCESS) ? 0 : -EIO;
2395
2400 spin_lock_irqsave(shost->host_lock, flags); 2396 spin_lock_irqsave(shost->host_lock, flags);
2401 shost->tmf_in_progress = 0; 2397 shost->tmf_in_progress = 0;
2402 spin_unlock_irqrestore(shost->host_lock, flags); 2398 spin_unlock_irqrestore(shost->host_lock, flags);
@@ -2416,9 +2412,9 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
2416 scsi_next_command(scmd); 2412 scsi_next_command(scmd);
2417out_put_autopm_host: 2413out_put_autopm_host:
2418 scsi_autopm_put_host(shost); 2414 scsi_autopm_put_host(shost);
2419 return rtn; 2415 return error;
2420} 2416}
2421EXPORT_SYMBOL(scsi_reset_provider); 2417EXPORT_SYMBOL(scsi_ioctl_reset);
2422 2418
2423/** 2419/**
2424 * scsi_normalize_sense - normalize main elements from either fixed or 2420 * scsi_normalize_sense - normalize main elements from either fixed or
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 5207274574f5..5ddc08f39987 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -292,8 +292,6 @@ EXPORT_SYMBOL(scsi_ioctl);
292int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, 292int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
293 void __user *arg, int ndelay) 293 void __user *arg, int ndelay)
294{ 294{
295 int val, val2, result;
296
297 /* The first set of iocts may be executed even if we're doing 295 /* The first set of iocts may be executed even if we're doing
298 * error processing, as long as the device was opened 296 * error processing, as long as the device was opened
299 * non-blocking */ 297 * non-blocking */
@@ -305,36 +303,7 @@ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
305 303
306 switch (cmd) { 304 switch (cmd) {
307 case SG_SCSI_RESET: 305 case SG_SCSI_RESET:
308 result = get_user(val, (int __user *)arg); 306 return scsi_ioctl_reset(sdev, arg);
309 if (result)
310 return result;
311 if (val & SG_SCSI_RESET_NO_ESCALATE) {
312 val &= ~SG_SCSI_RESET_NO_ESCALATE;
313 val2 = SCSI_TRY_RESET_NO_ESCALATE;
314 } else
315 val2 = 0;
316 if (val == SG_SCSI_RESET_NOTHING)
317 return 0;
318 switch (val) {
319 case SG_SCSI_RESET_DEVICE:
320 val2 |= SCSI_TRY_RESET_DEVICE;
321 break;
322 case SG_SCSI_RESET_TARGET:
323 val2 |= SCSI_TRY_RESET_TARGET;
324 break;
325 case SG_SCSI_RESET_BUS:
326 val2 |= SCSI_TRY_RESET_BUS;
327 break;
328 case SG_SCSI_RESET_HOST:
329 val2 |= SCSI_TRY_RESET_HOST;
330 break;
331 default:
332 return -EINVAL;
333 }
334 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
335 return -EACCES;
336 return (scsi_reset_provider(sdev, val2) ==
337 SUCCESS) ? 0 : -EIO;
338 } 307 }
339 return -ENODEV; 308 return -ENODEV;
340} 309}
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 2fe2701d86db..7c55cacceb7c 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -847,7 +847,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
847{ 847{
848 void __user *p = (void __user *)arg; 848 void __user *p = (void __user *)arg;
849 int __user *ip = p; 849 int __user *ip = p;
850 int result, val, val2, read_only; 850 int result, val, read_only;
851 Sg_device *sdp; 851 Sg_device *sdp;
852 Sg_fd *sfp; 852 Sg_fd *sfp;
853 Sg_request *srp; 853 Sg_request *srp;
@@ -1079,36 +1079,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
1079 return -EBUSY; 1079 return -EBUSY;
1080 } else if (!scsi_block_when_processing_errors(sdp->device)) 1080 } else if (!scsi_block_when_processing_errors(sdp->device))
1081 return -EBUSY; 1081 return -EBUSY;
1082 result = get_user(val, ip); 1082
1083 if (result) 1083 return scsi_ioctl_reset(sdp->device, ip);
1084 return result;
1085 if (val & SG_SCSI_RESET_NO_ESCALATE) {
1086 val &= ~SG_SCSI_RESET_NO_ESCALATE;
1087 val2 = SCSI_TRY_RESET_NO_ESCALATE;
1088 } else
1089 val2 = 0;
1090 if (SG_SCSI_RESET_NOTHING == val)
1091 return 0;
1092 switch (val) {
1093 case SG_SCSI_RESET_DEVICE:
1094 val2 |= SCSI_TRY_RESET_DEVICE;
1095 break;
1096 case SG_SCSI_RESET_TARGET:
1097 val2 |= SCSI_TRY_RESET_TARGET;
1098 break;
1099 case SG_SCSI_RESET_BUS:
1100 val2 |= SCSI_TRY_RESET_BUS;
1101 break;
1102 case SG_SCSI_RESET_HOST:
1103 val2 |= SCSI_TRY_RESET_HOST;
1104 break;
1105 default:
1106 return -EINVAL;
1107 }
1108 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
1109 return -EACCES;
1110 return (scsi_reset_provider(sdp->device, val2) ==
1111 SUCCESS) ? 0 : -EIO;
1112 case SCSI_IOCTL_SEND_COMMAND: 1084 case SCSI_IOCTL_SEND_COMMAND:
1113 if (atomic_read(&sdp->detaching)) 1085 if (atomic_read(&sdp->detaching))
1114 return -ENODEV; 1086 return -ENODEV;