diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/cio/crw.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/drivers/s390/cio/crw.c b/drivers/s390/cio/crw.c index d157665d0e76..425f741a280c 100644 --- a/drivers/s390/cio/crw.c +++ b/drivers/s390/cio/crw.c @@ -8,15 +8,16 @@ * Heiko Carstens <heiko.carstens@de.ibm.com>, */ -#include <linux/semaphore.h> #include <linux/mutex.h> #include <linux/kthread.h> #include <linux/init.h> +#include <linux/wait.h> #include <asm/crw.h> -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 |