aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2014-01-27 07:28:10 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2014-02-21 02:50:12 -0500
commit1e5320960510d6d6f2cbdc7ed33df9791283b7ea (patch)
tree85e3fbb9184567856ad88125d7edb7a93e4bd059 /drivers/s390
parent2253e8d79237c69086ded391e6767afe16972527 (diff)
s390/cio: reorder initialization of ccw consoles
Drivers for ccw consoles use ccw_device_probe_console to receive an initialized ccw device which is already enabled for interrupts. After that the device driver does the initialization of its private data. This can race with unsolicited interrupts which can happen once the device is enabled for interrupts. Split ccw_device_probe_console into ccw_device_create_console and ccw_device_enable_console and reorder the initialization of the ccw console drivers. While at it mark these functions as __init. 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/char/con3215.c8
-rw-r--r--drivers/s390/char/raw3270.c9
-rw-r--r--drivers/s390/cio/device.c29
3 files changed, 32 insertions, 14 deletions
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index bb86494e2b7b..5af7f0bd6125 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -922,7 +922,7 @@ static int __init con3215_init(void)
922 raw3215_freelist = req; 922 raw3215_freelist = req;
923 } 923 }
924 924
925 cdev = ccw_device_probe_console(&raw3215_ccw_driver); 925 cdev = ccw_device_create_console(&raw3215_ccw_driver);
926 if (IS_ERR(cdev)) 926 if (IS_ERR(cdev))
927 return -ENODEV; 927 return -ENODEV;
928 928
@@ -932,6 +932,12 @@ static int __init con3215_init(void)
932 cdev->handler = raw3215_irq; 932 cdev->handler = raw3215_irq;
933 933
934 raw->flags |= RAW3215_FIXED; 934 raw->flags |= RAW3215_FIXED;
935 if (ccw_device_enable_console(cdev)) {
936 ccw_device_destroy_console(cdev);
937 raw3215_free_info(raw);
938 raw3215[0] = NULL;
939 return -ENODEV;
940 }
935 941
936 /* Request the console irq */ 942 /* Request the console irq */
937 if (raw3215_startup(raw) != 0) { 943 if (raw3215_startup(raw) != 0) {
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index de2c0483949f..041c65bc7bb1 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -790,7 +790,7 @@ struct raw3270 __init *raw3270_setup_console(void)
790 char *ascebc; 790 char *ascebc;
791 int rc; 791 int rc;
792 792
793 cdev = ccw_device_probe_console(&raw3270_ccw_driver); 793 cdev = ccw_device_create_console(&raw3270_ccw_driver);
794 if (IS_ERR(cdev)) 794 if (IS_ERR(cdev))
795 return ERR_CAST(cdev); 795 return ERR_CAST(cdev);
796 796
@@ -800,6 +800,13 @@ struct raw3270 __init *raw3270_setup_console(void)
800 if (rc) 800 if (rc)
801 return ERR_PTR(rc); 801 return ERR_PTR(rc);
802 set_bit(RAW3270_FLAGS_CONSOLE, &rp->flags); 802 set_bit(RAW3270_FLAGS_CONSOLE, &rp->flags);
803
804 rc = ccw_device_enable_console(cdev);
805 if (rc) {
806 ccw_device_destroy_console(cdev);
807 return ERR_PTR(rc);
808 }
809
803 spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags); 810 spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
804 do { 811 do {
805 __raw3270_reset_device(rp); 812 __raw3270_reset_device(rp);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 4283dd3cdd49..da431992fd8e 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1572,11 +1572,14 @@ out:
1572} 1572}
1573 1573
1574#ifdef CONFIG_CCW_CONSOLE 1574#ifdef CONFIG_CCW_CONSOLE
1575static int ccw_device_console_enable(struct ccw_device *cdev, 1575int __init ccw_device_enable_console(struct ccw_device *cdev)
1576 struct subchannel *sch)
1577{ 1576{
1577 struct subchannel *sch = to_subchannel(cdev->dev.parent);
1578 int rc; 1578 int rc;
1579 1579
1580 if (!cdev->drv || !cdev->handler)
1581 return -EINVAL;
1582
1580 io_subchannel_init_fields(sch); 1583 io_subchannel_init_fields(sch);
1581 rc = cio_commit_config(sch); 1584 rc = cio_commit_config(sch);
1582 if (rc) 1585 if (rc)
@@ -1609,12 +1612,11 @@ out_unlock:
1609 return rc; 1612 return rc;
1610} 1613}
1611 1614
1612struct ccw_device *ccw_device_probe_console(struct ccw_driver *drv) 1615struct ccw_device * __init ccw_device_create_console(struct ccw_driver *drv)
1613{ 1616{
1614 struct io_subchannel_private *io_priv; 1617 struct io_subchannel_private *io_priv;
1615 struct ccw_device *cdev; 1618 struct ccw_device *cdev;
1616 struct subchannel *sch; 1619 struct subchannel *sch;
1617 int ret;
1618 1620
1619 sch = cio_probe_console(); 1621 sch = cio_probe_console();
1620 if (IS_ERR(sch)) 1622 if (IS_ERR(sch))
@@ -1633,17 +1635,20 @@ struct ccw_device *ccw_device_probe_console(struct ccw_driver *drv)
1633 } 1635 }
1634 cdev->drv = drv; 1636 cdev->drv = drv;
1635 set_io_private(sch, io_priv); 1637 set_io_private(sch, io_priv);
1636 ret = ccw_device_console_enable(cdev, sch);
1637 if (ret) {
1638 set_io_private(sch, NULL);
1639 put_device(&sch->dev);
1640 put_device(&cdev->dev);
1641 kfree(io_priv);
1642 return ERR_PTR(ret);
1643 }
1644 return cdev; 1638 return cdev;
1645} 1639}
1646 1640
1641void __init ccw_device_destroy_console(struct ccw_device *cdev)
1642{
1643 struct subchannel *sch = to_subchannel(cdev->dev.parent);
1644 struct io_subchannel_private *io_priv = to_io_private(sch);
1645
1646 set_io_private(sch, NULL);
1647 put_device(&sch->dev);
1648 put_device(&cdev->dev);
1649 kfree(io_priv);
1650}
1651
1647/** 1652/**
1648 * ccw_device_wait_idle() - busy wait for device to become idle 1653 * ccw_device_wait_idle() - busy wait for device to become idle
1649 * @cdev: ccw device 1654 * @cdev: ccw device