diff options
author | Julian Wiedmann | 2018-03-06 17:58:49 +0100 |
---|---|---|
committer | Martin Schwidefsky | 2018-03-26 16:13:02 +0200 |
commit | 88bf319fc2d6d971ef8692c2cae7f96708340461 (patch) | |
tree | 8cb695003b078fdcc459f651823a524b19aff9bf /drivers/s390 | |
parent | dae55b6fef58530c13df074bcc182c096609339e (diff) |
s390/qdio: split up CCQ handling for EQBS / SQBS
Get rid of the confusing two-stage translation in a hot path, and only
handle CCQs that we anticipate for the respective command. Any
unexpected value (such as CCQ 97 (rc == 1) for SQBS) should be
considered a severe HW/driver bug, and traced as such.
Signed-off-by: Julian Wiedmann <jwi@linux.vnet.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 77 |
1 files changed, 33 insertions, 44 deletions
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index de647b7e17b1..a337281337a7 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -98,22 +98,6 @@ static inline int do_siga_output(unsigned long schid, unsigned long mask, return cc; } -static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq) -{ - /* all done or next buffer state different */ - if (ccq == 0 || ccq == 32) - return 0; - /* no buffer processed */ - if (ccq == 97) - return 1; - /* not all buffers processed */ - if (ccq == 96) - return 2; - /* notify devices immediately */ - DBF_ERROR("%4x ccq:%3d", SCH_NO(q), ccq); - return -EIO; -} - /** * qdio_do_eqbs - extract buffer states for QEBSM * @q: queue to manipulate @@ -128,7 +112,7 @@ static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq) static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state, int start, int count, int auto_ack) { - int rc, tmp_count = count, tmp_start = start, nr = q->nr; + int tmp_count = count, tmp_start = start, nr = q->nr; unsigned int ccq = 0; qperf_inc(q, eqbs); @@ -138,27 +122,30 @@ static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state, again: ccq = do_eqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count, auto_ack); - rc = qdio_check_ccq(q, ccq); - if (!rc) - return count - tmp_count; - - if (rc == 1) { - DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "EQBS again:%2d", ccq); - goto again; - } - if (rc == 2) { + switch (ccq) { + case 0: + case 32: + /* all done, or next buffer state different */ + return count - tmp_count; + case 96: + /* not all buffers processed */ qperf_inc(q, eqbs_partial); DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "EQBS part:%02x", tmp_count); return count - tmp_count; + case 97: + /* no buffer processed */ + DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "EQBS again:%2d", ccq); + goto again; + default: + DBF_ERROR("%4x ccq:%3d", SCH_NO(q), ccq); + DBF_ERROR("%4x EQBS ERROR", SCH_NO(q)); + DBF_ERROR("%3d%3d%2d", count, tmp_count, nr); + q->handler(q->irq_ptr->cdev, QDIO_ERROR_GET_BUF_STATE, q->nr, + q->first_to_kick, count, q->irq_ptr->int_parm); + return 0; } - - DBF_ERROR("%4x EQBS ERROR", SCH_NO(q)); - DBF_ERROR("%3d%3d%2d", count, tmp_count, nr); - q->handler(q->irq_ptr->cdev, QDIO_ERROR_GET_BUF_STATE, - q->nr, q->first_to_kick, count, q->irq_ptr->int_parm); - return 0; } /** @@ -178,7 +165,6 @@ static int qdio_do_sqbs(struct qdio_q *q, unsigned char state, int start, unsigned int ccq = 0; int tmp_count = count, tmp_start = start; int nr = q->nr; - int rc; if (!count) return 0; @@ -188,23 +174,26 @@ static int qdio_do_sqbs(struct qdio_q *q, unsigned char state, int start, nr += q->irq_ptr->nr_input_qs; again: ccq = do_sqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count); - rc = qdio_check_ccq(q, ccq); - if (!rc) { + + switch (ccq) { + case 0: + case 32: + /* all done, or active buffer adapter-owned */ WARN_ON_ONCE(tmp_count); return count - tmp_count; - } - - if (rc == 1 || rc == 2) { + case 96: + /* not all buffers processed */ DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "SQBS again:%2d", ccq); qperf_inc(q, sqbs_partial); goto again; + default: + DBF_ERROR("%4x ccq:%3d", SCH_NO(q), ccq); + DBF_ERROR("%4x SQBS ERROR", SCH_NO(q)); + DBF_ERROR("%3d%3d%2d", count, tmp_count, nr); + q->handler(q->irq_ptr->cdev, QDIO_ERROR_SET_BUF_STATE, q->nr, + q->first_to_kick, count, q->irq_ptr->int_parm); + return 0; } - - DBF_ERROR("%4x SQBS ERROR", SCH_NO(q)); - DBF_ERROR("%3d%3d%2d", count, tmp_count, nr); - q->handler(q->irq_ptr->cdev, QDIO_ERROR_SET_BUF_STATE, - q->nr, q->first_to_kick, count, q->irq_ptr->int_parm); - return 0; } /* |