Commit 60b5df2f authored by Jan Glauber's avatar Jan Glauber Committed by Martin Schwidefsky

[S390] qdio: move adapter interrupt tasklet code

Move the adapter interrupt tasklet function to the qdio main code
since all the functions used by the tasklet are located there.
Signed-off-by: default avatarJan Glauber <jang@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent f3dfa86c
...@@ -351,15 +351,6 @@ static inline unsigned long long get_usecs(void) ...@@ -351,15 +351,6 @@ static inline unsigned long long get_usecs(void)
((bufnr - dec) & QDIO_MAX_BUFFERS_MASK) ((bufnr - dec) & QDIO_MAX_BUFFERS_MASK)
/* prototypes for thin interrupt */ /* prototypes for thin interrupt */
void qdio_sync_after_thinint(struct qdio_q *q);
int get_buf_state(struct qdio_q *q, unsigned int bufnr, unsigned char *state,
int auto_ack);
void qdio_check_outbound_after_thinint(struct qdio_q *q);
int qdio_inbound_q_moved(struct qdio_q *q);
void qdio_kick_handler(struct qdio_q *q);
void qdio_stop_polling(struct qdio_q *q);
int qdio_siga_sync_q(struct qdio_q *q);
void qdio_setup_thinint(struct qdio_irq *irq_ptr); void qdio_setup_thinint(struct qdio_irq *irq_ptr);
int qdio_establish_thinint(struct qdio_irq *irq_ptr); int qdio_establish_thinint(struct qdio_irq *irq_ptr);
void qdio_shutdown_thinint(struct qdio_irq *irq_ptr); void qdio_shutdown_thinint(struct qdio_irq *irq_ptr);
...@@ -392,4 +383,6 @@ void qdio_setup_destroy_sysfs(struct ccw_device *cdev); ...@@ -392,4 +383,6 @@ void qdio_setup_destroy_sysfs(struct ccw_device *cdev);
int qdio_setup_init(void); int qdio_setup_init(void);
void qdio_setup_exit(void); void qdio_setup_exit(void);
int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
unsigned char *state);
#endif /* _CIO_QDIO_H */ #endif /* _CIO_QDIO_H */
...@@ -70,9 +70,8 @@ static int qstat_show(struct seq_file *m, void *v) ...@@ -70,9 +70,8 @@ static int qstat_show(struct seq_file *m, void *v)
seq_printf(m, "slsb buffer states:\n"); seq_printf(m, "slsb buffer states:\n");
seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n"); seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
qdio_siga_sync_q(q);
for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) { for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
get_buf_state(q, i, &state, 0); debug_get_buf_state(q, i, &state);
switch (state) { switch (state) {
case SLSB_P_INPUT_NOT_INIT: case SLSB_P_INPUT_NOT_INIT:
case SLSB_P_OUTPUT_NOT_INIT: case SLSB_P_OUTPUT_NOT_INIT:
......
...@@ -231,7 +231,7 @@ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr, ...@@ -231,7 +231,7 @@ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr,
return i; return i;
} }
inline int get_buf_state(struct qdio_q *q, unsigned int bufnr, static inline int get_buf_state(struct qdio_q *q, unsigned int bufnr,
unsigned char *state, int auto_ack) unsigned char *state, int auto_ack)
{ {
return get_buf_states(q, bufnr, state, 1, auto_ack); return get_buf_states(q, bufnr, state, 1, auto_ack);
...@@ -276,7 +276,7 @@ void qdio_init_buf_states(struct qdio_irq *irq_ptr) ...@@ -276,7 +276,7 @@ void qdio_init_buf_states(struct qdio_irq *irq_ptr)
QDIO_MAX_BUFFERS_PER_Q); QDIO_MAX_BUFFERS_PER_Q);
} }
static int qdio_siga_sync(struct qdio_q *q, unsigned int output, static inline int qdio_siga_sync(struct qdio_q *q, unsigned int output,
unsigned int input) unsigned int input)
{ {
int cc; int cc;
...@@ -293,7 +293,7 @@ static int qdio_siga_sync(struct qdio_q *q, unsigned int output, ...@@ -293,7 +293,7 @@ static int qdio_siga_sync(struct qdio_q *q, unsigned int output,
return cc; return cc;
} }
inline int qdio_siga_sync_q(struct qdio_q *q) static inline int qdio_siga_sync_q(struct qdio_q *q)
{ {
if (q->is_input_q) if (q->is_input_q)
return qdio_siga_sync(q, 0, q->mask); return qdio_siga_sync(q, 0, q->mask);
...@@ -358,8 +358,7 @@ static inline int qdio_siga_input(struct qdio_q *q) ...@@ -358,8 +358,7 @@ static inline int qdio_siga_input(struct qdio_q *q)
return cc; return cc;
} }
/* called from thinint inbound handler */ static inline void qdio_sync_after_thinint(struct qdio_q *q)
void qdio_sync_after_thinint(struct qdio_q *q)
{ {
if (pci_out_supported(q)) { if (pci_out_supported(q)) {
if (need_siga_sync_thinint(q)) if (need_siga_sync_thinint(q))
...@@ -370,7 +369,14 @@ void qdio_sync_after_thinint(struct qdio_q *q) ...@@ -370,7 +369,14 @@ void qdio_sync_after_thinint(struct qdio_q *q)
qdio_siga_sync_q(q); qdio_siga_sync_q(q);
} }
inline void qdio_stop_polling(struct qdio_q *q) int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
unsigned char *state)
{
qdio_siga_sync_q(q);
return get_buf_states(q, bufnr, state, 1, 0);
}
static inline void qdio_stop_polling(struct qdio_q *q)
{ {
if (!q->u.in.polling) if (!q->u.in.polling)
return; return;
...@@ -516,7 +522,7 @@ out: ...@@ -516,7 +522,7 @@ out:
return q->first_to_check; return q->first_to_check;
} }
int qdio_inbound_q_moved(struct qdio_q *q) static int qdio_inbound_q_moved(struct qdio_q *q)
{ {
int bufnr; int bufnr;
...@@ -570,7 +576,23 @@ static int qdio_inbound_q_done(struct qdio_q *q) ...@@ -570,7 +576,23 @@ static int qdio_inbound_q_done(struct qdio_q *q)
} }
} }
void qdio_kick_handler(struct qdio_q *q) 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 void qdio_kick_handler(struct qdio_q *q)
{ {
int start = q->first_to_kick; int start = q->first_to_kick;
int end = q->first_to_check; int end = q->first_to_check;
...@@ -619,7 +641,6 @@ again: ...@@ -619,7 +641,6 @@ again:
goto again; goto again;
} }
/* inbound tasklet */
void qdio_inbound_processing(unsigned long data) void qdio_inbound_processing(unsigned long data)
{ {
struct qdio_q *q = (struct qdio_q *)data; struct qdio_q *q = (struct qdio_q *)data;
...@@ -797,8 +818,7 @@ void qdio_outbound_timer(unsigned long data) ...@@ -797,8 +818,7 @@ void qdio_outbound_timer(unsigned long data)
tasklet_schedule(&q->tasklet); tasklet_schedule(&q->tasklet);
} }
/* called from thinint inbound tasklet */ static inline void qdio_check_outbound_after_thinint(struct qdio_q *q)
void qdio_check_outbound_after_thinint(struct qdio_q *q)
{ {
struct qdio_q *out; struct qdio_q *out;
int i; int i;
...@@ -811,6 +831,46 @@ void qdio_check_outbound_after_thinint(struct qdio_q *q) ...@@ -811,6 +831,46 @@ void qdio_check_outbound_after_thinint(struct qdio_q *q)
tasklet_schedule(&out->tasklet); tasklet_schedule(&out->tasklet);
} }
static void __tiqdio_inbound_processing(struct qdio_q *q)
{
qdio_perf_stat_inc(&perf_stats.thinint_inbound);
qdio_sync_after_thinint(q);
/*
* The interrupt could be caused by a PCI request. Check the
* PCI capable outbound queues.
*/
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);
}
qdio_stop_polling(q);
/*
* We need to check again to not lose initiative after
* resetting the ACK state.
*/
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);
}
static inline void qdio_set_state(struct qdio_irq *irq_ptr, static inline void qdio_set_state(struct qdio_irq *irq_ptr,
enum qdio_irq_states state) enum qdio_irq_states state)
{ {
......
...@@ -126,68 +126,11 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) ...@@ -126,68 +126,11 @@ 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) static inline int shared_ind(struct qdio_irq *irq_ptr)
{ {
return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind; return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
} }
static void __tiqdio_inbound_processing(struct qdio_q *q)
{
qdio_perf_stat_inc(&perf_stats.thinint_inbound);
qdio_sync_after_thinint(q);
/*
* Maybe we have work on our outbound queues... at least
* we have to check the PCI capable queues.
*/
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);
}
qdio_stop_polling(q);
/*
* We need to check again to not lose initiative after
* resetting the ACK state.
*/
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 */ /* check for work on all inbound thinint queues */
static void tiqdio_tasklet_fn(unsigned long data) static void tiqdio_tasklet_fn(unsigned long data)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment