aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/s390/cio/device.c203
-rw-r--r--drivers/s390/cio/device.h3
-rw-r--r--drivers/s390/cio/device_fsm.c28
-rw-r--r--drivers/s390/cio/io_sch.h12
4 files changed, 119 insertions, 127 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 0dcfc0ee3d8..167446785d1 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -306,47 +306,6 @@ static void ccw_device_unregister(struct ccw_device *cdev)
306 } 306 }
307} 307}
308 308
309static void ccw_device_remove_orphan_cb(struct work_struct *work)
310{
311 struct ccw_device_private *priv;
312 struct ccw_device *cdev;
313
314 priv = container_of(work, struct ccw_device_private, kick_work);
315 cdev = priv->cdev;
316 ccw_device_unregister(cdev);
317 /* Release cdev reference for workqueue processing. */
318 put_device(&cdev->dev);
319}
320
321static void
322ccw_device_remove_disconnected(struct ccw_device *cdev)
323{
324 unsigned long flags;
325
326 /*
327 * Forced offline in disconnected state means
328 * 'throw away device'.
329 */
330 if (ccw_device_is_orphan(cdev)) {
331 /*
332 * Deregister ccw device.
333 * Unfortunately, we cannot do this directly from the
334 * attribute method.
335 */
336 /* Get cdev reference for workqueue processing. */
337 if (!get_device(&cdev->dev))
338 return;
339 spin_lock_irqsave(cdev->ccwlock, flags);
340 cdev->private->state = DEV_STATE_NOT_OPER;
341 spin_unlock_irqrestore(cdev->ccwlock, flags);
342 PREPARE_WORK(&cdev->private->kick_work,
343 ccw_device_remove_orphan_cb);
344 queue_work(slow_path_wq, &cdev->private->kick_work);
345 } else
346 /* Deregister subchannel, which will kill the ccw device. */
347 ccw_device_schedule_sch_unregister(cdev);
348}
349
350/** 309/**
351 * ccw_device_set_offline() - disable a ccw device for I/O 310 * ccw_device_set_offline() - disable a ccw device for I/O
352 * @cdev: target ccw device 311 * @cdev: target ccw device
@@ -494,9 +453,11 @@ error:
494 453
495static int online_store_handle_offline(struct ccw_device *cdev) 454static int online_store_handle_offline(struct ccw_device *cdev)
496{ 455{
497 if (cdev->private->state == DEV_STATE_DISCONNECTED) 456 if (cdev->private->state == DEV_STATE_DISCONNECTED) {
498 ccw_device_remove_disconnected(cdev); 457 spin_lock_irq(cdev->ccwlock);
499 else if (cdev->online && cdev->drv && cdev->drv->set_offline) 458 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG_EVAL);
459 spin_unlock_irq(cdev->ccwlock);
460 } else if (cdev->online && cdev->drv && cdev->drv->set_offline)
500 return ccw_device_set_offline(cdev); 461 return ccw_device_set_offline(cdev);
501 return 0; 462 return 0;
502} 463}
@@ -690,17 +651,10 @@ static struct ccw_device *get_ccwdev_by_dev_id(struct ccw_dev_id *dev_id)
690 return dev ? to_ccwdev(dev) : NULL; 651 return dev ? to_ccwdev(dev) : NULL;
691} 652}
692 653
693void ccw_device_do_unbind_bind(struct work_struct *work) 654static void ccw_device_do_unbind_bind(struct ccw_device *cdev)
694{ 655{
695 struct ccw_device_private *priv;
696 struct ccw_device *cdev;
697 struct subchannel *sch;
698 int ret; 656 int ret;
699 657
700 priv = container_of(work, struct ccw_device_private, kick_work);
701 cdev = priv->cdev;
702 sch = to_subchannel(cdev->dev.parent);
703
704 if (test_bit(1, &cdev->private->registered)) { 658 if (test_bit(1, &cdev->private->registered)) {
705 device_release_driver(&cdev->dev); 659 device_release_driver(&cdev->dev);
706 ret = device_attach(&cdev->dev); 660 ret = device_attach(&cdev->dev);
@@ -735,6 +689,8 @@ static struct ccw_device * io_subchannel_allocate_dev(struct subchannel *sch)
735 return ERR_PTR(-ENOMEM); 689 return ERR_PTR(-ENOMEM);
736} 690}
737 691
692static void ccw_device_todo(struct work_struct *work);
693
738static int io_subchannel_initialize_dev(struct subchannel *sch, 694static int io_subchannel_initialize_dev(struct subchannel *sch,
739 struct ccw_device *cdev) 695 struct ccw_device *cdev)
740{ 696{
@@ -742,7 +698,7 @@ static int io_subchannel_initialize_dev(struct subchannel *sch,
742 atomic_set(&cdev->private->onoff, 0); 698 atomic_set(&cdev->private->onoff, 0);
743 cdev->dev.parent = &sch->dev; 699 cdev->dev.parent = &sch->dev;
744 cdev->dev.release = ccw_device_release; 700 cdev->dev.release = ccw_device_release;
745 INIT_WORK(&cdev->private->kick_work, NULL); 701 INIT_WORK(&cdev->private->todo_work, ccw_device_todo);
746 cdev->dev.groups = ccwdev_attr_groups; 702 cdev->dev.groups = ccwdev_attr_groups;
747 /* Do first half of device_register. */ 703 /* Do first half of device_register. */
748 device_initialize(&cdev->dev); 704 device_initialize(&cdev->dev);
@@ -797,17 +753,12 @@ static void sch_create_and_recog_new_device(struct subchannel *sch)
797/* 753/*
798 * Register recognized device. 754 * Register recognized device.
799 */ 755 */
800static void 756static void io_subchannel_register(struct ccw_device *cdev)
801io_subchannel_register(struct work_struct *work)
802{ 757{
803 struct ccw_device_private *priv;
804 struct ccw_device *cdev;
805 struct subchannel *sch; 758 struct subchannel *sch;
806 int ret; 759 int ret;
807 unsigned long flags; 760 unsigned long flags;
808 761
809 priv = container_of(work, struct ccw_device_private, kick_work);
810 cdev = priv->cdev;
811 sch = to_subchannel(cdev->dev.parent); 762 sch = to_subchannel(cdev->dev.parent);
812 /* 763 /*
813 * Check if subchannel is still registered. It may have become 764 * Check if subchannel is still registered. It may have become
@@ -859,41 +810,23 @@ out:
859 cdev->private->flags.recog_done = 1; 810 cdev->private->flags.recog_done = 1;
860 wake_up(&cdev->private->wait_q); 811 wake_up(&cdev->private->wait_q);
861out_err: 812out_err:
862 /* Release reference for workqueue processing. */
863 put_device(&cdev->dev);
864 if (atomic_dec_and_test(&ccw_device_init_count)) 813 if (atomic_dec_and_test(&ccw_device_init_count))
865 wake_up(&ccw_device_init_wq); 814 wake_up(&ccw_device_init_wq);
866} 815}
867 816
868static void ccw_device_call_sch_unregister(struct work_struct *work) 817static void ccw_device_call_sch_unregister(struct ccw_device *cdev)
869{ 818{
870 struct ccw_device_private *priv;
871 struct ccw_device *cdev;
872 struct subchannel *sch; 819 struct subchannel *sch;
873 820
874 priv = container_of(work, struct ccw_device_private, kick_work);
875 cdev = priv->cdev;
876 /* Get subchannel reference for local processing. */ 821 /* Get subchannel reference for local processing. */
877 if (!get_device(cdev->dev.parent)) 822 if (!get_device(cdev->dev.parent))
878 return; 823 return;
879 sch = to_subchannel(cdev->dev.parent); 824 sch = to_subchannel(cdev->dev.parent);
880 css_sch_device_unregister(sch); 825 css_sch_device_unregister(sch);
881 /* Release cdev reference for workqueue processing.*/
882 put_device(&cdev->dev);
883 /* Release subchannel reference for local processing. */ 826 /* Release subchannel reference for local processing. */
884 put_device(&sch->dev); 827 put_device(&sch->dev);
885} 828}
886 829
887void ccw_device_schedule_sch_unregister(struct ccw_device *cdev)
888{
889 /* Get cdev reference for workqueue processing. */
890 if (!get_device(&cdev->dev))
891 return;
892 PREPARE_WORK(&cdev->private->kick_work,
893 ccw_device_call_sch_unregister);
894 queue_work(slow_path_wq, &cdev->private->kick_work);
895}
896
897/* 830/*
898 * subchannel recognition done. Called from the state machine. 831 * subchannel recognition done. Called from the state machine.
899 */ 832 */
@@ -909,7 +842,8 @@ io_subchannel_recog_done(struct ccw_device *cdev)
909 /* Device did not respond in time. */ 842 /* Device did not respond in time. */
910 case DEV_STATE_NOT_OPER: 843 case DEV_STATE_NOT_OPER:
911 cdev->private->flags.recog_done = 1; 844 cdev->private->flags.recog_done = 1;
912 ccw_device_schedule_sch_unregister(cdev); 845 /* Remove device found not operational. */
846 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
913 if (atomic_dec_and_test(&ccw_device_init_count)) 847 if (atomic_dec_and_test(&ccw_device_init_count))
914 wake_up(&ccw_device_init_wq); 848 wake_up(&ccw_device_init_wq);
915 break; 849 break;
@@ -918,11 +852,7 @@ io_subchannel_recog_done(struct ccw_device *cdev)
918 * We can't register the device in interrupt context so 852 * We can't register the device in interrupt context so
919 * we schedule a work item. 853 * we schedule a work item.
920 */ 854 */
921 if (!get_device(&cdev->dev)) 855 ccw_device_sched_todo(cdev, CDEV_TODO_REGISTER);
922 break;
923 PREPARE_WORK(&cdev->private->kick_work,
924 io_subchannel_register);
925 queue_work(slow_path_wq, &cdev->private->kick_work);
926 break; 856 break;
927 } 857 }
928} 858}
@@ -1333,20 +1263,16 @@ static void ccw_device_schedule_recovery(void)
1333static int purge_fn(struct device *dev, void *data) 1263static int purge_fn(struct device *dev, void *data)
1334{ 1264{
1335 struct ccw_device *cdev = to_ccwdev(dev); 1265 struct ccw_device *cdev = to_ccwdev(dev);
1336 struct ccw_device_private *priv = cdev->private; 1266 struct ccw_dev_id *id = &cdev->private->dev_id;
1337 int unreg;
1338 1267
1339 spin_lock_irq(cdev->ccwlock); 1268 spin_lock_irq(cdev->ccwlock);
1340 unreg = is_blacklisted(priv->dev_id.ssid, priv->dev_id.devno) && 1269 if (is_blacklisted(id->ssid, id->devno) &&
1341 (priv->state == DEV_STATE_OFFLINE); 1270 (cdev->private->state == DEV_STATE_OFFLINE)) {
1271 CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", id->ssid,
1272 id->devno);
1273 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
1274 }
1342 spin_unlock_irq(cdev->ccwlock); 1275 spin_unlock_irq(cdev->ccwlock);
1343 if (!unreg)
1344 goto out;
1345 CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", priv->dev_id.ssid,
1346 priv->dev_id.devno);
1347 ccw_device_schedule_sch_unregister(cdev);
1348
1349out:
1350 /* Abort loop in case of pending signal. */ 1276 /* Abort loop in case of pending signal. */
1351 if (signal_pending(current)) 1277 if (signal_pending(current))
1352 return -EINTR; 1278 return -EINTR;
@@ -1456,12 +1382,14 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
1456 goto out_unlock; 1382 goto out_unlock;
1457 if (work_pending(&sch->todo_work)) 1383 if (work_pending(&sch->todo_work))
1458 goto out_unlock; 1384 goto out_unlock;
1385 cdev = sch_get_cdev(sch);
1386 if (cdev && work_pending(&cdev->private->todo_work))
1387 goto out_unlock;
1459 action = sch_get_action(sch); 1388 action = sch_get_action(sch);
1460 CIO_MSG_EVENT(2, "event: sch 0.%x.%04x, process=%d, action=%d\n", 1389 CIO_MSG_EVENT(2, "event: sch 0.%x.%04x, process=%d, action=%d\n",
1461 sch->schid.ssid, sch->schid.sch_no, process, 1390 sch->schid.ssid, sch->schid.sch_no, process,
1462 action); 1391 action);
1463 /* Perform immediate actions while holding the lock. */ 1392 /* Perform immediate actions while holding the lock. */
1464 cdev = sch_get_cdev(sch);
1465 switch (action) { 1393 switch (action) {
1466 case IO_SCH_REPROBE: 1394 case IO_SCH_REPROBE:
1467 /* Trigger device recognition. */ 1395 /* Trigger device recognition. */
@@ -1753,7 +1681,7 @@ static int ccw_device_pm_prepare(struct device *dev)
1753{ 1681{
1754 struct ccw_device *cdev = to_ccwdev(dev); 1682 struct ccw_device *cdev = to_ccwdev(dev);
1755 1683
1756 if (work_pending(&cdev->private->kick_work)) 1684 if (work_pending(&cdev->private->todo_work))
1757 return -EAGAIN; 1685 return -EAGAIN;
1758 /* Fail while device is being set online/offline. */ 1686 /* Fail while device is being set online/offline. */
1759 if (atomic_read(&cdev->private->onoff)) 1687 if (atomic_read(&cdev->private->onoff))
@@ -1874,7 +1802,7 @@ static int resume_handle_boxed(struct ccw_device *cdev)
1874 cdev->private->state = DEV_STATE_BOXED; 1802 cdev->private->state = DEV_STATE_BOXED;
1875 if (ccw_device_notify(cdev, CIO_BOXED)) 1803 if (ccw_device_notify(cdev, CIO_BOXED))
1876 return 0; 1804 return 0;
1877 ccw_device_schedule_sch_unregister(cdev); 1805 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
1878 return -ENODEV; 1806 return -ENODEV;
1879} 1807}
1880 1808
@@ -1883,7 +1811,7 @@ static int resume_handle_disc(struct ccw_device *cdev)
1883 cdev->private->state = DEV_STATE_DISCONNECTED; 1811 cdev->private->state = DEV_STATE_DISCONNECTED;
1884 if (ccw_device_notify(cdev, CIO_GONE)) 1812 if (ccw_device_notify(cdev, CIO_GONE))
1885 return 0; 1813 return 0;
1886 ccw_device_schedule_sch_unregister(cdev); 1814 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
1887 return -ENODEV; 1815 return -ENODEV;
1888} 1816}
1889 1817
@@ -1928,9 +1856,7 @@ static int ccw_device_pm_restore(struct device *dev)
1928 /* check if the device type has changed */ 1856 /* check if the device type has changed */
1929 if (!ccw_device_test_sense_data(cdev)) { 1857 if (!ccw_device_test_sense_data(cdev)) {
1930 ccw_device_update_sense_data(cdev); 1858 ccw_device_update_sense_data(cdev);
1931 PREPARE_WORK(&cdev->private->kick_work, 1859 ccw_device_sched_todo(cdev, CDEV_TODO_REBIND);
1932 ccw_device_do_unbind_bind);
1933 queue_work(ccw_device_work, &cdev->private->kick_work);
1934 ret = -ENODEV; 1860 ret = -ENODEV;
1935 goto out_unlock; 1861 goto out_unlock;
1936 } 1862 }
@@ -1974,7 +1900,7 @@ out_disc_unlock:
1974 goto out_restore; 1900 goto out_restore;
1975 1901
1976out_unreg_unlock: 1902out_unreg_unlock:
1977 ccw_device_schedule_sch_unregister(cdev); 1903 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG_EVAL);
1978 ret = -ENODEV; 1904 ret = -ENODEV;
1979out_unlock: 1905out_unlock:
1980 spin_unlock_irq(sch->lock); 1906 spin_unlock_irq(sch->lock);
@@ -2039,6 +1965,77 @@ ccw_device_get_subchannel_id(struct ccw_device *cdev)
2039 return sch->schid; 1965 return sch->schid;
2040} 1966}
2041 1967
1968static void ccw_device_todo(struct work_struct *work)
1969{
1970 struct ccw_device_private *priv;
1971 struct ccw_device *cdev;
1972 struct subchannel *sch;
1973 enum cdev_todo todo;
1974
1975 priv = container_of(work, struct ccw_device_private, todo_work);
1976 cdev = priv->cdev;
1977 sch = to_subchannel(cdev->dev.parent);
1978 /* Find out todo. */
1979 spin_lock_irq(cdev->ccwlock);
1980 todo = priv->todo;
1981 priv->todo = CDEV_TODO_NOTHING;
1982 CIO_MSG_EVENT(4, "cdev_todo: cdev=0.%x.%04x todo=%d\n",
1983 priv->dev_id.ssid, priv->dev_id.devno, todo);
1984 spin_unlock_irq(cdev->ccwlock);
1985 /* Perform todo. */
1986 switch (todo) {
1987 case CDEV_TODO_ENABLE_CMF:
1988 cmf_reenable(cdev);
1989 break;
1990 case CDEV_TODO_REBIND:
1991 ccw_device_do_unbind_bind(cdev);
1992 break;
1993 case CDEV_TODO_REGISTER:
1994 io_subchannel_register(cdev);
1995 break;
1996 case CDEV_TODO_UNREG_EVAL:
1997 if (!sch_is_pseudo_sch(sch))
1998 css_schedule_eval(sch->schid);
1999 /* fall-through */
2000 case CDEV_TODO_UNREG:
2001 if (sch_is_pseudo_sch(sch))
2002 ccw_device_unregister(cdev);
2003 else
2004 ccw_device_call_sch_unregister(cdev);
2005 break;
2006 default:
2007 break;
2008 }
2009 /* Release workqueue ref. */
2010 put_device(&cdev->dev);
2011}
2012
2013/**
2014 * ccw_device_sched_todo - schedule ccw device operation
2015 * @cdev: ccw device
2016 * @todo: todo
2017 *
2018 * Schedule the operation identified by @todo to be performed on the slow path
2019 * workqueue. Do nothing if another operation with higher priority is already
2020 * scheduled. Needs to be called with ccwdev lock held.
2021 */
2022void ccw_device_sched_todo(struct ccw_device *cdev, enum cdev_todo todo)
2023{
2024 CIO_MSG_EVENT(4, "cdev_todo: sched cdev=0.%x.%04x todo=%d\n",
2025 cdev->private->dev_id.ssid, cdev->private->dev_id.devno,
2026 todo);
2027 if (cdev->private->todo >= todo)
2028 return;
2029 cdev->private->todo = todo;
2030 /* Get workqueue ref. */
2031 if (!get_device(&cdev->dev))
2032 return;
2033 if (!queue_work(slow_path_wq, &cdev->private->todo_work)) {
2034 /* Already queued, release workqueue ref. */
2035 put_device(&cdev->dev);
2036 }
2037}
2038
2042MODULE_LICENSE("GPL"); 2039MODULE_LICENSE("GPL");
2043EXPORT_SYMBOL(ccw_device_set_online); 2040EXPORT_SYMBOL(ccw_device_set_online);
2044EXPORT_SYMBOL(ccw_device_set_offline); 2041EXPORT_SYMBOL(ccw_device_set_offline);
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 246c6482842..adaa27efc59 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -81,8 +81,6 @@ void io_subchannel_init_config(struct subchannel *sch);
81 81
82int ccw_device_cancel_halt_clear(struct ccw_device *); 82int ccw_device_cancel_halt_clear(struct ccw_device *);
83 83
84void ccw_device_do_unbind_bind(struct work_struct *);
85void ccw_device_move_to_orphanage(struct work_struct *);
86int ccw_device_is_orphan(struct ccw_device *); 84int ccw_device_is_orphan(struct ccw_device *);
87 85
88int ccw_device_recognition(struct ccw_device *); 86int ccw_device_recognition(struct ccw_device *);
@@ -92,6 +90,7 @@ void ccw_device_update_sense_data(struct ccw_device *);
92int ccw_device_test_sense_data(struct ccw_device *); 90int ccw_device_test_sense_data(struct ccw_device *);
93void ccw_device_schedule_sch_unregister(struct ccw_device *); 91void ccw_device_schedule_sch_unregister(struct ccw_device *);
94int ccw_purge_blacklisted(void); 92int ccw_purge_blacklisted(void);
93void ccw_device_sched_todo(struct ccw_device *cdev, enum cdev_todo todo);
95 94
96/* Function prototypes for device status and basic sense stuff. */ 95/* Function prototypes for device status and basic sense stuff. */
97void ccw_device_accumulate_irb(struct ccw_device *, struct irb *); 96void ccw_device_accumulate_irb(struct ccw_device *, struct irb *);
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index d1e05f44fb6..b163743bf58 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -289,9 +289,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
289 wake_up(&cdev->private->wait_q); 289 wake_up(&cdev->private->wait_q);
290 } else { 290 } else {
291 ccw_device_update_sense_data(cdev); 291 ccw_device_update_sense_data(cdev);
292 PREPARE_WORK(&cdev->private->kick_work, 292 ccw_device_sched_todo(cdev, CDEV_TODO_REBIND);
293 ccw_device_do_unbind_bind);
294 queue_work(ccw_device_work, &cdev->private->kick_work);
295 } 293 }
296 return; 294 return;
297 case DEV_STATE_BOXED: 295 case DEV_STATE_BOXED:
@@ -343,28 +341,16 @@ int ccw_device_notify(struct ccw_device *cdev, int event)
343 return cdev->drv->notify ? cdev->drv->notify(cdev, event) : 0; 341 return cdev->drv->notify ? cdev->drv->notify(cdev, event) : 0;
344} 342}
345 343
346static void cmf_reenable_delayed(struct work_struct *work)
347{
348 struct ccw_device_private *priv;
349 struct ccw_device *cdev;
350
351 priv = container_of(work, struct ccw_device_private, kick_work);
352 cdev = priv->cdev;
353 cmf_reenable(cdev);
354}
355
356static void ccw_device_oper_notify(struct ccw_device *cdev) 344static void ccw_device_oper_notify(struct ccw_device *cdev)
357{ 345{
358 if (ccw_device_notify(cdev, CIO_OPER)) { 346 if (ccw_device_notify(cdev, CIO_OPER)) {
359 /* Reenable channel measurements, if needed. */ 347 /* Reenable channel measurements, if needed. */
360 PREPARE_WORK(&cdev->private->kick_work, cmf_reenable_delayed); 348 ccw_device_sched_todo(cdev, CDEV_TODO_ENABLE_CMF);
361 queue_work(ccw_device_work, &cdev->private->kick_work);
362 return; 349 return;
363 } 350 }
364 /* Driver doesn't want device back. */ 351 /* Driver doesn't want device back. */
365 ccw_device_set_notoper(cdev); 352 ccw_device_set_notoper(cdev);
366 PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unbind_bind); 353 ccw_device_sched_todo(cdev, CDEV_TODO_REBIND);
367 queue_work(ccw_device_work, &cdev->private->kick_work);
368} 354}
369 355
370/* 356/*
@@ -392,14 +378,14 @@ ccw_device_done(struct ccw_device *cdev, int state)
392 CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n", 378 CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n",
393 cdev->private->dev_id.devno, sch->schid.sch_no); 379 cdev->private->dev_id.devno, sch->schid.sch_no);
394 if (cdev->online && !ccw_device_notify(cdev, CIO_BOXED)) 380 if (cdev->online && !ccw_device_notify(cdev, CIO_BOXED))
395 ccw_device_schedule_sch_unregister(cdev); 381 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
396 cdev->private->flags.donotify = 0; 382 cdev->private->flags.donotify = 0;
397 break; 383 break;
398 case DEV_STATE_NOT_OPER: 384 case DEV_STATE_NOT_OPER:
399 CIO_MSG_EVENT(0, "Device %04x gone on subchannel %04x\n", 385 CIO_MSG_EVENT(0, "Device %04x gone on subchannel %04x\n",
400 cdev->private->dev_id.devno, sch->schid.sch_no); 386 cdev->private->dev_id.devno, sch->schid.sch_no);
401 if (!ccw_device_notify(cdev, CIO_GONE)) 387 if (!ccw_device_notify(cdev, CIO_GONE))
402 ccw_device_schedule_sch_unregister(cdev); 388 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
403 else 389 else
404 ccw_device_set_disconnected(cdev); 390 ccw_device_set_disconnected(cdev);
405 cdev->private->flags.donotify = 0; 391 cdev->private->flags.donotify = 0;
@@ -409,7 +395,7 @@ ccw_device_done(struct ccw_device *cdev, int state)
409 "%04x\n", cdev->private->dev_id.devno, 395 "%04x\n", cdev->private->dev_id.devno,
410 sch->schid.sch_no); 396 sch->schid.sch_no);
411 if (!ccw_device_notify(cdev, CIO_NO_PATH)) 397 if (!ccw_device_notify(cdev, CIO_NO_PATH))
412 ccw_device_schedule_sch_unregister(cdev); 398 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
413 else 399 else
414 ccw_device_set_disconnected(cdev); 400 ccw_device_set_disconnected(cdev);
415 cdev->private->flags.donotify = 0; 401 cdev->private->flags.donotify = 0;
@@ -751,7 +737,7 @@ static void ccw_device_generic_notoper(struct ccw_device *cdev,
751 enum dev_event dev_event) 737 enum dev_event dev_event)
752{ 738{
753 if (!ccw_device_notify(cdev, CIO_GONE)) 739 if (!ccw_device_notify(cdev, CIO_GONE))
754 ccw_device_schedule_sch_unregister(cdev); 740 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
755 else 741 else
756 ccw_device_set_disconnected(cdev); 742 ccw_device_set_disconnected(cdev);
757} 743}
diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h
index 0b8f381bd20..b770e420213 100644
--- a/drivers/s390/cio/io_sch.h
+++ b/drivers/s390/cio/io_sch.h
@@ -82,6 +82,15 @@ struct senseid {
82 struct ciw ciw[MAX_CIWS]; /* variable # of CIWs */ 82 struct ciw ciw[MAX_CIWS]; /* variable # of CIWs */
83} __attribute__ ((packed, aligned(4))); 83} __attribute__ ((packed, aligned(4)));
84 84
85enum cdev_todo {
86 CDEV_TODO_NOTHING,
87 CDEV_TODO_ENABLE_CMF,
88 CDEV_TODO_REBIND,
89 CDEV_TODO_REGISTER,
90 CDEV_TODO_UNREG,
91 CDEV_TODO_UNREG_EVAL,
92};
93
85struct ccw_device_private { 94struct ccw_device_private {
86 struct ccw_device *cdev; 95 struct ccw_device *cdev;
87 struct subchannel *sch; 96 struct subchannel *sch;
@@ -115,7 +124,8 @@ struct ccw_device_private {
115 struct senseid senseid; /* SenseID info */ 124 struct senseid senseid; /* SenseID info */
116 struct pgid pgid[8]; /* path group IDs per chpid*/ 125 struct pgid pgid[8]; /* path group IDs per chpid*/
117 struct ccw1 iccws[2]; /* ccws for SNID/SID/SPGID commands */ 126 struct ccw1 iccws[2]; /* ccws for SNID/SID/SPGID commands */
118 struct work_struct kick_work; 127 struct work_struct todo_work;
128 enum cdev_todo todo;
119 wait_queue_head_t wait_q; 129 wait_queue_head_t wait_q;
120 struct timer_list timer; 130 struct timer_list timer;
121 void *cmb; /* measurement information */ 131 void *cmb; /* measurement information */