From patchwork Thu Jul 9 07:32:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ike Panhc X-Patchwork-Id: 1325795 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4B2SYW68Lgz9sRR; Thu, 9 Jul 2020 17:32:15 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1jtR2S-0002A2-Fw; Thu, 09 Jul 2020 07:32:12 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1jtR2Q-00029p-W1 for kernel-team@lists.ubuntu.com; Thu, 09 Jul 2020 07:32:10 +0000 Received: from 1.general.ikepanhc.us.vpn ([10.172.69.54] helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1jtR2Q-0000px-0P for kernel-team@lists.ubuntu.com; Thu, 09 Jul 2020 07:32:10 +0000 From: Ike Panhc To: kernel-team@lists.ubuntu.com Subject: [PATCH 7/8] net: hns3: fix for TX queue not restarted problem Date: Thu, 9 Jul 2020 15:32:06 +0800 Message-Id: <20200709073206.14060-1-ike.pan@canonical.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200709073005.13674-1-ike.pan@canonical.com> References: <20200709073005.13674-1-ike.pan@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Yunsheng Lin BugLink: https://launchpad.net/bugs/1859756 There is timing window between ring_space checking and netif_stop_subqueue when transmiting a SKB, and the TX BD cleaning may be executed during the time window, which may caused TX queue not restarted problem. This patch fixes it by rechecking the ring_space after netif_stop_subqueue to make sure TX queue is restarted. Also, the ring->next_to_clean is updated even when pkts is zero, because all the TX BD cleaned may be non-SKB, so it needs to check if TX queue need to be restarted. Fixes: 76ad4f0ee747 ("net: hns3: Add support of HNS3 Ethernet Driver for hip08 SoC") Signed-off-by: Yunsheng Lin Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller (backported from commit 2a597eff2437d21841a1e87ffa536ab69dbffdcf) Signed-off-by: Ike Panhc --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 53049b34e873..26e9b07297ba 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1153,8 +1153,10 @@ static unsigned int hns3_nic_bd_num(struct sk_buff *skb) } static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring, + struct net_device *netdev, struct sk_buff **out_skb) { + struct hns3_nic_priv *priv = netdev_priv(netdev); struct sk_buff *skb = *out_skb; unsigned int bd_num; @@ -1179,10 +1181,24 @@ static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring, u64_stats_update_end(&ring->syncp); } - if (unlikely(ring_space(ring) < bd_num)) - return -EBUSY; + if (likely(ring_space(ring) >= bd_num)) + return bd_num; - return bd_num; + + netif_stop_subqueue(netdev, ring->queue_index); + smp_mb(); /* Memory barrier before checking ring_space */ + + /* Start queue in case hns3_clean_tx_ring has just made room + * available and has not seen the queue stopped state performed + * by netif_stop_subqueue above. + */ + if (ring_space(ring) >= bd_num && netif_carrier_ok(netdev) && + !test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) { + netif_start_subqueue(netdev, ring->queue_index); + return bd_num; + } + + return -EBUSY; } static void hns3_clear_desc(struct hns3_enet_ring *ring, int next_to_use_orig) @@ -1237,13 +1253,13 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) /* Prefetch the data used later */ prefetch(skb->data); - buf_num = hns3_nic_maybe_stop_tx(ring, &skb); + buf_num = hns3_nic_maybe_stop_tx(ring, netdev, &skb); if (unlikely(buf_num <= 0)) { if (buf_num == -EBUSY) { u64_stats_update_begin(&ring->syncp); ring->stats.tx_busy++; u64_stats_update_end(&ring->syncp); - goto out_net_tx_busy; + return NETDEV_TX_BUSY; } else if (buf_num == -ENOMEM) { u64_stats_update_begin(&ring->syncp); ring->stats.sw_err_cnt++; @@ -1301,12 +1317,6 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) out_err_tx_ok: dev_kfree_skb_any(skb); return NETDEV_TX_OK; - -out_net_tx_busy: - netif_stop_subqueue(netdev, ring_data->queue_index); - smp_mb(); /* Commit all data before submit */ - - return NETDEV_TX_BUSY; } static int hns3_nic_net_set_mac_address(struct net_device *netdev, void *p) @@ -2197,7 +2207,7 @@ void hns3_clean_tx_ring(struct hns3_enet_ring *ring) dev_queue = netdev_get_tx_queue(netdev, ring->tqp->tqp_index); netdev_tx_completed_queue(dev_queue, pkts, bytes); - if (unlikely(pkts && netif_carrier_ok(netdev) && + if (unlikely(netif_carrier_ok(netdev) && (ring_space(ring) > HNS3_MAX_BD_PER_PKT))) { /* Make sure that anybody stopping the queue after this * sees the new next_to_clean.