From 2223318c2862edc7f5b282939b850b19fc934ec4 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Sat, 30 Jan 2021 13:22:56 +0100 Subject: s390/qdio: remove 'merge_pending' mechanism For non-QEBSM devices, get_buf_states() merges PENDING and EMPTY buffers into a single group of finished buffers. To allow the upper-layer driver to differentiate between the two states, qdio_check_pending() looks at each buffer's state again and sets the sbal_state flag to QDIO_OUTBUF_STATE_FLAG_PENDING accordingly. So effectively we're spending overhead on _every_ Output Queue inspection, just to avoid some additional TX completion calls in case a group of buffers has completed with mixed EMPTY / PENDING state. Given that PENDING buffers should rarely occur, this is a bad trade-off. In particular so as the additional checks in get_buf_states() affect _all_ device types (even those that don't use the PENDING state). Rip it all out, and just report the PENDING completions separately as we already do for QEBSM devices. Signed-off-by: Julian Wiedmann Reviewed-by: Benjamin Block Signed-off-by: Vasily Gorbik --- drivers/s390/cio/qdio_main.c | 59 ++++++--------------------------------- drivers/s390/net/qeth_core_main.c | 4 +-- 2 files changed, 10 insertions(+), 53 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 0ad5a4c1bb08..03a011619908 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -202,7 +202,7 @@ again: */ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr, unsigned char *state, unsigned int count, - int auto_ack, int merge_pending) + int auto_ack) { unsigned char __state = 0; int i = 1; @@ -217,18 +217,9 @@ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr, if (__state & SLSB_OWNER_CU) goto out; - if (merge_pending && __state == SLSB_P_OUTPUT_PENDING) - __state = SLSB_P_OUTPUT_EMPTY; - for (; i < count; i++) { bufnr = next_buf(bufnr); - /* merge PENDING into EMPTY: */ - if (merge_pending && - q->slsb.val[bufnr] == SLSB_P_OUTPUT_PENDING && - __state == SLSB_P_OUTPUT_EMPTY) - continue; - /* stop if next state differs from initial state: */ if (q->slsb.val[bufnr] != __state) break; @@ -242,7 +233,7 @@ out: static inline int get_buf_state(struct qdio_q *q, unsigned int bufnr, unsigned char *state, int auto_ack) { - return get_buf_states(q, bufnr, state, 1, auto_ack, 0); + return get_buf_states(q, bufnr, state, 1, auto_ack); } /* wrap-around safe setting of slsb states, returns number of changed buffers */ @@ -464,7 +455,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q, unsigned int start, * No siga sync here, as a PCI or we after a thin interrupt * already sync'ed the queues. */ - count = get_buf_states(q, start, &state, count, 1, 0); + count = get_buf_states(q, start, &state, count, 1); if (!count) return 0; @@ -541,7 +532,6 @@ static inline unsigned long qdio_aob_for_buffer(struct qdio_output_q *q, WARN_ON_ONCE(phys_aob & 0xFF); } - q->sbal_state[bufnr].flags = 0; return phys_aob; } @@ -554,19 +544,6 @@ static inline int qdio_tasklet_schedule(struct qdio_q *q) return -EPERM; } -static void qdio_check_pending(struct qdio_q *q, unsigned int index) -{ - unsigned char state; - - if (get_buf_state(q, index, &state, 0) > 0 && - state == SLSB_P_OUTPUT_PENDING && - q->u.out.aobs[index]) { - q->u.out.sbal_state[index].flags |= - QDIO_OUTBUF_STATE_FLAG_PENDING; - q->u.out.aobs[index] = NULL; - } -} - static int get_outbound_buffer_frontier(struct qdio_q *q, unsigned int start, unsigned int *error) { @@ -587,7 +564,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q, unsigned int start, if (!count) return 0; - count = get_buf_states(q, start, &state, count, 0, q->u.out.use_cq); + count = get_buf_states(q, start, &state, count, 0); if (!count) return 0; @@ -609,6 +586,9 @@ static int get_outbound_buffer_frontier(struct qdio_q *q, unsigned int start, account_sbals(q, count); return count; case SLSB_P_OUTPUT_ERROR: + DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out error:%1d %02x", + q->nr, count); + *error = QDIO_ERROR_SLSB_STATE; process_buffer_error(q, start, count); atomic_sub(count, &q->nr_buf_used); @@ -640,27 +620,6 @@ static inline int qdio_outbound_q_done(struct qdio_q *q) return atomic_read(&q->nr_buf_used) == 0; } -static inline int qdio_outbound_q_moved(struct qdio_q *q, unsigned int start, - unsigned int *error) -{ - int count; - - count = get_outbound_buffer_frontier(q, start, error); - - if (count) { - DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr); - - if (q->u.out.use_cq && *error != QDIO_ERROR_SLSB_PENDING) { - unsigned int i; - - for (i = 0; i < count; i++) - qdio_check_pending(q, QDIO_BUFNR(start + i)); - } - } - - return count; -} - static int qdio_kick_outbound_q(struct qdio_q *q, unsigned int count, unsigned long aob) { @@ -715,7 +674,7 @@ void qdio_outbound_tasklet(struct tasklet_struct *t) qperf_inc(q, tasklet_outbound); WARN_ON_ONCE(atomic_read(&q->nr_buf_used) < 0); - count = qdio_outbound_q_moved(q, start, &error); + count = get_outbound_buffer_frontier(q, start, &error); if (count) { q->first_to_check = add_buf(start, count); @@ -1482,7 +1441,7 @@ static int __qdio_inspect_queue(struct qdio_q *q, unsigned int *bufnr, *error = 0; count = q->is_input_q ? get_inbound_buffer_frontier(q, start, error) : - qdio_outbound_q_moved(q, start, error); + get_outbound_buffer_frontier(q, start, error); if (count == 0) return 0; diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 13056cc2377b..068e2d9b1eb8 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -6076,9 +6076,7 @@ static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue, struct qeth_card *card = queue->card; bool error = !!qdio_error; - if ((qdio_error == QDIO_ERROR_SLSB_PENDING) || - (queue->bufstates && (queue->bufstates[bidx].flags & - QDIO_OUTBUF_STATE_FLAG_PENDING))) { + if (qdio_error == QDIO_ERROR_SLSB_PENDING) { WARN_ON_ONCE(card->options.cq != QETH_CQ_ENABLED); QETH_CARD_TEXT_(card, 5, "pel%u", bidx); -- cgit v1.2.3