aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net
diff options
context:
space:
mode:
authorJan Glauber <jang@linux.vnet.ibm.com>2009-03-26 10:24:31 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-03-26 10:24:22 -0400
commitd303b6fd858370c22d5c70c313669e3521a5f758 (patch)
tree3c8dd573bc3ea48af8f12c41e5f00358c09a579a /drivers/s390/net
parent9e890ad880be1dd98483313b2ec0e23fbd4e3792 (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.c55
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,
2693 struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err) 2693 struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err)
2694{ 2694{
2695 int sbalf15 = buffer->buffer->element[15].flags & 0xff; 2695 int sbalf15 = buffer->buffer->element[15].flags & 0xff;
2696 int cc = qdio_err & 3;
2697 2696
2698 QETH_DBF_TEXT(TRACE, 6, "hdsnderr"); 2697 QETH_DBF_TEXT(TRACE, 6, "hdsnderr");
2699 qeth_check_qdio_errors(buffer->buffer, qdio_err, "qouterr"); 2698 qeth_check_qdio_errors(buffer->buffer, qdio_err, "qouterr");
2700 switch (cc) { 2699
2701 case 0: 2700 if (!qdio_err)
2702 if (qdio_err) {
2703 QETH_DBF_TEXT(TRACE, 1, "lnkfail");
2704 QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
2705 QETH_DBF_TEXT_(TRACE, 1, "%04x %02x",
2706 (u16)qdio_err, (u8)sbalf15);
2707 return QETH_SEND_ERROR_LINK_FAILURE;
2708 }
2709 return QETH_SEND_ERROR_NONE; 2701 return QETH_SEND_ERROR_NONE;
2710 case 2: 2702
2711 if (qdio_err & QDIO_ERROR_SIGA_BUSY) { 2703 if ((sbalf15 >= 15) && (sbalf15 <= 31))
2712 QETH_DBF_TEXT(TRACE, 1, "SIGAcc2B"); 2704 return QETH_SEND_ERROR_RETRY;
2713 QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); 2705
2714 return QETH_SEND_ERROR_KICK_IT; 2706 QETH_DBF_TEXT(TRACE, 1, "lnkfail");
2715 } 2707 QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
2716 if ((sbalf15 >= 15) && (sbalf15 <= 31)) 2708 QETH_DBF_TEXT_(TRACE, 1, "%04x %02x",
2717 return QETH_SEND_ERROR_RETRY; 2709 (u16)qdio_err, (u8)sbalf15);
2718 return QETH_SEND_ERROR_LINK_FAILURE; 2710 return QETH_SEND_ERROR_LINK_FAILURE;
2719 /* look at qdio_error and sbalf 15 */
2720 case 1:
2721 QETH_DBF_TEXT(TRACE, 1, "SIGAcc1");
2722 QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
2723 return QETH_SEND_ERROR_LINK_FAILURE;
2724 case 3:
2725 default:
2726 QETH_DBF_TEXT(TRACE, 1, "SIGAcc3");
2727 QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
2728 return QETH_SEND_ERROR_KICK_IT;
2729 }
2730} 2711}
2731 2712
2732/* 2713/*
@@ -2862,10 +2843,14 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
2862 qeth_get_micros() - 2843 qeth_get_micros() -
2863 queue->card->perf_stats.outbound_do_qdio_start_time; 2844 queue->card->perf_stats.outbound_do_qdio_start_time;
2864 if (rc) { 2845 if (rc) {
2846 queue->card->stats.tx_errors += count;
2847 /* ignore temporary SIGA errors without busy condition */
2848 if (rc == QDIO_ERROR_SIGA_TARGET)
2849 return;
2865 QETH_DBF_TEXT(TRACE, 2, "flushbuf"); 2850 QETH_DBF_TEXT(TRACE, 2, "flushbuf");
2866 QETH_DBF_TEXT_(TRACE, 2, " err%d", rc); 2851 QETH_DBF_TEXT_(TRACE, 2, " err%d", rc);
2867 QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_DDEV_ID(queue->card)); 2852 QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_DDEV_ID(queue->card));
2868 queue->card->stats.tx_errors += count; 2853
2869 /* this must not happen under normal circumstances. if it 2854 /* this must not happen under normal circumstances. if it
2870 * happens something is really wrong -> recover */ 2855 * happens something is really wrong -> recover */
2871 qeth_schedule_recovery(queue->card); 2856 qeth_schedule_recovery(queue->card);
@@ -2940,13 +2925,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
2940 } 2925 }
2941 for (i = first_element; i < (first_element + count); ++i) { 2926 for (i = first_element; i < (first_element + count); ++i) {
2942 buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; 2927 buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
2943 /*we only handle the KICK_IT error by doing a recovery */ 2928 qeth_handle_send_error(card, buffer, qdio_error);
2944 if (qeth_handle_send_error(card, buffer, qdio_error)
2945 == QETH_SEND_ERROR_KICK_IT){
2946 netif_stop_queue(card->dev);
2947 qeth_schedule_recovery(card);
2948 return;
2949 }
2950 qeth_clear_output_buffer(queue, buffer); 2929 qeth_clear_output_buffer(queue, buffer);
2951 } 2930 }
2952 atomic_sub(count, &queue->used_buffers); 2931 atomic_sub(count, &queue->used_buffers);