Blob Blame History Raw
From: Julian Wiedmann <jwi@linux.ibm.com>
Date: Fri, 20 Mar 2020 14:00:00 +0100
Subject: s390/qdio: clear DSCI early for polling drivers
Git-commit: 9c159bbc14ba196d590dc1a2fe7931ccfe73db98
Patch-mainline: v5.7-rc1
References: jsc#SLE-13690

Polling drivers in a configuration with 1 Input Queue currently keep
their DSCI armed all the way through the poll cycle, until
qdio_start_irq() clears it.

_Any_ intermittent QDIO interrupt delivered to tiqdio_thinint_handler()
will thus cause
1) the 'adapter_int' statistic to be incremented,
2) a call to tiqdio_call_inq_handlers() for this device, and then
3) the 'int_discarded' statistics to be incremented.

This causes overhead & complexity in the IRQ path, along with ambiguity
in the statistics.
On the other hand the device should be in IRQ avoidance mode during a
poll cycle, so there won't be a lot of DSCI ping-pong that this
micro-optimization could prevent.

So align the DSCI handling with what we already do for devices with
multiple Input Queues: clear it right away while processing the IRQ.

For the non-polling path this means that we no longer need to handle
the 1-queue case separately.

Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/s390/cio/qdio.h         |  1 -
 drivers/s390/cio/qdio_main.c    |  2 --
 drivers/s390/cio/qdio_thinint.c | 25 ++-----------------------
 3 files changed, 2 insertions(+), 26 deletions(-)

diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index b0beafc43d37..b8453b594679 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -374,7 +374,6 @@ int tiqdio_allocate_memory(void);
 void tiqdio_free_memory(void);
 int tiqdio_register_thinints(void);
 void tiqdio_unregister_thinints(void);
-void clear_nonshared_ind(struct qdio_irq *);
 int test_nonshared_ind(struct qdio_irq *);
 
 /* prototypes for setup */
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 9d6e51bcd072..bcc3ab14e72d 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -1643,8 +1643,6 @@ int qdio_start_irq(struct ccw_device *cdev)
 	if (!irq_ptr)
 		return -ENODEV;
 
-	clear_nonshared_ind(irq_ptr);
-
 	for_each_input_queue(irq_ptr, q, i)
 		qdio_stop_polling(q);
 
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index c78c8dd18a89..ae50373617cd 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -82,32 +82,16 @@ void tiqdio_remove_device(struct qdio_irq *irq_ptr)
 	INIT_LIST_HEAD(&irq_ptr->entry);
 }
 
-static inline int has_multiple_inq_on_dsci(struct qdio_irq *irq_ptr)
-{
-	return irq_ptr->nr_input_qs > 1;
-}
-
 static inline int references_shared_dsci(struct qdio_irq *irq_ptr)
 {
 	return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
 }
 
-void clear_nonshared_ind(struct qdio_irq *irq_ptr)
-{
-	if (!is_thinint_irq(irq_ptr))
-		return;
-	if (references_shared_dsci(irq_ptr) ||
-	    has_multiple_inq_on_dsci(irq_ptr))
-		return;
-	xchg(irq_ptr->dsci, 0);
-}
-
 int test_nonshared_ind(struct qdio_irq *irq_ptr)
 {
 	if (!is_thinint_irq(irq_ptr))
 		return 0;
-	if (references_shared_dsci(irq_ptr) ||
-	    has_multiple_inq_on_dsci(irq_ptr))
+	if (references_shared_dsci(irq_ptr))
 		return 0;
 	if (*irq_ptr->dsci)
 		return 1;
@@ -127,8 +111,7 @@ static inline void tiqdio_call_inq_handlers(struct qdio_irq *irq)
 	struct qdio_q *q;
 	int i;
 
-	if (!references_shared_dsci(irq) &&
-	    has_multiple_inq_on_dsci(irq))
+	if (!references_shared_dsci(irq))
 		xchg(irq->dsci, 0);
 
 	if (irq->irq_poll) {
@@ -140,10 +123,6 @@ static inline void tiqdio_call_inq_handlers(struct qdio_irq *irq)
 		return;
 	}
 
-	if (!references_shared_dsci(irq) &&
-	    !has_multiple_inq_on_dsci(irq))
-		xchg(irq->dsci, 0);
-
 	for_each_input_queue(irq, q, i) {
 		/*
 		 * Call inbound processing but not directly