aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorJan Glauber <jang@linux.vnet.ibm.com>2009-06-22 06:08:13 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-06-22 06:08:20 -0400
commitcf9a031c2cc881e9873ab9ccf5e1f59f5b5167aa (patch)
tree0d580af91b11c929147636ca57d727255a9fd3dc /drivers/s390/cio
parent36e3e72120e27939233e4bd88a8d74b3a2377428 (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/cio')
-rw-r--r--drivers/s390/cio/qdio_thinint.c65
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};
44static struct indicator_t *q_indicators; 44static struct indicator_t *q_indicators;
45 45
46static void tiqdio_tasklet_fn(unsigned long data);
47static DECLARE_TASKLET(tiqdio_tasklet, tiqdio_tasklet_fn, 0);
48
49static int css_qdio_omit_svs; 46static int css_qdio_omit_svs;
50 47
51static inline unsigned long do_clear_global_summary(void) 48static 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 */
111void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) 103void 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/**
135static 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 */
131static 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);
140again: 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 */
186static 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
205static int set_subchannel_ind(struct qdio_irq *irq_ptr, int reset) 183static 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}