aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}