diff options
Diffstat (limited to 'drivers/s390/cio/qdio_thinint.c')
-rw-r--r-- | drivers/s390/cio/qdio_thinint.c | 114 |
1 files changed, 17 insertions, 97 deletions
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index c655d01..981a77e 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -43,9 +43,6 @@ struct indicator_t { }; static struct indicator_t *q_indicators; -static void tiqdio_tasklet_fn(unsigned long data); -static DECLARE_TASKLET(tiqdio_tasklet, tiqdio_tasklet_fn, 0); - static int css_qdio_omit_svs; static inline unsigned long do_clear_global_summary(void) @@ -103,11 +100,6 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr) xchg(irq_ptr->dsci, 1); } -/* - * we cannot stop the tiqdio tasklet here since it is for all - * thinint qdio devices and it must run as long as there is a - * thinint device left - */ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) { struct qdio_q *q; @@ -126,79 +118,39 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) } } -static inline int tiqdio_inbound_q_done(struct qdio_q *q) -{ - unsigned char state = 0; - - if (!atomic_read(&q->nr_buf_used)) - return 1; - - qdio_siga_sync_q(q); - get_buf_state(q, q->first_to_check, &state, 0); - - if (state == SLSB_P_INPUT_PRIMED) - /* more work coming */ - return 0; - return 1; -} - static inline int shared_ind(struct qdio_irq *irq_ptr) { return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind; } -static void __tiqdio_inbound_processing(struct qdio_q *q) +/** + * tiqdio_thinint_handler - thin interrupt handler for qdio + * @ind: pointer to adapter local summary indicator + * @drv_data: NULL + */ +static void tiqdio_thinint_handler(void *ind, void *drv_data) { - qdio_perf_stat_inc(&perf_stats.thinint_inbound); - qdio_sync_after_thinint(q); + struct qdio_q *q; + + qdio_perf_stat_inc(&perf_stats.thin_int); /* - * Maybe we have work on our outbound queues... at least - * we have to check the PCI capable queues. + * SVS only when needed: issue SVS to benefit from iqdio interrupt + * avoidance (SVS clears adapter interrupt suppression overwrite) */ - qdio_check_outbound_after_thinint(q); - - if (!qdio_inbound_q_moved(q)) - return; - - qdio_kick_handler(q); - - if (!tiqdio_inbound_q_done(q)) { - qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop); - if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) - tasklet_schedule(&q->tasklet); - } + if (!css_qdio_omit_svs) + do_clear_global_summary(); - qdio_stop_polling(q); /* - * We need to check again to not lose initiative after - * resetting the ACK state. + * reset local summary indicator (tiqdio_alsi) to stop adapter + * interrupts for now */ - if (!tiqdio_inbound_q_done(q)) { - qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop2); - if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) - tasklet_schedule(&q->tasklet); - } -} - -void tiqdio_inbound_processing(unsigned long data) -{ - struct qdio_q *q = (struct qdio_q *)data; - - __tiqdio_inbound_processing(q); -} - -/* check for work on all inbound thinint queues */ -static void tiqdio_tasklet_fn(unsigned long data) -{ - struct qdio_q *q; - - qdio_perf_stat_inc(&perf_stats.tasklet_thinint); -again: + xchg((u8 *)ind, 0); /* protect tiq_list entries, only changed in activate or shutdown */ rcu_read_lock(); + /* check for work on all inbound thinint queues */ list_for_each_entry_rcu(q, &tiq_list, entry) /* only process queues from changed sets */ if (*q->irq_ptr->dsci) { @@ -226,37 +178,6 @@ again: if (*tiqdio_alsi) xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1); } - - /* check for more work */ - if (*tiqdio_alsi) { - xchg(tiqdio_alsi, 0); - qdio_perf_stat_inc(&perf_stats.tasklet_thinint_loop); - goto again; - } -} - -/** - * tiqdio_thinint_handler - thin interrupt handler for qdio - * @ind: pointer to adapter local summary indicator - * @drv_data: NULL - */ -static void tiqdio_thinint_handler(void *ind, void *drv_data) -{ - qdio_perf_stat_inc(&perf_stats.thin_int); - - /* - * SVS only when needed: issue SVS to benefit from iqdio interrupt - * avoidance (SVS clears adapter interrupt suppression overwrite) - */ - if (!css_qdio_omit_svs) - do_clear_global_summary(); - - /* - * reset local summary indicator (tiqdio_alsi) to stop adapter - * interrupts for now, the tasklet will clean all dsci's - */ - xchg((u8 *)ind, 0); - tasklet_hi_schedule(&tiqdio_tasklet); } static int set_subchannel_ind(struct qdio_irq *irq_ptr, int reset) @@ -376,5 +297,4 @@ void __exit tiqdio_unregister_thinints(void) s390_unregister_adapter_interrupt(tiqdio_alsi, QDIO_AIRQ_ISC); isc_unregister(QDIO_AIRQ_ISC); } - tasklet_kill(&tiqdio_tasklet); } |