Skip to content

Commit 9daa5a8

Browse files
vneethvhcahca
authored andcommitted
s390/cio: Update purge function to unregister the unused subchannels
Starting with 'commit 2297791 ("s390/cio: dont unregister subchannel from child-drivers")', cio no longer unregisters subchannels when the attached device is invalid or unavailable. As an unintended side-effect, the cio_ignore purge function no longer removes subchannels for devices on the cio_ignore list if no CCW device is attached. This situation occurs when a CCW device is non-operational or unavailable To ensure the same outcome of the purge function as when the current cio_ignore list had been active during boot, update the purge function to remove I/O subchannels without working CCW devices if the associated device number is found on the cio_ignore list. Fixes: 2297791 ("s390/cio: dont unregister subchannel from child-drivers") Suggested-by: Peter Oberparleiter <oberpar@linux.ibm.com> Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com> Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
1 parent b043a81 commit 9daa5a8

File tree

1 file changed

+24
-13
lines changed

1 file changed

+24
-13
lines changed

drivers/s390/cio/device.c

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,23 +1316,34 @@ void ccw_device_schedule_recovery(void)
13161316
spin_unlock_irqrestore(&recovery_lock, flags);
13171317
}
13181318

1319-
static int purge_fn(struct device *dev, void *data)
1319+
static int purge_fn(struct subchannel *sch, void *data)
13201320
{
1321-
struct ccw_device *cdev = to_ccwdev(dev);
1322-
struct ccw_dev_id *id = &cdev->private->dev_id;
1323-
struct subchannel *sch = to_subchannel(cdev->dev.parent);
1321+
struct ccw_device *cdev;
13241322

1325-
spin_lock_irq(cdev->ccwlock);
1326-
if (is_blacklisted(id->ssid, id->devno) &&
1327-
(cdev->private->state == DEV_STATE_OFFLINE) &&
1328-
(atomic_cmpxchg(&cdev->private->onoff, 0, 1) == 0)) {
1329-
CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", id->ssid,
1330-
id->devno);
1323+
spin_lock_irq(&sch->lock);
1324+
if (sch->st != SUBCHANNEL_TYPE_IO || !sch->schib.pmcw.dnv)
1325+
goto unlock;
1326+
1327+
if (!is_blacklisted(sch->schid.ssid, sch->schib.pmcw.dev))
1328+
goto unlock;
1329+
1330+
cdev = sch_get_cdev(sch);
1331+
if (cdev) {
1332+
if (cdev->private->state != DEV_STATE_OFFLINE)
1333+
goto unlock;
1334+
1335+
if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0)
1336+
goto unlock;
13311337
ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
1332-
css_sched_sch_todo(sch, SCH_TODO_UNREG);
13331338
atomic_set(&cdev->private->onoff, 0);
13341339
}
1335-
spin_unlock_irq(cdev->ccwlock);
1340+
1341+
css_sched_sch_todo(sch, SCH_TODO_UNREG);
1342+
CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x%s\n", sch->schid.ssid,
1343+
sch->schib.pmcw.dev, cdev ? "" : " (no cdev)");
1344+
1345+
unlock:
1346+
spin_unlock_irq(&sch->lock);
13361347
/* Abort loop in case of pending signal. */
13371348
if (signal_pending(current))
13381349
return -EINTR;
@@ -1348,7 +1359,7 @@ static int purge_fn(struct device *dev, void *data)
13481359
int ccw_purge_blacklisted(void)
13491360
{
13501361
CIO_MSG_EVENT(2, "ccw: purging blacklisted devices\n");
1351-
bus_for_each_dev(&ccw_bus_type, NULL, NULL, purge_fn);
1362+
for_each_subchannel_staged(purge_fn, NULL, NULL);
13521363
return 0;
13531364
}
13541365

0 commit comments

Comments
 (0)