* [dpdk-dev] [PATCH 0/2] net/netvsc: patches @ 2020-03-16 23:56 Stephen Hemminger 2020-03-16 23:56 ` [dpdk-dev] [PATCH 1/2] net/netvsc: handle receive packets during multi-channel setup Stephen Hemminger ` (5 more replies) 0 siblings, 6 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-16 23:56 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger A couple of fixes for netvsc PMD. The first is more serious than the second. Stephen Hemminger (2): net/netvsc: handle receive packets during multi-channel setup net/netvsc: avoid mixing buffered and direct packets drivers/net/netvsc/hn_ethdev.c | 1 + drivers/net/netvsc/hn_nvs.c | 40 ++++++++++++++++++++++++++++++++-- drivers/net/netvsc/hn_rxtx.c | 15 ++++++------- drivers/net/netvsc/hn_var.h | 1 + 4 files changed, 47 insertions(+), 10 deletions(-) -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH 1/2] net/netvsc: handle receive packets during multi-channel setup 2020-03-16 23:56 [dpdk-dev] [PATCH 0/2] net/netvsc: patches Stephen Hemminger @ 2020-03-16 23:56 ` Stephen Hemminger 2020-03-16 23:56 ` [dpdk-dev] [PATCH 2/2] net/netvsc: avoid mixing buffered and direct packets Stephen Hemminger ` (4 subsequent siblings) 5 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-16 23:56 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger, stable It is possible for a packet to arrive during the configuration process when setting up multiple queue mode. This would cause configure to fail; fix by just ignoring receive packets while waiting for control commands. Add a spinlock to ensure that two control operations are not attempted at once. Fixes: 4e9c73e96e83 ("net/netvsc: add Hyper-V network device") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_ethdev.c | 1 + drivers/net/netvsc/hn_nvs.c | 40 ++++++++++++++++++++++++++++++++-- drivers/net/netvsc/hn_var.h | 1 + 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c index 564620748daf..01e69de6f3e2 100644 --- a/drivers/net/netvsc/hn_ethdev.c +++ b/drivers/net/netvsc/hn_ethdev.c @@ -951,6 +951,7 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) hv->latency = HN_CHAN_LATENCY_NS; hv->max_queues = 1; rte_spinlock_init(&hv->vf_lock); + rte_spinlock_init(&hv->nvs_lock); hv->vf_port = HN_INVALID_PORT; err = hn_parse_args(eth_dev); diff --git a/drivers/net/netvsc/hn_nvs.c b/drivers/net/netvsc/hn_nvs.c index 6b518685ab6f..f56692f4d605 100644 --- a/drivers/net/netvsc/hn_nvs.c +++ b/drivers/net/netvsc/hn_nvs.c @@ -54,7 +54,7 @@ static int hn_nvs_req_send(struct hn_data *hv, } static int -hn_nvs_execute(struct hn_data *hv, +__hn_nvs_execute(struct hn_data *hv, void *req, uint32_t reqlen, void *resp, uint32_t resplen, uint32_t type) @@ -62,6 +62,7 @@ hn_nvs_execute(struct hn_data *hv, struct vmbus_channel *chan = hn_primary_chan(hv); char buffer[NVS_RESPSIZE_MAX]; const struct hn_nvs_hdr *hdr; + uint64_t xactid; uint32_t len; int ret; @@ -77,7 +78,7 @@ hn_nvs_execute(struct hn_data *hv, retry: len = sizeof(buffer); - ret = rte_vmbus_chan_recv(chan, buffer, &len, NULL); + ret = rte_vmbus_chan_recv(chan, buffer, &len, &xactid); if (ret == -EAGAIN) { rte_delay_us(HN_CHAN_INTERVAL_US); goto retry; @@ -88,7 +89,20 @@ hn_nvs_execute(struct hn_data *hv, return ret; } + if (len < sizeof(*hdr)) { + PMD_DRV_LOG(ERR, "response missing NVS header"); + return -EINVAL; + } + hdr = (struct hn_nvs_hdr *)buffer; + + /* Silently drop received packets while waiting for response */ + if (hdr->type == NVS_TYPE_RNDIS) { + hn_nvs_ack_rxbuf(chan, xactid); + --hv->rxbuf_outstanding; + goto retry; + } + if (hdr->type != type) { PMD_DRV_LOG(ERR, "unexpected NVS resp %#x, expect %#x", hdr->type, type); @@ -108,6 +122,28 @@ hn_nvs_execute(struct hn_data *hv, return 0; } + +/* + * Execute one control command and get the response. + * Only one command can be active on a channel at once + * Unlike BSD, DPDK does not have an interrupt context + * so the polling is required to wait for response. + */ +static int +hn_nvs_execute(struct hn_data *hv, + void *req, uint32_t reqlen, + void *resp, uint32_t resplen, + uint32_t type) +{ + int ret; + + rte_spinlock_lock(&hv->nvs_lock); + ret = __hn_nvs_execute(hv, req, reqlen, resp, resplen, type); + rte_spinlock_unlock(&hv->nvs_lock); + + return ret; +} + static int hn_nvs_doinit(struct hn_data *hv, uint32_t nvs_ver) { diff --git a/drivers/net/netvsc/hn_var.h b/drivers/net/netvsc/hn_var.h index 05bc492511ec..7434ff19bfa5 100644 --- a/drivers/net/netvsc/hn_var.h +++ b/drivers/net/netvsc/hn_var.h @@ -97,6 +97,7 @@ struct hn_data { struct rte_vmbus_device *vmbus; struct hn_rx_queue *primary; rte_spinlock_t vf_lock; + rte_spinlock_t nvs_lock; uint16_t port_id; uint16_t vf_port; -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH 2/2] net/netvsc: avoid mixing buffered and direct packets 2020-03-16 23:56 [dpdk-dev] [PATCH 0/2] net/netvsc: patches Stephen Hemminger 2020-03-16 23:56 ` [dpdk-dev] [PATCH 1/2] net/netvsc: handle receive packets during multi-channel setup Stephen Hemminger @ 2020-03-16 23:56 ` Stephen Hemminger 2020-03-18 17:33 ` [dpdk-dev] [PATCH 0/2] net/netvsc: patches Ferruh Yigit ` (3 subsequent siblings) 5 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-16 23:56 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger Putting buffered and direct packets together into one request is an unnecessary optimization. Better to split into two requests (buffered and direct). Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_rxtx.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/netvsc/hn_rxtx.c b/drivers/net/netvsc/hn_rxtx.c index 7212780c156e..aad3d8c04c7f 100644 --- a/drivers/net/netvsc/hn_rxtx.c +++ b/drivers/net/netvsc/hn_rxtx.c @@ -1362,15 +1362,14 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) } else { struct hn_txdesc *txd; - /* can send chimney data and large packet at once */ + /* Send any outstanding packets in buffer */ txd = txq->agg_txd; - if (txd) { - hn_reset_txagg(txq); - } else { - txd = hn_new_txd(hv, txq); - if (unlikely(!txd)) - break; - } + if (txd && hn_flush_txagg(txq, &need_sig)) + goto fail; + + txd = hn_new_txd(hv, txq); + if (unlikely(!txd)) + break; pkt = txd->rndis_pkt; txd->m = m; -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [dpdk-dev] [PATCH 0/2] net/netvsc: patches 2020-03-16 23:56 [dpdk-dev] [PATCH 0/2] net/netvsc: patches Stephen Hemminger 2020-03-16 23:56 ` [dpdk-dev] [PATCH 1/2] net/netvsc: handle receive packets during multi-channel setup Stephen Hemminger 2020-03-16 23:56 ` [dpdk-dev] [PATCH 2/2] net/netvsc: avoid mixing buffered and direct packets Stephen Hemminger @ 2020-03-18 17:33 ` Ferruh Yigit 2020-03-18 18:09 ` Stephen Hemminger 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 0/4] net/netvsc patches Stephen Hemminger ` (2 subsequent siblings) 5 siblings, 1 reply; 27+ messages in thread From: Ferruh Yigit @ 2020-03-18 17:33 UTC (permalink / raw) To: Stephen Hemminger, dev On 3/16/2020 11:56 PM, Stephen Hemminger wrote: > A couple of fixes for netvsc PMD. > The first is more serious than the second. > > Stephen Hemminger (2): > net/netvsc: handle receive packets during multi-channel setup > net/netvsc: avoid mixing buffered and direct packets > Series applied to dpdk-next-net/master, thanks. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [dpdk-dev] [PATCH 0/2] net/netvsc: patches 2020-03-18 17:33 ` [dpdk-dev] [PATCH 0/2] net/netvsc: patches Ferruh Yigit @ 2020-03-18 18:09 ` Stephen Hemminger 2020-03-19 9:06 ` Ferruh Yigit 0 siblings, 1 reply; 27+ messages in thread From: Stephen Hemminger @ 2020-03-18 18:09 UTC (permalink / raw) To: Ferruh Yigit; +Cc: dev On Wed, 18 Mar 2020 17:33:18 +0000 Ferruh Yigit <ferruh.yigit@intel.com> wrote: > On 3/16/2020 11:56 PM, Stephen Hemminger wrote: > > A couple of fixes for netvsc PMD. > > The first is more serious than the second. > > > > Stephen Hemminger (2): > > net/netvsc: handle receive packets during multi-channel setup > > net/netvsc: avoid mixing buffered and direct packets > > > > Series applied to dpdk-next-net/master, thanks. Could you back it out. I have v2 to send today. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [dpdk-dev] [PATCH 0/2] net/netvsc: patches 2020-03-18 18:09 ` Stephen Hemminger @ 2020-03-19 9:06 ` Ferruh Yigit 0 siblings, 0 replies; 27+ messages in thread From: Ferruh Yigit @ 2020-03-19 9:06 UTC (permalink / raw) To: Stephen Hemminger; +Cc: dev On 3/18/2020 6:09 PM, Stephen Hemminger wrote: > On Wed, 18 Mar 2020 17:33:18 +0000 > Ferruh Yigit <ferruh.yigit@intel.com> wrote: > >> On 3/16/2020 11:56 PM, Stephen Hemminger wrote: >>> A couple of fixes for netvsc PMD. >>> The first is more serious than the second. >>> >>> Stephen Hemminger (2): >>> net/netvsc: handle receive packets during multi-channel setup >>> net/netvsc: avoid mixing buffered and direct packets >>> >> >> Series applied to dpdk-next-net/master, thanks. > > Could you back it out. I have v2 to send today. > Done, dropped from next-net. ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v2 0/4] net/netvsc patches 2020-03-16 23:56 [dpdk-dev] [PATCH 0/2] net/netvsc: patches Stephen Hemminger ` (2 preceding siblings ...) 2020-03-18 17:33 ` [dpdk-dev] [PATCH 0/2] net/netvsc: patches Ferruh Yigit @ 2020-03-18 20:29 ` Stephen Hemminger 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 1/4] net/netvsc: propogate descriptor limits from VF to netvsc Stephen Hemminger ` (3 more replies) 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 0/4] net/netvsc patches Stephen Hemminger 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes Stephen Hemminger 5 siblings, 4 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-18 20:29 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger These are bug fixes for netvsc PMD mostly related to issues discovered by users of multi-queue. v2 -- simplify the locking on multi-channel setup add patches to handle single queue and tx descriptor pool Stephen Hemminger (4): net/netvsc: propogate descriptor limits from VF to netvsc net/netvsc: handle receive packets during multi-channel setup net/netvsc: split send buffers from transmit descriptors net/netvsc: don't enable RSS if only single receive queue drivers/net/netvsc/hn_ethdev.c | 22 ++- drivers/net/netvsc/hn_nvs.c | 41 +++++- drivers/net/netvsc/hn_rxtx.c | 258 ++++++++++++++++++++------------- drivers/net/netvsc/hn_var.h | 10 +- drivers/net/netvsc/hn_vf.c | 13 ++ 5 files changed, 231 insertions(+), 113 deletions(-) -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v2 1/4] net/netvsc: propogate descriptor limits from VF to netvsc 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 0/4] net/netvsc patches Stephen Hemminger @ 2020-03-18 20:29 ` Stephen Hemminger 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 2/4] net/netvsc: handle receive packets during multi-channel setup Stephen Hemminger ` (2 subsequent siblings) 3 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-18 20:29 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger, stable If application cares about descriptor limits, the netvsc device values should reflect those of the VF as well. Fixes: dc7680e8597c ("net/netvsc: support integrated VF") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_vf.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/netvsc/hn_vf.c b/drivers/net/netvsc/hn_vf.c index 7a3734cadfa4..1261b2e2ef85 100644 --- a/drivers/net/netvsc/hn_vf.c +++ b/drivers/net/netvsc/hn_vf.c @@ -167,6 +167,17 @@ hn_nvs_handle_vfassoc(struct rte_eth_dev *dev, hn_vf_remove(hv); } +static void +hn_vf_merge_desc_lim(struct rte_eth_desc_lim *lim, + const struct rte_eth_desc_lim *vf_lim) +{ + lim->nb_max = RTE_MIN(vf_lim->nb_max, lim->nb_max); + lim->nb_min = RTE_MAX(vf_lim->nb_min, lim->nb_min); + lim->nb_align = RTE_MAX(vf_lim->nb_align, lim->nb_align); + lim->nb_seg_max = RTE_MIN(vf_lim->nb_seg_max, lim->nb_seg_max); + lim->nb_mtu_seg_max = RTE_MIN(vf_lim->nb_seg_max, lim->nb_seg_max); +} + /* * Merge the info from the VF and synthetic path. * use the default config of the VF @@ -196,11 +207,13 @@ static int hn_vf_info_merge(struct rte_eth_dev *vf_dev, info->max_tx_queues); info->tx_offload_capa &= vf_info.tx_offload_capa; info->tx_queue_offload_capa &= vf_info.tx_queue_offload_capa; + hn_vf_merge_desc_lim(&info->tx_desc_lim, &vf_info.tx_desc_lim); info->min_rx_bufsize = RTE_MAX(vf_info.min_rx_bufsize, info->min_rx_bufsize); info->max_rx_pktlen = RTE_MAX(vf_info.max_rx_pktlen, info->max_rx_pktlen); + hn_vf_merge_desc_lim(&info->rx_desc_lim, &vf_info.rx_desc_lim); return 0; } -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v2 2/4] net/netvsc: handle receive packets during multi-channel setup 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 0/4] net/netvsc patches Stephen Hemminger 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 1/4] net/netvsc: propogate descriptor limits from VF to netvsc Stephen Hemminger @ 2020-03-18 20:29 ` Stephen Hemminger 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 3/4] net/netvsc: split send buffers from transmit descriptors Stephen Hemminger 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 4/4] net/netvsc: don't enable RSS if only single receive queue Stephen Hemminger 3 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-18 20:29 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger, stable It is possible for a packet to arrive during the configuration process when setting up multiple queue mode. This would cause configure to fail; fix by just ignoring receive packets while waiting for control commands. Use the receive ring lock to avoid possible races between oddly behaved applications doing rx_burst and control operations concurrently. Fixes: 4e9c73e96e83 ("net/netvsc: add Hyper-V network device") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_nvs.c | 41 +++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/drivers/net/netvsc/hn_nvs.c b/drivers/net/netvsc/hn_nvs.c index 6b518685ab6f..477202b2a0b7 100644 --- a/drivers/net/netvsc/hn_nvs.c +++ b/drivers/net/netvsc/hn_nvs.c @@ -54,7 +54,7 @@ static int hn_nvs_req_send(struct hn_data *hv, } static int -hn_nvs_execute(struct hn_data *hv, +__hn_nvs_execute(struct hn_data *hv, void *req, uint32_t reqlen, void *resp, uint32_t resplen, uint32_t type) @@ -62,6 +62,7 @@ hn_nvs_execute(struct hn_data *hv, struct vmbus_channel *chan = hn_primary_chan(hv); char buffer[NVS_RESPSIZE_MAX]; const struct hn_nvs_hdr *hdr; + uint64_t xactid; uint32_t len; int ret; @@ -77,7 +78,7 @@ hn_nvs_execute(struct hn_data *hv, retry: len = sizeof(buffer); - ret = rte_vmbus_chan_recv(chan, buffer, &len, NULL); + ret = rte_vmbus_chan_recv(chan, buffer, &len, &xactid); if (ret == -EAGAIN) { rte_delay_us(HN_CHAN_INTERVAL_US); goto retry; @@ -88,7 +89,20 @@ hn_nvs_execute(struct hn_data *hv, return ret; } + if (len < sizeof(*hdr)) { + PMD_DRV_LOG(ERR, "response missing NVS header"); + return -EINVAL; + } + hdr = (struct hn_nvs_hdr *)buffer; + + /* Silently drop received packets while waiting for response */ + if (hdr->type == NVS_TYPE_RNDIS) { + hn_nvs_ack_rxbuf(chan, xactid); + --hv->rxbuf_outstanding; + goto retry; + } + if (hdr->type != type) { PMD_DRV_LOG(ERR, "unexpected NVS resp %#x, expect %#x", hdr->type, type); @@ -108,6 +122,29 @@ hn_nvs_execute(struct hn_data *hv, return 0; } + +/* + * Execute one control command and get the response. + * Only one command can be active on a channel at once + * Unlike BSD, DPDK does not have an interrupt context + * so the polling is required to wait for response. + */ +static int +hn_nvs_execute(struct hn_data *hv, + void *req, uint32_t reqlen, + void *resp, uint32_t resplen, + uint32_t type) +{ + struct hn_rx_queue *rxq = hv->primary; + int ret; + + rte_spinlock_lock(&rxq->ring_lock); + ret = __hn_nvs_execute(hv, req, reqlen, resp, resplen, type); + rte_spinlock_unlock(&rxq->ring_lock); + + return ret; +} + static int hn_nvs_doinit(struct hn_data *hv, uint32_t nvs_ver) { -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v2 3/4] net/netvsc: split send buffers from transmit descriptors 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 0/4] net/netvsc patches Stephen Hemminger 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 1/4] net/netvsc: propogate descriptor limits from VF to netvsc Stephen Hemminger 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 2/4] net/netvsc: handle receive packets during multi-channel setup Stephen Hemminger @ 2020-03-18 20:29 ` Stephen Hemminger 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 4/4] net/netvsc: don't enable RSS if only single receive queue Stephen Hemminger 3 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-18 20:29 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger, stable The VMBus has reserved transmit area (per device) and transmit descriptors (per queue). The previous code was always having a 1:1 mapping between send buffers and descriptors. This can lead to one queue starving another and also buffer bloat. Change to working more like FreeBSD where there is a pool of transmit descriptors per queue. If send buffer is not available then no aggregation happens but the queue can still drain. Fixes: 4e9c73e96e83 ("net/netvsc: add Hyper-V network device") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_ethdev.c | 9 +- drivers/net/netvsc/hn_rxtx.c | 258 ++++++++++++++++++++------------- drivers/net/netvsc/hn_var.h | 10 +- 3 files changed, 171 insertions(+), 106 deletions(-) diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c index 564620748daf..ac6610838008 100644 --- a/drivers/net/netvsc/hn_ethdev.c +++ b/drivers/net/netvsc/hn_ethdev.c @@ -257,6 +257,9 @@ static int hn_dev_info_get(struct rte_eth_dev *dev, dev_info->max_rx_queues = hv->max_queues; dev_info->max_tx_queues = hv->max_queues; + dev_info->tx_desc_lim.nb_min = 1; + dev_info->tx_desc_lim.nb_max = 4096; + if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; @@ -982,7 +985,7 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) if (err) goto failed; - err = hn_tx_pool_init(eth_dev); + err = hn_chim_init(eth_dev); if (err) goto failed; @@ -1018,7 +1021,7 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) failed: PMD_INIT_LOG(NOTICE, "device init failed"); - hn_tx_pool_uninit(eth_dev); + hn_chim_uninit(eth_dev); hn_detach(hv); return err; } @@ -1042,7 +1045,7 @@ eth_hn_dev_uninit(struct rte_eth_dev *eth_dev) eth_dev->rx_pkt_burst = NULL; hn_detach(hv); - hn_tx_pool_uninit(eth_dev); + hn_chim_uninit(eth_dev); rte_vmbus_chan_close(hv->primary->chan); rte_free(hv->primary); ret = rte_eth_dev_owner_delete(hv->owner.id); diff --git a/drivers/net/netvsc/hn_rxtx.c b/drivers/net/netvsc/hn_rxtx.c index 7212780c156e..f3ce5084eceb 100644 --- a/drivers/net/netvsc/hn_rxtx.c +++ b/drivers/net/netvsc/hn_rxtx.c @@ -18,6 +18,7 @@ #include <rte_memzone.h> #include <rte_malloc.h> #include <rte_atomic.h> +#include <rte_bitmap.h> #include <rte_branch_prediction.h> #include <rte_ether.h> #include <rte_common.h> @@ -83,7 +84,7 @@ struct hn_txdesc { struct rte_mbuf *m; uint16_t queue_id; - uint16_t chim_index; + uint32_t chim_index; uint32_t chim_size; uint32_t data_size; uint32_t packets; @@ -98,6 +99,8 @@ struct hn_txdesc { RNDIS_PKTINFO_SIZE(NDIS_LSO2_INFO_SIZE) + \ RNDIS_PKTINFO_SIZE(NDIS_TXCSUM_INFO_SIZE)) +#define HN_RNDIS_PKT_ALIGNED RTE_ALIGN(HN_RNDIS_PKT_LEN, RTE_CACHE_LINE_SIZE) + /* Minimum space required for a packet */ #define HN_PKTSIZE_MIN(align) \ RTE_ALIGN(RTE_ETHER_MIN_LEN + HN_RNDIS_PKT_LEN, align) @@ -150,63 +153,78 @@ hn_rndis_pktmsg_offset(uint32_t ofs) static void hn_txd_init(struct rte_mempool *mp __rte_unused, void *opaque, void *obj, unsigned int idx) { + struct hn_tx_queue *txq = opaque; struct hn_txdesc *txd = obj; - struct rte_eth_dev *dev = opaque; - struct rndis_packet_msg *pkt; memset(txd, 0, sizeof(*txd)); - txd->chim_index = idx; - - pkt = rte_malloc_socket("RNDIS_TX", HN_RNDIS_PKT_LEN, - rte_align32pow2(HN_RNDIS_PKT_LEN), - dev->device->numa_node); - if (!pkt) - rte_exit(EXIT_FAILURE, "can not allocate RNDIS header"); - txd->rndis_pkt = pkt; + txd->queue_id = txq->queue_id; + txd->chim_index = NVS_CHIM_IDX_INVALID; + txd->rndis_pkt = (struct rndis_packet_msg *)(char *)txq->tx_rndis + + idx * HN_RNDIS_PKT_ALIGNED; } -/* - * Unlike Linux and FreeBSD, this driver uses a mempool - * to limit outstanding transmits and reserve buffers - */ int -hn_tx_pool_init(struct rte_eth_dev *dev) +hn_chim_init(struct rte_eth_dev *dev) { struct hn_data *hv = dev->data->dev_private; - char name[RTE_MEMPOOL_NAMESIZE]; - struct rte_mempool *mp; + uint32_t i, chim_bmp_size; - snprintf(name, sizeof(name), - "hn_txd_%u", dev->data->port_id); - - PMD_INIT_LOG(DEBUG, "create a TX send pool %s n=%u size=%zu socket=%d", - name, hv->chim_cnt, sizeof(struct hn_txdesc), - dev->device->numa_node); - - mp = rte_mempool_create(name, hv->chim_cnt, sizeof(struct hn_txdesc), - HN_TXD_CACHE_SIZE, 0, - NULL, NULL, - hn_txd_init, dev, - dev->device->numa_node, 0); - if (!mp) { - PMD_DRV_LOG(ERR, - "mempool %s create failed: %d", name, rte_errno); - return -rte_errno; + rte_spinlock_init(&hv->chim_lock); + chim_bmp_size = rte_bitmap_get_memory_footprint(hv->chim_cnt); + hv->chim_bmem = rte_zmalloc("hn_chim_bitmap", chim_bmp_size, + RTE_CACHE_LINE_SIZE); + if (hv->chim_bmem == NULL) { + PMD_INIT_LOG(ERR, "failed to allocate bitmap size %u", chim_bmp_size); + return -1; + + } + + PMD_INIT_LOG(DEBUG, "create a TX bitmap n=%u size=%u", hv->chim_cnt, chim_bmp_size); + + hv->chim_bmap = rte_bitmap_init(hv->chim_cnt, hv->chim_bmem, chim_bmp_size); + if (hv->chim_bmap == NULL) { + PMD_INIT_LOG(ERR, "failed to init chim bitmap"); + return -1; } - hv->tx_pool = mp; + for (i = 0; i < hv->chim_cnt; i++) + rte_bitmap_set(hv->chim_bmap, i); + return 0; } void -hn_tx_pool_uninit(struct rte_eth_dev *dev) +hn_chim_uninit(struct rte_eth_dev *dev) { struct hn_data *hv = dev->data->dev_private; - if (hv->tx_pool) { - rte_mempool_free(hv->tx_pool); - hv->tx_pool = NULL; + rte_bitmap_free(hv->chim_bmap); + rte_free(hv->chim_bmem); + hv->chim_bmem = NULL; +} + +static uint32_t hn_chim_alloc(struct hn_data *hv) +{ + uint32_t index = NVS_CHIM_IDX_INVALID; + uint64_t slab; + + rte_spinlock_lock(&hv->chim_lock); + if (rte_bitmap_scan(hv->chim_bmap, &index, &slab)) + rte_bitmap_clear(hv->chim_bmap, index); + rte_spinlock_unlock(&hv->chim_lock); + + return index; +} + +static void hn_chim_free(struct hn_data *hv, uint32_t chim_idx) +{ + if (chim_idx >= hv->chim_cnt) { + PMD_DRV_LOG(ERR, "Invalid chimney index %u", chim_idx); + } else { + rte_spinlock_lock(&hv->chim_lock); + rte_bitmap_set(hv->chim_bmap, chim_idx); + rte_spinlock_unlock(&hv->chim_lock); } } @@ -220,15 +238,16 @@ static void hn_reset_txagg(struct hn_tx_queue *txq) int hn_dev_tx_queue_setup(struct rte_eth_dev *dev, - uint16_t queue_idx, uint16_t nb_desc __rte_unused, + uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf) { struct hn_data *hv = dev->data->dev_private; struct hn_tx_queue *txq; + char name[RTE_MEMPOOL_NAMESIZE]; uint32_t tx_free_thresh; - int err; + int err = -ENOMEM; PMD_INIT_FUNC_TRACE(); @@ -252,6 +271,28 @@ hn_dev_tx_queue_setup(struct rte_eth_dev *dev, txq->free_thresh = tx_free_thresh; + snprintf(name, sizeof(name), + "hn_txd_%u_%u", dev->data->port_id, queue_idx); + + PMD_INIT_LOG(DEBUG, "TX descriptor pool %s n=%u size=%zu", + name, nb_desc, sizeof(struct hn_txdesc)); + + txq->tx_rndis = rte_calloc("hn_txq_rndis", nb_desc, HN_RNDIS_PKT_ALIGNED, + RTE_CACHE_LINE_SIZE); + if (txq->tx_rndis == NULL) + goto error; + + txq->txdesc_pool = rte_mempool_create(name, nb_desc, sizeof(struct hn_txdesc), + 0, 0, + NULL, NULL, + hn_txd_init, txq, + dev->device->numa_node, 0); + if (txq->txdesc_pool == NULL) { + PMD_DRV_LOG(ERR, + "mempool %s create failed: %d", name, rte_errno); + goto error; + } + txq->agg_szmax = RTE_MIN(hv->chim_szmax, hv->rndis_agg_size); txq->agg_pktmax = hv->rndis_agg_pkts; txq->agg_align = hv->rndis_agg_align; @@ -260,31 +301,57 @@ hn_dev_tx_queue_setup(struct rte_eth_dev *dev, err = hn_vf_tx_queue_setup(dev, queue_idx, nb_desc, socket_id, tx_conf); - if (err) { - rte_free(txq); - return err; + if (err == 0) { + dev->data->tx_queues[queue_idx] = txq; + return 0; } - dev->data->tx_queues[queue_idx] = txq; - return 0; +error: + if (txq->txdesc_pool) + rte_mempool_free(txq->txdesc_pool); + rte_free(txq->tx_rndis); + rte_free(txq); + return err; +} + + +static struct hn_txdesc *hn_txd_get(struct hn_tx_queue *txq) +{ + struct hn_txdesc *txd; + + if (rte_mempool_get(txq->txdesc_pool, (void **)&txd)) { + ++txq->stats.ring_full; + PMD_TX_LOG(DEBUG, "tx pool exhausted!"); + return NULL; + } + + txd->m = NULL; + txd->packets = 0; + txd->data_size = 0; + txd->chim_size = 0; + + return txd; +} + +static void hn_txd_put(struct hn_tx_queue *txq, struct hn_txdesc *txd) +{ + rte_mempool_put(txq->txdesc_pool, txd); } void hn_dev_tx_queue_release(void *arg) { struct hn_tx_queue *txq = arg; - struct hn_txdesc *txd; PMD_INIT_FUNC_TRACE(); if (!txq) return; - /* If any pending data is still present just drop it */ - txd = txq->agg_txd; - if (txd) - rte_mempool_put(txq->hv->tx_pool, txd); + if (txq->txdesc_pool) + rte_mempool_free(txq->txdesc_pool); + rte_free(txq->tx_rndis); rte_free(txq); } @@ -292,6 +359,7 @@ static void hn_nvs_send_completed(struct rte_eth_dev *dev, uint16_t queue_id, unsigned long xactid, const struct hn_nvs_rndis_ack *ack) { + struct hn_data *hv = dev->data->dev_private; struct hn_txdesc *txd = (struct hn_txdesc *)xactid; struct hn_tx_queue *txq; @@ -312,9 +380,11 @@ hn_nvs_send_completed(struct rte_eth_dev *dev, uint16_t queue_id, ++txq->stats.errors; } - rte_pktmbuf_free(txd->m); + if (txd->chim_index != NVS_CHIM_IDX_INVALID) + hn_chim_free(hv, txd->chim_index); - rte_mempool_put(txq->hv->tx_pool, txd); + rte_pktmbuf_free(txd->m); + hn_txd_put(txq, txd); } /* Handle transmit completion events */ @@ -1036,28 +1106,15 @@ static int hn_flush_txagg(struct hn_tx_queue *txq, bool *need_sig) return ret; } -static struct hn_txdesc *hn_new_txd(struct hn_data *hv, - struct hn_tx_queue *txq) -{ - struct hn_txdesc *txd; - - if (rte_mempool_get(hv->tx_pool, (void **)&txd)) { - ++txq->stats.ring_full; - PMD_TX_LOG(DEBUG, "tx pool exhausted!"); - return NULL; - } - - txd->m = NULL; - txd->queue_id = txq->queue_id; - txd->packets = 0; - txd->data_size = 0; - txd->chim_size = 0; - - return txd; -} - +/* + * Try and find a place in a send chimney buffer to put + * the small packet. If space is available, this routine + * returns a pointer of where to place the data. + * If no space, caller should try direct transmit. + */ static void * -hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq, uint32_t pktsize) +hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq, + struct hn_txdesc *txd, uint32_t pktsize) { struct hn_txdesc *agg_txd = txq->agg_txd; struct rndis_packet_msg *pkt; @@ -1085,7 +1142,7 @@ hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq, uint32_t pktsize) } chim = (uint8_t *)pkt + pkt->len; - + txq->agg_prevpkt = chim; txq->agg_pktleft--; txq->agg_szleft -= pktsize; if (txq->agg_szleft < HN_PKTSIZE_MIN(txq->agg_align)) { @@ -1095,18 +1152,21 @@ hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq, uint32_t pktsize) */ txq->agg_pktleft = 0; } - } else { - agg_txd = hn_new_txd(hv, txq); - if (!agg_txd) - return NULL; - - chim = (uint8_t *)hv->chim_res->addr - + agg_txd->chim_index * hv->chim_szmax; - txq->agg_txd = agg_txd; - txq->agg_pktleft = txq->agg_pktmax - 1; - txq->agg_szleft = txq->agg_szmax - pktsize; + hn_txd_put(txq, txd); + return chim; } + + txd->chim_index = hn_chim_alloc(hv); + if (txd->chim_index == NVS_CHIM_IDX_INVALID) + return NULL; + + chim = (uint8_t *)hv->chim_res->addr + + txd->chim_index * hv->chim_szmax; + + txq->agg_txd = txd; + txq->agg_pktleft = txq->agg_pktmax - 1; + txq->agg_szleft = txq->agg_szmax - pktsize; txq->agg_prevpkt = chim; return chim; @@ -1329,13 +1389,18 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) return (*vf_dev->tx_pkt_burst)(sub_q, tx_pkts, nb_pkts); } - if (rte_mempool_avail_count(hv->tx_pool) <= txq->free_thresh) + if (rte_mempool_avail_count(txq->txdesc_pool) <= txq->free_thresh) hn_process_events(hv, txq->queue_id, 0); for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) { struct rte_mbuf *m = tx_pkts[nb_tx]; uint32_t pkt_size = m->pkt_len + HN_RNDIS_PKT_LEN; struct rndis_packet_msg *pkt; + struct hn_txdesc *txd; + + txd = hn_txd_get(txq); + if (txd == NULL) + break; /* For small packets aggregate them in chimney buffer */ if (m->pkt_len < HN_TXCOPY_THRESHOLD && pkt_size <= txq->agg_szmax) { @@ -1346,7 +1411,8 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) goto fail; } - pkt = hn_try_txagg(hv, txq, pkt_size); + + pkt = hn_try_txagg(hv, txq, txd, pkt_size); if (unlikely(!pkt)) break; @@ -1360,21 +1426,13 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) hn_flush_txagg(txq, &need_sig)) goto fail; } else { - struct hn_txdesc *txd; - - /* can send chimney data and large packet at once */ - txd = txq->agg_txd; - if (txd) { - hn_reset_txagg(txq); - } else { - txd = hn_new_txd(hv, txq); - if (unlikely(!txd)) - break; - } + /* Send any outstanding packets in buffer */ + if (txq->agg_txd && hn_flush_txagg(txq, &need_sig)) + goto fail; pkt = txd->rndis_pkt; txd->m = m; - txd->data_size += m->pkt_len; + txd->data_size = m->pkt_len; ++txd->packets; hn_encap(pkt, queue_id, m); @@ -1383,7 +1441,7 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) if (unlikely(ret != 0)) { PMD_TX_LOG(NOTICE, "sg send failed: %d", ret); ++txq->stats.errors; - rte_mempool_put(hv->tx_pool, txd); + hn_txd_put(txq, txd); goto fail; } } diff --git a/drivers/net/netvsc/hn_var.h b/drivers/net/netvsc/hn_var.h index 05bc492511ec..bd8aeada76ee 100644 --- a/drivers/net/netvsc/hn_var.h +++ b/drivers/net/netvsc/hn_var.h @@ -52,6 +52,8 @@ struct hn_tx_queue { uint16_t port_id; uint16_t queue_id; uint32_t free_thresh; + struct rte_mempool *txdesc_pool; + void *tx_rndis; /* Applied packet transmission aggregation limits. */ uint32_t agg_szmax; @@ -115,8 +117,10 @@ struct hn_data { uint16_t num_queues; uint64_t rss_offloads; + rte_spinlock_t chim_lock; struct rte_mem_resource *chim_res; /* UIO resource for Tx */ - struct rte_mempool *tx_pool; /* Tx descriptors */ + struct rte_bitmap *chim_bmap; /* Send buffer map */ + void *chim_bmem; uint32_t chim_szmax; /* Max size per buffer */ uint32_t chim_cnt; /* Max packets per buffer */ @@ -157,8 +161,8 @@ uint16_t hn_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t hn_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); -int hn_tx_pool_init(struct rte_eth_dev *dev); -void hn_tx_pool_uninit(struct rte_eth_dev *dev); +int hn_chim_init(struct rte_eth_dev *dev); +void hn_chim_uninit(struct rte_eth_dev *dev); int hn_dev_link_update(struct rte_eth_dev *dev, int wait); int hn_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v2 4/4] net/netvsc: don't enable RSS if only single receive queue 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 0/4] net/netvsc patches Stephen Hemminger ` (2 preceding siblings ...) 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 3/4] net/netvsc: split send buffers from transmit descriptors Stephen Hemminger @ 2020-03-18 20:29 ` Stephen Hemminger 3 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-18 20:29 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger, stable If application has multiple transmit queues but only a single receive queue, then do not enable RSS. Fixes: 8b945a7f7dcb ("drivers/net: update Rx RSS hash offload capabilities") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_ethdev.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c index ac6610838008..85f43996a623 100644 --- a/drivers/net/netvsc/hn_ethdev.c +++ b/drivers/net/netvsc/hn_ethdev.c @@ -597,11 +597,14 @@ static int hn_dev_configure(struct rte_eth_dev *dev) return err; } - err = hn_rndis_conf_rss(hv, 0); - if (err) { - PMD_DRV_LOG(NOTICE, - "initial RSS config failed"); - return err; + if ((dev_conf->rxmode.offloads & DEV_RX_OFFLOAD_RSS_HASH) && + dev->data->nb_rx_queues > 1) { + err = hn_rndis_conf_rss(hv, 0); + if (err) { + PMD_DRV_LOG(NOTICE, + "initial RSS config failed"); + return err; + } } } -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v3 0/4] net/netvsc patches 2020-03-16 23:56 [dpdk-dev] [PATCH 0/2] net/netvsc: patches Stephen Hemminger ` (3 preceding siblings ...) 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 0/4] net/netvsc patches Stephen Hemminger @ 2020-03-18 20:51 ` Stephen Hemminger 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 1/4] net/netvsc: propagate descriptor limits from VF to netvsc Stephen Hemminger ` (3 more replies) 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes Stephen Hemminger 5 siblings, 4 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-18 20:51 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger These are bug fixes for netvsc PMD mostly related to issues discovered by users of multi-queue. v3 - fix checkpatch complaints v2 - simplify the locking on multi-channel setup add patches to handle single queue and tx descriptor pool Stephen Hemminger (4): net/netvsc: propagate descriptor limits from VF to netvsc net/netvsc: handle receive packets during multi-channel setup net/netvsc: split send buffers from transmit descriptors net/netvsc: don't enable RSS if only single receive queue drivers/net/netvsc/hn_ethdev.c | 22 ++- drivers/net/netvsc/hn_nvs.c | 41 +++++- drivers/net/netvsc/hn_rxtx.c | 261 ++++++++++++++++++++------------- drivers/net/netvsc/hn_var.h | 10 +- drivers/net/netvsc/hn_vf.c | 13 ++ 5 files changed, 234 insertions(+), 113 deletions(-) -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v3 1/4] net/netvsc: propagate descriptor limits from VF to netvsc 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 0/4] net/netvsc patches Stephen Hemminger @ 2020-03-18 20:51 ` Stephen Hemminger 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 2/4] net/netvsc: handle receive packets during multi-channel setup Stephen Hemminger ` (2 subsequent siblings) 3 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-18 20:51 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger, stable If application cares about descriptor limits, the netvsc device values should reflect those of the VF as well. Fixes: dc7680e8597c ("net/netvsc: support integrated VF") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_vf.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/netvsc/hn_vf.c b/drivers/net/netvsc/hn_vf.c index 7a3734cadfa4..1261b2e2ef85 100644 --- a/drivers/net/netvsc/hn_vf.c +++ b/drivers/net/netvsc/hn_vf.c @@ -167,6 +167,17 @@ hn_nvs_handle_vfassoc(struct rte_eth_dev *dev, hn_vf_remove(hv); } +static void +hn_vf_merge_desc_lim(struct rte_eth_desc_lim *lim, + const struct rte_eth_desc_lim *vf_lim) +{ + lim->nb_max = RTE_MIN(vf_lim->nb_max, lim->nb_max); + lim->nb_min = RTE_MAX(vf_lim->nb_min, lim->nb_min); + lim->nb_align = RTE_MAX(vf_lim->nb_align, lim->nb_align); + lim->nb_seg_max = RTE_MIN(vf_lim->nb_seg_max, lim->nb_seg_max); + lim->nb_mtu_seg_max = RTE_MIN(vf_lim->nb_seg_max, lim->nb_seg_max); +} + /* * Merge the info from the VF and synthetic path. * use the default config of the VF @@ -196,11 +207,13 @@ static int hn_vf_info_merge(struct rte_eth_dev *vf_dev, info->max_tx_queues); info->tx_offload_capa &= vf_info.tx_offload_capa; info->tx_queue_offload_capa &= vf_info.tx_queue_offload_capa; + hn_vf_merge_desc_lim(&info->tx_desc_lim, &vf_info.tx_desc_lim); info->min_rx_bufsize = RTE_MAX(vf_info.min_rx_bufsize, info->min_rx_bufsize); info->max_rx_pktlen = RTE_MAX(vf_info.max_rx_pktlen, info->max_rx_pktlen); + hn_vf_merge_desc_lim(&info->rx_desc_lim, &vf_info.rx_desc_lim); return 0; } -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v3 2/4] net/netvsc: handle receive packets during multi-channel setup 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 0/4] net/netvsc patches Stephen Hemminger 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 1/4] net/netvsc: propagate descriptor limits from VF to netvsc Stephen Hemminger @ 2020-03-18 20:51 ` Stephen Hemminger 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 3/4] net/netvsc: split send buffers from transmit descriptors Stephen Hemminger 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 4/4] net/netvsc: don't enable RSS if only single receive queue Stephen Hemminger 3 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-18 20:51 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger, stable It is possible for a packet to arrive during the configuration process when setting up multiple queue mode. This would cause configure to fail; fix by just ignoring receive packets while waiting for control commands. Use the receive ring lock to avoid possible races between oddly behaved applications doing rx_burst and control operations concurrently. Fixes: 4e9c73e96e83 ("net/netvsc: add Hyper-V network device") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_nvs.c | 41 +++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/drivers/net/netvsc/hn_nvs.c b/drivers/net/netvsc/hn_nvs.c index 6b518685ab6f..477202b2a0b7 100644 --- a/drivers/net/netvsc/hn_nvs.c +++ b/drivers/net/netvsc/hn_nvs.c @@ -54,7 +54,7 @@ static int hn_nvs_req_send(struct hn_data *hv, } static int -hn_nvs_execute(struct hn_data *hv, +__hn_nvs_execute(struct hn_data *hv, void *req, uint32_t reqlen, void *resp, uint32_t resplen, uint32_t type) @@ -62,6 +62,7 @@ hn_nvs_execute(struct hn_data *hv, struct vmbus_channel *chan = hn_primary_chan(hv); char buffer[NVS_RESPSIZE_MAX]; const struct hn_nvs_hdr *hdr; + uint64_t xactid; uint32_t len; int ret; @@ -77,7 +78,7 @@ hn_nvs_execute(struct hn_data *hv, retry: len = sizeof(buffer); - ret = rte_vmbus_chan_recv(chan, buffer, &len, NULL); + ret = rte_vmbus_chan_recv(chan, buffer, &len, &xactid); if (ret == -EAGAIN) { rte_delay_us(HN_CHAN_INTERVAL_US); goto retry; @@ -88,7 +89,20 @@ hn_nvs_execute(struct hn_data *hv, return ret; } + if (len < sizeof(*hdr)) { + PMD_DRV_LOG(ERR, "response missing NVS header"); + return -EINVAL; + } + hdr = (struct hn_nvs_hdr *)buffer; + + /* Silently drop received packets while waiting for response */ + if (hdr->type == NVS_TYPE_RNDIS) { + hn_nvs_ack_rxbuf(chan, xactid); + --hv->rxbuf_outstanding; + goto retry; + } + if (hdr->type != type) { PMD_DRV_LOG(ERR, "unexpected NVS resp %#x, expect %#x", hdr->type, type); @@ -108,6 +122,29 @@ hn_nvs_execute(struct hn_data *hv, return 0; } + +/* + * Execute one control command and get the response. + * Only one command can be active on a channel at once + * Unlike BSD, DPDK does not have an interrupt context + * so the polling is required to wait for response. + */ +static int +hn_nvs_execute(struct hn_data *hv, + void *req, uint32_t reqlen, + void *resp, uint32_t resplen, + uint32_t type) +{ + struct hn_rx_queue *rxq = hv->primary; + int ret; + + rte_spinlock_lock(&rxq->ring_lock); + ret = __hn_nvs_execute(hv, req, reqlen, resp, resplen, type); + rte_spinlock_unlock(&rxq->ring_lock); + + return ret; +} + static int hn_nvs_doinit(struct hn_data *hv, uint32_t nvs_ver) { -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v3 3/4] net/netvsc: split send buffers from transmit descriptors 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 0/4] net/netvsc patches Stephen Hemminger 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 1/4] net/netvsc: propagate descriptor limits from VF to netvsc Stephen Hemminger 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 2/4] net/netvsc: handle receive packets during multi-channel setup Stephen Hemminger @ 2020-03-18 20:51 ` Stephen Hemminger 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 4/4] net/netvsc: don't enable RSS if only single receive queue Stephen Hemminger 3 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-18 20:51 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger, stable The VMBus has reserved transmit area (per device) and transmit descriptors (per queue). The previous code was always having a 1:1 mapping between send buffers and descriptors. This can lead to one queue starving another and also buffer bloat. Change to working more like FreeBSD where there is a pool of transmit descriptors per queue. If send buffer is not available then no aggregation happens but the queue can still drain. Fixes: 4e9c73e96e83 ("net/netvsc: add Hyper-V network device") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_ethdev.c | 9 +- drivers/net/netvsc/hn_rxtx.c | 261 ++++++++++++++++++++------------- drivers/net/netvsc/hn_var.h | 10 +- 3 files changed, 174 insertions(+), 106 deletions(-) diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c index 564620748daf..ac6610838008 100644 --- a/drivers/net/netvsc/hn_ethdev.c +++ b/drivers/net/netvsc/hn_ethdev.c @@ -257,6 +257,9 @@ static int hn_dev_info_get(struct rte_eth_dev *dev, dev_info->max_rx_queues = hv->max_queues; dev_info->max_tx_queues = hv->max_queues; + dev_info->tx_desc_lim.nb_min = 1; + dev_info->tx_desc_lim.nb_max = 4096; + if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; @@ -982,7 +985,7 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) if (err) goto failed; - err = hn_tx_pool_init(eth_dev); + err = hn_chim_init(eth_dev); if (err) goto failed; @@ -1018,7 +1021,7 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) failed: PMD_INIT_LOG(NOTICE, "device init failed"); - hn_tx_pool_uninit(eth_dev); + hn_chim_uninit(eth_dev); hn_detach(hv); return err; } @@ -1042,7 +1045,7 @@ eth_hn_dev_uninit(struct rte_eth_dev *eth_dev) eth_dev->rx_pkt_burst = NULL; hn_detach(hv); - hn_tx_pool_uninit(eth_dev); + hn_chim_uninit(eth_dev); rte_vmbus_chan_close(hv->primary->chan); rte_free(hv->primary); ret = rte_eth_dev_owner_delete(hv->owner.id); diff --git a/drivers/net/netvsc/hn_rxtx.c b/drivers/net/netvsc/hn_rxtx.c index 7212780c156e..eea09a431ec6 100644 --- a/drivers/net/netvsc/hn_rxtx.c +++ b/drivers/net/netvsc/hn_rxtx.c @@ -18,6 +18,7 @@ #include <rte_memzone.h> #include <rte_malloc.h> #include <rte_atomic.h> +#include <rte_bitmap.h> #include <rte_branch_prediction.h> #include <rte_ether.h> #include <rte_common.h> @@ -83,7 +84,7 @@ struct hn_txdesc { struct rte_mbuf *m; uint16_t queue_id; - uint16_t chim_index; + uint32_t chim_index; uint32_t chim_size; uint32_t data_size; uint32_t packets; @@ -98,6 +99,8 @@ struct hn_txdesc { RNDIS_PKTINFO_SIZE(NDIS_LSO2_INFO_SIZE) + \ RNDIS_PKTINFO_SIZE(NDIS_TXCSUM_INFO_SIZE)) +#define HN_RNDIS_PKT_ALIGNED RTE_ALIGN(HN_RNDIS_PKT_LEN, RTE_CACHE_LINE_SIZE) + /* Minimum space required for a packet */ #define HN_PKTSIZE_MIN(align) \ RTE_ALIGN(RTE_ETHER_MIN_LEN + HN_RNDIS_PKT_LEN, align) @@ -150,63 +153,80 @@ hn_rndis_pktmsg_offset(uint32_t ofs) static void hn_txd_init(struct rte_mempool *mp __rte_unused, void *opaque, void *obj, unsigned int idx) { + struct hn_tx_queue *txq = opaque; struct hn_txdesc *txd = obj; - struct rte_eth_dev *dev = opaque; - struct rndis_packet_msg *pkt; memset(txd, 0, sizeof(*txd)); - txd->chim_index = idx; - - pkt = rte_malloc_socket("RNDIS_TX", HN_RNDIS_PKT_LEN, - rte_align32pow2(HN_RNDIS_PKT_LEN), - dev->device->numa_node); - if (!pkt) - rte_exit(EXIT_FAILURE, "can not allocate RNDIS header"); - txd->rndis_pkt = pkt; + txd->queue_id = txq->queue_id; + txd->chim_index = NVS_CHIM_IDX_INVALID; + txd->rndis_pkt = (struct rndis_packet_msg *)(char *)txq->tx_rndis + + idx * HN_RNDIS_PKT_ALIGNED; } -/* - * Unlike Linux and FreeBSD, this driver uses a mempool - * to limit outstanding transmits and reserve buffers - */ int -hn_tx_pool_init(struct rte_eth_dev *dev) +hn_chim_init(struct rte_eth_dev *dev) { struct hn_data *hv = dev->data->dev_private; - char name[RTE_MEMPOOL_NAMESIZE]; - struct rte_mempool *mp; + uint32_t i, chim_bmp_size; + + rte_spinlock_init(&hv->chim_lock); + chim_bmp_size = rte_bitmap_get_memory_footprint(hv->chim_cnt); + hv->chim_bmem = rte_zmalloc("hn_chim_bitmap", chim_bmp_size, + RTE_CACHE_LINE_SIZE); + if (hv->chim_bmem == NULL) { + PMD_INIT_LOG(ERR, "failed to allocate bitmap size %u", + chim_bmp_size); + return -1; + } - snprintf(name, sizeof(name), - "hn_txd_%u", dev->data->port_id); - - PMD_INIT_LOG(DEBUG, "create a TX send pool %s n=%u size=%zu socket=%d", - name, hv->chim_cnt, sizeof(struct hn_txdesc), - dev->device->numa_node); - - mp = rte_mempool_create(name, hv->chim_cnt, sizeof(struct hn_txdesc), - HN_TXD_CACHE_SIZE, 0, - NULL, NULL, - hn_txd_init, dev, - dev->device->numa_node, 0); - if (!mp) { - PMD_DRV_LOG(ERR, - "mempool %s create failed: %d", name, rte_errno); - return -rte_errno; + PMD_INIT_LOG(DEBUG, "create a TX bitmap n=%u size=%u", + hv->chim_cnt, chim_bmp_size); + + hv->chim_bmap = rte_bitmap_init(hv->chim_cnt, hv->chim_bmem, + chim_bmp_size); + if (hv->chim_bmap == NULL) { + PMD_INIT_LOG(ERR, "failed to init chim bitmap"); + return -1; } - hv->tx_pool = mp; + for (i = 0; i < hv->chim_cnt; i++) + rte_bitmap_set(hv->chim_bmap, i); + return 0; } void -hn_tx_pool_uninit(struct rte_eth_dev *dev) +hn_chim_uninit(struct rte_eth_dev *dev) { struct hn_data *hv = dev->data->dev_private; - if (hv->tx_pool) { - rte_mempool_free(hv->tx_pool); - hv->tx_pool = NULL; + rte_bitmap_free(hv->chim_bmap); + rte_free(hv->chim_bmem); + hv->chim_bmem = NULL; +} + +static uint32_t hn_chim_alloc(struct hn_data *hv) +{ + uint32_t index = NVS_CHIM_IDX_INVALID; + uint64_t slab; + + rte_spinlock_lock(&hv->chim_lock); + if (rte_bitmap_scan(hv->chim_bmap, &index, &slab)) + rte_bitmap_clear(hv->chim_bmap, index); + rte_spinlock_unlock(&hv->chim_lock); + + return index; +} + +static void hn_chim_free(struct hn_data *hv, uint32_t chim_idx) +{ + if (chim_idx >= hv->chim_cnt) { + PMD_DRV_LOG(ERR, "Invalid chimney index %u", chim_idx); + } else { + rte_spinlock_lock(&hv->chim_lock); + rte_bitmap_set(hv->chim_bmap, chim_idx); + rte_spinlock_unlock(&hv->chim_lock); } } @@ -220,15 +240,16 @@ static void hn_reset_txagg(struct hn_tx_queue *txq) int hn_dev_tx_queue_setup(struct rte_eth_dev *dev, - uint16_t queue_idx, uint16_t nb_desc __rte_unused, + uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf) { struct hn_data *hv = dev->data->dev_private; struct hn_tx_queue *txq; + char name[RTE_MEMPOOL_NAMESIZE]; uint32_t tx_free_thresh; - int err; + int err = -ENOMEM; PMD_INIT_FUNC_TRACE(); @@ -252,6 +273,29 @@ hn_dev_tx_queue_setup(struct rte_eth_dev *dev, txq->free_thresh = tx_free_thresh; + snprintf(name, sizeof(name), + "hn_txd_%u_%u", dev->data->port_id, queue_idx); + + PMD_INIT_LOG(DEBUG, "TX descriptor pool %s n=%u size=%zu", + name, nb_desc, sizeof(struct hn_txdesc)); + + txq->tx_rndis = rte_calloc("hn_txq_rndis", nb_desc, + HN_RNDIS_PKT_ALIGNED, RTE_CACHE_LINE_SIZE); + if (txq->tx_rndis == NULL) + goto error; + + txq->txdesc_pool = rte_mempool_create(name, nb_desc, + sizeof(struct hn_txdesc), + 0, 0, + NULL, NULL, + hn_txd_init, txq, + dev->device->numa_node, 0); + if (txq->txdesc_pool == NULL) { + PMD_DRV_LOG(ERR, + "mempool %s create failed: %d", name, rte_errno); + goto error; + } + txq->agg_szmax = RTE_MIN(hv->chim_szmax, hv->rndis_agg_size); txq->agg_pktmax = hv->rndis_agg_pkts; txq->agg_align = hv->rndis_agg_align; @@ -260,31 +304,57 @@ hn_dev_tx_queue_setup(struct rte_eth_dev *dev, err = hn_vf_tx_queue_setup(dev, queue_idx, nb_desc, socket_id, tx_conf); - if (err) { - rte_free(txq); - return err; + if (err == 0) { + dev->data->tx_queues[queue_idx] = txq; + return 0; } - dev->data->tx_queues[queue_idx] = txq; - return 0; +error: + if (txq->txdesc_pool) + rte_mempool_free(txq->txdesc_pool); + rte_free(txq->tx_rndis); + rte_free(txq); + return err; +} + + +static struct hn_txdesc *hn_txd_get(struct hn_tx_queue *txq) +{ + struct hn_txdesc *txd; + + if (rte_mempool_get(txq->txdesc_pool, (void **)&txd)) { + ++txq->stats.ring_full; + PMD_TX_LOG(DEBUG, "tx pool exhausted!"); + return NULL; + } + + txd->m = NULL; + txd->packets = 0; + txd->data_size = 0; + txd->chim_size = 0; + + return txd; +} + +static void hn_txd_put(struct hn_tx_queue *txq, struct hn_txdesc *txd) +{ + rte_mempool_put(txq->txdesc_pool, txd); } void hn_dev_tx_queue_release(void *arg) { struct hn_tx_queue *txq = arg; - struct hn_txdesc *txd; PMD_INIT_FUNC_TRACE(); if (!txq) return; - /* If any pending data is still present just drop it */ - txd = txq->agg_txd; - if (txd) - rte_mempool_put(txq->hv->tx_pool, txd); + if (txq->txdesc_pool) + rte_mempool_free(txq->txdesc_pool); + rte_free(txq->tx_rndis); rte_free(txq); } @@ -292,6 +362,7 @@ static void hn_nvs_send_completed(struct rte_eth_dev *dev, uint16_t queue_id, unsigned long xactid, const struct hn_nvs_rndis_ack *ack) { + struct hn_data *hv = dev->data->dev_private; struct hn_txdesc *txd = (struct hn_txdesc *)xactid; struct hn_tx_queue *txq; @@ -312,9 +383,11 @@ hn_nvs_send_completed(struct rte_eth_dev *dev, uint16_t queue_id, ++txq->stats.errors; } - rte_pktmbuf_free(txd->m); + if (txd->chim_index != NVS_CHIM_IDX_INVALID) + hn_chim_free(hv, txd->chim_index); - rte_mempool_put(txq->hv->tx_pool, txd); + rte_pktmbuf_free(txd->m); + hn_txd_put(txq, txd); } /* Handle transmit completion events */ @@ -1036,28 +1109,15 @@ static int hn_flush_txagg(struct hn_tx_queue *txq, bool *need_sig) return ret; } -static struct hn_txdesc *hn_new_txd(struct hn_data *hv, - struct hn_tx_queue *txq) -{ - struct hn_txdesc *txd; - - if (rte_mempool_get(hv->tx_pool, (void **)&txd)) { - ++txq->stats.ring_full; - PMD_TX_LOG(DEBUG, "tx pool exhausted!"); - return NULL; - } - - txd->m = NULL; - txd->queue_id = txq->queue_id; - txd->packets = 0; - txd->data_size = 0; - txd->chim_size = 0; - - return txd; -} - +/* + * Try and find a place in a send chimney buffer to put + * the small packet. If space is available, this routine + * returns a pointer of where to place the data. + * If no space, caller should try direct transmit. + */ static void * -hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq, uint32_t pktsize) +hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq, + struct hn_txdesc *txd, uint32_t pktsize) { struct hn_txdesc *agg_txd = txq->agg_txd; struct rndis_packet_msg *pkt; @@ -1085,7 +1145,7 @@ hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq, uint32_t pktsize) } chim = (uint8_t *)pkt + pkt->len; - + txq->agg_prevpkt = chim; txq->agg_pktleft--; txq->agg_szleft -= pktsize; if (txq->agg_szleft < HN_PKTSIZE_MIN(txq->agg_align)) { @@ -1095,18 +1155,21 @@ hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq, uint32_t pktsize) */ txq->agg_pktleft = 0; } - } else { - agg_txd = hn_new_txd(hv, txq); - if (!agg_txd) - return NULL; - - chim = (uint8_t *)hv->chim_res->addr - + agg_txd->chim_index * hv->chim_szmax; - txq->agg_txd = agg_txd; - txq->agg_pktleft = txq->agg_pktmax - 1; - txq->agg_szleft = txq->agg_szmax - pktsize; + hn_txd_put(txq, txd); + return chim; } + + txd->chim_index = hn_chim_alloc(hv); + if (txd->chim_index == NVS_CHIM_IDX_INVALID) + return NULL; + + chim = (uint8_t *)hv->chim_res->addr + + txd->chim_index * hv->chim_szmax; + + txq->agg_txd = txd; + txq->agg_pktleft = txq->agg_pktmax - 1; + txq->agg_szleft = txq->agg_szmax - pktsize; txq->agg_prevpkt = chim; return chim; @@ -1329,13 +1392,18 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) return (*vf_dev->tx_pkt_burst)(sub_q, tx_pkts, nb_pkts); } - if (rte_mempool_avail_count(hv->tx_pool) <= txq->free_thresh) + if (rte_mempool_avail_count(txq->txdesc_pool) <= txq->free_thresh) hn_process_events(hv, txq->queue_id, 0); for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) { struct rte_mbuf *m = tx_pkts[nb_tx]; uint32_t pkt_size = m->pkt_len + HN_RNDIS_PKT_LEN; struct rndis_packet_msg *pkt; + struct hn_txdesc *txd; + + txd = hn_txd_get(txq); + if (txd == NULL) + break; /* For small packets aggregate them in chimney buffer */ if (m->pkt_len < HN_TXCOPY_THRESHOLD && pkt_size <= txq->agg_szmax) { @@ -1346,7 +1414,8 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) goto fail; } - pkt = hn_try_txagg(hv, txq, pkt_size); + + pkt = hn_try_txagg(hv, txq, txd, pkt_size); if (unlikely(!pkt)) break; @@ -1360,21 +1429,13 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) hn_flush_txagg(txq, &need_sig)) goto fail; } else { - struct hn_txdesc *txd; - - /* can send chimney data and large packet at once */ - txd = txq->agg_txd; - if (txd) { - hn_reset_txagg(txq); - } else { - txd = hn_new_txd(hv, txq); - if (unlikely(!txd)) - break; - } + /* Send any outstanding packets in buffer */ + if (txq->agg_txd && hn_flush_txagg(txq, &need_sig)) + goto fail; pkt = txd->rndis_pkt; txd->m = m; - txd->data_size += m->pkt_len; + txd->data_size = m->pkt_len; ++txd->packets; hn_encap(pkt, queue_id, m); @@ -1383,7 +1444,7 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) if (unlikely(ret != 0)) { PMD_TX_LOG(NOTICE, "sg send failed: %d", ret); ++txq->stats.errors; - rte_mempool_put(hv->tx_pool, txd); + hn_txd_put(txq, txd); goto fail; } } diff --git a/drivers/net/netvsc/hn_var.h b/drivers/net/netvsc/hn_var.h index 05bc492511ec..822d737bd3cc 100644 --- a/drivers/net/netvsc/hn_var.h +++ b/drivers/net/netvsc/hn_var.h @@ -52,6 +52,8 @@ struct hn_tx_queue { uint16_t port_id; uint16_t queue_id; uint32_t free_thresh; + struct rte_mempool *txdesc_pool; + void *tx_rndis; /* Applied packet transmission aggregation limits. */ uint32_t agg_szmax; @@ -115,8 +117,10 @@ struct hn_data { uint16_t num_queues; uint64_t rss_offloads; + rte_spinlock_t chim_lock; struct rte_mem_resource *chim_res; /* UIO resource for Tx */ - struct rte_mempool *tx_pool; /* Tx descriptors */ + struct rte_bitmap *chim_bmap; /* Send buffer map */ + void *chim_bmem; uint32_t chim_szmax; /* Max size per buffer */ uint32_t chim_cnt; /* Max packets per buffer */ @@ -157,8 +161,8 @@ uint16_t hn_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t hn_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); -int hn_tx_pool_init(struct rte_eth_dev *dev); -void hn_tx_pool_uninit(struct rte_eth_dev *dev); +int hn_chim_init(struct rte_eth_dev *dev); +void hn_chim_uninit(struct rte_eth_dev *dev); int hn_dev_link_update(struct rte_eth_dev *dev, int wait); int hn_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v3 4/4] net/netvsc: don't enable RSS if only single receive queue 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 0/4] net/netvsc patches Stephen Hemminger ` (2 preceding siblings ...) 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 3/4] net/netvsc: split send buffers from transmit descriptors Stephen Hemminger @ 2020-03-18 20:51 ` Stephen Hemminger 3 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-18 20:51 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger, stable If application has multiple transmit queues but only a single receive queue, then do not enable RSS. Fixes: 8b945a7f7dcb ("drivers/net: update Rx RSS hash offload capabilities") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_ethdev.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c index ac6610838008..85f43996a623 100644 --- a/drivers/net/netvsc/hn_ethdev.c +++ b/drivers/net/netvsc/hn_ethdev.c @@ -597,11 +597,14 @@ static int hn_dev_configure(struct rte_eth_dev *dev) return err; } - err = hn_rndis_conf_rss(hv, 0); - if (err) { - PMD_DRV_LOG(NOTICE, - "initial RSS config failed"); - return err; + if ((dev_conf->rxmode.offloads & DEV_RX_OFFLOAD_RSS_HASH) && + dev->data->nb_rx_queues > 1) { + err = hn_rndis_conf_rss(hv, 0); + if (err) { + PMD_DRV_LOG(NOTICE, + "initial RSS config failed"); + return err; + } } } -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes 2020-03-16 23:56 [dpdk-dev] [PATCH 0/2] net/netvsc: patches Stephen Hemminger ` (4 preceding siblings ...) 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 0/4] net/netvsc patches Stephen Hemminger @ 2020-03-31 17:13 ` Stephen Hemminger 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 1/8] net/netvsc: propagate descriptor limits from VF to netvsc Stephen Hemminger ` (8 more replies) 5 siblings, 9 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-31 17:13 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger These are bug fixes for netvsc PMD mostly related to issues in the transmit ring discovered by users of multi-queue. v4 - add more bug fixes v3 - fix checkpatch complaints v2 - simplify the locking on multi-channel setup Stephen Hemminger (8): net/netvsc: propagate descriptor limits from VF to netvsc net/netvsc: handle receive packets during multi-channel setup net/netvsc: split send buffers from transmit descriptors net/netvsc: fix invalid rte_free on dev_close net/netvsc: remove process event optimization net/netvsc: handle transmit completions based on burst size bus/vmbus: simplify args to need_signal net/netvsc: avoid possible live lock drivers/bus/vmbus/vmbus_bufring.c | 8 +- drivers/net/netvsc/hn_ethdev.c | 25 ++- drivers/net/netvsc/hn_nvs.c | 41 ++++- drivers/net/netvsc/hn_rxtx.c | 281 ++++++++++++++++++------------ drivers/net/netvsc/hn_var.h | 12 +- drivers/net/netvsc/hn_vf.c | 13 ++ 6 files changed, 248 insertions(+), 132 deletions(-) -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v4 1/8] net/netvsc: propagate descriptor limits from VF to netvsc 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes Stephen Hemminger @ 2020-03-31 17:13 ` Stephen Hemminger 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 2/8] net/netvsc: handle receive packets during multi-channel setup Stephen Hemminger ` (7 subsequent siblings) 8 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-31 17:13 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger, stable If application cares about descriptor limits, the netvsc device values should reflect those of the VF as well. Fixes: dc7680e8597c ("net/netvsc: support integrated VF") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_vf.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/netvsc/hn_vf.c b/drivers/net/netvsc/hn_vf.c index 7a3734cadfa4..1261b2e2ef85 100644 --- a/drivers/net/netvsc/hn_vf.c +++ b/drivers/net/netvsc/hn_vf.c @@ -167,6 +167,17 @@ hn_nvs_handle_vfassoc(struct rte_eth_dev *dev, hn_vf_remove(hv); } +static void +hn_vf_merge_desc_lim(struct rte_eth_desc_lim *lim, + const struct rte_eth_desc_lim *vf_lim) +{ + lim->nb_max = RTE_MIN(vf_lim->nb_max, lim->nb_max); + lim->nb_min = RTE_MAX(vf_lim->nb_min, lim->nb_min); + lim->nb_align = RTE_MAX(vf_lim->nb_align, lim->nb_align); + lim->nb_seg_max = RTE_MIN(vf_lim->nb_seg_max, lim->nb_seg_max); + lim->nb_mtu_seg_max = RTE_MIN(vf_lim->nb_seg_max, lim->nb_seg_max); +} + /* * Merge the info from the VF and synthetic path. * use the default config of the VF @@ -196,11 +207,13 @@ static int hn_vf_info_merge(struct rte_eth_dev *vf_dev, info->max_tx_queues); info->tx_offload_capa &= vf_info.tx_offload_capa; info->tx_queue_offload_capa &= vf_info.tx_queue_offload_capa; + hn_vf_merge_desc_lim(&info->tx_desc_lim, &vf_info.tx_desc_lim); info->min_rx_bufsize = RTE_MAX(vf_info.min_rx_bufsize, info->min_rx_bufsize); info->max_rx_pktlen = RTE_MAX(vf_info.max_rx_pktlen, info->max_rx_pktlen); + hn_vf_merge_desc_lim(&info->rx_desc_lim, &vf_info.rx_desc_lim); return 0; } -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v4 2/8] net/netvsc: handle receive packets during multi-channel setup 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes Stephen Hemminger 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 1/8] net/netvsc: propagate descriptor limits from VF to netvsc Stephen Hemminger @ 2020-03-31 17:13 ` Stephen Hemminger 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 3/8] net/netvsc: split send buffers from transmit descriptors Stephen Hemminger ` (6 subsequent siblings) 8 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-31 17:13 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger, stable It is possible for a packet to arrive during the configuration process when setting up multiple queue mode. This would cause configure to fail; fix by just ignoring receive packets while waiting for control commands. Use the receive ring lock to avoid possible races between oddly behaved applications doing rx_burst and control operations concurrently. Fixes: 4e9c73e96e83 ("net/netvsc: add Hyper-V network device") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_nvs.c | 41 +++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/drivers/net/netvsc/hn_nvs.c b/drivers/net/netvsc/hn_nvs.c index 6b518685ab6f..477202b2a0b7 100644 --- a/drivers/net/netvsc/hn_nvs.c +++ b/drivers/net/netvsc/hn_nvs.c @@ -54,7 +54,7 @@ static int hn_nvs_req_send(struct hn_data *hv, } static int -hn_nvs_execute(struct hn_data *hv, +__hn_nvs_execute(struct hn_data *hv, void *req, uint32_t reqlen, void *resp, uint32_t resplen, uint32_t type) @@ -62,6 +62,7 @@ hn_nvs_execute(struct hn_data *hv, struct vmbus_channel *chan = hn_primary_chan(hv); char buffer[NVS_RESPSIZE_MAX]; const struct hn_nvs_hdr *hdr; + uint64_t xactid; uint32_t len; int ret; @@ -77,7 +78,7 @@ hn_nvs_execute(struct hn_data *hv, retry: len = sizeof(buffer); - ret = rte_vmbus_chan_recv(chan, buffer, &len, NULL); + ret = rte_vmbus_chan_recv(chan, buffer, &len, &xactid); if (ret == -EAGAIN) { rte_delay_us(HN_CHAN_INTERVAL_US); goto retry; @@ -88,7 +89,20 @@ hn_nvs_execute(struct hn_data *hv, return ret; } + if (len < sizeof(*hdr)) { + PMD_DRV_LOG(ERR, "response missing NVS header"); + return -EINVAL; + } + hdr = (struct hn_nvs_hdr *)buffer; + + /* Silently drop received packets while waiting for response */ + if (hdr->type == NVS_TYPE_RNDIS) { + hn_nvs_ack_rxbuf(chan, xactid); + --hv->rxbuf_outstanding; + goto retry; + } + if (hdr->type != type) { PMD_DRV_LOG(ERR, "unexpected NVS resp %#x, expect %#x", hdr->type, type); @@ -108,6 +122,29 @@ hn_nvs_execute(struct hn_data *hv, return 0; } + +/* + * Execute one control command and get the response. + * Only one command can be active on a channel at once + * Unlike BSD, DPDK does not have an interrupt context + * so the polling is required to wait for response. + */ +static int +hn_nvs_execute(struct hn_data *hv, + void *req, uint32_t reqlen, + void *resp, uint32_t resplen, + uint32_t type) +{ + struct hn_rx_queue *rxq = hv->primary; + int ret; + + rte_spinlock_lock(&rxq->ring_lock); + ret = __hn_nvs_execute(hv, req, reqlen, resp, resplen, type); + rte_spinlock_unlock(&rxq->ring_lock); + + return ret; +} + static int hn_nvs_doinit(struct hn_data *hv, uint32_t nvs_ver) { -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v4 3/8] net/netvsc: split send buffers from transmit descriptors 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes Stephen Hemminger 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 1/8] net/netvsc: propagate descriptor limits from VF to netvsc Stephen Hemminger 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 2/8] net/netvsc: handle receive packets during multi-channel setup Stephen Hemminger @ 2020-03-31 17:13 ` Stephen Hemminger 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 4/8] net/netvsc: fix invalid rte_free on dev_close Stephen Hemminger ` (5 subsequent siblings) 8 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-31 17:13 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger, stable The VMBus has reserved transmit area (per device) and transmit descriptors (per queue). The previous code was always having a 1:1 mapping between send buffers and descriptors. This can lead to one queue starving another and also buffer bloat. Change to working more like FreeBSD where there is a pool of transmit descriptors per queue. If send buffer is not available then no aggregation happens but the queue can still drain. Fixes: 4e9c73e96e83 ("net/netvsc: add Hyper-V network device") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_ethdev.c | 9 +- drivers/net/netvsc/hn_rxtx.c | 271 ++++++++++++++++++++------------- drivers/net/netvsc/hn_var.h | 10 +- 3 files changed, 180 insertions(+), 110 deletions(-) diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c index 564620748daf..ac6610838008 100644 --- a/drivers/net/netvsc/hn_ethdev.c +++ b/drivers/net/netvsc/hn_ethdev.c @@ -257,6 +257,9 @@ static int hn_dev_info_get(struct rte_eth_dev *dev, dev_info->max_rx_queues = hv->max_queues; dev_info->max_tx_queues = hv->max_queues; + dev_info->tx_desc_lim.nb_min = 1; + dev_info->tx_desc_lim.nb_max = 4096; + if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; @@ -982,7 +985,7 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) if (err) goto failed; - err = hn_tx_pool_init(eth_dev); + err = hn_chim_init(eth_dev); if (err) goto failed; @@ -1018,7 +1021,7 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) failed: PMD_INIT_LOG(NOTICE, "device init failed"); - hn_tx_pool_uninit(eth_dev); + hn_chim_uninit(eth_dev); hn_detach(hv); return err; } @@ -1042,7 +1045,7 @@ eth_hn_dev_uninit(struct rte_eth_dev *eth_dev) eth_dev->rx_pkt_burst = NULL; hn_detach(hv); - hn_tx_pool_uninit(eth_dev); + hn_chim_uninit(eth_dev); rte_vmbus_chan_close(hv->primary->chan); rte_free(hv->primary); ret = rte_eth_dev_owner_delete(hv->owner.id); diff --git a/drivers/net/netvsc/hn_rxtx.c b/drivers/net/netvsc/hn_rxtx.c index 7212780c156e..32c03e3da0c7 100644 --- a/drivers/net/netvsc/hn_rxtx.c +++ b/drivers/net/netvsc/hn_rxtx.c @@ -18,6 +18,7 @@ #include <rte_memzone.h> #include <rte_malloc.h> #include <rte_atomic.h> +#include <rte_bitmap.h> #include <rte_branch_prediction.h> #include <rte_ether.h> #include <rte_common.h> @@ -83,7 +84,7 @@ struct hn_txdesc { struct rte_mbuf *m; uint16_t queue_id; - uint16_t chim_index; + uint32_t chim_index; uint32_t chim_size; uint32_t data_size; uint32_t packets; @@ -98,11 +99,13 @@ struct hn_txdesc { RNDIS_PKTINFO_SIZE(NDIS_LSO2_INFO_SIZE) + \ RNDIS_PKTINFO_SIZE(NDIS_TXCSUM_INFO_SIZE)) +#define HN_RNDIS_PKT_ALIGNED RTE_ALIGN(HN_RNDIS_PKT_LEN, RTE_CACHE_LINE_SIZE) + /* Minimum space required for a packet */ #define HN_PKTSIZE_MIN(align) \ RTE_ALIGN(RTE_ETHER_MIN_LEN + HN_RNDIS_PKT_LEN, align) -#define DEFAULT_TX_FREE_THRESH 32U +#define DEFAULT_TX_FREE_THRESH 32 static void hn_update_packet_stats(struct hn_stats *stats, const struct rte_mbuf *m) @@ -150,63 +153,77 @@ hn_rndis_pktmsg_offset(uint32_t ofs) static void hn_txd_init(struct rte_mempool *mp __rte_unused, void *opaque, void *obj, unsigned int idx) { + struct hn_tx_queue *txq = opaque; struct hn_txdesc *txd = obj; - struct rte_eth_dev *dev = opaque; - struct rndis_packet_msg *pkt; memset(txd, 0, sizeof(*txd)); - txd->chim_index = idx; - - pkt = rte_malloc_socket("RNDIS_TX", HN_RNDIS_PKT_LEN, - rte_align32pow2(HN_RNDIS_PKT_LEN), - dev->device->numa_node); - if (!pkt) - rte_exit(EXIT_FAILURE, "can not allocate RNDIS header"); - txd->rndis_pkt = pkt; + txd->queue_id = txq->queue_id; + txd->chim_index = NVS_CHIM_IDX_INVALID; + txd->rndis_pkt = (struct rndis_packet_msg *)(char *)txq->tx_rndis + + idx * HN_RNDIS_PKT_ALIGNED; } -/* - * Unlike Linux and FreeBSD, this driver uses a mempool - * to limit outstanding transmits and reserve buffers - */ int -hn_tx_pool_init(struct rte_eth_dev *dev) +hn_chim_init(struct rte_eth_dev *dev) { struct hn_data *hv = dev->data->dev_private; - char name[RTE_MEMPOOL_NAMESIZE]; - struct rte_mempool *mp; + uint32_t i, chim_bmp_size; + + rte_spinlock_init(&hv->chim_lock); + chim_bmp_size = rte_bitmap_get_memory_footprint(hv->chim_cnt); + hv->chim_bmem = rte_zmalloc("hn_chim_bitmap", chim_bmp_size, + RTE_CACHE_LINE_SIZE); + if (hv->chim_bmem == NULL) { + PMD_INIT_LOG(ERR, "failed to allocate bitmap size %u", + chim_bmp_size); + return -1; + } - snprintf(name, sizeof(name), - "hn_txd_%u", dev->data->port_id); - - PMD_INIT_LOG(DEBUG, "create a TX send pool %s n=%u size=%zu socket=%d", - name, hv->chim_cnt, sizeof(struct hn_txdesc), - dev->device->numa_node); - - mp = rte_mempool_create(name, hv->chim_cnt, sizeof(struct hn_txdesc), - HN_TXD_CACHE_SIZE, 0, - NULL, NULL, - hn_txd_init, dev, - dev->device->numa_node, 0); - if (!mp) { - PMD_DRV_LOG(ERR, - "mempool %s create failed: %d", name, rte_errno); - return -rte_errno; + hv->chim_bmap = rte_bitmap_init(hv->chim_cnt, + hv->chim_bmem, chim_bmp_size); + if (hv->chim_bmap == NULL) { + PMD_INIT_LOG(ERR, "failed to init chim bitmap"); + return -1; } - hv->tx_pool = mp; + for (i = 0; i < hv->chim_cnt; i++) + rte_bitmap_set(hv->chim_bmap, i); + return 0; } void -hn_tx_pool_uninit(struct rte_eth_dev *dev) +hn_chim_uninit(struct rte_eth_dev *dev) { struct hn_data *hv = dev->data->dev_private; - if (hv->tx_pool) { - rte_mempool_free(hv->tx_pool); - hv->tx_pool = NULL; + rte_bitmap_free(hv->chim_bmap); + rte_free(hv->chim_bmem); + hv->chim_bmem = NULL; +} + +static uint32_t hn_chim_alloc(struct hn_data *hv) +{ + uint32_t index = NVS_CHIM_IDX_INVALID; + uint64_t slab; + + rte_spinlock_lock(&hv->chim_lock); + if (rte_bitmap_scan(hv->chim_bmap, &index, &slab)) + rte_bitmap_clear(hv->chim_bmap, index); + rte_spinlock_unlock(&hv->chim_lock); + + return index; +} + +static void hn_chim_free(struct hn_data *hv, uint32_t chim_idx) +{ + if (chim_idx >= hv->chim_cnt) { + PMD_DRV_LOG(ERR, "Invalid chimney index %u", chim_idx); + } else { + rte_spinlock_lock(&hv->chim_lock); + rte_bitmap_set(hv->chim_bmap, chim_idx); + rte_spinlock_unlock(&hv->chim_lock); } } @@ -220,15 +237,16 @@ static void hn_reset_txagg(struct hn_tx_queue *txq) int hn_dev_tx_queue_setup(struct rte_eth_dev *dev, - uint16_t queue_idx, uint16_t nb_desc __rte_unused, + uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf) { struct hn_data *hv = dev->data->dev_private; struct hn_tx_queue *txq; + char name[RTE_MEMPOOL_NAMESIZE]; uint32_t tx_free_thresh; - int err; + int err = -ENOMEM; PMD_INIT_FUNC_TRACE(); @@ -244,14 +262,42 @@ hn_dev_tx_queue_setup(struct rte_eth_dev *dev, tx_free_thresh = tx_conf->tx_free_thresh; if (tx_free_thresh == 0) - tx_free_thresh = RTE_MIN(hv->chim_cnt / 4, + tx_free_thresh = RTE_MIN(nb_desc / 4, DEFAULT_TX_FREE_THRESH); - if (tx_free_thresh >= hv->chim_cnt - 3) - tx_free_thresh = hv->chim_cnt - 3; + if (tx_free_thresh + 3 >= nb_desc) { + PMD_INIT_LOG(ERR, + "tx_free_thresh must be less than the number of TX entries minus 3(%u)." + " (tx_free_thresh=%u port=%u queue=%u)\n", + nb_desc - 3, + tx_free_thresh, dev->data->port_id, queue_idx); + return -EINVAL; + } txq->free_thresh = tx_free_thresh; + snprintf(name, sizeof(name), + "hn_txd_%u_%u", dev->data->port_id, queue_idx); + + PMD_INIT_LOG(DEBUG, "TX descriptor pool %s n=%u size=%zu", + name, nb_desc, sizeof(struct hn_txdesc)); + + txq->tx_rndis = rte_calloc("hn_txq_rndis", nb_desc, + HN_RNDIS_PKT_ALIGNED, RTE_CACHE_LINE_SIZE); + if (txq->tx_rndis == NULL) + goto error; + + txq->txdesc_pool = rte_mempool_create(name, nb_desc, + sizeof(struct hn_txdesc), + 0, 0, NULL, NULL, + hn_txd_init, txq, + dev->device->numa_node, 0); + if (txq->txdesc_pool == NULL) { + PMD_DRV_LOG(ERR, + "mempool %s create failed: %d", name, rte_errno); + goto error; + } + txq->agg_szmax = RTE_MIN(hv->chim_szmax, hv->rndis_agg_size); txq->agg_pktmax = hv->rndis_agg_pkts; txq->agg_align = hv->rndis_agg_align; @@ -260,31 +306,57 @@ hn_dev_tx_queue_setup(struct rte_eth_dev *dev, err = hn_vf_tx_queue_setup(dev, queue_idx, nb_desc, socket_id, tx_conf); - if (err) { - rte_free(txq); - return err; + if (err == 0) { + dev->data->tx_queues[queue_idx] = txq; + return 0; } - dev->data->tx_queues[queue_idx] = txq; - return 0; +error: + if (txq->txdesc_pool) + rte_mempool_free(txq->txdesc_pool); + rte_free(txq->tx_rndis); + rte_free(txq); + return err; +} + + +static struct hn_txdesc *hn_txd_get(struct hn_tx_queue *txq) +{ + struct hn_txdesc *txd; + + if (rte_mempool_get(txq->txdesc_pool, (void **)&txd)) { + ++txq->stats.ring_full; + PMD_TX_LOG(DEBUG, "tx pool exhausted!"); + return NULL; + } + + txd->m = NULL; + txd->packets = 0; + txd->data_size = 0; + txd->chim_size = 0; + + return txd; +} + +static void hn_txd_put(struct hn_tx_queue *txq, struct hn_txdesc *txd) +{ + rte_mempool_put(txq->txdesc_pool, txd); } void hn_dev_tx_queue_release(void *arg) { struct hn_tx_queue *txq = arg; - struct hn_txdesc *txd; PMD_INIT_FUNC_TRACE(); if (!txq) return; - /* If any pending data is still present just drop it */ - txd = txq->agg_txd; - if (txd) - rte_mempool_put(txq->hv->tx_pool, txd); + if (txq->txdesc_pool) + rte_mempool_free(txq->txdesc_pool); + rte_free(txq->tx_rndis); rte_free(txq); } @@ -292,6 +364,7 @@ static void hn_nvs_send_completed(struct rte_eth_dev *dev, uint16_t queue_id, unsigned long xactid, const struct hn_nvs_rndis_ack *ack) { + struct hn_data *hv = dev->data->dev_private; struct hn_txdesc *txd = (struct hn_txdesc *)xactid; struct hn_tx_queue *txq; @@ -312,9 +385,11 @@ hn_nvs_send_completed(struct rte_eth_dev *dev, uint16_t queue_id, ++txq->stats.errors; } - rte_pktmbuf_free(txd->m); + if (txd->chim_index != NVS_CHIM_IDX_INVALID) + hn_chim_free(hv, txd->chim_index); - rte_mempool_put(txq->hv->tx_pool, txd); + rte_pktmbuf_free(txd->m); + hn_txd_put(txq, txd); } /* Handle transmit completion events */ @@ -1036,28 +1111,15 @@ static int hn_flush_txagg(struct hn_tx_queue *txq, bool *need_sig) return ret; } -static struct hn_txdesc *hn_new_txd(struct hn_data *hv, - struct hn_tx_queue *txq) -{ - struct hn_txdesc *txd; - - if (rte_mempool_get(hv->tx_pool, (void **)&txd)) { - ++txq->stats.ring_full; - PMD_TX_LOG(DEBUG, "tx pool exhausted!"); - return NULL; - } - - txd->m = NULL; - txd->queue_id = txq->queue_id; - txd->packets = 0; - txd->data_size = 0; - txd->chim_size = 0; - - return txd; -} - +/* + * Try and find a place in a send chimney buffer to put + * the small packet. If space is available, this routine + * returns a pointer of where to place the data. + * If no space, caller should try direct transmit. + */ static void * -hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq, uint32_t pktsize) +hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq, + struct hn_txdesc *txd, uint32_t pktsize) { struct hn_txdesc *agg_txd = txq->agg_txd; struct rndis_packet_msg *pkt; @@ -1085,7 +1147,7 @@ hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq, uint32_t pktsize) } chim = (uint8_t *)pkt + pkt->len; - + txq->agg_prevpkt = chim; txq->agg_pktleft--; txq->agg_szleft -= pktsize; if (txq->agg_szleft < HN_PKTSIZE_MIN(txq->agg_align)) { @@ -1095,18 +1157,21 @@ hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq, uint32_t pktsize) */ txq->agg_pktleft = 0; } - } else { - agg_txd = hn_new_txd(hv, txq); - if (!agg_txd) - return NULL; - - chim = (uint8_t *)hv->chim_res->addr - + agg_txd->chim_index * hv->chim_szmax; - txq->agg_txd = agg_txd; - txq->agg_pktleft = txq->agg_pktmax - 1; - txq->agg_szleft = txq->agg_szmax - pktsize; + hn_txd_put(txq, txd); + return chim; } + + txd->chim_index = hn_chim_alloc(hv); + if (txd->chim_index == NVS_CHIM_IDX_INVALID) + return NULL; + + chim = (uint8_t *)hv->chim_res->addr + + txd->chim_index * hv->chim_szmax; + + txq->agg_txd = txd; + txq->agg_pktleft = txq->agg_pktmax - 1; + txq->agg_szleft = txq->agg_szmax - pktsize; txq->agg_prevpkt = chim; return chim; @@ -1329,13 +1394,18 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) return (*vf_dev->tx_pkt_burst)(sub_q, tx_pkts, nb_pkts); } - if (rte_mempool_avail_count(hv->tx_pool) <= txq->free_thresh) + if (rte_mempool_avail_count(txq->txdesc_pool) <= txq->free_thresh) hn_process_events(hv, txq->queue_id, 0); for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) { struct rte_mbuf *m = tx_pkts[nb_tx]; uint32_t pkt_size = m->pkt_len + HN_RNDIS_PKT_LEN; struct rndis_packet_msg *pkt; + struct hn_txdesc *txd; + + txd = hn_txd_get(txq); + if (txd == NULL) + break; /* For small packets aggregate them in chimney buffer */ if (m->pkt_len < HN_TXCOPY_THRESHOLD && pkt_size <= txq->agg_szmax) { @@ -1346,7 +1416,8 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) goto fail; } - pkt = hn_try_txagg(hv, txq, pkt_size); + + pkt = hn_try_txagg(hv, txq, txd, pkt_size); if (unlikely(!pkt)) break; @@ -1360,21 +1431,13 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) hn_flush_txagg(txq, &need_sig)) goto fail; } else { - struct hn_txdesc *txd; - - /* can send chimney data and large packet at once */ - txd = txq->agg_txd; - if (txd) { - hn_reset_txagg(txq); - } else { - txd = hn_new_txd(hv, txq); - if (unlikely(!txd)) - break; - } + /* Send any outstanding packets in buffer */ + if (txq->agg_txd && hn_flush_txagg(txq, &need_sig)) + goto fail; pkt = txd->rndis_pkt; txd->m = m; - txd->data_size += m->pkt_len; + txd->data_size = m->pkt_len; ++txd->packets; hn_encap(pkt, queue_id, m); @@ -1383,7 +1446,7 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) if (unlikely(ret != 0)) { PMD_TX_LOG(NOTICE, "sg send failed: %d", ret); ++txq->stats.errors; - rte_mempool_put(hv->tx_pool, txd); + hn_txd_put(txq, txd); goto fail; } } diff --git a/drivers/net/netvsc/hn_var.h b/drivers/net/netvsc/hn_var.h index 05bc492511ec..822d737bd3cc 100644 --- a/drivers/net/netvsc/hn_var.h +++ b/drivers/net/netvsc/hn_var.h @@ -52,6 +52,8 @@ struct hn_tx_queue { uint16_t port_id; uint16_t queue_id; uint32_t free_thresh; + struct rte_mempool *txdesc_pool; + void *tx_rndis; /* Applied packet transmission aggregation limits. */ uint32_t agg_szmax; @@ -115,8 +117,10 @@ struct hn_data { uint16_t num_queues; uint64_t rss_offloads; + rte_spinlock_t chim_lock; struct rte_mem_resource *chim_res; /* UIO resource for Tx */ - struct rte_mempool *tx_pool; /* Tx descriptors */ + struct rte_bitmap *chim_bmap; /* Send buffer map */ + void *chim_bmem; uint32_t chim_szmax; /* Max size per buffer */ uint32_t chim_cnt; /* Max packets per buffer */ @@ -157,8 +161,8 @@ uint16_t hn_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t hn_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); -int hn_tx_pool_init(struct rte_eth_dev *dev); -void hn_tx_pool_uninit(struct rte_eth_dev *dev); +int hn_chim_init(struct rte_eth_dev *dev); +void hn_chim_uninit(struct rte_eth_dev *dev); int hn_dev_link_update(struct rte_eth_dev *dev, int wait); int hn_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v4 4/8] net/netvsc: fix invalid rte_free on dev_close 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes Stephen Hemminger ` (2 preceding siblings ...) 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 3/8] net/netvsc: split send buffers from transmit descriptors Stephen Hemminger @ 2020-03-31 17:14 ` Stephen Hemminger 2020-04-06 16:00 ` [dpdk-dev] [dpdk-stable] " Ferruh Yigit 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 5/8] net/netvsc: remove process event optimization Stephen Hemminger ` (4 subsequent siblings) 8 siblings, 1 reply; 27+ messages in thread From: Stephen Hemminger @ 2020-03-31 17:14 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger, stable The netvsc PMD was putting the mac address in private data but the core rte_ethdev doesn't allow that it. It has to be in rte_malloc'd memory or the a message will be printed on shutdown/close. EAL: Invalid memory Fixes: f8279f47dd89 ("net/netvsc: fix crash in secondary process") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_ethdev.c | 16 ++++++++++------ drivers/net/netvsc/hn_var.h | 2 -- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c index ac6610838008..05f1a25a1abc 100644 --- a/drivers/net/netvsc/hn_ethdev.c +++ b/drivers/net/netvsc/hn_ethdev.c @@ -134,8 +134,6 @@ eth_dev_vmbus_allocate(struct rte_vmbus_device *dev, size_t private_data_size) static void eth_dev_vmbus_release(struct rte_eth_dev *eth_dev) { - /* mac_addrs must not be freed alone because part of dev_private */ - eth_dev->data->mac_addrs = NULL; /* free ether device */ rte_eth_dev_release_port(eth_dev); @@ -937,9 +935,6 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) eth_dev->tx_pkt_burst = &hn_xmit_pkts; eth_dev->rx_pkt_burst = &hn_recv_pkts; - /* Since Hyper-V only supports one MAC address, just use local data */ - eth_dev->data->mac_addrs = &hv->mac_addr; - /* * for secondary processes, we don't initialize any further as primary * has already done this work. @@ -947,6 +942,15 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; + /* Since Hyper-V only supports one MAC address */ + eth_dev->data->mac_addrs = rte_calloc("hv_mac", HN_MAX_MAC_ADDRS, + sizeof(struct rte_ether_addr), 0); + if (eth_dev->data->mac_addrs == NULL) { + PMD_INIT_LOG(ERR, + "Failed to allocate memory store MAC addresses"); + return -ENOMEM; + } + hv->vmbus = vmbus; hv->rxbuf_res = &vmbus->resource[HV_RECV_BUF_MAP]; hv->chim_res = &vmbus->resource[HV_SEND_BUF_MAP]; @@ -989,7 +993,7 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) if (err) goto failed; - err = hn_rndis_get_eaddr(hv, hv->mac_addr.addr_bytes); + err = hn_rndis_get_eaddr(hv, eth_dev->data->mac_addrs->addr_bytes); if (err) goto failed; diff --git a/drivers/net/netvsc/hn_var.h b/drivers/net/netvsc/hn_var.h index 822d737bd3cc..b4c61717379f 100644 --- a/drivers/net/netvsc/hn_var.h +++ b/drivers/net/netvsc/hn_var.h @@ -139,8 +139,6 @@ struct hn_data { uint8_t rss_key[40]; uint16_t rss_ind[128]; - struct rte_ether_addr mac_addr; - struct rte_eth_dev_owner owner; struct rte_intr_handle vf_intr; -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [dpdk-dev] [dpdk-stable] [PATCH v4 4/8] net/netvsc: fix invalid rte_free on dev_close 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 4/8] net/netvsc: fix invalid rte_free on dev_close Stephen Hemminger @ 2020-04-06 16:00 ` Ferruh Yigit 0 siblings, 0 replies; 27+ messages in thread From: Ferruh Yigit @ 2020-04-06 16:00 UTC (permalink / raw) To: Stephen Hemminger, dev; +Cc: stable On 3/31/2020 6:14 PM, Stephen Hemminger wrote: > The netvsc PMD was putting the mac address in private data but the > core rte_ethdev doesn't allow that it. It has to be in rte_malloc'd > memory or the a message will be printed on shutdown/close. It doesn't have to be rte_malloc'ed. Setting 'eth_dev->data->mac_addrs' to null in 'hn_dev_close()' should fix it. But dynamically allocating it also works if that is what preferred. > EAL: Invalid memory > > Fixes: f8279f47dd89 ("net/netvsc: fix crash in secondary process") > Cc: stable@dpdk.org > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> > --- > drivers/net/netvsc/hn_ethdev.c | 16 ++++++++++------ > drivers/net/netvsc/hn_var.h | 2 -- > 2 files changed, 10 insertions(+), 8 deletions(-) > > diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c > index ac6610838008..05f1a25a1abc 100644 > --- a/drivers/net/netvsc/hn_ethdev.c > +++ b/drivers/net/netvsc/hn_ethdev.c > @@ -134,8 +134,6 @@ eth_dev_vmbus_allocate(struct rte_vmbus_device *dev, size_t private_data_size) > static void > eth_dev_vmbus_release(struct rte_eth_dev *eth_dev) > { > - /* mac_addrs must not be freed alone because part of dev_private */ > - eth_dev->data->mac_addrs = NULL; > /* free ether device */ > rte_eth_dev_release_port(eth_dev); > > @@ -937,9 +935,6 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) > eth_dev->tx_pkt_burst = &hn_xmit_pkts; > eth_dev->rx_pkt_burst = &hn_recv_pkts; > > - /* Since Hyper-V only supports one MAC address, just use local data */ > - eth_dev->data->mac_addrs = &hv->mac_addr; > - > /* > * for secondary processes, we don't initialize any further as primary > * has already done this work. > @@ -947,6 +942,15 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) > if (rte_eal_process_type() != RTE_PROC_PRIMARY) > return 0; > > + /* Since Hyper-V only supports one MAC address */ > + eth_dev->data->mac_addrs = rte_calloc("hv_mac", HN_MAX_MAC_ADDRS, > + sizeof(struct rte_ether_addr), 0); > + if (eth_dev->data->mac_addrs == NULL) { > + PMD_INIT_LOG(ERR, > + "Failed to allocate memory store MAC addresses"); > + return -ENOMEM; > + } > + > hv->vmbus = vmbus; > hv->rxbuf_res = &vmbus->resource[HV_RECV_BUF_MAP]; > hv->chim_res = &vmbus->resource[HV_SEND_BUF_MAP]; > @@ -989,7 +993,7 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) > if (err) > goto failed; > > - err = hn_rndis_get_eaddr(hv, hv->mac_addr.addr_bytes); > + err = hn_rndis_get_eaddr(hv, eth_dev->data->mac_addrs->addr_bytes); > if (err) > goto failed; > > diff --git a/drivers/net/netvsc/hn_var.h b/drivers/net/netvsc/hn_var.h > index 822d737bd3cc..b4c61717379f 100644 > --- a/drivers/net/netvsc/hn_var.h > +++ b/drivers/net/netvsc/hn_var.h > @@ -139,8 +139,6 @@ struct hn_data { > uint8_t rss_key[40]; > uint16_t rss_ind[128]; > > - struct rte_ether_addr mac_addr; > - > struct rte_eth_dev_owner owner; > struct rte_intr_handle vf_intr; > > ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v4 5/8] net/netvsc: remove process event optimization 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes Stephen Hemminger ` (3 preceding siblings ...) 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 4/8] net/netvsc: fix invalid rte_free on dev_close Stephen Hemminger @ 2020-03-31 17:14 ` Stephen Hemminger 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 6/8] net/netvsc: handle transmit completions based on burst size Stephen Hemminger ` (3 subsequent siblings) 8 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-31 17:14 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger, stable Remove unlocked check for data in receive ring. This check is not safe because of missing barriers etc. Fixes: 4e9c73e96e83 ("net/netvsc: add Hyper-V network device") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_rxtx.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/netvsc/hn_rxtx.c b/drivers/net/netvsc/hn_rxtx.c index 32c03e3da0c7..e8df84604202 100644 --- a/drivers/net/netvsc/hn_rxtx.c +++ b/drivers/net/netvsc/hn_rxtx.c @@ -969,10 +969,6 @@ uint32_t hn_process_events(struct hn_data *hv, uint16_t queue_id, rxq = queue_id == 0 ? hv->primary : dev->data->rx_queues[queue_id]; - /* If no pending data then nothing to do */ - if (rte_vmbus_chan_rx_empty(rxq->chan)) - return 0; - /* * Since channel is shared between Rx and TX queue need to have a lock * since DPDK does not force same CPU to be used for Rx/Tx. -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v4 6/8] net/netvsc: handle transmit completions based on burst size 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes Stephen Hemminger ` (4 preceding siblings ...) 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 5/8] net/netvsc: remove process event optimization Stephen Hemminger @ 2020-03-31 17:14 ` Stephen Hemminger 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 7/8] bus/vmbus: simplify args to need_signal Stephen Hemminger ` (2 subsequent siblings) 8 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-31 17:14 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger, stable If tx_free_thresh is quite low, it is possible that we need to cleanup based on burst size. Fixes: fc30efe3a22e ("net/netvsc: change Rx descriptor setup and sizing") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_rxtx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/netvsc/hn_rxtx.c b/drivers/net/netvsc/hn_rxtx.c index e8df84604202..cbdfcc628b75 100644 --- a/drivers/net/netvsc/hn_rxtx.c +++ b/drivers/net/netvsc/hn_rxtx.c @@ -1375,7 +1375,7 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) struct hn_data *hv = txq->hv; struct rte_eth_dev *vf_dev; bool need_sig = false; - uint16_t nb_tx; + uint16_t nb_tx, avail; int ret; if (unlikely(hv->closed)) @@ -1390,7 +1390,8 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) return (*vf_dev->tx_pkt_burst)(sub_q, tx_pkts, nb_pkts); } - if (rte_mempool_avail_count(txq->txdesc_pool) <= txq->free_thresh) + avail = rte_mempool_avail_count(txq->txdesc_pool); + if (nb_pkts > avail || avail <= txq->free_thresh) hn_process_events(hv, txq->queue_id, 0); for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) { -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v4 7/8] bus/vmbus: simplify args to need_signal 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes Stephen Hemminger ` (5 preceding siblings ...) 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 6/8] net/netvsc: handle transmit completions based on burst size Stephen Hemminger @ 2020-03-31 17:14 ` Stephen Hemminger 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 8/8] net/netvsc: avoid possible live lock Stephen Hemminger 2020-04-07 8:34 ` [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes Ferruh Yigit 8 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-31 17:14 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger The transmit need signal function can avoid an unnecessary dereference by passing the right pointer. This also makes code better match FreeBSD driver. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/bus/vmbus/vmbus_bufring.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/bus/vmbus/vmbus_bufring.c b/drivers/bus/vmbus/vmbus_bufring.c index c88001605dbb..c4aa07b307ff 100644 --- a/drivers/bus/vmbus/vmbus_bufring.c +++ b/drivers/bus/vmbus/vmbus_bufring.c @@ -54,10 +54,10 @@ void vmbus_br_setup(struct vmbus_br *br, void *buf, unsigned int blen) * data have arrived. */ static inline bool -vmbus_txbr_need_signal(const struct vmbus_br *tbr, uint32_t old_windex) +vmbus_txbr_need_signal(const struct vmbus_bufring *vbr, uint32_t old_windex) { rte_smp_mb(); - if (tbr->vbr->imask) + if (vbr->imask) return false; rte_smp_rmb(); @@ -66,7 +66,7 @@ vmbus_txbr_need_signal(const struct vmbus_br *tbr, uint32_t old_windex) * This is the only case we need to signal when the * ring transitions from being empty to non-empty. */ - return old_windex == tbr->vbr->rindex; + return old_windex == vbr->rindex; } static inline uint32_t @@ -163,7 +163,7 @@ vmbus_txbr_write(struct vmbus_br *tbr, const struct iovec iov[], int iovlen, rte_pause(); /* If host had read all data before this, then need to signal */ - *need_sig |= vmbus_txbr_need_signal(tbr, old_windex); + *need_sig |= vmbus_txbr_need_signal(vbr, old_windex); return 0; } -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [dpdk-dev] [PATCH v4 8/8] net/netvsc: avoid possible live lock 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes Stephen Hemminger ` (6 preceding siblings ...) 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 7/8] bus/vmbus: simplify args to need_signal Stephen Hemminger @ 2020-03-31 17:14 ` Stephen Hemminger 2020-04-07 8:34 ` [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes Ferruh Yigit 8 siblings, 0 replies; 27+ messages in thread From: Stephen Hemminger @ 2020-03-31 17:14 UTC (permalink / raw) To: dev; +Cc: Stephen Hemminger Since the ring buffer with host is shared for both transmit completions and receive packets, it is possible that transmitter could get starved if receive ring gets full. Better to process all outstanding events which frees up transmit buffer slots, even if means dropping some packets. Fixes: 7e6c82430702 ("net/netvsc: avoid over filling Rx descriptor ring") Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- drivers/net/netvsc/hn_rxtx.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/netvsc/hn_rxtx.c b/drivers/net/netvsc/hn_rxtx.c index cbdfcc628b75..19f00a05285f 100644 --- a/drivers/net/netvsc/hn_rxtx.c +++ b/drivers/net/netvsc/hn_rxtx.c @@ -1032,9 +1032,6 @@ uint32_t hn_process_events(struct hn_data *hv, uint16_t queue_id, if (tx_limit && tx_done >= tx_limit) break; - - if (rxq->rx_ring && rte_ring_full(rxq->rx_ring)) - break; } if (bytes_read > 0) -- 2.20.1 ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes Stephen Hemminger ` (7 preceding siblings ...) 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 8/8] net/netvsc: avoid possible live lock Stephen Hemminger @ 2020-04-07 8:34 ` Ferruh Yigit 8 siblings, 0 replies; 27+ messages in thread From: Ferruh Yigit @ 2020-04-07 8:34 UTC (permalink / raw) To: Stephen Hemminger, dev On 3/31/2020 6:13 PM, Stephen Hemminger wrote: > These are bug fixes for netvsc PMD mostly related to issues > in the transmit ring discovered by users of multi-queue. > > v4 - add more bug fixes > v3 - fix checkpatch complaints > v2 - simplify the locking on multi-channel setup > > Stephen Hemminger (8): > net/netvsc: propagate descriptor limits from VF to netvsc > net/netvsc: handle receive packets during multi-channel setup > net/netvsc: split send buffers from transmit descriptors > net/netvsc: fix invalid rte_free on dev_close > net/netvsc: remove process event optimization > net/netvsc: handle transmit completions based on burst size > bus/vmbus: simplify args to need_signal > net/netvsc: avoid possible live lock Series applied to dpdk-next-net/master, thanks. ^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2020-04-07 8:34 UTC | newest] Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-03-16 23:56 [dpdk-dev] [PATCH 0/2] net/netvsc: patches Stephen Hemminger 2020-03-16 23:56 ` [dpdk-dev] [PATCH 1/2] net/netvsc: handle receive packets during multi-channel setup Stephen Hemminger 2020-03-16 23:56 ` [dpdk-dev] [PATCH 2/2] net/netvsc: avoid mixing buffered and direct packets Stephen Hemminger 2020-03-18 17:33 ` [dpdk-dev] [PATCH 0/2] net/netvsc: patches Ferruh Yigit 2020-03-18 18:09 ` Stephen Hemminger 2020-03-19 9:06 ` Ferruh Yigit 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 0/4] net/netvsc patches Stephen Hemminger 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 1/4] net/netvsc: propogate descriptor limits from VF to netvsc Stephen Hemminger 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 2/4] net/netvsc: handle receive packets during multi-channel setup Stephen Hemminger 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 3/4] net/netvsc: split send buffers from transmit descriptors Stephen Hemminger 2020-03-18 20:29 ` [dpdk-dev] [PATCH v2 4/4] net/netvsc: don't enable RSS if only single receive queue Stephen Hemminger 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 0/4] net/netvsc patches Stephen Hemminger 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 1/4] net/netvsc: propagate descriptor limits from VF to netvsc Stephen Hemminger 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 2/4] net/netvsc: handle receive packets during multi-channel setup Stephen Hemminger 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 3/4] net/netvsc: split send buffers from transmit descriptors Stephen Hemminger 2020-03-18 20:51 ` [dpdk-dev] [PATCH v3 4/4] net/netvsc: don't enable RSS if only single receive queue Stephen Hemminger 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes Stephen Hemminger 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 1/8] net/netvsc: propagate descriptor limits from VF to netvsc Stephen Hemminger 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 2/8] net/netvsc: handle receive packets during multi-channel setup Stephen Hemminger 2020-03-31 17:13 ` [dpdk-dev] [PATCH v4 3/8] net/netvsc: split send buffers from transmit descriptors Stephen Hemminger 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 4/8] net/netvsc: fix invalid rte_free on dev_close Stephen Hemminger 2020-04-06 16:00 ` [dpdk-dev] [dpdk-stable] " Ferruh Yigit 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 5/8] net/netvsc: remove process event optimization Stephen Hemminger 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 6/8] net/netvsc: handle transmit completions based on burst size Stephen Hemminger 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 7/8] bus/vmbus: simplify args to need_signal Stephen Hemminger 2020-03-31 17:14 ` [dpdk-dev] [PATCH v4 8/8] net/netvsc: avoid possible live lock Stephen Hemminger 2020-04-07 8:34 ` [dpdk-dev] [PATCH v4 0/8] net/netvsc: bug fixes Ferruh Yigit
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).