From 0624f52f77e11a6edfc48827a12190f874d572b8 Mon Sep 17 00:00:00 2001 From: Ernesto Ramos Date: Wed, 28 Jul 2010 16:04:53 -0500 Subject: [PATCH] staging: ti dspbridge: use node id instead of kernel address Use idr kernel library to send/receive node ids to the user instead of kernel address. This id will be use to access the node handles at the kernel side, if id does not match to any handle error -EFAULT is returned. Signed-off-by: Ernesto Ramos Signed-off-by: Greg Kroah-Hartman --- .../tidspbridge/include/dspbridge/drv.h | 6 +- .../tidspbridge/include/dspbridge/node.h | 14 +- .../include/dspbridge/resourcecleanup.h | 6 - drivers/staging/tidspbridge/pmgr/dspapi.c | 158 +++++++++++++++--- drivers/staging/tidspbridge/rmgr/drv.c | 153 +++++------------ .../staging/tidspbridge/rmgr/drv_interface.c | 7 +- drivers/staging/tidspbridge/rmgr/node.c | 109 ++++++------ 7 files changed, 257 insertions(+), 196 deletions(-) diff --git a/drivers/staging/tidspbridge/include/dspbridge/drv.h b/drivers/staging/tidspbridge/include/dspbridge/drv.h index 28541f7f07ef..0b36a11820b5 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/drv.h +++ b/drivers/staging/tidspbridge/include/dspbridge/drv.h @@ -24,6 +24,7 @@ #include #include +#include #define DRV_ASSIGN 1 #define DRV_RELEASE 0 @@ -81,7 +82,7 @@ struct node_res_object { s32 node_allocated; /* Node status */ s32 heap_allocated; /* Heap status */ s32 streams_allocated; /* Streams status */ - struct node_res_object *next; + int id; }; /* used to cache dma mapping information */ @@ -158,8 +159,7 @@ struct process_context { void *hprocessor; /* DSP Node resources */ - struct node_res_object *node_list; - struct mutex node_mutex; + struct idr *node_id; /* DMM mapped memory resources */ struct list_head dmm_map_list; diff --git a/drivers/staging/tidspbridge/include/dspbridge/node.h b/drivers/staging/tidspbridge/include/dspbridge/node.h index 61d2d9b7cc9d..49ed5c1128e5 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/node.h +++ b/drivers/staging/tidspbridge/include/dspbridge/node.h @@ -36,7 +36,7 @@ * pargs: Optional arguments to be passed to the node. * attr_in: Optional pointer to node attributes (priority, * timeout...) - * ph_node: Location to store node handle on output. + * noderes: Location to store node resource info. * Returns: * 0: Success. * -ENOMEM: Insufficient memory on GPP. @@ -50,17 +50,17 @@ * node_init(void) called. * hprocessor != NULL. * node_uuid != NULL. - * ph_node != NULL. + * noderes != NULL. * Ensures: * 0: IsValidNode(*ph_node). - * error: *ph_node == NULL. + * error: *noderes == NULL. */ extern int node_allocate(struct proc_object *hprocessor, const struct dsp_uuid *node_uuid, const struct dsp_cbdata *pargs, const struct dsp_nodeattrin *attr_in, - struct node_object **ph_node, + struct node_res_object **noderes, struct process_context *pr_ctxt); /* @@ -242,7 +242,9 @@ extern int node_create_mgr(struct node_mgr **node_man, * delete function. Loads the node's delete function if necessary. * GPP side resources are freed after node's delete function returns. * Parameters: - * hnode: Node handle returned from node_allocate(). + * noderes: Node resource info handle returned from + * node_allocate(). + * pr_ctxt: Poninter to process context data. * Returns: * 0: Success. * -EFAULT: Invalid hnode. @@ -254,7 +256,7 @@ extern int node_create_mgr(struct node_mgr **node_man, * Ensures: * 0: hnode is invalid. */ -extern int node_delete(struct node_object *hnode, +extern int node_delete(struct node_res_object *noderes, struct process_context *pr_ctxt); /* diff --git a/drivers/staging/tidspbridge/include/dspbridge/resourcecleanup.h b/drivers/staging/tidspbridge/include/dspbridge/resourcecleanup.h index 4e1b8a29825a..d17c7fb69d92 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/resourcecleanup.h +++ b/drivers/staging/tidspbridge/include/dspbridge/resourcecleanup.h @@ -34,17 +34,11 @@ extern int drv_remove_all_resources(void *process_ctxt); extern int drv_remove_proc_context(struct drv_object *driver_obj, void *pr_ctxt); -extern int drv_get_node_res_element(void *hnode, void *node_resource, - void *process_ctx); - extern int drv_insert_node_res_element(void *hnode, void *node_resource, void *process_ctxt); extern void drv_proc_node_update_heap_status(void *node_resource, s32 status); -extern int drv_remove_node_res_element(void *node_resource, - void *process_ctxt); - extern void drv_proc_node_update_status(void *node_resource, s32 status); extern int drv_proc_update_strm_res(u32 num_bufs, void *strm_resources); diff --git a/drivers/staging/tidspbridge/pmgr/dspapi.c b/drivers/staging/tidspbridge/pmgr/dspapi.c index da08dfc64593..6eda7c5324a8 100644 --- a/drivers/staging/tidspbridge/pmgr/dspapi.c +++ b/drivers/staging/tidspbridge/pmgr/dspapi.c @@ -1051,6 +1051,20 @@ u32 procwrap_stop(union trapped_args *args, void *pr_ctxt) return ret; } +/* + * ======== find_handle ========= + */ +inline void find_node_handle(struct node_res_object **noderes, + void *pr_ctxt, void *hnode) +{ + rcu_read_lock(); + *noderes = idr_find(((struct process_context *)pr_ctxt)->node_id, + (int)hnode); + rcu_read_unlock(); + return; +} + + /* * ======== nodewrap_allocate ======== */ @@ -1062,7 +1076,7 @@ u32 nodewrap_allocate(union trapped_args *args, void *pr_ctxt) u32 __user *psize = (u32 __user *) args->args_node_allocate.pargs; u8 *pargs = NULL; struct dsp_nodeattrin proc_attr_in, *attr_in = NULL; - struct node_object *hnode; + struct node_res_object *node_res; /* Optional argument */ if (psize) { @@ -1095,13 +1109,14 @@ u32 nodewrap_allocate(union trapped_args *args, void *pr_ctxt) if (!status) { status = node_allocate(args->args_node_allocate.hprocessor, &node_uuid, (struct dsp_cbdata *)pargs, - attr_in, &hnode, pr_ctxt); + attr_in, &node_res, pr_ctxt); } if (!status) { - CP_TO_USR(args->args_node_allocate.ph_node, &hnode, status, 1); + CP_TO_USR(args->args_node_allocate.ph_node, &node_res->id, + status, 1); if (status) { status = -EFAULT; - node_delete(hnode, pr_ctxt); + node_delete(node_res, pr_ctxt); } } func_cont: @@ -1119,6 +1134,13 @@ u32 nodewrap_alloc_msg_buf(union trapped_args *args, void *pr_ctxt) struct dsp_bufferattr *pattr = NULL; struct dsp_bufferattr attr; u8 *pbuffer = NULL; + struct node_res_object *node_res; + + find_node_handle(&node_res, pr_ctxt, + args->args_node_allocmsgbuf.hnode); + + if (!node_res) + return -EFAULT; if (!args->args_node_allocmsgbuf.usize) return -EINVAL; @@ -1132,7 +1154,7 @@ u32 nodewrap_alloc_msg_buf(union trapped_args *args, void *pr_ctxt) /* argument */ CP_FM_USR(&pbuffer, args->args_node_allocmsgbuf.pbuffer, status, 1); if (!status) { - status = node_alloc_msg_buf(args->args_node_allocmsgbuf.hnode, + status = node_alloc_msg_buf(node_res->hnode, args->args_node_allocmsgbuf.usize, pattr, &pbuffer); } @@ -1146,8 +1168,15 @@ u32 nodewrap_alloc_msg_buf(union trapped_args *args, void *pr_ctxt) u32 nodewrap_change_priority(union trapped_args *args, void *pr_ctxt) { u32 ret; + struct node_res_object *node_res; - ret = node_change_priority(args->args_node_changepriority.hnode, + find_node_handle(&node_res, pr_ctxt, + args->args_node_changepriority.hnode); + + if (!node_res) + return -EFAULT; + + ret = node_change_priority(node_res->hnode, args->args_node_changepriority.prio); return ret; @@ -1164,6 +1193,29 @@ u32 nodewrap_connect(union trapped_args *args, void *pr_ctxt) u32 cb_data_size; u32 __user *psize = (u32 __user *) args->args_node_connect.conn_param; u8 *pargs = NULL; + struct node_res_object *node_res1, *node_res2; + struct node_object *node1 = NULL, *node2 = NULL; + + if ((int)args->args_node_connect.hnode != DSP_HGPPNODE) { + find_node_handle(&node_res1, pr_ctxt, + args->args_node_connect.hnode); + if (node_res1) + node1 = node_res1->hnode; + } else { + node1 = args->args_node_connect.hnode; + } + + if ((int)args->args_node_connect.other_node != DSP_HGPPNODE) { + find_node_handle(&node_res2, pr_ctxt, + args->args_node_connect.other_node); + if (node_res2) + node2 = node_res2->hnode; + } else { + node2 = args->args_node_connect.other_node; + } + + if (!node1 || !node2) + return -EFAULT; /* Optional argument */ if (psize) { @@ -1191,9 +1243,9 @@ u32 nodewrap_connect(union trapped_args *args, void *pr_ctxt) } if (!status) { - status = node_connect(args->args_node_connect.hnode, + status = node_connect(node1, args->args_node_connect.stream_id, - args->args_node_connect.other_node, + node2, args->args_node_connect.other_stream, pattrs, (struct dsp_cbdata *)pargs); } @@ -1209,8 +1261,14 @@ func_cont: u32 nodewrap_create(union trapped_args *args, void *pr_ctxt) { u32 ret; + struct node_res_object *node_res; + + find_node_handle(&node_res, pr_ctxt, args->args_node_create.hnode); - ret = node_create(args->args_node_create.hnode); + if (!node_res) + return -EFAULT; + + ret = node_create(node_res->hnode); return ret; } @@ -1221,8 +1279,14 @@ u32 nodewrap_create(union trapped_args *args, void *pr_ctxt) u32 nodewrap_delete(union trapped_args *args, void *pr_ctxt) { u32 ret; + struct node_res_object *node_res; + + find_node_handle(&node_res, pr_ctxt, args->args_node_delete.hnode); + + if (!node_res) + return -EFAULT; - ret = node_delete(args->args_node_delete.hnode, pr_ctxt); + ret = node_delete(node_res, pr_ctxt); return ret; } @@ -1235,6 +1299,13 @@ u32 nodewrap_free_msg_buf(union trapped_args *args, void *pr_ctxt) int status = 0; struct dsp_bufferattr *pattr = NULL; struct dsp_bufferattr attr; + struct node_res_object *node_res; + + find_node_handle(&node_res, pr_ctxt, args->args_node_freemsgbuf.hnode); + + if (!node_res) + return -EFAULT; + if (args->args_node_freemsgbuf.pattr) { /* Optional argument */ CP_FM_USR(&attr, args->args_node_freemsgbuf.pattr, status, 1); if (!status) @@ -1246,7 +1317,7 @@ u32 nodewrap_free_msg_buf(union trapped_args *args, void *pr_ctxt) return -EFAULT; if (!status) { - status = node_free_msg_buf(args->args_node_freemsgbuf.hnode, + status = node_free_msg_buf(node_res->hnode, args->args_node_freemsgbuf.pbuffer, pattr); } @@ -1261,8 +1332,14 @@ u32 nodewrap_get_attr(union trapped_args *args, void *pr_ctxt) { int status = 0; struct dsp_nodeattr attr; + struct node_res_object *node_res; - status = node_get_attr(args->args_node_getattr.hnode, &attr, + find_node_handle(&node_res, pr_ctxt, args->args_node_getattr.hnode); + + if (!node_res) + return -EFAULT; + + status = node_get_attr(node_res->hnode, &attr, args->args_node_getattr.attr_size); CP_TO_USR(args->args_node_getattr.pattr, &attr, status, 1); @@ -1276,8 +1353,14 @@ u32 nodewrap_get_message(union trapped_args *args, void *pr_ctxt) { int status; struct dsp_msg msg; + struct node_res_object *node_res; + + find_node_handle(&node_res, pr_ctxt, args->args_node_getmessage.hnode); - status = node_get_message(args->args_node_getmessage.hnode, &msg, + if (!node_res) + return -EFAULT; + + status = node_get_message(node_res->hnode, &msg, args->args_node_getmessage.utimeout); CP_TO_USR(args->args_node_getmessage.message, &msg, status, 1); @@ -1291,8 +1374,14 @@ u32 nodewrap_get_message(union trapped_args *args, void *pr_ctxt) u32 nodewrap_pause(union trapped_args *args, void *pr_ctxt) { u32 ret; + struct node_res_object *node_res; + + find_node_handle(&node_res, pr_ctxt, args->args_node_pause.hnode); + + if (!node_res) + return -EFAULT; - ret = node_pause(args->args_node_pause.hnode); + ret = node_pause(node_res->hnode); return ret; } @@ -1304,12 +1393,18 @@ u32 nodewrap_put_message(union trapped_args *args, void *pr_ctxt) { int status = 0; struct dsp_msg msg; + struct node_res_object *node_res; + + find_node_handle(&node_res, pr_ctxt, args->args_node_putmessage.hnode); + + if (!node_res) + return -EFAULT; CP_FM_USR(&msg, args->args_node_putmessage.message, status, 1); if (!status) { status = - node_put_message(args->args_node_putmessage.hnode, &msg, + node_put_message(node_res->hnode, &msg, args->args_node_putmessage.utimeout); } @@ -1323,6 +1418,13 @@ u32 nodewrap_register_notify(union trapped_args *args, void *pr_ctxt) { int status = 0; struct dsp_notification notification; + struct node_res_object *node_res; + + find_node_handle(&node_res, pr_ctxt, + args->args_node_registernotify.hnode); + + if (!node_res) + return -EFAULT; /* Initialize the notification data structure */ notification.ps_name = NULL; @@ -1333,7 +1435,7 @@ u32 nodewrap_register_notify(union trapped_args *args, void *pr_ctxt) args->args_proc_register_notify.hnotification, status, 1); - status = node_register_notify(args->args_node_registernotify.hnode, + status = node_register_notify(node_res->hnode, args->args_node_registernotify.event_mask, args->args_node_registernotify. notify_type, ¬ification); @@ -1348,8 +1450,14 @@ u32 nodewrap_register_notify(union trapped_args *args, void *pr_ctxt) u32 nodewrap_run(union trapped_args *args, void *pr_ctxt) { u32 ret; + struct node_res_object *node_res; + + find_node_handle(&node_res, pr_ctxt, args->args_node_run.hnode); + + if (!node_res) + return -EFAULT; - ret = node_run(args->args_node_run.hnode); + ret = node_run(node_res->hnode); return ret; } @@ -1361,8 +1469,14 @@ u32 nodewrap_terminate(union trapped_args *args, void *pr_ctxt) { int status; int tempstatus; + struct node_res_object *node_res; - status = node_terminate(args->args_node_terminate.hnode, &tempstatus); + find_node_handle(&node_res, pr_ctxt, args->args_node_terminate.hnode); + + if (!node_res) + return -EFAULT; + + status = node_terminate(node_res->hnode, &tempstatus); CP_TO_USR(args->args_node_terminate.pstatus, &tempstatus, status, 1); @@ -1548,6 +1662,12 @@ u32 strmwrap_open(union trapped_args *args, void *pr_ctxt) struct strm_attr attr; struct strm_object *strm_obj; struct dsp_streamattrin strm_attr_in; + struct node_res_object *node_res; + + find_node_handle(&node_res, pr_ctxt, args->args_strm_open.hnode); + + if (!node_res) + return -EFAULT; CP_FM_USR(&attr, args->args_strm_open.attr_in, status, 1); @@ -1560,7 +1680,7 @@ u32 strmwrap_open(union trapped_args *args, void *pr_ctxt) } } - status = strm_open(args->args_strm_open.hnode, + status = strm_open(node_res->hnode, args->args_strm_open.direction, args->args_strm_open.index, &attr, &strm_obj, pr_ctxt); diff --git a/drivers/staging/tidspbridge/rmgr/drv.c b/drivers/staging/tidspbridge/rmgr/drv.c index 12c270aa7ac9..c8d9d2551ff0 100644 --- a/drivers/staging/tidspbridge/rmgr/drv.c +++ b/drivers/staging/tidspbridge/rmgr/drv.c @@ -73,7 +73,7 @@ static int request_bridge_resources(struct cfg_hostres *res); /* GPP PROCESS CLEANUP CODE */ -static int drv_proc_free_node_res(void *process_ctxt); +static int drv_proc_free_node_res(int id, void *p, void *data); /* Allocate and add a node resource element * This function is called from .Node_Allocate. */ @@ -84,88 +84,61 @@ int drv_insert_node_res_element(void *hnode, void *node_resource, (struct node_res_object **)node_resource; struct process_context *ctxt = (struct process_context *)process_ctxt; int status = 0; - struct node_res_object *temp_node_res = NULL; + int retval; *node_res_obj = kzalloc(sizeof(struct node_res_object), GFP_KERNEL); - if (*node_res_obj == NULL) - status = -EFAULT; + if (!*node_res_obj) { + status = -ENOMEM; + goto func_end; + } - if (!status) { - if (mutex_lock_interruptible(&ctxt->node_mutex)) { - kfree(*node_res_obj); - return -EPERM; + (*node_res_obj)->hnode = hnode; + retval = idr_get_new(ctxt->node_id, *node_res_obj, + &(*node_res_obj)->id); + if (retval == -EAGAIN) { + if (!idr_pre_get(ctxt->node_id, GFP_KERNEL)) { + pr_err("%s: OUT OF MEMORY\n", __func__); + status = -ENOMEM; + goto func_end; } - (*node_res_obj)->hnode = hnode; - if (ctxt->node_list != NULL) { - temp_node_res = ctxt->node_list; - while (temp_node_res->next != NULL) - temp_node_res = temp_node_res->next; - temp_node_res->next = *node_res_obj; - } else { - ctxt->node_list = *node_res_obj; - } - mutex_unlock(&ctxt->node_mutex); + retval = idr_get_new(ctxt->node_id, *node_res_obj, + &(*node_res_obj)->id); + } + if (retval) { + pr_err("%s: FAILED, IDR is FULL\n", __func__); + status = -EFAULT; } +func_end: + if (status) + kfree(*node_res_obj); return status; } /* Release all Node resources and its context -* This is called from .Node_Delete. */ -int drv_remove_node_res_element(void *node_resource, void *process_ctxt) + * Actual Node De-Allocation */ +static int drv_proc_free_node_res(int id, void *p, void *data) { - struct node_res_object *node_res_obj = - (struct node_res_object *)node_resource; - struct process_context *ctxt = (struct process_context *)process_ctxt; - struct node_res_object *temp_node; - int status = 0; - - if (mutex_lock_interruptible(&ctxt->node_mutex)) - return -EPERM; - temp_node = ctxt->node_list; - if (temp_node == node_res_obj) { - ctxt->node_list = node_res_obj->next; - } else { - while (temp_node && temp_node->next != node_res_obj) - temp_node = temp_node->next; - if (!temp_node) - status = -ENOENT; - else - temp_node->next = node_res_obj->next; - } - mutex_unlock(&ctxt->node_mutex); - kfree(node_res_obj); - return status; -} - -/* Actual Node De-Allocation */ -static int drv_proc_free_node_res(void *process_ctxt) -{ - struct process_context *ctxt = (struct process_context *)process_ctxt; - int status = 0; - struct node_res_object *node_list = NULL; - struct node_res_object *node_res_obj = NULL; + struct process_context *ctxt = data; + int status; + struct node_res_object *node_res_obj = p; u32 node_state; - node_list = ctxt->node_list; - while (node_list != NULL) { - node_res_obj = node_list; - node_list = node_list->next; - if (node_res_obj->node_allocated) { - node_state = node_get_state(node_res_obj->hnode); - if (node_state <= NODE_DELETING) { - if ((node_state == NODE_RUNNING) || - (node_state == NODE_PAUSED) || - (node_state == NODE_TERMINATING)) - status = node_terminate - (node_res_obj->hnode, &status); - - status = node_delete(node_res_obj->hnode, ctxt); - } + if (node_res_obj->node_allocated) { + node_state = node_get_state(node_res_obj->hnode); + if (node_state <= NODE_DELETING) { + if ((node_state == NODE_RUNNING) || + (node_state == NODE_PAUSED) || + (node_state == NODE_TERMINATING)) + node_terminate + (node_res_obj->hnode, &status); + + node_delete(node_res_obj, ctxt); } } - return status; + + return 0; } /* Release all Mapped and Reserved DMM resources */ @@ -220,50 +193,12 @@ void drv_proc_node_update_heap_status(void *node_resource, s32 status) */ int drv_remove_all_node_res_elements(void *process_ctxt) { - struct process_context *ctxt = (struct process_context *)process_ctxt; - int status = 0; - struct node_res_object *temp_node2 = NULL; - struct node_res_object *temp_node = NULL; - - drv_proc_free_node_res(ctxt); - temp_node = ctxt->node_list; - while (temp_node != NULL) { - temp_node2 = temp_node; - temp_node = temp_node->next; - kfree(temp_node2); - } - ctxt->node_list = NULL; - return status; -} + struct process_context *ctxt = process_ctxt; -/* Getting the node resource element */ -int drv_get_node_res_element(void *hnode, void *node_resource, - void *process_ctxt) -{ - struct node_res_object **node_res = - (struct node_res_object **)node_resource; - struct process_context *ctxt = (struct process_context *)process_ctxt; - int status = 0; - struct node_res_object *temp_node2 = NULL; - struct node_res_object *temp_node = NULL; - - if (mutex_lock_interruptible(&ctxt->node_mutex)) - return -EPERM; - - temp_node = ctxt->node_list; - while ((temp_node != NULL) && (temp_node->hnode != hnode)) { - temp_node2 = temp_node; - temp_node = temp_node->next; - } + idr_for_each(ctxt->node_id, drv_proc_free_node_res, ctxt); + idr_destroy(ctxt->node_id); - mutex_unlock(&ctxt->node_mutex); - - if (temp_node != NULL) - *node_res = temp_node; - else - status = -ENOENT; - - return status; + return 0; } /* Allocate the STRM resource element diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index aec7cf7d0d58..900cdd356f76 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -511,8 +511,13 @@ static int bridge_open(struct inode *ip, struct file *filp) INIT_LIST_HEAD(&pr_ctxt->dmm_map_list); spin_lock_init(&pr_ctxt->dmm_rsv_lock); INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list); - mutex_init(&pr_ctxt->node_mutex); mutex_init(&pr_ctxt->strm_mutex); + + pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL); + if (pr_ctxt->node_id) + idr_init(pr_ctxt->node_id); + else + status = -ENOMEM; } else { status = -ENOMEM; } diff --git a/drivers/staging/tidspbridge/rmgr/node.c b/drivers/staging/tidspbridge/rmgr/node.c index e2d02c410e04..6e9441e21265 100644 --- a/drivers/staging/tidspbridge/rmgr/node.c +++ b/drivers/staging/tidspbridge/rmgr/node.c @@ -291,11 +291,11 @@ enum node_state node_get_state(void *hnode) * Allocate GPP resources to manage a node on the DSP. */ int node_allocate(struct proc_object *hprocessor, - const struct dsp_uuid *node_uuid, - const struct dsp_cbdata *pargs, - const struct dsp_nodeattrin *attr_in, - struct node_object **ph_node, - struct process_context *pr_ctxt) + const struct dsp_uuid *node_uuid, + const struct dsp_cbdata *pargs, + const struct dsp_nodeattrin *attr_in, + struct node_res_object **noderes, + struct process_context *pr_ctxt) { struct node_mgr *hnode_mgr; struct dev_object *hdev_obj; @@ -327,10 +327,10 @@ int node_allocate(struct proc_object *hprocessor, DBC_REQUIRE(refs > 0); DBC_REQUIRE(hprocessor != NULL); - DBC_REQUIRE(ph_node != NULL); + DBC_REQUIRE(noderes != NULL); DBC_REQUIRE(node_uuid != NULL); - *ph_node = NULL; + *noderes = NULL; status = proc_get_processor_id(hprocessor, &proc_id); @@ -653,9 +653,6 @@ func_cont: * (for overlay and dll) */ pnode->phase_split = true; - if (!status) - *ph_node = pnode; - /* Notify all clients registered for DSP_NODESTATECHANGE. */ proc_notify_all_clients(hprocessor, DSP_NODESTATECHANGE); } else { @@ -666,16 +663,21 @@ func_cont: } if (!status) { - drv_insert_node_res_element(*ph_node, &node_res, pr_ctxt); + status = drv_insert_node_res_element(pnode, &node_res, pr_ctxt); + if (status) { + delete_node(pnode, pr_ctxt); + goto func_end; + } + + *noderes = (struct node_res_object *)node_res; drv_proc_node_update_heap_status(node_res, true); drv_proc_node_update_status(node_res, true); } - DBC_ENSURE((status && (*ph_node == NULL)) || - (!status && *ph_node)); + DBC_ENSURE((status && *noderes == NULL) || (!status && *noderes)); func_end: - dev_dbg(bridge, "%s: hprocessor: %p node_uuid: %p pargs: %p attr_in:" - " %p ph_node: %p status: 0x%x\n", __func__, hprocessor, - node_uuid, pargs, attr_in, ph_node, status); + dev_dbg(bridge, "%s: hprocessor: %p pNodeId: %p pargs: %p attr_in: %p " + "node_res: %p status: 0x%x\n", __func__, hprocessor, + node_uuid, pargs, attr_in, noderes, status); return status; } @@ -1433,10 +1435,10 @@ int node_create_mgr(struct node_mgr **node_man, * Loads the node's delete function if necessary. Free GPP side resources * after node's delete function returns. */ -int node_delete(struct node_object *hnode, +int node_delete(struct node_res_object *noderes, struct process_context *pr_ctxt) { - struct node_object *pnode = (struct node_object *)hnode; + struct node_object *pnode = noderes->hnode; struct node_mgr *hnode_mgr; struct proc_object *hprocessor; struct disp_object *disp_obj; @@ -1449,32 +1451,32 @@ int node_delete(struct node_object *hnode, u32 proc_id; struct bridge_drv_interface *intf_fxns; - void *node_res; + void *node_res = noderes; struct dsp_processorstate proc_state; DBC_REQUIRE(refs > 0); - if (!hnode) { + if (!pnode) { status = -EFAULT; goto func_end; } /* create struct dsp_cbdata struct for PWR call */ cb_data.cb_data = PWR_TIMEOUT; - hnode_mgr = hnode->hnode_mgr; - hprocessor = hnode->hprocessor; + hnode_mgr = pnode->hnode_mgr; + hprocessor = pnode->hprocessor; disp_obj = hnode_mgr->disp_obj; - node_type = node_get_type(hnode); + node_type = node_get_type(pnode); intf_fxns = hnode_mgr->intf_fxns; /* Enter critical section */ mutex_lock(&hnode_mgr->node_mgr_lock); - state = node_get_state(hnode); + state = node_get_state(pnode); /* Execute delete phase code for non-device node in all cases * except when the node was only allocated. Delete phase must be * executed even if create phase was executed, but failed. * If the node environment pointer is non-NULL, the delete phase * code must be executed. */ - if (!(state == NODE_ALLOCATED && hnode->node_env == (u32) NULL) && + if (!(state == NODE_ALLOCATED && pnode->node_env == (u32) NULL) && node_type != NODE_DEVICE) { status = proc_get_processor_id(pnode->hprocessor, &proc_id); if (status) @@ -1487,26 +1489,26 @@ int node_delete(struct node_object *hnode, * is now ok to unload it. If the node is running, we * will unload the execute phase only after deleting * the node. */ - if (state == NODE_PAUSED && hnode->loaded && - hnode->phase_split) { + if (state == NODE_PAUSED && pnode->loaded && + pnode->phase_split) { /* Ok to unload execute code as long as node * is not * running */ status1 = hnode_mgr->nldr_fxns. - pfn_unload(hnode->nldr_node_obj, + pfn_unload(pnode->nldr_node_obj, NLDR_EXECUTE); - hnode->loaded = false; - NODE_SET_STATE(hnode, NODE_DONE); + pnode->loaded = false; + NODE_SET_STATE(pnode, NODE_DONE); } /* Load delete phase code if not loaded or if haven't * * unloaded EXECUTE phase */ - if ((!(hnode->loaded) || (state == NODE_RUNNING)) && - hnode->phase_split) { + if ((!(pnode->loaded) || (state == NODE_RUNNING)) && + pnode->phase_split) { status = hnode_mgr->nldr_fxns. - pfn_load(hnode->nldr_node_obj, NLDR_DELETE); + pfn_load(pnode->nldr_node_obj, NLDR_DELETE); if (!status) - hnode->loaded = true; + pnode->loaded = true; else pr_err("%s: fail - load delete code:" " 0x%x\n", __func__, status); @@ -1515,14 +1517,14 @@ int node_delete(struct node_object *hnode, func_cont1: if (!status) { /* Unblock a thread trying to terminate the node */ - (void)sync_set_event(hnode->sync_done); + (void)sync_set_event(pnode->sync_done); if (proc_id == DSP_UNIT) { /* ul_delete_fxn = address of node's delete * function */ - status = get_fxn_address(hnode, &ul_delete_fxn, + status = get_fxn_address(pnode, &ul_delete_fxn, DELETEPHASE); } else if (proc_id == IVA_UNIT) - ul_delete_fxn = (u32) hnode->node_env; + ul_delete_fxn = (u32) pnode->node_env; if (!status) { status = proc_get_state(hprocessor, &proc_state, @@ -1530,22 +1532,22 @@ func_cont1: dsp_processorstate)); if (proc_state.proc_state != PROC_ERROR) { status = - disp_node_delete(disp_obj, hnode, + disp_node_delete(disp_obj, pnode, hnode_mgr-> ul_fxn_addrs [RMSDELETENODE], ul_delete_fxn, - hnode->node_env); + pnode->node_env); } else - NODE_SET_STATE(hnode, NODE_DONE); + NODE_SET_STATE(pnode, NODE_DONE); /* Unload execute, if not unloaded, and delete * function */ if (state == NODE_RUNNING && - hnode->phase_split) { + pnode->phase_split) { status1 = hnode_mgr->nldr_fxns. - pfn_unload(hnode->nldr_node_obj, + pfn_unload(pnode->nldr_node_obj, NLDR_EXECUTE); } if (status1) @@ -1553,10 +1555,10 @@ func_cont1: " 0x%x\n", __func__, status1); status1 = - hnode_mgr->nldr_fxns.pfn_unload(hnode-> + hnode_mgr->nldr_fxns.pfn_unload(pnode-> nldr_node_obj, NLDR_DELETE); - hnode->loaded = false; + pnode->loaded = false; if (status1) pr_err("%s: fail - unload delete code: " "0x%x\n", __func__, status1); @@ -1565,25 +1567,28 @@ func_cont1: } /* Free host side resources even if a failure occurred */ /* Remove node from hnode_mgr->node_list */ - lst_remove_elem(hnode_mgr->node_list, (struct list_head *)hnode); + lst_remove_elem(hnode_mgr->node_list, (struct list_head *)pnode); hnode_mgr->num_nodes--; /* Decrement count of nodes created on DSP */ if ((state != NODE_ALLOCATED) || ((state == NODE_ALLOCATED) && - (hnode->node_env != (u32) NULL))) + (pnode->node_env != (u32) NULL))) hnode_mgr->num_created--; /* Free host-side resources allocated by node_create() * delete_node() fails if SM buffers not freed by client! */ - if (drv_get_node_res_element(hnode, &node_res, pr_ctxt) != - -ENOENT) - drv_proc_node_update_status(node_res, false); - delete_node(hnode, pr_ctxt); + drv_proc_node_update_status(node_res, false); + delete_node(pnode, pr_ctxt); + + /* + * Release all Node resources and its context + */ + idr_remove(pr_ctxt->node_id, ((struct node_res_object *)node_res)->id); + kfree(node_res); - drv_remove_node_res_element(node_res, pr_ctxt); /* Exit critical section */ mutex_unlock(&hnode_mgr->node_mgr_lock); proc_notify_clients(hprocessor, DSP_NODESTATECHANGE); func_end: - dev_dbg(bridge, "%s: hnode: %p status 0x%x\n", __func__, hnode, status); + dev_dbg(bridge, "%s: pnode: %p status 0x%x\n", __func__, pnode, status); return status; } -- 2.39.5