Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp605649ybl; Fri, 10 Jan 2020 03:55:46 -0800 (PST) X-Google-Smtp-Source: APXvYqzZ5rori5Pbs8oFaf/mkuCdKuvcxWbPrloWG7JlYv8kuMzwIRuBNNqHsn+2x2oIOnDqhrfl X-Received: by 2002:a05:6830:1d91:: with SMTP id y17mr2106424oti.276.1578657346416; Fri, 10 Jan 2020 03:55:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1578657346; cv=none; d=google.com; s=arc-20160816; b=kfIwxROBVE6h7fXkhcBA4yZvw+yG7DGQhw3i5YOGv65rqHZhpsTROl80WVZsEQPqEX SG/c0+B/hqqflr72Z14B7iLVEcS6CjXBHXu/DPNyweUsbZ95qVdrNXLKGHHLSOO8D7kk Y13wYZvWiV5BUC29SVb6h7tqJhY8cGjbWYoGWgUMR8iMyvTBNhenSMMhB4E/RmAlDNM0 jHwzDkmC0T8TJqEr1P6D2SHfiMJf4IM4iC8dJL5ohxmCI4zyFfRlxRwge/+Lgyztk/TU Livl2vW0uDxI1Te2dWYS/x6pJvydoo/AUBvgSdIRZwtKH/f2FXHeJv1UkzOBijDnEf6/ XcHA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=1x0GfsUqpB9A+IvJMzyPbg2dRbrEqZxJQn0WCRvML0c=; b=hyCQUcBq36sUp+LGcu8SlA2afBjL2MWnoQWXEstqX6kDAJG4rFou1CpvVvc4+HihVr KH9cQBy5d29LbbHSSlNhwr2WN18k48AnYVCPE3xUNvuJqDolZtHKhQ862P7tMnyTKxCv c6kd0XOf2JpBaecchNdig3xJ3B3zcO8Jhn5K/CXTFxZ3GykKo+OVPDhcgWhXk2/ye7rf 1gsEFOuD9MWMGnblL+6khvJRNdACHV5Jg7L2Sok1PSQxTapxAKSEOdH1nNGaNjZh655M eNafDA6zxCC0FyTAEFsQDyPhvPD36VB9LtW2cw+y4Q+8GnY5F8FoMIlqPHT76buv09tr Bnmg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u130si935783oif.94.2020.01.10.03.55.35; Fri, 10 Jan 2020 03:55:46 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728100AbgAJLyc (ORCPT + 99 others); Fri, 10 Jan 2020 06:54:32 -0500 Received: from foss.arm.com ([217.140.110.172]:43132 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728029AbgAJLya (ORCPT ); Fri, 10 Jan 2020 06:54:30 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 0F64E1063; Fri, 10 Jan 2020 03:54:30 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id E797B3F534; Fri, 10 Jan 2020 03:54:28 -0800 (PST) From: Andre Przywara To: "David S . Miller" , Radhey Shyam Pandey Cc: Michal Simek , Robert Hancock , netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 05/14] net: axienet: Factor out TX descriptor chain cleanup Date: Fri, 10 Jan 2020 11:54:06 +0000 Message-Id: <20200110115415.75683-6-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200110115415.75683-1-andre.przywara@arm.com> References: <20200110115415.75683-1-andre.przywara@arm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Factor out the code that cleans up a number of connected TX descriptors, as we will need it to properly roll back a failed _xmit() call. There are subtle differences between cleaning up a successfully sent chain (unknown number of involved descriptors, total data size needed) and a chain that was about to set up (number of descriptors known), so cater for those variations with some extra parameters. Signed-off-by: Andre Przywara --- .../net/ethernet/xilinx/xilinx_axienet_main.c | 75 ++++++++++++------- 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index ec5d01adc1d5..82abe2b0f16a 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -543,33 +543,37 @@ static int axienet_device_reset(struct net_device *ndev) return 0; } -/** - * axienet_start_xmit_done - Invoked once a transmit is completed by the - * Axi DMA Tx channel. - * @ndev: Pointer to the net_device structure - * - * This function is invoked from the Axi DMA Tx isr to notify the completion - * of transmit operation. It clears fields in the corresponding Tx BDs and - * unmaps the corresponding buffer so that CPU can regain ownership of the - * buffer. It finally invokes "netif_wake_queue" to restart transmission if - * required. +/* Clean up a series of linked TX descriptors. Would either be called + * after a successful transmit operation, or after there was an error + * when setting up the chain. + * Returns the number of descriptors handled. */ -static void axienet_start_xmit_done(struct net_device *ndev) +static int axienet_free_tx_chain(struct net_device *ndev, u32 first_bd, + int nr_bds, u32 *sizep) { - u32 size = 0; - u32 packets = 0; struct axienet_local *lp = netdev_priv(ndev); + int max_bds = (nr_bds != -1) ? nr_bds : lp->tx_bd_num; struct axidma_bd *cur_p; - unsigned int status = 0; + unsigned int status; + int i; + + for (i = 0; i < max_bds; i++) { + cur_p = &lp->tx_bd_v[(first_bd + i) % lp->tx_bd_num]; + status = cur_p->status; + + /* If no number is given, clean up *all* descriptors that have + * been completed by the MAC. + */ + if (nr_bds == -1 && !(status & XAXIDMA_BD_STS_COMPLETE_MASK)) + break; - cur_p = &lp->tx_bd_v[lp->tx_bd_ci]; - status = cur_p->status; - while (status & XAXIDMA_BD_STS_COMPLETE_MASK) { dma_unmap_single(ndev->dev.parent, cur_p->phys, (cur_p->cntrl & XAXIDMA_BD_CTRL_LENGTH_MASK), DMA_TO_DEVICE); - if (cur_p->skb) + + if (cur_p->skb && (status & XAXIDMA_BD_STS_COMPLETE_MASK)) dev_consume_skb_irq(cur_p->skb); + cur_p->cntrl = 0; cur_p->app0 = 0; cur_p->app1 = 0; @@ -578,15 +582,36 @@ static void axienet_start_xmit_done(struct net_device *ndev) cur_p->status = 0; cur_p->skb = NULL; - size += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK; - packets++; - - if (++lp->tx_bd_ci >= lp->tx_bd_num) - lp->tx_bd_ci = 0; - cur_p = &lp->tx_bd_v[lp->tx_bd_ci]; - status = cur_p->status; + if (sizep) + *sizep += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK; } + return i; +} + +/** + * axienet_start_xmit_done - Invoked once a transmit is completed by the + * Axi DMA Tx channel. + * @ndev: Pointer to the net_device structure + * + * This function is invoked from the Axi DMA Tx isr to notify the completion + * of transmit operation. It clears fields in the corresponding Tx BDs and + * unmaps the corresponding buffer so that CPU can regain ownership of the + * buffer. It finally invokes "netif_wake_queue" to restart transmission if + * required. + */ +static void axienet_start_xmit_done(struct net_device *ndev) +{ + u32 size = 0; + u32 packets = 0; + struct axienet_local *lp = netdev_priv(ndev); + + packets = axienet_free_tx_chain(ndev, lp->tx_bd_ci, -1, &size); + + lp->tx_bd_ci += packets; + if (lp->tx_bd_ci >= lp->tx_bd_num) + lp->tx_bd_ci -= lp->tx_bd_num; + ndev->stats.tx_packets += packets; ndev->stats.tx_bytes += size; -- 2.17.1