diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/cio/device.c | 73 |
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 |
1584 | static struct ccw_device console_cdev; | ||
1585 | static struct ccw_device_private console_private; | ||
1586 | static int console_cdev_in_use; | ||
1587 | |||
1588 | static int ccw_device_console_enable(struct ccw_device *cdev, | 1577 | static 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; | ||
1617 | out_unlock: | 1607 | out_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 | ||
1622 | struct ccw_device * | 1614 | struct ccw_device *ccw_device_probe_console(void) |
1623 | ccw_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 | /** |