From patchwork Mon Dec 12 08:21:14 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Puiu X-Patchwork-Id: 17860 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 975A62BA4; Mon, 12 Dec 2016 09:22:05 +0100 (CET) Received: from mail-wm0-f68.google.com (mail-wm0-f68.google.com [74.125.82.68]) by dpdk.org (Postfix) with ESMTP id D84E610A7 for ; Mon, 12 Dec 2016 09:22:03 +0100 (CET) Received: by mail-wm0-f68.google.com with SMTP id u144so9565816wmu.0 for ; Mon, 12 Dec 2016 00:22:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=GM3d/GVVjFQIaPmLaGzY8OChAlG3J20+FCpjTZMsDAY=; b=DNQh7Nf8B1R4JaOY+UUf7VEe8x9yPd0tut2BPfvpKJ/qqIhac+1/VpK9uKo/u3h26O 1hyWLmjaX7GTX2OxY3IjMsAJV+Cd1Da9HIqU0jpH4FIV/ifsLc1Pt3TqbfXsBrN3gCZC 4dlr+Q0RT8WaI2SmJCZfo1Jev7CqVoYkczlVTVrEZ4aBUD9Ia4VxNFpYTWNlfn9A6asZ C4F5kuaL1pYE9SdykSTbEcJ8I28Z09CIiU49BaARzuCqyeeG8NOoQUq1QdG4ohSCMQUr d6PvMfoDAJ+s+AwXlOKls5t7kKYBHHW8ZwHj3690gcUrgKl52CSqCU6uzY4juH6zC5QJ 6/kw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=GM3d/GVVjFQIaPmLaGzY8OChAlG3J20+FCpjTZMsDAY=; b=kc8Pjxb4xWyVYt//bKnIWd0K3Wrjrej/mnm7Mj/QAML9jhcWOF8r+m82W1oXKYN1G5 Kw641/IPtgl4TgMiGfIpgH/VScm86JuuiH8Dx099s7hcmlNZHKHgXsFyzkHXivOjPJ+j SOidOSrz+TptIMYZzny/G53Jm0i5HAJfvImM8Nnq25OXe6f7oJ7rcYA+U1F+lMiYRDf+ bjsJ7jyCDP+0WB7C9+ndnlMH3RzHeoq0cJgIO6XIFsN7ZfEHwVViAqOA60g5TTh2leW/ fl0UZtPY6eWfHhzkFVBBS25gNet/NZV09xChiPWij0dw7DgUiXBwhrLXVgHXyhU8k8Xn n1xg== X-Gm-Message-State: AKaTC02zNXLvts1oJmIqawZYDuHIwib4TXeUU5N9Pf4Ckpa9HMQXECxyMAwp9oid1+CEqA== X-Received: by 10.28.8.202 with SMTP id 193mr15890619wmi.101.1481530923491; Mon, 12 Dec 2016 00:22:03 -0800 (PST) Received: from spuiu-vm2.anuesystems.local ([109.100.41.154]) by smtp.gmail.com with ESMTPSA id f134sm34174388wmf.19.2016.12.12.00.22.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 12 Dec 2016 00:22:02 -0800 (PST) From: Stefan Puiu To: dev@dpdk.org Cc: yongwang@vmware.com, mac_leehk@yahoo.com.hk, Stefan Puiu Date: Mon, 12 Dec 2016 10:21:14 +0200 Message-Id: <1481530874-8660-1-git-send-email-stefan.puiu@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1479120376-48723-1-git-send-email-stefan.puiu@gmail.com> References: <1479120376-48723-1-git-send-email-stefan.puiu@gmail.com> Subject: [dpdk-dev] [PATCH v2] vmxnet3: fix Rx deadlock X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Our use case is that we have an app that needs to keep mbufs around for a while. We've seen cases when calling vmxnet3_post_rx_bufs() from vmxet3_recv_pkts(), it might not succeed to add any mbufs to any RX descriptors (where it returns -err). Since there are no mbufs that the virtual hardware can use, no packets will be received after this; nobody retries this later, so the driver gets stuck in this state. I call this a deadlock for lack of a better term - the virtual HW waits for free mbufs, while the app waits for the hardware to notify it for data. Note that after this, the app can't recover. This fix is a rework of this patch by Marco Lee: http://dpdk.org/dev/patchwork/patch/6575/. I had to forward port it, address review comments and also reverted the allocation failure handing to the first version of the patch (http://dpdk.org/ml/archives/dev/2015-July/022079.html), since that's the only approach that seems to work, and seems to be what other drivers are doing (I checked ixgbe and em). Reusing the mbuf that's getting passed to the application doesn't seem to make sense, and it was causing weird issues in our app. Also, reusing rxm without checking if it's NULL could cause the code to crash. v2: - address review comments, reworded description a bit --- drivers/net/vmxnet3/vmxnet3_rxtx.c | 39 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/drivers/net/vmxnet3/vmxnet3_rxtx.c b/drivers/net/vmxnet3/vmxnet3_rxtx.c index b109168..93db10f 100644 --- a/drivers/net/vmxnet3/vmxnet3_rxtx.c +++ b/drivers/net/vmxnet3/vmxnet3_rxtx.c @@ -518,6 +518,32 @@ return nb_tx; } +static inline void +vmxnet3_renew_desc(vmxnet3_rx_queue_t *rxq, uint8_t ring_id, + struct rte_mbuf *mbuf) +{ + uint32_t val = 0; + struct vmxnet3_cmd_ring *ring = &rxq->cmd_ring[ring_id]; + struct Vmxnet3_RxDesc *rxd = + (struct Vmxnet3_RxDesc *)(ring->base + ring->next2fill); + vmxnet3_buf_info_t *buf_info = &ring->buf_info[ring->next2fill]; + + if (ring_id == 0) + val = VMXNET3_RXD_BTYPE_HEAD; + else + val = VMXNET3_RXD_BTYPE_BODY; + + buf_info->m = mbuf; + buf_info->len = (uint16_t)(mbuf->buf_len - RTE_PKTMBUF_HEADROOM); + buf_info->bufPA = rte_mbuf_data_dma_addr_default(mbuf); + + rxd->addr = buf_info->bufPA; + rxd->btype = val; + rxd->len = buf_info->len; + rxd->gen = ring->gen; + + vmxnet3_cmd_ring_adv_next2fill(ring); +} /* * Allocates mbufs and clusters. Post rx descriptors with buffer details * so that device can receive packets in those buffers. @@ -657,9 +683,18 @@ } while (rcd->gen == rxq->comp_ring.gen) { + struct rte_mbuf *newm; + if (nb_rx >= nb_pkts) break; + newm = rte_mbuf_raw_alloc(rxq->mp); + if (unlikely(newm == NULL)) { + PMD_RX_LOG(ERR, "Error allocating mbuf"); + rxq->stats.rx_buf_alloc_failure++; + break; + } + idx = rcd->rxdIdx; ring_idx = (uint8_t)((rcd->rqID == rxq->qid1) ? 0 : 1); rxd = (Vmxnet3_RxDesc *)rxq->cmd_ring[ring_idx].base + idx; @@ -759,8 +794,8 @@ VMXNET3_INC_RING_IDX_ONLY(rxq->cmd_ring[ring_idx].next2comp, rxq->cmd_ring[ring_idx].size); - /* It's time to allocate some new buf and renew descriptors */ - vmxnet3_post_rx_bufs(rxq, ring_idx); + /* It's time to renew descriptors */ + vmxnet3_renew_desc(rxq, ring_idx, newm); if (unlikely(rxq->shared->ctrl.updateRxProd)) { VMXNET3_WRITE_BAR0_REG(hw, rxprod_reg[ring_idx] + (rxq->queue_id * VMXNET3_REG_ALIGN), rxq->cmd_ring[ring_idx].next2fill);