summaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device_ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/device_ops.c')
-rw-r--r--drivers/s390/cio/device_ops.c50
1 files changed, 27 insertions, 23 deletions
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 151754d5474..2d0efee8a29 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -1,10 +1,8 @@
/*
- * drivers/s390/cio/device_ops.c
+ * Copyright IBM Corp. 2002, 2009
*
- * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
- * IBM Corporation
- * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
- * Cornelia Huck (cornelia.huck@de.ibm.com)
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
*/
#include <linux/module.h>
#include <linux/init.h>
@@ -114,16 +112,17 @@ int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
struct subchannel *sch;
int ret;
- if (!cdev)
+ if (!cdev || !cdev->dev.parent)
return -ENODEV;
+ sch = to_subchannel(cdev->dev.parent);
+ if (!sch->schib.pmcw.ena)
+ return -EINVAL;
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
if (cdev->private->state != DEV_STATE_ONLINE &&
cdev->private->state != DEV_STATE_W4SENSE)
return -EINVAL;
- sch = to_subchannel(cdev->dev.parent);
- if (!sch)
- return -ENODEV;
+
ret = cio_clear(sch);
if (ret == 0)
cdev->private->intparm = intparm;
@@ -161,11 +160,11 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
struct subchannel *sch;
int ret;
- if (!cdev)
+ if (!cdev || !cdev->dev.parent)
return -ENODEV;
sch = to_subchannel(cdev->dev.parent);
- if (!sch)
- return -ENODEV;
+ if (!sch->schib.pmcw.ena)
+ return -EINVAL;
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
if (cdev->private->state == DEV_STATE_VERIFY ||
@@ -339,16 +338,17 @@ int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
struct subchannel *sch;
int ret;
- if (!cdev)
+ if (!cdev || !cdev->dev.parent)
return -ENODEV;
+ sch = to_subchannel(cdev->dev.parent);
+ if (!sch->schib.pmcw.ena)
+ return -EINVAL;
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
if (cdev->private->state != DEV_STATE_ONLINE &&
cdev->private->state != DEV_STATE_W4SENSE)
return -EINVAL;
- sch = to_subchannel(cdev->dev.parent);
- if (!sch)
- return -ENODEV;
+
ret = cio_halt(sch);
if (ret == 0)
cdev->private->intparm = intparm;
@@ -372,11 +372,11 @@ int ccw_device_resume(struct ccw_device *cdev)
{
struct subchannel *sch;
- if (!cdev)
+ if (!cdev || !cdev->dev.parent)
return -ENODEV;
sch = to_subchannel(cdev->dev.parent);
- if (!sch)
- return -ENODEV;
+ if (!sch->schib.pmcw.ena)
+ return -EINVAL;
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
if (cdev->private->state != DEV_STATE_ONLINE ||
@@ -471,11 +471,11 @@ __u8 ccw_device_get_path_mask(struct ccw_device *cdev)
{
struct subchannel *sch;
- sch = to_subchannel(cdev->dev.parent);
- if (!sch)
+ if (!cdev->dev.parent)
return 0;
- else
- return sch->lpm;
+
+ sch = to_subchannel(cdev->dev.parent);
+ return sch->lpm;
}
/*
@@ -588,6 +588,8 @@ int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw,
int rc;
sch = to_subchannel(cdev->dev.parent);
+ if (!sch->schib.pmcw.ena)
+ return -EINVAL;
if (cdev->private->state != DEV_STATE_ONLINE)
return -EIO;
/* Adjust requested path mask to excluded varied off paths. */
@@ -677,6 +679,8 @@ int ccw_device_tm_intrg(struct ccw_device *cdev)
{
struct subchannel *sch = to_subchannel(cdev->dev.parent);
+ if (!sch->schib.pmcw.ena)
+ return -EINVAL;
if (cdev->private->state != DEV_STATE_ONLINE)
return -EIO;
if (!scsw_is_tm(&sch->schib.scsw) ||