> >> >Copy public function pointers (rx_pkt_burst(), etc.) and related >> >pointers to internal data from rte_eth_dev structure into a >> >separate flat array. That array will remain in a public header. >> >The intention here is to make rte_eth_dev and related structures >> >internal. >> >That should allow future possible changes to core eth_dev >structures >> >to be transparent to the user and help to avoid ABI/API breakages. >> >The plan is to keep minimal part of data from rte_eth_dev public, >> >so we still can use inline functions for 'fast' calls >> >(like rte_eth_rx_burst(), etc.) to avoid/minimize slowdown. >> > >> >Signed-off-by: Konstantin Ananyev ><konstantin.anan...@intel.com> >> >--- >> > lib/ethdev/ethdev_private.c | 52 >> >++++++++++++++++++++++++++++++++++++ >> > lib/ethdev/ethdev_private.h | 7 +++++ >> > lib/ethdev/rte_ethdev.c | 17 ++++++++++++ >> > lib/ethdev/rte_ethdev_core.h | 45 >> >+++++++++++++++++++++++++++++++ >> > 4 files changed, 121 insertions(+) >> > >> >> <snip> >> >> >+void >> >+eth_dev_fp_ops_reset(struct rte_eth_fp_ops *fpo) >> >+{ >> >+ static void *dummy_data[RTE_MAX_QUEUES_PER_PORT]; >> >+ static const struct rte_eth_fp_ops dummy_ops = { >> >+ .rx_pkt_burst = dummy_eth_rx_burst, >> >+ .tx_pkt_burst = dummy_eth_tx_burst, >> >+ .rxq = {.data = dummy_data, .clbk = dummy_data,}, >> >+ .txq = {.data = dummy_data, .clbk = dummy_data,}, >> >+ }; >> >+ >> >+ *fpo = dummy_ops; >> >+} >> >+ >> >+void >> >+eth_dev_fp_ops_setup(struct rte_eth_fp_ops *fpo, >> >+ const struct rte_eth_dev *dev) >> >+{ >> >+ fpo->rx_pkt_burst = dev->rx_pkt_burst; >> >+ fpo->tx_pkt_burst = dev->tx_pkt_burst; >> >+ fpo->tx_pkt_prepare = dev->tx_pkt_prepare; >> >+ fpo->rx_queue_count = dev->rx_queue_count; >> >+ fpo->rx_descriptor_status = dev->rx_descriptor_status; >> >+ fpo->tx_descriptor_status = dev->tx_descriptor_status; >> >+ >> >+ fpo->rxq.data = dev->data->rx_queues; >> >+ fpo->rxq.clbk = (void **)(uintptr_t)dev->post_rx_burst_cbs; >> >+ >> >+ fpo->txq.data = dev->data->tx_queues; >> >+ fpo->txq.clbk = (void **)(uintptr_t)dev->pre_tx_burst_cbs; >> >+} >> >diff --git a/lib/ethdev/ethdev_private.h >b/lib/ethdev/ethdev_private.h >> >index 3724429577..40333e7651 100644 >> >--- a/lib/ethdev/ethdev_private.h >> >+++ b/lib/ethdev/ethdev_private.h >> >@@ -26,4 +26,11 @@ eth_find_device(const struct rte_eth_dev >> >*_start, rte_eth_cmp_t cmp, >> > /* Parse devargs value for representor parameter. */ >> > int rte_eth_devargs_parse_representor_ports(char *str, void >*data); >> > >> >+/* reset eth 'fast' API to dummy values */ >> >+void eth_dev_fp_ops_reset(struct rte_eth_fp_ops *fpo); >> >+ >> >+/* setup eth 'fast' API to ethdev values */ >> >+void eth_dev_fp_ops_setup(struct rte_eth_fp_ops *fpo, >> >+ const struct rte_eth_dev *dev); >> >+ >> > #endif /* _ETH_PRIVATE_H_ */ >> >diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c >> >index 424bc260fa..9fbb1bc3db 100644 >> >--- a/lib/ethdev/rte_ethdev.c >> >+++ b/lib/ethdev/rte_ethdev.c >> >@@ -44,6 +44,9 @@ >> > static const char *MZ_RTE_ETH_DEV_DATA = "rte_eth_dev_data"; >> > struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS]; >> > >> >+/* public 'fast' API */ >> >+struct rte_eth_fp_ops rte_eth_fp_ops[RTE_MAX_ETHPORTS]; >> >+ >> > /* spinlock for eth device callbacks */ >> > static rte_spinlock_t eth_dev_cb_lock = >RTE_SPINLOCK_INITIALIZER; >> > >> >@@ -1788,6 +1791,9 @@ rte_eth_dev_start(uint16_t port_id) >> > (*dev->dev_ops->link_update)(dev, 0); >> > } >> > >> >+ /* expose selection of PMD rx/tx function */ >> >+ eth_dev_fp_ops_setup(rte_eth_fp_ops + port_id, dev); >> >+ >> >> Secondary process will not set these properly I believe as it might not >> call start() if it does primary process ops will not be set. > >That's a very good point, have to admit - I missed that part. > >> >> One simple solution is to call ops_setup() around >rte_eth_dev_attach_secondary() >> but if application doesn't invoke start() on Primary the ops will not be >set for it. > >I think rte_eth_dev_attach_secondary() wouldn't work, as majority of >the PMDs setup >fast ops function pointers after it. >From reading the code rte_eth_dev_probing_finish() seems like a good >choice - >as it is always the final point in device initialization for secondary >process.
Ack, make sense to me, I did a similar thing for event device in http://patches.dpdk.org/project/dpdk/patch/20211003082710.8398-4-pbhagavat...@marvell.com/ > >BTW, we also need something similar at de-init phase. >rte_eth_dev_release_port() seems like a good candidate for it. > Hindsight I should have added reset to rte_event_pmd_pci_remove(), I will add it in next version. > >> >> > rte_ethdev_trace_start(port_id); >> > return 0; >> > } >> >@@ -1810,6 +1816,9 @@ rte_eth_dev_stop(uint16_t port_id) >> > return 0; >> > } >> > >> >+ /* point rx/tx functions to dummy ones */ >> >+ eth_dev_fp_ops_reset(rte_eth_fp_ops + port_id); >> >+ >> > dev->data->dev_started = 0; >> > ret = (*dev->dev_ops->dev_stop)(dev); >> > rte_ethdev_trace_stop(port_id, ret); >> >2.26.3