From patchwork Wed Aug 26 12:01:06 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: frank.blaschka@de.ibm.com X-Patchwork-Id: 32134 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@bilbo.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from ozlabs.org (ozlabs.org [203.10.76.45]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "mx.ozlabs.org", Issuer "CA Cert Signing Authority" (verified OK)) by bilbo.ozlabs.org (Postfix) with ESMTPS id A0DC2B70CF for ; Wed, 26 Aug 2009 22:01:53 +1000 (EST) Received: by ozlabs.org (Postfix) id 8FC8CDDD0C; Wed, 26 Aug 2009 22:01:53 +1000 (EST) Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by ozlabs.org (Postfix) with ESMTP id 20D18DDD0B for ; Wed, 26 Aug 2009 22:01:53 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754576AbZHZMBm (ORCPT ); Wed, 26 Aug 2009 08:01:42 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S932303AbZHZMBl (ORCPT ); Wed, 26 Aug 2009 08:01:41 -0400 Received: from mtagate5.de.ibm.com ([195.212.17.165]:57564 "EHLO mtagate5.de.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754576AbZHZMBi (ORCPT ); Wed, 26 Aug 2009 08:01:38 -0400 Received: from d12nrmr1607.megacenter.de.ibm.com (d12nrmr1607.megacenter.de.ibm.com [9.149.167.49]) by mtagate5.de.ibm.com (8.13.1/8.13.1) with ESMTP id n7QC1ajm020208; Wed, 26 Aug 2009 12:01:36 GMT Received: from d12av02.megacenter.de.ibm.com (d12av02.megacenter.de.ibm.com [9.149.165.228]) by d12nrmr1607.megacenter.de.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id n7QC1aW22232526; Wed, 26 Aug 2009 14:01:36 +0200 Received: from d12av02.megacenter.de.ibm.com (loopback [127.0.0.1]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id n7QC1aNR032588; Wed, 26 Aug 2009 14:01:36 +0200 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id n7QC1age032583; Wed, 26 Aug 2009 14:01:36 +0200 Received: by tuxmaker.boeblingen.de.ibm.com (Postfix, from userid 24631) id 1C3421224229; Wed, 26 Aug 2009 14:01:36 +0200 (CEST) Message-Id: <20090826120135.998746000@de.ibm.com> User-Agent: quilt/0.47-1 Date: Wed, 26 Aug 2009 14:01:06 +0200 From: frank.blaschka@de.ibm.com To: davem@davemloft.net Cc: netdev@vger.kernel.org, linux-s390@vger.kernel.org, Klaus-Dieter Wacker Subject: [patch 1/5] [PATCH] qeth: HiperSockets SIGA retry support on CC=2. References: <20090826120105.727838000@de.ibm.com> Content-Disposition: inline; filename=605-hipersockets-SIGA-retry.diff Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Klaus-Dieter Wacker Qeth HiperSockets support now retries sending of packets when the IBM System z signals a temporary resource shortage (e.g. target buffer full). The packet is enqueued into the device queue. After 3 times of unsuccessful send the packet is dropped. Signed-off-by: Klaus-Dieter Wacker --- drivers/s390/net/qeth_core.h | 9 +++++ drivers/s390/net/qeth_core_main.c | 60 ++++++++++++++++++++++++++++++++------ 2 files changed, 61 insertions(+), 8 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Index: git_net-next/drivers/s390/net/qeth_core.h =================================================================== --- git_net-next.orig/drivers/s390/net/qeth_core.h +++ git_net-next/drivers/s390/net/qeth_core.h @@ -435,6 +435,7 @@ struct qeth_qdio_out_q { * index of buffer to be filled by driver; state EMPTY or PACKING */ int next_buf_to_fill; + int sync_iqdio_error; /* * number of buffers that are currently filled (PRIMED) * -> these buffers are hardware-owned @@ -685,6 +686,14 @@ struct qeth_mc_mac { int is_vmac; }; +struct qeth_skb_data { + __u32 magic; + int count; +}; + +#define QETH_SKB_MAGIC 0x71657468 +#define QETH_SIGA_CC2_RETRIES 3 + struct qeth_card { struct list_head list; enum qeth_card_states state; Index: git_net-next/drivers/s390/net/qeth_core_main.c =================================================================== --- git_net-next.orig/drivers/s390/net/qeth_core_main.c +++ git_net-next/drivers/s390/net/qeth_core_main.c @@ -927,8 +927,8 @@ out: return; } -static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, - struct qeth_qdio_out_buffer *buf) +static void __qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, + struct qeth_qdio_out_buffer *buf, unsigned int qeth_skip_skb) { int i; struct sk_buff *skb; @@ -937,11 +937,13 @@ static void qeth_clear_output_buffer(str if (buf->buffer->element[0].flags & 0x40) atomic_dec(&queue->set_pci_flags_count); - skb = skb_dequeue(&buf->skb_list); - while (skb) { - atomic_dec(&skb->users); - dev_kfree_skb_any(skb); + if (!qeth_skip_skb) { skb = skb_dequeue(&buf->skb_list); + while (skb) { + atomic_dec(&skb->users); + dev_kfree_skb_any(skb); + skb = skb_dequeue(&buf->skb_list); + } } for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) { if (buf->buffer->element[i].addr && buf->is_header[i]) @@ -957,6 +959,12 @@ static void qeth_clear_output_buffer(str atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY); } +static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, + struct qeth_qdio_out_buffer *buf) +{ + __qeth_clear_output_buffer(queue, buf, 0); +} + void qeth_clear_qdio_buffers(struct qeth_card *card) { int i, j; @@ -2685,6 +2693,13 @@ static int qeth_handle_send_error(struct int sbalf15 = buffer->buffer->element[15].flags & 0xff; QETH_DBF_TEXT(TRACE, 6, "hdsnderr"); + if (card->info.type == QETH_CARD_TYPE_IQD) { + if (sbalf15 == 0) { + qdio_err = 0; + } else { + qdio_err = 1; + } + } qeth_check_qdio_errors(buffer->buffer, qdio_err, "qouterr"); if (!qdio_err) @@ -2817,6 +2832,7 @@ static void qeth_flush_buffers(struct qe } } + queue->sync_iqdio_error = 0; queue->card->dev->trans_start = jiffies; if (queue->card->options.performance_stats) { queue->card->perf_stats.outbound_do_qdio_cnt++; @@ -2832,6 +2848,10 @@ static void qeth_flush_buffers(struct qe queue->card->perf_stats.outbound_do_qdio_time += qeth_get_micros() - queue->card->perf_stats.outbound_do_qdio_start_time; + if (rc > 0) { + if (!(rc & QDIO_ERROR_SIGA_BUSY)) + queue->sync_iqdio_error = rc & 3; + } if (rc) { queue->card->stats.tx_errors += count; /* ignore temporary SIGA errors without busy condition */ @@ -2899,6 +2919,7 @@ void qeth_qdio_output_handler(struct ccw struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue]; struct qeth_qdio_out_buffer *buffer; int i; + unsigned qeth_send_err; QETH_DBF_TEXT(TRACE, 6, "qdouhdl"); if (qdio_error & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) { @@ -2915,8 +2936,9 @@ void qeth_qdio_output_handler(struct ccw } for (i = first_element; i < (first_element + count); ++i) { buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; - qeth_handle_send_error(card, buffer, qdio_error); - qeth_clear_output_buffer(queue, buffer); + qeth_send_err = qeth_handle_send_error(card, buffer, qdio_error); + __qeth_clear_output_buffer(queue, buffer, + (qeth_send_err == QETH_SEND_ERROR_RETRY) ? 1 : 0); } atomic_sub(count, &queue->used_buffers); /* check if we need to do something on this outbound queue */ @@ -3159,7 +3181,10 @@ int qeth_do_send_packet_fast(struct qeth int offset, int hd_len) { struct qeth_qdio_out_buffer *buffer; + struct sk_buff *skb1; + struct qeth_skb_data *retry_ctrl; int index; + int rc; /* spin until we get the queue ... */ while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED, @@ -3178,6 +3203,25 @@ int qeth_do_send_packet_fast(struct qeth atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len); qeth_flush_buffers(queue, index, 1); + if (queue->sync_iqdio_error == 2) { + skb1 = skb_dequeue(&buffer->skb_list); + while (skb1) { + atomic_dec(&skb1->users); + skb1 = skb_dequeue(&buffer->skb_list); + } + retry_ctrl = (struct qeth_skb_data *) &skb->cb[16]; + if (retry_ctrl->magic != QETH_SKB_MAGIC) { + retry_ctrl->magic = QETH_SKB_MAGIC; + retry_ctrl->count = 0; + } + if (retry_ctrl->count < QETH_SIGA_CC2_RETRIES) { + retry_ctrl->count++; + rc = dev_queue_xmit(skb); + } else { + dev_kfree_skb_any(skb); + QETH_DBF_TEXT(QERR, 2, "qrdrop"); + } + } return 0; out: atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);