diff options
author | Jan Glauber <jang@linux.vnet.ibm.com> | 2009-03-26 15:24:31 +0100 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-03-26 15:24:22 +0100 |
commit | d303b6fd858370c22d5c70c313669e3521a5f758 (patch) | |
tree | 3c8dd573bc3ea48af8f12c41e5f00358c09a579a /drivers/s390/net | |
parent | 9e890ad880be1dd98483313b2ec0e23fbd4e3792 (diff) |
[S390] qdio: report SIGA errors directly
Errors from SIGA instructions are stored in the per queue qdio_error
and reported back when the queue handler is called. That opens a race
when multiple error conditions occur simultanously.
Report SIGA errors immediately in the return value of do_QDIO so the
upper layer can react and SIGA errors no longer interfere with other
errors.
Move the SIGA error handling in qeth from the outbound handler to
qeth_flush_buffers.
Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com>
Diffstat (limited to 'drivers/s390/net')
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 55 |
1 files changed, 17 insertions, 38 deletions
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index d1b5bebea7fb..2489bcebf5ec 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2693,40 +2693,21 @@ static int qeth_handle_send_error(struct qeth_card *card, struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err) { int sbalf15 = buffer->buffer->element[15].flags & 0xff; - int cc = qdio_err & 3; QETH_DBF_TEXT(TRACE, 6, "hdsnderr"); qeth_check_qdio_errors(buffer->buffer, qdio_err, "qouterr"); - switch (cc) { - case 0: - if (qdio_err) { - QETH_DBF_TEXT(TRACE, 1, "lnkfail"); - QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); - QETH_DBF_TEXT_(TRACE, 1, "%04x %02x", - (u16)qdio_err, (u8)sbalf15); - return QETH_SEND_ERROR_LINK_FAILURE; - } + + if (!qdio_err) return QETH_SEND_ERROR_NONE; - case 2: - if (qdio_err & QDIO_ERROR_SIGA_BUSY) { - QETH_DBF_TEXT(TRACE, 1, "SIGAcc2B"); - QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); - return QETH_SEND_ERROR_KICK_IT; - } - if ((sbalf15 >= 15) && (sbalf15 <= 31)) - return QETH_SEND_ERROR_RETRY; - return QETH_SEND_ERROR_LINK_FAILURE; - /* look at qdio_error and sbalf 15 */ - case 1: - QETH_DBF_TEXT(TRACE, 1, "SIGAcc1"); - QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); - return QETH_SEND_ERROR_LINK_FAILURE; - case 3: - default: - QETH_DBF_TEXT(TRACE, 1, "SIGAcc3"); - QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); - return QETH_SEND_ERROR_KICK_IT; - } + + if ((sbalf15 >= 15) && (sbalf15 <= 31)) + return QETH_SEND_ERROR_RETRY; + + QETH_DBF_TEXT(TRACE, 1, "lnkfail"); + QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); + QETH_DBF_TEXT_(TRACE, 1, "%04x %02x", + (u16)qdio_err, (u8)sbalf15); + return QETH_SEND_ERROR_LINK_FAILURE; } /* @@ -2862,10 +2843,14 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, qeth_get_micros() - queue->card->perf_stats.outbound_do_qdio_start_time; if (rc) { + queue->card->stats.tx_errors += count; + /* ignore temporary SIGA errors without busy condition */ + if (rc == QDIO_ERROR_SIGA_TARGET) + return; QETH_DBF_TEXT(TRACE, 2, "flushbuf"); QETH_DBF_TEXT_(TRACE, 2, " err%d", rc); QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_DDEV_ID(queue->card)); - queue->card->stats.tx_errors += count; + /* this must not happen under normal circumstances. if it * happens something is really wrong -> recover */ qeth_schedule_recovery(queue->card); @@ -2940,13 +2925,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, } for (i = first_element; i < (first_element + count); ++i) { buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; - /*we only handle the KICK_IT error by doing a recovery */ - if (qeth_handle_send_error(card, buffer, qdio_error) - == QETH_SEND_ERROR_KICK_IT){ - netif_stop_queue(card->dev); - qeth_schedule_recovery(card); - return; - } + qeth_handle_send_error(card, buffer, qdio_error); qeth_clear_output_buffer(queue, buffer); } atomic_sub(count, &queue->used_buffers); |