From 423d9322c20b379d7fe64b2ca9f1d035f15c08cd Mon Sep 17 00:00:00 2001 From: Sam Andrew <108894698+samuelandrew@users.noreply.github.com> Date: Fri, 4 Aug 2023 17:50:44 +0000 Subject: [PATCH 1/7] implement MTU change for netvsc driver --- drivers/bus/vmbus/vmbus_common.c | 4 +- drivers/net/netvsc/hn_ethdev.c | 168 +++++++++++++++++++++++++------ drivers/net/netvsc/hn_rndis.c | 7 ++ drivers/net/netvsc/hn_rndis.h | 1 + drivers/net/netvsc/hn_var.h | 2 +- 5 files changed, 148 insertions(+), 34 deletions(-) diff --git a/drivers/bus/vmbus/vmbus_common.c b/drivers/bus/vmbus/vmbus_common.c index 95f3ad78bc8..fd205e8ac34 100644 --- a/drivers/bus/vmbus/vmbus_common.c +++ b/drivers/bus/vmbus/vmbus_common.c @@ -39,7 +39,9 @@ vmbus_map_resource(void *requested_addr, int fd, off_t offset, size_t size, "mmap(%d, %p, %zu, %ld) failed: %s", fd, requested_addr, size, (long)offset, strerror(errno)); - } + } else + VMBUS_LOG(DEBUG, " VMBUS memory mapped at %p", + mapaddr); return mapaddr; } diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c index d0bbc0a4c0c..f785c718fb8 100644 --- a/drivers/net/netvsc/hn_ethdev.c +++ b/drivers/net/netvsc/hn_ethdev.c @@ -1059,37 +1059,6 @@ hn_dev_close(struct rte_eth_dev *dev) return ret; } -static const struct eth_dev_ops hn_eth_dev_ops = { - .dev_configure = hn_dev_configure, - .dev_start = hn_dev_start, - .dev_stop = hn_dev_stop, - .dev_close = hn_dev_close, - .dev_infos_get = hn_dev_info_get, - .txq_info_get = hn_dev_tx_queue_info, - .rxq_info_get = hn_dev_rx_queue_info, - .dev_supported_ptypes_get = hn_vf_supported_ptypes, - .promiscuous_enable = hn_dev_promiscuous_enable, - .promiscuous_disable = hn_dev_promiscuous_disable, - .allmulticast_enable = hn_dev_allmulticast_enable, - .allmulticast_disable = hn_dev_allmulticast_disable, - .set_mc_addr_list = hn_dev_mc_addr_list, - .reta_update = hn_rss_reta_update, - .reta_query = hn_rss_reta_query, - .rss_hash_update = hn_rss_hash_update, - .rss_hash_conf_get = hn_rss_hash_conf_get, - .tx_queue_setup = hn_dev_tx_queue_setup, - .tx_queue_release = hn_dev_tx_queue_release, - .tx_done_cleanup = hn_dev_tx_done_cleanup, - .rx_queue_setup = hn_dev_rx_queue_setup, - .rx_queue_release = hn_dev_rx_queue_release, - .link_update = hn_dev_link_update, - .stats_get = hn_dev_stats_get, - .stats_reset = hn_dev_stats_reset, - .xstats_get = hn_dev_xstats_get, - .xstats_get_names = hn_dev_xstats_get_names, - .xstats_reset = hn_dev_xstats_reset, -}; - /* * Setup connection between PMD and kernel. */ @@ -1129,12 +1098,141 @@ hn_detach(struct hn_data *hv) hn_rndis_detach(hv); } +static int +hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) +{ + struct hn_data *hv = dev->data->dev_private; + struct rte_eth_dev *vf_dev; + unsigned int orig_mtu = dev->data->mtu; + uint32_t rndis_mtu; + int ret = 0; + + if (dev->data->dev_started) { + PMD_DRV_LOG(ERR, "Device must be stopped before changing MTU"); + return -EIO; + } + + ret = hn_dev_close(dev); + if (ret) + return ret; + + /* Change MTU of underlying VF netdev first, if it exists */ + rte_rwlock_read_lock(&hv->vf_lock); + vf_dev = hn_get_vf_dev(hv); + if (hv->vf_ctx.vf_vsc_switched && vf_dev) { + ret = vf_dev->dev_ops->mtu_set(vf_dev, mtu); + if (ret) { + rte_rwlock_read_unlock(&hv->vf_lock); + goto out; + } + } + rte_rwlock_read_unlock(&hv->vf_lock); + + /* Release channel resources */ + hn_detach(hv); + hn_chim_uninit(dev); + rte_vmbus_chan_close(hv->channels[0]); + + /* Unmap and re-map vmbus device */ + rte_vmbus_unmap_device(hv->vmbus); + ret = rte_vmbus_map_device(hv->vmbus); + if (ret) { + /* This is a catastrophic error - the device is unusable */ + PMD_DRV_LOG(ERR, "Could not re-map vmbus device!"); + return ret; + } + + /* Update pointers to re-mapped memory */ + hv->rxbuf_res = hv->vmbus->resource[HV_RECV_BUF_MAP]; + hv->chim_res = hv->vmbus->resource[HV_SEND_BUF_MAP]; + + /* Re-open the vmbus channel */ + ret = rte_vmbus_chan_open(hv->vmbus, &hv->channels[0]); + if (ret) { + /* This is a catastrophic error - the device is unusable */ + PMD_DRV_LOG(ERR, "Could not re-open vmbus channel!"); + } + + rte_vmbus_set_latency(hv->vmbus, hv->channels[0], hv->latency); + + hv->primary = hn_rx_queue_alloc(hv, 0, + dev->device->numa_node); + + if (!hv->primary) { + /* This is a catastrophic error - the device is unusable */ + PMD_DRV_LOG(ERR, "No memory to allocate rx queue!"); + return -ENOMEM; + } + + ret = hn_attach(hv, mtu); + if (ret) + goto error; + + ret = hn_chim_init(dev); + if (!ret) + goto out; + +error: + /* In case of error, attempt rollback to original MTU */ + if (hn_attach(hv, orig_mtu)) + PMD_DRV_LOG(ERR, "Restoring original MTU failed"); + + rte_rwlock_read_lock(&hv->vf_lock); + vf_dev = hn_get_vf_dev(hv); + if (hv->vf_ctx.vf_vsc_switched && vf_dev) + vf_dev->dev_ops->mtu_set(vf_dev, orig_mtu); + rte_rwlock_read_unlock(&hv->vf_lock); + +out: + if (hn_rndis_get_mtu(hv, &rndis_mtu)) + PMD_DRV_LOG(ERR, "Could not get MTU via RNDIS"); + else { + dev->data->mtu = (uint16_t)rndis_mtu; + PMD_DRV_LOG(DEBUG, "RNDIS MTU is %u", dev->data->mtu); + } + + return ret; +} + +static const struct eth_dev_ops hn_eth_dev_ops = { + .dev_configure = hn_dev_configure, + .dev_start = hn_dev_start, + .dev_stop = hn_dev_stop, + .dev_close = hn_dev_close, + .dev_infos_get = hn_dev_info_get, + .txq_info_get = hn_dev_tx_queue_info, + .rxq_info_get = hn_dev_rx_queue_info, + .dev_supported_ptypes_get = hn_vf_supported_ptypes, + .promiscuous_enable = hn_dev_promiscuous_enable, + .promiscuous_disable = hn_dev_promiscuous_disable, + .allmulticast_enable = hn_dev_allmulticast_enable, + .allmulticast_disable = hn_dev_allmulticast_disable, + .set_mc_addr_list = hn_dev_mc_addr_list, + .mtu_set = hn_dev_mtu_set, + .reta_update = hn_rss_reta_update, + .reta_query = hn_rss_reta_query, + .rss_hash_update = hn_rss_hash_update, + .rss_hash_conf_get = hn_rss_hash_conf_get, + .tx_queue_setup = hn_dev_tx_queue_setup, + .tx_queue_release = hn_dev_tx_queue_release, + .tx_done_cleanup = hn_dev_tx_done_cleanup, + .rx_queue_setup = hn_dev_rx_queue_setup, + .rx_queue_release = hn_dev_rx_queue_release, + .link_update = hn_dev_link_update, + .stats_get = hn_dev_stats_get, + .stats_reset = hn_dev_stats_reset, + .xstats_get = hn_dev_xstats_get, + .xstats_get_names = hn_dev_xstats_get_names, + .xstats_reset = hn_dev_xstats_reset, +}; + static int eth_hn_dev_init(struct rte_eth_dev *eth_dev) { struct hn_data *hv = eth_dev->data->dev_private; struct rte_device *device = eth_dev->device; struct rte_vmbus_device *vmbus; + uint32_t mtu; unsigned int rxr_cnt; int err, max_chan; @@ -1218,6 +1316,12 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) if (err) goto failed; + err = hn_rndis_get_mtu(hv, &mtu); + if (err) + goto failed; + eth_dev->data->mtu = (uint16_t)mtu; + PMD_INIT_LOG(DEBUG, "RNDIS MTU is %u", eth_dev->data->mtu); + err = hn_rndis_get_eaddr(hv, eth_dev->data->mac_addrs->addr_bytes); if (err) goto failed; @@ -1272,7 +1376,7 @@ eth_hn_dev_uninit(struct rte_eth_dev *eth_dev) hn_detach(hv); hn_chim_uninit(eth_dev); - rte_vmbus_chan_close(hv->primary->chan); + rte_vmbus_chan_close(hv->channels[0]); rte_free(hv->primary); ret = rte_eth_dev_owner_delete(hv->owner.id); if (ret != 0) diff --git a/drivers/net/netvsc/hn_rndis.c b/drivers/net/netvsc/hn_rndis.c index 29c6009b2cb..778f86f2bfe 100644 --- a/drivers/net/netvsc/hn_rndis.c +++ b/drivers/net/netvsc/hn_rndis.c @@ -1111,6 +1111,13 @@ hn_rndis_get_eaddr(struct hn_data *hv, uint8_t *eaddr) return 0; } +int +hn_rndis_get_mtu(struct hn_data *hv, uint32_t *mtu) +{ + return hn_rndis_query(hv, OID_GEN_MAXIMUM_FRAME_SIZE, NULL, 0, + mtu, sizeof(uint32_t)); +} + int hn_rndis_get_linkstatus(struct hn_data *hv) { diff --git a/drivers/net/netvsc/hn_rndis.h b/drivers/net/netvsc/hn_rndis.h index 9a8251fc2fb..7f40f6221de 100644 --- a/drivers/net/netvsc/hn_rndis.h +++ b/drivers/net/netvsc/hn_rndis.h @@ -10,6 +10,7 @@ void hn_rndis_link_status(struct rte_eth_dev *dev, const void *msg); int hn_rndis_attach(struct hn_data *hv); void hn_rndis_detach(struct hn_data *hv); int hn_rndis_get_eaddr(struct hn_data *hv, uint8_t *eaddr); +int hn_rndis_get_mtu(struct hn_data *hv, uint32_t *mtu); int hn_rndis_get_linkstatus(struct hn_data *hv); int hn_rndis_get_linkspeed(struct hn_data *hv); int hn_rndis_set_rxfilter(struct hn_data *hv, uint32_t filter); diff --git a/drivers/net/netvsc/hn_var.h b/drivers/net/netvsc/hn_var.h index e1f8e69a286..ba7841ef5ef 100644 --- a/drivers/net/netvsc/hn_var.h +++ b/drivers/net/netvsc/hn_var.h @@ -13,7 +13,7 @@ * Tunable ethdev params */ #define HN_MIN_RX_BUF_SIZE 1024 -#define HN_MAX_XFER_LEN 2048 +#define HN_MAX_XFER_LEN RTE_ETHER_MAX_JUMBO_FRAME_LEN #define HN_MAX_MAC_ADDRS 1 #define HN_MAX_CHANNELS 64 From 5f2675dbe32e2916a9832e1312c2e49986290455 Mon Sep 17 00:00:00 2001 From: Sam Andrew <108894698+samuelandrew@users.noreply.github.com> Date: Fri, 1 Sep 2023 00:18:54 +0000 Subject: [PATCH 2/7] do not close device, do not re-allocate queues, simply assign new vmbus channels to pre-existing queues --- drivers/net/netvsc/hn_ethdev.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c index f785c718fb8..10762816419 100644 --- a/drivers/net/netvsc/hn_ethdev.c +++ b/drivers/net/netvsc/hn_ethdev.c @@ -1102,6 +1102,8 @@ static int hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) { struct hn_data *hv = dev->data->dev_private; + struct hn_rx_queue *rxq = dev->data->rx_queues[0]; + struct hn_tx_queue *txq = dev->data->tx_queues[0]; struct rte_eth_dev *vf_dev; unsigned int orig_mtu = dev->data->mtu; uint32_t rndis_mtu; @@ -1112,10 +1114,6 @@ hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) return -EIO; } - ret = hn_dev_close(dev); - if (ret) - return ret; - /* Change MTU of underlying VF netdev first, if it exists */ rte_rwlock_read_lock(&hv->vf_lock); vf_dev = hn_get_vf_dev(hv); @@ -1131,6 +1129,8 @@ hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) /* Release channel resources */ hn_detach(hv); hn_chim_uninit(dev); + + /* Close primary channel */ rte_vmbus_chan_close(hv->channels[0]); /* Unmap and re-map vmbus device */ @@ -1155,20 +1155,18 @@ hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) rte_vmbus_set_latency(hv->vmbus, hv->channels[0], hv->latency); - hv->primary = hn_rx_queue_alloc(hv, 0, - dev->device->numa_node); - - if (!hv->primary) { - /* This is a catastrophic error - the device is unusable */ - PMD_DRV_LOG(ERR, "No memory to allocate rx queue!"); - return -ENOMEM; - } + rxq->chan = hv->channels[0]; + txq->chan = hv->channels[0]; ret = hn_attach(hv, mtu); if (ret) goto error; ret = hn_chim_init(dev); + if (ret) + goto error; + + ret = hn_dev_configure(dev); if (!ret) goto out; From b590c764319858ceb8bc7c9e12cd9b0d236f6ba0 Mon Sep 17 00:00:00 2001 From: Sam Andrew <108894698+samuelandrew@users.noreply.github.com> Date: Fri, 8 Sep 2023 19:16:14 +0000 Subject: [PATCH 3/7] handle multiple queues when tearing down/re-creating vmbus channels to change mtu --- drivers/net/netvsc/hn_ethdev.c | 44 +++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c index 10762816419..da64d58c1c9 100644 --- a/drivers/net/netvsc/hn_ethdev.c +++ b/drivers/net/netvsc/hn_ethdev.c @@ -1102,12 +1102,13 @@ static int hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) { struct hn_data *hv = dev->data->dev_private; - struct hn_rx_queue *rxq = dev->data->rx_queues[0]; - struct hn_tx_queue *txq = dev->data->tx_queues[0]; + struct hn_rx_queue **rxqs = (struct hn_rx_queue **)dev->data->rx_queues; + struct hn_tx_queue **txqs = (struct hn_tx_queue **)dev->data->tx_queues; struct rte_eth_dev *vf_dev; unsigned int orig_mtu = dev->data->mtu; uint32_t rndis_mtu; int ret = 0; + int i; if (dev->data->dev_started) { PMD_DRV_LOG(ERR, "Device must be stopped before changing MTU"); @@ -1128,7 +1129,6 @@ hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) /* Release channel resources */ hn_detach(hv); - hn_chim_uninit(dev); /* Close primary channel */ rte_vmbus_chan_close(hv->channels[0]); @@ -1142,7 +1142,7 @@ hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) return ret; } - /* Update pointers to re-mapped memory */ + /* Update pointers to re-mapped UIO resources */ hv->rxbuf_res = hv->vmbus->resource[HV_RECV_BUF_MAP]; hv->chim_res = hv->vmbus->resource[HV_SEND_BUF_MAP]; @@ -1155,23 +1155,37 @@ hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) rte_vmbus_set_latency(hv->vmbus, hv->channels[0], hv->latency); - rxq->chan = hv->channels[0]; - txq->chan = hv->channels[0]; + /* Point primary queues at new primary channel */ + rxqs[0]->chan = hv->channels[0]; + txqs[0]->chan = hv->channels[0]; ret = hn_attach(hv, mtu); if (ret) goto error; - ret = hn_chim_init(dev); + /* Create vmbus subchannels, additional RNDIS configuration */ + ret = hn_dev_configure(dev); if (ret) goto error; + + /* Point any additional queues at new subchannels */ + for (i = 1; i < dev->data->nb_rx_queues; i++) + rxqs[i]->chan = hv->channels[i]; + for (i = 1; i < dev->data->nb_tx_queues; i++) + txqs[i]->chan = hv->channels[i]; - ret = hn_dev_configure(dev); - if (!ret) - goto out; +out: + if (hn_rndis_get_mtu(hv, &rndis_mtu)) + PMD_DRV_LOG(ERR, "Could not get MTU via RNDIS"); + else { + dev->data->mtu = (uint16_t)rndis_mtu; + PMD_DRV_LOG(DEBUG, "RNDIS MTU is %u", dev->data->mtu); + } + + return ret; error: - /* In case of error, attempt rollback to original MTU */ + /* In case of error, attempt to restore original MTU */ if (hn_attach(hv, orig_mtu)) PMD_DRV_LOG(ERR, "Restoring original MTU failed"); @@ -1181,14 +1195,6 @@ hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) vf_dev->dev_ops->mtu_set(vf_dev, orig_mtu); rte_rwlock_read_unlock(&hv->vf_lock); -out: - if (hn_rndis_get_mtu(hv, &rndis_mtu)) - PMD_DRV_LOG(ERR, "Could not get MTU via RNDIS"); - else { - dev->data->mtu = (uint16_t)rndis_mtu; - PMD_DRV_LOG(DEBUG, "RNDIS MTU is %u", dev->data->mtu); - } - return ret; } From 96c5772f01583611b250b31a68a814980187e8e3 Mon Sep 17 00:00:00 2001 From: Sam Andrew <108894698+samuelandrew@users.noreply.github.com> Date: Fri, 8 Sep 2023 19:54:21 +0000 Subject: [PATCH 4/7] close vmbus subchannels before unmapping vmbus device --- drivers/net/netvsc/hn_ethdev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c index da64d58c1c9..da0be70fca7 100644 --- a/drivers/net/netvsc/hn_ethdev.c +++ b/drivers/net/netvsc/hn_ethdev.c @@ -1130,8 +1130,9 @@ hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) /* Release channel resources */ hn_detach(hv); - /* Close primary channel */ - rte_vmbus_chan_close(hv->channels[0]); + /* Close vmbus channels */ + for (i = 0; i < hv->num_queues; i++) + rte_vmbus_chan_close(hv->channels[i]); /* Unmap and re-map vmbus device */ rte_vmbus_unmap_device(hv->vmbus); From 16da2e8b04454f9c32abac0f0540165f3145ed08 Mon Sep 17 00:00:00 2001 From: Sam Andrew <108894698+samuelandrew@users.noreply.github.com> Date: Fri, 29 Sep 2023 20:17:21 +0000 Subject: [PATCH 5/7] Refactor re-initialization after un/re-mapping vmbus channels into separate function. Move VF MTU change into separate function. Ensure that subchannels are reconnected if rolling back to original MTU. --- drivers/net/netvsc/hn_ethdev.c | 98 +++++++++++++++++++--------------- drivers/net/netvsc/hn_var.h | 1 + drivers/net/netvsc/hn_vf.c | 15 ++++++ 3 files changed, 71 insertions(+), 43 deletions(-) diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c index da0be70fca7..d5517dca789 100644 --- a/drivers/net/netvsc/hn_ethdev.c +++ b/drivers/net/netvsc/hn_ethdev.c @@ -1098,13 +1098,47 @@ hn_detach(struct hn_data *hv) hn_rndis_detach(hv); } +/* + * Connects EXISTING rx/tx queues to NEW vmbus channel(s), and + * re-initializes NDIS and RNDIS, including re-sending initial + * NDIS/RNDIS configuration. To be used after the underlying vmbus + * has been un- and re-mapped, e.g. as must happen when the device + * MTU is changed. + */ static int -hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) +hn_reinit(struct rte_eth_dev *dev, uint16_t mtu) { struct hn_data *hv = dev->data->dev_private; struct hn_rx_queue **rxqs = (struct hn_rx_queue **)dev->data->rx_queues; struct hn_tx_queue **txqs = (struct hn_tx_queue **)dev->data->tx_queues; - struct rte_eth_dev *vf_dev; + int i, ret = 0; + + /* Point primary queues at new primary channel */ + rxqs[0]->chan = hv->channels[0]; + txqs[0]->chan = hv->channels[0]; + + ret = hn_attach(hv, mtu); + if (ret) + return ret; + + /* Create vmbus subchannels, additional RNDIS configuration */ + ret = hn_dev_configure(dev); + if (ret) + return ret; + + /* Point any additional queues at new subchannels */ + for (i = 1; i < dev->data->nb_rx_queues; i++) + rxqs[i]->chan = hv->channels[i]; + for (i = 1; i < dev->data->nb_tx_queues; i++) + txqs[i]->chan = hv->channels[i]; + + return ret; +} + +static int +hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) +{ + struct hn_data *hv = dev->data->dev_private; unsigned int orig_mtu = dev->data->mtu; uint32_t rndis_mtu; int ret = 0; @@ -1115,25 +1149,21 @@ hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) return -EIO; } - /* Change MTU of underlying VF netdev first, if it exists */ - rte_rwlock_read_lock(&hv->vf_lock); - vf_dev = hn_get_vf_dev(hv); - if (hv->vf_ctx.vf_vsc_switched && vf_dev) { - ret = vf_dev->dev_ops->mtu_set(vf_dev, mtu); - if (ret) { - rte_rwlock_read_unlock(&hv->vf_lock); - goto out; - } - } - rte_rwlock_read_unlock(&hv->vf_lock); + /* Change MTU of underlying VF dev first, if it exists */ + ret = hn_vf_mtu_set(dev, mtu); + if (ret) + return ret; /* Release channel resources */ hn_detach(hv); - /* Close vmbus channels */ - for (i = 0; i < hv->num_queues; i++) + /* Close any secondary vmbus channels */ + for (i = 1; i < hv->num_queues; i++) rte_vmbus_chan_close(hv->channels[i]); + /* Close primary vmbus channel */ + rte_free(hv->channels[0]); + /* Unmap and re-map vmbus device */ rte_vmbus_unmap_device(hv->vmbus); ret = rte_vmbus_map_device(hv->vmbus); @@ -1147,33 +1177,28 @@ hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) hv->rxbuf_res = hv->vmbus->resource[HV_RECV_BUF_MAP]; hv->chim_res = hv->vmbus->resource[HV_SEND_BUF_MAP]; - /* Re-open the vmbus channel */ + /* Re-open the primary vmbus channel */ ret = rte_vmbus_chan_open(hv->vmbus, &hv->channels[0]); if (ret) { /* This is a catastrophic error - the device is unusable */ PMD_DRV_LOG(ERR, "Could not re-open vmbus channel!"); + return ret; } rte_vmbus_set_latency(hv->vmbus, hv->channels[0], hv->latency); - /* Point primary queues at new primary channel */ - rxqs[0]->chan = hv->channels[0]; - txqs[0]->chan = hv->channels[0]; + ret = hn_reinit(dev, mtu); + if (!ret) + goto out; - ret = hn_attach(hv, mtu); + /* In case of error, attempt to restore original MTU */ + ret = hn_reinit(dev, orig_mtu); if (ret) - goto error; + PMD_DRV_LOG(ERR, "Restoring original MTU failed for netvsc"); - /* Create vmbus subchannels, additional RNDIS configuration */ - ret = hn_dev_configure(dev); + ret = hn_vf_mtu_set(dev, orig_mtu); if (ret) - goto error; - - /* Point any additional queues at new subchannels */ - for (i = 1; i < dev->data->nb_rx_queues; i++) - rxqs[i]->chan = hv->channels[i]; - for (i = 1; i < dev->data->nb_tx_queues; i++) - txqs[i]->chan = hv->channels[i]; + PMD_DRV_LOG(ERR, "Restoring original MTU failed for VF"); out: if (hn_rndis_get_mtu(hv, &rndis_mtu)) @@ -1183,19 +1208,6 @@ hn_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) PMD_DRV_LOG(DEBUG, "RNDIS MTU is %u", dev->data->mtu); } - return ret; - -error: - /* In case of error, attempt to restore original MTU */ - if (hn_attach(hv, orig_mtu)) - PMD_DRV_LOG(ERR, "Restoring original MTU failed"); - - rte_rwlock_read_lock(&hv->vf_lock); - vf_dev = hn_get_vf_dev(hv); - if (hv->vf_ctx.vf_vsc_switched && vf_dev) - vf_dev->dev_ops->mtu_set(vf_dev, orig_mtu); - rte_rwlock_read_unlock(&hv->vf_lock); - return ret; } diff --git a/drivers/net/netvsc/hn_var.h b/drivers/net/netvsc/hn_var.h index ba7841ef5ef..e37946804db 100644 --- a/drivers/net/netvsc/hn_var.h +++ b/drivers/net/netvsc/hn_var.h @@ -287,6 +287,7 @@ int hn_vf_rss_hash_update(struct rte_eth_dev *dev, int hn_vf_reta_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); +int hn_vf_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); int hn_eth_rmv_event_callback(uint16_t port_id, enum rte_eth_event_type event __rte_unused, void *cb_arg, void *out __rte_unused); diff --git a/drivers/net/netvsc/hn_vf.c b/drivers/net/netvsc/hn_vf.c index 782395d805e..2e96f0d92d2 100644 --- a/drivers/net/netvsc/hn_vf.c +++ b/drivers/net/netvsc/hn_vf.c @@ -778,3 +778,18 @@ int hn_vf_reta_hash_update(struct rte_eth_dev *dev, return ret; } + +int hn_vf_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) +{ + struct hn_data *hv = dev->data->dev_private; + struct rte_eth_dev *vf_dev; + int ret = 0; + + rte_rwlock_read_lock(&hv->vf_lock); + vf_dev = hn_get_vf_dev(hv); + if (hv->vf_ctx.vf_vsc_switched && vf_dev) + ret = vf_dev->dev_ops->mtu_set(vf_dev, mtu); + rte_rwlock_read_unlock(&hv->vf_lock); + + return ret; +} From 2f6584f877c1857dcb72df3d9dec6ef32c12dcbf Mon Sep 17 00:00:00 2001 From: Sam Andrew <108894698+samuelandrew@users.noreply.github.com> Date: Fri, 29 Sep 2023 21:37:47 +0000 Subject: [PATCH 6/7] Configure VF MTU on hot add --- drivers/net/netvsc/hn_vf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/netvsc/hn_vf.c b/drivers/net/netvsc/hn_vf.c index 2e96f0d92d2..404ddd0e775 100644 --- a/drivers/net/netvsc/hn_vf.c +++ b/drivers/net/netvsc/hn_vf.c @@ -239,7 +239,7 @@ int hn_vf_add(struct rte_eth_dev *dev, struct hn_data *hv) port = hv->vf_ctx.vf_port; - /* If the primary device has started, this is a VF host add. + /* If the primary device has started, this is a VF hot add. * Configure and start VF device. */ if (dev->data->dev_started) { @@ -264,6 +264,8 @@ int hn_vf_add(struct rte_eth_dev *dev, struct hn_data *hv) goto exit; } + ret = hn_vf_mtu_set(dev, dev->data->mtu); + PMD_DRV_LOG(NOTICE, "Starting VF port %d", port); ret = rte_eth_dev_start(port); if (ret) { From b8cbd69102a37adb01c8d26f27433b809a22317f Mon Sep 17 00:00:00 2001 From: Sam Andrew <108894698+samuelandrew@users.noreply.github.com> Date: Fri, 29 Sep 2023 21:44:03 +0000 Subject: [PATCH 7/7] Handle MTU set error on VF hot add --- drivers/net/netvsc/hn_vf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/netvsc/hn_vf.c b/drivers/net/netvsc/hn_vf.c index 404ddd0e775..90cb6f69236 100644 --- a/drivers/net/netvsc/hn_vf.c +++ b/drivers/net/netvsc/hn_vf.c @@ -265,6 +265,10 @@ int hn_vf_add(struct rte_eth_dev *dev, struct hn_data *hv) } ret = hn_vf_mtu_set(dev, dev->data->mtu); + if (ret) { + PMD_DRV_LOG(ERR, "Failed to set VF MTU"); + goto exit; + } PMD_DRV_LOG(NOTICE, "Starting VF port %d", port); ret = rte_eth_dev_start(port);