Commit 1ecbcfd5 authored by Julian Wiedmann's avatar Julian Wiedmann Committed by Vasily Gorbik

s390/qdio: remove Input tasklet code

Both qeth and zfcp have fully moved to the polling-driven flow for
Input Queues with commit 0a6e6345 ("s390/qdio: extend polling
support to multiple queues") and commit 0b524abc ("scsi: zfcp: Lift
Input Queue tasklet from qdio").

So remove the tasklet code for Input Queues, streamline the IRQ handlers
and push the tasklet struct into struct qdio_output_q.
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Reviewed-by: default avatarBenjamin Block <bblock@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 1daafea4
...@@ -336,7 +336,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int, ...@@ -336,7 +336,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
* @no_output_qs: number of output queues * @no_output_qs: number of output queues
* @input_handler: handler to be called for input queues * @input_handler: handler to be called for input queues
* @output_handler: handler to be called for output queues * @output_handler: handler to be called for output queues
* @irq_poll: Data IRQ polling handler (NULL when not supported) * @irq_poll: Data IRQ polling handler
* @scan_threshold: # of in-use buffers that triggers scan on output queue * @scan_threshold: # of in-use buffers that triggers scan on output queue
* @int_parm: interruption parameter * @int_parm: interruption parameter
* @input_sbal_addr_array: per-queue array, each element points to 128 SBALs * @input_sbal_addr_array: per-queue array, each element points to 128 SBALs
......
...@@ -139,9 +139,6 @@ struct qdio_dev_perf_stat { ...@@ -139,9 +139,6 @@ struct qdio_dev_perf_stat {
unsigned int qdio_int; unsigned int qdio_int;
unsigned int pci_request_int; unsigned int pci_request_int;
unsigned int tasklet_inbound;
unsigned int tasklet_inbound_resched;
unsigned int tasklet_inbound_resched2;
unsigned int tasklet_outbound; unsigned int tasklet_outbound;
unsigned int siga_read; unsigned int siga_read;
...@@ -193,6 +190,8 @@ struct qdio_output_q { ...@@ -193,6 +190,8 @@ struct qdio_output_q {
struct qdio_outbuf_state *sbal_state; struct qdio_outbuf_state *sbal_state;
/* timer to check for more outbound work */ /* timer to check for more outbound work */
struct timer_list timer; struct timer_list timer;
/* tasklet to check for completions */
struct tasklet_struct tasklet;
}; };
/* /*
...@@ -222,7 +221,6 @@ struct qdio_q { ...@@ -222,7 +221,6 @@ struct qdio_q {
/* last scan of the queue */ /* last scan of the queue */
u64 timestamp; u64 timestamp;
struct tasklet_struct tasklet;
struct qdio_queue_perf_stat q_stats; struct qdio_queue_perf_stat q_stats;
struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q] ____cacheline_aligned; struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q] ____cacheline_aligned;
...@@ -324,6 +322,14 @@ static inline int multicast_outbound(struct qdio_q *q) ...@@ -324,6 +322,14 @@ static inline int multicast_outbound(struct qdio_q *q)
(q->nr == q->irq_ptr->nr_output_qs - 1); (q->nr == q->irq_ptr->nr_output_qs - 1);
} }
static inline void qdio_deliver_irq(struct qdio_irq *irq)
{
if (!test_and_set_bit(QDIO_IRQ_DISABLED, &irq->poll_state))
irq->irq_poll(irq->cdev, irq->int_parm);
else
QDIO_PERF_STAT_INC(irq, int_discarded);
}
#define pci_out_supported(irq) ((irq)->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) #define pci_out_supported(irq) ((irq)->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED)
#define is_qebsm(q) (q->irq_ptr->sch_token != 0) #define is_qebsm(q) (q->irq_ptr->sch_token != 0)
...@@ -359,13 +365,11 @@ int qdio_establish_thinint(struct qdio_irq *irq_ptr); ...@@ -359,13 +365,11 @@ 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);
void tiqdio_add_device(struct qdio_irq *irq_ptr); void tiqdio_add_device(struct qdio_irq *irq_ptr);
void tiqdio_remove_device(struct qdio_irq *irq_ptr); void tiqdio_remove_device(struct qdio_irq *irq_ptr);
void tiqdio_inbound_processing(unsigned long q);
int qdio_thinint_init(void); int qdio_thinint_init(void);
void qdio_thinint_exit(void); void qdio_thinint_exit(void);
int test_nonshared_ind(struct qdio_irq *); int test_nonshared_ind(struct qdio_irq *);
/* prototypes for setup */ /* prototypes for setup */
void qdio_inbound_processing(unsigned long data);
void qdio_outbound_processing(unsigned long data); void qdio_outbound_processing(unsigned long data);
void qdio_outbound_timer(struct timer_list *t); void qdio_outbound_timer(struct timer_list *t);
void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
......
...@@ -197,9 +197,6 @@ static char *qperf_names[] = { ...@@ -197,9 +197,6 @@ static char *qperf_names[] = {
"Assumed adapter interrupts", "Assumed adapter interrupts",
"QDIO interrupts", "QDIO interrupts",
"Requested PCIs", "Requested PCIs",
"Inbound tasklet runs",
"Inbound tasklet resched",
"Inbound tasklet resched2",
"Outbound tasklet runs", "Outbound tasklet runs",
"SIGA read", "SIGA read",
"SIGA write", "SIGA write",
......
...@@ -575,51 +575,12 @@ static void qdio_kick_handler(struct qdio_q *q, unsigned int start, ...@@ -575,51 +575,12 @@ static void qdio_kick_handler(struct qdio_q *q, unsigned int start,
static inline int qdio_tasklet_schedule(struct qdio_q *q) static inline int qdio_tasklet_schedule(struct qdio_q *q)
{ {
if (likely(q->irq_ptr->state == QDIO_IRQ_STATE_ACTIVE)) { if (likely(q->irq_ptr->state == QDIO_IRQ_STATE_ACTIVE)) {
tasklet_schedule(&q->tasklet); tasklet_schedule(&q->u.out.tasklet);
return 0; return 0;
} }
return -EPERM; return -EPERM;
} }
static void __qdio_inbound_processing(struct qdio_q *q)
{
unsigned int start = q->first_to_check;
int count;
qperf_inc(q, tasklet_inbound);
count = qdio_inbound_q_moved(q, start);
if (count == 0)
return;
qdio_kick_handler(q, start, count);
start = add_buf(start, count);
q->first_to_check = start;
if (!qdio_inbound_q_done(q, start)) {
/* means poll time is not yet over */
qperf_inc(q, tasklet_inbound_resched);
if (!qdio_tasklet_schedule(q))
return;
}
qdio_stop_polling(q);
/*
* We need to check again to not lose initiative after
* resetting the ACK state.
*/
if (!qdio_inbound_q_done(q, start)) {
qperf_inc(q, tasklet_inbound_resched2);
qdio_tasklet_schedule(q);
}
}
void qdio_inbound_processing(unsigned long data)
{
struct qdio_q *q = (struct qdio_q *)data;
__qdio_inbound_processing(q);
}
static void qdio_check_pending(struct qdio_q *q, unsigned int index) static void qdio_check_pending(struct qdio_q *q, unsigned int index)
{ {
unsigned char state; unsigned char state;
...@@ -825,19 +786,6 @@ static inline void qdio_check_outbound_pci_queues(struct qdio_irq *irq) ...@@ -825,19 +786,6 @@ static inline void qdio_check_outbound_pci_queues(struct qdio_irq *irq)
qdio_tasklet_schedule(out); qdio_tasklet_schedule(out);
} }
void tiqdio_inbound_processing(unsigned long data)
{
struct qdio_q *q = (struct qdio_q *)data;
if (need_siga_sync(q) && need_siga_sync_after_ai(q))
qdio_sync_queues(q);
/* The interrupt could be caused by a PCI request: */
qdio_check_outbound_pci_queues(q->irq_ptr);
__qdio_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)
{ {
...@@ -865,15 +813,7 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr) ...@@ -865,15 +813,7 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
if (unlikely(irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)) if (unlikely(irq_ptr->state != QDIO_IRQ_STATE_ACTIVE))
return; return;
if (irq_ptr->irq_poll) { qdio_deliver_irq(irq_ptr);
if (!test_and_set_bit(QDIO_IRQ_DISABLED, &irq_ptr->poll_state))
irq_ptr->irq_poll(irq_ptr->cdev, irq_ptr->int_parm);
else
QDIO_PERF_STAT_INC(irq_ptr, int_discarded);
} else {
for_each_input_queue(irq_ptr, q, i)
tasklet_schedule(&q->tasklet);
}
if (!pci_out_supported(irq_ptr) || !irq_ptr->scan_threshold) if (!pci_out_supported(irq_ptr) || !irq_ptr->scan_threshold)
return; return;
...@@ -1016,12 +956,9 @@ static void qdio_shutdown_queues(struct qdio_irq *irq_ptr) ...@@ -1016,12 +956,9 @@ static void qdio_shutdown_queues(struct qdio_irq *irq_ptr)
struct qdio_q *q; struct qdio_q *q;
int i; int i;
for_each_input_queue(irq_ptr, q, i)
tasklet_kill(&q->tasklet);
for_each_output_queue(irq_ptr, q, i) { for_each_output_queue(irq_ptr, q, i) {
del_timer_sync(&q->u.out.timer); del_timer_sync(&q->u.out.timer);
tasklet_kill(&q->tasklet); tasklet_kill(&q->u.out.tasklet);
} }
} }
...@@ -1263,6 +1200,9 @@ int qdio_establish(struct ccw_device *cdev, ...@@ -1263,6 +1200,9 @@ int qdio_establish(struct ccw_device *cdev,
!init_data->output_sbal_addr_array) !init_data->output_sbal_addr_array)
return -EINVAL; return -EINVAL;
if (!init_data->irq_poll)
return -EINVAL;
mutex_lock(&irq_ptr->setup_mutex); mutex_lock(&irq_ptr->setup_mutex);
qdio_trace_init_data(irq_ptr, init_data); qdio_trace_init_data(irq_ptr, init_data);
qdio_setup_irq(irq_ptr, init_data); qdio_setup_irq(irq_ptr, init_data);
......
...@@ -259,14 +259,6 @@ static void setup_queues(struct qdio_irq *irq_ptr, ...@@ -259,14 +259,6 @@ static void setup_queues(struct qdio_irq *irq_ptr,
setup_storage_lists(q, irq_ptr, setup_storage_lists(q, irq_ptr,
qdio_init->input_sbal_addr_array[i], i); qdio_init->input_sbal_addr_array[i], i);
if (is_thinint_irq(irq_ptr)) {
tasklet_init(&q->tasklet, tiqdio_inbound_processing,
(unsigned long) q);
} else {
tasklet_init(&q->tasklet, qdio_inbound_processing,
(unsigned long) q);
}
} }
for_each_output_queue(irq_ptr, q, i) { for_each_output_queue(irq_ptr, q, i) {
...@@ -280,7 +272,7 @@ static void setup_queues(struct qdio_irq *irq_ptr, ...@@ -280,7 +272,7 @@ static void setup_queues(struct qdio_irq *irq_ptr,
setup_storage_lists(q, irq_ptr, setup_storage_lists(q, irq_ptr,
qdio_init->output_sbal_addr_array[i], i); qdio_init->output_sbal_addr_array[i], i);
tasklet_init(&q->tasklet, qdio_outbound_processing, tasklet_init(&q->u.out.tasklet, qdio_outbound_processing,
(unsigned long) q); (unsigned long) q);
timer_setup(&q->u.out.timer, qdio_outbound_timer, 0); timer_setup(&q->u.out.timer, qdio_outbound_timer, 0);
} }
...@@ -483,12 +475,8 @@ int qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data) ...@@ -483,12 +475,8 @@ int qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data)
ccw_device_get_schid(cdev, &irq_ptr->schid); ccw_device_get_schid(cdev, &irq_ptr->schid);
setup_queues(irq_ptr, init_data); setup_queues(irq_ptr, init_data);
if (init_data->irq_poll) { irq_ptr->irq_poll = init_data->irq_poll;
irq_ptr->irq_poll = init_data->irq_poll; set_bit(QDIO_IRQ_DISABLED, &irq_ptr->poll_state);
set_bit(QDIO_IRQ_DISABLED, &irq_ptr->poll_state);
} else {
irq_ptr->irq_poll = NULL;
}
setup_qib(irq_ptr, init_data); setup_qib(irq_ptr, init_data);
set_impl_params(irq_ptr, init_data->qib_param_field_format, set_impl_params(irq_ptr, init_data->qib_param_field_format,
......
...@@ -106,32 +106,6 @@ static inline u32 clear_shared_ind(void) ...@@ -106,32 +106,6 @@ static inline u32 clear_shared_ind(void)
return xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0); return xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
} }
static inline void tiqdio_call_inq_handlers(struct qdio_irq *irq)
{
struct qdio_q *q;
int i;
if (!references_shared_dsci(irq))
xchg(irq->dsci, 0);
if (irq->irq_poll) {
if (!test_and_set_bit(QDIO_IRQ_DISABLED, &irq->poll_state))
irq->irq_poll(irq->cdev, irq->int_parm);
else
QDIO_PERF_STAT_INC(irq, int_discarded);
return;
}
for_each_input_queue(irq, q, i) {
/*
* Call inbound processing but not directly
* since that could starve other thinint queues.
*/
tasklet_schedule(&q->tasklet);
}
}
/** /**
* tiqdio_thinint_handler - thin interrupt handler for qdio * tiqdio_thinint_handler - thin interrupt handler for qdio
* @airq: pointer to adapter interrupt descriptor * @airq: pointer to adapter interrupt descriptor
...@@ -153,10 +127,14 @@ static void tiqdio_thinint_handler(struct airq_struct *airq, bool floating) ...@@ -153,10 +127,14 @@ static void tiqdio_thinint_handler(struct airq_struct *airq, bool floating)
if (unlikely(references_shared_dsci(irq))) { if (unlikely(references_shared_dsci(irq))) {
if (!si_used) if (!si_used)
continue; continue;
} else if (!*irq->dsci) } else {
continue; if (!*irq->dsci)
continue;
xchg(irq->dsci, 0);
}
tiqdio_call_inq_handlers(irq); qdio_deliver_irq(irq);
QDIO_PERF_STAT_INC(irq, adapter_int); QDIO_PERF_STAT_INC(irq, adapter_int);
} }
......
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