@@ -133,6 +133,7 @@ noinst_HEADERS = \
${srcdir}/include/_ishm_internal.h \
${srcdir}/include/_ishmphy_internal.h \
${srcdir}/include/_ishmpool_internal.h \
+ ${srcdir}/include/drv_driver_internal.h\
${srcdir}/include/odp_align_internal.h \
${srcdir}/include/odp_atomic_internal.h \
${srcdir}/include/odp_buffer_inlines.h \
@@ -9,6 +9,7 @@
#include <odp/api/std_types.h>
#include <odp/api/debug.h>
#include <odp_debug_internal.h>
+#include <drv_driver_internal.h>
#include <libconfig.h>
#include <dlfcn.h>
@@ -40,6 +41,9 @@ static int load_modules(void)
ODP_DBG("module %s loaded.\n", module_name);
}
+ /* give a chance top the driver interface to probe for new things: */
+ _odpdrv_driver_probe_drv_items();
+
return 0;
}
@@ -4,20 +4,131 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <string.h>
+
#include <odp_config_internal.h>
+#include <_ishmpool_internal.h>
#include <odp/api/std_types.h>
#include <odp/api/debug.h>
+#include <odp/api/rwlock_recursive.h>
#include <odp/drv/driver.h>
+#include <odp/drv/spec/driver.h>
#include <odp_debug_internal.h>
+#include <drv_driver_internal.h>
+
+static enum {UNDONE, IN_PROGRESS, DONE} init_global_status;
+
+/* pool from which different list elements are alocated: */
+#define ELT_POOL_SIZE (1 << 20) /* 1Mb */
+static _odp_ishm_pool_t *list_elt_pool;
+
+typedef struct _odpdrv_enumr_class_s _odpdrv_enumr_class_t;
+
+/* an enumerator class (list element) */
+struct _odpdrv_enumr_class_s {
+ odpdrv_enumr_class_param_t param;
+ int probed;
+ _odp_ishm_pool_t *pool;
+ struct _odpdrv_enumr_class_s *next;
+};
+
+/* the enumerator class list: */
+typedef struct _odpdrv_enumr_class_lst_t {
+ odp_rwlock_recursive_t lock;
+ _odpdrv_enumr_class_t *head;
+} _odpdrv_enumr_class_lst_t;
+static struct _odpdrv_enumr_class_lst_t enumr_class_lst;
+
+/* some driver elements (such as enumeraor classes, drivers, devio) may
+ * register before init_global and init_local complete. Mutex will fail
+ * in this cases but should be used later on.
+ * These functions disable the usage of Mutex while it is global init i.e.
+ * while single threaded*/
+static void enumr_class_list_read_lock(void)
+{
+ if (init_global_status == DONE)
+ odp_rwlock_recursive_read_lock(&enumr_class_lst.lock);
+}
+
+static void enumr_class_list_read_unlock(void)
+{
+ if (init_global_status == DONE)
+ odp_rwlock_recursive_read_unlock(&enumr_class_lst.lock);
+}
+
+static void enumr_class_list_write_lock(void)
+{
+ if (init_global_status == DONE)
+ odp_rwlock_recursive_write_lock(&enumr_class_lst.lock);
+}
+
+static void enumr_class_list_write_unlock(void)
+{
+ if (init_global_status == DONE)
+ odp_rwlock_recursive_write_unlock(&enumr_class_lst.lock);
+}
+
odpdrv_enumr_class_t odpdrv_enumr_class_register(odpdrv_enumr_class_param_t
*param)
{
- ODP_ERR("NOT Supported yet! Enumerator Class %s Registration!\n.",
- param->name);
+ _odpdrv_enumr_class_t *enumr_c;
- return ODPDRV_ENUMR_CLASS_INVALID;
+ /* parse the list of already registered enumerator class to make
+ * sure no enumerator with identical name already exists:
+ */
+ enumr_class_list_read_lock();
+ enumr_c = enumr_class_lst.head;
+ while (enumr_c) {
+ if (strncmp(param->name, enumr_c->param.name,
+ ODPDRV_NAME_SIZE) == 0) {
+ ODP_ERR("enumerator class %s already exists!\n",
+ param->name);
+ enumr_class_list_read_unlock();
+ return ODPDRV_ENUMR_CLASS_INVALID;
+ }
+ enumr_c = enumr_c->next;
+ }
+ enumr_class_list_read_unlock();
+
+ /* allocate memory for the new enumerator class:
+ * If init_global has not been done yet, then, we cannot allocate
+ * from any _ishm pool (ishm has not even been initialised at this
+ * stage...this happens when statically linked enumerator classes
+ * register: their __constructor__ function is run before main()
+ * is called). But any malloc performed here(before init_global)
+ * will be inherited by any odpthreads (process or pthreads) as we
+ * are still running in the ODP instantiation processes and all
+ * other processes are guaranteed to be descendent of this one...
+ * If init_global has been done, then we allocate from the _ishm pool
+ * to guarantee visibility from any ODP thread.
+ */
+
+ if (init_global_status == UNDONE) {
+ enumr_c = malloc(sizeof(_odpdrv_enumr_class_t));
+ if (!enumr_c)
+ return ODPDRV_ENUMR_CLASS_INVALID;
+ enumr_c->pool = NULL;
+ } else {
+ enumr_c = _odp_ishm_pool_alloc(list_elt_pool,
+ sizeof(_odpdrv_enumr_class_t));
+ if (!enumr_c) {
+ ODP_ERR("_odp_ishm_pool_alloc failed!\n");
+ return ODPDRV_ENUMR_CLASS_INVALID;
+ }
+ enumr_c->pool = list_elt_pool;
+ }
+
+ /* save init parameters and insert enumerator class in list */
+ enumr_c->param = *param;
+ enumr_c->probed = 0;
+ enumr_class_list_write_lock();
+ enumr_c->next = enumr_class_lst.head;
+ enumr_class_lst.head = enumr_c;
+ enumr_class_list_write_unlock();
+
+ return (odpdrv_enumr_class_t)enumr_c;
}
odpdrv_enumr_t odpdrv_enumr_register(odpdrv_enumr_param_t *param)
@@ -57,8 +168,101 @@ odpdrv_driver_t odpdrv_driver_register(odpdrv_driver_param_t *param)
return ODPDRV_DRIVER_INVALID;
}
+/* the following function is called each time probing is needed, i.e.
+ * at init or after loading a new module as a module can be anything,
+ * including enumerators or drivers */
+void _odpdrv_driver_probe_drv_items(void)
+{
+ _odpdrv_enumr_class_t *enumr_c;
+
+ /* probe unprobed enumerators: */
+ enumr_class_list_read_lock();
+ enumr_c = enumr_class_lst.head;
+ while (enumr_c) {
+ if (!enumr_c->probed) {
+ enumr_c->param.probe();
+ enumr_c->probed = 1;
+ }
+ enumr_c = enumr_c->next;
+ }
+ enumr_class_list_read_unlock();
+}
+
int odpdrv_print_all(void)
{
- ODP_ERR("odpdrv_print_all not Supported yet!\n.");
+ _odpdrv_enumr_class_t *enumr_c;
+
+ /* we cannot use ODP_DBG before ODP init... */
+ if (init_global_status == UNDONE)
+ return 0;
+
+ ODP_DBG("ODP Driver status:\n");
+
+ /* print the list of registered enumerator classes: */
+ enumr_class_list_read_lock();
+ enumr_c = enumr_class_lst.head;
+ ODP_DBG("The following enumerator classes have been registered:\n");
+ while (enumr_c) {
+ ODP_DBG(" class: %s\n", enumr_c->param.name);
+ enumr_c = enumr_c->next;
+ }
+ enumr_class_list_read_unlock();
+ return 0;
+}
+
+int _odpdrv_driver_init_global(void)
+{
+ /* create a memory pool to for list elements: */
+ list_elt_pool = _odp_ishm_pool_create(NULL, ELT_POOL_SIZE,
+ 0, ELT_POOL_SIZE, 0);
+
+ /* remember that init global is being done so the further list allocs
+ * are made from the list_elt_pool: */
+ init_global_status = IN_PROGRESS;
+
+ /* from now, we want to ensure mutex on the list: init lock: */
+ odp_rwlock_recursive_init(&enumr_class_lst.lock);
+
+ /* probe things... */
+ _odpdrv_driver_probe_drv_items();
+
+ return 0;
+}
+
+int _odpdrv_driver_init_local(void)
+{
+ /* remember that init global is done, so list mutexes are used from
+ * now */
+ init_global_status = DONE;
+ return 0;
+}
+
+int _odpdrv_driver_term_global(void)
+{
+ _odpdrv_enumr_class_t *enumr_c;
+
+ if (init_global_status == UNDONE)
+ return 0;
+
+ /* remove all enumerator classes which are registered: */
+ enumr_class_list_write_lock();
+ while (enumr_class_lst.head) {
+ enumr_c = enumr_class_lst.head;
+ if (enumr_c->param.remove) { /* run remove callback, if any */
+ if (enumr_c->param.remove())
+ ODP_ERR("Enumerator class %s removal failed.\n",
+ enumr_c->param.name);
+ }
+ enumr_class_lst.head = enumr_c->next;
+ if (enumr_c->pool)
+ _odp_ishm_pool_free(list_elt_pool, enumr_c);
+ else
+ free(enumr_c);
+ }
+ enumr_class_list_write_unlock();
+
+ /* destroy the list element pool: */
+ _odp_ishm_pool_destroy(list_elt_pool);
+
return 0;
}
new file mode 100644
@@ -0,0 +1,22 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DRV_DRIVER_INTERNAL_H_
+#define DRV_DRIVER_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+void _odpdrv_driver_probe_drv_items(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
@@ -71,6 +71,7 @@ enum init_stage {
CLASSIFICATION_INIT,
TRAFFIC_MNGR_INIT,
NAME_TABLE_INIT,
+ DRIVER_INIT,
MODULES_INIT,
ALL_INIT /* All init stages completed */
};
@@ -130,6 +131,10 @@ int _odp_ishm_init_local(void);
int _odp_ishm_term_global(void);
int _odp_ishm_term_local(void);
+int _odpdrv_driver_init_global(void);
+int _odpdrv_driver_init_local(void);
+int _odpdrv_driver_term_global(void);
+
int _odp_modules_init_global(void);
int cpuinfo_parser(FILE *file, system_info_t *sysinfo);
@@ -266,6 +266,12 @@ int odp_init_global(odp_instance_t *instance,
}
stage = NAME_TABLE_INIT;
+ if (_odpdrv_driver_init_global()) {
+ ODP_ERR("ODP drivers init failed\n");
+ goto init_failed;
+ }
+ stage = DRIVER_INIT;
+
if (_odp_modules_init_global()) {
ODP_ERR("ODP modules init failed\n");
goto init_failed;
@@ -296,6 +302,13 @@ int _odp_term_global(enum init_stage stage)
switch (stage) {
case ALL_INIT:
case MODULES_INIT:
+ case DRIVER_INIT:
+ if (_odpdrv_driver_term_global()) {
+ ODP_ERR("driver term failed.\n");
+ rc = -1;
+ }
+ /* Fall through */
+
case NAME_TABLE_INIT:
if (_odp_int_name_tbl_term_global()) {
ODP_ERR("Name table term failed.\n");
@@ -445,7 +458,13 @@ int odp_init_local(odp_instance_t instance, odp_thread_type_t thr_type)
ODP_ERR("ODP schedule local init failed.\n");
goto init_fail;
}
- /* stage = SCHED_INIT; */
+ stage = SCHED_INIT;
+
+ if (_odpdrv_driver_init_local()) {
+ ODP_ERR("ODP driver local init failed.\n");
+ goto init_fail;
+ }
+ /* stage = DRIVER_INIT; */
return 0;
The functions to register and probe enumerator classes are added. Signed-off-by: Christophe Milard <christophe.milard@linaro.org> --- platform/linux-generic/Makefile.am | 1 + platform/linux-generic/_modules.c | 4 + platform/linux-generic/drv_driver.c | 212 ++++++++++++++++++++- .../linux-generic/include/drv_driver_internal.h | 22 +++ platform/linux-generic/include/odp_internal.h | 5 + platform/linux-generic/odp_init.c | 21 +- 6 files changed, 260 insertions(+), 5 deletions(-) create mode 100644 platform/linux-generic/include/drv_driver_internal.h -- 2.7.4