diff options
| author | Julian Wiedmann <jwi@linux.ibm.com> | 2019-08-23 11:48:48 +0200 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2019-08-24 16:39:18 -0700 | 
| commit | 313dc689b16c08b081939ee9b87dac3736c780e3 (patch) | |
| tree | 473f175b8e96dd7f404e10872d2353ce4e895838 /drivers/s390 | |
| parent | 7c47f5afdeef763599f1ae22d29b8c3904c58315 (diff) | |
| download | linux-313dc689b16c08b081939ee9b87dac3736c780e3.tar.bz2 | |
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: Julian Wiedmann <jwi@linux.ibm.com>
Acked-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/s390')
| -rw-r--r-- | drivers/s390/cio/qdio.h | 3 | ||||
| -rw-r--r-- | drivers/s390/cio/qdio_main.c | 11 | ||||
| -rw-r--r-- | drivers/s390/cio/qdio_setup.c | 2 | 
3 files changed, 10 insertions, 6 deletions
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index a06944399865..a58b45df95d7 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -206,8 +206,6 @@ struct qdio_output_q {  	struct qdio_outbuf_state *sbal_state;  	/* timer to check for more outbound work */  	struct timer_list timer; -	/* used SBALs before tasklet schedule */ -	int scan_threshold;  };  /* @@ -295,6 +293,7 @@ struct qdio_irq {  	struct qdio_ssqd_desc ssqd_desc;  	void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *); +	unsigned int scan_threshold;	/* used SBALs before tasklet schedule */  	int perf_stat_enabled;  	struct qdr *qdr; diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 5efba0d29190..5b63c505a2f7 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -880,7 +880,7 @@ static inline void qdio_check_outbound_pci_queues(struct qdio_irq *irq)  	struct qdio_q *out;  	int i; -	if (!pci_out_supported(irq)) +	if (!pci_out_supported(irq) || !irq->scan_threshold)  		return;  	for_each_output_queue(irq, out, i) @@ -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;  	for_each_output_queue(irq_ptr, q, i) { @@ -1528,6 +1528,7 @@ set:  static int handle_outbound(struct qdio_q *q, unsigned int callflags,  			   int bufnr, int count)  { +	const unsigned int scan_threshold = q->irq_ptr->scan_threshold;  	unsigned char state = 0;  	int used, rc = 0; @@ -1566,8 +1567,12 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,  		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 */ -	if (used >= q->u.out.scan_threshold || rc) +	if (used >= scan_threshold || rc)  		qdio_tasklet_schedule(q);  	else  		/* free the SBALs in case of no further traffic */ diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index d4101cecdc8d..f4ca1d29d61b 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -248,7 +248,6 @@ static void setup_queues(struct qdio_irq *irq_ptr,  		output_sbal_state_array += QDIO_MAX_BUFFERS_PER_Q;  		q->is_input_q = 0; -		q->u.out.scan_threshold = qdio_init->scan_threshold;  		setup_storage_lists(q, irq_ptr, output_sbal_array, i);  		output_sbal_array += QDIO_MAX_BUFFERS_PER_Q; @@ -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_output_qs = init_data->no_output_qs;  	irq_ptr->cdev = init_data->cdev; +	irq_ptr->scan_threshold = init_data->scan_threshold;  	ccw_device_get_schid(irq_ptr->cdev, &irq_ptr->schid);  	setup_queues(irq_ptr, init_data);  |