aboutsummaryrefslogtreecommitdiff
path: root/drivers/s390
diff options
context:
space:
mode:
authorJulian Wiedmann2020-04-21 10:22:01 +0200
committerVasily Gorbik2020-05-20 10:22:50 +0200
commit9de6c08700ce9fab4589c1a44cec2a21812ab565 (patch)
tree4588e8ccb219ebf855f9544cb0e9f32b3f16dd24 /drivers/s390
parentfee36576656f662dcfa4788eaeb033a4c5dd870b (diff)
s390/qdio: simplify overlap calculation on Input refill
Refilling the Input Queue requires additional checks, as the refilled SBALs can overlap with the ACKs that qdio maintains on the queue. This code path is way too complex, and does a whole bunch of wrap-around checks that the modulo arithmetic in sub_buf() takes care of by itself. So shrink down all that code into a few lines of equivalent functionality. Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/cio/qdio_main.c50
1 files changed, 7 insertions, 43 deletions
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 4bd6dbfe8387..c3d696bb106b 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -1438,24 +1438,6 @@ out:
}
EXPORT_SYMBOL_GPL(qdio_activate);
-static inline int buf_in_between(int bufnr, int start, int count)
-{
- int end = add_buf(start, count);
-
- if (end > start) {
- if (bufnr >= start && bufnr < end)
- return 1;
- else
- return 0;
- }
-
- /* wrap-around case */
- if (bufnr >= start || bufnr < end)
- return 1;
- else
- return 0;
-}
-
/**
* handle_inbound - reset processed input buffers
* @q: queue containing the buffers
@@ -1466,36 +1448,18 @@ static inline int buf_in_between(int bufnr, int start, int count)
static int handle_inbound(struct qdio_q *q, unsigned int callflags,
int bufnr, int count)
{
- int diff;
+ int overlap;
qperf_inc(q, inbound_call);
- if (!q->u.in.ack_count)
- goto set;
-
- /* protect against stop polling setting an ACK for an emptied slsb */
- if (count == QDIO_MAX_BUFFERS_PER_Q) {
- /* overwriting everything, just delete polling status */
- q->u.in.ack_count = 0;
- goto set;
- } else if (buf_in_between(q->u.in.ack_start, bufnr, count)) {
- if (is_qebsm(q)) {
- /* partial overwrite, just update ack_start */
- diff = add_buf(bufnr, count);
- diff = sub_buf(diff, q->u.in.ack_start);
- q->u.in.ack_count -= diff;
- if (q->u.in.ack_count <= 0) {
- q->u.in.ack_count = 0;
- goto set;
- }
- q->u.in.ack_start = add_buf(q->u.in.ack_start, diff);
- } else {
- /* the only ACK will be deleted */
- q->u.in.ack_count = 0;
- }
+ /* If any ACKed SBALs are returned to HW, adjust ACK tracking: */
+ overlap = min(count - sub_buf(q->u.in.ack_start, bufnr),
+ q->u.in.ack_count);
+ if (overlap > 0) {
+ q->u.in.ack_start = add_buf(q->u.in.ack_start, overlap);
+ q->u.in.ack_count -= overlap;
}
-set:
count = set_buf_states(q, bufnr, SLSB_CU_INPUT_EMPTY, count);
atomic_add(count, &q->nr_buf_used);