| From 64e03ff72623b8c2ea89ca3cb660094e019ed4ae Mon Sep 17 00:00:00 2001 |
| From: Julian Wiedmann <jwi@linux.ibm.com> |
| Date: Wed, 16 May 2018 09:37:25 +0200 |
| Subject: s390/qdio: reset old sbal_state flags |
| |
| From: Julian Wiedmann <jwi@linux.ibm.com> |
| |
| commit 64e03ff72623b8c2ea89ca3cb660094e019ed4ae upstream. |
| |
| When allocating a new AOB fails, handle_outbound() is still capable of |
| transmitting the selected buffer (just without async completion). |
| |
| But if a previous transfer on this queue slot used async completion, its |
| sbal_state flags field is still set to QDIO_OUTBUF_STATE_FLAG_PENDING. |
| So when the upper layer driver sees this stale flag, it expects an async |
| completion that never happens. |
| |
| Fix this by unconditionally clearing the flags field. |
| |
| Fixes: 104ea556ee7f ("qdio: support asynchronous delivery of storage blocks") |
| Cc: <stable@vger.kernel.org> #v3.2+ |
| Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> |
| Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/s390/include/asm/qdio.h | 1 - |
| drivers/s390/cio/qdio_main.c | 5 ++--- |
| 2 files changed, 2 insertions(+), 4 deletions(-) |
| |
| --- a/arch/s390/include/asm/qdio.h |
| +++ b/arch/s390/include/asm/qdio.h |
| @@ -262,7 +262,6 @@ struct qdio_outbuf_state { |
| void *user; |
| }; |
| |
| -#define QDIO_OUTBUF_STATE_FLAG_NONE 0x00 |
| #define QDIO_OUTBUF_STATE_FLAG_PENDING 0x01 |
| |
| #define CHSC_AC1_INITIATE_INPUTQ 0x80 |
| --- a/drivers/s390/cio/qdio_main.c |
| +++ b/drivers/s390/cio/qdio_main.c |
| @@ -641,21 +641,20 @@ static inline unsigned long qdio_aob_for |
| unsigned long phys_aob = 0; |
| |
| if (!q->use_cq) |
| - goto out; |
| + return 0; |
| |
| if (!q->aobs[bufnr]) { |
| struct qaob *aob = qdio_allocate_aob(); |
| q->aobs[bufnr] = aob; |
| } |
| if (q->aobs[bufnr]) { |
| - q->sbal_state[bufnr].flags = QDIO_OUTBUF_STATE_FLAG_NONE; |
| q->sbal_state[bufnr].aob = q->aobs[bufnr]; |
| q->aobs[bufnr]->user1 = (u64) q->sbal_state[bufnr].user; |
| phys_aob = virt_to_phys(q->aobs[bufnr]); |
| WARN_ON_ONCE(phys_aob & 0xFF); |
| } |
| |
| -out: |
| + q->sbal_state[bufnr].flags = 0; |
| return phys_aob; |
| } |
| |