s390/qdio: let drivers opt-out from Output Queue scanning
authorJulian Wiedmann <jwi@linux.ibm.com>
Fri, 23 Aug 2019 09:48:48 +0000 (11:48 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sat, 24 Aug 2019 23:39:18 +0000 (16:39 -0700)
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>
arch/s390/include/asm/qdio.h
drivers/s390/cio/qdio.h
drivers/s390/cio/qdio_main.c
drivers/s390/cio/qdio_setup.c

index 79b4a3e9dc5d5d52139380dbde00a6cdc6e52ef1..556d3e703faea82848d230376b80a39e62ec1b19 100644 (file)
@@ -359,7 +359,7 @@ struct qdio_initialize {
        qdio_handler_t *output_handler;
        void (**queue_start_poll_array) (struct ccw_device *, int,
                                          unsigned long);
-       int scan_threshold;
+       unsigned int scan_threshold;
        unsigned long int_parm;
        struct qdio_buffer **input_sbal_addr_array;
        struct qdio_buffer **output_sbal_addr_array;
index a069443998652c6790d3b26526108e5cdf226d27..a58b45df95d7ed85516d52527bda359dac586dfe 100644 (file)
@@ -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;
index 5efba0d29190e0f31ca43821a93d95c1589ffcb3..5b63c505a2f7cf906e65fb148a56e6e54e038c02 100644 (file)
@@ -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 */
index d4101cecdc8db3db7bd33bca0818069e66183346..f4ca1d29d61bad716fc655da27f7703fb6cdc0c7 100644 (file)
@@ -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);