]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Gerald Schaefer <geraldsc@de.ibm.com> |
2 | Subject: qdio: add missing tiq_list locking | |
3 | References: bnc#484767,LTC#52205 | |
4 | ||
5 | Symptom: The system may hang if multiple qdio devices are added or | |
6 | removed in parallel. | |
7 | Problem: Although reading the tiq_list is done using RCU adding and | |
8 | removing elements from the list must still happen locked since | |
9 | multiple qdio devices may change the list in parallel otherwise. | |
10 | Solution: Add a mutex to protect the tiq_list. | |
11 | ||
12 | Acked-by: John Jolly <jjolly@suse.de> | |
13 | --- | |
14 | drivers/s390/cio/qdio_main.c | 1 + | |
15 | drivers/s390/cio/qdio_thinint.c | 10 +++++++--- | |
16 | 2 files changed, 8 insertions(+), 3 deletions(-) | |
17 | ||
18 | Index: linux-sles11/drivers/s390/cio/qdio_main.c | |
19 | =================================================================== | |
20 | --- linux-sles11.orig/drivers/s390/cio/qdio_main.c | |
21 | +++ linux-sles11/drivers/s390/cio/qdio_main.c | |
22 | @@ -1094,6 +1094,7 @@ int qdio_shutdown(struct ccw_device *cde | |
23 | if (!irq_ptr) | |
24 | return -ENODEV; | |
25 | ||
26 | + BUG_ON(irqs_disabled()); | |
27 | DBF_EVENT("qshutdown:%4x", cdev->private->schid.sch_no); | |
28 | ||
29 | mutex_lock(&irq_ptr->setup_mutex); | |
30 | Index: linux-sles11/drivers/s390/cio/qdio_thinint.c | |
31 | =================================================================== | |
32 | --- linux-sles11.orig/drivers/s390/cio/qdio_thinint.c | |
33 | +++ linux-sles11/drivers/s390/cio/qdio_thinint.c | |
34 | @@ -31,6 +31,7 @@ | |
35 | ||
36 | /* list of thin interrupt input queues */ | |
37 | static LIST_HEAD(tiq_list); | |
38 | +DEFINE_MUTEX(tiq_list_lock); | |
39 | ||
40 | /* adapter local summary indicator */ | |
41 | static unsigned char *tiqdio_alsi; | |
42 | @@ -95,10 +96,10 @@ void tiqdio_add_input_queues(struct qdio | |
43 | if (!css_qdio_omit_svs && irq_ptr->siga_flag.sync) | |
44 | css_qdio_omit_svs = 1; | |
45 | ||
46 | - for_each_input_queue(irq_ptr, q, i) { | |
47 | + mutex_lock(&tiq_list_lock); | |
48 | + for_each_input_queue(irq_ptr, q, i) | |
49 | list_add_rcu(&q->entry, &tiq_list); | |
50 | - synchronize_rcu(); | |
51 | - } | |
52 | + mutex_unlock(&tiq_list_lock); | |
53 | xchg(irq_ptr->dsci, 1); | |
54 | tasklet_schedule(&tiqdio_tasklet); | |
55 | } | |
56 | @@ -118,7 +119,10 @@ void tiqdio_remove_input_queues(struct q | |
57 | /* if establish triggered an error */ | |
58 | if (!q || !q->entry.prev || !q->entry.next) | |
59 | continue; | |
60 | + | |
61 | + mutex_lock(&tiq_list_lock); | |
62 | list_del_rcu(&q->entry); | |
63 | + mutex_unlock(&tiq_list_lock); | |
64 | synchronize_rcu(); | |
65 | } | |
66 | } |