summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/qdio.h1
-rw-r--r--drivers/s390/cio/qdio_main.c11
-rw-r--r--drivers/s390/net/qeth_core_main.c9
3 files changed, 16 insertions, 5 deletions
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h
index f96454f5d4cd..c85f75a3d452 100644
--- a/arch/s390/include/asm/qdio.h
+++ b/arch/s390/include/asm/qdio.h
@@ -315,6 +315,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
#define QDIO_ERROR_GET_BUF_STATE 0x0002
#define QDIO_ERROR_SET_BUF_STATE 0x0004
#define QDIO_ERROR_SLSB_STATE 0x0100
+#define QDIO_ERROR_SLSB_PENDING 0x0200
#define QDIO_ERROR_FATAL 0x00ff
#define QDIO_ERROR_TEMPORARY 0xff00
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 4252f43ef214..0ad5a4c1bb08 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -571,6 +571,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q, unsigned int start,
unsigned int *error)
{
unsigned char state = 0;
+ unsigned int i;
int count;
q->timestamp = get_tod_clock_fast();
@@ -591,8 +592,14 @@ static int get_outbound_buffer_frontier(struct qdio_q *q, unsigned int start,
return 0;
switch (state) {
- case SLSB_P_OUTPUT_EMPTY:
case SLSB_P_OUTPUT_PENDING:
+ /* detach the utilized QAOBs: */
+ for (i = 0; i < count; i++)
+ q->u.out.aobs[QDIO_BUFNR(start + i)] = NULL;
+
+ *error = QDIO_ERROR_SLSB_PENDING;
+ fallthrough;
+ case SLSB_P_OUTPUT_EMPTY:
/* the adapter got it */
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr,
"out empty:%1d %02x", q->nr, count);
@@ -643,7 +650,7 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q, unsigned int start,
if (count) {
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr);
- if (q->u.out.use_cq) {
+ if (q->u.out.use_cq && *error != QDIO_ERROR_SLSB_PENDING) {
unsigned int i;
for (i = 0; i < count; i++)
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index cf18d87da41e..13056cc2377b 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6068,14 +6068,17 @@ int qeth_poll(struct napi_struct *napi, int budget)
EXPORT_SYMBOL_GPL(qeth_poll);
static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue,
- unsigned int bidx, bool error, int budget)
+ unsigned int bidx, unsigned int qdio_error,
+ int budget)
{
struct qeth_qdio_out_buffer *buffer = queue->bufs[bidx];
u8 sflags = buffer->buffer->element[15].sflags;
struct qeth_card *card = queue->card;
+ bool error = !!qdio_error;
- if (queue->bufstates && (queue->bufstates[bidx].flags &
- QDIO_OUTBUF_STATE_FLAG_PENDING)) {
+ if ((qdio_error == QDIO_ERROR_SLSB_PENDING) ||
+ (queue->bufstates && (queue->bufstates[bidx].flags &
+ QDIO_OUTBUF_STATE_FLAG_PENDING))) {
WARN_ON_ONCE(card->options.cq != QETH_CQ_ENABLED);
QETH_CARD_TEXT_(card, 5, "pel%u", bidx);