aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/css.c
diff options
context:
space:
mode:
authorPeter Oberparleiter <peter.oberparleiter@de.ibm.com>2009-03-26 10:24:20 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-03-26 10:24:18 -0400
commit56e25e9777bf15365293e27a3256eb9214a11edf (patch)
tree832f5944f20379e33855cb55418b6407c81141a3 /drivers/s390/cio/css.c
parent0cc110651bed4612074eeb445a23418a5ee34cd0 (diff)
[S390] cio: prevent workqueue deadlock
Subchannel reprobing can block the kslowcrw workqueue indefinitely while waiting for device recognition to finish which is also scheduled to run on kslowcrw. Prevent this deadlock by moving the waiting portion of subchannel reprobing to the cio workqueue. Signed-off-by: Peter Oberparleiter <peter.oberparleiter@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/css.c')
-rw-r--r--drivers/s390/cio/css.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 1f2e424596af..8446d15e4485 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -533,6 +533,17 @@ static int reprobe_subchannel(struct subchannel_id schid, void *data)
533 return ret; 533 return ret;
534} 534}
535 535
536static void reprobe_after_idle(struct work_struct *unused)
537{
538 /* Make sure initial subchannel scan is done. */
539 wait_event(ccw_device_init_wq,
540 atomic_read(&ccw_device_init_count) == 0);
541 if (need_reprobe)
542 css_schedule_reprobe();
543}
544
545static DECLARE_WORK(reprobe_idle_work, reprobe_after_idle);
546
536/* Work function used to reprobe all unregistered subchannels. */ 547/* Work function used to reprobe all unregistered subchannels. */
537static void reprobe_all(struct work_struct *unused) 548static void reprobe_all(struct work_struct *unused)
538{ 549{
@@ -540,10 +551,12 @@ static void reprobe_all(struct work_struct *unused)
540 551
541 CIO_MSG_EVENT(4, "reprobe start\n"); 552 CIO_MSG_EVENT(4, "reprobe start\n");
542 553
543 need_reprobe = 0;
544 /* Make sure initial subchannel scan is done. */ 554 /* Make sure initial subchannel scan is done. */
545 wait_event(ccw_device_init_wq, 555 if (atomic_read(&ccw_device_init_count) != 0) {
546 atomic_read(&ccw_device_init_count) == 0); 556 queue_work(ccw_device_work, &reprobe_idle_work);
557 return;
558 }
559 need_reprobe = 0;
547 ret = for_each_subchannel_staged(NULL, reprobe_subchannel, NULL); 560 ret = for_each_subchannel_staged(NULL, reprobe_subchannel, NULL);
548 561
549 CIO_MSG_EVENT(4, "reprobe done (rc=%d, need_reprobe=%d)\n", ret, 562 CIO_MSG_EVENT(4, "reprobe done (rc=%d, need_reprobe=%d)\n", ret,