From 5fb6b8544d9ccd2ed478af777f9e99e342eb8886 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 25 Dec 2008 13:39:08 +0100 Subject: [PATCH] [S390] cio: Only register ccw_device for registered subchannel. There is a race between io_subchannel_register() and io_subchannel_sch_event() which may cause a subchannel to be unregistered because it is no longer operational before io_subchannel_register() had run. We need to check whether the subchannel is still registered before the ccw device can be registered and just bail out if it is not. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index cba33aa..91acea1 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -950,6 +950,14 @@ io_subchannel_register(struct work_struct *work) priv = container_of(work, struct ccw_device_private, kick_work); cdev = priv->cdev; sch = to_subchannel(cdev->dev.parent); + /* + * Check if subchannel is still registered. It may have become + * unregistered if a machine check hit us after finishing + * device recognition but before the register work could be + * queued. + */ + if (!device_is_registered(&sch->dev)) + goto out_err; css_update_ssd_info(sch); /* * io_subchannel_register() will also be called after device @@ -984,18 +992,16 @@ io_subchannel_register(struct work_struct *work) spin_lock_irqsave(sch->lock, flags); sch_set_cdev(sch, NULL); spin_unlock_irqrestore(sch->lock, flags); - /* Release reference for workqueue processing. */ - put_device(&cdev->dev); /* Release initial device reference. */ put_device(&cdev->dev); - if (atomic_dec_and_test(&ccw_device_init_count)) - wake_up(&ccw_device_init_wq); - return; + goto out_err; } - put_device(&cdev->dev); out: cdev->private->flags.recog_done = 1; wake_up(&cdev->private->wait_q); +out_err: + /* Release reference for workqueue processing. */ + put_device(&cdev->dev); if (atomic_dec_and_test(&ccw_device_init_count)) wake_up(&ccw_device_init_wq); } -- 2.7.4