aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2018-03-15 10:03:43 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2018-03-26 10:13:06 -0400
commit135a8b4ce5d737115571f08c6d0649f1aed6a48a (patch)
tree2c604872a0bea58568e5435a11797333364d53eb
parent88bf319fc2d6d971ef8692c2cae7f96708340461 (diff)
s390/cio: fix unbind of io_subchannel_driver
If the io_subchannel_driver is unbound from a subchannel it bluntly kills all I/O on the subchannel and sets the ccw_device state to not operable before deregistering the ccw_device. However, for online devices we should set the device offline (disband path groups etc.) which does not happen if the device is in not oper state. Simply deregister the ccw device - ccw_device_remove is smart enough to set the device offline properly. If everything fails call io_subchannel_quiesce afterwards as a safeguard. Reported-by: Shalini Chellathurai Saroja <shalini@de.ibm.com> Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Acked-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--drivers/s390/cio/device.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index f50ea035aa9b..1540229a37bb 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1073,8 +1073,7 @@ out_schedule:
1073 return 0; 1073 return 0;
1074} 1074}
1075 1075
1076static int 1076static int io_subchannel_remove(struct subchannel *sch)
1077io_subchannel_remove (struct subchannel *sch)
1078{ 1077{
1079 struct io_subchannel_private *io_priv = to_io_private(sch); 1078 struct io_subchannel_private *io_priv = to_io_private(sch);
1080 struct ccw_device *cdev; 1079 struct ccw_device *cdev;
@@ -1082,14 +1081,12 @@ io_subchannel_remove (struct subchannel *sch)
1082 cdev = sch_get_cdev(sch); 1081 cdev = sch_get_cdev(sch);
1083 if (!cdev) 1082 if (!cdev)
1084 goto out_free; 1083 goto out_free;
1085 io_subchannel_quiesce(sch); 1084
1086 /* Set ccw device to not operational and drop reference. */ 1085 ccw_device_unregister(cdev);
1087 spin_lock_irq(cdev->ccwlock); 1086 spin_lock_irq(sch->lock);
1088 sch_set_cdev(sch, NULL); 1087 sch_set_cdev(sch, NULL);
1089 set_io_private(sch, NULL); 1088 set_io_private(sch, NULL);
1090 cdev->private->state = DEV_STATE_NOT_OPER; 1089 spin_unlock_irq(sch->lock);
1091 spin_unlock_irq(cdev->ccwlock);
1092 ccw_device_unregister(cdev);
1093out_free: 1090out_free:
1094 kfree(io_priv); 1091 kfree(io_priv);
1095 sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group); 1092 sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group);
@@ -1721,6 +1718,7 @@ static int ccw_device_remove(struct device *dev)
1721{ 1718{
1722 struct ccw_device *cdev = to_ccwdev(dev); 1719 struct ccw_device *cdev = to_ccwdev(dev);
1723 struct ccw_driver *cdrv = cdev->drv; 1720 struct ccw_driver *cdrv = cdev->drv;
1721 struct subchannel *sch;
1724 int ret; 1722 int ret;
1725 1723
1726 if (cdrv->remove) 1724 if (cdrv->remove)
@@ -1746,7 +1744,9 @@ static int ccw_device_remove(struct device *dev)
1746 ccw_device_set_timeout(cdev, 0); 1744 ccw_device_set_timeout(cdev, 0);
1747 cdev->drv = NULL; 1745 cdev->drv = NULL;
1748 cdev->private->int_class = IRQIO_CIO; 1746 cdev->private->int_class = IRQIO_CIO;
1747 sch = to_subchannel(cdev->dev.parent);
1749 spin_unlock_irq(cdev->ccwlock); 1748 spin_unlock_irq(cdev->ccwlock);
1749 io_subchannel_quiesce(sch);
1750 __disable_cmf(cdev); 1750 __disable_cmf(cdev);
1751 1751
1752 return 0; 1752 return 0;