diff options
Diffstat (limited to 'drivers/staging/tidspbridge/rmgr/nldr.c')
-rw-r--r-- | drivers/staging/tidspbridge/rmgr/nldr.c | 1861 |
1 files changed, 0 insertions, 1861 deletions
diff --git a/drivers/staging/tidspbridge/rmgr/nldr.c b/drivers/staging/tidspbridge/rmgr/nldr.c deleted file mode 100644 index 900585ab059a..000000000000 --- a/drivers/staging/tidspbridge/rmgr/nldr.c +++ /dev/null @@ -1,1861 +0,0 @@ -/* - * nldr.c - * - * DSP-BIOS Bridge driver support functions for TI OMAP processors. - * - * DSP/BIOS Bridge dynamic + overlay Node loader. - * - * Copyright (C) 2005-2006 Texas Instruments, Inc. - * - * This package is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#include <linux/types.h> - -#include <dspbridge/host_os.h> - -#include <dspbridge/dbdefs.h> - -/* Platform manager */ -#include <dspbridge/cod.h> -#include <dspbridge/dev.h> - -/* Resource manager */ -#include <dspbridge/dbll.h> -#include <dspbridge/dbdcd.h> -#include <dspbridge/rmm.h> -#include <dspbridge/uuidutil.h> - -#include <dspbridge/nldr.h> -#include <linux/lcm.h> - -/* Name of section containing dynamic load mem */ -#define DYNMEMSECT ".dspbridge_mem" - -/* Name of section containing dependent library information */ -#define DEPLIBSECT ".dspbridge_deplibs" - -/* Max depth of recursion for loading node's dependent libraries */ -#define MAXDEPTH 5 - -/* Max number of persistent libraries kept by a node */ -#define MAXLIBS 5 - -/* - * Defines for extracting packed dynamic load memory requirements from two - * masks. - * These defines must match node.cdb and dynm.cdb - * Format of data/code mask is: - * uuuuuuuu|fueeeeee|fudddddd|fucccccc| - * where - * u = unused - * cccccc = preferred/required dynamic mem segid for create phase data/code - * dddddd = preferred/required dynamic mem segid for delete phase data/code - * eeeeee = preferred/req. dynamic mem segid for execute phase data/code - * f = flag indicating if memory is preferred or required: - * f = 1 if required, f = 0 if preferred. - * - * The 6 bits of the segid are interpreted as follows: - * - * If the 6th bit (bit 5) is not set, then this specifies a memory segment - * between 0 and 31 (a maximum of 32 dynamic loading memory segments). - * If the 6th bit (bit 5) is set, segid has the following interpretation: - * segid = 32 - Any internal memory segment can be used. - * segid = 33 - Any external memory segment can be used. - * segid = 63 - Any memory segment can be used (in this case the - * required/preferred flag is irrelevant). - * - */ -/* Maximum allowed dynamic loading memory segments */ -#define MAXMEMSEGS 32 - -#define MAXSEGID 3 /* Largest possible (real) segid */ -#define MEMINTERNALID 32 /* Segid meaning use internal mem */ -#define MEMEXTERNALID 33 /* Segid meaning use external mem */ -#define NULLID 63 /* Segid meaning no memory req/pref */ -#define FLAGBIT 7 /* 7th bit is pref./req. flag */ -#define SEGMASK 0x3f /* Bits 0 - 5 */ - -#define CREATEBIT 0 /* Create segid starts at bit 0 */ -#define DELETEBIT 8 /* Delete segid starts at bit 8 */ -#define EXECUTEBIT 16 /* Execute segid starts at bit 16 */ - -/* - * Masks that define memory type. Must match defines in dynm.cdb. - */ -#define DYNM_CODE 0x2 -#define DYNM_DATA 0x4 -#define DYNM_CODEDATA (DYNM_CODE | DYNM_DATA) -#define DYNM_INTERNAL 0x8 -#define DYNM_EXTERNAL 0x10 - -/* - * Defines for packing memory requirement/preference flags for code and - * data of each of the node's phases into one mask. - * The bit is set if the segid is required for loading code/data of the - * given phase. The bit is not set, if the segid is preferred only. - * - * These defines are also used as indeces into a segid array for the node. - * eg node's segid[CREATEDATAFLAGBIT] is the memory segment id that the - * create phase data is required or preferred to be loaded into. - */ -#define CREATEDATAFLAGBIT 0 -#define CREATECODEFLAGBIT 1 -#define EXECUTEDATAFLAGBIT 2 -#define EXECUTECODEFLAGBIT 3 -#define DELETEDATAFLAGBIT 4 -#define DELETECODEFLAGBIT 5 -#define MAXFLAGS 6 - - /* - * These names may be embedded in overlay sections to identify which - * node phase the section should be overlayed. - */ -#define PCREATE "create" -#define PDELETE "delete" -#define PEXECUTE "execute" - -static inline bool is_equal_uuid(struct dsp_uuid *uuid1, - struct dsp_uuid *uuid2) -{ - return !memcmp(uuid1, uuid2, sizeof(struct dsp_uuid)); -} - - /* - * ======== mem_seg_info ======== - * Format of dynamic loading memory segment info in coff file. - * Must match dynm.h55. - */ -struct mem_seg_info { - u32 segid; /* Dynamic loading memory segment number */ - u32 base; - u32 len; - u32 type; /* Mask of DYNM_CODE, DYNM_INTERNAL, etc. */ -}; - -/* - * ======== lib_node ======== - * For maintaining a tree of library dependencies. - */ -struct lib_node { - struct dbll_library_obj *lib; /* The library */ - u16 dep_libs; /* Number of dependent libraries */ - struct lib_node *dep_libs_tree; /* Dependent libraries of lib */ -}; - -/* - * ======== ovly_sect ======== - * Information needed to overlay a section. - */ -struct ovly_sect { - struct ovly_sect *next_sect; - u32 sect_load_addr; /* Load address of section */ - u32 sect_run_addr; /* Run address of section */ - u32 size; /* Size of section */ - u16 page; /* DBL_CODE, DBL_DATA */ -}; - -/* - * ======== ovly_node ======== - * For maintaining a list of overlay nodes, with sections that need to be - * overlayed for each of the nodes phases. - */ -struct ovly_node { - struct dsp_uuid uuid; - char *node_name; - struct ovly_sect *create_sects_list; - struct ovly_sect *delete_sects_list; - struct ovly_sect *execute_sects_list; - struct ovly_sect *other_sects_list; - u16 create_sects; - u16 delete_sects; - u16 execute_sects; - u16 other_sects; - u16 create_ref; - u16 delete_ref; - u16 execute_ref; - u16 other_ref; -}; - -/* - * ======== nldr_object ======== - * Overlay loader object. - */ -struct nldr_object { - struct dev_object *dev_obj; /* Device object */ - struct dcd_manager *dcd_mgr; /* Proc/Node data manager */ - struct dbll_tar_obj *dbll; /* The DBL loader */ - struct dbll_library_obj *base_lib; /* Base image library */ - struct rmm_target_obj *rmm; /* Remote memory manager for DSP */ - struct dbll_fxns ldr_fxns; /* Loader function table */ - struct dbll_attrs ldr_attrs; /* attrs to pass to loader functions */ - nldr_ovlyfxn ovly_fxn; /* "write" for overlay nodes */ - nldr_writefxn write_fxn; /* "write" for dynamic nodes */ - struct ovly_node *ovly_table; /* Table of overlay nodes */ - u16 ovly_nodes; /* Number of overlay nodes in base */ - u16 ovly_nid; /* Index for tracking overlay nodes */ - u16 dload_segs; /* Number of dynamic load mem segs */ - u32 *seg_table; /* memtypes of dynamic memory segs - * indexed by segid - */ - u16 dsp_mau_size; /* Size of DSP MAU */ - u16 dsp_word_size; /* Size of DSP word */ -}; - -/* - * ======== nldr_nodeobject ======== - * Dynamic node object. This object is created when a node is allocated. - */ -struct nldr_nodeobject { - struct nldr_object *nldr_obj; /* Dynamic loader handle */ - void *priv_ref; /* Handle to pass to dbl_write_fxn */ - struct dsp_uuid uuid; /* Node's UUID */ - bool dynamic; /* Dynamically loaded node? */ - bool overlay; /* Overlay node? */ - bool *phase_split; /* Multiple phase libraries? */ - struct lib_node root; /* Library containing node phase */ - struct lib_node create_lib; /* Library with create phase lib */ - struct lib_node execute_lib; /* Library with execute phase lib */ - struct lib_node delete_lib; /* Library with delete phase lib */ - /* libs remain loaded until Delete */ - struct lib_node pers_lib_table[MAXLIBS]; - s32 pers_libs; /* Number of persistent libraries */ - /* Path in lib dependency tree */ - struct dbll_library_obj *lib_path[MAXDEPTH + 1]; - enum nldr_phase phase; /* Node phase currently being loaded */ - - /* - * Dynamic loading memory segments for data and code of each phase. - */ - u16 seg_id[MAXFLAGS]; - - /* - * Mask indicating whether each mem segment specified in seg_id[] - * is preferred or required. - * For example - * if (code_data_flag_mask & (1 << EXECUTEDATAFLAGBIT)) != 0, - * then it is required to load execute phase data into the memory - * specified by seg_id[EXECUTEDATAFLAGBIT]. - */ - u32 code_data_flag_mask; -}; - -/* Dynamic loader function table */ -static struct dbll_fxns ldr_fxns = { - (dbll_close_fxn) dbll_close, - (dbll_create_fxn) dbll_create, - (dbll_delete_fxn) dbll_delete, - (dbll_exit_fxn) dbll_exit, - (dbll_get_attrs_fxn) dbll_get_attrs, - (dbll_get_addr_fxn) dbll_get_addr, - (dbll_get_c_addr_fxn) dbll_get_c_addr, - (dbll_get_sect_fxn) dbll_get_sect, - (dbll_init_fxn) dbll_init, - (dbll_load_fxn) dbll_load, - (dbll_open_fxn) dbll_open, - (dbll_read_sect_fxn) dbll_read_sect, - (dbll_unload_fxn) dbll_unload, -}; - -static int add_ovly_info(void *handle, struct dbll_sect_info *sect_info, - u32 addr, u32 bytes); -static int add_ovly_node(struct dsp_uuid *uuid_obj, - enum dsp_dcdobjtype obj_type, void *handle); -static int add_ovly_sect(struct nldr_object *nldr_obj, - struct ovly_sect **lst, - struct dbll_sect_info *sect_inf, - bool *exists, u32 addr, u32 bytes); -static s32 fake_ovly_write(void *handle, u32 dsp_address, void *buf, u32 bytes, - s32 mtype); -static void free_sects(struct nldr_object *nldr_obj, - struct ovly_sect *phase_sects, u16 alloc_num); -static bool get_symbol_value(void *handle, void *parg, void *rmm_handle, - char *sym_name, struct dbll_sym_val **sym); -static int load_lib(struct nldr_nodeobject *nldr_node_obj, - struct lib_node *root, struct dsp_uuid uuid, - bool root_prstnt, - struct dbll_library_obj **lib_path, - enum nldr_phase phase, u16 depth); -static int load_ovly(struct nldr_nodeobject *nldr_node_obj, - enum nldr_phase phase); -static int remote_alloc(void **ref, u16 mem_sect, u32 size, - u32 align, u32 *dsp_address, - s32 segmnt_id, - s32 req, bool reserve); -static int remote_free(void **ref, u16 space, u32 dsp_address, u32 size, - bool reserve); - -static void unload_lib(struct nldr_nodeobject *nldr_node_obj, - struct lib_node *root); -static void unload_ovly(struct nldr_nodeobject *nldr_node_obj, - enum nldr_phase phase); -static bool find_in_persistent_lib_array(struct nldr_nodeobject *nldr_node_obj, - struct dbll_library_obj *lib); - -/* - * ======== nldr_allocate ======== - */ -int nldr_allocate(struct nldr_object *nldr_obj, void *priv_ref, - const struct dcd_nodeprops *node_props, - struct nldr_nodeobject **nldr_nodeobj, - bool *pf_phase_split) -{ - struct nldr_nodeobject *nldr_node_obj = NULL; - int status = 0; - - /* Initialize handle in case of failure */ - *nldr_nodeobj = NULL; - /* Allocate node object */ - nldr_node_obj = kzalloc(sizeof(struct nldr_nodeobject), GFP_KERNEL); - - if (nldr_node_obj == NULL) { - status = -ENOMEM; - } else { - nldr_node_obj->phase_split = pf_phase_split; - nldr_node_obj->pers_libs = 0; - nldr_node_obj->nldr_obj = nldr_obj; - nldr_node_obj->priv_ref = priv_ref; - /* Save node's UUID. */ - nldr_node_obj->uuid = node_props->ndb_props.ui_node_id; - /* - * Determine if node is a dynamically loaded node from - * ndb_props. - */ - if (node_props->load_type == NLDR_DYNAMICLOAD) { - /* Dynamic node */ - nldr_node_obj->dynamic = true; - /* - * Extract memory requirements from ndb_props masks - */ - /* Create phase */ - nldr_node_obj->seg_id[CREATEDATAFLAGBIT] = (u16) - (node_props->data_mem_seg_mask >> CREATEBIT) & - SEGMASK; - nldr_node_obj->code_data_flag_mask |= - ((node_props->data_mem_seg_mask >> - (CREATEBIT + FLAGBIT)) & 1) << CREATEDATAFLAGBIT; - nldr_node_obj->seg_id[CREATECODEFLAGBIT] = (u16) - (node_props->code_mem_seg_mask >> - CREATEBIT) & SEGMASK; - nldr_node_obj->code_data_flag_mask |= - ((node_props->code_mem_seg_mask >> - (CREATEBIT + FLAGBIT)) & 1) << CREATECODEFLAGBIT; - /* Execute phase */ - nldr_node_obj->seg_id[EXECUTEDATAFLAGBIT] = (u16) - (node_props->data_mem_seg_mask >> - EXECUTEBIT) & SEGMASK; - nldr_node_obj->code_data_flag_mask |= - ((node_props->data_mem_seg_mask >> - (EXECUTEBIT + FLAGBIT)) & 1) << - EXECUTEDATAFLAGBIT; - nldr_node_obj->seg_id[EXECUTECODEFLAGBIT] = (u16) - (node_props->code_mem_seg_mask >> - EXECUTEBIT) & SEGMASK; - nldr_node_obj->code_data_flag_mask |= - ((node_props->code_mem_seg_mask >> - (EXECUTEBIT + FLAGBIT)) & 1) << - EXECUTECODEFLAGBIT; - /* Delete phase */ - nldr_node_obj->seg_id[DELETEDATAFLAGBIT] = (u16) - (node_props->data_mem_seg_mask >> DELETEBIT) & - SEGMASK; - nldr_node_obj->code_data_flag_mask |= - ((node_props->data_mem_seg_mask >> - (DELETEBIT + FLAGBIT)) & 1) << DELETEDATAFLAGBIT; - nldr_node_obj->seg_id[DELETECODEFLAGBIT] = (u16) - (node_props->code_mem_seg_mask >> - DELETEBIT) & SEGMASK; - nldr_node_obj->code_data_flag_mask |= - ((node_props->code_mem_seg_mask >> - (DELETEBIT + FLAGBIT)) & 1) << DELETECODEFLAGBIT; - } else { - /* Non-dynamically loaded nodes are part of the - * base image */ - nldr_node_obj->root.lib = nldr_obj->base_lib; - /* Check for overlay node */ - if (node_props->load_type == NLDR_OVLYLOAD) - nldr_node_obj->overlay = true; - - } - *nldr_nodeobj = (struct nldr_nodeobject *)nldr_node_obj; - } - /* Cleanup on failure */ - if (status && nldr_node_obj) - kfree(nldr_node_obj); - - return status; -} - -/* - * ======== nldr_create ======== - */ -int nldr_create(struct nldr_object **nldr, - struct dev_object *hdev_obj, - const struct nldr_attrs *pattrs) -{ - struct cod_manager *cod_mgr; /* COD manager */ - char *psz_coff_buf = NULL; - char sz_zl_file[COD_MAXPATHLENGTH]; - struct nldr_object *nldr_obj = NULL; - struct dbll_attrs save_attrs; - struct dbll_attrs new_attrs; - dbll_flags flags; - u32 ul_entry; - u16 dload_segs = 0; - struct mem_seg_info *mem_info_obj; - u32 ul_len = 0; - u32 ul_addr; - struct rmm_segment *rmm_segs = NULL; - u16 i; - int status = 0; - - /* Allocate dynamic loader object */ - nldr_obj = kzalloc(sizeof(struct nldr_object), GFP_KERNEL); - if (nldr_obj) { - nldr_obj->dev_obj = hdev_obj; - /* warning, lazy status checking alert! */ - dev_get_cod_mgr(hdev_obj, &cod_mgr); - if (cod_mgr) { - status = cod_get_loader(cod_mgr, &nldr_obj->dbll); - status = cod_get_base_lib(cod_mgr, &nldr_obj->base_lib); - status = - cod_get_base_name(cod_mgr, sz_zl_file, - COD_MAXPATHLENGTH); - } - status = 0; - /* end lazy status checking */ - nldr_obj->dsp_mau_size = pattrs->dsp_mau_size; - nldr_obj->dsp_word_size = pattrs->dsp_word_size; - nldr_obj->ldr_fxns = ldr_fxns; - if (!(nldr_obj->ldr_fxns.init_fxn())) - status = -ENOMEM; - - } else { - status = -ENOMEM; - } - /* Create the DCD Manager */ - if (!status) - status = dcd_create_manager(NULL, &nldr_obj->dcd_mgr); - - /* Get dynamic loading memory sections from base lib */ - if (!status) { - status = - nldr_obj->ldr_fxns.get_sect_fxn(nldr_obj->base_lib, - DYNMEMSECT, &ul_addr, - &ul_len); - if (!status) { - psz_coff_buf = - kzalloc(ul_len * nldr_obj->dsp_mau_size, - GFP_KERNEL); - if (!psz_coff_buf) - status = -ENOMEM; - } else { - /* Ok to not have dynamic loading memory */ - status = 0; - ul_len = 0; - dev_dbg(bridge, "%s: failed - no dynamic loading mem " - "segments: 0x%x\n", __func__, status); - } - } - if (!status && ul_len > 0) { - /* Read section containing dynamic load mem segments */ - status = - nldr_obj->ldr_fxns.read_sect_fxn(nldr_obj->base_lib, - DYNMEMSECT, psz_coff_buf, - ul_len); - } - if (!status && ul_len > 0) { - /* Parse memory segment data */ - dload_segs = (u16) (*((u32 *) psz_coff_buf)); - if (dload_segs > MAXMEMSEGS) - status = -EBADF; - } - /* Parse dynamic load memory segments */ - if (!status && dload_segs > 0) { - rmm_segs = kzalloc(sizeof(struct rmm_segment) * dload_segs, - GFP_KERNEL); - nldr_obj->seg_table = - kzalloc(sizeof(u32) * dload_segs, GFP_KERNEL); - if (rmm_segs == NULL || nldr_obj->seg_table == NULL) { - status = -ENOMEM; - } else { - nldr_obj->dload_segs = dload_segs; - mem_info_obj = (struct mem_seg_info *)(psz_coff_buf + - sizeof(u32)); - for (i = 0; i < dload_segs; i++) { - rmm_segs[i].base = (mem_info_obj + i)->base; - rmm_segs[i].length = (mem_info_obj + i)->len; - rmm_segs[i].space = 0; - nldr_obj->seg_table[i] = - (mem_info_obj + i)->type; - dev_dbg(bridge, - "(proc) DLL MEMSEGMENT: %d, " - "Base: 0x%x, Length: 0x%x\n", i, - rmm_segs[i].base, rmm_segs[i].length); - } - } - } - /* Create Remote memory manager */ - if (!status) - status = rmm_create(&nldr_obj->rmm, rmm_segs, dload_segs); - - if (!status) { - /* set the alloc, free, write functions for loader */ - nldr_obj->ldr_fxns.get_attrs_fxn(nldr_obj->dbll, &save_attrs); - new_attrs = save_attrs; - new_attrs.alloc = (dbll_alloc_fxn) remote_alloc; - new_attrs.free = (dbll_free_fxn) remote_free; - new_attrs.sym_lookup = (dbll_sym_lookup) get_symbol_value; - new_attrs.sym_handle = nldr_obj; - new_attrs.write = (dbll_write_fxn) pattrs->write; - nldr_obj->ovly_fxn = pattrs->ovly; - nldr_obj->write_fxn = pattrs->write; - nldr_obj->ldr_attrs = new_attrs; - } - kfree(rmm_segs); - - kfree(psz_coff_buf); - - /* Get overlay nodes */ - if (!status) { - status = - cod_get_base_name(cod_mgr, sz_zl_file, COD_MAXPATHLENGTH); - /* lazy check */ - /* First count number of overlay nodes */ - status = - dcd_get_objects(nldr_obj->dcd_mgr, sz_zl_file, - add_ovly_node, (void *)nldr_obj); - /* Now build table of overlay nodes */ - if (!status && nldr_obj->ovly_nodes > 0) { - /* Allocate table for overlay nodes */ - nldr_obj->ovly_table = - kzalloc(sizeof(struct ovly_node) * - nldr_obj->ovly_nodes, GFP_KERNEL); - /* Put overlay nodes in the table */ - nldr_obj->ovly_nid = 0; - status = dcd_get_objects(nldr_obj->dcd_mgr, sz_zl_file, - add_ovly_node, - (void *)nldr_obj); - } - } - /* Do a fake reload of the base image to get overlay section info */ - if (!status && nldr_obj->ovly_nodes > 0) { - save_attrs.write = fake_ovly_write; - save_attrs.log_write = add_ovly_info; - save_attrs.log_write_handle = nldr_obj; - flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB; - status = nldr_obj->ldr_fxns.load_fxn(nldr_obj->base_lib, flags, - &save_attrs, &ul_entry); - } - if (!status) { - *nldr = (struct nldr_object *)nldr_obj; - } else { - if (nldr_obj) - nldr_delete((struct nldr_object *)nldr_obj); - - *nldr = NULL; - } - /* FIXME:Temp. Fix. Must be removed */ - return status; -} - -/* - * ======== nldr_delete ======== - */ -void nldr_delete(struct nldr_object *nldr_obj) -{ - struct ovly_sect *ovly_section; - struct ovly_sect *next; - u16 i; - - nldr_obj->ldr_fxns.exit_fxn(); - if (nldr_obj->rmm) - rmm_delete(nldr_obj->rmm); - - kfree(nldr_obj->seg_table); - - if (nldr_obj->dcd_mgr) - dcd_destroy_manager(nldr_obj->dcd_mgr); - - /* Free overlay node information */ - if (nldr_obj->ovly_table) { - for (i = 0; i < nldr_obj->ovly_nodes; i++) { - ovly_section = - nldr_obj->ovly_table[i].create_sects_list; - while (ovly_section) { - next = ovly_section->next_sect; - kfree(ovly_section); - ovly_section = next; - } - ovly_section = - nldr_obj->ovly_table[i].delete_sects_list; - while (ovly_section) { - next = ovly_section->next_sect; - kfree(ovly_section); - ovly_section = next; - } - ovly_section = - nldr_obj->ovly_table[i].execute_sects_list; - while (ovly_section) { - next = ovly_section->next_sect; - kfree(ovly_section); - ovly_section = next; - } - ovly_section = nldr_obj->ovly_table[i].other_sects_list; - while (ovly_section) { - next = ovly_section->next_sect; - kfree(ovly_section); - ovly_section = next; - } - } - kfree(nldr_obj->ovly_table); - } - kfree(nldr_obj); -} - -/* - * ======== nldr_get_fxn_addr ======== - */ -int nldr_get_fxn_addr(struct nldr_nodeobject *nldr_node_obj, - char *str_fxn, u32 *addr) -{ - struct dbll_sym_val *dbll_sym; - struct nldr_object *nldr_obj; - int status = 0; - bool status1 = false; - s32 i = 0; - struct lib_node root = { NULL, 0, NULL }; - - nldr_obj = nldr_node_obj->nldr_obj; - /* Called from node_create(), node_delete(), or node_run(). */ - if (nldr_node_obj->dynamic && *nldr_node_obj->phase_split) { - switch (nldr_node_obj->phase) { - case NLDR_CREATE: - root = nldr_node_obj->create_lib; - break; - case NLDR_EXECUTE: - root = nldr_node_obj->execute_lib; - break; - case NLDR_DELETE: - root = nldr_node_obj->delete_lib; - break; - default: - break; - } - } else { - /* for Overlay nodes or non-split Dynamic nodes */ - root = nldr_node_obj->root; - } - status1 = - nldr_obj->ldr_fxns.get_c_addr_fxn(root.lib, str_fxn, &dbll_sym); - if (!status1) - status1 = - nldr_obj->ldr_fxns.get_addr_fxn(root.lib, str_fxn, - &dbll_sym); - - /* If symbol not found, check dependent libraries */ - if (!status1) { - for (i = 0; i < root.dep_libs; i++) { - status1 = - nldr_obj->ldr_fxns.get_addr_fxn(root.dep_libs_tree - [i].lib, str_fxn, - &dbll_sym); - if (!status1) { - status1 = - nldr_obj->ldr_fxns. - get_c_addr_fxn(root.dep_libs_tree[i].lib, - str_fxn, &dbll_sym); - } - if (status1) { - /* Symbol found */ - break; - } - } - } - /* Check persistent libraries */ - if (!status1) { - for (i = 0; i < nldr_node_obj->pers_libs; i++) { - status1 = - nldr_obj->ldr_fxns. - get_addr_fxn(nldr_node_obj->pers_lib_table[i].lib, - str_fxn, &dbll_sym); - if (!status1) { - status1 = - nldr_obj->ldr_fxns. - get_c_addr_fxn(nldr_node_obj->pers_lib_table - [i].lib, str_fxn, &dbll_sym); - } - if (status1) { - /* Symbol found */ - break; - } - } - } - - if (status1) - *addr = dbll_sym->value; - else - status = -ESPIPE; - - return status; -} - -/* - * ======== nldr_get_rmm_manager ======== - * Given a NLDR object, retrieve RMM Manager Handle - */ -int nldr_get_rmm_manager(struct nldr_object *nldr, - struct rmm_target_obj **rmm_mgr) -{ - int status = 0; - struct nldr_object *nldr_obj = nldr; - - if (nldr) { - *rmm_mgr = nldr_obj->rmm; - } else { - *rmm_mgr = NULL; - status = -EFAULT; - } - - return status; -} - -/* - * ======== nldr_load ======== - */ -int nldr_load(struct nldr_nodeobject *nldr_node_obj, - enum nldr_phase phase) -{ - struct nldr_object *nldr_obj; - struct dsp_uuid lib_uuid; - int status = 0; - - nldr_obj = nldr_node_obj->nldr_obj; - - if (nldr_node_obj->dynamic) { - nldr_node_obj->phase = phase; - - lib_uuid = nldr_node_obj->uuid; - - /* At this point, we may not know if node is split into - * different libraries. So we'll go ahead and load the - * library, and then save the pointer to the appropriate - * location after we know. */ - - status = - load_lib(nldr_node_obj, &nldr_node_obj->root, lib_uuid, - false, nldr_node_obj->lib_path, phase, 0); - - if (!status) { - if (*nldr_node_obj->phase_split) { - switch (phase) { - case NLDR_CREATE: - nldr_node_obj->create_lib = - nldr_node_obj->root; - break; - - case NLDR_EXECUTE: - nldr_node_obj->execute_lib = - nldr_node_obj->root; - break; - - case NLDR_DELETE: - nldr_node_obj->delete_lib = - nldr_node_obj->root; - break; - - default: - break; - } - } - } - } else { - if (nldr_node_obj->overlay) - status = load_ovly(nldr_node_obj, phase); - - } - - return status; -} - -/* - * ======== nldr_unload ======== - */ -int nldr_unload(struct nldr_nodeobject *nldr_node_obj, - enum nldr_phase phase) -{ - int status = 0; - struct lib_node *root_lib = NULL; - s32 i = 0; - - if (nldr_node_obj != NULL) { - if (nldr_node_obj->dynamic) { - if (*nldr_node_obj->phase_split) { - switch (phase) { - case NLDR_CREATE: - root_lib = &nldr_node_obj->create_lib; - break; - case NLDR_EXECUTE: - root_lib = &nldr_node_obj->execute_lib; - break; - case NLDR_DELETE: - root_lib = &nldr_node_obj->delete_lib; - /* Unload persistent libraries */ - for (i = 0; - i < nldr_node_obj->pers_libs; - i++) { - unload_lib(nldr_node_obj, - &nldr_node_obj-> - pers_lib_table[i]); - } - nldr_node_obj->pers_libs = 0; - break; - default: - break; - } - } else { - /* Unload main library */ - root_lib = &nldr_node_obj->root; - } - if (root_lib) - unload_lib(nldr_node_obj, root_lib); - } else { - if (nldr_node_obj->overlay) - unload_ovly(nldr_node_obj, phase); - - } - } - return status; -} - -/* - * ======== add_ovly_info ======== - */ -static int add_ovly_info(void *handle, struct dbll_sect_info *sect_info, - u32 addr, u32 bytes) -{ - char *node_name; - char *sect_name = (char *)sect_info->name; - bool sect_exists = false; - char seps = ':'; - char *pch; - u16 i; - struct nldr_object *nldr_obj = (struct nldr_object *)handle; - int status = 0; - - /* Is this an overlay section (load address != run address)? */ - if (sect_info->sect_load_addr == sect_info->sect_run_addr) - goto func_end; - - /* Find the node it belongs to */ - for (i = 0; i < nldr_obj->ovly_nodes; i++) { - node_name = nldr_obj->ovly_table[i].node_name; - if (strncmp(node_name, sect_name + 1, strlen(node_name)) == 0) { - /* Found the node */ - break; - } - } - if (!(i < nldr_obj->ovly_nodes)) - goto func_end; - - /* Determine which phase this section belongs to */ - for (pch = sect_name + 1; *pch && *pch != seps; pch++) - ; - - if (*pch) { - pch++; /* Skip over the ':' */ - if (strncmp(pch, PCREATE, strlen(PCREATE)) == 0) { - status = - add_ovly_sect(nldr_obj, - &nldr_obj-> - ovly_table[i].create_sects_list, - sect_info, §_exists, addr, bytes); - if (!status && !sect_exists) - nldr_obj->ovly_table[i].create_sects++; - - } else if (strncmp(pch, PDELETE, strlen(PDELETE)) == 0) { - status = - add_ovly_sect(nldr_obj, - &nldr_obj-> - ovly_table[i].delete_sects_list, - sect_info, §_exists, addr, bytes); - if (!status && !sect_exists) - nldr_obj->ovly_table[i].delete_sects++; - - } else if (strncmp(pch, PEXECUTE, strlen(PEXECUTE)) == 0) { - status = - add_ovly_sect(nldr_obj, - &nldr_obj-> - ovly_table[i].execute_sects_list, - sect_info, §_exists, addr, bytes); - if (!status && !sect_exists) - nldr_obj->ovly_table[i].execute_sects++; - - } else { - /* Put in "other" sections */ - status = - add_ovly_sect(nldr_obj, - &nldr_obj-> - ovly_table[i].other_sects_list, - sect_info, §_exists, addr, bytes); - if (!status && !sect_exists) - nldr_obj->ovly_table[i].other_sects++; - - } - } -func_end: - return status; -} - -/* - * ======== add_ovly_node ========= - * Callback function passed to dcd_get_objects. - */ -static int add_ovly_node(struct dsp_uuid *uuid_obj, - enum dsp_dcdobjtype obj_type, void *handle) -{ - struct nldr_object *nldr_obj = (struct nldr_object *)handle; - char *node_name = NULL; - char *pbuf = NULL; - u32 len; - struct dcd_genericobj obj_def; - int status = 0; - - if (obj_type != DSP_DCDNODETYPE) - goto func_end; - - status = - dcd_get_object_def(nldr_obj->dcd_mgr, uuid_obj, obj_type, - &obj_def); - if (status) - goto func_end; - - /* If overlay node, add to the list */ - if (obj_def.obj_data.node_obj.load_type == NLDR_OVLYLOAD) { - if (nldr_obj->ovly_table == NULL) { - nldr_obj->ovly_nodes++; - } else { - /* Add node to table */ - nldr_obj->ovly_table[nldr_obj->ovly_nid].uuid = - *uuid_obj; - len = - strlen(obj_def.obj_data.node_obj.ndb_props.ac_name); - node_name = obj_def.obj_data.node_obj.ndb_props.ac_name; - pbuf = kzalloc(len + 1, GFP_KERNEL); - if (pbuf == NULL) { - status = -ENOMEM; - } else { - strncpy(pbuf, node_name, len); - nldr_obj->ovly_table[nldr_obj->ovly_nid]. - node_name = pbuf; - nldr_obj->ovly_nid++; - } - } - } - /* These were allocated in dcd_get_object_def */ - kfree(obj_def.obj_data.node_obj.str_create_phase_fxn); - - kfree(obj_def.obj_data.node_obj.str_execute_phase_fxn); - - kfree(obj_def.obj_data.node_obj.str_delete_phase_fxn); - - kfree(obj_def.obj_data.node_obj.str_i_alg_name); - -func_end: - return status; -} - -/* - * ======== add_ovly_sect ======== - */ -static int add_ovly_sect(struct nldr_object *nldr_obj, - struct ovly_sect **lst, - struct dbll_sect_info *sect_inf, - bool *exists, u32 addr, u32 bytes) -{ - struct ovly_sect *new_sect = NULL; - struct ovly_sect *last_sect; - struct ovly_sect *ovly_section; - int status = 0; - - ovly_section = last_sect = *lst; - *exists = false; - while (ovly_section) { - /* - * Make sure section has not already been added. Multiple - * 'write' calls may be made to load the section. - */ - if (ovly_section->sect_load_addr == addr) { - /* Already added */ - *exists = true; - break; - } - last_sect = ovly_section; - ovly_section = ovly_section->next_sect; - } - - if (!ovly_section) { - /* New section */ - new_sect = kzalloc(sizeof(struct ovly_sect), GFP_KERNEL); - if (new_sect == NULL) { - status = -ENOMEM; - } else { - new_sect->sect_load_addr = addr; - new_sect->sect_run_addr = sect_inf->sect_run_addr + - (addr - sect_inf->sect_load_addr); - new_sect->size = bytes; - new_sect->page = sect_inf->type; - } - - /* Add to the list */ - if (!status) { - if (*lst == NULL) { - /* First in the list */ - *lst = new_sect; - } else { - last_sect->next_sect = new_sect; - } - } - } - - return status; -} - -/* - * ======== fake_ovly_write ======== - */ -static s32 fake_ovly_write(void *handle, u32 dsp_address, void *buf, u32 bytes, - s32 mtype) -{ - return (s32) bytes; -} - -/* - * ======== free_sects ======== - */ -static void free_sects(struct nldr_object *nldr_obj, - struct ovly_sect *phase_sects, u16 alloc_num) -{ - struct ovly_sect *ovly_section = phase_sects; - u16 i = 0; - bool ret; - - while (ovly_section && i < alloc_num) { - /* 'Deallocate' */ - /* segid - page not supported yet */ - /* Reserved memory */ - ret = - rmm_free(nldr_obj->rmm, 0, ovly_section->sect_run_addr, - ovly_section->size, true); - ovly_section = ovly_section->next_sect; - i++; - } -} - -/* - * ======== get_symbol_value ======== - * Find symbol in library's base image. If not there, check dependent - * libraries. - */ -static bool get_symbol_value(void *handle, void *parg, void *rmm_handle, - char *sym_name, struct dbll_sym_val **sym) -{ - struct nldr_object *nldr_obj = (struct nldr_object *)handle; - struct nldr_nodeobject *nldr_node_obj = - (struct nldr_nodeobject *)rmm_handle; - struct lib_node *root = (struct lib_node *)parg; - u16 i; - bool status = false; - - /* check the base image */ - status = nldr_obj->ldr_fxns.get_addr_fxn(nldr_obj->base_lib, - sym_name, sym); - if (!status) - status = - nldr_obj->ldr_fxns.get_c_addr_fxn(nldr_obj->base_lib, - sym_name, sym); - - /* - * Check in root lib itself. If the library consists of - * multiple object files linked together, some symbols in the - * library may need to be resolved. - */ - if (!status) { - status = nldr_obj->ldr_fxns.get_addr_fxn(root->lib, sym_name, - sym); - if (!status) { - status = - nldr_obj->ldr_fxns.get_c_addr_fxn(root->lib, - sym_name, sym); - } - } - - /* - * Check in root lib's dependent libraries, but not dependent - * libraries' dependents. - */ - if (!status) { - for (i = 0; i < root->dep_libs; i++) { - status = - nldr_obj->ldr_fxns.get_addr_fxn(root-> - dep_libs_tree - [i].lib, - sym_name, sym); - if (!status) { - status = - nldr_obj->ldr_fxns. - get_c_addr_fxn(root->dep_libs_tree[i].lib, - sym_name, sym); - } - if (status) { - /* Symbol found */ - break; - } - } - } - /* - * Check in persistent libraries - */ - if (!status) { - for (i = 0; i < nldr_node_obj->pers_libs; i++) { - status = - nldr_obj->ldr_fxns. - get_addr_fxn(nldr_node_obj->pers_lib_table[i].lib, - sym_name, sym); - if (!status) { - status = nldr_obj->ldr_fxns.get_c_addr_fxn - (nldr_node_obj->pers_lib_table[i].lib, - sym_name, sym); - } - if (status) { - /* Symbol found */ - break; - } - } - } - - return status; -} - -/* - * ======== load_lib ======== - * Recursively load library and all its dependent libraries. The library - * we're loading is specified by a uuid. - */ -static int load_lib(struct nldr_nodeobject *nldr_node_obj, - struct lib_node *root, struct dsp_uuid uuid, - bool root_prstnt, - struct dbll_library_obj **lib_path, - enum nldr_phase phase, u16 depth) -{ - struct nldr_object *nldr_obj = nldr_node_obj->nldr_obj; - u16 nd_libs = 0; /* Number of dependent libraries */ - u16 np_libs = 0; /* Number of persistent libraries */ - u16 nd_libs_loaded = 0; /* Number of dep. libraries loaded */ - u16 i; - u32 entry; - u32 dw_buf_size = NLDR_MAXPATHLENGTH; - dbll_flags flags = DBLL_SYMB | DBLL_CODE | DBLL_DATA | DBLL_DYNAMIC; - struct dbll_attrs new_attrs; - char *psz_file_name = NULL; - struct dsp_uuid *dep_lib_uui_ds = NULL; - bool *persistent_dep_libs = NULL; - int status = 0; - bool lib_status = false; - struct lib_node *dep_lib; - - if (depth > MAXDEPTH) { - /* Error */ - } - root->lib = NULL; - /* Allocate a buffer for library file name of size DBL_MAXPATHLENGTH */ - psz_file_name = kzalloc(DBLL_MAXPATHLENGTH, GFP_KERNEL); - if (psz_file_name == NULL) - status = -ENOMEM; - - if (!status) { - /* Get the name of the library */ - if (depth == 0) { - status = - dcd_get_library_name(nldr_node_obj->nldr_obj-> - dcd_mgr, &uuid, psz_file_name, - &dw_buf_size, phase, - nldr_node_obj->phase_split); - } else { - /* Dependent libraries are registered with a phase */ - status = - dcd_get_library_name(nldr_node_obj->nldr_obj-> - dcd_mgr, &uuid, psz_file_name, - &dw_buf_size, NLDR_NOPHASE, - NULL); - } - } - if (!status) { - /* Open the library, don't load symbols */ - status = - nldr_obj->ldr_fxns.open_fxn(nldr_obj->dbll, psz_file_name, - DBLL_NOLOAD, &root->lib); - } - /* Done with file name */ - kfree(psz_file_name); - - /* Check to see if library not already loaded */ - if (!status && root_prstnt) { - lib_status = - find_in_persistent_lib_array(nldr_node_obj, root->lib); - /* Close library */ - if (lib_status) { - nldr_obj->ldr_fxns.close_fxn(root->lib); - return 0; - } - } - if (!status) { - /* Check for circular dependencies. */ - for (i = 0; i < depth; i++) { - if (root->lib == lib_path[i]) { - /* This condition could be checked by a - * tool at build time. */ - status = -EILSEQ; - } - } - } - if (!status) { - /* Add library to current path in dependency tree */ - lib_path[depth] = root->lib; - depth++; - /* Get number of dependent libraries */ - status = - dcd_get_num_dep_libs(nldr_node_obj->nldr_obj->dcd_mgr, - &uuid, &nd_libs, &np_libs, phase); - } - if (!status) { - if (!(*nldr_node_obj->phase_split)) - np_libs = 0; - - /* nd_libs = #of dependent libraries */ - root->dep_libs = nd_libs - np_libs; - if (nd_libs > 0) { - dep_lib_uui_ds = kzalloc(sizeof(struct dsp_uuid) * - nd_libs, GFP_KERNEL); - persistent_dep_libs = - kzalloc(sizeof(bool) * nd_libs, GFP_KERNEL); - if (!dep_lib_uui_ds || !persistent_dep_libs) - status = -ENOMEM; - - if (root->dep_libs > 0) { - /* Allocate arrays for dependent lib UUIDs, - * lib nodes */ - root->dep_libs_tree = kzalloc - (sizeof(struct lib_node) * - (root->dep_libs), GFP_KERNEL); - if (!(root->dep_libs_tree)) - status = -ENOMEM; - - } - - if (!status) { - /* Get the dependent library UUIDs */ - status = - dcd_get_dep_libs(nldr_node_obj-> - nldr_obj->dcd_mgr, &uuid, - nd_libs, dep_lib_uui_ds, - persistent_dep_libs, - phase); - } - } - } - - /* - * Recursively load dependent libraries. - */ - if (!status) { - for (i = 0; i < nd_libs; i++) { - /* If root library is NOT persistent, and dep library - * is, then record it. If root library IS persistent, - * the deplib is already included */ - if (!root_prstnt && persistent_dep_libs[i] && - *nldr_node_obj->phase_split) { - if ((nldr_node_obj->pers_libs) >= MAXLIBS) { - status = -EILSEQ; - break; - } - - /* Allocate library outside of phase */ - dep_lib = - &nldr_node_obj->pers_lib_table - [nldr_node_obj->pers_libs]; - } else { - if (root_prstnt) - persistent_dep_libs[i] = true; - - /* Allocate library within phase */ - dep_lib = &root->dep_libs_tree[nd_libs_loaded]; - } - - status = load_lib(nldr_node_obj, dep_lib, - dep_lib_uui_ds[i], - persistent_dep_libs[i], lib_path, - phase, depth); - - if (!status) { - if ((status != 0) && - !root_prstnt && persistent_dep_libs[i] && - *nldr_node_obj->phase_split) { - (nldr_node_obj->pers_libs)++; - } else { - if (!persistent_dep_libs[i] || - !(*nldr_node_obj->phase_split)) { - nd_libs_loaded++; - } - } - } else { - break; - } - } - } - - /* Now we can load the root library */ - if (!status) { - new_attrs = nldr_obj->ldr_attrs; - new_attrs.sym_arg = root; - new_attrs.rmm_handle = nldr_node_obj; - new_attrs.input_params = nldr_node_obj->priv_ref; - new_attrs.base_image = false; - - status = - nldr_obj->ldr_fxns.load_fxn(root->lib, flags, &new_attrs, - &entry); - } - - /* - * In case of failure, unload any dependent libraries that - * were loaded, and close the root library. - * (Persistent libraries are unloaded from the very top) - */ - if (status) { - if (phase != NLDR_EXECUTE) { - for (i = 0; i < nldr_node_obj->pers_libs; i++) - unload_lib(nldr_node_obj, - &nldr_node_obj->pers_lib_table[i]); - - nldr_node_obj->pers_libs = 0; - } - for (i = 0; i < nd_libs_loaded; i++) - unload_lib(nldr_node_obj, &root->dep_libs_tree[i]); - - if (root->lib) - nldr_obj->ldr_fxns.close_fxn(root->lib); - - } - - /* Going up one node in the dependency tree */ - depth--; - - kfree(dep_lib_uui_ds); - dep_lib_uui_ds = NULL; - - kfree(persistent_dep_libs); - persistent_dep_libs = NULL; - - return status; -} - -/* - * ======== load_ovly ======== - */ -static int load_ovly(struct nldr_nodeobject *nldr_node_obj, - enum nldr_phase phase) -{ - struct nldr_object *nldr_obj = nldr_node_obj->nldr_obj; - struct ovly_node *po_node = NULL; - struct ovly_sect *phase_sects = NULL; - struct ovly_sect *other_sects_list = NULL; - u16 i; - u16 alloc_num = 0; - u16 other_alloc = 0; - u16 *ref_count = NULL; - u16 *other_ref = NULL; - u32 bytes; - struct ovly_sect *ovly_section; - int status = 0; - - /* Find the node in the table */ - for (i = 0; i < nldr_obj->ovly_nodes; i++) { - if (is_equal_uuid - (&nldr_node_obj->uuid, &nldr_obj->ovly_table[i].uuid)) { - /* Found it */ - po_node = &(nldr_obj->ovly_table[i]); - break; - } - } - - - if (!po_node) { - status = -ENOENT; - goto func_end; - } - - switch (phase) { - case NLDR_CREATE: - ref_count = &(po_node->create_ref); - other_ref = &(po_node->other_ref); - phase_sects = po_node->create_sects_list; - other_sects_list = po_node->other_sects_list; - break; - - case NLDR_EXECUTE: - ref_count = &(po_node->execute_ref); - phase_sects = po_node->execute_sects_list; - break; - - case NLDR_DELETE: - ref_count = &(po_node->delete_ref); - phase_sects = po_node->delete_sects_list; - break; - - default: - break; - } - - if (ref_count == NULL) - goto func_end; - - if (*ref_count != 0) - goto func_end; - - /* 'Allocate' memory for overlay sections of this phase */ - ovly_section = phase_sects; - while (ovly_section) { - /* allocate *//* page not supported yet */ - /* reserve *//* align */ - status = rmm_alloc(nldr_obj->rmm, 0, ovly_section->size, 0, - &(ovly_section->sect_run_addr), true); - if (!status) { - ovly_section = ovly_section->next_sect; - alloc_num++; - } else { - break; - } - } - if (other_ref && *other_ref == 0) { - /* 'Allocate' memory for other overlay sections - * (create phase) */ - if (!status) { - ovly_section = other_sects_list; - while (ovly_section) { - /* page not supported *//* align */ - /* reserve */ - status = - rmm_alloc(nldr_obj->rmm, 0, - ovly_section->size, 0, - &(ovly_section->sect_run_addr), - true); - if (!status) { - ovly_section = ovly_section->next_sect; - other_alloc++; - } else { - break; - } - } - } - } - if (*ref_count == 0) { - if (!status) { - /* Load sections for this phase */ - ovly_section = phase_sects; - while (ovly_section && !status) { - bytes = - (*nldr_obj->ovly_fxn) (nldr_node_obj-> - priv_ref, - ovly_section-> - sect_run_addr, - ovly_section-> - sect_load_addr, - ovly_section->size, - ovly_section->page); - if (bytes != ovly_section->size) - status = -EPERM; - - ovly_section = ovly_section->next_sect; - } - } - } - if (other_ref && *other_ref == 0) { - if (!status) { - /* Load other sections (create phase) */ - ovly_section = other_sects_list; - while (ovly_section && !status) { - bytes = - (*nldr_obj->ovly_fxn) (nldr_node_obj-> - priv_ref, - ovly_section-> - sect_run_addr, - ovly_section-> - sect_load_addr, - ovly_section->size, - ovly_section->page); - if (bytes != ovly_section->size) - status = -EPERM; - - ovly_section = ovly_section->next_sect; - } - } - } - if (status) { - /* 'Deallocate' memory */ - free_sects(nldr_obj, phase_sects, alloc_num); - free_sects(nldr_obj, other_sects_list, other_alloc); - } -func_end: - if (!status && (ref_count != NULL)) { - *ref_count += 1; - if (other_ref) - *other_ref += 1; - - } - - return status; -} - -/* - * ======== remote_alloc ======== - */ -static int remote_alloc(void **ref, u16 mem_sect, u32 size, - u32 align, u32 *dsp_address, - s32 segmnt_id, s32 req, - bool reserve) -{ - struct nldr_nodeobject *hnode = (struct nldr_nodeobject *)ref; - struct nldr_object *nldr_obj; - struct rmm_target_obj *rmm; - u16 mem_phase_bit = MAXFLAGS; - u16 segid = 0; - u16 i; - u16 mem_sect_type; - u32 word_size; - struct rmm_addr *rmm_addr_obj = (struct rmm_addr *)dsp_address; - bool mem_load_req = false; - int status = -ENOMEM; /* Set to fail */ - - nldr_obj = hnode->nldr_obj; - rmm = nldr_obj->rmm; - /* Convert size to DSP words */ - word_size = - (size + nldr_obj->dsp_word_size - - 1) / nldr_obj->dsp_word_size; - /* Modify memory 'align' to account for DSP cache line size */ - align = lcm(GEM_CACHE_LINE_SIZE, align); - dev_dbg(bridge, "%s: memory align to 0x%x\n", __func__, align); - if (segmnt_id != -1) { - rmm_addr_obj->segid = segmnt_id; - segid = segmnt_id; - mem_load_req = req; - } else { - switch (hnode->phase) { - case NLDR_CREATE: - mem_phase_bit = CREATEDATAFLAGBIT; - break; - case NLDR_DELETE: - mem_phase_bit = DELETEDATAFLAGBIT; - break; - case NLDR_EXECUTE: - mem_phase_bit = EXECUTEDATAFLAGBIT; - break; - default: - break; - } - if (mem_sect == DBLL_CODE) - mem_phase_bit++; - - if (mem_phase_bit < MAXFLAGS) - segid = hnode->seg_id[mem_phase_bit]; - - /* Determine if there is a memory loading requirement */ - if ((hnode->code_data_flag_mask >> mem_phase_bit) & 0x1) - mem_load_req = true; - - } - mem_sect_type = (mem_sect == DBLL_CODE) ? DYNM_CODE : DYNM_DATA; - - /* Find an appropriate segment based on mem_sect */ - if (segid == NULLID) { - /* No memory requirements of preferences */ - goto func_cont; - } - if (segid <= MAXSEGID) { - /* Attempt to allocate from segid first. */ - rmm_addr_obj->segid = segid; - status = - rmm_alloc(rmm, segid, word_size, align, dsp_address, false); - if (status) { - dev_dbg(bridge, "%s: Unable allocate from segment %d\n", - __func__, segid); - } - } else { - /* segid > MAXSEGID ==> Internal or external memory */ - /* Check for any internal or external memory segment, - * depending on segid. */ - mem_sect_type |= segid == MEMINTERNALID ? - DYNM_INTERNAL : DYNM_EXTERNAL; - for (i = 0; i < nldr_obj->dload_segs; i++) { - if ((nldr_obj->seg_table[i] & mem_sect_type) != - mem_sect_type) - continue; - - status = rmm_alloc(rmm, i, word_size, align, - dsp_address, false); - if (!status) { - /* Save segid for freeing later */ - rmm_addr_obj->segid = i; - break; - } - } - } -func_cont: - /* Haven't found memory yet, attempt to find any segment that works */ - if (status == -ENOMEM && !mem_load_req) { - dev_dbg(bridge, "%s: Preferred segment unavailable, trying " - "another\n", __func__); - for (i = 0; i < nldr_obj->dload_segs; i++) { - /* All bits of mem_sect_type must be set */ - if ((nldr_obj->seg_table[i] & mem_sect_type) != - mem_sect_type) - continue; - - status = rmm_alloc(rmm, i, word_size, align, - dsp_address, false); - if (!status) { - /* Save segid */ - rmm_addr_obj->segid = i; - break; - } - } - } - - return status; -} - -static int remote_free(void **ref, u16 space, u32 dsp_address, - u32 size, bool reserve) -{ - struct nldr_object *nldr_obj = (struct nldr_object *)ref; - struct rmm_target_obj *rmm; - u32 word_size; - int status = -ENOMEM; /* Set to fail */ - - rmm = nldr_obj->rmm; - - /* Convert size to DSP words */ - word_size = - (size + nldr_obj->dsp_word_size - - 1) / nldr_obj->dsp_word_size; - - if (rmm_free(rmm, space, dsp_address, word_size, reserve)) - status = 0; - - return status; -} - -/* - * ======== unload_lib ======== - */ -static void unload_lib(struct nldr_nodeobject *nldr_node_obj, - struct lib_node *root) -{ - struct dbll_attrs new_attrs; - struct nldr_object *nldr_obj = nldr_node_obj->nldr_obj; - u16 i; - - - /* Unload dependent libraries */ - for (i = 0; i < root->dep_libs; i++) - unload_lib(nldr_node_obj, &root->dep_libs_tree[i]); - - root->dep_libs = 0; - - new_attrs = nldr_obj->ldr_attrs; - new_attrs.rmm_handle = nldr_obj->rmm; - new_attrs.input_params = nldr_node_obj->priv_ref; - new_attrs.base_image = false; - new_attrs.sym_arg = root; - - if (root->lib) { - /* Unload the root library */ - nldr_obj->ldr_fxns.unload_fxn(root->lib, &new_attrs); - nldr_obj->ldr_fxns.close_fxn(root->lib); - } - - /* Free dependent library list */ - kfree(root->dep_libs_tree); - root->dep_libs_tree = NULL; -} - -/* - * ======== unload_ovly ======== - */ -static void unload_ovly(struct nldr_nodeobject *nldr_node_obj, - enum nldr_phase phase) -{ - struct nldr_object *nldr_obj = nldr_node_obj->nldr_obj; - struct ovly_node *po_node = NULL; - struct ovly_sect *phase_sects = NULL; - struct ovly_sect *other_sects_list = NULL; - u16 i; - u16 alloc_num = 0; - u16 other_alloc = 0; - u16 *ref_count = NULL; - u16 *other_ref = NULL; - - /* Find the node in the table */ - for (i = 0; i < nldr_obj->ovly_nodes; i++) { - if (is_equal_uuid - (&nldr_node_obj->uuid, &nldr_obj->ovly_table[i].uuid)) { - /* Found it */ - po_node = &(nldr_obj->ovly_table[i]); - break; - } - } - - - if (!po_node) - /* TODO: Should we print warning here? */ - return; - - switch (phase) { - case NLDR_CREATE: - ref_count = &(po_node->create_ref); - phase_sects = po_node->create_sects_list; - alloc_num = po_node->create_sects; - break; - case NLDR_EXECUTE: - ref_count = &(po_node->execute_ref); - phase_sects = po_node->execute_sects_list; - alloc_num = po_node->execute_sects; - break; - case NLDR_DELETE: - ref_count = &(po_node->delete_ref); - other_ref = &(po_node->other_ref); - phase_sects = po_node->delete_sects_list; - /* 'Other' overlay sections are unloaded in the delete phase */ - other_sects_list = po_node->other_sects_list; - alloc_num = po_node->delete_sects; - other_alloc = po_node->other_sects; - break; - default: - break; - } - if (ref_count && (*ref_count > 0)) { - *ref_count -= 1; - if (other_ref) - *other_ref -= 1; - } - - if (ref_count && *ref_count == 0) { - /* 'Deallocate' memory */ - free_sects(nldr_obj, phase_sects, alloc_num); - } - if (other_ref && *other_ref == 0) - free_sects(nldr_obj, other_sects_list, other_alloc); -} - -/* - * ======== find_in_persistent_lib_array ======== - */ -static bool find_in_persistent_lib_array(struct nldr_nodeobject *nldr_node_obj, - struct dbll_library_obj *lib) -{ - s32 i = 0; - - for (i = 0; i < nldr_node_obj->pers_libs; i++) { - if (lib == nldr_node_obj->pers_lib_table[i].lib) - return true; - - } - - return false; -} - -#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE -/** - * nldr_find_addr() - Find the closest symbol to the given address based on - * dynamic node object. - * - * @nldr_node: Dynamic node object - * @sym_addr: Given address to find the dsp symbol - * @offset_range: offset range to look for dsp symbol - * @offset_output: Symbol Output address - * @sym_name: String with the dsp symbol - * - * This function finds the node library for a given address and - * retrieves the dsp symbol by calling dbll_find_dsp_symbol. - */ -int nldr_find_addr(struct nldr_nodeobject *nldr_node, u32 sym_addr, - u32 offset_range, void *offset_output, char *sym_name) -{ - int status = 0; - bool status1 = false; - s32 i = 0; - struct lib_node root = { NULL, 0, NULL }; - - if (nldr_node->dynamic && *nldr_node->phase_split) { - switch (nldr_node->phase) { - case NLDR_CREATE: - root = nldr_node->create_lib; - break; - case NLDR_EXECUTE: - root = nldr_node->execute_lib; - break; - case NLDR_DELETE: - root = nldr_node->delete_lib; - break; - default: - break; - } - } else { - /* for Overlay nodes or non-split Dynamic nodes */ - root = nldr_node->root; - } - - status1 = dbll_find_dsp_symbol(root.lib, sym_addr, - offset_range, offset_output, sym_name); - - /* If symbol not found, check dependent libraries */ - if (!status1) - for (i = 0; i < root.dep_libs; i++) { - status1 = dbll_find_dsp_symbol( - root.dep_libs_tree[i].lib, sym_addr, - offset_range, offset_output, sym_name); - if (status1) - /* Symbol found */ - break; - } - /* Check persistent libraries */ - if (!status1) - for (i = 0; i < nldr_node->pers_libs; i++) { - status1 = dbll_find_dsp_symbol( - nldr_node->pers_lib_table[i].lib, sym_addr, - offset_range, offset_output, sym_name); - if (status1) - /* Symbol found */ - break; - } - - if (!status1) { - pr_debug("%s: Address 0x%x not found in range %d.\n", - __func__, sym_addr, offset_range); - status = -ESPIPE; - } else { - pr_debug("%s(0x%x, 0x%x, 0x%x, 0x%x, %s)\n", - __func__, (u32) nldr_node, sym_addr, offset_range, - (u32) offset_output, sym_name); - } - - return status; -} -#endif |