diff options
Diffstat (limited to 'drivers/s390/cio/crw.c')
| -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 d157665d0e7..425f741a280 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  |