On Mon, Jan 10, 2022 at 6:26 AM <rohit....@nxp.com> wrote:
>
> From: Rohit Raj <rohit....@nxp.com>
>
> As per the current code we have API for bus probe, but the
> bus close API is missing. This breaks the multi process
> scenarios as objects are not cleaned while terminating the
> secondary processes.

After an application crash, how does this bus resets the associated resources?


>
> This patch adds a new API rte_bus_close() for cleanup of
> bus objects which were acquired during probe.

The patch in its current form breaks the ABI on rte_bus object.
This can be seen in GHA, or calling DPDK_ABI_REF_VERSION=v21.11
./devtools/test-meson-builds.sh.


[snip]

> diff --git a/doc/guides/rel_notes/release_22_03.rst 
> b/doc/guides/rel_notes/release_22_03.rst
> index 6d99d1eaa9..7417606a2a 100644
> --- a/doc/guides/rel_notes/release_22_03.rst
> +++ b/doc/guides/rel_notes/release_22_03.rst
> @@ -55,6 +55,11 @@ New Features
>       Also, make sure to start the actual text at the margin.
>       =======================================================
>
> +    * **Added support to close bus.**
> +
> +      Added capability to allow a user to do cleanup of bus objects which
> +      were acquired during bus probe.
> +

Wrongly indented.


