aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/device.c')
-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)
1087 dev_set_uevent_suppress(&sch->dev, 0); 1087 dev_set_uevent_suppress(&sch->dev, 0);
1088 kobject_uevent(&sch->dev.kobj, KOBJ_ADD); 1088 kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
1089 cdev = sch_get_cdev(sch); 1089 cdev = sch_get_cdev(sch);
1090 cdev->dev.groups = ccwdev_attr_groups; 1090 rc = ccw_device_register(cdev);
1091 device_initialize(&cdev->dev); 1091 if (rc) {
1092 cdev->private->flags.initialized = 1; 1092 /* Release online reference. */
1093 ccw_device_register(cdev); 1093 put_device(&cdev->dev);
1094 /* 1094 goto out_schedule;
1095 * Check if the device is already online. If it is 1095 }
1096 * the reference count needs to be corrected since we
1097 * didn't obtain a reference in ccw_device_set_online.
1098 */
1099 if (cdev->private->state != DEV_STATE_NOT_OPER &&
1100 cdev->private->state != DEV_STATE_OFFLINE &&
1101 cdev->private->state != DEV_STATE_BOXED)
1102 get_device(&cdev->dev);
1103 return 0; 1096 return 0;
1104 } 1097 }
1105 io_subchannel_init_fields(sch); 1098 io_subchannel_init_fields(sch);
@@ -1581,10 +1574,6 @@ out:
1581} 1574}
1582 1575
1583#ifdef CONFIG_CCW_CONSOLE 1576#ifdef CONFIG_CCW_CONSOLE
1584static struct ccw_device console_cdev;
1585static struct ccw_device_private console_private;
1586static int console_cdev_in_use;
1587
1588static int ccw_device_console_enable(struct ccw_device *cdev, 1577static int ccw_device_console_enable(struct ccw_device *cdev,
1589 struct subchannel *sch) 1578 struct subchannel *sch)
1590{ 1579{
@@ -1595,8 +1584,6 @@ static int ccw_device_console_enable(struct ccw_device *cdev,
1595 if (rc) 1584 if (rc)
1596 return rc; 1585 return rc;
1597 sch->driver = &io_subchannel_driver; 1586 sch->driver = &io_subchannel_driver;
1598 /* Initialize the ccw_device structure. */
1599 cdev->dev.parent= &sch->dev;
1600 sch_set_cdev(sch, cdev); 1587 sch_set_cdev(sch, cdev);
1601 io_subchannel_recog(cdev, sch); 1588 io_subchannel_recog(cdev, sch);
1602 /* Now wait for the async. recognition to come to an end. */ 1589 /* 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,
1604 while (!dev_fsm_final_state(cdev)) 1591 while (!dev_fsm_final_state(cdev))
1605 ccw_device_wait_idle(cdev); 1592 ccw_device_wait_idle(cdev);
1606 1593
1607 rc = -EIO; 1594 /* Hold on to an extra reference while device is online. */
1608 if (cdev->private->state != DEV_STATE_OFFLINE) 1595 get_device(&cdev->dev);
1596 rc = ccw_device_online(cdev);
1597 if (rc)
1609 goto out_unlock; 1598 goto out_unlock;
1610 ccw_device_online(cdev); 1599
1611 while (!dev_fsm_final_state(cdev)) 1600 while (!dev_fsm_final_state(cdev))
1612 ccw_device_wait_idle(cdev); 1601 ccw_device_wait_idle(cdev);
1613 1602
1614 if (cdev->private->state != DEV_STATE_ONLINE) 1603 if (cdev->private->state == DEV_STATE_ONLINE)
1615 goto out_unlock; 1604 cdev->online = 1;
1616 rc = 0; 1605 else
1606 rc = -EIO;
1617out_unlock: 1607out_unlock:
1618 spin_unlock_irq(cdev->ccwlock); 1608 spin_unlock_irq(cdev->ccwlock);
1609 if (rc) /* Give up online reference since onlining failed. */
1610 put_device(&cdev->dev);
1619 return rc; 1611 return rc;
1620} 1612}
1621 1613
1622struct ccw_device * 1614struct ccw_device *ccw_device_probe_console(void)
1623ccw_device_probe_console(void)
1624{ 1615{
1625 struct io_subchannel_private *io_priv; 1616 struct io_subchannel_private *io_priv;
1617 struct ccw_device *cdev;
1626 struct subchannel *sch; 1618 struct subchannel *sch;
1627 int ret; 1619 int ret;
1628 1620
1629 if (xchg(&console_cdev_in_use, 1) != 0)
1630 return ERR_PTR(-EBUSY);
1631 sch = cio_probe_console(); 1621 sch = cio_probe_console();
1632 if (IS_ERR(sch)) { 1622 if (IS_ERR(sch))
1633 console_cdev_in_use = 0; 1623 return ERR_CAST(sch);
1634 return (void *) sch;
1635 }
1636 memset(&console_cdev, 0, sizeof(struct ccw_device));
1637 memset(&console_private, 0, sizeof(struct ccw_device_private));
1638 console_cdev.private = &console_private;
1639 console_private.cdev = &console_cdev;
1640 console_private.int_class = IRQIO_CIO;
1641 1624
1642 io_priv = kzalloc(sizeof(*io_priv), GFP_KERNEL | GFP_DMA); 1625 io_priv = kzalloc(sizeof(*io_priv), GFP_KERNEL | GFP_DMA);
1643 if (!io_priv) { 1626 if (!io_priv) {
1644 put_device(&sch->dev); 1627 put_device(&sch->dev);
1645 return ERR_PTR(-ENOMEM); 1628 return ERR_PTR(-ENOMEM);
1646 } 1629 }
1630 cdev = io_subchannel_create_ccwdev(sch);
1631 if (IS_ERR(cdev)) {
1632 put_device(&sch->dev);
1633 kfree(io_priv);
1634 return cdev;
1635 }
1647 set_io_private(sch, io_priv); 1636 set_io_private(sch, io_priv);
1648 1637 ret = ccw_device_console_enable(cdev, sch);
1649 ret = ccw_device_console_enable(&console_cdev, sch);
1650 if (ret) { 1638 if (ret) {
1651 console_cdev_in_use = 0;
1652 set_io_private(sch, NULL); 1639 set_io_private(sch, NULL);
1653 put_device(&sch->dev); 1640 put_device(&sch->dev);
1641 put_device(&cdev->dev);
1654 kfree(io_priv); 1642 kfree(io_priv);
1655 return ERR_PTR(ret); 1643 return ERR_PTR(ret);
1656 } 1644 }
1657 console_cdev.online = 1; 1645 return cdev;
1658 return &console_cdev;
1659} 1646}
1660 1647
1661/** 1648/**