Message ID | 20231024145119.2366588-4-srasheed@marvell.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:ce89:0:b0:403:3b70:6f57 with SMTP id p9csp1996488vqx; Tue, 24 Oct 2023 07:52:08 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGppYgOgC+ZUqZOoKvraNU4LWARtstLZa2LG8IJ+jGSM1Uxmq+Yl/j0LvAbLDr1Dya+1j1S X-Received: by 2002:a17:902:facb:b0:1ca:85ae:3b59 with SMTP id ld11-20020a170902facb00b001ca85ae3b59mr12875755plb.9.1698159128351; Tue, 24 Oct 2023 07:52:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1698159128; cv=none; d=google.com; s=arc-20160816; b=EnshBCF86/Ezs+jVWxYvZyCAsgeMb8SLFm996w9pK0I2TXzwKEjFkU8OQkWWcaqtmd B9JAiX9HUnMUvjHWGamR/SFEWcbX/MeKD+8r5OH5QUUmuvGos5S/YpIGFWZbHCSS7m05 T6f2+a8pGRtTLkGPcqizQ0khJCMMYETzEIsCogDUm5W8yDDvK1wmfd1SJ8XRcLueDsFJ 12updhhjiEAT96yWJBkqTObTXmF4pbSbMc24AKUSneLY6Ig9U3nnL0cOtZuGtqsXfilr X/zrKQLR0tZMDAXRR/RnLSvEHiPNra52cogxc0oma796nNkcmTevAli+Kjg4qgrr1rRd 44xg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=IFVG9SilRa/MRmDVoe+eoB8mh3aaZAJsY4D9VWbLWRY=; fh=PUbSZjf2dtyqulLdd5rISVghnntgSGxvYpWMBobeHB0=; b=yrAgyGG+2CsRaqitvM7o5/8NMhob0Cj4DQmb2fA188ILqg9t7SogvKhvNOvT9xKFnf nqrCqByhDsF9I+I/PFm8cFctdC0dr4vWzpNoQNJmfp4McaGVW/Hcupu5O5e6noqJMhwI k/FW+ppySTr6l8fbXKJGzyufyqtGoU+jIWUGMQ7F4WbNYVZAKnFtWex9hXRZ31QAPYlb rjZiyzWqae3GVsh1Vh9Wl8pbc5ALRjLprrlt8Ra0ZXl3VFJFr3gbgX4hqKTuwn7akJmY CeFsNKHrEb41N1jvW3RJ1t/cjQDRJXJ3N2gK+KVIfU/J5f6/o3NHDVC3vU4GARwxSBOy RHtw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=XZ4fo5pu; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from snail.vger.email (snail.vger.email. [23.128.96.37]) by mx.google.com with ESMTPS id i12-20020a170902c94c00b001b222cd9826si8755869pla.349.2023.10.24.07.52.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Oct 2023 07:52:08 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) client-ip=23.128.96.37; Authentication-Results: mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=XZ4fo5pu; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by snail.vger.email (Postfix) with ESMTP id 892A5802C68C; Tue, 24 Oct 2023 07:52:07 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at snail.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234612AbjJXOv6 (ORCPT <rfc822;a1648639935@gmail.com> + 26 others); Tue, 24 Oct 2023 10:51:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47454 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343702AbjJXOvu (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Tue, 24 Oct 2023 10:51:50 -0400 Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 168CF10DE; Tue, 24 Oct 2023 07:51:47 -0700 (PDT) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 39O2K86x021789; Tue, 24 Oct 2023 07:51:42 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=IFVG9SilRa/MRmDVoe+eoB8mh3aaZAJsY4D9VWbLWRY=; b=XZ4fo5pu4Iyhq9lENnD7mEUGIwtO6FA315CaIMiVhS41u1jA1RhoM08VNt1rUCIhXcYq VkZuc8FJuITBW86hlMBb5hnFefTWFc4A6wRbXqnxiBcX/3DZqkpPW29xhD3s/MtrUo6O 3bovB0Ew3qCw0NUUMBocCUdD/T5pomVxHF3/Rl8xq3wz43jkhqfrzH6I98VhFYEApVyt wJVmxdqNYbR4tzJjRyrfkDEIfoTrLF9Q9kz6evUyp9Gu0FvqFCaB7/ZVe6bPcYX2c0Wr RiGcQLWiBcV5lzfXPng0OYV8XziLPMJIHPzg3/1227AjK5YgdxmoMWbENby0nEoTl5p+ +g== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3tx523tpqa-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Tue, 24 Oct 2023 07:51:41 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 24 Oct 2023 07:51:40 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 24 Oct 2023 07:51:40 -0700 Received: from ubuntu-PowerEdge-T110-II.sclab.marvell.com (unknown [10.106.27.86]) by maili.marvell.com (Postfix) with ESMTP id 072183F7076; Tue, 24 Oct 2023 07:51:39 -0700 (PDT) From: Shinas Rasheed <srasheed@marvell.com> To: <netdev@vger.kernel.org>, <linux-kernel@vger.kernel.org> CC: <hgani@marvell.com>, <vimleshk@marvell.com>, <egallen@redhat.com>, <mschmidt@redhat.com>, <pabeni@redhat.com>, <horms@kernel.org>, <kuba@kernel.org>, <davem@davemloft.net>, <wizhao@redhat.com>, <konguyen@redhat.com>, Shinas Rasheed <srasheed@marvell.com>, "Veerasenareddy Burru" <vburru@marvell.com>, Sathesh Edara <sedara@marvell.com>, Eric Dumazet <edumazet@google.com> Subject: [PATCH net-next v2 3/4] octeon_ep: implement xmit_more in transmit Date: Tue, 24 Oct 2023 07:51:18 -0700 Message-ID: <20231024145119.2366588-4-srasheed@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231024145119.2366588-1-srasheed@marvell.com> References: <20231024145119.2366588-1-srasheed@marvell.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Proofpoint-GUID: QXrlSMIZs2y_ZRI-5Y15kpvMRNfBDlk9 X-Proofpoint-ORIG-GUID: QXrlSMIZs2y_ZRI-5Y15kpvMRNfBDlk9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-24_15,2023-10-24_01,2023-05-22_02 X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (snail.vger.email [0.0.0.0]); Tue, 24 Oct 2023 07:52:07 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1780648906311678812 X-GMAIL-MSGID: 1780648906311678812 |
Series |
Cleanup and optimizations to transmit code
|
|
Commit Message
Shinas Rasheed
Oct. 24, 2023, 2:51 p.m. UTC
Add xmit_more handling in tx datapath for octeon_ep pf.
Signed-off-by: Shinas Rasheed <srasheed@marvell.com>
---
V2:
- Updated changelog to have imperative tone.
V1: https://lore.kernel.org/all/20231023114449.2362147-3-srasheed@marvell.com/
.../ethernet/marvell/octeon_ep/octep_config.h | 2 +-
.../ethernet/marvell/octeon_ep/octep_main.c | 19 +++++++++++++++----
2 files changed, 16 insertions(+), 5 deletions(-)
Comments
On Tue, 24 Oct 2023 07:51:18 -0700 Shinas Rasheed wrote: > iq->host_write_index = wi; > + if (xmit_more && > + (atomic_read(&iq->instr_pending) < > + (iq->max_count - OCTEP_WAKE_QUEUE_THRESHOLD)) && > + iq->fill_cnt < iq->fill_threshold) > + return NETDEV_TX_OK; Does this guarantee that a full-sized skb can be accommodated? If so - consider stopping stopping the queue when the condition is not true. The recommended way of implementing 'driver flow control' is to stop the queue once next packet may not fit, and then use netif_xmit_stopped() when deciding whether we need to flush or we can trust xmit_more. see https://www.kernel.org/doc/html/next/networking/driver.html#transmit-path-guidelines > /* Flush the hw descriptor before writing to doorbell */ > wmb(); > - > - /* Ring Doorbell to notify the NIC there is a new packet */ > - writel(1, iq->doorbell_reg); > - iq->stats.instr_posted++; > + /* Ring Doorbell to notify the NIC of new packets */ > + writel(iq->fill_cnt, iq->doorbell_reg); > + iq->stats.instr_posted += iq->fill_cnt; > + iq->fill_cnt = 0; > return NETDEV_TX_OK;
Hi Jakub, Again, thanks for your review. > Does this guarantee that a full-sized skb can be accommodated? >> I assume by full-sized skb you mean a non-linear skb with MAX_SG_FRAGS elements in frags array. Yes, this can be accommodated and the hardware uses separate SG list memory to siphon these skb frags instead of obtaining them from the same tx hardware queue. What I'm trying to say is, this means that a single tx descriptor will be enough for a full-sized skb as well, as hardware can pick up SG frags from separate memory and doesn't require separate descriptors. >If so - consider stopping stopping the queue when the condition is not true. >> We do stop the queue if tx queue is full, as in octep_iq_full_check earlier on. >The recommended way of implementing 'driver flow control' is to stop the queue once next packet may not fit, and then use netif_xmit_stopped() when deciding whether we need to flush or we can trust xmit_more. see https://urldefense.proofpoint.com/v2/url?u=https-3A__www.kernel.org_doc_html_next_networking_driver.html-23transmit-2Dpath-2Dguidelines&d=DwICAg&c=nKjWec2b6R0mOyPaz7xtfQ&r=1OxLD4y-oxrlgQ1rjXgWtmLz1pnaDjD96sDq-cKUwK4&m=FyJHTb5Z2u9DTFSYPU38S5kPcP5KvwGWzY-DPcqOl1gdnm7ToZhTFpyvhLMqh1hd&s=dBMmwfWKAi0UH3nrz7j9kYnAodDjuN3LZ5tC2aL_Prs&e= >> In the skeleton code above, as I understand each tx desc holds a skb frag and hence there can be possibility of receiving a full-sized skb, stopping the queue but on receiving another normal skb we should observe our queue to be stopped. This doesn't arise in our case as even if the skb is full-sized, it will only use a single tx descriptor so we can be sure if queue has been stopped, the write index will only be updated once posted (and read) tx descriptors are processed in napi context and queues awoken. Please correct me if I'm wrong anywhere (sorry if so) to further my understanding, and again thanks for your time!
On Thu, Oct 26, 2023 at 9:58 AM Shinas Rasheed <srasheed@marvell.com> wrote: > > Hi Jakub, > > Again, thanks for your review. > > > Does this guarantee that a full-sized skb can be accommodated? > >> I assume by full-sized skb you mean a non-linear skb with MAX_SG_FRAGS elements in frags array. Yes, this can be accommodated and the hardware uses separate SG list memory to siphon these skb frags instead of obtaining them from the same tx hardware queue. What I'm trying to say is, this means that a single tx descriptor will be enough for a full-sized skb as well, as hardware can pick up SG frags from separate memory and doesn't require separate descriptors. > > >If so - consider stopping stopping the queue when the condition is not true. > >> We do stop the queue if tx queue is full, as in octep_iq_full_check earlier on. > > >The recommended way of implementing 'driver flow control' > is to stop the queue once next packet may not fit, and then use > netif_xmit_stopped() when deciding whether we need to flush or we can > trust xmit_more. see > https://urldefense.proofpoint.com/v2/url?u=https-3A__www.kernel.org_doc_html_next_networking_driver.html-23transmit-2Dpath-2Dguidelines&d=DwICAg&c=nKjWec2b6R0mOyPaz7xtfQ&r=1OxLD4y-oxrlgQ1rjXgWtmLz1pnaDjD96sDq-cKUwK4&m=FyJHTb5Z2u9DTFSYPU38S5kPcP5KvwGWzY-DPcqOl1gdnm7ToZhTFpyvhLMqh1hd&s=dBMmwfWKAi0UH3nrz7j9kYnAodDjuN3LZ5tC2aL_Prs&e= > > >> In the skeleton code above, as I understand each tx desc holds a skb frag and hence there can be possibility of receiving a full-sized skb, stopping the queue but on receiving another normal skb we should observe our queue to be stopped. This doesn't arise in our case as even if the skb is full-sized, it will only use a single tx descriptor so we can be sure if queue has been stopped, the write index will only be updated once posted (and read) tx descriptors are processed in napi context and queues awoken. > > Please correct me if I'm wrong anywhere (sorry if so) to further my understanding, and again thanks for your time! Fact that octep_start_xmit() can return NETDEV_TX_BUSY is very suspicious. I do not think a driver can implement xmit_more and keep NETDEV_TX_BUSY at the same time. Please make sure to remove NETDEV_TX_BUSY first, by stopping the queue earlier.
On Thu, 26 Oct 2023 07:57:54 +0000 Shinas Rasheed wrote: > >The recommended way of implementing 'driver flow control' > is to stop the queue once next packet may not fit, and then use > netif_xmit_stopped() when deciding whether we need to flush or we can > trust xmit_more. see > https://urldefense.proofpoint.com/v2/url?u=https-3A__www.kernel.org_doc_html_next_networking_driver.html-23transmit-2Dpath-2Dguidelines&d=DwICAg&c=nKjWec2b6R0mOyPaz7xtfQ&r=1OxLD4y-oxrlgQ1rjXgWtmLz1pnaDjD96sDq-cKUwK4&m=FyJHTb5Z2u9DTFSYPU38S5kPcP5KvwGWzY-DPcqOl1gdnm7ToZhTFpyvhLMqh1hd&s=dBMmwfWKAi0UH3nrz7j9kYnAodDjuN3LZ5tC2aL_Prs&e= > > >> In the skeleton code above, as I understand each tx desc holds a skb frag and hence there can be possibility of receiving a full-sized skb, stopping the queue but on receiving another normal skb we should observe our queue to be stopped. This doesn't arise in our case as even if the skb is full-sized, it will only use a single tx descriptor so we can be sure if queue has been stopped, the write index will only be updated once posted (and read) tx descriptors are processed in napi context and queues awoken. > > Please correct me if I'm wrong anywhere (sorry if so) to further my understanding, and again thanks for your time! Could you please do some training on how to use normal / mailing list style email at Marvell? Multiple people from Marvell can't quote replies correctly, it makes it hard to have a conversation and help y'all.
> -----Original Message----- > From: Jakub Kicinski <kuba@kernel.org> > Sent: Thursday, October 26, 2023 8:15 PM > To: Shinas Rasheed <srasheed@marvell.com> > Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org; Haseeb Gani > <hgani@marvell.com>; Vimlesh Kumar <vimleshk@marvell.com>; > egallen@redhat.com; mschmidt@redhat.com; pabeni@redhat.com; > horms@kernel.org; davem@davemloft.net; wizhao@redhat.com; > konguyen@redhat.com; Veerasenareddy Burru <vburru@marvell.com>; > Sathesh B Edara <sedara@marvell.com>; Eric Dumazet > <edumazet@google.com> > Subject: Re: [EXT] Re: [PATCH net-next v2 3/4] octeon_ep: implement > xmit_more in transmit > > On Thu, 26 Oct 2023 07:57:54 +0000 Shinas Rasheed wrote: > > >The recommended way of implementing 'driver flow control' > > is to stop the queue once next packet may not fit, and then use > > netif_xmit_stopped() when deciding whether we need to flush or we can > > trust xmit_more. see > > https://urldefense.proofpoint.com/v2/url?u=https- > 3A__www.kernel.org_doc_html_next_networking_driver.html-23transmit- > 2Dpath-2Dguidelines&d=DwICAg&c=nKjWec2b6R0mOyPaz7xtfQ&r=1OxLD4y- > oxrlgQ1rjXgWtmLz1pnaDjD96sDq- > cKUwK4&m=FyJHTb5Z2u9DTFSYPU38S5kPcP5KvwGWzY- > DPcqOl1gdnm7ToZhTFpyvhLMqh1hd&s=dBMmwfWKAi0UH3nrz7j9kYnAodDj > uN3LZ5tC2aL_Prs&e= > > > > >> In the skeleton code above, as I understand each tx desc holds a skb frag > and hence there can be possibility of receiving a full-sized skb, stopping the > queue but on receiving another normal skb we should observe our queue to > be stopped. This doesn't arise in our case as even if the skb is full-sized, it will > only use a single tx descriptor so we can be sure if queue has been stopped, > the write index will only be updated once posted (and read) tx descriptors > are processed in napi context and queues awoken. > > > > Please correct me if I'm wrong anywhere (sorry if so) to further my > understanding, and again thanks for your time! > > Could you please do some training on how to use normal / mailing list > style email at Marvell? Multiple people from Marvell can't quote > replies correctly, it makes it hard to have a conversation and help > y'all. Hi Jacub, apologizing for format errors on my part, will try to rectify in coming mails. Sorry again. > -----Original Message----- > From: Eric Dumazet <edumazet@google.com> > Sent: Thursday, October 26, 2023 1:59 PM > To: Shinas Rasheed <srasheed@marvell.com> > Cc: Jakub Kicinski <kuba@kernel.org>; netdev@vger.kernel.org; linux- > kernel@vger.kernel.org; Haseeb Gani <hgani@marvell.com>; Vimlesh Kumar > <vimleshk@marvell.com>; egallen@redhat.com; mschmidt@redhat.com; > pabeni@redhat.com; horms@kernel.org; davem@davemloft.net; > wizhao@redhat.com; konguyen@redhat.com; Veerasenareddy Burru > <vburru@marvell.com>; Sathesh B Edara <sedara@marvell.com> > Subject: Re: [EXT] Re: [PATCH net-next v2 3/4] octeon_ep: implement > xmit_more in transmit > > Fact that octep_start_xmit() can return NETDEV_TX_BUSY is very suspicious. > > I do not think a driver can implement xmit_more and keep > NETDEV_TX_BUSY at the same time. > > Please make sure to remove NETDEV_TX_BUSY first, by stopping the queue > earlier. Hi Eric, I think I understand your point and shall submit an updated patch. Thanks your time!
From: Shinas Rasheed > Sent: 24 October 2023 15:51 > > Add xmit_more handling in tx datapath for octeon_ep pf. > ... > - > - /* Ring Doorbell to notify the NIC there is a new packet */ > - writel(1, iq->doorbell_reg); > - iq->stats.instr_posted++; > + /* Ring Doorbell to notify the NIC of new packets */ > + writel(iq->fill_cnt, iq->doorbell_reg); > + iq->stats.instr_posted += iq->fill_cnt; > + iq->fill_cnt = 0; > return NETDEV_TX_OK; Does that really need the count? A 'doorbell' register usually just tells the MAC engine to go and look at the transmit ring. It then continues to process transmits until it fails to find a packet. So if the transmit is active you don't need to set the bit. (Although that is actually rather hard to detect.) The 'xmit_more' flag is useful if (the equivalent of) writing the doorbell register is expensive since it can be delayed to a later frame and only done once - adding a slight latency to the earlier transmits if the mac engine was idle. I'm not sure how much (if any) performance gain you actually get from avoiding the writel(). Single PCIe writes are 'posted' and pretty much completely asynchronous. The other problem I've seen is that netdev_xmit_more() is the state of the queue when the transmit was started, not the current state. If a packet is added while the earlier transmit setup code is running (setting up the descriptors etc) the it isn't set. So the fast path doesn't get taken. David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
Hi, I understand the window is closed, but just replying to a pending comment on the thread. > -----Original Message----- > From: David Laight <David.Laight@ACULAB.COM> > ---------------------------------------------------------------------- > From: Shinas Rasheed > > Sent: 24 October 2023 15:51 > > > > Add xmit_more handling in tx datapath for octeon_ep pf. > > > ... > > - > > - /* Ring Doorbell to notify the NIC there is a new packet */ > > - writel(1, iq->doorbell_reg); > > - iq->stats.instr_posted++; > > + /* Ring Doorbell to notify the NIC of new packets */ > > + writel(iq->fill_cnt, iq->doorbell_reg); > > + iq->stats.instr_posted += iq->fill_cnt; > > + iq->fill_cnt = 0; > > return NETDEV_TX_OK; > > Does that really need the count? > A 'doorbell' register usually just tells the MAC engine > to go and look at the transmit ring. > It then continues to process transmits until it fails > to find a packet. > So if the transmit is active you don't need to set the bit. > (Although that is actually rather hard to detect.) The way the octeon hardware works is that it expects number of newly updated packets to be written to the doorbell register, which effectively increments the doorbell count which shall be decremented by hardware as it reads these packets. So in essence, the doorbell count also indicates outstanding packets to be read by hardware. > The 'xmit_more' flag is useful if (the equivalent of) writing > the doorbell register is expensive since it can be delayed > to a later frame and only done once - adding a slight latency > to the earlier transmits if the mac engine was idle. > > I'm not sure how much (if any) performance gain you actually > get from avoiding the writel(). > Single PCIe writes are 'posted' and pretty much completely > asynchronous. Can you elaborate what you are suggesting here to do? The driver is trying to make use of the 'xmit_more' hint from the network stack, as any network driver might opt to do. I think avoiding continuous PCIe posts for each packet shall still be wasteful as the hardware can bulk read from the queue if we give it a batch of packets. > The other problem I've seen is that netdev_xmit_more() is > the state of the queue when the transmit was started, not > the current state. > If a packet is added while the earlier transmit setup code > is running (setting up the descriptors etc) the it isn't set. > So the fast path doesn't get taken. By the next packet the kernel sends, the xmit_more should be set as far I understand, right? (as the xmit_more bool is set if skb->next is present, if the transmit path follows dev_hard_start_xmit).
From: Shinas Rasheed <srasheed@marvell.com> > Sent: 30 October 2023 14:15 > > Hi, > > I understand the window is closed, but just replying to a pending comment on the thread. > > > -----Original Message----- > > From: David Laight <David.Laight@ACULAB.COM> > > ---------------------------------------------------------------------- > > From: Shinas Rasheed > > > Sent: 24 October 2023 15:51 > > > > > > Add xmit_more handling in tx datapath for octeon_ep pf. > > > > > ... > > > - > > > - /* Ring Doorbell to notify the NIC there is a new packet */ > > > - writel(1, iq->doorbell_reg); > > > - iq->stats.instr_posted++; > > > + /* Ring Doorbell to notify the NIC of new packets */ > > > + writel(iq->fill_cnt, iq->doorbell_reg); > > > + iq->stats.instr_posted += iq->fill_cnt; > > > + iq->fill_cnt = 0; > > > return NETDEV_TX_OK; > > > > Does that really need the count? > > A 'doorbell' register usually just tells the MAC engine > > to go and look at the transmit ring. > > It then continues to process transmits until it fails > > to find a packet. > > So if the transmit is active you don't need to set the bit. > > (Although that is actually rather hard to detect.) > > The way the octeon hardware works is that it expects number of newly updated packets > to be written to the doorbell register,which effectively increments the doorbell > count which shall be decremented by hardware as it reads these packets. So in essence, > the doorbell count also indicates outstanding packets to be read by hardware. Unusual - I wouldn't call that a doorbell register. > > The 'xmit_more' flag is useful if (the equivalent of) writing > > the doorbell register is expensive since it can be delayed > > to a later frame and only done once - adding a slight latency > > to the earlier transmits if the mac engine was idle. > > > > I'm not sure how much (if any) performance gain you actually > > get from avoiding the writel(). > > Single PCIe writes are 'posted' and pretty much completely > > asynchronous. > > Can you elaborate what you are suggesting here to do? The driver is trying > to make use of the 'xmit_more' hint from the network stack, as any network > driver might opt to do. There are some drivers where waking up the MAC engine is expensive. If you need to do a PCIe read then they are expensive. There might also be drivers that need to send a USB message. I don't actually know which one it was added for. > I think avoiding continuous PCIe posts for each packet shall still be wasteful > as the hardware can bulk read from the queue if we give it a batch of packets. If you do writes for every packet then the hardware can get on with sending the first packet and might be able to do bulk reads for the next packet(s) when that finishes. The extra code you are adding could easily (waving hands) be more expensive than the posted PCIe write. (Especially if you have to add an atomic operation.) Unless, of course, you have to wait for it to send that batch of packets before you can give it any more. Which would be rather entirely broken and would really require you do the write in the end-of-transit path. > > The other problem I've seen is that netdev_xmit_more() is > > the state of the queue when the transmit was started, not > > the current state. > > If a packet is added while the earlier transmit setup code > > is running (setting up the descriptors etc) the it isn't set. > > So the fast path doesn't get taken. > > By the next packet the kernel sends, the xmit_more should be set > as far I understand, right? (as the xmit_more bool is set if skb->next > is present, if the transmit path follows dev_hard_start_xmit). The loop is something like: while (get_packet()) { per_cpu->xmit_more = !queue_empty(); if (transmit_packet() != TX_OK) break; } So if a packet is added while all the transmit setup code is running it isn't detected. I managed to repeatedly get that to loop when xmit_more wasn't set and in a driver where the 'doorbell' write wasn't entirely trivial. David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
Hi David, > -----Original Message----- > From: David Laight <David.Laight@ACULAB.COM> > Sent: Monday, October 30, 2023 9:00 PM > To: Shinas Rasheed <srasheed@marvell.com>; netdev@vger.kernel.org; > linux-kernel@vger.kernel.org > > > > - /* Ring Doorbell to notify the NIC there is a new packet */ > > > > - writel(1, iq->doorbell_reg); > > > > - iq->stats.instr_posted++; > > > > + /* Ring Doorbell to notify the NIC of new packets */ > > > > + writel(iq->fill_cnt, iq->doorbell_reg); > > > > + iq->stats.instr_posted += iq->fill_cnt; > > > > + iq->fill_cnt = 0; > > > > return NETDEV_TX_OK; > > > > > > Does that really need the count? > > > A 'doorbell' register usually just tells the MAC engine > > > to go and look at the transmit ring. > > > It then continues to process transmits until it fails > > > to find a packet. > > > So if the transmit is active you don't need to set the bit. > > > (Although that is actually rather hard to detect.) > > > > The way the octeon hardware works is that it expects number of newly > updated packets > > to be written to the doorbell register,which effectively increments the > doorbell > > count which shall be decremented by hardware as it reads these packets. > So in essence, > > the doorbell count also indicates outstanding packets to be read by > hardware. > > Unusual - I wouldn't call that a doorbell register. I double checked in earlier implementations as well as the reference manuals. This is how the hardware register is prescribed to be used. > If you do writes for every packet then the hardware can get on with > sending the first packet and might be able to do bulk reads > for the next packet(s) when that finishes. > > The extra code you are adding could easily (waving hands) > be more expensive than the posted PCIe write. > (Especially if you have to add an atomic operation.) > > Unless, of course, you have to wait for it to send that batch > of packets before you can give it any more. > Which would be rather entirely broken and would really require > you do the write in the end-of-transit path. The atomic operation is replaced in the very next patch. Other than that, what is it that you suggest we should 'fix' in this implementation of handling xmit_more? > The loop is something like: > while (get_packet()) { > per_cpu->xmit_more = !queue_empty(); > if (transmit_packet() != TX_OK) > break; > } > So if a packet is added while all the transmit setup code is running > it isn't detected. > I managed to repeatedly get that to loop when xmit_more wasn't set > and in a driver where the 'doorbell' write wasn't entirely trivial. How are you suggesting we handle or diagnose such a case, in the driver? Can you provide an example reference which handles adequately this special case? When the net-next opens again, I can submit the patches again with the added changes you suggested. Thanks for reviewing! Shinas
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_config.h b/drivers/net/ethernet/marvell/octeon_ep/octep_config.h index 1622a6ebf036..ed8b1ace56b9 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_config.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_config.h @@ -15,7 +15,7 @@ /* Tx Queue: maximum descriptors per ring */ #define OCTEP_IQ_MAX_DESCRIPTORS 1024 /* Minimum input (Tx) requests to be enqueued to ring doorbell */ -#define OCTEP_DB_MIN 1 +#define OCTEP_DB_MIN 8 /* Packet threshold for Tx queue interrupt */ #define OCTEP_IQ_INTR_THRESHOLD 0x0 diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c index 1c02304677c9..1a88a6bf0598 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c @@ -818,6 +818,7 @@ static netdev_tx_t octep_start_xmit(struct sk_buff *skb, struct octep_iq *iq; skb_frag_t *frag; u16 nr_frags, si; + int xmit_more; u16 q_no, wi; if (skb_put_padto(skb, ETH_ZLEN)) @@ -895,18 +896,28 @@ static netdev_tx_t octep_start_xmit(struct sk_buff *skb, } netdev_tx_sent_queue(iq->netdev_q, skb->len); + + xmit_more = netdev_xmit_more(); + skb_tx_timestamp(skb); atomic_inc(&iq->instr_pending); + iq->fill_cnt++; wi++; if (wi == iq->max_count) wi = 0; iq->host_write_index = wi; + if (xmit_more && + (atomic_read(&iq->instr_pending) < + (iq->max_count - OCTEP_WAKE_QUEUE_THRESHOLD)) && + iq->fill_cnt < iq->fill_threshold) + return NETDEV_TX_OK; + /* Flush the hw descriptor before writing to doorbell */ wmb(); - - /* Ring Doorbell to notify the NIC there is a new packet */ - writel(1, iq->doorbell_reg); - iq->stats.instr_posted++; + /* Ring Doorbell to notify the NIC of new packets */ + writel(iq->fill_cnt, iq->doorbell_reg); + iq->stats.instr_posted += iq->fill_cnt; + iq->fill_cnt = 0; return NETDEV_TX_OK; dma_map_sg_err: