Commit 313dc689 authored by Julian Wiedmann's avatar Julian Wiedmann Committed by David S. Miller

s390/qdio: let drivers opt-out from Output Queue scanning

If a driver wants to use the new Output Queue poll code, then the qdio
layer must disable its internal Queue scanning. Let the driver select
this mode by passing a special scan_threshold of 0.

As the scan_threshold is the same for all Output Queues, also move it
into the main qdio_irq struct. This allows for fast opt-out checking, a
driver is expected to operate either _all_ or none of its Output Queues
in polling mode.
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Acked-by: default avatarVasily Gorbik <gor@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7c47f5af
...@@ -359,7 +359,7 @@ struct qdio_initialize { ...@@ -359,7 +359,7 @@ struct qdio_initialize {
qdio_handler_t *output_handler; qdio_handler_t *output_handler;
void (**queue_start_poll_array) (struct ccw_device *, int, void (**queue_start_poll_array) (struct ccw_device *, int,
unsigned long); unsigned long);
int scan_threshold; unsigned int scan_threshold;
unsigned long int_parm; unsigned long int_parm;
struct qdio_buffer **input_sbal_addr_array; struct qdio_buffer **input_sbal_addr_array;
struct qdio_buffer **output_sbal_addr_array; struct qdio_buffer **output_sbal_addr_array;
......
...@@ -206,8 +206,6 @@ struct qdio_output_q { ...@@ -206,8 +206,6 @@ 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;
/* used SBALs before tasklet schedule */
int scan_threshold;
}; };
/* /*
...@@ -295,6 +293,7 @@ struct qdio_irq { ...@@ -295,6 +293,7 @@ struct qdio_irq {
struct qdio_ssqd_desc ssqd_desc; struct qdio_ssqd_desc ssqd_desc;
void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *); void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *);
unsigned int scan_threshold; /* used SBALs before tasklet schedule */
int perf_stat_enabled; int perf_stat_enabled;
struct qdr *qdr; struct qdr *qdr;
......
...@@ -880,7 +880,7 @@ static inline void qdio_check_outbound_pci_queues(struct qdio_irq *irq) ...@@ -880,7 +880,7 @@ static inline void qdio_check_outbound_pci_queues(struct qdio_irq *irq)
struct qdio_q *out; struct qdio_q *out;
int i; int i;
if (!pci_out_supported(irq)) if (!pci_out_supported(irq) || !irq->scan_threshold)
return; return;
for_each_output_queue(irq, out, i) for_each_output_queue(irq, out, i)
...@@ -973,7 +973,7 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr) ...@@ -973,7 +973,7 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
} }
} }
if (!pci_out_supported(irq_ptr)) if (!pci_out_supported(irq_ptr) || !irq_ptr->scan_threshold)
return; return;
for_each_output_queue(irq_ptr, q, i) { for_each_output_queue(irq_ptr, q, i) {
...@@ -1528,6 +1528,7 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags, ...@@ -1528,6 +1528,7 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags,
static int handle_outbound(struct qdio_q *q, unsigned int callflags, static int handle_outbound(struct qdio_q *q, unsigned int callflags,
int bufnr, int count) int bufnr, int count)
{ {
const unsigned int scan_threshold = q->irq_ptr->scan_threshold;
unsigned char state = 0; unsigned char state = 0;
int used, rc = 0; int used, rc = 0;
...@@ -1566,8 +1567,12 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags, ...@@ -1566,8 +1567,12 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
rc = qdio_kick_outbound_q(q, 0); rc = qdio_kick_outbound_q(q, 0);
} }
/* Let drivers implement their own completion scanning: */
if (!scan_threshold)
return rc;
/* in case of SIGA errors we must process the error immediately */ /* in case of SIGA errors we must process the error immediately */
if (used >= q->u.out.scan_threshold || rc) if (used >= scan_threshold || rc)
qdio_tasklet_schedule(q); qdio_tasklet_schedule(q);
else else
/* free the SBALs in case of no further traffic */ /* free the SBALs in case of no further traffic */
......
...@@ -248,7 +248,6 @@ static void setup_queues(struct qdio_irq *irq_ptr, ...@@ -248,7 +248,6 @@ static void setup_queues(struct qdio_irq *irq_ptr,
output_sbal_state_array += QDIO_MAX_BUFFERS_PER_Q; output_sbal_state_array += QDIO_MAX_BUFFERS_PER_Q;
q->is_input_q = 0; q->is_input_q = 0;
q->u.out.scan_threshold = qdio_init->scan_threshold;
setup_storage_lists(q, irq_ptr, output_sbal_array, i); setup_storage_lists(q, irq_ptr, output_sbal_array, i);
output_sbal_array += QDIO_MAX_BUFFERS_PER_Q; output_sbal_array += QDIO_MAX_BUFFERS_PER_Q;
...@@ -474,6 +473,7 @@ int qdio_setup_irq(struct qdio_initialize *init_data) ...@@ -474,6 +473,7 @@ int qdio_setup_irq(struct qdio_initialize *init_data)
irq_ptr->nr_input_qs = init_data->no_input_qs; irq_ptr->nr_input_qs = init_data->no_input_qs;
irq_ptr->nr_output_qs = init_data->no_output_qs; irq_ptr->nr_output_qs = init_data->no_output_qs;
irq_ptr->cdev = init_data->cdev; irq_ptr->cdev = init_data->cdev;
irq_ptr->scan_threshold = init_data->scan_threshold;
ccw_device_get_schid(irq_ptr->cdev, &irq_ptr->schid); ccw_device_get_schid(irq_ptr->cdev, &irq_ptr->schid);
setup_queues(irq_ptr, init_data); setup_queues(irq_ptr, init_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