diff options
author | Takashi Iwai | 2014-09-03 16:57:41 +0200 |
---|---|---|
committer | Takashi Iwai | 2014-09-03 16:57:41 +0200 |
commit | 05244d166739ae273fdc7a2151bdef61df49ca7d (patch) | |
tree | 9065482d33f445c90f0b99d29aa51485d1d96488 /drivers/staging/tidspbridge/pmgr/dbll.c | |
parent | ALSA: hda - Fix COEF setups for ALC1150 codec (diff) | |
parent | Merge remote-tracking branches 'asoc/fix/axi', 'asoc/fix/cs4265', 'asoc/fix/d... (diff) | |
download | kernel-qcow2-linux-05244d166739ae273fdc7a2151bdef61df49ca7d.tar.gz kernel-qcow2-linux-05244d166739ae273fdc7a2151bdef61df49ca7d.tar.xz kernel-qcow2-linux-05244d166739ae273fdc7a2151bdef61df49ca7d.zip |
Merge tag 'asoc-v3.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Fixes for v3.17
A few more driver specific fixes on top of the currently pending fixes
(which are already in your tree but not Linus').
Diffstat (limited to 'drivers/staging/tidspbridge/pmgr/dbll.c')
-rw-r--r-- | drivers/staging/tidspbridge/pmgr/dbll.c | 1421 |
1 files changed, 0 insertions, 1421 deletions
diff --git a/drivers/staging/tidspbridge/pmgr/dbll.c b/drivers/staging/tidspbridge/pmgr/dbll.c deleted file mode 100644 index 8e21d1e47c9c..000000000000 --- a/drivers/staging/tidspbridge/pmgr/dbll.c +++ /dev/null @@ -1,1421 +0,0 @@ -/* - * dbll.c - * - * DSP-BIOS Bridge driver support functions for TI OMAP processors. - * - * 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> - -/* ----------------------------------- Host OS */ -#include <dspbridge/host_os.h> - -/* ----------------------------------- DSP/BIOS Bridge */ -#include <dspbridge/dbdefs.h> - -#include <dspbridge/gh.h> - -/* ----------------------------------- OS Adaptation Layer */ - -/* Dynamic loader library interface */ -#include <dspbridge/dynamic_loader.h> -#include <dspbridge/getsection.h> - -/* ----------------------------------- This */ -#include <dspbridge/dbll.h> -#include <dspbridge/rmm.h> - -/* Max buffer length */ -#define MAXEXPR 128 - -#define DOFF_ALIGN(x) (((x) + 3) & ~3UL) - -/* - * ======== struct dbll_tar_obj* ======== - * A target may have one or more libraries of symbols/code/data loaded - * onto it, where a library is simply the symbols/code/data contained - * in a DOFF file. - */ -/* - * ======== dbll_tar_obj ======== - */ -struct dbll_tar_obj { - struct dbll_attrs attrs; - struct dbll_library_obj *head; /* List of all opened libraries */ -}; - -/* - * The following 4 typedefs are "super classes" of the dynamic loader - * library types used in dynamic loader functions (dynamic_loader.h). - */ -/* - * ======== dbll_stream ======== - * Contains dynamic_loader_stream - */ -struct dbll_stream { - struct dynamic_loader_stream dl_stream; - struct dbll_library_obj *lib; -}; - -/* - * ======== ldr_symbol ======== - */ -struct ldr_symbol { - struct dynamic_loader_sym dl_symbol; - struct dbll_library_obj *lib; -}; - -/* - * ======== dbll_alloc ======== - */ -struct dbll_alloc { - struct dynamic_loader_allocate dl_alloc; - struct dbll_library_obj *lib; -}; - -/* - * ======== dbll_init_obj ======== - */ -struct dbll_init_obj { - struct dynamic_loader_initialize dl_init; - struct dbll_library_obj *lib; -}; - -/* - * ======== DBLL_Library ======== - * A library handle is returned by DBLL_Open() and is passed to dbll_load() - * to load symbols/code/data, and to dbll_unload(), to remove the - * symbols/code/data loaded by dbll_load(). - */ - -/* - * ======== dbll_library_obj ======== - */ -struct dbll_library_obj { - struct dbll_library_obj *next; /* Next library in target's list */ - struct dbll_library_obj *prev; /* Previous in the list */ - struct dbll_tar_obj *target_obj; /* target for this library */ - - /* Objects needed by dynamic loader */ - struct dbll_stream stream; - struct ldr_symbol symbol; - struct dbll_alloc allocate; - struct dbll_init_obj init; - void *dload_mod_obj; - - char *file_name; /* COFF file name */ - void *fp; /* Opaque file handle */ - u32 entry; /* Entry point */ - void *desc; /* desc of DOFF file loaded */ - u32 open_ref; /* Number of times opened */ - u32 load_ref; /* Number of times loaded */ - struct gh_t_hash_tab *sym_tab; /* Hash table of symbols */ - u32 pos; -}; - -/* - * ======== dbll_symbol ======== - */ -struct dbll_symbol { - struct dbll_sym_val value; - char *name; -}; - -static void dof_close(struct dbll_library_obj *zl_lib); -static int dof_open(struct dbll_library_obj *zl_lib); -static s32 no_op(struct dynamic_loader_initialize *thisptr, void *bufr, - ldr_addr locn, struct ldr_section_info *info, - unsigned bytsize); - -/* - * Functions called by dynamic loader - * - */ -/* dynamic_loader_stream */ -static int dbll_read_buffer(struct dynamic_loader_stream *this, void *buffer, - unsigned bufsize); -static int dbll_set_file_posn(struct dynamic_loader_stream *this, - unsigned int pos); -/* dynamic_loader_sym */ -static struct dynload_symbol *dbll_find_symbol(struct dynamic_loader_sym *this, - const char *name); -static struct dynload_symbol *dbll_add_to_symbol_table(struct dynamic_loader_sym - *this, const char *name, - unsigned module_id); -static struct dynload_symbol *find_in_symbol_table(struct dynamic_loader_sym - *this, const char *name, - unsigned moduleid); -static void dbll_purge_symbol_table(struct dynamic_loader_sym *this, - unsigned module_id); -static void *allocate(struct dynamic_loader_sym *this, unsigned memsize); -static void deallocate(struct dynamic_loader_sym *this, void *mem_ptr); -static void dbll_err_report(struct dynamic_loader_sym *this, const char *errstr, - va_list args); -/* dynamic_loader_allocate */ -static int dbll_rmm_alloc(struct dynamic_loader_allocate *this, - struct ldr_section_info *info, unsigned align); -static void rmm_dealloc(struct dynamic_loader_allocate *this, - struct ldr_section_info *info); - -/* dynamic_loader_initialize */ -static int connect(struct dynamic_loader_initialize *this); -static int read_mem(struct dynamic_loader_initialize *this, void *buf, - ldr_addr addr, struct ldr_section_info *info, - unsigned bytes); -static int write_mem(struct dynamic_loader_initialize *this, void *buf, - ldr_addr addr, struct ldr_section_info *info, - unsigned nbytes); -static int fill_mem(struct dynamic_loader_initialize *this, ldr_addr addr, - struct ldr_section_info *info, unsigned bytes, - unsigned val); -static int execute(struct dynamic_loader_initialize *this, ldr_addr start); -static void release(struct dynamic_loader_initialize *this); - -/* symbol table hash functions */ -static u32 name_hash(const void *key); -static bool name_match(const void *key, const void *sp); -static void sym_delete(void *value); - -/* Symbol Redefinition */ -static int redefined_symbol; -static int gbl_search = 1; - -/* - * ======== dbll_close ======== - */ -void dbll_close(struct dbll_library_obj *zl_lib) -{ - struct dbll_tar_obj *zl_target; - - zl_target = zl_lib->target_obj; - zl_lib->open_ref--; - if (zl_lib->open_ref == 0) { - /* Remove library from list */ - if (zl_target->head == zl_lib) - zl_target->head = zl_lib->next; - - if (zl_lib->prev) - (zl_lib->prev)->next = zl_lib->next; - - if (zl_lib->next) - (zl_lib->next)->prev = zl_lib->prev; - - /* Free DOF resources */ - dof_close(zl_lib); - kfree(zl_lib->file_name); - - /* remove symbols from symbol table */ - if (zl_lib->sym_tab) - gh_delete(zl_lib->sym_tab); - - /* remove the library object itself */ - kfree(zl_lib); - zl_lib = NULL; - } -} - -/* - * ======== dbll_create ======== - */ -int dbll_create(struct dbll_tar_obj **target_obj, - struct dbll_attrs *pattrs) -{ - struct dbll_tar_obj *pzl_target; - int status = 0; - - /* Allocate DBL target object */ - pzl_target = kzalloc(sizeof(struct dbll_tar_obj), GFP_KERNEL); - if (target_obj != NULL) { - if (pzl_target == NULL) { - *target_obj = NULL; - status = -ENOMEM; - } else { - pzl_target->attrs = *pattrs; - *target_obj = (struct dbll_tar_obj *)pzl_target; - } - } - - return status; -} - -/* - * ======== dbll_delete ======== - */ -void dbll_delete(struct dbll_tar_obj *target) -{ - struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target; - - kfree(zl_target); - -} - -/* - * ======== dbll_exit ======== - * Discontinue usage of DBL module. - */ -void dbll_exit(void) -{ - /* do nothing */ -} - -/* - * ======== dbll_get_addr ======== - * Get address of name in the specified library. - */ -bool dbll_get_addr(struct dbll_library_obj *zl_lib, char *name, - struct dbll_sym_val **sym_val) -{ - struct dbll_symbol *sym; - - sym = (struct dbll_symbol *)gh_find(zl_lib->sym_tab, name); - if (IS_ERR(sym)) - return false; - - *sym_val = &sym->value; - - dev_dbg(bridge, "%s: lib: %p name: %s paddr: %p\n", - __func__, zl_lib, name, sym_val); - return true; -} - -/* - * ======== dbll_get_attrs ======== - * Retrieve the attributes of the target. - */ -void dbll_get_attrs(struct dbll_tar_obj *target, struct dbll_attrs *pattrs) -{ - struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target; - - if ((pattrs != NULL) && (zl_target != NULL)) - *pattrs = zl_target->attrs; - -} - -/* - * ======== dbll_get_c_addr ======== - * Get address of a "C" name in the specified library. - */ -bool dbll_get_c_addr(struct dbll_library_obj *zl_lib, char *name, - struct dbll_sym_val **sym_val) -{ - struct dbll_symbol *sym; - char cname[MAXEXPR + 1]; - - cname[0] = '_'; - - strncpy(cname + 1, name, sizeof(cname) - 2); - cname[MAXEXPR] = '\0'; /* insure '\0' string termination */ - - /* Check for C name, if not found */ - sym = (struct dbll_symbol *)gh_find(zl_lib->sym_tab, cname); - if (IS_ERR(sym)) - return false; - - *sym_val = &sym->value; - - return true; -} - -/* - * ======== dbll_get_sect ======== - * Get the base address and size (in bytes) of a COFF section. - */ -int dbll_get_sect(struct dbll_library_obj *lib, char *name, u32 *paddr, - u32 *psize) -{ - u32 byte_size; - bool opened_doff = false; - const struct ldr_section_info *sect = NULL; - struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib; - int status = 0; - - /* If DOFF file is not open, we open it. */ - if (zl_lib != NULL) { - if (zl_lib->fp == NULL) { - status = dof_open(zl_lib); - if (!status) - opened_doff = true; - - } else { - (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, - zl_lib->pos, - SEEK_SET); - } - } else { - status = -EFAULT; - } - if (!status) { - byte_size = 1; - if (dload_get_section_info(zl_lib->desc, name, §)) { - *paddr = sect->load_addr; - *psize = sect->size * byte_size; - /* Make sure size is even for good swap */ - if (*psize % 2) - (*psize)++; - - /* Align size */ - *psize = DOFF_ALIGN(*psize); - } else { - status = -ENXIO; - } - } - if (opened_doff) { - dof_close(zl_lib); - opened_doff = false; - } - - dev_dbg(bridge, "%s: lib: %p name: %s paddr: %p psize: %p, status 0x%x\n", - __func__, lib, name, paddr, psize, status); - - return status; -} - -/* - * ======== dbll_init ======== - */ -bool dbll_init(void) -{ - /* do nothing */ - - return true; -} - -/* - * ======== dbll_load ======== - */ -int dbll_load(struct dbll_library_obj *lib, dbll_flags flags, - struct dbll_attrs *attrs, u32 *entry) -{ - struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib; - struct dbll_tar_obj *dbzl; - bool got_symbols = true; - s32 err; - int status = 0; - bool opened_doff = false; - - /* - * Load if not already loaded. - */ - if (zl_lib->load_ref == 0 || !(flags & DBLL_DYNAMIC)) { - dbzl = zl_lib->target_obj; - dbzl->attrs = *attrs; - /* Create a hash table for symbols if not already created */ - if (zl_lib->sym_tab == NULL) { - got_symbols = false; - zl_lib->sym_tab = gh_create(sizeof(struct dbll_symbol), - name_hash, - name_match, sym_delete); - if (IS_ERR(zl_lib->sym_tab)) { - status = PTR_ERR(zl_lib->sym_tab); - zl_lib->sym_tab = NULL; - } - - } - /* - * Set up objects needed by the dynamic loader - */ - /* Stream */ - zl_lib->stream.dl_stream.read_buffer = dbll_read_buffer; - zl_lib->stream.dl_stream.set_file_posn = dbll_set_file_posn; - zl_lib->stream.lib = zl_lib; - /* Symbol */ - zl_lib->symbol.dl_symbol.find_matching_symbol = - dbll_find_symbol; - if (got_symbols) { - zl_lib->symbol.dl_symbol.add_to_symbol_table = - find_in_symbol_table; - } else { - zl_lib->symbol.dl_symbol.add_to_symbol_table = - dbll_add_to_symbol_table; - } - zl_lib->symbol.dl_symbol.purge_symbol_table = - dbll_purge_symbol_table; - zl_lib->symbol.dl_symbol.dload_allocate = allocate; - zl_lib->symbol.dl_symbol.dload_deallocate = deallocate; - zl_lib->symbol.dl_symbol.error_report = dbll_err_report; - zl_lib->symbol.lib = zl_lib; - /* Allocate */ - zl_lib->allocate.dl_alloc.dload_allocate = dbll_rmm_alloc; - zl_lib->allocate.dl_alloc.dload_deallocate = rmm_dealloc; - zl_lib->allocate.lib = zl_lib; - /* Init */ - zl_lib->init.dl_init.connect = connect; - zl_lib->init.dl_init.readmem = read_mem; - zl_lib->init.dl_init.writemem = write_mem; - zl_lib->init.dl_init.fillmem = fill_mem; - zl_lib->init.dl_init.execute = execute; - zl_lib->init.dl_init.release = release; - zl_lib->init.lib = zl_lib; - /* If COFF file is not open, we open it. */ - if (zl_lib->fp == NULL) { - status = dof_open(zl_lib); - if (!status) - opened_doff = true; - - } - if (!status) { - zl_lib->pos = (*(zl_lib->target_obj->attrs.ftell)) - (zl_lib->fp); - /* Reset file cursor */ - (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, - (long)0, - SEEK_SET); - symbols_reloaded = true; - /* The 5th argument, DLOAD_INITBSS, tells the DLL - * module to zero-init all BSS sections. In general, - * this is not necessary and also increases load time. - * We may want to make this configurable by the user */ - err = dynamic_load_module(&zl_lib->stream.dl_stream, - &zl_lib->symbol.dl_symbol, - &zl_lib->allocate.dl_alloc, - &zl_lib->init.dl_init, - DLOAD_INITBSS, - &zl_lib->dload_mod_obj); - - if (err != 0) { - status = -EILSEQ; - } else if (redefined_symbol) { - zl_lib->load_ref++; - dbll_unload(zl_lib, (struct dbll_attrs *)attrs); - redefined_symbol = false; - status = -EILSEQ; - } else { - *entry = zl_lib->entry; - } - } - } - if (!status) - zl_lib->load_ref++; - - /* Clean up DOFF resources */ - if (opened_doff) - dof_close(zl_lib); - - dev_dbg(bridge, "%s: lib: %p flags: 0x%x entry: %p, status 0x%x\n", - __func__, lib, flags, entry, status); - - return status; -} - -/* - * ======== dbll_open ======== - */ -int dbll_open(struct dbll_tar_obj *target, char *file, dbll_flags flags, - struct dbll_library_obj **lib_obj) -{ - struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target; - struct dbll_library_obj *zl_lib = NULL; - s32 err; - int status = 0; - - zl_lib = zl_target->head; - while (zl_lib != NULL) { - if (strcmp(zl_lib->file_name, file) == 0) { - /* Library is already opened */ - zl_lib->open_ref++; - break; - } - zl_lib = zl_lib->next; - } - if (zl_lib == NULL) { - /* Allocate DBL library object */ - zl_lib = kzalloc(sizeof(struct dbll_library_obj), GFP_KERNEL); - if (zl_lib == NULL) { - status = -ENOMEM; - } else { - zl_lib->pos = 0; - /* Increment ref count to allow close on failure - * later on */ - zl_lib->open_ref++; - zl_lib->target_obj = zl_target; - /* Keep a copy of the file name */ - zl_lib->file_name = kzalloc(strlen(file) + 1, - GFP_KERNEL); - if (zl_lib->file_name == NULL) { - status = -ENOMEM; - } else { - strncpy(zl_lib->file_name, file, - strlen(file) + 1); - } - zl_lib->sym_tab = NULL; - } - } - /* - * Set up objects needed by the dynamic loader - */ - if (status) - goto func_cont; - - /* Stream */ - zl_lib->stream.dl_stream.read_buffer = dbll_read_buffer; - zl_lib->stream.dl_stream.set_file_posn = dbll_set_file_posn; - zl_lib->stream.lib = zl_lib; - /* Symbol */ - zl_lib->symbol.dl_symbol.add_to_symbol_table = dbll_add_to_symbol_table; - zl_lib->symbol.dl_symbol.find_matching_symbol = dbll_find_symbol; - zl_lib->symbol.dl_symbol.purge_symbol_table = dbll_purge_symbol_table; - zl_lib->symbol.dl_symbol.dload_allocate = allocate; - zl_lib->symbol.dl_symbol.dload_deallocate = deallocate; - zl_lib->symbol.dl_symbol.error_report = dbll_err_report; - zl_lib->symbol.lib = zl_lib; - /* Allocate */ - zl_lib->allocate.dl_alloc.dload_allocate = dbll_rmm_alloc; - zl_lib->allocate.dl_alloc.dload_deallocate = rmm_dealloc; - zl_lib->allocate.lib = zl_lib; - /* Init */ - zl_lib->init.dl_init.connect = connect; - zl_lib->init.dl_init.readmem = read_mem; - zl_lib->init.dl_init.writemem = write_mem; - zl_lib->init.dl_init.fillmem = fill_mem; - zl_lib->init.dl_init.execute = execute; - zl_lib->init.dl_init.release = release; - zl_lib->init.lib = zl_lib; - if (!status && zl_lib->fp == NULL) - status = dof_open(zl_lib); - - zl_lib->pos = (*(zl_lib->target_obj->attrs.ftell)) (zl_lib->fp); - (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, (long)0, SEEK_SET); - /* Create a hash table for symbols if flag is set */ - if (zl_lib->sym_tab != NULL || !(flags & DBLL_SYMB)) - goto func_cont; - - zl_lib->sym_tab = - gh_create(sizeof(struct dbll_symbol), name_hash, name_match, - sym_delete); - if (IS_ERR(zl_lib->sym_tab)) { - status = PTR_ERR(zl_lib->sym_tab); - zl_lib->sym_tab = NULL; - } else { - /* Do a fake load to get symbols - set write func to no_op */ - zl_lib->init.dl_init.writemem = no_op; - err = dynamic_open_module(&zl_lib->stream.dl_stream, - &zl_lib->symbol.dl_symbol, - &zl_lib->allocate.dl_alloc, - &zl_lib->init.dl_init, 0, - &zl_lib->dload_mod_obj); - if (err != 0) { - status = -EILSEQ; - } else { - /* Now that we have the symbol table, we can unload */ - err = dynamic_unload_module(zl_lib->dload_mod_obj, - &zl_lib->symbol.dl_symbol, - &zl_lib->allocate.dl_alloc, - &zl_lib->init.dl_init); - if (err != 0) - status = -EILSEQ; - - zl_lib->dload_mod_obj = NULL; - } - } -func_cont: - if (!status) { - if (zl_lib->open_ref == 1) { - /* First time opened - insert in list */ - if (zl_target->head) - (zl_target->head)->prev = zl_lib; - - zl_lib->prev = NULL; - zl_lib->next = zl_target->head; - zl_target->head = zl_lib; - } - *lib_obj = (struct dbll_library_obj *)zl_lib; - } else { - *lib_obj = NULL; - if (zl_lib != NULL) - dbll_close((struct dbll_library_obj *)zl_lib); - - } - - dev_dbg(bridge, "%s: target: %p file: %s lib_obj: %p, status 0x%x\n", - __func__, target, file, lib_obj, status); - - return status; -} - -/* - * ======== dbll_read_sect ======== - * Get the content of a COFF section. - */ -int dbll_read_sect(struct dbll_library_obj *lib, char *name, - char *buf, u32 size) -{ - struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib; - bool opened_doff = false; - u32 byte_size; /* size of bytes */ - u32 ul_sect_size; /* size of section */ - const struct ldr_section_info *sect = NULL; - int status = 0; - - /* If DOFF file is not open, we open it. */ - if (zl_lib != NULL) { - if (zl_lib->fp == NULL) { - status = dof_open(zl_lib); - if (!status) - opened_doff = true; - - } else { - (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, - zl_lib->pos, - SEEK_SET); - } - } else { - status = -EFAULT; - } - if (status) - goto func_cont; - - byte_size = 1; - if (!dload_get_section_info(zl_lib->desc, name, §)) { - status = -ENXIO; - goto func_cont; - } - /* - * Ensure the supplied buffer size is sufficient to store - * the section buf to be read. - */ - ul_sect_size = sect->size * byte_size; - /* Make sure size is even for good swap */ - if (ul_sect_size % 2) - ul_sect_size++; - - /* Align size */ - ul_sect_size = DOFF_ALIGN(ul_sect_size); - if (ul_sect_size > size) { - status = -EPERM; - } else { - if (!dload_get_section(zl_lib->desc, sect, buf)) - status = -EBADF; - - } -func_cont: - if (opened_doff) { - dof_close(zl_lib); - opened_doff = false; - } - - dev_dbg(bridge, "%s: lib: %p name: %s buf: %p size: 0x%x, status 0x%x\n", - __func__, lib, name, buf, size, status); - return status; -} - -/* - * ======== dbll_unload ======== - */ -void dbll_unload(struct dbll_library_obj *lib, struct dbll_attrs *attrs) -{ - struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib; - s32 err = 0; - - dev_dbg(bridge, "%s: lib: %p\n", __func__, lib); - zl_lib->load_ref--; - /* Unload only if reference count is 0 */ - if (zl_lib->load_ref != 0) - return; - - zl_lib->target_obj->attrs = *attrs; - if (zl_lib->dload_mod_obj) { - err = dynamic_unload_module(zl_lib->dload_mod_obj, - &zl_lib->symbol.dl_symbol, - &zl_lib->allocate.dl_alloc, - &zl_lib->init.dl_init); - if (err != 0) - dev_dbg(bridge, "%s: failed: 0x%x\n", __func__, err); - } - /* remove symbols from symbol table */ - if (zl_lib->sym_tab != NULL) { - gh_delete(zl_lib->sym_tab); - zl_lib->sym_tab = NULL; - } - /* delete DOFF desc since it holds *lots* of host OS - * resources */ - dof_close(zl_lib); -} - -/* - * ======== dof_close ======== - */ -static void dof_close(struct dbll_library_obj *zl_lib) -{ - if (zl_lib->desc) { - dload_module_close(zl_lib->desc); - zl_lib->desc = NULL; - } - /* close file */ - if (zl_lib->fp) { - (zl_lib->target_obj->attrs.fclose) (zl_lib->fp); - zl_lib->fp = NULL; - } -} - -/* - * ======== dof_open ======== - */ -static int dof_open(struct dbll_library_obj *zl_lib) -{ - void *open = *(zl_lib->target_obj->attrs.fopen); - int status = 0; - - /* First open the file for the dynamic loader, then open COF */ - zl_lib->fp = - (void *)((dbll_f_open_fxn) (open)) (zl_lib->file_name, "rb"); - - /* Open DOFF module */ - if (zl_lib->fp && zl_lib->desc == NULL) { - (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, (long)0, - SEEK_SET); - zl_lib->desc = - dload_module_open(&zl_lib->stream.dl_stream, - &zl_lib->symbol.dl_symbol); - if (zl_lib->desc == NULL) { - (zl_lib->target_obj->attrs.fclose) (zl_lib->fp); - zl_lib->fp = NULL; - status = -EBADF; - } - } else { - status = -EBADF; - } - - return status; -} - -/* - * ======== name_hash ======== - */ -static u32 name_hash(const void *key) -{ - u32 hash; - const char *name = key; - - hash = 0; - - while (*name) { - hash <<= 1; - hash ^= *name++; - } - - return hash; -} - -/* - * ======== name_match ======== - */ -static bool name_match(const void *key, const void *sp) -{ - if ((key != NULL) && (sp != NULL)) { - if (strcmp(key, ((struct dbll_symbol *)sp)->name) == 0) - return true; - } - return false; -} - -/* - * ======== no_op ======== - */ -static int no_op(struct dynamic_loader_initialize *thisptr, void *bufr, - ldr_addr locn, struct ldr_section_info *info, unsigned bytsize) -{ - return 1; -} - -/* - * ======== sym_delete ======== - */ -static void sym_delete(void *value) -{ - struct dbll_symbol *sp = (struct dbll_symbol *)value; - - kfree(sp->name); -} - -/* - * Dynamic Loader Functions - */ - -/* dynamic_loader_stream */ -/* - * ======== dbll_read_buffer ======== - */ -static int dbll_read_buffer(struct dynamic_loader_stream *this, void *buffer, - unsigned bufsize) -{ - struct dbll_stream *pstream = (struct dbll_stream *)this; - struct dbll_library_obj *lib; - int bytes_read = 0; - - lib = pstream->lib; - if (lib != NULL) { - bytes_read = - (*(lib->target_obj->attrs.fread)) (buffer, 1, bufsize, - lib->fp); - } - return bytes_read; -} - -/* - * ======== dbll_set_file_posn ======== - */ -static int dbll_set_file_posn(struct dynamic_loader_stream *this, - unsigned int pos) -{ - struct dbll_stream *pstream = (struct dbll_stream *)this; - struct dbll_library_obj *lib; - int status = 0; /* Success */ - - lib = pstream->lib; - if (lib != NULL) { - status = (*(lib->target_obj->attrs.fseek)) (lib->fp, (long)pos, - SEEK_SET); - } - - return status; -} - -/* dynamic_loader_sym */ - -/* - * ======== dbll_find_symbol ======== - */ -static struct dynload_symbol *dbll_find_symbol(struct dynamic_loader_sym *this, - const char *name) -{ - struct dynload_symbol *ret_sym; - struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; - struct dbll_library_obj *lib; - struct dbll_sym_val *dbll_sym = NULL; - bool status = false; /* Symbol not found yet */ - - lib = ldr_sym->lib; - if (lib != NULL) { - if (lib->target_obj->attrs.sym_lookup) { - /* Check current lib + base lib + dep lib + - * persistent lib */ - status = (*(lib->target_obj->attrs.sym_lookup)) - (lib->target_obj->attrs.sym_handle, - lib->target_obj->attrs.sym_arg, - lib->target_obj->attrs.rmm_handle, name, - &dbll_sym); - } else { - /* Just check current lib for symbol */ - status = dbll_get_addr((struct dbll_library_obj *)lib, - (char *)name, &dbll_sym); - if (!status) { - status = dbll_get_c_addr( - (struct dbll_library_obj *) - lib, (char *)name, - &dbll_sym); - } - } - } - - if (!status && gbl_search) - dev_dbg(bridge, "%s: Symbol not found: %s\n", __func__, name); - - ret_sym = (struct dynload_symbol *)dbll_sym; - return ret_sym; -} - -/* - * ======== find_in_symbol_table ======== - */ -static struct dynload_symbol *find_in_symbol_table(struct dynamic_loader_sym - *this, const char *name, - unsigned moduleid) -{ - struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; - struct dbll_library_obj *lib; - struct dbll_symbol *sym; - - lib = ldr_sym->lib; - sym = (struct dbll_symbol *)gh_find(lib->sym_tab, (char *)name); - - if (IS_ERR(sym)) - return NULL; - - return (struct dynload_symbol *)&sym->value; -} - -/* - * ======== dbll_add_to_symbol_table ======== - */ -static struct dynload_symbol *dbll_add_to_symbol_table(struct dynamic_loader_sym - *this, const char *name, - unsigned module_id) -{ - struct dbll_symbol *sym_ptr = NULL; - struct dbll_symbol symbol; - struct dynload_symbol *dbll_sym = NULL; - struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; - struct dbll_library_obj *lib; - struct dynload_symbol *ret; - - lib = ldr_sym->lib; - - /* Check to see if symbol is already defined in symbol table */ - if (!(lib->target_obj->attrs.base_image)) { - gbl_search = false; - dbll_sym = dbll_find_symbol(this, name); - gbl_search = true; - if (dbll_sym) { - redefined_symbol = true; - dev_dbg(bridge, "%s already defined in symbol table\n", - name); - return NULL; - } - } - /* Allocate string to copy symbol name */ - symbol.name = kzalloc(strlen((char *const)name) + 1, GFP_KERNEL); - if (symbol.name == NULL) - return NULL; - - if (symbol.name != NULL) { - /* Just copy name (value will be filled in by dynamic loader) */ - strncpy(symbol.name, (char *const)name, - strlen((char *const)name) + 1); - - /* Add symbol to symbol table */ - sym_ptr = - (struct dbll_symbol *)gh_insert(lib->sym_tab, (void *)name, - (void *)&symbol); - if (IS_ERR(sym_ptr)) { - kfree(symbol.name); - sym_ptr = NULL; - } - - } - if (sym_ptr != NULL) - ret = (struct dynload_symbol *)&sym_ptr->value; - else - ret = NULL; - - return ret; -} - -/* - * ======== dbll_purge_symbol_table ======== - */ -static void dbll_purge_symbol_table(struct dynamic_loader_sym *this, - unsigned module_id) -{ - struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; - struct dbll_library_obj *lib; - - lib = ldr_sym->lib; - /* May not need to do anything */ -} - -/* - * ======== allocate ======== - */ -static void *allocate(struct dynamic_loader_sym *this, unsigned memsize) -{ - struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; - struct dbll_library_obj *lib; - void *buf; - - lib = ldr_sym->lib; - - buf = kzalloc(memsize, GFP_KERNEL); - - return buf; -} - -/* - * ======== deallocate ======== - */ -static void deallocate(struct dynamic_loader_sym *this, void *mem_ptr) -{ - struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; - struct dbll_library_obj *lib; - - lib = ldr_sym->lib; - - kfree(mem_ptr); -} - -/* - * ======== dbll_err_report ======== - */ -static void dbll_err_report(struct dynamic_loader_sym *this, const char *errstr, - va_list args) -{ - struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; - struct dbll_library_obj *lib; - char temp_buf[MAXEXPR]; - - lib = ldr_sym->lib; - vsnprintf((char *)temp_buf, MAXEXPR, (char *)errstr, args); - dev_dbg(bridge, "%s\n", temp_buf); -} - -/* dynamic_loader_allocate */ - -/* - * ======== dbll_rmm_alloc ======== - */ -static int dbll_rmm_alloc(struct dynamic_loader_allocate *this, - struct ldr_section_info *info, unsigned align) -{ - struct dbll_alloc *dbll_alloc_obj = (struct dbll_alloc *)this; - struct dbll_library_obj *lib; - int status = 0; - u32 mem_sect_type; - struct rmm_addr rmm_addr_obj; - s32 ret = true; - unsigned stype = DLOAD_SECTION_TYPE(info->type); - char *token = NULL; - char *sz_sec_last_token = NULL; - char *sz_last_token = NULL; - char *sz_sect_name = NULL; - char *psz_cur; - s32 token_len = 0; - s32 seg_id = -1; - s32 req = -1; - s32 count = 0; - u32 alloc_size = 0; - u32 run_addr_flag = 0; - - lib = dbll_alloc_obj->lib; - - mem_sect_type = - (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == - DLOAD_BSS) ? DBLL_BSS : - DBLL_DATA; - - /* Attempt to extract the segment ID and requirement information from - the name of the section */ - token_len = strlen((char *)(info->name)) + 1; - - sz_sect_name = kzalloc(token_len, GFP_KERNEL); - sz_last_token = kzalloc(token_len, GFP_KERNEL); - sz_sec_last_token = kzalloc(token_len, GFP_KERNEL); - - if (sz_sect_name == NULL || sz_sec_last_token == NULL || - sz_last_token == NULL) { - status = -ENOMEM; - goto func_cont; - } - strncpy(sz_sect_name, (char *)(info->name), token_len); - psz_cur = sz_sect_name; - while ((token = strsep(&psz_cur, ":")) && *token != '\0') { - strncpy(sz_sec_last_token, sz_last_token, - strlen(sz_last_token) + 1); - strncpy(sz_last_token, token, strlen(token) + 1); - token = strsep(&psz_cur, ":"); - count++; /* optimizes processing */ - } - /* If token is 0 or 1, and sz_sec_last_token is DYN_DARAM or DYN_SARAM, - or DYN_EXTERNAL, then mem granularity information is present - within the section name - only process if there are at least three - tokens within the section name (just a minor optimization) */ - if (count >= 3) { - status = kstrtos32(sz_last_token, 10, &req); - if (status) - goto func_cont; - } - - if ((req == 0) || (req == 1)) { - if (strcmp(sz_sec_last_token, "DYN_DARAM") == 0) { - seg_id = 0; - } else { - if (strcmp(sz_sec_last_token, "DYN_SARAM") == 0) { - seg_id = 1; - } else { - if (strcmp(sz_sec_last_token, - "DYN_EXTERNAL") == 0) - seg_id = 2; - } - } - } -func_cont: - kfree(sz_sect_name); - sz_sect_name = NULL; - kfree(sz_last_token); - sz_last_token = NULL; - kfree(sz_sec_last_token); - sz_sec_last_token = NULL; - - if (mem_sect_type == DBLL_CODE) - alloc_size = info->size + GEM_L1P_PREFETCH_SIZE; - else - alloc_size = info->size; - - if (info->load_addr != info->run_addr) - run_addr_flag = 1; - /* TODO - ideally, we can pass the alignment requirement also - * from here */ - if (lib != NULL) { - status = - (lib->target_obj->attrs.alloc) (lib->target_obj->attrs. - rmm_handle, mem_sect_type, - alloc_size, align, - (u32 *) &rmm_addr_obj, - seg_id, req, false); - } - if (status) { - ret = false; - } else { - /* RMM gives word address. Need to convert to byte address */ - info->load_addr = rmm_addr_obj.addr * DSPWORDSIZE; - if (!run_addr_flag) - info->run_addr = info->load_addr; - info->context = (u32) rmm_addr_obj.segid; - dev_dbg(bridge, "%s: %s base = 0x%x len = 0x%x, info->run_addr 0x%x, info->load_addr 0x%x\n", - __func__, info->name, info->load_addr / DSPWORDSIZE, - info->size / DSPWORDSIZE, info->run_addr, - info->load_addr); - } - return ret; -} - -/* - * ======== rmm_dealloc ======== - */ -static void rmm_dealloc(struct dynamic_loader_allocate *this, - struct ldr_section_info *info) -{ - struct dbll_alloc *dbll_alloc_obj = (struct dbll_alloc *)this; - struct dbll_library_obj *lib; - u32 segid; - int status = 0; - unsigned stype = DLOAD_SECTION_TYPE(info->type); - u32 mem_sect_type; - u32 free_size = 0; - - mem_sect_type = - (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == - DLOAD_BSS) ? DBLL_BSS : - DBLL_DATA; - lib = dbll_alloc_obj->lib; - /* segid was set by alloc function */ - segid = (u32) info->context; - if (mem_sect_type == DBLL_CODE) - free_size = info->size + GEM_L1P_PREFETCH_SIZE; - else - free_size = info->size; - if (lib != NULL) { - status = - (lib->target_obj->attrs.free) (lib->target_obj->attrs. - sym_handle, segid, - info->load_addr / - DSPWORDSIZE, free_size, - false); - } -} - -/* dynamic_loader_initialize */ -/* - * ======== connect ======== - */ -static int connect(struct dynamic_loader_initialize *this) -{ - return true; -} - -/* - * ======== read_mem ======== - * This function does not need to be implemented. - */ -static int read_mem(struct dynamic_loader_initialize *this, void *buf, - ldr_addr addr, struct ldr_section_info *info, - unsigned nbytes) -{ - struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this; - struct dbll_library_obj *lib; - int bytes_read = 0; - - lib = init_obj->lib; - /* Need bridge_brd_read function */ - return bytes_read; -} - -/* - * ======== write_mem ======== - */ -static int write_mem(struct dynamic_loader_initialize *this, void *buf, - ldr_addr addr, struct ldr_section_info *info, - unsigned bytes) -{ - struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this; - struct dbll_library_obj *lib; - struct dbll_tar_obj *target_obj; - struct dbll_sect_info sect_info; - u32 mem_sect_type; - bool ret = true; - - lib = init_obj->lib; - if (!lib) - return false; - - target_obj = lib->target_obj; - - mem_sect_type = - (DLOAD_SECTION_TYPE(info->type) == - DLOAD_TEXT) ? DBLL_CODE : DBLL_DATA; - if (target_obj && target_obj->attrs.write) { - ret = - (*target_obj->attrs.write) (target_obj->attrs.input_params, - addr, buf, bytes, - mem_sect_type); - - if (target_obj->attrs.log_write) { - sect_info.name = info->name; - sect_info.sect_run_addr = info->run_addr; - sect_info.sect_load_addr = info->load_addr; - sect_info.size = info->size; - sect_info.type = mem_sect_type; - /* Pass the information about what we've written to - * another module */ - (*target_obj->attrs.log_write) (target_obj->attrs. - log_write_handle, - §_info, addr, - bytes); - } - } - return ret; -} - -/* - * ======== fill_mem ======== - * Fill bytes of memory at a given address with a given value by - * writing from a buffer containing the given value. Write in - * sets of MAXEXPR (128) bytes to avoid large stack buffer issues. - */ -static int fill_mem(struct dynamic_loader_initialize *this, ldr_addr addr, - struct ldr_section_info *info, unsigned bytes, unsigned val) -{ - bool ret = true; - char *pbuf; - struct dbll_library_obj *lib; - struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this; - - lib = init_obj->lib; - pbuf = NULL; - /* Pass the NULL pointer to write_mem to get the start address of Shared - memory. This is a trick to just get the start address, there is no - writing taking place with this Writemem - */ - if ((lib->target_obj->attrs.write) != (dbll_write_fxn) no_op) - write_mem(this, &pbuf, addr, info, 0); - if (pbuf) - memset(pbuf, val, bytes); - - return ret; -} - -/* - * ======== execute ======== - */ -static int execute(struct dynamic_loader_initialize *this, ldr_addr start) -{ - struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this; - struct dbll_library_obj *lib; - bool ret = true; - - lib = init_obj->lib; - /* Save entry point */ - if (lib != NULL) - lib->entry = (u32) start; - - return ret; -} - -/* - * ======== release ======== - */ -static void release(struct dynamic_loader_initialize *this) -{ -} - -#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE -/** - * find_symbol_context - Basic symbol context structure - * @address: Symbol Address - * @offset_range: Offset range where the search for the DSP symbol - * started. - * @cur_best_offset: Best offset to start looking for the DSP symbol - * @sym_addr: Address of the DSP symbol - * @name: Symbol name - * - */ -struct find_symbol_context { - /* input */ - u32 address; - u32 offset_range; - /* state */ - u32 cur_best_offset; - /* output */ - u32 sym_addr; - char name[120]; -}; - -/** - * find_symbol_callback() - Validates symbol address and copies the symbol name - * to the user data. - * @elem: dsp library context - * @user_data: Find symbol context - * - */ -void find_symbol_callback(void *elem, void *user_data) -{ - struct dbll_symbol *symbol = elem; - struct find_symbol_context *context = user_data; - u32 symbol_addr = symbol->value.value; - u32 offset = context->address - symbol_addr; - - /* - * Address given should be greater than symbol address, - * symbol address should be within specified range - * and the offset should be better than previous one - */ - if (context->address >= symbol_addr && symbol_addr < (u32)-1 && - offset < context->cur_best_offset) { - context->cur_best_offset = offset; - context->sym_addr = symbol_addr; - strlcpy(context->name, symbol->name, sizeof(context->name)); - } - - return; -} - -/** - * dbll_find_dsp_symbol() - This function retrieves the dsp symbol from the dsp binary. - * @zl_lib: DSP binary obj library pointer - * @address: Given address to find the dsp symbol - * @offset_range: offset range to look for dsp symbol - * @sym_addr_output: Symbol Output address - * @name_output: String with the dsp symbol - * - * This function retrieves the dsp symbol from the dsp binary. - */ -bool dbll_find_dsp_symbol(struct dbll_library_obj *zl_lib, u32 address, - u32 offset_range, u32 *sym_addr_output, - char *name_output) -{ - bool status = false; - struct find_symbol_context context; - - context.address = address; - context.offset_range = offset_range; - context.cur_best_offset = offset_range; - context.sym_addr = 0; - context.name[0] = '\0'; - - gh_iterate(zl_lib->sym_tab, find_symbol_callback, &context); - - if (context.name[0]) { - status = true; - strcpy(name_output, context.name); - *sym_addr_output = context.sym_addr; - } - - return status; -} -#endif |