| From: Julian Wiedmann <jwi@linux.vnet.ibm.com> |
| Date: Mon, 5 Mar 2018 09:39:38 +0100 |
| Subject: s390/qdio: don't retry EQBS after CCQ 96 |
| |
| commit dae55b6fef58530c13df074bcc182c096609339e upstream. |
| |
| Immediate retry of EQBS after CCQ 96 means that we potentially misreport |
| the state of buffers inspected during the first EQBS call. |
| |
| This occurs when |
| 1. the first EQBS finds all inspected buffers still in the initial state |
| set by the driver (ie INPUT EMPTY or OUTPUT PRIMED), |
| 2. the EQBS terminates early with CCQ 96, and |
| 3. by the time that the second EQBS comes around, the state of those |
| previously inspected buffers has changed. |
| |
| If the state reported by the second EQBS is 'driver-owned', all we know |
| is that the previous buffers are driver-owned now as well. But we can't |
| tell if they all have the same state. So for instance |
| - the second EQBS reports OUTPUT EMPTY, but any number of the previous |
| buffers could be OUTPUT ERROR by now, |
| - the second EQBS reports OUTPUT ERROR, but any number of the previous |
| buffers could be OUTPUT EMPTY by now. |
| |
| Effectively, this can result in both over- and underreporting of errors. |
| |
| If the state reported by the second EQBS is 'HW-owned', that doesn't |
| guarantee that the previous buffers have not been switched to |
| driver-owned in the mean time. So for instance |
| - the second EQBS reports INPUT EMPTY, but any number of the previous |
| buffers could be INPUT PRIMED (or INPUT ERROR) by now. |
| |
| This would result in failure to process pending work on the queue. If |
| it's the final check before yielding initiative, this can cause |
| a (temporary) queue stall due to IRQ avoidance. |
| |
| Fixes: 25f269f17316 ("[S390] qdio: EQBS retry after CCQ 96") |
| 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> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/s390/cio/qdio_main.c | 11 ++--------- |
| 1 file changed, 2 insertions(+), 9 deletions(-) |
| |
| --- a/drivers/s390/cio/qdio_main.c |
| +++ b/drivers/s390/cio/qdio_main.c |
| @@ -126,7 +126,7 @@ static inline int qdio_check_ccq(struct |
| 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, retried = 0; |
| + int rc, tmp_count = count, tmp_start = start, nr = q->nr; |
| unsigned int ccq = 0; |
| |
| qperf_inc(q, eqbs); |
| @@ -149,14 +149,7 @@ again: |
| qperf_inc(q, eqbs_partial); |
| DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "EQBS part:%02x", |
| tmp_count); |
| - /* |
| - * Retry once, if that fails bail out and process the |
| - * extracted buffers before trying again. |
| - */ |
| - if (!retried++) |
| - goto again; |
| - else |
| - return count - tmp_count; |
| + return count - tmp_count; |
| } |
| |
| DBF_ERROR("%4x EQBS ERROR", SCH_NO(q)); |