The enumerator registration functions for the linux-gen ODP implementation.

Signed-off-by: Christophe Milard <christophe.mil...@linaro.org>
---
 platform/linux-generic/drv_driver.c | 139 +++++++++++++++++++++++++++++++++++-
 1 file changed, 136 insertions(+), 3 deletions(-)

diff --git a/platform/linux-generic/drv_driver.c 
b/platform/linux-generic/drv_driver.c
index 50956a7..35473bd 100644
--- a/platform/linux-generic/drv_driver.c
+++ b/platform/linux-generic/drv_driver.c
@@ -24,6 +24,7 @@ static enum {UNDONE, IN_PROGRESS, DONE} init_global_status;
 static _odp_ishm_pool_t *list_elt_pool;
 
 typedef struct _odpdrv_enumr_class_s _odpdrv_enumr_class_t;
+typedef struct _odpdrv_enumr_s _odpdrv_enumr_t;
 
 /* an enumerator class (list element) */
 struct _odpdrv_enumr_class_s {
@@ -40,6 +41,20 @@ typedef struct _odpdrv_enumr_class_lst_t {
 } _odpdrv_enumr_class_lst_t;
 static struct _odpdrv_enumr_class_lst_t enumr_class_lst;
 
+/* an enumerator (list element) */
+struct _odpdrv_enumr_s {
+       odpdrv_enumr_param_t param;
+       int probed;
+       struct _odpdrv_enumr_s *next;
+};
+
+/* the enumerator list: */
+typedef struct _odpdrv_enumr_lst_t {
+       odp_rwlock_recursive_t lock;
+       _odpdrv_enumr_t *head;
+} _odpdrv_enumr_lst_t;
+static struct _odpdrv_enumr_lst_t enumr_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.
@@ -69,6 +84,35 @@ static void enumr_class_list_write_unlock(void)
                odp_rwlock_recursive_write_unlock(&enumr_class_lst.lock);
 }
 
+static void enumr_list_read_lock(void)
+{
+       if (init_global_status == DONE)
+               odp_rwlock_recursive_read_lock(&enumr_lst.lock);
+}
+
+static void enumr_list_read_unlock(void)
+{
+       if (init_global_status == DONE)
+               odp_rwlock_recursive_read_unlock(&enumr_lst.lock);
+}
+
+static void enumr_list_write_lock(void)
+{
+       if (init_global_status == DONE)
+               odp_rwlock_recursive_write_lock(&enumr_lst.lock);
+}
+
+static void enumr_list_write_unlock(void)
+{
+       if (init_global_status == DONE)
+               odp_rwlock_recursive_write_unlock(&enumr_lst.lock);
+}
+
+/* some functions to get internal pointers from handles... */
+static inline _odpdrv_enumr_class_t *get_enumr_class(odpdrv_enumr_class_t 
class)
+{
+       return (_odpdrv_enumr_class_t *)(void *)class;
+}
 
 odpdrv_enumr_class_t odpdrv_enumr_class_register(odpdrv_enumr_class_param_t
                                                 *param)
