summaryrefslogtreecommitdiff
path: root/drivers/staging/tidspbridge/rmgr/nldr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/tidspbridge/rmgr/nldr.c')
-rw-r--r--drivers/staging/tidspbridge/rmgr/nldr.c1860
1 files changed, 0 insertions, 1860 deletions
diff --git a/drivers/staging/tidspbridge/rmgr/nldr.c b/drivers/staging/tidspbridge/rmgr/nldr.c
deleted file mode 100644
index 5ac507ccd19d..000000000000
--- a/drivers/staging/tidspbridge/rmgr/nldr.c
+++ /dev/null
@@ -1,1860 +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, &sect_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, &sect_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, &sect_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, &sect_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