From b4563e891a043fe521e62f6f621b928641474ff3 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Fri, 26 Feb 2010 22:37:26 +0100 Subject: [S390] cio: wait for channel report To fetch a pending channel report word (crw) we use a kernel thread which triggers stcrw and sleeps on a semaphore. The s390 machine check handler uses crw_handle_channel_report to handle one crw if needed. This patch replaces the semaphore with a waitqueue (to block the kernel thread) and an atomic_t (to count the number of pending requests). By this we achieve the ability to force this thread to check for a pending crw (independent on when it is triggered by the machine check handler) and wait for this action to finish. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/crw.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/cio/crw.c b/drivers/s390/cio/crw.c index d157665..425f741 100644 --- a/drivers/s390/cio/crw.c +++ b/drivers/s390/cio/crw.c @@ -8,15 +8,16 @@ * Heiko Carstens , */ -#include #include #include #include +#include #include -static struct semaphore crw_semaphore; static DEFINE_MUTEX(crw_handler_mutex); static crw_handler_t crw_handlers[NR_RSCS]; +static atomic_t crw_nr_req = ATOMIC_INIT(0); +static DECLARE_WAIT_QUEUE_HEAD(crw_handler_wait_q); /** * crw_register_handler() - register a channel report word handler @@ -59,12 +60,14 @@ void crw_unregister_handler(int rsc) static int crw_collect_info(void *unused) { struct crw crw[2]; - int ccode; + int ccode, signal; unsigned int chain; - int ignore; repeat: - ignore = down_interruptible(&crw_semaphore); + signal = wait_event_interruptible(crw_handler_wait_q, + atomic_read(&crw_nr_req) > 0); + if (unlikely(signal)) + atomic_inc(&crw_nr_req); chain = 0; while (1) { crw_handler_t handler; @@ -122,25 +125,23 @@ repeat: /* chain is always 0 or 1 here. */ chain = crw[chain].chn ? chain + 1 : 0; } + if (atomic_dec_and_test(&crw_nr_req)) + wake_up(&crw_handler_wait_q); goto repeat; return 0; } void crw_handle_channel_report(void) { - up(&crw_semaphore); + atomic_inc(&crw_nr_req); + wake_up(&crw_handler_wait_q); } -/* - * Separate initcall needed for semaphore initialization since - * crw_handle_channel_report might be called before crw_machine_check_init. - */ -static int __init crw_init_semaphore(void) +void crw_wait_for_channel_report(void) { - init_MUTEX_LOCKED(&crw_semaphore); - return 0; + crw_handle_channel_report(); + wait_event(crw_handler_wait_q, atomic_read(&crw_nr_req) == 0); } -pure_initcall(crw_init_semaphore); /* * Machine checks for the channel subsystem must be enabled -- cgit v1.1