@@ -133,10 +177,52 @@ odpdrv_enumr_class_t 
odpdrv_enumr_class_register(odpdrv_enumr_class_param_t
 
 odpdrv_enumr_t odpdrv_enumr_register(odpdrv_enumr_param_t *param)
 {
-       ODP_ERR("NOT Supported yet! Enumerator API %s Registration!\n.",
-               param->api_name);
+       _odpdrv_enumr_t *enumr;
+       _odpdrv_enumr_class_t *enumr_c;
+       int found_class = 0;
 
-       return ODPDRV_ENUMR_INVALID;
+       /* make sure that the provided enumerator_class does indeed exist: */
+       enumr_class_list_read_lock();
+       enumr_c = enumr_class_lst.head;
+       while (enumr_c) {
+               if (get_enumr_class(param->enumr_class) == enumr_c) {
+                       found_class = 1;
+                       break;
+               }
+               enumr_c = enumr_c->next;
+       }
+       enumr_class_list_read_unlock();
+       if (!found_class) {
+               ODP_ERR("invalid enumerator class provided!\n");
+               return ODPDRV_ENUMR_INVALID;
+       }
+
+       /* allocate memory for the new enumerator:
+        * If init_global has not been done yet, we have a big issue,
+        * as none of the enumerator classes should be probed before that!
+        * We cannot even issue an error as ODP_* functions have not been
+        * initialised yet, but this is no good...
+        */
+
+       if (init_global_status == UNDONE)
+               return ODPDRV_ENUMR_INVALID;
+
+       enumr = _odp_ishm_pool_alloc(list_elt_pool,
+                                    sizeof(_odpdrv_enumr_t));
+       if (!enumr) {
+               ODP_ERR("_odp_ishm_pool_alloc failed!\n");
+               return ODPDRV_ENUMR_INVALID;
+       }
+
+       /* save init parameters and insert enumerator in list */
+       enumr->param = *param;
+       enumr->probed = 0;
+       enumr_list_write_lock();
+       enumr->next = enumr_lst.head;
+       enumr_lst.head = enumr;
+       enumr_list_write_unlock();
+
+       return (odpdrv_enumr_t)enumr;
 }
 
 odpdrv_device_t odpdrv_device_create(odpdrv_device_param_t *param)
@@ -174,6 +260,7 @@ odpdrv_driver_t 
odpdrv_driver_register(odpdrv_driver_param_t *param)
 void _odpdrv_driver_probe_drv_items(void)
 {
        _odpdrv_enumr_class_t *enumr_c;
+       _odpdrv_enumr_t *enumr;
 
        /* probe unprobed enumerators: */
        enumr_class_list_read_lock();
@@ -186,11 +273,26 @@ void _odpdrv_driver_probe_drv_items(void)
                enumr_c = enumr_c->next;
        }
        enumr_class_list_read_unlock();
+
+       /* go through the list of registered enumerator probing the new
+        * (never probed) ones:
+        */
+       enumr_list_read_lock();
+       enumr = enumr_lst.head;
+       while (enumr) {
+               if (!enumr->probed) {
+                       enumr->param.probe();
+                       enumr->probed = 1;
+               }
+               enumr = enumr->next;
+       }
+       enumr_list_read_unlock();
 }
 
 int odpdrv_print_all(void)
 {
        _odpdrv_enumr_class_t *enumr_c;
+       _odpdrv_enumr_t *enumr;
 
        /* we cannot use ODP_DBG before ODP init... */
        if (init_global_status == UNDONE)
@@ -207,6 +309,21 @@ int odpdrv_print_all(void)
                enumr_c = enumr_c->next;
        }
        enumr_class_list_read_unlock();
+
+       /* print the list of registered enumerators: */
+       enumr_list_read_lock();
+       enumr = enumr_lst.head;
+       ODP_DBG("The following enumerators have been registered:\n");
+       while (enumr) {
+               enumr_c = get_enumr_class(enumr->param.enumr_class);
+               ODP_DBG(" enumerator: class: %s, API: %s, Version: %d\n",
+                       enumr_c->param.name,
+                       enumr->param.api_name,
+                       enumr->param.api_version);
+               enumr = enumr->next;
+       }
+       enumr_list_read_unlock();
+
        return 0;
 }
 
@@ -222,6 +339,7 @@ int _odpdrv_driver_init_global(void)
 
        /* from now, we want to ensure mutex on the list: init lock: */
        odp_rwlock_recursive_init(&enumr_class_lst.lock);
+       odp_rwlock_recursive_init(&enumr_lst.lock);
 
        /* probe things... */
        _odpdrv_driver_probe_drv_items();
@@ -240,10 +358,25 @@ int _odpdrv_driver_init_local(void)
 int _odpdrv_driver_term_global(void)
 {
        _odpdrv_enumr_class_t *enumr_c;
+       _odpdrv_enumr_t *enumr;
 
        if (init_global_status == UNDONE)
                return 0;
 
+       /* remove all enumerators which are registered: */
+       enumr_list_write_lock();
+       while (enumr_lst.head) {
+               enumr = enumr_lst.head;
+               if (enumr->param.remove) { /* run remove callback, if any */
+                       if (enumr->param.remove())
+                               ODP_ERR("Enumerator (API %s) removal failed.\n",
+                                       enumr->param.api_name);
+               }
+               enumr_lst.head = enumr->next;
+               _odp_ishm_pool_free(list_elt_pool, enumr);
+       }
+       enumr_list_write_unlock();
+
        /* remove all enumerator classes which are registered: */
        enumr_class_list_write_lock();
        while (enumr_class_lst.head) {
-- 
2.7.4

Reply via email to