From 6fb7349af0e0febac68f03424b4bfc5f52b31867 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Mar 2009 15:24:09 +0100 Subject: [PATCH] --- yaml --- r: 135612 b: refs/heads/master c: 98c1c6825247c71e3d8a9a5439ba21fce7563014 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/s390/cio/crw.c | 32 +++++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/[refs] b/[refs] index aa217110e808..55d019a1881f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: e74fe0cec92439115630b51195444b89b910800a +refs/heads/master: 98c1c6825247c71e3d8a9a5439ba21fce7563014 diff --git a/trunk/drivers/s390/cio/crw.c b/trunk/drivers/s390/cio/crw.c index 508f88f6420c..d157665d0e76 100644 --- a/trunk/drivers/s390/cio/crw.c +++ b/trunk/drivers/s390/cio/crw.c @@ -9,11 +9,13 @@ */ #include +#include #include #include #include static struct semaphore crw_semaphore; +static DEFINE_MUTEX(crw_handler_mutex); static crw_handler_t crw_handlers[NR_RSCS]; /** @@ -25,11 +27,17 @@ static crw_handler_t crw_handlers[NR_RSCS]; */ int crw_register_handler(int rsc, crw_handler_t handler) { + int rc = 0; + if ((rsc < 0) || (rsc >= NR_RSCS)) return -EINVAL; - if (!cmpxchg(&crw_handlers[rsc], NULL, handler)) - return 0; - return -EBUSY; + mutex_lock(&crw_handler_mutex); + if (crw_handlers[rsc]) + rc = -EBUSY; + else + crw_handlers[rsc] = handler; + mutex_unlock(&crw_handler_mutex); + return rc; } /** @@ -40,8 +48,9 @@ void crw_unregister_handler(int rsc) { if ((rsc < 0) || (rsc >= NR_RSCS)) return; - xchg(&crw_handlers[rsc], NULL); - synchronize_sched(); + mutex_lock(&crw_handler_mutex); + crw_handlers[rsc] = NULL; + mutex_unlock(&crw_handler_mutex); } /* @@ -58,6 +67,8 @@ static int crw_collect_info(void *unused) ignore = down_interruptible(&crw_semaphore); chain = 0; while (1) { + crw_handler_t handler; + if (unlikely(chain > 1)) { struct crw tmp_crw; @@ -90,10 +101,12 @@ static int crw_collect_info(void *unused) int i; pr_debug("%s: crw overflow detected!\n", __func__); + mutex_lock(&crw_handler_mutex); for (i = 0; i < NR_RSCS; i++) { if (crw_handlers[i]) crw_handlers[i](NULL, NULL, 1); } + mutex_unlock(&crw_handler_mutex); chain = 0; continue; } @@ -101,10 +114,11 @@ static int crw_collect_info(void *unused) chain++; continue; } - if (crw_handlers[crw[chain].rsc]) - crw_handlers[crw[chain].rsc](&crw[0], - chain ? &crw[1] : NULL, - 0); + mutex_lock(&crw_handler_mutex); + handler = crw_handlers[crw[chain].rsc]; + if (handler) + handler(&crw[0], chain ? &crw[1] : NULL, 0); + mutex_unlock(&crw_handler_mutex); /* chain is always 0 or 1 here. */ chain = crw[chain].chn ? chain + 1 : 0; }