aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/device.c')
-rw-r--r--drivers/s390/cio/device.c160
1 files changed, 80 insertions, 80 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index a6c7d5426fb2..c6abb75c4615 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -136,7 +136,6 @@ static int io_subchannel_sch_event(struct subchannel *, int);
136static int io_subchannel_chp_event(struct subchannel *, struct chp_link *, 136static int io_subchannel_chp_event(struct subchannel *, struct chp_link *,
137 int); 137 int);
138static void recovery_func(unsigned long data); 138static void recovery_func(unsigned long data);
139struct workqueue_struct *ccw_device_work;
140wait_queue_head_t ccw_device_init_wq; 139wait_queue_head_t ccw_device_init_wq;
141atomic_t ccw_device_init_count; 140atomic_t ccw_device_init_count;
142 141
@@ -159,11 +158,16 @@ static int io_subchannel_prepare(struct subchannel *sch)
159 return 0; 158 return 0;
160} 159}
161 160
162static void io_subchannel_settle(void) 161static int io_subchannel_settle(void)
163{ 162{
164 wait_event(ccw_device_init_wq, 163 int ret;
165 atomic_read(&ccw_device_init_count) == 0); 164
166 flush_workqueue(ccw_device_work); 165 ret = wait_event_interruptible(ccw_device_init_wq,
166 atomic_read(&ccw_device_init_count) == 0);
167 if (ret)
168 return -EINTR;
169 flush_workqueue(cio_work_q);
170 return 0;
167} 171}
168 172
169static struct css_driver io_subchannel_driver = { 173static struct css_driver io_subchannel_driver = {
@@ -188,27 +192,13 @@ int __init io_subchannel_init(void)
188 atomic_set(&ccw_device_init_count, 0); 192 atomic_set(&ccw_device_init_count, 0);
189 setup_timer(&recovery_timer, recovery_func, 0); 193 setup_timer(&recovery_timer, recovery_func, 0);
190 194
191 ccw_device_work = create_singlethread_workqueue("cio"); 195 ret = bus_register(&ccw_bus_type);
192 if (!ccw_device_work) 196 if (ret)
193 return -ENOMEM; 197 return ret;
194 slow_path_wq = create_singlethread_workqueue("kslowcrw");
195 if (!slow_path_wq) {
196 ret = -ENOMEM;
197 goto out_err;
198 }
199 if ((ret = bus_register (&ccw_bus_type)))
200 goto out_err;
201
202 ret = css_driver_register(&io_subchannel_driver); 198 ret = css_driver_register(&io_subchannel_driver);
203 if (ret) 199 if (ret)
204 goto out_err; 200 bus_unregister(&ccw_bus_type);
205 201
206 return 0;
207out_err:
208 if (ccw_device_work)
209 destroy_workqueue(ccw_device_work);
210 if (slow_path_wq)
211 destroy_workqueue(slow_path_wq);
212 return ret; 202 return ret;
213} 203}
214 204
@@ -1348,7 +1338,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)
1348 /* Not operational. */ 1338 /* Not operational. */
1349 if (!cdev) 1339 if (!cdev)
1350 return IO_SCH_UNREG; 1340 return IO_SCH_UNREG;
1351 if (!ccw_device_notify(cdev, CIO_GONE)) 1341 if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK)
1352 return IO_SCH_UNREG; 1342 return IO_SCH_UNREG;
1353 return IO_SCH_ORPH_UNREG; 1343 return IO_SCH_ORPH_UNREG;
1354 } 1344 }
@@ -1356,12 +1346,12 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)
1356 if (!cdev) 1346 if (!cdev)
1357 return IO_SCH_ATTACH; 1347 return IO_SCH_ATTACH;
1358 if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { 1348 if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) {
1359 if (!ccw_device_notify(cdev, CIO_GONE)) 1349 if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK)
1360 return IO_SCH_UNREG_ATTACH; 1350 return IO_SCH_UNREG_ATTACH;
1361 return IO_SCH_ORPH_ATTACH; 1351 return IO_SCH_ORPH_ATTACH;
1362 } 1352 }
1363 if ((sch->schib.pmcw.pam & sch->opm) == 0) { 1353 if ((sch->schib.pmcw.pam & sch->opm) == 0) {
1364 if (!ccw_device_notify(cdev, CIO_NO_PATH)) 1354 if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK)
1365 return IO_SCH_UNREG; 1355 return IO_SCH_UNREG;
1366 return IO_SCH_DISC; 1356 return IO_SCH_DISC;
1367 } 1357 }
@@ -1410,6 +1400,12 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
1410 rc = 0; 1400 rc = 0;
1411 goto out_unlock; 1401 goto out_unlock;
1412 case IO_SCH_VERIFY: 1402 case IO_SCH_VERIFY:
1403 if (cdev->private->flags.resuming == 1) {
1404 if (cio_enable_subchannel(sch, (u32)(addr_t)sch)) {
1405 ccw_device_set_notoper(cdev);
1406 break;
1407 }
1408 }
1413 /* Trigger path verification. */ 1409 /* Trigger path verification. */
1414 io_subchannel_verify(sch); 1410 io_subchannel_verify(sch);
1415 rc = 0; 1411 rc = 0;
@@ -1448,7 +1444,8 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
1448 break; 1444 break;
1449 case IO_SCH_UNREG_ATTACH: 1445 case IO_SCH_UNREG_ATTACH:
1450 /* Unregister ccw device. */ 1446 /* Unregister ccw device. */
1451 ccw_device_unregister(cdev); 1447 if (!cdev->private->flags.resuming)
1448 ccw_device_unregister(cdev);
1452 break; 1449 break;
1453 default: 1450 default:
1454 break; 1451 break;
@@ -1457,7 +1454,8 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
1457 switch (action) { 1454 switch (action) {
1458 case IO_SCH_ORPH_UNREG: 1455 case IO_SCH_ORPH_UNREG:
1459 case IO_SCH_UNREG: 1456 case IO_SCH_UNREG:
1460 css_sch_device_unregister(sch); 1457 if (!cdev || !cdev->private->flags.resuming)
1458 css_sch_device_unregister(sch);
1461 break; 1459 break;
1462 case IO_SCH_ORPH_ATTACH: 1460 case IO_SCH_ORPH_ATTACH:
1463 case IO_SCH_UNREG_ATTACH: 1461 case IO_SCH_UNREG_ATTACH:
@@ -1779,26 +1777,42 @@ static void __ccw_device_pm_restore(struct ccw_device *cdev)
1779{ 1777{
1780 struct subchannel *sch = to_subchannel(cdev->dev.parent); 1778 struct subchannel *sch = to_subchannel(cdev->dev.parent);
1781 1779
1782 if (cio_is_console(sch->schid)) 1780 spin_lock_irq(sch->lock);
1783 goto out; 1781 if (cio_is_console(sch->schid)) {
1782 cio_enable_subchannel(sch, (u32)(addr_t)sch);
1783 goto out_unlock;
1784 }
1784 /* 1785 /*
1785 * While we were sleeping, devices may have gone or become 1786 * While we were sleeping, devices may have gone or become
1786 * available again. Kick re-detection. 1787 * available again. Kick re-detection.
1787 */ 1788 */
1788 spin_lock_irq(sch->lock);
1789 cdev->private->flags.resuming = 1; 1789 cdev->private->flags.resuming = 1;
1790 css_schedule_eval(sch->schid);
1791 spin_unlock_irq(sch->lock);
1792 css_complete_work();
1793
1794 /* cdev may have been moved to a different subchannel. */
1795 sch = to_subchannel(cdev->dev.parent);
1796 spin_lock_irq(sch->lock);
1797 if (cdev->private->state != DEV_STATE_ONLINE &&
1798 cdev->private->state != DEV_STATE_OFFLINE)
1799 goto out_unlock;
1800
1790 ccw_device_recognition(cdev); 1801 ccw_device_recognition(cdev);
1791 spin_unlock_irq(sch->lock); 1802 spin_unlock_irq(sch->lock);
1792 wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev) || 1803 wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev) ||
1793 cdev->private->state == DEV_STATE_DISCONNECTED); 1804 cdev->private->state == DEV_STATE_DISCONNECTED);
1794out: 1805 spin_lock_irq(sch->lock);
1806
1807out_unlock:
1795 cdev->private->flags.resuming = 0; 1808 cdev->private->flags.resuming = 0;
1809 spin_unlock_irq(sch->lock);
1796} 1810}
1797 1811
1798static int resume_handle_boxed(struct ccw_device *cdev) 1812static int resume_handle_boxed(struct ccw_device *cdev)
1799{ 1813{
1800 cdev->private->state = DEV_STATE_BOXED; 1814 cdev->private->state = DEV_STATE_BOXED;
1801 if (ccw_device_notify(cdev, CIO_BOXED)) 1815 if (ccw_device_notify(cdev, CIO_BOXED) == NOTIFY_OK)
1802 return 0; 1816 return 0;
1803 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); 1817 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
1804 return -ENODEV; 1818 return -ENODEV;
@@ -1807,7 +1821,7 @@ static int resume_handle_boxed(struct ccw_device *cdev)
1807static int resume_handle_disc(struct ccw_device *cdev) 1821static int resume_handle_disc(struct ccw_device *cdev)
1808{ 1822{
1809 cdev->private->state = DEV_STATE_DISCONNECTED; 1823 cdev->private->state = DEV_STATE_DISCONNECTED;
1810 if (ccw_device_notify(cdev, CIO_GONE)) 1824 if (ccw_device_notify(cdev, CIO_GONE) == NOTIFY_OK)
1811 return 0; 1825 return 0;
1812 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); 1826 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
1813 return -ENODEV; 1827 return -ENODEV;
@@ -1816,40 +1830,31 @@ static int resume_handle_disc(struct ccw_device *cdev)
1816static int ccw_device_pm_restore(struct device *dev) 1830static int ccw_device_pm_restore(struct device *dev)
1817{ 1831{
1818 struct ccw_device *cdev = to_ccwdev(dev); 1832 struct ccw_device *cdev = to_ccwdev(dev);
1819 struct subchannel *sch = to_subchannel(cdev->dev.parent); 1833 struct subchannel *sch;
1820 int ret = 0, cm_enabled; 1834 int ret = 0;
1821 1835
1822 __ccw_device_pm_restore(cdev); 1836 __ccw_device_pm_restore(cdev);
1837 sch = to_subchannel(cdev->dev.parent);
1823 spin_lock_irq(sch->lock); 1838 spin_lock_irq(sch->lock);
1824 if (cio_is_console(sch->schid)) { 1839 if (cio_is_console(sch->schid))
1825 cio_enable_subchannel(sch, (u32)(addr_t)sch);
1826 spin_unlock_irq(sch->lock);
1827 goto out_restore; 1840 goto out_restore;
1828 } 1841
1829 cdev->private->flags.donotify = 0;
1830 /* check recognition results */ 1842 /* check recognition results */
1831 switch (cdev->private->state) { 1843 switch (cdev->private->state) {
1832 case DEV_STATE_OFFLINE: 1844 case DEV_STATE_OFFLINE:
1845 case DEV_STATE_ONLINE:
1846 cdev->private->flags.donotify = 0;
1833 break; 1847 break;
1834 case DEV_STATE_BOXED: 1848 case DEV_STATE_BOXED:
1835 ret = resume_handle_boxed(cdev); 1849 ret = resume_handle_boxed(cdev);
1836 spin_unlock_irq(sch->lock);
1837 if (ret) 1850 if (ret)
1838 goto out; 1851 goto out_unlock;
1839 goto out_restore; 1852 goto out_restore;
1840 case DEV_STATE_DISCONNECTED:
1841 goto out_disc_unlock;
1842 default: 1853 default:
1843 goto out_unreg_unlock; 1854 ret = resume_handle_disc(cdev);
1844 } 1855 if (ret)
1845 /* check if the device id has changed */ 1856 goto out_unlock;
1846 if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { 1857 goto out_restore;
1847 CIO_MSG_EVENT(0, "resume: sch 0.%x.%04x: failed (devno "
1848 "changed from %04x to %04x)\n",
1849 sch->schid.ssid, sch->schid.sch_no,
1850 cdev->private->dev_id.devno,
1851 sch->schib.pmcw.dev);
1852 goto out_unreg_unlock;
1853 } 1858 }
1854 /* check if the device type has changed */ 1859 /* check if the device type has changed */
1855 if (!ccw_device_test_sense_data(cdev)) { 1860 if (!ccw_device_test_sense_data(cdev)) {
@@ -1858,24 +1863,30 @@ static int ccw_device_pm_restore(struct device *dev)
1858 ret = -ENODEV; 1863 ret = -ENODEV;
1859 goto out_unlock; 1864 goto out_unlock;
1860 } 1865 }
1861 if (!cdev->online) { 1866 if (!cdev->online)
1862 ret = 0;
1863 goto out_unlock; 1867 goto out_unlock;
1864 }
1865 ret = ccw_device_online(cdev);
1866 if (ret)
1867 goto out_disc_unlock;
1868 1868
1869 cm_enabled = cdev->private->cmb != NULL; 1869 if (ccw_device_online(cdev)) {
1870 ret = resume_handle_disc(cdev);
1871 if (ret)
1872 goto out_unlock;
1873 goto out_restore;
1874 }
1870 spin_unlock_irq(sch->lock); 1875 spin_unlock_irq(sch->lock);
1871
1872 wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); 1876 wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
1873 if (cdev->private->state != DEV_STATE_ONLINE) { 1877 spin_lock_irq(sch->lock);
1874 spin_lock_irq(sch->lock); 1878
1875 goto out_disc_unlock; 1879 if (ccw_device_notify(cdev, CIO_OPER) == NOTIFY_BAD) {
1880 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
1881 ret = -ENODEV;
1882 goto out_unlock;
1876 } 1883 }
1877 if (cm_enabled) { 1884
1885 /* reenable cmf, if needed */
1886 if (cdev->private->cmb) {
1887 spin_unlock_irq(sch->lock);
1878 ret = ccw_set_cmf(cdev, 1); 1888 ret = ccw_set_cmf(cdev, 1);
1889 spin_lock_irq(sch->lock);
1879 if (ret) { 1890 if (ret) {
1880 CIO_MSG_EVENT(2, "resume: cdev 0.%x.%04x: cmf failed " 1891 CIO_MSG_EVENT(2, "resume: cdev 0.%x.%04x: cmf failed "
1881 "(rc=%d)\n", cdev->private->dev_id.ssid, 1892 "(rc=%d)\n", cdev->private->dev_id.ssid,
@@ -1885,21 +1896,11 @@ static int ccw_device_pm_restore(struct device *dev)
1885 } 1896 }
1886 1897
1887out_restore: 1898out_restore:
1899 spin_unlock_irq(sch->lock);
1888 if (cdev->online && cdev->drv && cdev->drv->restore) 1900 if (cdev->online && cdev->drv && cdev->drv->restore)
1889 ret = cdev->drv->restore(cdev); 1901 ret = cdev->drv->restore(cdev);
1890out:
1891 return ret; 1902 return ret;
1892 1903
1893out_disc_unlock:
1894 ret = resume_handle_disc(cdev);
1895 spin_unlock_irq(sch->lock);
1896 if (ret)
1897 return ret;
1898 goto out_restore;
1899
1900out_unreg_unlock:
1901 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG_EVAL);
1902 ret = -ENODEV;
1903out_unlock: 1904out_unlock:
1904 spin_unlock_irq(sch->lock); 1905 spin_unlock_irq(sch->lock);
1905 return ret; 1906 return ret;
@@ -2028,7 +2029,7 @@ void ccw_device_sched_todo(struct ccw_device *cdev, enum cdev_todo todo)
2028 /* Get workqueue ref. */ 2029 /* Get workqueue ref. */
2029 if (!get_device(&cdev->dev)) 2030 if (!get_device(&cdev->dev))
2030 return; 2031 return;
2031 if (!queue_work(slow_path_wq, &cdev->private->todo_work)) { 2032 if (!queue_work(cio_work_q, &cdev->private->todo_work)) {
2032 /* Already queued, release workqueue ref. */ 2033 /* Already queued, release workqueue ref. */
2033 put_device(&cdev->dev); 2034 put_device(&cdev->dev);
2034 } 2035 }
@@ -2041,5 +2042,4 @@ EXPORT_SYMBOL(ccw_driver_register);
2041EXPORT_SYMBOL(ccw_driver_unregister); 2042EXPORT_SYMBOL(ccw_driver_unregister);
2042EXPORT_SYMBOL(get_ccwdev_by_busid); 2043EXPORT_SYMBOL(get_ccwdev_by_busid);
2043EXPORT_SYMBOL(ccw_bus_type); 2044EXPORT_SYMBOL(ccw_bus_type);
2044EXPORT_SYMBOL(ccw_device_work);
2045EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id); 2045EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id);