diff options
| author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2014-06-11 07:06:57 -0400 |
|---|---|---|
| committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2014-06-16 04:31:03 -0400 |
| commit | 2c3e7e15c7e420e35132aa3c0a614524cb2ab9e2 (patch) | |
| tree | dda857017edc03894035cb190b89b84538851dc8 | |
| parent | 8122574c216608ae1d5388303336c4d792bc3841 (diff) | |
s390/cio: set device name as early as possible
Currently we set the device name at the time we call device_add after
we receive the interrupt for the first I/O. When something is not working
as expected during that first I/O (e.g. we don't receive an interrupt) we
print a message including the device name which has not yet been
initialized.
Set the device name after calling device_initialize (prior to starting
the first I/O) so that we have the name present if some unexpected error
occurs during that first I/O.
Reported-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reported-by: Jason J. Herne <jjherne@linux.vnet.ibm.com>
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>
| -rw-r--r-- | drivers/s390/cio/device.c | 71 |
1 files changed, 36 insertions, 35 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index d8d9b5b5cc56..dfef5e63cb7b 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
| @@ -678,18 +678,11 @@ static const struct attribute_group *ccwdev_attr_groups[] = { | |||
| 678 | NULL, | 678 | NULL, |
| 679 | }; | 679 | }; |
| 680 | 680 | ||
| 681 | /* this is a simple abstraction for device_register that sets the | 681 | static int ccw_device_add(struct ccw_device *cdev) |
| 682 | * correct bus type and adds the bus specific files */ | ||
| 683 | static int ccw_device_register(struct ccw_device *cdev) | ||
| 684 | { | 682 | { |
| 685 | struct device *dev = &cdev->dev; | 683 | struct device *dev = &cdev->dev; |
| 686 | int ret; | ||
| 687 | 684 | ||
| 688 | dev->bus = &ccw_bus_type; | 685 | dev->bus = &ccw_bus_type; |
| 689 | ret = dev_set_name(&cdev->dev, "0.%x.%04x", cdev->private->dev_id.ssid, | ||
| 690 | cdev->private->dev_id.devno); | ||
| 691 | if (ret) | ||
| 692 | return ret; | ||
| 693 | return device_add(dev); | 686 | return device_add(dev); |
| 694 | } | 687 | } |
| 695 | 688 | ||
| @@ -764,22 +757,46 @@ static void ccw_device_todo(struct work_struct *work); | |||
| 764 | static int io_subchannel_initialize_dev(struct subchannel *sch, | 757 | static int io_subchannel_initialize_dev(struct subchannel *sch, |
| 765 | struct ccw_device *cdev) | 758 | struct ccw_device *cdev) |
| 766 | { | 759 | { |
| 767 | cdev->private->cdev = cdev; | 760 | struct ccw_device_private *priv = cdev->private; |
| 768 | cdev->private->int_class = IRQIO_CIO; | 761 | int ret; |
| 769 | atomic_set(&cdev->private->onoff, 0); | 762 | |
| 763 | priv->cdev = cdev; | ||
| 764 | priv->int_class = IRQIO_CIO; | ||
| 765 | priv->state = DEV_STATE_NOT_OPER; | ||
| 766 | priv->dev_id.devno = sch->schib.pmcw.dev; | ||
| 767 | priv->dev_id.ssid = sch->schid.ssid; | ||
| 768 | priv->schid = sch->schid; | ||
| 769 | |||
| 770 | INIT_WORK(&priv->todo_work, ccw_device_todo); | ||
| 771 | INIT_LIST_HEAD(&priv->cmb_list); | ||
| 772 | init_waitqueue_head(&priv->wait_q); | ||
| 773 | init_timer(&priv->timer); | ||
| 774 | |||
| 775 | atomic_set(&priv->onoff, 0); | ||
| 776 | cdev->ccwlock = sch->lock; | ||
| 770 | cdev->dev.parent = &sch->dev; | 777 | cdev->dev.parent = &sch->dev; |
| 771 | cdev->dev.release = ccw_device_release; | 778 | cdev->dev.release = ccw_device_release; |
| 772 | INIT_WORK(&cdev->private->todo_work, ccw_device_todo); | ||
| 773 | cdev->dev.groups = ccwdev_attr_groups; | 779 | cdev->dev.groups = ccwdev_attr_groups; |
| 774 | /* Do first half of device_register. */ | 780 | /* Do first half of device_register. */ |
| 775 | device_initialize(&cdev->dev); | 781 | device_initialize(&cdev->dev); |
| 782 | ret = dev_set_name(&cdev->dev, "0.%x.%04x", cdev->private->dev_id.ssid, | ||
| 783 | cdev->private->dev_id.devno); | ||
| 784 | if (ret) | ||
| 785 | goto out_put; | ||
| 776 | if (!get_device(&sch->dev)) { | 786 | if (!get_device(&sch->dev)) { |
| 777 | /* Release reference from device_initialize(). */ | 787 | ret = -ENODEV; |
| 778 | put_device(&cdev->dev); | 788 | goto out_put; |
| 779 | return -ENODEV; | ||
| 780 | } | 789 | } |
| 781 | cdev->private->flags.initialized = 1; | 790 | priv->flags.initialized = 1; |
| 791 | spin_lock_irq(sch->lock); | ||
| 792 | sch_set_cdev(sch, cdev); | ||
| 793 | spin_unlock_irq(sch->lock); | ||
| 782 | return 0; | 794 | return 0; |
| 795 | |||
| 796 | out_put: | ||
| 797 | /* Release reference from device_initialize(). */ | ||
| 798 | put_device(&cdev->dev); | ||
| 799 | return ret; | ||
| 783 | } | 800 | } |
| 784 | 801 | ||
| 785 | static struct ccw_device * io_subchannel_create_ccwdev(struct subchannel *sch) | 802 | static struct ccw_device * io_subchannel_create_ccwdev(struct subchannel *sch) |
| @@ -858,7 +875,7 @@ static void io_subchannel_register(struct ccw_device *cdev) | |||
| 858 | dev_set_uevent_suppress(&sch->dev, 0); | 875 | dev_set_uevent_suppress(&sch->dev, 0); |
| 859 | kobject_uevent(&sch->dev.kobj, KOBJ_ADD); | 876 | kobject_uevent(&sch->dev.kobj, KOBJ_ADD); |
| 860 | /* make it known to the system */ | 877 | /* make it known to the system */ |
| 861 | ret = ccw_device_register(cdev); | 878 | ret = ccw_device_add(cdev); |
| 862 | if (ret) { | 879 | if (ret) { |
| 863 | CIO_MSG_EVENT(0, "Could not register ccw dev 0.%x.%04x: %d\n", | 880 | CIO_MSG_EVENT(0, "Could not register ccw dev 0.%x.%04x: %d\n", |
| 864 | cdev->private->dev_id.ssid, | 881 | cdev->private->dev_id.ssid, |
| @@ -923,26 +940,11 @@ io_subchannel_recog_done(struct ccw_device *cdev) | |||
| 923 | 940 | ||
| 924 | static void io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch) | 941 | static void io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch) |
| 925 | { | 942 | { |
| 926 | struct ccw_device_private *priv; | ||
| 927 | |||
| 928 | cdev->ccwlock = sch->lock; | ||
| 929 | |||
| 930 | /* Init private data. */ | ||
| 931 | priv = cdev->private; | ||
| 932 | priv->dev_id.devno = sch->schib.pmcw.dev; | ||
| 933 | priv->dev_id.ssid = sch->schid.ssid; | ||
| 934 | priv->schid = sch->schid; | ||
| 935 | priv->state = DEV_STATE_NOT_OPER; | ||
| 936 | INIT_LIST_HEAD(&priv->cmb_list); | ||
| 937 | init_waitqueue_head(&priv->wait_q); | ||
| 938 | init_timer(&priv->timer); | ||
| 939 | |||
| 940 | /* Increase counter of devices currently in recognition. */ | 943 | /* Increase counter of devices currently in recognition. */ |
| 941 | atomic_inc(&ccw_device_init_count); | 944 | atomic_inc(&ccw_device_init_count); |
| 942 | 945 | ||
| 943 | /* Start async. device sensing. */ | 946 | /* Start async. device sensing. */ |
| 944 | spin_lock_irq(sch->lock); | 947 | spin_lock_irq(sch->lock); |
| 945 | sch_set_cdev(sch, cdev); | ||
| 946 | ccw_device_recognition(cdev); | 948 | ccw_device_recognition(cdev); |
| 947 | spin_unlock_irq(sch->lock); | 949 | spin_unlock_irq(sch->lock); |
| 948 | } | 950 | } |
| @@ -1083,7 +1085,7 @@ static int io_subchannel_probe(struct subchannel *sch) | |||
| 1083 | dev_set_uevent_suppress(&sch->dev, 0); | 1085 | dev_set_uevent_suppress(&sch->dev, 0); |
| 1084 | kobject_uevent(&sch->dev.kobj, KOBJ_ADD); | 1086 | kobject_uevent(&sch->dev.kobj, KOBJ_ADD); |
| 1085 | cdev = sch_get_cdev(sch); | 1087 | cdev = sch_get_cdev(sch); |
| 1086 | rc = ccw_device_register(cdev); | 1088 | rc = ccw_device_add(cdev); |
| 1087 | if (rc) { | 1089 | if (rc) { |
| 1088 | /* Release online reference. */ | 1090 | /* Release online reference. */ |
| 1089 | put_device(&cdev->dev); | 1091 | put_device(&cdev->dev); |
| @@ -1597,7 +1599,6 @@ int __init ccw_device_enable_console(struct ccw_device *cdev) | |||
| 1597 | if (rc) | 1599 | if (rc) |
| 1598 | return rc; | 1600 | return rc; |
| 1599 | sch->driver = &io_subchannel_driver; | 1601 | sch->driver = &io_subchannel_driver; |
| 1600 | sch_set_cdev(sch, cdev); | ||
| 1601 | io_subchannel_recog(cdev, sch); | 1602 | io_subchannel_recog(cdev, sch); |
| 1602 | /* Now wait for the async. recognition to come to an end. */ | 1603 | /* Now wait for the async. recognition to come to an end. */ |
| 1603 | spin_lock_irq(cdev->ccwlock); | 1604 | spin_lock_irq(cdev->ccwlock); |
| @@ -1639,6 +1640,7 @@ struct ccw_device * __init ccw_device_create_console(struct ccw_driver *drv) | |||
| 1639 | put_device(&sch->dev); | 1640 | put_device(&sch->dev); |
| 1640 | return ERR_PTR(-ENOMEM); | 1641 | return ERR_PTR(-ENOMEM); |
| 1641 | } | 1642 | } |
| 1643 | set_io_private(sch, io_priv); | ||
| 1642 | cdev = io_subchannel_create_ccwdev(sch); | 1644 | cdev = io_subchannel_create_ccwdev(sch); |
| 1643 | if (IS_ERR(cdev)) { | 1645 | if (IS_ERR(cdev)) { |
| 1644 | put_device(&sch->dev); | 1646 | put_device(&sch->dev); |
| @@ -1646,7 +1648,6 @@ struct ccw_device * __init ccw_device_create_console(struct ccw_driver *drv) | |||
| 1646 | return cdev; | 1648 | return cdev; |
| 1647 | } | 1649 | } |
| 1648 | cdev->drv = drv; | 1650 | cdev->drv = drv; |
| 1649 | set_io_private(sch, io_priv); | ||
| 1650 | ccw_device_set_int_class(cdev); | 1651 | ccw_device_set_int_class(cdev); |
| 1651 | return cdev; | 1652 | return cdev; |
| 1652 | } | 1653 | } |
