From patchwork Tue Mar 8 12:35:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xuan Zhuo X-Patchwork-Id: 12773725 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DC6E0C3525A for ; Tue, 8 Mar 2022 12:38:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346956AbiCHMjJ (ORCPT ); Tue, 8 Mar 2022 07:39:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35812 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347004AbiCHMhk (ORCPT ); Tue, 8 Mar 2022 07:37:40 -0500 Received: from out30-42.freemail.mail.aliyun.com (out30-42.freemail.mail.aliyun.com [115.124.30.42]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B4A0F47057; Tue, 8 Mar 2022 04:36:17 -0800 (PST) X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R151e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=e01e04423;MF=xuanzhuo@linux.alibaba.com;NM=1;PH=DS;RN=34;SR=0;TI=SMTPD_---0V6eSqDW_1646742970; Received: from localhost(mailfrom:xuanzhuo@linux.alibaba.com fp:SMTPD_---0V6eSqDW_1646742970) by smtp.aliyun-inc.com(127.0.0.1); Tue, 08 Mar 2022 20:36:12 +0800 From: Xuan Zhuo To: virtualization@lists.linux-foundation.org, netdev@vger.kernel.org Cc: Jeff Dike , Richard Weinberger , Anton Ivanov , "Michael S. Tsirkin" , Jason Wang , "David S. Miller" , Jakub Kicinski , Hans de Goede , Mark Gross , Vadim Pasternak , Bjorn Andersson , Mathieu Poirier , Cornelia Huck , Halil Pasic , Heiko Carstens , Vasily Gorbik , Christian Borntraeger , Alexander Gordeev , Sven Schnelle , Alexei Starovoitov , Daniel Borkmann , Jesper Dangaard Brouer , John Fastabend , Johannes Berg , Vincent Whitchurch , Xuan Zhuo , linux-um@lists.infradead.org, platform-driver-x86@vger.kernel.org, linux-remoteproc@vger.kernel.org, linux-s390@vger.kernel.org, kvm@vger.kernel.org, bpf@vger.kernel.org Subject: [PATCH v7 24/26] virtio_net: support rx/tx queue reset Date: Tue, 8 Mar 2022 20:35:16 +0800 Message-Id: <20220308123518.33800-25-xuanzhuo@linux.alibaba.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20220308123518.33800-1-xuanzhuo@linux.alibaba.com> References: <20220308123518.33800-1-xuanzhuo@linux.alibaba.com> MIME-Version: 1.0 X-Git-Hash: f06b131dbfed Precedence: bulk List-ID: X-Mailing-List: linux-remoteproc@vger.kernel.org This patch implements the reset function of the rx, tx queues. Based on this function, it is possible to modify the ring num of the queue. And quickly recycle the buffer in the queue. In the process of the queue disable, in theory, as long as virtio supports queue reset, there will be no exceptions. However, in the process of the queue enable, there may be exceptions due to memory allocation. In this case, vq is not available, but we still have to execute napi_enable(). Because napi_disable is similar to a lock, napi_enable must be called after calling napi_disable. Signed-off-by: Xuan Zhuo --- drivers/net/virtio_net.c | 107 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 409a8e180918..ffff323dcef0 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -251,6 +251,11 @@ struct padded_vnet_hdr { char padding[4]; }; +static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi, + struct send_queue *sq); +static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi, + struct receive_queue *rq); + static bool is_xdp_frame(void *ptr) { return (unsigned long)ptr & VIRTIO_XDP_FLAG; @@ -1369,6 +1374,9 @@ static void virtnet_napi_enable(struct virtqueue *vq, struct napi_struct *napi) { napi_enable(napi); + if (vq->reset) + return; + /* If all buffers were filled by other side before we napi_enabled, we * won't get another interrupt, so process any outstanding packets now. * Call local_bh_enable after to trigger softIRQ processing. @@ -1413,6 +1421,10 @@ static void refill_work(struct work_struct *work) struct receive_queue *rq = &vi->rq[i]; napi_disable(&rq->napi); + if (rq->vq->reset) { + virtnet_napi_enable(rq->vq, &rq->napi); + continue; + } still_empty = !try_fill_recv(vi, rq, GFP_KERNEL); virtnet_napi_enable(rq->vq, &rq->napi); @@ -1523,6 +1535,9 @@ static void virtnet_poll_cleantx(struct receive_queue *rq) if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index)) return; + if (sq->vq->reset) + return; + if (__netif_tx_trylock(txq)) { do { virtqueue_disable_cb(sq->vq); @@ -1769,6 +1784,98 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } +static int virtnet_rx_vq_reset(struct virtnet_info *vi, + struct receive_queue *rq, u32 ring_num) +{ + int err; + + /* stop napi */ + napi_disable(&rq->napi); + + /* reset the queue */ + err = virtio_reset_vq(rq->vq); + if (err) + goto err; + + /* free bufs */ + virtnet_rq_free_unused_bufs(vi, rq); + + /* reset vring. */ + err = virtqueue_reset_vring(rq->vq, ring_num); + if (err) + goto err; + + /* enable reset queue */ + err = virtio_enable_resetq(rq->vq); + if (err) + goto err; + + /* fill recv */ + if (!try_fill_recv(vi, rq, GFP_KERNEL)) + schedule_delayed_work(&vi->refill, 0); + + /* enable napi */ + virtnet_napi_enable(rq->vq, &rq->napi); + return 0; + +err: + netdev_err(vi->dev, + "reset rx reset vq fail: rx queue index: %ld err: %d\n", + rq - vi->rq, err); + virtnet_napi_enable(rq->vq, &rq->napi); + return err; +} + +static int virtnet_tx_vq_reset(struct virtnet_info *vi, + struct send_queue *sq, u32 ring_num) +{ + struct netdev_queue *txq; + int err, qindex; + + qindex = sq - vi->sq; + + txq = netdev_get_tx_queue(vi->dev, qindex); + __netif_tx_lock_bh(txq); + + /* stop tx queue and napi */ + netif_stop_subqueue(vi->dev, qindex); + virtnet_napi_tx_disable(&sq->napi); + + __netif_tx_unlock_bh(txq); + + /* reset the queue */ + err = virtio_reset_vq(sq->vq); + if (err) { + netif_start_subqueue(vi->dev, qindex); + goto err; + } + + /* free bufs */ + virtnet_sq_free_unused_bufs(vi, sq); + + /* reset vring. */ + err = virtqueue_reset_vring(sq->vq, ring_num); + if (err) + goto err; + + /* enable reset queue */ + err = virtio_enable_resetq(sq->vq); + if (err) + goto err; + + /* start tx queue and napi */ + netif_start_subqueue(vi->dev, qindex); + virtnet_napi_tx_enable(vi, sq->vq, &sq->napi); + return 0; + +err: + netdev_err(vi->dev, + "reset tx reset vq fail: tx queue index: %ld err: %d\n", + sq - vi->sq, err); + virtnet_napi_tx_enable(vi, sq->vq, &sq->napi); + return err; +} + /* * Send command via the control virtqueue and check status. Commands * supported by the hypervisor, as indicated by feature bits, should