Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 59a8a6e2 authored by Cornelia Huck's avatar Cornelia Huck Committed by Martin Schwidefsky
Browse files

[S390] cio: Use device_schedule_callback() for removing disconnected devices.



We can't deregister disconnected and orphaned devices directly from
the online attribute's store method, but must take a detour.

Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent ea1f4eec
Loading
Loading
Loading
Loading
+38 −11
Original line number Original line Diff line number Diff line
@@ -296,30 +296,57 @@ static void ccw_device_unregister(struct ccw_device *cdev)
		device_del(&cdev->dev);
		device_del(&cdev->dev);
}
}


static void ccw_device_remove_orphan_cb(struct device *dev)
{
	struct ccw_device *cdev = to_ccwdev(dev);

	ccw_device_unregister(cdev);
	put_device(&cdev->dev);
}

static void ccw_device_remove_sch_cb(struct device *dev)
{
	struct subchannel *sch;

	sch = to_subchannel(dev);
	css_sch_device_unregister(sch);
	/* Reset intparm to zeroes. */
	sch->schib.pmcw.intparm = 0;
	cio_modify(sch);
	put_device(&sch->dev);
}

static void
static void
ccw_device_remove_disconnected(struct ccw_device *cdev)
ccw_device_remove_disconnected(struct ccw_device *cdev)
{
{
	struct subchannel *sch;
	unsigned long flags;
	unsigned long flags;
	int rc;

	/*
	/*
	 * Forced offline in disconnected state means
	 * Forced offline in disconnected state means
	 * 'throw away device'.
	 * 'throw away device'.
	 */
	 */
	if (ccw_device_is_orphan(cdev)) {
	if (ccw_device_is_orphan(cdev)) {
		/* Deregister ccw device. */
		/*
		 * Deregister ccw device.
		 * Unfortunately, we cannot do this directly from the
		 * attribute method.
		 */
		spin_lock_irqsave(cdev->ccwlock, flags);
		spin_lock_irqsave(cdev->ccwlock, flags);
		cdev->private->state = DEV_STATE_NOT_OPER;
		cdev->private->state = DEV_STATE_NOT_OPER;
		spin_unlock_irqrestore(cdev->ccwlock, flags);
		spin_unlock_irqrestore(cdev->ccwlock, flags);
		ccw_device_unregister(cdev);
		rc = device_schedule_callback(&cdev->dev,
		put_device(&cdev->dev);
					      ccw_device_remove_orphan_cb);
		if (rc)
			dev_info(&cdev->dev, "Couldn't unregister orphan\n");
		return;
		return;
	}
	}
	sch = to_subchannel(cdev->dev.parent);
	/* Deregister subchannel, which will kill the ccw device. */
	css_sch_device_unregister(sch);
	rc = device_schedule_callback(cdev->dev.parent,
	/* Reset intparm to zeroes. */
				      ccw_device_remove_sch_cb);
	sch->schib.pmcw.intparm = 0;
	if (rc)
	cio_modify(sch);
		dev_info(&cdev->dev,
	put_device(&sch->dev);
			 "Couldn't unregister disconnected device\n");
}
}


int
int