summaryrefslogtreecommitdiff
path: root/drivers/s390
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2013-04-13 15:03:03 +0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-04-17 16:07:32 +0400
commitafdfed0f86d192c9957996d58d51c06ff2b9cb44 (patch)
treef81c16aa5b6561e4988cdb4c78ea657c85f3f459 /drivers/s390
parent863fc8492734822b95671780db803cd9a4b7d923 (diff)
downloadlinux-afdfed0f86d192c9957996d58d51c06ff2b9cb44.tar.xz
s390/cio: get rid of static console device
Remove the static console ccw device (and friends) and use dynamic allocation for these structures. With this change the console device is treated (mostly) like any other ccw device and we can remove some special cases. Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/cio/device.c73
1 files changed, 30 insertions, 43 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 25d04b7b5109..41a16785be29 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1087,19 +1087,12 @@ static int io_subchannel_probe(struct subchannel *sch)
dev_set_uevent_suppress(&sch->dev, 0);
kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
cdev = sch_get_cdev(sch);
- cdev->dev.groups = ccwdev_attr_groups;
- device_initialize(&cdev->dev);
- cdev->private->flags.initialized = 1;
- ccw_device_register(cdev);
- /*
- * Check if the device is already online. If it is
- * the reference count needs to be corrected since we
- * didn't obtain a reference in ccw_device_set_online.
- */
- if (cdev->private->state != DEV_STATE_NOT_OPER &&
- cdev->private->state != DEV_STATE_OFFLINE &&
- cdev->private->state != DEV_STATE_BOXED)
- get_device(&cdev->dev);
+ rc = ccw_device_register(cdev);
+ if (rc) {
+ /* Release online reference. */
+ put_device(&cdev->dev);
+ goto out_schedule;
+ }
return 0;
}
io_subchannel_init_fields(sch);
@@ -1581,10 +1574,6 @@ out:
}
#ifdef CONFIG_CCW_CONSOLE
-static struct ccw_device console_cdev;
-static struct ccw_device_private console_private;
-static int console_cdev_in_use;
-
static int ccw_device_console_enable(struct ccw_device *cdev,
struct subchannel *sch)
{
@@ -1595,8 +1584,6 @@ static int ccw_device_console_enable(struct ccw_device *cdev,
if (rc)
return rc;
sch->driver = &io_subchannel_driver;
- /* Initialize the ccw_device structure. */
- cdev->dev.parent= &sch->dev;
sch_set_cdev(sch, cdev);
io_subchannel_recog(cdev, sch);
/* Now wait for the async. recognition to come to an end. */
@@ -1604,58 +1591,58 @@ static int ccw_device_console_enable(struct ccw_device *cdev,
while (!dev_fsm_final_state(cdev))
ccw_device_wait_idle(cdev);
- rc = -EIO;
- if (cdev->private->state != DEV_STATE_OFFLINE)
+ /* Hold on to an extra reference while device is online. */
+ get_device(&cdev->dev);
+ rc = ccw_device_online(cdev);
+ if (rc)
goto out_unlock;
- ccw_device_online(cdev);
+
while (!dev_fsm_final_state(cdev))
ccw_device_wait_idle(cdev);
- if (cdev->private->state != DEV_STATE_ONLINE)
- goto out_unlock;
- rc = 0;
+ if (cdev->private->state == DEV_STATE_ONLINE)
+ cdev->online = 1;
+ else
+ rc = -EIO;
out_unlock:
spin_unlock_irq(cdev->ccwlock);
+ if (rc) /* Give up online reference since onlining failed. */
+ put_device(&cdev->dev);
return rc;
}
-struct ccw_device *
-ccw_device_probe_console(void)
+struct ccw_device *ccw_device_probe_console(void)
{
struct io_subchannel_private *io_priv;
+ struct ccw_device *cdev;
struct subchannel *sch;
int ret;
- if (xchg(&console_cdev_in_use, 1) != 0)
- return ERR_PTR(-EBUSY);
sch = cio_probe_console();
- if (IS_ERR(sch)) {
- console_cdev_in_use = 0;
- return (void *) sch;
- }
- memset(&console_cdev, 0, sizeof(struct ccw_device));
- memset(&console_private, 0, sizeof(struct ccw_device_private));
- console_cdev.private = &console_private;
- console_private.cdev = &console_cdev;
- console_private.int_class = IRQIO_CIO;
+ if (IS_ERR(sch))
+ return ERR_CAST(sch);
io_priv = kzalloc(sizeof(*io_priv), GFP_KERNEL | GFP_DMA);
if (!io_priv) {
put_device(&sch->dev);
return ERR_PTR(-ENOMEM);
}
+ cdev = io_subchannel_create_ccwdev(sch);
+ if (IS_ERR(cdev)) {
+ put_device(&sch->dev);
+ kfree(io_priv);
+ return cdev;
+ }
set_io_private(sch, io_priv);
-
- ret = ccw_device_console_enable(&console_cdev, sch);
+ ret = ccw_device_console_enable(cdev, sch);
if (ret) {
- console_cdev_in_use = 0;
set_io_private(sch, NULL);
put_device(&sch->dev);
+ put_device(&cdev->dev);
kfree(io_priv);
return ERR_PTR(ret);
}
- console_cdev.online = 1;
- return &console_cdev;
+ return cdev;
}
/**