aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2013-12-16 04:51:54 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-12-16 08:38:01 -0500
commit74bd0d859dc3536b01c892abfa9f87620e4bca2f (patch)
tree6dcdde5d5952bc69956abd656e23b0a18b6a1ae7 /drivers/s390/cio
parentd7528862cf035994972c2c6f42c927db78f2f3a2 (diff)
s390/cio: fix unlocked access of online member
Make sure that access to the online member of a ccw device is guarded by the ccwlock. Reported-by: Cornelia Huck <cornelia.huck@de.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>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r--drivers/s390/cio/device.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index e4a7ab2bb629..4a0734fcc83c 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -333,9 +333,9 @@ int ccw_device_set_offline(struct ccw_device *cdev)
333 if (ret != 0) 333 if (ret != 0)
334 return ret; 334 return ret;
335 } 335 }
336 cdev->online = 0;
337 spin_lock_irq(cdev->ccwlock); 336 spin_lock_irq(cdev->ccwlock);
338 sch = to_subchannel(cdev->dev.parent); 337 sch = to_subchannel(cdev->dev.parent);
338 cdev->online = 0;
339 /* Wait until a final state or DISCONNECTED is reached */ 339 /* Wait until a final state or DISCONNECTED is reached */
340 while (!dev_fsm_final_state(cdev) && 340 while (!dev_fsm_final_state(cdev) &&
341 cdev->private->state != DEV_STATE_DISCONNECTED) { 341 cdev->private->state != DEV_STATE_DISCONNECTED) {
@@ -446,7 +446,10 @@ int ccw_device_set_online(struct ccw_device *cdev)
446 ret = cdev->drv->set_online(cdev); 446 ret = cdev->drv->set_online(cdev);
447 if (ret) 447 if (ret)
448 goto rollback; 448 goto rollback;
449
450 spin_lock_irq(cdev->ccwlock);
449 cdev->online = 1; 451 cdev->online = 1;
452 spin_unlock_irq(cdev->ccwlock);
450 return 0; 453 return 0;
451 454
452rollback: 455rollback:
@@ -1745,8 +1748,7 @@ ccw_device_probe (struct device *dev)
1745 return 0; 1748 return 0;
1746} 1749}
1747 1750
1748static int 1751static int ccw_device_remove(struct device *dev)
1749ccw_device_remove (struct device *dev)
1750{ 1752{
1751 struct ccw_device *cdev = to_ccwdev(dev); 1753 struct ccw_device *cdev = to_ccwdev(dev);
1752 struct ccw_driver *cdrv = cdev->drv; 1754 struct ccw_driver *cdrv = cdev->drv;
@@ -1754,9 +1756,10 @@ ccw_device_remove (struct device *dev)
1754 1756
1755 if (cdrv->remove) 1757 if (cdrv->remove)
1756 cdrv->remove(cdev); 1758 cdrv->remove(cdev);
1759
1760 spin_lock_irq(cdev->ccwlock);
1757 if (cdev->online) { 1761 if (cdev->online) {
1758 cdev->online = 0; 1762 cdev->online = 0;
1759 spin_lock_irq(cdev->ccwlock);
1760 ret = ccw_device_offline(cdev); 1763 ret = ccw_device_offline(cdev);
1761 spin_unlock_irq(cdev->ccwlock); 1764 spin_unlock_irq(cdev->ccwlock);
1762 if (ret == 0) 1765 if (ret == 0)
@@ -1769,10 +1772,12 @@ ccw_device_remove (struct device *dev)
1769 cdev->private->dev_id.devno); 1772 cdev->private->dev_id.devno);
1770 /* Give up reference obtained in ccw_device_set_online(). */ 1773 /* Give up reference obtained in ccw_device_set_online(). */
1771 put_device(&cdev->dev); 1774 put_device(&cdev->dev);
1775 spin_lock_irq(cdev->ccwlock);
1772 } 1776 }
1773 ccw_device_set_timeout(cdev, 0); 1777 ccw_device_set_timeout(cdev, 0);
1774 cdev->drv = NULL; 1778 cdev->drv = NULL;
1775 cdev->private->int_class = IRQIO_CIO; 1779 cdev->private->int_class = IRQIO_CIO;
1780 spin_unlock_irq(cdev->ccwlock);
1776 return 0; 1781 return 0;
1777} 1782}
1778 1783