aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2006-12-08 09:53:57 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2006-12-08 09:53:57 -0500
commitc16375329c2ab4667df873394c4be7a61d163c62 (patch)
tree9ee9505e4587ce5f472db3fd09935611b0062f83 /drivers/s390/cio
parente45ccc0562e3f391dcba8b2e8a02551e8e42d8db (diff)
[S390] more workqueue fixes.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r--drivers/s390/cio/css.h2
-rw-r--r--drivers/s390/cio/device.c43
-rw-r--r--drivers/s390/cio/device.h4
-rw-r--r--drivers/s390/cio/device_fsm.c38
-rw-r--r--drivers/s390/cio/qdio.c8
5 files changed, 56 insertions, 39 deletions
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 9ff064e71767..dfd5462f993f 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -73,6 +73,8 @@ struct senseid {
73} __attribute__ ((packed,aligned(4))); 73} __attribute__ ((packed,aligned(4)));
74 74
75struct ccw_device_private { 75struct ccw_device_private {
76 struct ccw_device *cdev;
77 struct subchannel *sch;
76 int state; /* device state */ 78 int state; /* device state */
77 atomic_t onoff; 79 atomic_t onoff;
78 unsigned long registered; 80 unsigned long registered;
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index d3d3716ff84b..0f604621de40 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -585,12 +585,13 @@ static struct ccw_device * get_disc_ccwdev_by_dev_id(struct ccw_dev_id *dev_id,
585} 585}
586 586
587static void 587static void
588ccw_device_add_changed(void *data) 588ccw_device_add_changed(struct work_struct *work)
589{ 589{
590 590 struct ccw_device_private *priv;
591 struct ccw_device *cdev; 591 struct ccw_device *cdev;
592 592
593 cdev = data; 593 priv = container_of(work, struct ccw_device_private, kick_work);
594 cdev = priv->cdev;
594 if (device_add(&cdev->dev)) { 595 if (device_add(&cdev->dev)) {
595 put_device(&cdev->dev); 596 put_device(&cdev->dev);
596 return; 597 return;
@@ -605,13 +606,15 @@ ccw_device_add_changed(void *data)
605extern int css_get_ssd_info(struct subchannel *sch); 606extern int css_get_ssd_info(struct subchannel *sch);
606 607
607void 608void
608ccw_device_do_unreg_rereg(void *data) 609ccw_device_do_unreg_rereg(struct work_struct *work)
609{ 610{
611 struct ccw_device_private *priv;
610 struct ccw_device *cdev; 612 struct ccw_device *cdev;
611 struct subchannel *sch; 613 struct subchannel *sch;
612 int need_rename; 614 int need_rename;
613 615
614 cdev = data; 616 priv = container_of(work, struct ccw_device_private, kick_work);
617 cdev = priv->cdev;
615 sch = to_subchannel(cdev->dev.parent); 618 sch = to_subchannel(cdev->dev.parent);
616 if (cdev->private->dev_id.devno != sch->schib.pmcw.dev) { 619 if (cdev->private->dev_id.devno != sch->schib.pmcw.dev) {
617 /* 620 /*
@@ -659,7 +662,7 @@ ccw_device_do_unreg_rereg(void *data)
659 snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", 662 snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
660 sch->schid.ssid, sch->schib.pmcw.dev); 663 sch->schid.ssid, sch->schib.pmcw.dev);
661 PREPARE_WORK(&cdev->private->kick_work, 664 PREPARE_WORK(&cdev->private->kick_work,
662 ccw_device_add_changed, cdev); 665 ccw_device_add_changed);
663 queue_work(ccw_device_work, &cdev->private->kick_work); 666 queue_work(ccw_device_work, &cdev->private->kick_work);
664} 667}
665 668
@@ -677,14 +680,16 @@ ccw_device_release(struct device *dev)
677 * Register recognized device. 680 * Register recognized device.
678 */ 681 */
679static void 682static void
680io_subchannel_register(void *data) 683io_subchannel_register(struct work_struct *work)
681{ 684{
685 struct ccw_device_private *priv;
682 struct ccw_device *cdev; 686 struct ccw_device *cdev;
683 struct subchannel *sch; 687 struct subchannel *sch;
684 int ret; 688 int ret;
685 unsigned long flags; 689 unsigned long flags;
686 690
687 cdev = data; 691 priv = container_of(work, struct ccw_device_private, kick_work);
692 cdev = priv->cdev;
688 sch = to_subchannel(cdev->dev.parent); 693 sch = to_subchannel(cdev->dev.parent);
689 694
690 /* 695 /*
@@ -734,11 +739,14 @@ out:
734} 739}
735 740
736void 741void
737ccw_device_call_sch_unregister(void *data) 742ccw_device_call_sch_unregister(struct work_struct *work)
738{ 743{
739 struct ccw_device *cdev = data; 744 struct ccw_device_private *priv;
745 struct ccw_device *cdev;
740 struct subchannel *sch; 746 struct subchannel *sch;
741 747
748 priv = container_of(work, struct ccw_device_private, kick_work);
749 cdev = priv->cdev;
742 sch = to_subchannel(cdev->dev.parent); 750 sch = to_subchannel(cdev->dev.parent);
743 css_sch_device_unregister(sch); 751 css_sch_device_unregister(sch);
744 /* Reset intparm to zeroes. */ 752 /* Reset intparm to zeroes. */
@@ -768,7 +776,7 @@ io_subchannel_recog_done(struct ccw_device *cdev)
768 break; 776 break;
769 sch = to_subchannel(cdev->dev.parent); 777 sch = to_subchannel(cdev->dev.parent);
770 PREPARE_WORK(&cdev->private->kick_work, 778 PREPARE_WORK(&cdev->private->kick_work,
771 ccw_device_call_sch_unregister, cdev); 779 ccw_device_call_sch_unregister);
772 queue_work(slow_path_wq, &cdev->private->kick_work); 780 queue_work(slow_path_wq, &cdev->private->kick_work);
773 if (atomic_dec_and_test(&ccw_device_init_count)) 781 if (atomic_dec_and_test(&ccw_device_init_count))
774 wake_up(&ccw_device_init_wq); 782 wake_up(&ccw_device_init_wq);
@@ -783,7 +791,7 @@ io_subchannel_recog_done(struct ccw_device *cdev)
783 if (!get_device(&cdev->dev)) 791 if (!get_device(&cdev->dev))
784 break; 792 break;
785 PREPARE_WORK(&cdev->private->kick_work, 793 PREPARE_WORK(&cdev->private->kick_work,
786 io_subchannel_register, cdev); 794 io_subchannel_register);
787 queue_work(slow_path_wq, &cdev->private->kick_work); 795 queue_work(slow_path_wq, &cdev->private->kick_work);
788 break; 796 break;
789 } 797 }
@@ -865,6 +873,7 @@ io_subchannel_probe (struct subchannel *sch)
865 kfree(cdev); 873 kfree(cdev);
866 return -ENOMEM; 874 return -ENOMEM;
867 } 875 }
876 cdev->private->cdev = cdev;
868 atomic_set(&cdev->private->onoff, 0); 877 atomic_set(&cdev->private->onoff, 0);
869 cdev->dev.parent = &sch->dev; 878 cdev->dev.parent = &sch->dev;
870 cdev->dev.release = ccw_device_release; 879 cdev->dev.release = ccw_device_release;
@@ -890,12 +899,13 @@ io_subchannel_probe (struct subchannel *sch)
890 return rc; 899 return rc;
891} 900}
892 901
893static void 902static void ccw_device_unregister(struct work_struct *work)
894ccw_device_unregister(void *data)
895{ 903{
904 struct ccw_device_private *priv;
896 struct ccw_device *cdev; 905 struct ccw_device *cdev;
897 906
898 cdev = (struct ccw_device *)data; 907 priv = container_of(work, struct ccw_device_private, kick_work);
908 cdev = priv->cdev;
899 if (test_and_clear_bit(1, &cdev->private->registered)) 909 if (test_and_clear_bit(1, &cdev->private->registered))
900 device_unregister(&cdev->dev); 910 device_unregister(&cdev->dev);
901 put_device(&cdev->dev); 911 put_device(&cdev->dev);
@@ -921,7 +931,7 @@ io_subchannel_remove (struct subchannel *sch)
921 */ 931 */
922 if (get_device(&cdev->dev)) { 932 if (get_device(&cdev->dev)) {
923 PREPARE_WORK(&cdev->private->kick_work, 933 PREPARE_WORK(&cdev->private->kick_work,
924 ccw_device_unregister, cdev); 934 ccw_device_unregister);
925 queue_work(ccw_device_work, &cdev->private->kick_work); 935 queue_work(ccw_device_work, &cdev->private->kick_work);
926 } 936 }
927 return 0; 937 return 0;
@@ -1048,6 +1058,7 @@ ccw_device_probe_console(void)
1048 memset(&console_cdev, 0, sizeof(struct ccw_device)); 1058 memset(&console_cdev, 0, sizeof(struct ccw_device));
1049 memset(&console_private, 0, sizeof(struct ccw_device_private)); 1059 memset(&console_private, 0, sizeof(struct ccw_device_private));
1050 console_cdev.private = &console_private; 1060 console_cdev.private = &console_private;
1061 console_private.cdev = &console_cdev;
1051 ret = ccw_device_console_enable(&console_cdev, sch); 1062 ret = ccw_device_console_enable(&console_cdev, sch);
1052 if (ret) { 1063 if (ret) {
1053 cio_release_console(); 1064 cio_release_console();
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 9233b5c0bcc8..d5fe95e04cfe 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -78,8 +78,8 @@ void io_subchannel_recog_done(struct ccw_device *cdev);
78 78
79int ccw_device_cancel_halt_clear(struct ccw_device *); 79int ccw_device_cancel_halt_clear(struct ccw_device *);
80 80
81void ccw_device_do_unreg_rereg(void *); 81void ccw_device_do_unreg_rereg(struct work_struct *);
82void ccw_device_call_sch_unregister(void *); 82void ccw_device_call_sch_unregister(struct work_struct *);
83 83
84int ccw_device_recognition(struct ccw_device *); 84int ccw_device_recognition(struct ccw_device *);
85int ccw_device_online(struct ccw_device *); 85int ccw_device_online(struct ccw_device *);
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 09c7672eb3f3..0f0301ce37fe 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -194,7 +194,7 @@ ccw_device_handle_oper(struct ccw_device *cdev)
194 cdev->id.dev_model != cdev->private->senseid.dev_model || 194 cdev->id.dev_model != cdev->private->senseid.dev_model ||
195 cdev->private->dev_id.devno != sch->schib.pmcw.dev) { 195 cdev->private->dev_id.devno != sch->schib.pmcw.dev) {
196 PREPARE_WORK(&cdev->private->kick_work, 196 PREPARE_WORK(&cdev->private->kick_work,
197 ccw_device_do_unreg_rereg, cdev); 197 ccw_device_do_unreg_rereg);
198 queue_work(ccw_device_work, &cdev->private->kick_work); 198 queue_work(ccw_device_work, &cdev->private->kick_work);
199 return 0; 199 return 0;
200 } 200 }
@@ -329,19 +329,21 @@ ccw_device_sense_id_done(struct ccw_device *cdev, int err)
329} 329}
330 330
331static void 331static void
332ccw_device_oper_notify(void *data) 332ccw_device_oper_notify(struct work_struct *work)
333{ 333{
334 struct ccw_device_private *priv;
334 struct ccw_device *cdev; 335 struct ccw_device *cdev;
335 struct subchannel *sch; 336 struct subchannel *sch;
336 int ret; 337 int ret;
337 338
338 cdev = data; 339 priv = container_of(work, struct ccw_device_private, kick_work);
340 cdev = priv->cdev;
339 sch = to_subchannel(cdev->dev.parent); 341 sch = to_subchannel(cdev->dev.parent);
340 ret = (sch->driver && sch->driver->notify) ? 342 ret = (sch->driver && sch->driver->notify) ?
341 sch->driver->notify(&sch->dev, CIO_OPER) : 0; 343 sch->driver->notify(&sch->dev, CIO_OPER) : 0;
342 if (!ret) 344 if (!ret)
343 /* Driver doesn't want device back. */ 345 /* Driver doesn't want device back. */
344 ccw_device_do_unreg_rereg(cdev); 346 ccw_device_do_unreg_rereg(work);
345 else { 347 else {
346 /* Reenable channel measurements, if needed. */ 348 /* Reenable channel measurements, if needed. */
347 cmf_reenable(cdev); 349 cmf_reenable(cdev);
@@ -377,8 +379,7 @@ ccw_device_done(struct ccw_device *cdev, int state)
377 379
378 if (cdev->private->flags.donotify) { 380 if (cdev->private->flags.donotify) {
379 cdev->private->flags.donotify = 0; 381 cdev->private->flags.donotify = 0;
380 PREPARE_WORK(&cdev->private->kick_work, ccw_device_oper_notify, 382 PREPARE_WORK(&cdev->private->kick_work, ccw_device_oper_notify);
381 cdev);
382 queue_work(ccw_device_notify_work, &cdev->private->kick_work); 383 queue_work(ccw_device_notify_work, &cdev->private->kick_work);
383 } 384 }
384 wake_up(&cdev->private->wait_q); 385 wake_up(&cdev->private->wait_q);
@@ -528,13 +529,15 @@ ccw_device_recog_timeout(struct ccw_device *cdev, enum dev_event dev_event)
528 529
529 530
530static void 531static void
531ccw_device_nopath_notify(void *data) 532ccw_device_nopath_notify(struct work_struct *work)
532{ 533{
534 struct ccw_device_private *priv;
533 struct ccw_device *cdev; 535 struct ccw_device *cdev;
534 struct subchannel *sch; 536 struct subchannel *sch;
535 int ret; 537 int ret;
536 538
537 cdev = data; 539 priv = container_of(work, struct ccw_device_private, kick_work);
540 cdev = priv->cdev;
538 sch = to_subchannel(cdev->dev.parent); 541 sch = to_subchannel(cdev->dev.parent);
539 /* Extra sanity. */ 542 /* Extra sanity. */
540 if (sch->lpm) 543 if (sch->lpm)
@@ -547,8 +550,7 @@ ccw_device_nopath_notify(void *data)
547 cio_disable_subchannel(sch); 550 cio_disable_subchannel(sch);
548 if (get_device(&cdev->dev)) { 551 if (get_device(&cdev->dev)) {
549 PREPARE_WORK(&cdev->private->kick_work, 552 PREPARE_WORK(&cdev->private->kick_work,
550 ccw_device_call_sch_unregister, 553 ccw_device_call_sch_unregister);
551 cdev);
552 queue_work(ccw_device_work, 554 queue_work(ccw_device_work,
553 &cdev->private->kick_work); 555 &cdev->private->kick_work);
554 } else 556 } else
@@ -607,7 +609,7 @@ ccw_device_verify_done(struct ccw_device *cdev, int err)
607 /* Reset oper notify indication after verify error. */ 609 /* Reset oper notify indication after verify error. */
608 cdev->private->flags.donotify = 0; 610 cdev->private->flags.donotify = 0;
609 PREPARE_WORK(&cdev->private->kick_work, 611 PREPARE_WORK(&cdev->private->kick_work,
610 ccw_device_nopath_notify, cdev); 612 ccw_device_nopath_notify);
611 queue_work(ccw_device_notify_work, &cdev->private->kick_work); 613 queue_work(ccw_device_notify_work, &cdev->private->kick_work);
612 ccw_device_done(cdev, DEV_STATE_NOT_OPER); 614 ccw_device_done(cdev, DEV_STATE_NOT_OPER);
613 break; 615 break;
@@ -738,7 +740,7 @@ ccw_device_offline_notoper(struct ccw_device *cdev, enum dev_event dev_event)
738 sch = to_subchannel(cdev->dev.parent); 740 sch = to_subchannel(cdev->dev.parent);
739 if (get_device(&cdev->dev)) { 741 if (get_device(&cdev->dev)) {
740 PREPARE_WORK(&cdev->private->kick_work, 742 PREPARE_WORK(&cdev->private->kick_work,
741 ccw_device_call_sch_unregister, cdev); 743 ccw_device_call_sch_unregister);
742 queue_work(ccw_device_work, &cdev->private->kick_work); 744 queue_work(ccw_device_work, &cdev->private->kick_work);
743 } 745 }
744 wake_up(&cdev->private->wait_q); 746 wake_up(&cdev->private->wait_q);
@@ -769,7 +771,7 @@ ccw_device_online_notoper(struct ccw_device *cdev, enum dev_event dev_event)
769 } 771 }
770 if (get_device(&cdev->dev)) { 772 if (get_device(&cdev->dev)) {
771 PREPARE_WORK(&cdev->private->kick_work, 773 PREPARE_WORK(&cdev->private->kick_work,
772 ccw_device_call_sch_unregister, cdev); 774 ccw_device_call_sch_unregister);
773 queue_work(ccw_device_work, &cdev->private->kick_work); 775 queue_work(ccw_device_work, &cdev->private->kick_work);
774 } 776 }
775 wake_up(&cdev->private->wait_q); 777 wake_up(&cdev->private->wait_q);
@@ -874,7 +876,7 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event)
874 sch = to_subchannel(cdev->dev.parent); 876 sch = to_subchannel(cdev->dev.parent);
875 if (!sch->lpm) { 877 if (!sch->lpm) {
876 PREPARE_WORK(&cdev->private->kick_work, 878 PREPARE_WORK(&cdev->private->kick_work,
877 ccw_device_nopath_notify, cdev); 879 ccw_device_nopath_notify);
878 queue_work(ccw_device_notify_work, 880 queue_work(ccw_device_notify_work,
879 &cdev->private->kick_work); 881 &cdev->private->kick_work);
880 } else 882 } else
@@ -969,7 +971,7 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event)
969 ERR_PTR(-EIO)); 971 ERR_PTR(-EIO));
970 if (!sch->lpm) { 972 if (!sch->lpm) {
971 PREPARE_WORK(&cdev->private->kick_work, 973 PREPARE_WORK(&cdev->private->kick_work,
972 ccw_device_nopath_notify, cdev); 974 ccw_device_nopath_notify);
973 queue_work(ccw_device_notify_work, &cdev->private->kick_work); 975 queue_work(ccw_device_notify_work, &cdev->private->kick_work);
974 } else if (cdev->private->flags.doverify) 976 } else if (cdev->private->flags.doverify)
975 /* Start delayed path verification. */ 977 /* Start delayed path verification. */
@@ -992,7 +994,7 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event)
992 sch = to_subchannel(cdev->dev.parent); 994 sch = to_subchannel(cdev->dev.parent);
993 if (!sch->lpm) { 995 if (!sch->lpm) {
994 PREPARE_WORK(&cdev->private->kick_work, 996 PREPARE_WORK(&cdev->private->kick_work,
995 ccw_device_nopath_notify, cdev); 997 ccw_device_nopath_notify);
996 queue_work(ccw_device_notify_work, 998 queue_work(ccw_device_notify_work,
997 &cdev->private->kick_work); 999 &cdev->private->kick_work);
998 } else 1000 } else
@@ -1021,7 +1023,7 @@ void device_kill_io(struct subchannel *sch)
1021 if (ret == -ENODEV) { 1023 if (ret == -ENODEV) {
1022 if (!sch->lpm) { 1024 if (!sch->lpm) {
1023 PREPARE_WORK(&cdev->private->kick_work, 1025 PREPARE_WORK(&cdev->private->kick_work,
1024 ccw_device_nopath_notify, cdev); 1026 ccw_device_nopath_notify);
1025 queue_work(ccw_device_notify_work, 1027 queue_work(ccw_device_notify_work,
1026 &cdev->private->kick_work); 1028 &cdev->private->kick_work);
1027 } else 1029 } else
@@ -1033,7 +1035,7 @@ void device_kill_io(struct subchannel *sch)
1033 ERR_PTR(-EIO)); 1035 ERR_PTR(-EIO));
1034 if (!sch->lpm) { 1036 if (!sch->lpm) {
1035 PREPARE_WORK(&cdev->private->kick_work, 1037 PREPARE_WORK(&cdev->private->kick_work,
1036 ccw_device_nopath_notify, cdev); 1038 ccw_device_nopath_notify);
1037 queue_work(ccw_device_notify_work, &cdev->private->kick_work); 1039 queue_work(ccw_device_notify_work, &cdev->private->kick_work);
1038 } else 1040 } else
1039 /* Start delayed path verification. */ 1041 /* Start delayed path verification. */
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 8d5fa1b4d11f..d066dbf2c65d 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -2045,11 +2045,13 @@ omit_handler_call:
2045} 2045}
2046 2046
2047static void 2047static void
2048qdio_call_shutdown(void *data) 2048qdio_call_shutdown(struct work_struct *work)
2049{ 2049{
2050 struct ccw_device_private *priv;
2050 struct ccw_device *cdev; 2051 struct ccw_device *cdev;
2051 2052
2052 cdev = (struct ccw_device *)data; 2053 priv = container_of(work, struct ccw_device_private, kick_work);
2054 cdev = priv->cdev;
2053 qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR); 2055 qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
2054 put_device(&cdev->dev); 2056 put_device(&cdev->dev);
2055} 2057}
@@ -2091,7 +2093,7 @@ qdio_timeout_handler(struct ccw_device *cdev)
2091 if (get_device(&cdev->dev)) { 2093 if (get_device(&cdev->dev)) {
2092 /* Can't call shutdown from interrupt context. */ 2094 /* Can't call shutdown from interrupt context. */
2093 PREPARE_WORK(&cdev->private->kick_work, 2095 PREPARE_WORK(&cdev->private->kick_work,
2094 qdio_call_shutdown, (void *)cdev); 2096 qdio_call_shutdown);
2095 queue_work(ccw_device_work, &cdev->private->kick_work); 2097 queue_work(ccw_device_work, &cdev->private->kick_work);
2096 } 2098 }
2097 break; 2099 break;