]>
Commit | Line | Data |
---|---|---|
82094b55 AF |
1 | From: Gerald Schaefer <geraldsc@de.ibm.com> |
2 | Subject: [PATCH] qdio: merge AI tasklet into interrupt handler | |
3 | References: bnc#532063,LTC#55526 | |
4 | ||
5 | From: Jan Glauber <jang@linux.vnet.ibm.com> | |
6 | ||
7 | Since the adapter interrupt tasklet only schedules the queue tasklets | |
8 | and contains no code that requires serialization in can be merged | |
9 | with the adapter interrupt handler. That possibly safes some CPU | |
10 | cycles. | |
11 | ||
12 | Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com> | |
13 | ||
14 | Acked-by: John Jolly <jjolly@suse.de> | |
15 | ||
16 | --- | |
17 | drivers/s390/cio/qdio_thinint.c | 66 ++++++++++++---------------------------- | |
18 | 1 file changed, 21 insertions(+), 45 deletions(-) | |
19 | ||
20 | Index: linux-sles11/drivers/s390/cio/qdio_thinint.c | |
21 | =================================================================== | |
22 | --- linux-sles11.orig/drivers/s390/cio/qdio_thinint.c | |
23 | +++ linux-sles11/drivers/s390/cio/qdio_thinint.c | |
24 | @@ -43,9 +43,6 @@ struct indicator_t { | |
25 | }; | |
26 | static struct indicator_t *q_indicators; | |
27 | ||
28 | -static void tiqdio_tasklet_fn(unsigned long data); | |
29 | -static DECLARE_TASKLET(tiqdio_tasklet, tiqdio_tasklet_fn, 0); | |
30 | - | |
31 | static int css_qdio_omit_svs; | |
32 | ||
33 | static inline unsigned long do_clear_global_summary(void) | |
34 | @@ -103,11 +100,6 @@ void tiqdio_add_input_queues(struct qdio | |
35 | xchg(irq_ptr->dsci, 1); | |
36 | } | |
37 | ||
38 | -/* | |
39 | - * we cannot stop the tiqdio tasklet here since it is for all | |
40 | - * thinint qdio devices and it must run as long as there is a | |
41 | - * thinint device left | |
42 | - */ | |
43 | void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) | |
44 | { | |
45 | struct qdio_q *q; | |
46 | @@ -131,17 +123,34 @@ static inline int shared_ind(struct qdio | |
47 | return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind; | |
48 | } | |
49 | ||
50 | -/* check for work on all inbound thinint queues */ | |
51 | -static void tiqdio_tasklet_fn(unsigned long data) | |
52 | +/** | |
53 | + * tiqdio_thinint_handler - thin interrupt handler for qdio | |
54 | + * @ind: pointer to adapter local summary indicator | |
55 | + * @drv_data: NULL | |
56 | + */ | |
57 | +static void tiqdio_thinint_handler(void *ind, void *drv_data) | |
58 | { | |
59 | struct qdio_q *q; | |
60 | ||
61 | - qdio_perf_stat_inc(&perf_stats.tasklet_thinint); | |
62 | -again: | |
63 | + qdio_perf_stat_inc(&perf_stats.thin_int); | |
64 | + | |
65 | + /* | |
66 | + * SVS only when needed: issue SVS to benefit from iqdio interrupt | |
67 | + * avoidance (SVS clears adapter interrupt suppression overwrite) | |
68 | + */ | |
69 | + if (!css_qdio_omit_svs) | |
70 | + do_clear_global_summary(); | |
71 | + | |
72 | + /* | |
73 | + * reset local summary indicator (tiqdio_alsi) to stop adapter | |
74 | + * interrupts for now | |
75 | + */ | |
76 | + xchg((u8 *)ind, 0); | |
77 | ||
78 | /* protect tiq_list entries, only changed in activate or shutdown */ | |
79 | rcu_read_lock(); | |
80 | ||
81 | + /* check for work on all inbound thinint queues */ | |
82 | list_for_each_entry_rcu(q, &tiq_list, entry) | |
83 | /* only process queues from changed sets */ | |
84 | if (*q->irq_ptr->dsci) { | |
85 | @@ -169,37 +178,6 @@ again: | |
86 | if (*tiqdio_alsi) | |
87 | xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1); | |
88 | } | |
89 | - | |
90 | - /* check for more work */ | |
91 | - if (*tiqdio_alsi) { | |
92 | - xchg(tiqdio_alsi, 0); | |
93 | - qdio_perf_stat_inc(&perf_stats.tasklet_thinint_loop); | |
94 | - goto again; | |
95 | - } | |
96 | -} | |
97 | - | |
98 | -/** | |
99 | - * tiqdio_thinint_handler - thin interrupt handler for qdio | |
100 | - * @ind: pointer to adapter local summary indicator | |
101 | - * @drv_data: NULL | |
102 | - */ | |
103 | -static void tiqdio_thinint_handler(void *ind, void *drv_data) | |
104 | -{ | |
105 | - qdio_perf_stat_inc(&perf_stats.thin_int); | |
106 | - | |
107 | - /* | |
108 | - * SVS only when needed: issue SVS to benefit from iqdio interrupt | |
109 | - * avoidance (SVS clears adapter interrupt suppression overwrite) | |
110 | - */ | |
111 | - if (!css_qdio_omit_svs) | |
112 | - do_clear_global_summary(); | |
113 | - | |
114 | - /* | |
115 | - * reset local summary indicator (tiqdio_alsi) to stop adapter | |
116 | - * interrupts for now, the tasklet will clean all dsci's | |
117 | - */ | |
118 | - xchg((u8 *)ind, 0); | |
119 | - tasklet_hi_schedule(&tiqdio_tasklet); | |
120 | } | |
121 | ||
122 | static int set_subchannel_ind(struct qdio_irq *irq_ptr, int reset) | |
123 | @@ -313,8 +291,6 @@ void qdio_shutdown_thinint(struct qdio_i | |
124 | ||
125 | void __exit tiqdio_unregister_thinints(void) | |
126 | { | |
127 | - tasklet_disable(&tiqdio_tasklet); | |
128 | - | |
129 | if (tiqdio_alsi) { | |
130 | s390_unregister_adapter_interrupt(tiqdio_alsi, QDIO_AIRQ_ISC); | |
131 | isc_unregister(QDIO_AIRQ_ISC); |