diff options
author | Jan Glauber <jang@linux.vnet.ibm.com> | 2009-03-26 10:24:24 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-03-26 10:24:19 -0400 |
commit | b454740246d14b0a9c00220696f9020eaa15ca12 (patch) | |
tree | 8d0deb7de94992548aae364ef39f34c4c67cf096 | |
parent | feed9b62da6e2997612143ae4b857ec7f33c810d (diff) |
[S390] qdio: add missing tiq_list locking
Add a mutex to protect the tiq_list. Although reading the list is done
using RCU adding and removing elements from the list must still
happen locked since multiple qdio devices may change the list in parallel
otherwise.
Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 1 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_thinint.c | 10 |
2 files changed, 8 insertions, 3 deletions
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 10cb0f8726e5..5100996201d1 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -1112,6 +1112,7 @@ int qdio_shutdown(struct ccw_device *cdev, int how) | |||
1112 | if (!irq_ptr) | 1112 | if (!irq_ptr) |
1113 | return -ENODEV; | 1113 | return -ENODEV; |
1114 | 1114 | ||
1115 | BUG_ON(irqs_disabled()); | ||
1115 | DBF_EVENT("qshutdown:%4x", cdev->private->schid.sch_no); | 1116 | DBF_EVENT("qshutdown:%4x", cdev->private->schid.sch_no); |
1116 | 1117 | ||
1117 | mutex_lock(&irq_ptr->setup_mutex); | 1118 | mutex_lock(&irq_ptr->setup_mutex); |
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index 8e90e147b746..981044c83864 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c | |||
@@ -31,6 +31,7 @@ | |||
31 | 31 | ||
32 | /* list of thin interrupt input queues */ | 32 | /* list of thin interrupt input queues */ |
33 | static LIST_HEAD(tiq_list); | 33 | static LIST_HEAD(tiq_list); |
34 | DEFINE_MUTEX(tiq_list_lock); | ||
34 | 35 | ||
35 | /* adapter local summary indicator */ | 36 | /* adapter local summary indicator */ |
36 | static unsigned char *tiqdio_alsi; | 37 | static unsigned char *tiqdio_alsi; |
@@ -95,10 +96,10 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr) | |||
95 | if (!css_qdio_omit_svs && irq_ptr->siga_flag.sync) | 96 | if (!css_qdio_omit_svs && irq_ptr->siga_flag.sync) |
96 | css_qdio_omit_svs = 1; | 97 | css_qdio_omit_svs = 1; |
97 | 98 | ||
98 | for_each_input_queue(irq_ptr, q, i) { | 99 | mutex_lock(&tiq_list_lock); |
100 | for_each_input_queue(irq_ptr, q, i) | ||
99 | list_add_rcu(&q->entry, &tiq_list); | 101 | list_add_rcu(&q->entry, &tiq_list); |
100 | synchronize_rcu(); | 102 | mutex_unlock(&tiq_list_lock); |
101 | } | ||
102 | xchg(irq_ptr->dsci, 1); | 103 | xchg(irq_ptr->dsci, 1); |
103 | tasklet_schedule(&tiqdio_tasklet); | 104 | tasklet_schedule(&tiqdio_tasklet); |
104 | } | 105 | } |
@@ -118,7 +119,10 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) | |||
118 | /* if establish triggered an error */ | 119 | /* if establish triggered an error */ |
119 | if (!q || !q->entry.prev || !q->entry.next) | 120 | if (!q || !q->entry.prev || !q->entry.next) |
120 | continue; | 121 | continue; |
122 | |||
123 | mutex_lock(&tiq_list_lock); | ||
121 | list_del_rcu(&q->entry); | 124 | list_del_rcu(&q->entry); |
125 | mutex_unlock(&tiq_list_lock); | ||
122 | synchronize_rcu(); | 126 | synchronize_rcu(); |
123 | } | 127 | } |
124 | } | 128 | } |