summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Wiedmann <jwi@linux.ibm.com>2021-07-23 10:02:17 +0200
committerVasily Gorbik <gor@linux.ibm.com>2021-08-18 10:01:28 +0200
commit87e225bfa0015aee2812246de56a09126a743192 (patch)
treea3bd3f35c39b69b590444c3c8044a6d5403c7b83
parent10376b53502ef14661274c40a78cb860b54455fa (diff)
s390/qdio: fine-tune the queue sync
Push the sync check from qdio_inspect_queue() down into the two get_*_buffer_frontier() code paths, where we actually need the sync to look at the current queue state. This lets us avoid the check when we know that there is no work on the queue (ie. when q->nr_buf_used is 0). While at it introduce the qdio_sync_*_queue() helpers, so that we can avoid the branch on q->is_input_q when we already know the queue type. 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>
-rw-r--r--drivers/s390/cio/qdio_main.c31
1 files changed, 20 insertions, 11 deletions
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 86ee3a490e8a..aef0575c14e8 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -303,12 +303,22 @@ static inline int qdio_siga_sync(struct qdio_q *q, unsigned int output,
return (cc) ? -EIO : 0;
}
+static inline int qdio_sync_input_queue(struct qdio_q *q)
+{
+ return qdio_siga_sync(q, 0, q->mask);
+}
+
+static inline int qdio_sync_output_queue(struct qdio_q *q)
+{
+ return qdio_siga_sync(q, q->mask, 0);
+}
+
static inline int qdio_siga_sync_q(struct qdio_q *q)
{
if (q->is_input_q)
- return qdio_siga_sync(q, 0, q->mask);
+ return qdio_sync_input_queue(q);
else
- return qdio_siga_sync(q, q->mask, 0);
+ return qdio_sync_output_queue(q);
}
static int qdio_siga_output(struct qdio_q *q, unsigned int count,
@@ -442,10 +452,9 @@ static int get_inbound_buffer_frontier(struct qdio_q *q, unsigned int start,
if (!count)
return 0;
- /*
- * No siga sync here, as a PCI or we after a thin interrupt
- * already sync'ed the queues.
- */
+ if (qdio_need_siga_sync(q->irq_ptr))
+ qdio_sync_input_queue(q);
+
count = get_buf_states(q, start, &state, count, 1);
if (!count)
return 0;
@@ -498,7 +507,7 @@ static inline int qdio_inbound_q_done(struct qdio_q *q, unsigned int start)
return 1;
if (qdio_need_siga_sync(q->irq_ptr))
- qdio_siga_sync_q(q);
+ qdio_sync_input_queue(q);
get_buf_state(q, start, &state, 0);
if (state == SLSB_P_INPUT_PRIMED || state == SLSB_P_INPUT_ERROR)
@@ -520,6 +529,9 @@ static int get_outbound_buffer_frontier(struct qdio_q *q, unsigned int start,
if (!count)
return 0;
+ if (qdio_need_siga_sync(q->irq_ptr))
+ qdio_sync_output_queue(q);
+
count = get_buf_states(q, start, &state, count, 0);
if (!count)
return 0;
@@ -1160,7 +1172,7 @@ static int handle_outbound(struct qdio_q *q, unsigned int bufnr, unsigned int co
WARN_ON_ONCE(!IS_ALIGNED(phys_aob, 256));
rc = qdio_kick_outbound_q(q, count, phys_aob);
} else if (qdio_need_siga_sync(q->irq_ptr)) {
- rc = qdio_siga_sync_q(q);
+ rc = qdio_sync_output_queue(q);
} else if (count < QDIO_MAX_BUFFERS_PER_Q &&
get_buf_state(q, prev_buf(bufnr), &state, 0) > 0 &&
state == SLSB_CU_OUTPUT_PRIMED) {
@@ -1283,9 +1295,6 @@ int qdio_inspect_queue(struct ccw_device *cdev, unsigned int nr, bool is_input,
return -ENODEV;
q = is_input ? irq_ptr->input_qs[nr] : irq_ptr->output_qs[nr];
- if (qdio_need_siga_sync(irq_ptr))
- qdio_siga_sync_q(q);
-
return __qdio_inspect_queue(q, bufnr, error);
}
EXPORT_SYMBOL_GPL(qdio_inspect_queue);