aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVineeth Vijayan <vneethv@linux.ibm.com>2026-09-10 11:32:02 +0200
committerHeiko Carstens <hca@linux.ibm.com>2026-09-17 06:59:41 +0200
commitf6f2985eabdb2bfdc82ce90a1ea3ec53ba795f34 (patch)
tree7488713f727af4adf543aec4a6ec59fb19c8261d
parents390/cio: Fix cio_update_schib() to not cache invalid schib (diff)
s390/cio: Check pmcw.dnv before pmcw.ena in I/O entry points
The device number valid (dnv) bit in the PMCW must be checked before acting on any other PMCW fields for IO-type subchannels. A subchannel with dnv=0 has no valid device number associated, making it meaningless to evaluate the enabled (ena) state or issue any I/O instruction against it. Reported-by: William Bezenah <wbezenah@linux.ibm.com> Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com> Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com> Fixes: 8c58a229688c ("s390/cio: Do not unregister the subchannel based on DNV") Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
-rw-r--r--drivers/s390/cio/device_ops.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 61c07b4a0fe8..c1ba4a19368f 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -142,6 +142,8 @@ int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
if (!cdev || !cdev->dev.parent)
return -ENODEV;
sch = to_subchannel(cdev->dev.parent);
+ if (!sch->schib.pmcw.dnv)
+ return -ENODEV;
if (!sch->schib.pmcw.ena)
return -EINVAL;
if (cdev->private->state == DEV_STATE_NOT_OPER)
@@ -198,6 +200,8 @@ int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,
if (!cdev || !cdev->dev.parent)
return -ENODEV;
sch = to_subchannel(cdev->dev.parent);
+ if (!sch->schib.pmcw.dnv)
+ return -ENODEV;
if (!sch->schib.pmcw.ena)
return -EINVAL;
if (cdev->private->state == DEV_STATE_NOT_OPER)
@@ -379,6 +383,8 @@ int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
if (!cdev || !cdev->dev.parent)
return -ENODEV;
sch = to_subchannel(cdev->dev.parent);
+ if (!sch->schib.pmcw.dnv)
+ return -ENODEV;
if (!sch->schib.pmcw.ena)
return -EINVAL;
if (cdev->private->state == DEV_STATE_NOT_OPER)
@@ -413,6 +419,8 @@ int ccw_device_resume(struct ccw_device *cdev)
if (!cdev || !cdev->dev.parent)
return -ENODEV;
sch = to_subchannel(cdev->dev.parent);
+ if (!sch->schib.pmcw.dnv)
+ return -ENODEV;
if (!sch->schib.pmcw.ena)
return -EINVAL;
if (cdev->private->state == DEV_STATE_NOT_OPER)
@@ -548,6 +556,8 @@ int ccw_device_tm_start_timeout_key(struct ccw_device *cdev, struct tcw *tcw,
int rc;
sch = to_subchannel(cdev->dev.parent);
+ if (!sch->schib.pmcw.dnv)
+ return -ENODEV;
if (!sch->schib.pmcw.ena)
return -EINVAL;
if (cdev->private->state == DEV_STATE_VERIFY) {
@@ -694,6 +704,8 @@ int ccw_device_tm_intrg(struct ccw_device *cdev)
{
struct subchannel *sch = to_subchannel(cdev->dev.parent);
+ if (!sch->schib.pmcw.dnv)
+ return -ENODEV;
if (!sch->schib.pmcw.ena)
return -EINVAL;
if (cdev->private->state != DEV_STATE_ONLINE)