>
>  Removed Items
>  -------------
> @@ -84,6 +89,9 @@ API Changes
>     Also, make sure to start the actual text at the margin.
>     =======================================================
>
> +   * eal: Added new API ``rte_bus_close`` to perform cleanup bus objects 
> which
> +     were acquired during bus probe.
> +
>
>  ABI Changes
>  -----------
> diff --git a/lib/eal/common/eal_common_bus.c b/lib/eal/common/eal_common_bus.c
> index baa5b532af..2c3c0a90d2 100644
> --- a/lib/eal/common/eal_common_bus.c
> +++ b/lib/eal/common/eal_common_bus.c
> @@ -1,5 +1,5 @@
>  /* SPDX-License-Identifier: BSD-3-Clause
> - * Copyright 2016 NXP
> + * Copyright 2016,2022 NXP
>   */
>
>  #include <stdio.h>
> @@ -85,6 +85,37 @@ rte_bus_probe(void)
>         return 0;
>  }
>
> +/* Close all devices of all buses */
> +int
> +rte_bus_close(void)
> +{
> +       int ret;
> +       struct rte_bus *bus, *vbus = NULL;
> +
> +       TAILQ_FOREACH(bus, &rte_bus_list, next) {
> +               if (!strcmp(bus->name, "vdev")) {
> +                       vbus = bus;
> +                       continue;
> +               }
> +
> +               if (bus->close) {
> +                       ret = bus->close();
> +                       if (ret)
> +                               RTE_LOG(ERR, EAL, "Bus (%s) close failed.\n",
> +                                       bus->name);
> +               }
> +       }
> +
> +       if (vbus && vbus->close) {
> +               ret = vbus->close();
> +               if (ret)
> +                       RTE_LOG(ERR, EAL, "Bus (%s) close failed.\n",
> +                               vbus->name);
> +       }

The vdev bus is special in that some drivers can reference objects
from other buses (see f4ce209a8ce5 ("eal: postpone vdev
initialization") and da76cc02342b ("eal: probe new virtual bus after
other bus devices")).
For this reason, I would expect that the vdev bus is closed before the
other buses.


> +
> +       return 0;
> +}
> +
>  /* Dump information of a single bus */
>  static int
>  bus_dump_one(FILE *f, struct rte_bus *bus)
> diff --git a/lib/eal/freebsd/eal.c b/lib/eal/freebsd/eal.c
> index a1cd2462db..87d70c6898 100644
> --- a/lib/eal/freebsd/eal.c
> +++ b/lib/eal/freebsd/eal.c
> @@ -984,6 +984,7 @@ rte_eal_cleanup(void)
>  {
>         struct internal_config *internal_conf =
>                 eal_get_internal_configuration();
> +       rte_bus_close();
>         rte_service_finalize();
>         rte_mp_channel_cleanup();
>         /* after this point, any DPDK pointers will become dangling */
> diff --git a/lib/eal/include/rte_bus.h b/lib/eal/include/rte_bus.h
> index bbbb6efd28..c6211bbd95 100644
> --- a/lib/eal/include/rte_bus.h
> +++ b/lib/eal/include/rte_bus.h
> @@ -1,5 +1,5 @@
>  /* SPDX-License-Identifier: BSD-3-Clause
> - * Copyright 2016 NXP
> + * Copyright 2016,2022 NXP
>   */
>
>  #ifndef _RTE_BUS_H_
> @@ -66,6 +66,23 @@ typedef int (*rte_bus_scan_t)(void);
>   */
>  typedef int (*rte_bus_probe_t)(void);
>
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice
> + *
> + * Implementation specific close function which is responsible for resetting 
> all
> + * detected devices on the bus to a default state, closing UIO nodes or VFIO
> + * groups and also freeing any memory allocated during rte_bus_probe like
> + * private resources for device list.
> + *
> + * This is called while iterating over each registered bus.
> + *
> + * @return
> + *     0 for successful close
> + *     !0 for any error while closing
> + */
> +typedef int (*rte_bus_close_t)(void);
> +
>  /**
>   * Device iterator to find a device on a bus.
>   *
> @@ -263,6 +280,7 @@ struct rte_bus {
>         const char *name;            /**< Name of the bus */
>         rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
>         rte_bus_probe_t probe;       /**< Probe devices on bus */
> +       rte_bus_close_t close;       /**< Close devices on bus */
>         rte_bus_find_device_t find_device; /**< Find a device on the bus */
>         rte_bus_plug_t plug;         /**< Probe single device for drivers */
>         rte_bus_unplug_t unplug;     /**< Remove single device from driver */
> @@ -317,6 +335,16 @@ int rte_bus_scan(void);
>   */
>  int rte_bus_probe(void);
>
> +/**
> + * For each device on the buses, call the device specific close.
> + *
> + * @return
> + *      0 for successful close
> + *     !0 otherwise
> + */
> +__rte_experimental
> +int rte_bus_close(void);
> +
>  /**
>   * Dump information of all the buses registered with EAL.
>   *
> diff --git a/lib/eal/linux/eal.c b/lib/eal/linux/eal.c
> index 60b4924838..5c60131e46 100644
> --- a/lib/eal/linux/eal.c
> +++ b/lib/eal/linux/eal.c
> @@ -1362,6 +1362,14 @@ rte_eal_cleanup(void)
>
>         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
>                 rte_memseg_walk(mark_freeable, NULL);
> +
> +       /* Close all the buses and devices/drivers on them */
> +       if (rte_bus_close()) {
> +               rte_eal_init_alert("Cannot close devices");

You can't call rte_eal_*init*_alert in rte_eal_cleanup.

There is not much to do if the bus close fails, I'd rather leave the
cleanup continue.


> +               rte_errno = ENOTSUP;
> +               return -1;
> +       }
> +
>         rte_service_finalize();
>         rte_mp_channel_cleanup();
>         /* after this point, any DPDK pointers will become dangling */
> diff --git a/lib/eal/version.map b/lib/eal/version.map
> index ab28c22791..39882dbbd5 100644
> --- a/lib/eal/version.map
> +++ b/lib/eal/version.map
> @@ -420,6 +420,9 @@ EXPERIMENTAL {
>         rte_intr_instance_free;
>         rte_intr_type_get;
>         rte_intr_type_set;
> +
> +       # added in 22.03
> +       rte_bus_close;
>  };
>
>  INTERNAL {
> diff --git a/lib/eal/windows/eal.c b/lib/eal/windows/eal.c
> index 67db7f099a..5915ab6291 100644
> --- a/lib/eal/windows/eal.c
> +++ b/lib/eal/windows/eal.c
> @@ -260,6 +260,7 @@ rte_eal_cleanup(void)
>         struct internal_config *internal_conf =
>                 eal_get_internal_configuration();
>
> +       rte_bus_close();
>         eal_intr_thread_cancel();
>         eal_mem_virt2iova_cleanup();
>         /* after this point, any DPDK pointers will become dangling */
> --
> 2.17.1
>


-- 
David Marchand

Reply via email to