diff options
author | Jan Glauber <jang@linux.vnet.ibm.com> | 2009-06-22 06:08:13 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-06-22 06:08:20 -0400 |
commit | cf9a031c2cc881e9873ab9ccf5e1f59f5b5167aa (patch) | |
tree | 0d580af91b11c929147636ca57d727255a9fd3dc /drivers/s390 | |
parent | 36e3e72120e27939233e4bd88a8d74b3a2377428 (diff) |
[S390] qdio: merge AI tasklet into interrupt handler
Since the adapter interrupt tasklet only schedules the queue tasklets
and contains no code that requires serialization in can be merged
with the adapter interrupt handler. That possibly safes some CPU
cycles.
Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/cio/qdio_thinint.c | 65 |
1 files changed, 21 insertions, 44 deletions
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index e122f780f5ee..981a77ea7ee2 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c | |||
@@ -43,9 +43,6 @@ struct indicator_t { | |||
43 | }; | 43 | }; |
44 | static struct indicator_t *q_indicators; | 44 | static struct indicator_t *q_indicators; |
45 | 45 | ||
46 | static void tiqdio_tasklet_fn(unsigned long data); | ||
47 | static DECLARE_TASKLET(tiqdio_tasklet, tiqdio_tasklet_fn, 0); | ||
48 | |||
49 | static int css_qdio_omit_svs; | 46 | static int css_qdio_omit_svs; |
50 | 47 | ||
51 | static inline unsigned long do_clear_global_summary(void) | 48 | static inline unsigned long do_clear_global_summary(void) |
@@ -103,11 +100,6 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr) | |||
103 | xchg(irq_ptr->dsci, 1); | 100 | xchg(irq_ptr->dsci, 1); |
104 | } | 101 | } |
105 | 102 | ||
106 | /* | ||
107 | * we cannot stop the tiqdio tasklet here since it is for all | ||
108 | * thinint qdio devices and it must run as long as there is a | ||
109 | * thinint device left | ||
110 | */ | ||
111 | void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) | 103 | void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) |
112 | { | 104 | { |
113 | struct qdio_q *q; | 105 | struct qdio_q *q; |
@@ -131,17 +123,34 @@ static inline int shared_ind(struct qdio_irq *irq_ptr) | |||
131 | return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind; | 123 | return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind; |
132 | } | 124 | } |
133 | 125 | ||
134 | /* check for work on all inbound thinint queues */ | 126 | /** |
135 | static void tiqdio_tasklet_fn(unsigned long data) | 127 | * tiqdio_thinint_handler - thin interrupt handler for qdio |
128 | * @ind: pointer to adapter local summary indicator | ||
129 | * @drv_data: NULL | ||
130 | */ | ||
131 | static void tiqdio_thinint_handler(void *ind, void *drv_data) | ||
136 | { | 132 | { |
137 | struct qdio_q *q; | 133 | struct qdio_q *q; |
138 | 134 | ||
139 | qdio_perf_stat_inc(&perf_stats.tasklet_thinint); | 135 | qdio_perf_stat_inc(&perf_stats.thin_int); |
140 | again: | 136 | |
137 | /* | ||
138 | * SVS only when needed: issue SVS to benefit from iqdio interrupt | ||
139 | * avoidance (SVS clears adapter interrupt suppression overwrite) | ||
140 | */ | ||
141 | if (!css_qdio_omit_svs) | ||
142 | do_clear_global_summary(); | ||
143 | |||
144 | /* | ||
145 | * reset local summary indicator (tiqdio_alsi) to stop adapter | ||
146 | * interrupts for now | ||
147 | */ | ||
148 | xchg((u8 *)ind, 0); | ||
141 | 149 | ||
142 | /* protect tiq_list entries, only changed in activate or shutdown */ | 150 | /* protect tiq_list entries, only changed in activate or shutdown */ |
143 | rcu_read_lock(); | 151 | rcu_read_lock(); |
144 | 152 | ||
153 | /* check for work on all inbound thinint queues */ | ||
145 | list_for_each_entry_rcu(q, &tiq_list, entry) | 154 | list_for_each_entry_rcu(q, &tiq_list, entry) |
146 | /* only process queues from changed sets */ | 155 | /* only process queues from changed sets */ |
147 | if (*q->irq_ptr->dsci) { | 156 | if (*q->irq_ptr->dsci) { |
@@ -169,37 +178,6 @@ again: | |||
169 | if (*tiqdio_alsi) | 178 | if (*tiqdio_alsi) |
170 | xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1); | 179 | xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1); |
171 | } | 180 | } |
172 | |||
173 | /* check for more work */ | ||
174 | if (*tiqdio_alsi) { | ||
175 | xchg(tiqdio_alsi, 0); | ||
176 | qdio_perf_stat_inc(&perf_stats.tasklet_thinint_loop); | ||
177 | goto again; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | /** | ||
182 | * tiqdio_thinint_handler - thin interrupt handler for qdio | ||
183 | * @ind: pointer to adapter local summary indicator | ||
184 | * @drv_data: NULL | ||
185 | */ | ||
186 | static void tiqdio_thinint_handler(void *ind, void *drv_data) | ||
187 | { | ||
188 | qdio_perf_stat_inc(&perf_stats.thin_int); | ||
189 | |||
190 | /* | ||
191 | * SVS only when needed: issue SVS to benefit from iqdio interrupt | ||
192 | * avoidance (SVS clears adapter interrupt suppression overwrite) | ||
193 | */ | ||
194 | if (!css_qdio_omit_svs) | ||
195 | do_clear_global_summary(); | ||
196 | |||
197 | /* | ||
198 | * reset local summary indicator (tiqdio_alsi) to stop adapter | ||
199 | * interrupts for now, the tasklet will clean all dsci's | ||
200 | */ | ||
201 | xchg((u8 *)ind, 0); | ||
202 | tasklet_hi_schedule(&tiqdio_tasklet); | ||
203 | } | 181 | } |
204 | 182 | ||
205 | static int set_subchannel_ind(struct qdio_irq *irq_ptr, int reset) | 183 | static int set_subchannel_ind(struct qdio_irq *irq_ptr, int reset) |
@@ -319,5 +297,4 @@ void __exit tiqdio_unregister_thinints(void) | |||
319 | s390_unregister_adapter_interrupt(tiqdio_alsi, QDIO_AIRQ_ISC); | 297 | s390_unregister_adapter_interrupt(tiqdio_alsi, QDIO_AIRQ_ISC); |
320 | isc_unregister(QDIO_AIRQ_ISC); | 298 | isc_unregister(QDIO_AIRQ_ISC); |
321 | } | 299 | } |
322 | tasklet_kill(&tiqdio_tasklet); | ||
323 | } | 300 | } |