summaryrefslogtreecommitdiff
path: root/drivers/staging/tidspbridge/rmgr
diff options
context:
space:
mode:
authorKristina Martšenko <kristina.martsenko@gmail.com>2014-07-16 02:30:18 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-07-15 21:01:05 -0700
commitf190be7f39a5e480ddc5e0f49bbe670feb328c32 (patch)
tree3f9e857d94f4a95166b25ba049d91a2fa78d90a1 /drivers/staging/tidspbridge/rmgr
parentcb3aadaec89109edb60d4829ce82e50b27cb4ce6 (diff)
staging: tidspbridge: remove driver
The driver has been broken and disabled for several kernel versions now. It doesn't have a maintainer anymore, and most of the people who've worked on it have moved on. There's also still a long list of issues in the TODO file before it can be moved out of staging. Until someone can put in the work to make the driver work again and move it out of staging, remove it from the kernel. Signed-off-by: Kristina Martšenko <kristina.martsenko@gmail.com> Cc: Omar Ramirez Luna <omar.ramirez@copitl.com> Cc: Suman Anna <s-anna@ti.com> Cc: Felipe Contreras <felipe.contreras@gmail.com> Cc: Ohad Ben-Cohen <ohad@wizery.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/tidspbridge/rmgr')
-rw-r--r--drivers/staging/tidspbridge/rmgr/dbdcd.c1484
-rw-r--r--drivers/staging/tidspbridge/rmgr/disp.c655
-rw-r--r--drivers/staging/tidspbridge/rmgr/drv.c816
-rw-r--r--drivers/staging/tidspbridge/rmgr/drv_interface.c650
-rw-r--r--drivers/staging/tidspbridge/rmgr/dspdrv.c139
-rw-r--r--drivers/staging/tidspbridge/rmgr/mgr.c352
-rw-r--r--drivers/staging/tidspbridge/rmgr/nldr.c1861
-rw-r--r--drivers/staging/tidspbridge/rmgr/node.c3031
-rw-r--r--drivers/staging/tidspbridge/rmgr/proc.c1836
-rw-r--r--drivers/staging/tidspbridge/rmgr/pwr.c176
-rw-r--r--drivers/staging/tidspbridge/rmgr/rmm.c456
-rw-r--r--drivers/staging/tidspbridge/rmgr/strm.c733
12 files changed, 0 insertions, 12189 deletions
diff --git a/drivers/staging/tidspbridge/rmgr/dbdcd.c b/drivers/staging/tidspbridge/rmgr/dbdcd.c
deleted file mode 100644
index c91d1d7d0884..000000000000
--- a/drivers/staging/tidspbridge/rmgr/dbdcd.c
+++ /dev/null
@@ -1,1484 +0,0 @@
-/*
- * dbdcd.c
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * This file contains the implementation of the DSP/BIOS Bridge
- * Configuration Database (DCD).
- *
- * Notes:
- * The fxn dcd_get_objects can apply a callback fxn to each DCD object
- * that is located in a specified COFF file. At the moment,
- * dcd_auto_register, dcd_auto_unregister, and NLDR module all use
- * dcd_get_objects.
- *
- * 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>
-
-/* ----------------------------------- Platform Manager */
-#include <dspbridge/cod.h>
-
-/* ----------------------------------- Others */
-#include <dspbridge/uuidutil.h>
-
-/* ----------------------------------- This */
-#include <dspbridge/dbdcd.h>
-
-/* ----------------------------------- Global defines. */
-#define MAX_INT2CHAR_LENGTH 16 /* Max int2char len of 32 bit int */
-
-/* Name of section containing dependent libraries */
-#define DEPLIBSECT ".dspbridge_deplibs"
-
-/* DCD specific structures. */
-struct dcd_manager {
- struct cod_manager *cod_mgr; /* Handle to COD manager object. */
-};
-
-/* Pointer to the registry support key */
-static struct list_head reg_key_list;
-static DEFINE_SPINLOCK(dbdcd_lock);
-
-/* Global reference variables. */
-static u32 refs;
-static u32 enum_refs;
-
-/* Helper function prototypes. */
-static s32 atoi(char *psz_buf);
-static int get_attrs_from_buf(char *psz_buf, u32 ul_buf_size,
- enum dsp_dcdobjtype obj_type,
- struct dcd_genericobj *gen_obj);
-static void compress_buf(char *psz_buf, u32 ul_buf_size, s32 char_size);
-static char dsp_char2_gpp_char(char *word, s32 dsp_char_size);
-static int get_dep_lib_info(struct dcd_manager *hdcd_mgr,
- struct dsp_uuid *uuid_obj,
- u16 *num_libs,
- u16 *num_pers_libs,
- struct dsp_uuid *dep_lib_uuids,
- bool *prstnt_dep_libs,
- enum nldr_phase phase);
-
-/*
- * ======== dcd_uuid_from_string ========
- * Purpose:
- * Converts an ANSI string to a dsp_uuid.
- * Parameters:
- * sz_uuid: Pointer to a string that represents a dsp_uuid object.
- * uuid_obj: Pointer to a dsp_uuid object.
- * Returns:
- * 0: Success.
- * -EINVAL: Coversion failed
- * Requires:
- * uuid_obj & sz_uuid are non-NULL values.
- * Ensures:
- * Details:
- * We assume the string representation of a UUID has the following format:
- * "12345678_1234_1234_1234_123456789abc".
- */
-static int dcd_uuid_from_string(char *sz_uuid, struct dsp_uuid *uuid_obj)
-{
- char c;
- u64 t;
- struct dsp_uuid uuid_tmp;
-
- /*
- * sscanf implementation cannot deal with hh format modifier
- * if the converted value doesn't fit in u32. So, convert the
- * last six bytes to u64 and memcpy what is needed
- */
- if (sscanf(sz_uuid, "%8x%c%4hx%c%4hx%c%2hhx%2hhx%c%llx",
- &uuid_tmp.data1, &c, &uuid_tmp.data2, &c,
- &uuid_tmp.data3, &c, &uuid_tmp.data4,
- &uuid_tmp.data5, &c, &t) != 10)
- return -EINVAL;
-
- t = cpu_to_be64(t);
- memcpy(&uuid_tmp.data6[0], ((char *)&t) + 2, 6);
- *uuid_obj = uuid_tmp;
-
- return 0;
-}
-
-/*
- * ======== dcd_auto_register ========
- * Purpose:
- * Parses the supplied image and resigsters with DCD.
- */
-int dcd_auto_register(struct dcd_manager *hdcd_mgr,
- char *sz_coff_path)
-{
- int status = 0;
-
- if (hdcd_mgr)
- status = dcd_get_objects(hdcd_mgr, sz_coff_path,
- (dcd_registerfxn) dcd_register_object,
- (void *)sz_coff_path);
- else
- status = -EFAULT;
-
- return status;
-}
-
-/*
- * ======== dcd_auto_unregister ========
- * Purpose:
- * Parses the supplied DSP image and unresiters from DCD.
- */
-int dcd_auto_unregister(struct dcd_manager *hdcd_mgr,
- char *sz_coff_path)
-{
- int status = 0;
-
- if (hdcd_mgr)
- status = dcd_get_objects(hdcd_mgr, sz_coff_path,
- (dcd_registerfxn) dcd_register_object,
- NULL);
- else
- status = -EFAULT;
-
- return status;
-}
-
-/*
- * ======== dcd_create_manager ========
- * Purpose:
- * Creates DCD manager.
- */
-int dcd_create_manager(char *sz_zl_dll_name,
- struct dcd_manager **dcd_mgr)
-{
- struct cod_manager *cod_mgr; /* COD manager handle */
- struct dcd_manager *dcd_mgr_obj = NULL; /* DCD Manager pointer */
- int status = 0;
-
- status = cod_create(&cod_mgr, sz_zl_dll_name);
- if (status)
- goto func_end;
-
- /* Create a DCD object. */
- dcd_mgr_obj = kzalloc(sizeof(struct dcd_manager), GFP_KERNEL);
- if (dcd_mgr_obj != NULL) {
- /* Fill out the object. */
- dcd_mgr_obj->cod_mgr = cod_mgr;
-
- /* Return handle to this DCD interface. */
- *dcd_mgr = dcd_mgr_obj;
- } else {
- status = -ENOMEM;
-
- /*
- * If allocation of DcdManager object failed, delete the
- * COD manager.
- */
- cod_delete(cod_mgr);
- }
-
-func_end:
- return status;
-}
-
-/*
- * ======== dcd_destroy_manager ========
- * Purpose:
- * Frees DCD Manager object.
- */
-int dcd_destroy_manager(struct dcd_manager *hdcd_mgr)
-{
- struct dcd_manager *dcd_mgr_obj = hdcd_mgr;
- int status = -EFAULT;
-
- if (hdcd_mgr) {
- /* Delete the COD manager. */
- cod_delete(dcd_mgr_obj->cod_mgr);
-
- /* Deallocate a DCD manager object. */
- kfree(dcd_mgr_obj);
-
- status = 0;
- }
-
- return status;
-}
-
-/*
- * ======== dcd_enumerate_object ========
- * Purpose:
- * Enumerates objects in the DCD.
- */
-int dcd_enumerate_object(s32 index, enum dsp_dcdobjtype obj_type,
- struct dsp_uuid *uuid_obj)
-{
- int status = 0;
- char sz_reg_key[DCD_MAXPATHLENGTH];
- char sz_value[DCD_MAXPATHLENGTH];
- struct dsp_uuid dsp_uuid_obj;
- char sz_obj_type[MAX_INT2CHAR_LENGTH]; /* str. rep. of obj_type. */
- u32 dw_key_len = 0;
- struct dcd_key_elem *dcd_key;
- int len;
-
- if ((index != 0) && (enum_refs == 0)) {
- /*
- * If an enumeration is being performed on an index greater
- * than zero, then the current enum_refs must have been
- * incremented to greater than zero.
- */
- status = -EIDRM;
- } else {
- /*
- * Pre-determine final key length. It's length of DCD_REGKEY +
- * "_\0" + length of sz_obj_type string + terminating NULL.
- */
- dw_key_len = strlen(DCD_REGKEY) + 1 + sizeof(sz_obj_type) + 1;
-
- /* Create proper REG key; concatenate DCD_REGKEY with
- * obj_type. */
- strncpy(sz_reg_key, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
- if ((strlen(sz_reg_key) + strlen("_\0")) <
- DCD_MAXPATHLENGTH) {
- strncat(sz_reg_key, "_\0", 2);
- } else {
- status = -EPERM;
- }
-
- /* This snprintf is guaranteed not to exceed max size of an
- * integer. */
- status = snprintf(sz_obj_type, MAX_INT2CHAR_LENGTH, "%d",
- obj_type);
-
- if (status == -1) {
- status = -EPERM;
- } else {
- status = 0;
- if ((strlen(sz_reg_key) + strlen(sz_obj_type)) <
- DCD_MAXPATHLENGTH) {
- strncat(sz_reg_key, sz_obj_type,
- strlen(sz_obj_type) + 1);
- } else {
- status = -EPERM;
- }
- }
-
- if (!status) {
- len = strlen(sz_reg_key);
- spin_lock(&dbdcd_lock);
- list_for_each_entry(dcd_key, &reg_key_list, link) {
- if (!strncmp(dcd_key->name, sz_reg_key, len)
- && !index--) {
- strncpy(sz_value, &dcd_key->name[len],
- strlen(&dcd_key->name[len]) + 1);
- break;
- }
- }
- spin_unlock(&dbdcd_lock);
-
- if (&dcd_key->link == &reg_key_list)
- status = -ENODATA;
- }
-
- if (!status) {
- /* Create UUID value using string retrieved from
- * registry. */
- status = dcd_uuid_from_string(sz_value, &dsp_uuid_obj);
-
- if (!status) {
- *uuid_obj = dsp_uuid_obj;
-
- /* Increment enum_refs to update reference
- * count. */
- enum_refs++;
- }
- } else if (status == -ENODATA) {
- /* At the end of enumeration. Reset enum_refs. */
- enum_refs = 0;
-
- /*
- * TODO: Revisit, this is not an error case but code
- * expects non-zero value.
- */
- status = ENODATA;
- } else {
- status = -EPERM;
- }
- }
-
- return status;
-}
-
-/*
- * ======== dcd_exit ========
- * Purpose:
- * Discontinue usage of the DCD module.
- */
-void dcd_exit(void)
-{
- struct dcd_key_elem *rv, *rv_tmp;
-
- refs--;
- if (refs == 0) {
- list_for_each_entry_safe(rv, rv_tmp, &reg_key_list, link) {
- list_del(&rv->link);
- kfree(rv->path);
- kfree(rv);
- }
- }
-
-}
-
-/*
- * ======== dcd_get_dep_libs ========
- */
-int dcd_get_dep_libs(struct dcd_manager *hdcd_mgr,
- struct dsp_uuid *uuid_obj,
- u16 num_libs, struct dsp_uuid *dep_lib_uuids,
- bool *prstnt_dep_libs,
- enum nldr_phase phase)
-{
- int status = 0;
-
- status =
- get_dep_lib_info(hdcd_mgr, uuid_obj, &num_libs, NULL, dep_lib_uuids,
- prstnt_dep_libs, phase);
-
- return status;
-}
-
-/*
- * ======== dcd_get_num_dep_libs ========
- */
-int dcd_get_num_dep_libs(struct dcd_manager *hdcd_mgr,
- struct dsp_uuid *uuid_obj,
- u16 *num_libs, u16 *num_pers_libs,
- enum nldr_phase phase)
-{
- int status = 0;
-
- status = get_dep_lib_info(hdcd_mgr, uuid_obj, num_libs, num_pers_libs,
- NULL, NULL, phase);
-
- return status;
-}
-
-/*
- * ======== dcd_get_object_def ========
- * Purpose:
- * Retrieves the properties of a node or processor based on the UUID and
- * object type.
- */
-int dcd_get_object_def(struct dcd_manager *hdcd_mgr,
- struct dsp_uuid *obj_uuid,
- enum dsp_dcdobjtype obj_type,
- struct dcd_genericobj *obj_def)
-{
- struct dcd_manager *dcd_mgr_obj = hdcd_mgr; /* ptr to DCD mgr */
- struct cod_libraryobj *lib = NULL;
- int status = 0;
- int len;
- u32 ul_addr = 0; /* Used by cod_get_section */
- u32 ul_len = 0; /* Used by cod_get_section */
- u32 dw_buf_size; /* Used by REG functions */
- char sz_reg_key[DCD_MAXPATHLENGTH];
- char *sz_uuid; /*[MAXUUIDLEN]; */
- char *tmp;
- struct dcd_key_elem *dcd_key = NULL;
- char sz_sect_name[MAXUUIDLEN + 2]; /* ".[UUID]\0" */
- char *psz_coff_buf;
- u32 dw_key_len; /* Len of REG key. */
- char sz_obj_type[MAX_INT2CHAR_LENGTH]; /* str. rep. of obj_type. */
-
- sz_uuid = kzalloc(MAXUUIDLEN, GFP_KERNEL);
- if (!sz_uuid) {
- status = -ENOMEM;
- goto func_end;
- }
-
- if (!hdcd_mgr) {
- status = -EFAULT;
- goto func_end;
- }
-
- /* Pre-determine final key length. It's length of DCD_REGKEY +
- * "_\0" + length of sz_obj_type string + terminating NULL */
- dw_key_len = strlen(DCD_REGKEY) + 1 + sizeof(sz_obj_type) + 1;
-
- /* Create proper REG key; concatenate DCD_REGKEY with obj_type. */
- strncpy(sz_reg_key, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
-
- if ((strlen(sz_reg_key) + strlen("_\0")) < DCD_MAXPATHLENGTH)
- strncat(sz_reg_key, "_\0", 2);
- else
- status = -EPERM;
-
- status = snprintf(sz_obj_type, MAX_INT2CHAR_LENGTH, "%d", obj_type);
- if (status == -1) {
- status = -EPERM;
- } else {
- status = 0;
-
- if ((strlen(sz_reg_key) + strlen(sz_obj_type)) <
- DCD_MAXPATHLENGTH) {
- strncat(sz_reg_key, sz_obj_type,
- strlen(sz_obj_type) + 1);
- } else {
- status = -EPERM;
- }
-
- /* Create UUID value to set in registry. */
- snprintf(sz_uuid, MAXUUIDLEN, "%pUL", obj_uuid);
-
- if ((strlen(sz_reg_key) + MAXUUIDLEN) < DCD_MAXPATHLENGTH)
- strncat(sz_reg_key, sz_uuid, MAXUUIDLEN);
- else
- status = -EPERM;
-
- /* Retrieve paths from the registry based on struct dsp_uuid */
- dw_buf_size = DCD_MAXPATHLENGTH;
- }
- if (!status) {
- spin_lock(&dbdcd_lock);
- list_for_each_entry(dcd_key, &reg_key_list, link) {
- if (!strncmp(dcd_key->name, sz_reg_key,
- strlen(sz_reg_key) + 1))
- break;
- }
- spin_unlock(&dbdcd_lock);
- if (&dcd_key->link == &reg_key_list) {
- status = -ENOKEY;
- goto func_end;
- }
- }
-
-
- /* Open COFF file. */
- status = cod_open(dcd_mgr_obj->cod_mgr, dcd_key->path,
- COD_NOLOAD, &lib);
- if (status) {
- status = -EACCES;
- goto func_end;
- }
-
- /* Ensure sz_uuid + 1 is not greater than sizeof sz_sect_name. */
- len = strlen(sz_uuid);
- if (len + 1 > sizeof(sz_sect_name)) {
- status = -EPERM;
- goto func_end;
- }
-
- /* Create section name based on node UUID. A period is
- * pre-pended to the UUID string to form the section name.
- * I.e. ".24BC8D90_BB45_11d4_B756_006008BDB66F" */
-
- len -= 4; /* uuid has 4 delimiters '-' */
- tmp = sz_uuid;
-
- strncpy(sz_sect_name, ".", 2);
- do {
- char *uuid = strsep(&tmp, "-");
-
- if (!uuid)
- break;
- len -= strlen(uuid);
- strncat(sz_sect_name, uuid, strlen(uuid) + 1);
- } while (len && strncat(sz_sect_name, "_", 2));
-
- /* Get section information. */
- status = cod_get_section(lib, sz_sect_name, &ul_addr, &ul_len);
- if (status) {
- status = -EACCES;
- goto func_end;
- }
-
- /* Allocate zeroed buffer. */
- psz_coff_buf = kzalloc(ul_len + 4, GFP_KERNEL);
- if (psz_coff_buf == NULL) {
- status = -ENOMEM;
- goto func_end;
- }
-#ifdef _DB_TIOMAP
- if (strstr(dcd_key->path, "iva") == NULL) {
- /* Locate section by objectID and read its content. */
- status =
- cod_read_section(lib, sz_sect_name, psz_coff_buf, ul_len);
- } else {
- status =
- cod_read_section(lib, sz_sect_name, psz_coff_buf, ul_len);
- dev_dbg(bridge, "%s: Skipped Byte swap for IVA!!\n", __func__);
- }
-#else
- status = cod_read_section(lib, sz_sect_name, psz_coff_buf, ul_len);
-#endif
- if (!status) {
- /* Compress DSP buffer to conform to PC format. */
- if (strstr(dcd_key->path, "iva") == NULL) {
- compress_buf(psz_coff_buf, ul_len, DSPWORDSIZE);
- } else {
- compress_buf(psz_coff_buf, ul_len, 1);
- dev_dbg(bridge, "%s: Compressing IVA COFF buffer by 1 "
- "for IVA!!\n", __func__);
- }
-
- /* Parse the content of the COFF buffer. */
- status =
- get_attrs_from_buf(psz_coff_buf, ul_len, obj_type, obj_def);
- if (status)
- status = -EACCES;
- } else {
- status = -EACCES;
- }
-
- /* Free the previously allocated dynamic buffer. */
- kfree(psz_coff_buf);
-func_end:
- if (lib)
- cod_close(lib);
-
- kfree(sz_uuid);
-
- return status;
-}
-
-/*
- * ======== dcd_get_objects ========
- */
-int dcd_get_objects(struct dcd_manager *hdcd_mgr,
- char *sz_coff_path, dcd_registerfxn register_fxn,
- void *handle)
-{
- struct dcd_manager *dcd_mgr_obj = hdcd_mgr;
- int status = 0;
- char *psz_coff_buf;
- char *psz_cur;
- struct cod_libraryobj *lib = NULL;
- u32 ul_addr = 0; /* Used by cod_get_section */
- u32 ul_len = 0; /* Used by cod_get_section */
- char seps[] = ":, ";
- char *token = NULL;
- struct dsp_uuid dsp_uuid_obj;
- s32 object_type;
-
- if (!hdcd_mgr) {
- status = -EFAULT;
- goto func_end;
- }
-
- /* Open DSP coff file, don't load symbols. */
- status = cod_open(dcd_mgr_obj->cod_mgr, sz_coff_path, COD_NOLOAD, &lib);
- if (status) {
- status = -EACCES;
- goto func_cont;
- }
-
- /* Get DCD_RESIGER_SECTION section information. */
- status = cod_get_section(lib, DCD_REGISTER_SECTION, &ul_addr, &ul_len);
- if (status || !(ul_len > 0)) {
- status = -EACCES;
- goto func_cont;
- }
-
- /* Allocate zeroed buffer. */
- psz_coff_buf = kzalloc(ul_len + 4, GFP_KERNEL);
- if (psz_coff_buf == NULL) {
- status = -ENOMEM;
- goto func_cont;
- }
-#ifdef _DB_TIOMAP
- if (strstr(sz_coff_path, "iva") == NULL) {
- /* Locate section by objectID and read its content. */
- status = cod_read_section(lib, DCD_REGISTER_SECTION,
- psz_coff_buf, ul_len);
- } else {
- dev_dbg(bridge, "%s: Skipped Byte swap for IVA!!\n", __func__);
- status = cod_read_section(lib, DCD_REGISTER_SECTION,
- psz_coff_buf, ul_len);
- }
-#else
- status =
- cod_read_section(lib, DCD_REGISTER_SECTION, psz_coff_buf, ul_len);
-#endif
- if (!status) {
- /* Compress DSP buffer to conform to PC format. */
- if (strstr(sz_coff_path, "iva") == NULL) {
- compress_buf(psz_coff_buf, ul_len, DSPWORDSIZE);
- } else {
- compress_buf(psz_coff_buf, ul_len, 1);
- dev_dbg(bridge, "%s: Compress COFF buffer with 1 word "
- "for IVA!!\n", __func__);
- }
-
- /* Read from buffer and register object in buffer. */
- psz_cur = psz_coff_buf;
- while ((token = strsep(&psz_cur, seps)) && *token != '\0') {
- /* Retrieve UUID string. */
- status = dcd_uuid_from_string(token, &dsp_uuid_obj);
-
- if (!status) {
- /* Retrieve object type */
- token = strsep(&psz_cur, seps);
-
- /* Retrieve object type */
- object_type = atoi(token);
-
- /*
- * Apply register_fxn to the found DCD object.
- * Possible actions include:
- *
- * 1) Register found DCD object.
- * 2) Unregister found DCD object
- * (when handle == NULL)
- * 3) Add overlay node.
- */
- status =
- register_fxn(&dsp_uuid_obj, object_type,
- handle);
- }
- if (status) {
- /* if error occurs, break from while loop. */
- break;
- }
- }
- } else {
- status = -EACCES;
- }
-
- /* Free the previously allocated dynamic buffer. */
- kfree(psz_coff_buf);
-func_cont:
- if (lib)
- cod_close(lib);
-
-func_end:
- return status;
-}
-
-/*
- * ======== dcd_get_library_name ========
- * Purpose:
- * Retrieves the library name for the given UUID.
- *
- */
-int dcd_get_library_name(struct dcd_manager *hdcd_mgr,
- struct dsp_uuid *uuid_obj,
- char *str_lib_name,
- u32 *buff_size,
- enum nldr_phase phase, bool *phase_split)
-{
- char sz_reg_key[DCD_MAXPATHLENGTH];
- char sz_uuid[MAXUUIDLEN];
- u32 dw_key_len; /* Len of REG key. */
- char sz_obj_type[MAX_INT2CHAR_LENGTH]; /* str. rep. of obj_type. */
- int status = 0;
- struct dcd_key_elem *dcd_key = NULL;
-
- dev_dbg(bridge, "%s: hdcd_mgr %p, uuid_obj %p, str_lib_name %p,"
- " buff_size %p\n", __func__, hdcd_mgr, uuid_obj, str_lib_name,
- buff_size);
-
- /*
- * Pre-determine final key length. It's length of DCD_REGKEY +
- * "_\0" + length of sz_obj_type string + terminating NULL.
- */
- dw_key_len = strlen(DCD_REGKEY) + 1 + sizeof(sz_obj_type) + 1;
-
- /* Create proper REG key; concatenate DCD_REGKEY with obj_type. */
- strncpy(sz_reg_key, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
- if ((strlen(sz_reg_key) + strlen("_\0")) < DCD_MAXPATHLENGTH)
- strncat(sz_reg_key, "_\0", 2);
- else
- status = -EPERM;
-
- switch (phase) {
- case NLDR_CREATE:
- /* create phase type */
- sprintf(sz_obj_type, "%d", DSP_DCDCREATELIBTYPE);
- break;
- case NLDR_EXECUTE:
- /* execute phase type */
- sprintf(sz_obj_type, "%d", DSP_DCDEXECUTELIBTYPE);
- break;
- case NLDR_DELETE:
- /* delete phase type */
- sprintf(sz_obj_type, "%d", DSP_DCDDELETELIBTYPE);
- break;
- case NLDR_NOPHASE:
- /* known to be a dependent library */
- sprintf(sz_obj_type, "%d", DSP_DCDLIBRARYTYPE);
- break;
- default:
- status = -EINVAL;
- }
- if (!status) {
- if ((strlen(sz_reg_key) + strlen(sz_obj_type)) <
- DCD_MAXPATHLENGTH) {
- strncat(sz_reg_key, sz_obj_type,
- strlen(sz_obj_type) + 1);
- } else {
- status = -EPERM;
- }
- /* Create UUID value to find match in registry. */
- snprintf(sz_uuid, MAXUUIDLEN, "%pUL", uuid_obj);
- if ((strlen(sz_reg_key) + MAXUUIDLEN) < DCD_MAXPATHLENGTH)
- strncat(sz_reg_key, sz_uuid, MAXUUIDLEN);
- else
- status = -EPERM;
- }
- if (!status) {
- spin_lock(&dbdcd_lock);
- list_for_each_entry(dcd_key, &reg_key_list, link) {
- /* See if the name matches. */
- if (!strncmp(dcd_key->name, sz_reg_key,
- strlen(sz_reg_key) + 1))
- break;
- }
- spin_unlock(&dbdcd_lock);
- }
-
- if (&dcd_key->link == &reg_key_list)
- status = -ENOKEY;
-
- /* If can't find, phases might be registered as generic LIBRARYTYPE */
- if (status && phase != NLDR_NOPHASE) {
- if (phase_split)
- *phase_split = false;
-
- strncpy(sz_reg_key, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
- if ((strlen(sz_reg_key) + strlen("_\0")) <
- DCD_MAXPATHLENGTH) {
- strncat(sz_reg_key, "_\0", 2);
- } else {
- status = -EPERM;
- }
- sprintf(sz_obj_type, "%d", DSP_DCDLIBRARYTYPE);
- if ((strlen(sz_reg_key) + strlen(sz_obj_type))
- < DCD_MAXPATHLENGTH) {
- strncat(sz_reg_key, sz_obj_type,
- strlen(sz_obj_type) + 1);
- } else {
- status = -EPERM;
- }
- snprintf(sz_uuid, MAXUUIDLEN, "%pUL", uuid_obj);
- if ((strlen(sz_reg_key) + MAXUUIDLEN) < DCD_MAXPATHLENGTH)
- strncat(sz_reg_key, sz_uuid, MAXUUIDLEN);
- else
- status = -EPERM;
-
- spin_lock(&dbdcd_lock);
- list_for_each_entry(dcd_key, &reg_key_list, link) {
- /* See if the name matches. */
- if (!strncmp(dcd_key->name, sz_reg_key,
- strlen(sz_reg_key) + 1))
- break;
- }
- spin_unlock(&dbdcd_lock);
-
- status = (&dcd_key->link != &reg_key_list) ?
- 0 : -ENOKEY;
- }
-
- if (!status)
- memcpy(str_lib_name, dcd_key->path, strlen(dcd_key->path) + 1);
- return status;
-}
-
-/*
- * ======== dcd_init ========
- * Purpose:
- * Initialize the DCD module.
- */
-bool dcd_init(void)
-{
- bool ret = true;
-
- if (refs == 0)
- INIT_LIST_HEAD(&reg_key_list);
-
- if (ret)
- refs++;
-
- return ret;
-}
-
-/*
- * ======== dcd_register_object ========
- * Purpose:
- * Registers a node or a processor with the DCD.
- * If psz_path_name == NULL, unregister the specified DCD object.
- */
-int dcd_register_object(struct dsp_uuid *uuid_obj,
- enum dsp_dcdobjtype obj_type,
- char *psz_path_name)
-{
- int status = 0;
- char sz_reg_key[DCD_MAXPATHLENGTH];
- char sz_uuid[MAXUUIDLEN + 1];
- u32 dw_path_size = 0;
- u32 dw_key_len; /* Len of REG key. */
- char sz_obj_type[MAX_INT2CHAR_LENGTH]; /* str. rep. of obj_type. */
- struct dcd_key_elem *dcd_key = NULL;
-
- dev_dbg(bridge, "%s: object UUID %p, obj_type %d, szPathName %s\n",
- __func__, uuid_obj, obj_type, psz_path_name);
-
- /*
- * Pre-determine final key length. It's length of DCD_REGKEY +
- * "_\0" + length of sz_obj_type string + terminating NULL.
- */
- dw_key_len = strlen(DCD_REGKEY) + 1 + sizeof(sz_obj_type) + 1;
-
- /* Create proper REG key; concatenate DCD_REGKEY with obj_type. */
- strncpy(sz_reg_key, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
- if ((strlen(sz_reg_key) + strlen("_\0")) < DCD_MAXPATHLENGTH)
- strncat(sz_reg_key, "_\0", 2);
- else {
- status = -EPERM;
- goto func_end;
- }
-
- status = snprintf(sz_obj_type, MAX_INT2CHAR_LENGTH, "%d", obj_type);
- if (status == -1) {
- status = -EPERM;
- } else {
- status = 0;
- if ((strlen(sz_reg_key) + strlen(sz_obj_type)) <
- DCD_MAXPATHLENGTH) {
- strncat(sz_reg_key, sz_obj_type,
- strlen(sz_obj_type) + 1);
- } else
- status = -EPERM;
-
- /* Create UUID value to set in registry. */
- snprintf(sz_uuid, MAXUUIDLEN, "%pUL", uuid_obj);
- if ((strlen(sz_reg_key) + MAXUUIDLEN) < DCD_MAXPATHLENGTH)
- strncat(sz_reg_key, sz_uuid, MAXUUIDLEN);
- else
- status = -EPERM;
- }
-
- if (status)
- goto func_end;
-
- /*
- * If psz_path_name != NULL, perform registration, otherwise,
- * perform unregistration.
- */
-
- if (psz_path_name) {
- dw_path_size = strlen(psz_path_name) + 1;
- spin_lock(&dbdcd_lock);
- list_for_each_entry(dcd_key, &reg_key_list, link) {
- /* See if the name matches. */
- if (!strncmp(dcd_key->name, sz_reg_key,
- strlen(sz_reg_key) + 1))
- break;
- }
- spin_unlock(&dbdcd_lock);
- if (&dcd_key->link == &reg_key_list) {
- /*
- * Add new reg value (UUID+obj_type)
- * with COFF path info
- */
-
- dcd_key = kmalloc(sizeof(struct dcd_key_elem),
- GFP_KERNEL);
- if (!dcd_key) {
- status = -ENOMEM;
- goto func_end;
- }
-
- dcd_key->path = kmalloc(dw_path_size, GFP_KERNEL);
-
- if (!dcd_key->path) {
- kfree(dcd_key);
- status = -ENOMEM;
- goto func_end;
- }
-
- strncpy(dcd_key->name, sz_reg_key,
- strlen(sz_reg_key) + 1);
- strncpy(dcd_key->path, psz_path_name ,
- dw_path_size);
- spin_lock(&dbdcd_lock);
- list_add_tail(&dcd_key->link, &reg_key_list);
- spin_unlock(&dbdcd_lock);
- } else {
- /* Make sure the new data is the same. */
- if (strncmp(dcd_key->path, psz_path_name,
- dw_path_size)) {
- /* The caller needs a different data size! */
- kfree(dcd_key->path);
- dcd_key->path = kmalloc(dw_path_size,
- GFP_KERNEL);
- if (dcd_key->path == NULL) {
- status = -ENOMEM;
- goto func_end;
- }
- }
-
- /* We have a match! Copy out the data. */
- memcpy(dcd_key->path, psz_path_name, dw_path_size);
- }
- dev_dbg(bridge, "%s: psz_path_name=%s, dw_path_size=%d\n",
- __func__, psz_path_name, dw_path_size);
- } else {
- /* Deregister an existing object */
- spin_lock(&dbdcd_lock);
- list_for_each_entry(dcd_key, &reg_key_list, link) {
- if (!strncmp(dcd_key->name, sz_reg_key,
- strlen(sz_reg_key) + 1)) {
- list_del(&dcd_key->link);
- kfree(dcd_key->path);
- kfree(dcd_key);
- break;
- }
- }
- spin_unlock(&dbdcd_lock);
- if (&dcd_key->link == &reg_key_list)
- status = -EPERM;
- }
-
- if (!status) {
- /*
- * Because the node database has been updated through a
- * successful object registration/de-registration operation,
- * we need to reset the object enumeration counter to allow
- * current enumerations to reflect this update in the node
- * database.
- */
- enum_refs = 0;
- }
-func_end:
- return status;
-}
-
-/*
- * ======== dcd_unregister_object ========
- * Call DCD_Register object with psz_path_name set to NULL to
- * perform actual object de-registration.
- */
-int dcd_unregister_object(struct dsp_uuid *uuid_obj,
- enum dsp_dcdobjtype obj_type)
-{
- int status = 0;
-
- /*
- * When dcd_register_object is called with NULL as pathname,
- * it indicates an unregister object operation.
- */
- status = dcd_register_object(uuid_obj, obj_type, NULL);
-
- return status;
-}
-
-/*
- **********************************************************************
- * DCD Helper Functions
- **********************************************************************
- */
-
-/*
- * ======== atoi ========
- * Purpose:
- * This function converts strings in decimal or hex format to integers.
- */
-static s32 atoi(char *psz_buf)
-{
- char *pch = psz_buf;
- s32 base = 0;
-
- while (isspace(*pch))
- pch++;
-
- if (*pch == '-' || *pch == '+') {
- base = 10;
- pch++;
- } else if (*pch && tolower(pch[strlen(pch) - 1]) == 'h') {
- base = 16;
- }
-
- return simple_strtoul(pch, NULL, base);
-}
-
-/*
- * ======== get_attrs_from_buf ========
- * Purpose:
- * Parse the content of a buffer filled with DSP-side data and
- * retrieve an object's attributes from it. IMPORTANT: Assume the
- * buffer has been converted from DSP format to GPP format.
- */
-static int get_attrs_from_buf(char *psz_buf, u32 ul_buf_size,
- enum dsp_dcdobjtype obj_type,
- struct dcd_genericobj *gen_obj)
-{
- int status = 0;
- char seps[] = ", ";
- char *psz_cur;
- char *token;
- s32 token_len = 0;
- u32 i = 0;
-#ifdef _DB_TIOMAP
- s32 entry_id;
-#endif
-
- switch (obj_type) {
- case DSP_DCDNODETYPE:
- /*
- * Parse COFF sect buffer to retrieve individual tokens used
- * to fill in object attrs.
- */
- psz_cur = psz_buf;
- token = strsep(&psz_cur, seps);
-
- /* u32 cb_struct */
- gen_obj->obj_data.node_obj.ndb_props.cb_struct =
- (u32) atoi(token);
- token = strsep(&psz_cur, seps);
-
- /* dsp_uuid ui_node_id */
- status = dcd_uuid_from_string(token,
- &gen_obj->obj_data.node_obj.
- ndb_props.ui_node_id);
- if (status)
- break;
-
- token = strsep(&psz_cur, seps);
-
- /* ac_name */
- token_len = strlen(token);
- if (token_len > DSP_MAXNAMELEN - 1)
- token_len = DSP_MAXNAMELEN - 1;
-
- strncpy(gen_obj->obj_data.node_obj.ndb_props.ac_name,
- token, token_len);
- gen_obj->obj_data.node_obj.ndb_props.ac_name[token_len] = '\0';
- token = strsep(&psz_cur, seps);
- /* u32 ntype */
- gen_obj->obj_data.node_obj.ndb_props.ntype = atoi(token);
- token = strsep(&psz_cur, seps);
- /* u32 cache_on_gpp */
- gen_obj->obj_data.node_obj.ndb_props.cache_on_gpp = atoi(token);
- token = strsep(&psz_cur, seps);
- /* dsp_resourcereqmts dsp_resource_reqmts */
- gen_obj->obj_data.node_obj.ndb_props.dsp_resource_reqmts.
- cb_struct = (u32) atoi(token);
- token = strsep(&psz_cur, seps);
-
- gen_obj->obj_data.node_obj.ndb_props.
- dsp_resource_reqmts.static_data_size = atoi(token);
- token = strsep(&psz_cur, seps);
- gen_obj->obj_data.node_obj.ndb_props.
- dsp_resource_reqmts.global_data_size = atoi(token);
- token = strsep(&psz_cur, seps);
- gen_obj->obj_data.node_obj.ndb_props.
- dsp_resource_reqmts.program_mem_size = atoi(token);
- token = strsep(&psz_cur, seps);
- gen_obj->obj_data.node_obj.ndb_props.
- dsp_resource_reqmts.wc_execution_time = atoi(token);
- token = strsep(&psz_cur, seps);
- gen_obj->obj_data.node_obj.ndb_props.
- dsp_resource_reqmts.wc_period = atoi(token);
- token = strsep(&psz_cur, seps);
-
- gen_obj->obj_data.node_obj.ndb_props.
- dsp_resource_reqmts.wc_deadline = atoi(token);
- token = strsep(&psz_cur, seps);
-
- gen_obj->obj_data.node_obj.ndb_props.
- dsp_resource_reqmts.avg_exection_time = atoi(token);
- token = strsep(&psz_cur, seps);
-
- gen_obj->obj_data.node_obj.ndb_props.
- dsp_resource_reqmts.minimum_period = atoi(token);
- token = strsep(&psz_cur, seps);
-
- /* s32 prio */
- gen_obj->obj_data.node_obj.ndb_props.prio = atoi(token);
- token = strsep(&psz_cur, seps);
-
- /* u32 stack_size */
- gen_obj->obj_data.node_obj.ndb_props.stack_size = atoi(token);
- token = strsep(&psz_cur, seps);
-
- /* u32 sys_stack_size */
- gen_obj->obj_data.node_obj.ndb_props.sys_stack_size =
- atoi(token);
- token = strsep(&psz_cur, seps);
-
- /* u32 stack_seg */
- gen_obj->obj_data.node_obj.ndb_props.stack_seg = atoi(token);
- token = strsep(&psz_cur, seps);
-
- /* u32 message_depth */
- gen_obj->obj_data.node_obj.ndb_props.message_depth =
- atoi(token);
- token = strsep(&psz_cur, seps);
-
- /* u32 num_input_streams */
- gen_obj->obj_data.node_obj.ndb_props.num_input_streams =
- atoi(token);
- token = strsep(&psz_cur, seps);
-
- /* u32 num_output_streams */
- gen_obj->obj_data.node_obj.ndb_props.num_output_streams =
- atoi(token);
- token = strsep(&psz_cur, seps);
-
- /* u32 timeout */
- gen_obj->obj_data.node_obj.ndb_props.timeout = atoi(token);
- token = strsep(&psz_cur, seps);
-
- /* char *str_create_phase_fxn */
- token_len = strlen(token);
- gen_obj->obj_data.node_obj.str_create_phase_fxn =
- kzalloc(token_len + 1, GFP_KERNEL);
- strncpy(gen_obj->obj_data.node_obj.str_create_phase_fxn,
- token, token_len);
- gen_obj->obj_data.node_obj.str_create_phase_fxn[token_len] =
- '\0';
- token = strsep(&psz_cur, seps);
-
- /* char *str_execute_phase_fxn */
- token_len = strlen(token);
- gen_obj->obj_data.node_obj.str_execute_phase_fxn =
- kzalloc(token_len + 1, GFP_KERNEL);
- strncpy(gen_obj->obj_data.node_obj.str_execute_phase_fxn,
- token, token_len);
- gen_obj->obj_data.node_obj.str_execute_phase_fxn[token_len] =
- '\0';
- token = strsep(&psz_cur, seps);
-
- /* char *str_delete_phase_fxn */
- token_len = strlen(token);
- gen_obj->obj_data.node_obj.str_delete_phase_fxn =
- kzalloc(token_len + 1, GFP_KERNEL);
- strncpy(gen_obj->obj_data.node_obj.str_delete_phase_fxn,
- token, token_len);
- gen_obj->obj_data.node_obj.str_delete_phase_fxn[token_len] =
- '\0';
- token = strsep(&psz_cur, seps);
-
- /* Segment id for message buffers */
- gen_obj->obj_data.node_obj.msg_segid = atoi(token);
- token = strsep(&psz_cur, seps);
-
- /* Message notification type */
- gen_obj->obj_data.node_obj.msg_notify_type = atoi(token);
- token = strsep(&psz_cur, seps);
-
- /* char *str_i_alg_name */
- if (token) {
- token_len = strlen(token);
- gen_obj->obj_data.node_obj.str_i_alg_name =
- kzalloc(token_len + 1, GFP_KERNEL);
- strncpy(gen_obj->obj_data.node_obj.str_i_alg_name,
- token, token_len);
- gen_obj->obj_data.node_obj.str_i_alg_name[token_len] =
- '\0';
- token = strsep(&psz_cur, seps);
- }
-
- /* Load type (static, dynamic, or overlay) */
- if (token) {
- gen_obj->obj_data.node_obj.load_type = atoi(token);
- token = strsep(&psz_cur, seps);
- }
-
- /* Dynamic load data requirements */
- if (token) {
- gen_obj->obj_data.node_obj.data_mem_seg_mask =
- atoi(token);
- token = strsep(&psz_cur, seps);
- }
-
- /* Dynamic load code requirements */
- if (token) {
- gen_obj->obj_data.node_obj.code_mem_seg_mask =
- atoi(token);
- token = strsep(&psz_cur, seps);
- }
-
- /* Extract node profiles into node properties */
- if (token) {
-
- gen_obj->obj_data.node_obj.ndb_props.count_profiles =
- atoi(token);
- for (i = 0;
- i <
- gen_obj->obj_data.node_obj.
- ndb_props.count_profiles; i++) {
- token = strsep(&psz_cur, seps);
- if (token) {
- /* Heap Size for the node */
- gen_obj->obj_data.node_obj.
- ndb_props.node_profiles[i].
- heap_size = atoi(token);
- }
- }
- }
- token = strsep(&psz_cur, seps);
- if (token) {
- gen_obj->obj_data.node_obj.ndb_props.stack_seg_name =
- (u32) (token);
- }
-
- break;
-
- case DSP_DCDPROCESSORTYPE:
- /*
- * Parse COFF sect buffer to retrieve individual tokens used
- * to fill in object attrs.
- */
- psz_cur = psz_buf;
- token = strsep(&psz_cur, seps);
-
- gen_obj->obj_data.proc_info.cb_struct = atoi(token);
- token = strsep(&psz_cur, seps);
-
- gen_obj->obj_data.proc_info.processor_family = atoi(token);
- token = strsep(&psz_cur, seps);
-
- gen_obj->obj_data.proc_info.processor_type = atoi(token);
- token = strsep(&psz_cur, seps);
-
- gen_obj->obj_data.proc_info.clock_rate = atoi(token);
- token = strsep(&psz_cur, seps);
-
- gen_obj->obj_data.proc_info.internal_mem_size = atoi(token);
- token = strsep(&psz_cur, seps);
-
- gen_obj->obj_data.proc_info.external_mem_size = atoi(token);
- token = strsep(&psz_cur, seps);
-
- gen_obj->obj_data.proc_info.processor_id = atoi(token);
- token = strsep(&psz_cur, seps);
-
- gen_obj->obj_data.proc_info.ty_running_rtos = atoi(token);
- token = strsep(&psz_cur, seps);
-
- gen_obj->obj_data.proc_info.node_min_priority = atoi(token);
- token = strsep(&psz_cur, seps);
-
- gen_obj->obj_data.proc_info.node_max_priority = atoi(token);
-
-#ifdef _DB_TIOMAP
- /* Proc object may contain additional(extended) attributes. */
- /* attr must match proc.hxx */
- for (entry_id = 0; entry_id < 7; entry_id++) {
- token = strsep(&psz_cur, seps);
- gen_obj->obj_data.ext_proc_obj.ty_tlb[entry_id].
- gpp_phys = atoi(token);
-
- token = strsep(&psz_cur, seps);
- gen_obj->obj_data.ext_proc_obj.ty_tlb[entry_id].
- dsp_virt = atoi(token);
- }
-#endif
-
- break;
-
- default:
- status = -EPERM;
- break;
- }
-
- return status;
-}
-
-/*
- * ======== CompressBuffer ========
- * Purpose:
- * Compress the DSP buffer, if necessary, to conform to PC format.
- */
-static void compress_buf(char *psz_buf, u32 ul_buf_size, s32 char_size)
-{
- char *p;
- char ch;
- char *q;
-
- p = psz_buf;
- if (p == NULL)
- return;
-
- for (q = psz_buf; q < (psz_buf + ul_buf_size);) {
- ch = dsp_char2_gpp_char(q, char_size);
- if (ch == '\\') {
- q += char_size;
- ch = dsp_char2_gpp_char(q, char_size);
- switch (ch) {
- case 't':
- *p = '\t';
- break;
-
- case 'n':
- *p = '\n';
- break;
-
- case 'r':
- *p = '\r';
- break;
-
- case '0':
- *p = '\0';
- break;
-
- default:
- *p = ch;
- break;
- }
- } else {
- *p = ch;
- }
- p++;
- q += char_size;
- }
-
- /* NULL out remainder of buffer. */
- while (p < q)
- *p++ = '\0';
-}
-
-/*
- * ======== dsp_char2_gpp_char ========
- * Purpose:
- * Convert DSP char to host GPP char in a portable manner
- */
-static char dsp_char2_gpp_char(char *word, s32 dsp_char_size)
-{
- char ch = '\0';
- char *ch_src;
- s32 i;
-
- for (ch_src = word, i = dsp_char_size; i > 0; i--)
- ch |= *ch_src++;
-
- return ch;
-}
-
-/*
- * ======== get_dep_lib_info ========
- */
-static int get_dep_lib_info(struct dcd_manager *hdcd_mgr,
- struct dsp_uuid *uuid_obj,
- u16 *num_libs,
- u16 *num_pers_libs,
- struct dsp_uuid *dep_lib_uuids,
- bool *prstnt_dep_libs,
- enum nldr_phase phase)
-{
- struct dcd_manager *dcd_mgr_obj = hdcd_mgr;
- char *psz_coff_buf = NULL;
- char *psz_cur;
- char *psz_file_name = NULL;
- struct cod_libraryobj *lib = NULL;
- u32 ul_addr = 0; /* Used by cod_get_section */
- u32 ul_len = 0; /* Used by cod_get_section */
- u32 dw_data_size = COD_MAXPATHLENGTH;
- char seps[] = ", ";
- char *token = NULL;
- bool get_uuids = (dep_lib_uuids != NULL);
- u16 dep_libs = 0;
- int status = 0;
-
- /* Initialize to 0 dependent libraries, if only counting number of
- * dependent libraries */
- if (!get_uuids) {
- *num_libs = 0;
- *num_pers_libs = 0;
- }
-
- /* Allocate a buffer for file name */
- psz_file_name = kzalloc(dw_data_size, GFP_KERNEL);
- if (psz_file_name == NULL) {
- status = -ENOMEM;
- } else {
- /* Get the name of the library */
- status = dcd_get_library_name(hdcd_mgr, uuid_obj, psz_file_name,
- &dw_data_size, phase, NULL);
- }
-
- /* Open the library */
- if (!status) {
- status = cod_open(dcd_mgr_obj->cod_mgr, psz_file_name,
- COD_NOLOAD, &lib);
- }
- if (!status) {
- /* Get dependent library section information. */
- status = cod_get_section(lib, DEPLIBSECT, &ul_addr, &ul_len);
-
- if (status) {
- /* Ok, no dependent libraries */
- ul_len = 0;
- status = 0;
- }
- }
-
- if (status || !(ul_len > 0))
- goto func_cont;
-
- /* Allocate zeroed buffer. */
- psz_coff_buf = kzalloc(ul_len + 4, GFP_KERNEL);
- if (psz_coff_buf == NULL)
- status = -ENOMEM;
-
- /* Read section contents. */
- status = cod_read_section(lib, DEPLIBSECT, psz_coff_buf, ul_len);
- if (status)
- goto func_cont;
-
- /* Compress and format DSP buffer to conform to PC format. */
- compress_buf(psz_coff_buf, ul_len, DSPWORDSIZE);
-
- /* Read from buffer */
- psz_cur = psz_coff_buf;
- while ((token = strsep(&psz_cur, seps)) && *token != '\0') {
- if (get_uuids) {
- if (dep_libs >= *num_libs) {
- /* Gone beyond the limit */
- break;
- } else {
- /* Retrieve UUID string. */
- status = dcd_uuid_from_string(token,
- &(dep_lib_uuids
- [dep_libs]));
- if (status)
- break;
-
- /* Is this library persistent? */
- token = strsep(&psz_cur, seps);
- prstnt_dep_libs[dep_libs] = atoi(token);
- dep_libs++;
- }
- } else {
- /* Advanc to next token */
- token = strsep(&psz_cur, seps);
- if (atoi(token))
- (*num_pers_libs)++;
-
- /* Just counting number of dependent libraries */
- (*num_libs)++;
- }
- }
-func_cont:
- if (lib)
- cod_close(lib);
-
- /* Free previously allocated dynamic buffers. */
- kfree(psz_file_name);
-
- kfree(psz_coff_buf);
-
- return status;
-}
diff --git a/drivers/staging/tidspbridge/rmgr/disp.c b/drivers/staging/tidspbridge/rmgr/disp.c
deleted file mode 100644
index 4af51b75aeab..000000000000
--- a/drivers/staging/tidspbridge/rmgr/disp.c
+++ /dev/null
@@ -1,655 +0,0 @@
-/*
- * disp.c
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * Node Dispatcher interface. Communicates with Resource Manager Server
- * (RMS) on DSP. Access to RMS is synchronized in NODE.
- *
- * 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>
-
-/* ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/sync.h>
-
-/* ----------------------------------- Link Driver */
-#include <dspbridge/dspdefs.h>
-
-/* ----------------------------------- Platform Manager */
-#include <dspbridge/dev.h>
-#include <dspbridge/chnldefs.h>
-
-/* ----------------------------------- Resource Manager */
-#include <dspbridge/nodedefs.h>
-#include <dspbridge/nodepriv.h>
-#include <dspbridge/rms_sh.h>
-
-/* ----------------------------------- This */
-#include <dspbridge/disp.h>
-
-/* Size of a reply from RMS */
-#define REPLYSIZE (3 * sizeof(rms_word))
-
-/* Reserved channel offsets for communication with RMS */
-#define CHNLTORMSOFFSET 0
-#define CHNLFROMRMSOFFSET 1
-
-#define CHNLIOREQS 1
-
-/*
- * ======== disp_object ========
- */
-struct disp_object {
- struct dev_object *dev_obj; /* Device for this processor */
- /* Function interface to Bridge driver */
- struct bridge_drv_interface *intf_fxns;
- struct chnl_mgr *chnl_mgr; /* Channel manager */
- struct chnl_object *chnl_to_dsp; /* Chnl for commands to RMS */
- struct chnl_object *chnl_from_dsp; /* Chnl for replies from RMS */
- u8 *buf; /* Buffer for commands, replies */
- u32 bufsize; /* buf size in bytes */
- u32 bufsize_rms; /* buf size in RMS words */
- u32 char_size; /* Size of DSP character */
- u32 word_size; /* Size of DSP word */
- u32 data_mau_size; /* Size of DSP Data MAU */
-};
-
-static void delete_disp(struct disp_object *disp_obj);
-static int fill_stream_def(rms_word *pdw_buf, u32 *ptotal, u32 offset,
- struct node_strmdef strm_def, u32 max,
- u32 chars_in_rms_word);
-static int send_message(struct disp_object *disp_obj, u32 timeout,
- u32 ul_bytes, u32 *pdw_arg);
-
-/*
- * ======== disp_create ========
- * Create a NODE Dispatcher object.
- */
-int disp_create(struct disp_object **dispatch_obj,
- struct dev_object *hdev_obj,
- const struct disp_attr *disp_attrs)
-{
- struct disp_object *disp_obj;
- struct bridge_drv_interface *intf_fxns;
- u32 ul_chnl_id;
- struct chnl_attr chnl_attr_obj;
- int status = 0;
- u8 dev_type;
-
- *dispatch_obj = NULL;
-
- /* Allocate Node Dispatcher object */
- disp_obj = kzalloc(sizeof(struct disp_object), GFP_KERNEL);
- if (disp_obj == NULL)
- status = -ENOMEM;
- else
- disp_obj->dev_obj = hdev_obj;
-
- /* Get Channel manager and Bridge function interface */
- if (!status) {
- status = dev_get_chnl_mgr(hdev_obj, &(disp_obj->chnl_mgr));
- if (!status) {
- (void)dev_get_intf_fxns(hdev_obj, &intf_fxns);
- disp_obj->intf_fxns = intf_fxns;
- }
- }
-
- /* check device type and decide if streams or messag'ing is used for
- * RMS/EDS */
- if (status)
- goto func_cont;
-
- status = dev_get_dev_type(hdev_obj, &dev_type);
-
- if (status)
- goto func_cont;
-
- if (dev_type != DSP_UNIT) {
- status = -EPERM;
- goto func_cont;
- }
-
- disp_obj->char_size = DSPWORDSIZE;
- disp_obj->word_size = DSPWORDSIZE;
- disp_obj->data_mau_size = DSPWORDSIZE;
- /* Open channels for communicating with the RMS */
- chnl_attr_obj.uio_reqs = CHNLIOREQS;
- chnl_attr_obj.event_obj = NULL;
- ul_chnl_id = disp_attrs->chnl_offset + CHNLTORMSOFFSET;
- status = (*intf_fxns->chnl_open) (&(disp_obj->chnl_to_dsp),
- disp_obj->chnl_mgr,
- CHNL_MODETODSP, ul_chnl_id,
- &chnl_attr_obj);
-
- if (!status) {
- ul_chnl_id = disp_attrs->chnl_offset + CHNLFROMRMSOFFSET;
- status =
- (*intf_fxns->chnl_open) (&(disp_obj->chnl_from_dsp),
- disp_obj->chnl_mgr,
- CHNL_MODEFROMDSP, ul_chnl_id,
- &chnl_attr_obj);
- }
- if (!status) {
- /* Allocate buffer for commands, replies */
- disp_obj->bufsize = disp_attrs->chnl_buf_size;
- disp_obj->bufsize_rms = RMS_COMMANDBUFSIZE;
- disp_obj->buf = kzalloc(disp_obj->bufsize, GFP_KERNEL);
- if (disp_obj->buf == NULL)
- status = -ENOMEM;
- }
-func_cont:
- if (!status)
- *dispatch_obj = disp_obj;
- else
- delete_disp(disp_obj);
-
- return status;
-}
-
-/*
- * ======== disp_delete ========
- * Delete the NODE Dispatcher.
- */
-void disp_delete(struct disp_object *disp_obj)
-{
- delete_disp(disp_obj);
-}
-
-/*
- * ======== disp_node_change_priority ========
- * Change the priority of a node currently running on the target.
- */
-int disp_node_change_priority(struct disp_object *disp_obj,
- struct node_object *hnode,
- u32 rms_fxn, nodeenv node_env, s32 prio)
-{
- u32 dw_arg;
- struct rms_command *rms_cmd;
- int status = 0;
-
- /* Send message to RMS to change priority */
- rms_cmd = (struct rms_command *)(disp_obj->buf);
- rms_cmd->fxn = (rms_word) (rms_fxn);
- rms_cmd->arg1 = (rms_word) node_env;
- rms_cmd->arg2 = prio;
- status = send_message(disp_obj, node_get_timeout(hnode),
- sizeof(struct rms_command), &dw_arg);
-
- return status;
-}
-
-/*
- * ======== disp_node_create ========
- * Create a node on the DSP by remotely calling the node's create function.
- */
-int disp_node_create(struct disp_object *disp_obj,
- struct node_object *hnode, u32 rms_fxn,
- u32 ul_create_fxn,
- const struct node_createargs *pargs,
- nodeenv *node_env)
-{
- struct node_msgargs node_msg_args;
- struct node_taskargs task_arg_obj;
- struct rms_command *rms_cmd;
- struct rms_msg_args *pmsg_args;
- struct rms_more_task_args *more_task_args;
- enum node_type node_type;
- u32 dw_length;
- rms_word *pdw_buf = NULL;
- u32 ul_bytes;
- u32 i;
- u32 total;
- u32 chars_in_rms_word;
- s32 task_args_offset;
- s32 sio_in_def_offset;
- s32 sio_out_def_offset;
- s32 sio_defs_offset;
- s32 args_offset = -1;
- s32 offset;
- struct node_strmdef strm_def;
- u32 max;
- int status = 0;
- struct dsp_nodeinfo node_info;
- u8 dev_type;
-
- status = dev_get_dev_type(disp_obj->dev_obj, &dev_type);
-
- if (status)
- goto func_end;
-
- if (dev_type != DSP_UNIT) {
- dev_dbg(bridge, "%s: unknown device type = 0x%x\n",
- __func__, dev_type);
- goto func_end;
- }
- node_type = node_get_type(hnode);
- node_msg_args = pargs->asa.node_msg_args;
- max = disp_obj->bufsize_rms; /*Max # of RMS words that can be sent */
- chars_in_rms_word = sizeof(rms_word) / disp_obj->char_size;
- /* Number of RMS words needed to hold arg data */
- dw_length =
- (node_msg_args.arg_length + chars_in_rms_word -
- 1) / chars_in_rms_word;
- /* Make sure msg args and command fit in buffer */
- total = sizeof(struct rms_command) / sizeof(rms_word) +
- sizeof(struct rms_msg_args)
- / sizeof(rms_word) - 1 + dw_length;
- if (total >= max) {
- status = -EPERM;
- dev_dbg(bridge, "%s: Message args too large for buffer! size "
- "= %d, max = %d\n", __func__, total, max);
- }
- /*
- * Fill in buffer to send to RMS.
- * The buffer will have the following format:
- *
- * RMS command:
- * Address of RMS_CreateNode()
- * Address of node's create function
- * dummy argument
- * node type
- *
- * Message Args:
- * max number of messages
- * segid for message buffer allocation
- * notification type to use when message is received
- * length of message arg data
- * message args data
- *
- * Task Args (if task or socket node):
- * priority
- * stack size
- * system stack size
- * stack segment
- * misc
- * number of input streams
- * pSTRMInDef[] - offsets of STRM definitions for input streams
- * number of output streams
- * pSTRMOutDef[] - offsets of STRM definitions for output
- * streams
- * STRMInDef[] - array of STRM definitions for input streams
- * STRMOutDef[] - array of STRM definitions for output streams
- *
- * Socket Args (if DAIS socket node):
- *
- */
- if (!status) {
- total = 0; /* Total number of words in buffer so far */
- pdw_buf = (rms_word *) disp_obj->buf;
- rms_cmd = (struct rms_command *)pdw_buf;
- rms_cmd->fxn = (rms_word) (rms_fxn);
- rms_cmd->arg1 = (rms_word) (ul_create_fxn);
- if (node_get_load_type(hnode) == NLDR_DYNAMICLOAD) {
- /* Flush ICACHE on Load */
- rms_cmd->arg2 = 1; /* dummy argument */
- } else {
- /* Do not flush ICACHE */
- rms_cmd->arg2 = 0; /* dummy argument */
- }
- rms_cmd->data = node_get_type(hnode);
- /*
- * args_offset is the offset of the data field in struct
- * rms_command structure. We need this to calculate stream
- * definition offsets.
- */
- args_offset = 3;
- total += sizeof(struct rms_command) / sizeof(rms_word);
- /* Message args */
- pmsg_args = (struct rms_msg_args *)(pdw_buf + total);
- pmsg_args->max_msgs = node_msg_args.max_msgs;
- pmsg_args->segid = node_msg_args.seg_id;
- pmsg_args->notify_type = node_msg_args.notify_type;
- pmsg_args->arg_length = node_msg_args.arg_length;
- total += sizeof(struct rms_msg_args) / sizeof(rms_word) - 1;
- memcpy(pdw_buf + total, node_msg_args.pdata,
- node_msg_args.arg_length);
- total += dw_length;
- }
- if (status)
- goto func_end;
-
- /* If node is a task node, copy task create arguments into buffer */
- if (node_type == NODE_TASK || node_type == NODE_DAISSOCKET) {
- task_arg_obj = pargs->asa.task_arg_obj;
- task_args_offset = total;
- total += sizeof(struct rms_more_task_args) / sizeof(rms_word) +
- 1 + task_arg_obj.num_inputs + task_arg_obj.num_outputs;
- /* Copy task arguments */
- if (total < max) {
- total = task_args_offset;
- more_task_args = (struct rms_more_task_args *)(pdw_buf +
- total);
- /*
- * Get some important info about the node. Note that we
- * don't just reach into the hnode struct because
- * that would break the node object's abstraction.
- */
- get_node_info(hnode, &node_info);
- more_task_args->priority = node_info.execution_priority;
- more_task_args->stack_size = task_arg_obj.stack_size;
- more_task_args->sysstack_size =
- task_arg_obj.sys_stack_size;
- more_task_args->stack_seg = task_arg_obj.stack_seg;
- more_task_args->heap_addr = task_arg_obj.dsp_heap_addr;
- more_task_args->heap_size = task_arg_obj.heap_size;
- more_task_args->misc = task_arg_obj.dais_arg;
- more_task_args->num_input_streams =
- task_arg_obj.num_inputs;
- total +=
- sizeof(struct rms_more_task_args) /
- sizeof(rms_word);
- dev_dbg(bridge, "%s: dsp_heap_addr %x, heap_size %x\n",
- __func__, task_arg_obj.dsp_heap_addr,
- task_arg_obj.heap_size);
- /* Keep track of pSIOInDef[] and pSIOOutDef[]
- * positions in the buffer, since this needs to be
- * filled in later. */
- sio_in_def_offset = total;
- total += task_arg_obj.num_inputs;
- pdw_buf[total++] = task_arg_obj.num_outputs;
- sio_out_def_offset = total;
- total += task_arg_obj.num_outputs;
- sio_defs_offset = total;
- /* Fill SIO defs and offsets */
- offset = sio_defs_offset;
- for (i = 0; i < task_arg_obj.num_inputs; i++) {
- if (status)
- break;
-
- pdw_buf[sio_in_def_offset + i] =
- (offset - args_offset)
- * (sizeof(rms_word) / DSPWORDSIZE);
- strm_def = task_arg_obj.strm_in_def[i];
- status =
- fill_stream_def(pdw_buf, &total, offset,
- strm_def, max,
- chars_in_rms_word);
- offset = total;
- }
- for (i = 0; (i < task_arg_obj.num_outputs) &&
- (!status); i++) {
- pdw_buf[sio_out_def_offset + i] =
- (offset - args_offset)
- * (sizeof(rms_word) / DSPWORDSIZE);
- strm_def = task_arg_obj.strm_out_def[i];
- status =
- fill_stream_def(pdw_buf, &total, offset,
- strm_def, max,
- chars_in_rms_word);
- offset = total;
- }
- } else {
- /* Args won't fit */
- status = -EPERM;
- }
- }
- if (!status) {
- ul_bytes = total * sizeof(rms_word);
- status = send_message(disp_obj, node_get_timeout(hnode),
- ul_bytes, node_env);
- }
-func_end:
- return status;
-}
-
-/*
- * ======== disp_node_delete ========
- * purpose:
- * Delete a node on the DSP by remotely calling the node's delete function.
- *
- */
-int disp_node_delete(struct disp_object *disp_obj,
- struct node_object *hnode, u32 rms_fxn,
- u32 ul_delete_fxn, nodeenv node_env)
-{
- u32 dw_arg;
- struct rms_command *rms_cmd;
- int status = 0;
- u8 dev_type;
-
- status = dev_get_dev_type(disp_obj->dev_obj, &dev_type);
-
- if (!status) {
-
- if (dev_type == DSP_UNIT) {
-
- /*
- * Fill in buffer to send to RMS
- */
- rms_cmd = (struct rms_command *)disp_obj->buf;
- rms_cmd->fxn = (rms_word) (rms_fxn);
- rms_cmd->arg1 = (rms_word) node_env;
- rms_cmd->arg2 = (rms_word) (ul_delete_fxn);
- rms_cmd->data = node_get_type(hnode);
-
- status = send_message(disp_obj, node_get_timeout(hnode),
- sizeof(struct rms_command),
- &dw_arg);
- }
- }
- return status;
-}
-
-/*
- * ======== disp_node_run ========
- * purpose:
- * Start execution of a node's execute phase, or resume execution of a node
- * that has been suspended (via DISP_NodePause()) on the DSP.
- */
-int disp_node_run(struct disp_object *disp_obj,
- struct node_object *hnode, u32 rms_fxn,
- u32 ul_execute_fxn, nodeenv node_env)
-{
- u32 dw_arg;
- struct rms_command *rms_cmd;
- int status = 0;
- u8 dev_type;
-
- status = dev_get_dev_type(disp_obj->dev_obj, &dev_type);
-
- if (!status) {
-
- if (dev_type == DSP_UNIT) {
-
- /*
- * Fill in buffer to send to RMS.
- */
- rms_cmd = (struct rms_command *)disp_obj->buf;
- rms_cmd->fxn = (rms_word) (rms_fxn);
- rms_cmd->arg1 = (rms_word) node_env;
- rms_cmd->arg2 = (rms_word) (ul_execute_fxn);
- rms_cmd->data = node_get_type(hnode);
-
- status = send_message(disp_obj, node_get_timeout(hnode),
- sizeof(struct rms_command),
- &dw_arg);
- }
- }
-
- return status;
-}
-
-/*
- * ======== delete_disp ========
- * purpose:
- * Frees the resources allocated for the dispatcher.
- */
-static void delete_disp(struct disp_object *disp_obj)
-{
- int status = 0;
- struct bridge_drv_interface *intf_fxns;
-
- if (disp_obj) {
- intf_fxns = disp_obj->intf_fxns;
-
- /* Free Node Dispatcher resources */
- if (disp_obj->chnl_from_dsp) {
- /* Channel close can fail only if the channel handle
- * is invalid. */
- status = (*intf_fxns->chnl_close)
- (disp_obj->chnl_from_dsp);
- if (status) {
- dev_dbg(bridge, "%s: Failed to close channel "
- "from RMS: 0x%x\n", __func__, status);
- }
- }
- if (disp_obj->chnl_to_dsp) {
- status =
- (*intf_fxns->chnl_close) (disp_obj->
- chnl_to_dsp);
- if (status) {
- dev_dbg(bridge, "%s: Failed to close channel to"
- " RMS: 0x%x\n", __func__, status);
- }
- }
- kfree(disp_obj->buf);
-
- kfree(disp_obj);
- }
-}
-
-/*
- * ======== fill_stream_def ========
- * purpose:
- * Fills stream definitions.
- */
-static int fill_stream_def(rms_word *pdw_buf, u32 *ptotal, u32 offset,
- struct node_strmdef strm_def, u32 max,
- u32 chars_in_rms_word)
-{
- struct rms_strm_def *strm_def_obj;
- u32 total = *ptotal;
- u32 name_len;
- u32 dw_length;
- int status = 0;
-
- if (total + sizeof(struct rms_strm_def) / sizeof(rms_word) >= max) {
- status = -EPERM;
- } else {
- strm_def_obj = (struct rms_strm_def *)(pdw_buf + total);
- strm_def_obj->bufsize = strm_def.buf_size;
- strm_def_obj->nbufs = strm_def.num_bufs;
- strm_def_obj->segid = strm_def.seg_id;
- strm_def_obj->align = strm_def.buf_alignment;
- strm_def_obj->timeout = strm_def.timeout;
- }
-
- if (!status) {
- /*
- * Since we haven't added the device name yet, subtract
- * 1 from total.
- */
- total += sizeof(struct rms_strm_def) / sizeof(rms_word) - 1;
- dw_length = strlen(strm_def.sz_device) + 1;
-
- /* Number of RMS_WORDS needed to hold device name */
- name_len =
- (dw_length + chars_in_rms_word - 1) / chars_in_rms_word;
-
- if (total + name_len >= max) {
- status = -EPERM;
- } else {
- /*
- * Zero out last word, since the device name may not
- * extend to completely fill this word.
- */
- pdw_buf[total + name_len - 1] = 0;
- /** TODO USE SERVICES * */
- memcpy(pdw_buf + total, strm_def.sz_device, dw_length);
- total += name_len;
- *ptotal = total;
- }
- }
-
- return status;
-}
-
-/*
- * ======== send_message ======
- * Send command message to RMS, get reply from RMS.
- */
-static int send_message(struct disp_object *disp_obj, u32 timeout,
- u32 ul_bytes, u32 *pdw_arg)
-{
- struct bridge_drv_interface *intf_fxns;
- struct chnl_object *chnl_obj;
- u32 dw_arg = 0;
- u8 *pbuf;
- struct chnl_ioc chnl_ioc_obj;
- int status = 0;
-
- *pdw_arg = (u32) NULL;
- intf_fxns = disp_obj->intf_fxns;
- chnl_obj = disp_obj->chnl_to_dsp;
- pbuf = disp_obj->buf;
-
- /* Send the command */
- status = (*intf_fxns->chnl_add_io_req) (chnl_obj, pbuf, ul_bytes, 0,
- 0L, dw_arg);
- if (status)
- goto func_end;
-
- status =
- (*intf_fxns->chnl_get_ioc) (chnl_obj, timeout, &chnl_ioc_obj);
- if (!status) {
- if (!CHNL_IS_IO_COMPLETE(chnl_ioc_obj)) {
- if (CHNL_IS_TIMED_OUT(chnl_ioc_obj))
- status = -ETIME;
- else
- status = -EPERM;
- }
- }
- /* Get the reply */
- if (status)
- goto func_end;
-
- chnl_obj = disp_obj->chnl_from_dsp;
- ul_bytes = REPLYSIZE;
- status = (*intf_fxns->chnl_add_io_req) (chnl_obj, pbuf, ul_bytes,
- 0, 0L, dw_arg);
- if (status)
- goto func_end;
-
- status =
- (*intf_fxns->chnl_get_ioc) (chnl_obj, timeout, &chnl_ioc_obj);
- if (!status) {
- if (CHNL_IS_TIMED_OUT(chnl_ioc_obj)) {
- status = -ETIME;
- } else if (chnl_ioc_obj.byte_size < ul_bytes) {
- /* Did not get all of the reply from the RMS */
- status = -EPERM;
- } else {
- if (CHNL_IS_IO_COMPLETE(chnl_ioc_obj)) {
- if (*((int *)chnl_ioc_obj.buf) < 0) {
- /* Translate DSP's to kernel error */
- status = -EREMOTEIO;
- dev_dbg(bridge, "%s: DSP-side failed:"
- " DSP errcode = 0x%x, Kernel "
- "errcode = %d\n", __func__,
- *(int *)pbuf, status);
- }
- *pdw_arg =
- (((rms_word *) (chnl_ioc_obj.buf))[1]);
- } else {
- status = -EPERM;
- }
- }
- }
-func_end:
- return status;
-}
diff --git a/drivers/staging/tidspbridge/rmgr/drv.c b/drivers/staging/tidspbridge/rmgr/drv.c
deleted file mode 100644
index 757ae20b38ee..000000000000
--- a/drivers/staging/tidspbridge/rmgr/drv.c
+++ /dev/null
@@ -1,816 +0,0 @@
-/*
- * drv.c
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * DSP/BIOS Bridge resource allocation module.
- *
- * 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 <linux/list.h>
-
-/* ----------------------------------- Host OS */
-#include <dspbridge/host_os.h>
-
-/* ----------------------------------- DSP/BIOS Bridge */
-#include <dspbridge/dbdefs.h>
-
-/* ----------------------------------- This */
-#include <dspbridge/drv.h>
-#include <dspbridge/dev.h>
-
-#include <dspbridge/node.h>
-#include <dspbridge/proc.h>
-#include <dspbridge/strm.h>
-#include <dspbridge/nodepriv.h>
-#include <dspbridge/dspchnl.h>
-#include <dspbridge/resourcecleanup.h>
-
-/* ----------------------------------- Defines, Data Structures, Typedefs */
-struct drv_object {
- struct list_head dev_list;
- struct list_head dev_node_string;
-};
-
-/*
- * This is the Device Extension. Named with the Prefix
- * DRV_ since it is living in this module
- */
-struct drv_ext {
- struct list_head link;
- char sz_string[MAXREGPATHLENGTH];
-};
-
-/* ----------------------------------- Globals */
-static bool ext_phys_mem_pool_enabled;
-struct ext_phys_mem_pool {
- u32 phys_mem_base;
- u32 phys_mem_size;
- u32 virt_mem_base;
- u32 next_phys_alloc_ptr;
-};
-static struct ext_phys_mem_pool ext_mem_pool;
-
-/* ----------------------------------- Function Prototypes */
-static int request_bridge_resources(struct cfg_hostres *res);
-
-
-/* GPP PROCESS CLEANUP CODE */
-
-static int drv_proc_free_node_res(int id, void *p, void *data);
-
-/* Allocate and add a node resource element
-* This function is called from .Node_Allocate. */
-int drv_insert_node_res_element(void *hnode, void *node_resource,
- void *process_ctxt)
-{
- struct node_res_object **node_res_obj =
- (struct node_res_object **)node_resource;
- struct process_context *ctxt = (struct process_context *)process_ctxt;
- int retval;
-
- *node_res_obj = kzalloc(sizeof(struct node_res_object), GFP_KERNEL);
- if (!*node_res_obj)
- return -ENOMEM;
-
- (*node_res_obj)->node = hnode;
- retval = idr_alloc(ctxt->node_id, *node_res_obj, 0, 0, GFP_KERNEL);
- if (retval >= 0) {
- (*node_res_obj)->id = retval;
- return 0;
- }
-
- kfree(*node_res_obj);
-
- if (retval == -ENOSPC) {
- pr_err("%s: FAILED, IDR is FULL\n", __func__);
- return -EFAULT;
- } else {
- pr_err("%s: OUT OF MEMORY\n", __func__);
- return -ENOMEM;
- }
-}
-
-/* Release all Node resources and its context
- * Actual Node De-Allocation */
-static int drv_proc_free_node_res(int id, void *p, void *data)
-{
- struct process_context *ctxt = data;
- int status;
- struct node_res_object *node_res_obj = p;
- u32 node_state;
-
- if (node_res_obj->node_allocated) {
- node_state = node_get_state(node_res_obj->node);
- if (node_state <= NODE_DELETING) {
- if ((node_state == NODE_RUNNING) ||
- (node_state == NODE_PAUSED) ||
- (node_state == NODE_TERMINATING))
- node_terminate
- (node_res_obj->node, &status);
-
- node_delete(node_res_obj, ctxt);
- }
- }
-
- return 0;
-}
-
-/* Release all Mapped and Reserved DMM resources */
-int drv_remove_all_dmm_res_elements(void *process_ctxt)
-{
- struct process_context *ctxt = (struct process_context *)process_ctxt;
- int status = 0;
- struct dmm_map_object *temp_map, *map_obj;
- struct dmm_rsv_object *temp_rsv, *rsv_obj;
-
- /* Free DMM mapped memory resources */
- list_for_each_entry_safe(map_obj, temp_map, &ctxt->dmm_map_list, link) {
- status = proc_un_map(ctxt->processor,
- (void *)map_obj->dsp_addr, ctxt);
- if (status)
- pr_err("%s: proc_un_map failed!"
- " status = 0x%xn", __func__, status);
- }
-
- /* Free DMM reserved memory resources */
- list_for_each_entry_safe(rsv_obj, temp_rsv, &ctxt->dmm_rsv_list, link) {
- status = proc_un_reserve_memory(ctxt->processor, (void *)
- rsv_obj->dsp_reserved_addr,
- ctxt);
- if (status)
- pr_err("%s: proc_un_reserve_memory failed!"
- " status = 0x%xn", __func__, status);
- }
- return status;
-}
-
-/* Update Node allocation status */
-void drv_proc_node_update_status(void *node_resource, s32 status)
-{
- struct node_res_object *node_res_obj =
- (struct node_res_object *)node_resource;
- node_res_obj->node_allocated = status;
-}
-
-/* Update Node Heap status */
-void drv_proc_node_update_heap_status(void *node_resource, s32 status)
-{
- struct node_res_object *node_res_obj =
- (struct node_res_object *)node_resource;
- node_res_obj->heap_allocated = status;
-}
-
-/* Release all Node resources and its context
-* This is called from .bridge_release.
- */
-int drv_remove_all_node_res_elements(void *process_ctxt)
-{
- struct process_context *ctxt = process_ctxt;
-
- idr_for_each(ctxt->node_id, drv_proc_free_node_res, ctxt);
- idr_destroy(ctxt->node_id);
-
- return 0;
-}
-
-/* Allocate the STRM resource element
-* This is called after the actual resource is allocated
- */
-int drv_proc_insert_strm_res_element(void *stream_obj,
- void *strm_res, void *process_ctxt)
-{
- struct strm_res_object **pstrm_res =
- (struct strm_res_object **)strm_res;
- struct process_context *ctxt = (struct process_context *)process_ctxt;
- int retval;
-
- *pstrm_res = kzalloc(sizeof(struct strm_res_object), GFP_KERNEL);
- if (*pstrm_res == NULL)
- return -EFAULT;
-
- (*pstrm_res)->stream = stream_obj;
- retval = idr_alloc(ctxt->stream_id, *pstrm_res, 0, 0, GFP_KERNEL);
- if (retval >= 0) {
- (*pstrm_res)->id = retval;
- return 0;
- }
-
- if (retval == -ENOSPC) {
- pr_err("%s: FAILED, IDR is FULL\n", __func__);
- return -EPERM;
- } else {
- pr_err("%s: OUT OF MEMORY\n", __func__);
- return -ENOMEM;
- }
-}
-
-static int drv_proc_free_strm_res(int id, void *p, void *process_ctxt)
-{
- struct process_context *ctxt = process_ctxt;
- struct strm_res_object *strm_res = p;
- struct stream_info strm_info;
- struct dsp_streaminfo user;
- u8 **ap_buffer = NULL;
- u8 *buf_ptr;
- u32 ul_bytes;
- u32 dw_arg;
- s32 ul_buf_size;
-
- if (strm_res->num_bufs) {
- ap_buffer = kmalloc((strm_res->num_bufs *
- sizeof(u8 *)), GFP_KERNEL);
- if (ap_buffer) {
- strm_free_buffer(strm_res,
- ap_buffer,
- strm_res->num_bufs,
- ctxt);
- kfree(ap_buffer);
- }
- }
- strm_info.user_strm = &user;
- user.number_bufs_in_stream = 0;
- strm_get_info(strm_res->stream, &strm_info, sizeof(strm_info));
- while (user.number_bufs_in_stream--)
- strm_reclaim(strm_res->stream, &buf_ptr, &ul_bytes,
- (u32 *) &ul_buf_size, &dw_arg);
- strm_close(strm_res, ctxt);
- return 0;
-}
-
-/* Release all Stream resources and its context
-* This is called from .bridge_release.
- */
-int drv_remove_all_strm_res_elements(void *process_ctxt)
-{
- struct process_context *ctxt = process_ctxt;
-
- idr_for_each(ctxt->stream_id, drv_proc_free_strm_res, ctxt);
- idr_destroy(ctxt->stream_id);
-
- return 0;
-}
-
-/* Updating the stream resource element */
-int drv_proc_update_strm_res(u32 num_bufs, void *strm_resources)
-{
- int status = 0;
- struct strm_res_object **strm_res =
- (struct strm_res_object **)strm_resources;
-
- (*strm_res)->num_bufs = num_bufs;
- return status;
-}
-
-/* GPP PROCESS CLEANUP CODE END */
-
-/*
- * ======== = drv_create ======== =
- * Purpose:
- * DRV Object gets created only once during Driver Loading.
- */
-int drv_create(struct drv_object **drv_obj)
-{
- int status = 0;
- struct drv_object *pdrv_object = NULL;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
-
- pdrv_object = kzalloc(sizeof(struct drv_object), GFP_KERNEL);
- if (pdrv_object) {
- /* Create and Initialize List of device objects */
- INIT_LIST_HEAD(&pdrv_object->dev_list);
- INIT_LIST_HEAD(&pdrv_object->dev_node_string);
- } else {
- status = -ENOMEM;
- }
- /* Store the DRV Object in the driver data */
- if (!status) {
- if (drv_datap) {
- drv_datap->drv_object = (void *)pdrv_object;
- } else {
- status = -EPERM;
- pr_err("%s: Failed to store DRV object\n", __func__);
- }
- }
-
- if (!status) {
- *drv_obj = pdrv_object;
- } else {
- /* Free the DRV Object */
- kfree(pdrv_object);
- }
-
- return status;
-}
-
-/*
- * ======== = drv_destroy ======== =
- * purpose:
- * Invoked during bridge de-initialization
- */
-int drv_destroy(struct drv_object *driver_obj)
-{
- int status = 0;
- struct drv_object *pdrv_object = (struct drv_object *)driver_obj;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
-
- kfree(pdrv_object);
- /* Update the DRV Object in the driver data */
- if (drv_datap) {
- drv_datap->drv_object = NULL;
- } else {
- status = -EPERM;
- pr_err("%s: Failed to store DRV object\n", __func__);
- }
-
- return status;
-}
-
-/*
- * ======== drv_get_dev_object ========
- * Purpose:
- * Given a index, returns a handle to DevObject from the list.
- */
-int drv_get_dev_object(u32 index, struct drv_object *hdrv_obj,
- struct dev_object **device_obj)
-{
- int status = 0;
- struct dev_object *dev_obj;
- u32 i;
-
- dev_obj = (struct dev_object *)drv_get_first_dev_object();
- for (i = 0; i < index; i++) {
- dev_obj =
- (struct dev_object *)drv_get_next_dev_object((u32) dev_obj);
- }
- if (dev_obj) {
- *device_obj = (struct dev_object *)dev_obj;
- } else {
- *device_obj = NULL;
- status = -EPERM;
- }
-
- return status;
-}
-
-/*
- * ======== drv_get_first_dev_object ========
- * Purpose:
- * Retrieve the first Device Object handle from an internal linked list of
- * of DEV_OBJECTs maintained by DRV.
- */
-u32 drv_get_first_dev_object(void)
-{
- u32 dw_dev_object = 0;
- struct drv_object *pdrv_obj;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
-
- if (drv_datap && drv_datap->drv_object) {
- pdrv_obj = drv_datap->drv_object;
- if (!list_empty(&pdrv_obj->dev_list))
- dw_dev_object = (u32) pdrv_obj->dev_list.next;
- } else {
- pr_err("%s: Failed to retrieve the object handle\n", __func__);
- }
-
- return dw_dev_object;
-}
-
-/*
- * ======== DRV_GetFirstDevNodeString ========
- * Purpose:
- * Retrieve the first Device Extension from an internal linked list of
- * of Pointer to dev_node Strings maintained by DRV.
- */
-u32 drv_get_first_dev_extension(void)
-{
- u32 dw_dev_extension = 0;
- struct drv_object *pdrv_obj;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
-
- if (drv_datap && drv_datap->drv_object) {
- pdrv_obj = drv_datap->drv_object;
- if (!list_empty(&pdrv_obj->dev_node_string)) {
- dw_dev_extension =
- (u32) pdrv_obj->dev_node_string.next;
- }
- } else {
- pr_err("%s: Failed to retrieve the object handle\n", __func__);
- }
-
- return dw_dev_extension;
-}
-
-/*
- * ======== drv_get_next_dev_object ========
- * Purpose:
- * Retrieve the next Device Object handle from an internal linked list of
- * of DEV_OBJECTs maintained by DRV, after having previously called
- * drv_get_first_dev_object() and zero or more DRV_GetNext.
- */
-u32 drv_get_next_dev_object(u32 hdev_obj)
-{
- u32 dw_next_dev_object = 0;
- struct drv_object *pdrv_obj;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
- struct list_head *curr;
-
- if (drv_datap && drv_datap->drv_object) {
- pdrv_obj = drv_datap->drv_object;
- if (!list_empty(&pdrv_obj->dev_list)) {
- curr = (struct list_head *)hdev_obj;
- if (list_is_last(curr, &pdrv_obj->dev_list))
- return 0;
- dw_next_dev_object = (u32) curr->next;
- }
- } else {
- pr_err("%s: Failed to retrieve the object handle\n", __func__);
- }
-
- return dw_next_dev_object;
-}
-
-/*
- * ======== drv_get_next_dev_extension ========
- * Purpose:
- * Retrieve the next Device Extension from an internal linked list of
- * of pointer to DevNodeString maintained by DRV, after having previously
- * called drv_get_first_dev_extension() and zero or more
- * drv_get_next_dev_extension().
- */
-u32 drv_get_next_dev_extension(u32 dev_extension)
-{
- u32 dw_dev_extension = 0;
- struct drv_object *pdrv_obj;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
- struct list_head *curr;
-
- if (drv_datap && drv_datap->drv_object) {
- pdrv_obj = drv_datap->drv_object;
- if (!list_empty(&pdrv_obj->dev_node_string)) {
- curr = (struct list_head *)dev_extension;
- if (list_is_last(curr, &pdrv_obj->dev_node_string))
- return 0;
- dw_dev_extension = (u32) curr->next;
- }
- } else {
- pr_err("%s: Failed to retrieve the object handle\n", __func__);
- }
-
- return dw_dev_extension;
-}
-
-/*
- * ======== drv_insert_dev_object ========
- * Purpose:
- * Insert a DevObject into the list of Manager object.
- */
-int drv_insert_dev_object(struct drv_object *driver_obj,
- struct dev_object *hdev_obj)
-{
- struct drv_object *pdrv_object = (struct drv_object *)driver_obj;
-
- list_add_tail((struct list_head *)hdev_obj, &pdrv_object->dev_list);
-
- return 0;
-}
-
-/*
- * ======== drv_remove_dev_object ========
- * Purpose:
- * Search for and remove a DeviceObject from the given list of DRV
- * objects.
- */
-int drv_remove_dev_object(struct drv_object *driver_obj,
- struct dev_object *hdev_obj)
-{
- int status = -EPERM;
- struct drv_object *pdrv_object = (struct drv_object *)driver_obj;
- struct list_head *cur_elem;
-
- /* Search list for p_proc_object: */
- list_for_each(cur_elem, &pdrv_object->dev_list) {
- /* If found, remove it. */
- if ((struct dev_object *)cur_elem == hdev_obj) {
- list_del(cur_elem);
- status = 0;
- break;
- }
- }
-
- return status;
-}
-
-/*
- * ======== drv_request_resources ========
- * Purpose:
- * Requests resources from the OS.
- */
-int drv_request_resources(u32 dw_context, u32 *dev_node_strg)
-{
- int status = 0;
- struct drv_object *pdrv_object;
- struct drv_ext *pszdev_node;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
-
- /*
- * Allocate memory to hold the string. This will live until
- * it is freed in the Release resources. Update the driver object
- * list.
- */
-
- if (!drv_datap || !drv_datap->drv_object)
- status = -ENODATA;
- else
- pdrv_object = drv_datap->drv_object;
-
- if (!status) {
- pszdev_node = kzalloc(sizeof(struct drv_ext), GFP_KERNEL);
- if (pszdev_node) {
- strncpy(pszdev_node->sz_string,
- (char *)dw_context, MAXREGPATHLENGTH - 1);
- pszdev_node->sz_string[MAXREGPATHLENGTH - 1] = '\0';
- /* Update the Driver Object List */
- *dev_node_strg = (u32) pszdev_node->sz_string;
- list_add_tail(&pszdev_node->link,
- &pdrv_object->dev_node_string);
- } else {
- status = -ENOMEM;
- *dev_node_strg = 0;
- }
- } else {
- dev_dbg(bridge, "%s: Failed to get Driver Object from Registry",
- __func__);
- *dev_node_strg = 0;
- }
-
- return status;
-}
-
-/*
- * ======== drv_release_resources ========
- * Purpose:
- * Releases resources from the OS.
- */
-int drv_release_resources(u32 dw_context, struct drv_object *hdrv_obj)
-{
- int status = 0;
- struct drv_ext *pszdev_node;
-
- /*
- * Irrespective of the status go ahead and clean it
- * The following will over write the status.
- */
- for (pszdev_node = (struct drv_ext *)drv_get_first_dev_extension();
- pszdev_node != NULL; pszdev_node = (struct drv_ext *)
- drv_get_next_dev_extension((u32) pszdev_node)) {
- if ((u32) pszdev_node == dw_context) {
- /* Found it */
- /* Delete from the Driver object list */
- list_del(&pszdev_node->link);
- kfree(pszdev_node);
- break;
- }
- }
- return status;
-}
-
-/*
- * ======== request_bridge_resources ========
- * Purpose:
- * Reserves shared memory for bridge.
- */
-static int request_bridge_resources(struct cfg_hostres *res)
-{
- struct cfg_hostres *host_res = res;
-
- /* num_mem_windows must not be more than CFG_MAXMEMREGISTERS */
- host_res->num_mem_windows = 2;
-
- /* First window is for DSP internal memory */
- dev_dbg(bridge, "mem_base[0] 0x%x\n", host_res->mem_base[0]);
- dev_dbg(bridge, "mem_base[3] 0x%x\n", host_res->mem_base[3]);
- dev_dbg(bridge, "dmmu_base %p\n", host_res->dmmu_base);
-
- /* for 24xx base port is not mapping the mamory for DSP
- * internal memory TODO Do a ioremap here */
- /* Second window is for DSP external memory shared with MPU */
-
- /* These are hard-coded values */
- host_res->birq_registers = 0;
- host_res->birq_attrib = 0;
- host_res->offset_for_monitor = 0;
- host_res->chnl_offset = 0;
- /* CHNL_MAXCHANNELS */
- host_res->num_chnls = CHNL_MAXCHANNELS;
- host_res->chnl_buf_size = 0x400;
-
- return 0;
-}
-
-/*
- * ======== drv_request_bridge_res_dsp ========
- * Purpose:
- * Reserves shared memory for bridge.
- */
-int drv_request_bridge_res_dsp(void **phost_resources)
-{
- int status = 0;
- struct cfg_hostres *host_res;
- u32 dw_buff_size;
- u32 dma_addr;
- u32 shm_size;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
-
- dw_buff_size = sizeof(struct cfg_hostres);
-
- host_res = kzalloc(dw_buff_size, GFP_KERNEL);
-
- if (host_res != NULL) {
- request_bridge_resources(host_res);
- /* num_mem_windows must not be more than CFG_MAXMEMREGISTERS */
- host_res->num_mem_windows = 4;
-
- host_res->mem_base[0] = 0;
- host_res->mem_base[2] = (u32) ioremap(OMAP_DSP_MEM1_BASE,
- OMAP_DSP_MEM1_SIZE);
- host_res->mem_base[3] = (u32) ioremap(OMAP_DSP_MEM2_BASE,
- OMAP_DSP_MEM2_SIZE);
- host_res->mem_base[4] = (u32) ioremap(OMAP_DSP_MEM3_BASE,
- OMAP_DSP_MEM3_SIZE);
- host_res->per_base = ioremap(OMAP_PER_CM_BASE,
- OMAP_PER_CM_SIZE);
- host_res->per_pm_base = ioremap(OMAP_PER_PRM_BASE,
- OMAP_PER_PRM_SIZE);
- host_res->core_pm_base = ioremap(OMAP_CORE_PRM_BASE,
- OMAP_CORE_PRM_SIZE);
- host_res->dmmu_base = ioremap(OMAP_DMMU_BASE,
- OMAP_DMMU_SIZE);
-
- dev_dbg(bridge, "mem_base[0] 0x%x\n",
- host_res->mem_base[0]);
- dev_dbg(bridge, "mem_base[1] 0x%x\n",
- host_res->mem_base[1]);
- dev_dbg(bridge, "mem_base[2] 0x%x\n",
- host_res->mem_base[2]);
- dev_dbg(bridge, "mem_base[3] 0x%x\n",
- host_res->mem_base[3]);
- dev_dbg(bridge, "mem_base[4] 0x%x\n",
- host_res->mem_base[4]);
- dev_dbg(bridge, "dmmu_base %p\n", host_res->dmmu_base);
-
- shm_size = drv_datap->shm_size;
- if (shm_size >= 0x10000) {
- /* Allocate Physically contiguous,
- * non-cacheable memory */
- host_res->mem_base[1] =
- (u32) mem_alloc_phys_mem(shm_size, 0x100000,
- &dma_addr);
- if (host_res->mem_base[1] == 0) {
- status = -ENOMEM;
- pr_err("shm reservation Failed\n");
- } else {
- host_res->mem_length[1] = shm_size;
- host_res->mem_phys[1] = dma_addr;
-
- dev_dbg(bridge, "%s: Bridge shm address 0x%x "
- "dma_addr %x size %x\n", __func__,
- host_res->mem_base[1],
- dma_addr, shm_size);
- }
- }
- if (!status) {
- /* These are hard-coded values */
- host_res->birq_registers = 0;
- host_res->birq_attrib = 0;
- host_res->offset_for_monitor = 0;
- host_res->chnl_offset = 0;
- /* CHNL_MAXCHANNELS */
- host_res->num_chnls = CHNL_MAXCHANNELS;
- host_res->chnl_buf_size = 0x400;
- dw_buff_size = sizeof(struct cfg_hostres);
- }
- *phost_resources = host_res;
- }
- /* End Mem alloc */
- return status;
-}
-
-void mem_ext_phys_pool_init(u32 pool_phys_base, u32 pool_size)
-{
- u32 pool_virt_base;
-
- /* get the virtual address for the physical memory pool passed */
- pool_virt_base = (u32) ioremap(pool_phys_base, pool_size);
-
- if ((void **)pool_virt_base == NULL) {
- pr_err("%s: external physical memory map failed\n", __func__);
- ext_phys_mem_pool_enabled = false;
- } else {
- ext_mem_pool.phys_mem_base = pool_phys_base;
- ext_mem_pool.phys_mem_size = pool_size;
- ext_mem_pool.virt_mem_base = pool_virt_base;
- ext_mem_pool.next_phys_alloc_ptr = pool_phys_base;
- ext_phys_mem_pool_enabled = true;
- }
-}
-
-void mem_ext_phys_pool_release(void)
-{
- if (ext_phys_mem_pool_enabled) {
- iounmap((void *)(ext_mem_pool.virt_mem_base));
- ext_phys_mem_pool_enabled = false;
- }
-}
-
-/*
- * ======== mem_ext_phys_mem_alloc ========
- * Purpose:
- * Allocate physically contiguous, uncached memory from external memory pool
- */
-
-static void *mem_ext_phys_mem_alloc(u32 bytes, u32 align, u32 *phys_addr)
-{
- u32 new_alloc_ptr;
- u32 offset;
- u32 virt_addr;
-
- if (align == 0)
- align = 1;
-
- if (bytes > ((ext_mem_pool.phys_mem_base + ext_mem_pool.phys_mem_size)
- - ext_mem_pool.next_phys_alloc_ptr)) {
- phys_addr = NULL;
- return NULL;
- } else {
- offset = (ext_mem_pool.next_phys_alloc_ptr & (align - 1));
- if (offset == 0)
- new_alloc_ptr = ext_mem_pool.next_phys_alloc_ptr;
- else
- new_alloc_ptr = (ext_mem_pool.next_phys_alloc_ptr) +
- (align - offset);
- if ((new_alloc_ptr + bytes) <=
- (ext_mem_pool.phys_mem_base + ext_mem_pool.phys_mem_size)) {
- /* we can allocate */
- *phys_addr = new_alloc_ptr;
- ext_mem_pool.next_phys_alloc_ptr =
- new_alloc_ptr + bytes;
- virt_addr =
- ext_mem_pool.virt_mem_base + (new_alloc_ptr -
- ext_mem_pool.
- phys_mem_base);
- return (void *)virt_addr;
- } else {
- *phys_addr = 0;
- return NULL;
- }
- }
-}
-
-/*
- * ======== mem_alloc_phys_mem ========
- * Purpose:
- * Allocate physically contiguous, uncached memory
- */
-void *mem_alloc_phys_mem(u32 byte_size, u32 align_mask,
- u32 *physical_address)
-{
- void *va_mem = NULL;
- dma_addr_t pa_mem;
-
- if (byte_size > 0) {
- if (ext_phys_mem_pool_enabled) {
- va_mem = mem_ext_phys_mem_alloc(byte_size, align_mask,
- (u32 *) &pa_mem);
- } else
- va_mem = dma_alloc_coherent(NULL, byte_size, &pa_mem,
- GFP_KERNEL);
- if (va_mem == NULL)
- *physical_address = 0;
- else
- *physical_address = pa_mem;
- }
- return va_mem;
-}
-
-/*
- * ======== mem_free_phys_mem ========
- * Purpose:
- * Free the given block of physically contiguous memory.
- */
-void mem_free_phys_mem(void *virtual_address, u32 physical_address,
- u32 byte_size)
-{
- if (!ext_phys_mem_pool_enabled)
- dma_free_coherent(NULL, byte_size, virtual_address,
- physical_address);
-}
diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c
deleted file mode 100644
index e3918d2efa17..000000000000
--- a/drivers/staging/tidspbridge/rmgr/drv_interface.c
+++ /dev/null
@@ -1,650 +0,0 @@
-/*
- * drv_interface.c
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * DSP/BIOS Bridge driver interface.
- *
- * 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/platform_data/dsp-omap.h>
-
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/pm.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/moduleparam.h>
-#include <linux/cdev.h>
-
-/* ----------------------------------- DSP/BIOS Bridge */
-#include <dspbridge/dbdefs.h>
-
-/* ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/clk.h>
-
-/* ----------------------------------- Platform Manager */
-#include <dspbridge/dspapi.h>
-#include <dspbridge/dspdrv.h>
-
-/* ----------------------------------- Resource Manager */
-#include <dspbridge/pwr.h>
-
-#include <dspbridge/resourcecleanup.h>
-#include <dspbridge/proc.h>
-#include <dspbridge/dev.h>
-
-#ifdef CONFIG_TIDSPBRIDGE_DVFS
-#include <mach-omap2/omap3-opp.h>
-#endif
-
-/* ----------------------------------- Globals */
-#define DSPBRIDGE_VERSION "0.3"
-s32 dsp_debug;
-
-struct platform_device *omap_dspbridge_dev;
-struct device *bridge;
-
-/* This is a test variable used by Bridge to test different sleep states */
-s32 dsp_test_sleepstate;
-
-static struct cdev bridge_cdev;
-
-static struct class *bridge_class;
-
-static u32 driver_context;
-static s32 driver_major;
-static char *base_img;
-static s32 shm_size = 0x500000; /* 5 MB */
-static int tc_wordswapon; /* Default value is always false */
-#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
-#define REC_TIMEOUT 5000 /*recovery timeout in msecs */
-static atomic_t bridge_cref; /* number of bridge open handles */
-static struct workqueue_struct *bridge_rec_queue;
-static struct work_struct bridge_recovery_work;
-static DECLARE_COMPLETION(bridge_comp);
-static DECLARE_COMPLETION(bridge_open_comp);
-static bool recover;
-#endif
-
-#ifdef CONFIG_PM
-struct omap34_xx_bridge_suspend_data {
- int suspended;
- wait_queue_head_t suspend_wq;
-};
-
-static struct omap34_xx_bridge_suspend_data bridge_suspend_data;
-
-static int omap34_xxbridge_suspend_lockout(struct omap34_xx_bridge_suspend_data
- *s, struct file *f)
-{
- if ((s)->suspended) {
- if ((f)->f_flags & O_NONBLOCK)
- return -EPERM;
- wait_event_interruptible((s)->suspend_wq, (s)->suspended == 0);
- }
- return 0;
-}
-#endif
-
-module_param(dsp_debug, int, 0);
-MODULE_PARM_DESC(dsp_debug, "Wait after loading DSP image. default = false");
-
-module_param(dsp_test_sleepstate, int, 0);
-MODULE_PARM_DESC(dsp_test_sleepstate, "DSP Sleep state = 0");
-
-module_param(base_img, charp, 0);
-MODULE_PARM_DESC(base_img, "DSP base image, default = NULL");
-
-module_param(shm_size, int, 0);
-MODULE_PARM_DESC(shm_size, "shm size, default = 4 MB, minimum = 64 KB");
-
-module_param(tc_wordswapon, int, 0);
-MODULE_PARM_DESC(tc_wordswapon, "TC Word Swap Option. default = 0");
-
-MODULE_AUTHOR("Texas Instruments");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DSPBRIDGE_VERSION);
-
-/*
- * This function is called when an application opens handle to the
- * bridge driver.
- */
-static int bridge_open(struct inode *ip, struct file *filp)
-{
- int status = 0;
- struct process_context *pr_ctxt = NULL;
-
- /*
- * Allocate a new process context and insert it into global
- * process context list.
- */
-
-#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
- if (recover) {
- if (filp->f_flags & O_NONBLOCK ||
- wait_for_completion_interruptible(&bridge_open_comp))
- return -EBUSY;
- }
-#endif
- pr_ctxt = kzalloc(sizeof(struct process_context), GFP_KERNEL);
- if (!pr_ctxt)
- return -ENOMEM;
-
- pr_ctxt->res_state = PROC_RES_ALLOCATED;
- spin_lock_init(&pr_ctxt->dmm_map_lock);
- INIT_LIST_HEAD(&pr_ctxt->dmm_map_list);
- spin_lock_init(&pr_ctxt->dmm_rsv_lock);
- INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list);
-
- pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
- if (!pr_ctxt->node_id) {
- status = -ENOMEM;
- goto err1;
- }
-
- idr_init(pr_ctxt->node_id);
-
- pr_ctxt->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
- if (!pr_ctxt->stream_id) {
- status = -ENOMEM;
- goto err2;
- }
-
- idr_init(pr_ctxt->stream_id);
-
- filp->private_data = pr_ctxt;
-
-#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
- atomic_inc(&bridge_cref);
-#endif
- return 0;
-
-err2:
- kfree(pr_ctxt->node_id);
-err1:
- kfree(pr_ctxt);
- return status;
-}
-
-/*
- * This function is called when an application closes handle to the bridge
- * driver.
- */
-static int bridge_release(struct inode *ip, struct file *filp)
-{
- int status = 0;
- struct process_context *pr_ctxt;
-
- if (!filp->private_data) {
- status = -EIO;
- goto err;
- }
-
- pr_ctxt = filp->private_data;
- flush_signals(current);
- drv_remove_all_resources(pr_ctxt);
- proc_detach(pr_ctxt);
- kfree(pr_ctxt->node_id);
- kfree(pr_ctxt->stream_id);
- kfree(pr_ctxt);
-
- filp->private_data = NULL;
-
-err:
-#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
- if (!atomic_dec_return(&bridge_cref))
- complete(&bridge_comp);
-#endif
- return status;
-}
-
-/* This function provides IO interface to the bridge driver. */
-static long bridge_ioctl(struct file *filp, unsigned int code,
- unsigned long args)
-{
- int status;
- u32 retval = 0;
- union trapped_args buf_in;
-
-#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
- if (recover) {
- status = -EIO;
- goto err;
- }
-#endif
-#ifdef CONFIG_PM
- status = omap34_xxbridge_suspend_lockout(&bridge_suspend_data, filp);
- if (status != 0)
- return status;
-#endif
-
- if (!filp->private_data) {
- status = -EIO;
- goto err;
- }
-
- status = copy_from_user(&buf_in, (union trapped_args *)args,
- sizeof(union trapped_args));
-
- if (!status) {
- status = api_call_dev_ioctl(code, &buf_in, &retval,
- filp->private_data);
-
- if (!status) {
- status = retval;
- } else {
- dev_dbg(bridge, "%s: IOCTL Failed, code: 0x%x "
- "status 0x%x\n", __func__, code, status);
- status = -1;
- }
-
- }
-
-err:
- return status;
-}
-
-/* This function maps kernel space memory to user space memory. */
-static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- unsigned long base_pgoff;
- int status;
- struct omap_dsp_platform_data *pdata =
- omap_dspbridge_dev->dev.platform_data;
-
- /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- dev_dbg(bridge, "%s: vm filp %p start %lx end %lx page_prot %ulx "
- "flags %lx\n", __func__, filp,
- vma->vm_start, vma->vm_end, vma->vm_page_prot,
- vma->vm_flags);
-
- /*
- * vm_iomap_memory() expects vma->vm_pgoff to be expressed as an offset
- * from the start of the physical memory pool, but we're called with
- * a pfn (physical page number) stored there instead.
- *
- * To avoid duplicating lots of tricky overflow checking logic,
- * temporarily convert vma->vm_pgoff to the offset vm_iomap_memory()
- * expects, but restore the original value once the mapping has been
- * created.
- */
- base_pgoff = pdata->phys_mempool_base >> PAGE_SHIFT;
-
- if (vma->vm_pgoff < base_pgoff)
- return -EINVAL;
-
- vma->vm_pgoff -= base_pgoff;
-
- status = vm_iomap_memory(vma,
- pdata->phys_mempool_base,
- pdata->phys_mempool_size);
-
- /* Restore the original value of vma->vm_pgoff */
- vma->vm_pgoff += base_pgoff;
-
- return status;
-}
-
-static const struct file_operations bridge_fops = {
- .open = bridge_open,
- .release = bridge_release,
- .unlocked_ioctl = bridge_ioctl,
- .mmap = bridge_mmap,
- .llseek = noop_llseek,
-};
-
-#ifdef CONFIG_PM
-static u32 time_out = 1000;
-#ifdef CONFIG_TIDSPBRIDGE_DVFS
-s32 dsp_max_opps = VDD1_OPP5;
-#endif
-
-/* Maximum Opps that can be requested by IVA */
-/*vdd1 rate table */
-#ifdef CONFIG_TIDSPBRIDGE_DVFS
-const struct omap_opp vdd1_rate_table_bridge[] = {
- {0, 0, 0},
- /*OPP1 */
- {S125M, VDD1_OPP1, 0},
- /*OPP2 */
- {S250M, VDD1_OPP2, 0},
- /*OPP3 */
- {S500M, VDD1_OPP3, 0},
- /*OPP4 */
- {S550M, VDD1_OPP4, 0},
- /*OPP5 */
- {S600M, VDD1_OPP5, 0},
-};
-#endif
-#endif
-
-struct omap_dsp_platform_data *omap_dspbridge_pdata;
-
-u32 vdd1_dsp_freq[6][4] = {
- {0, 0, 0, 0},
- /*OPP1 */
- {0, 90000, 0, 86000},
- /*OPP2 */
- {0, 180000, 80000, 170000},
- /*OPP3 */
- {0, 360000, 160000, 340000},
- /*OPP4 */
- {0, 396000, 325000, 376000},
- /*OPP5 */
- {0, 430000, 355000, 430000},
-};
-
-#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
-static void bridge_recover(struct work_struct *work)
-{
- struct dev_object *dev;
- struct cfg_devnode *dev_node;
-
- if (atomic_read(&bridge_cref)) {
- reinit_completion(&bridge_comp);
- while (!wait_for_completion_timeout(&bridge_comp,
- msecs_to_jiffies(REC_TIMEOUT)))
- pr_info("%s:%d handle(s) still opened\n",
- __func__, atomic_read(&bridge_cref));
- }
- dev = dev_get_first();
- dev_get_dev_node(dev, &dev_node);
- if (!dev_node || proc_auto_start(dev_node, dev))
- pr_err("DSP could not be restarted\n");
- recover = false;
- complete_all(&bridge_open_comp);
-}
-
-void bridge_recover_schedule(void)
-{
- reinit_completion(&bridge_open_comp);
- recover = true;
- queue_work(bridge_rec_queue, &bridge_recovery_work);
-}
-#endif
-#ifdef CONFIG_TIDSPBRIDGE_DVFS
-static int dspbridge_scale_notification(struct notifier_block *op,
- unsigned long val, void *ptr)
-{
- struct omap_dsp_platform_data *pdata =
- omap_dspbridge_dev->dev.platform_data;
-
- if (CPUFREQ_POSTCHANGE == val && pdata->dsp_get_opp)
- pwr_pm_post_scale(PRCM_VDD1, pdata->dsp_get_opp());
-
- return 0;
-}
-
-static struct notifier_block iva_clk_notifier = {
- .notifier_call = dspbridge_scale_notification,
- NULL,
-};
-#endif
-
-/**
- * omap3_bridge_startup() - perform low lever initializations
- * @pdev: pointer to platform device
- *
- * Initializes recovery, PM and DVFS required data, before calling
- * clk and memory init routines.
- */
-static int omap3_bridge_startup(struct platform_device *pdev)
-{
- struct omap_dsp_platform_data *pdata = pdev->dev.platform_data;
- struct drv_data *drv_datap = NULL;
- u32 phys_membase, phys_memsize;
- int err;
-
-#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
- bridge_rec_queue = create_workqueue("bridge_rec_queue");
- INIT_WORK(&bridge_recovery_work, bridge_recover);
- reinit_completion(&bridge_comp);
-#endif
-
-#ifdef CONFIG_PM
- /* Initialize the wait queue */
- bridge_suspend_data.suspended = 0;
- init_waitqueue_head(&bridge_suspend_data.suspend_wq);
-
-#ifdef CONFIG_TIDSPBRIDGE_DVFS
- for (i = 0; i < 6; i++)
- pdata->mpu_speed[i] = vdd1_rate_table_bridge[i].rate;
-
- err = cpufreq_register_notifier(&iva_clk_notifier,
- CPUFREQ_TRANSITION_NOTIFIER);
- if (err)
- pr_err("%s: clk_notifier_register failed for iva2_ck\n",
- __func__);
-#endif
-#endif
-
- dsp_clk_init();
-
- drv_datap = kzalloc(sizeof(struct drv_data), GFP_KERNEL);
- if (!drv_datap) {
- err = -ENOMEM;
- goto err1;
- }
-
- drv_datap->shm_size = shm_size;
- drv_datap->tc_wordswapon = tc_wordswapon;
-
- if (base_img) {
- drv_datap->base_img = kstrdup(base_img, GFP_KERNEL);
- if (!drv_datap->base_img) {
- err = -ENOMEM;
- goto err2;
- }
- }
-
- dev_set_drvdata(bridge, drv_datap);
-
- if (shm_size < 0x10000) { /* 64 KB */
- err = -EINVAL;
- pr_err("%s: shm size must be at least 64 KB\n", __func__);
- goto err3;
- }
- dev_dbg(bridge, "%s: requested shm_size = 0x%x\n", __func__, shm_size);
-
- phys_membase = pdata->phys_mempool_base;
- phys_memsize = pdata->phys_mempool_size;
- if (phys_membase > 0 && phys_memsize > 0)
- mem_ext_phys_pool_init(phys_membase, phys_memsize);
-
- if (tc_wordswapon)
- dev_dbg(bridge, "%s: TC Word Swap is enabled\n", __func__);
-
- driver_context = dsp_init(&err);
- if (err) {
- pr_err("DSP Bridge driver initialization failed\n");
- goto err4;
- }
-
- return 0;
-
-err4:
- mem_ext_phys_pool_release();
-err3:
- kfree(drv_datap->base_img);
-err2:
- kfree(drv_datap);
-err1:
-#ifdef CONFIG_TIDSPBRIDGE_DVFS
- cpufreq_unregister_notifier(&iva_clk_notifier,
- CPUFREQ_TRANSITION_NOTIFIER);
-#endif
- dsp_clk_exit();
-
- return err;
-}
-
-static int omap34_xx_bridge_probe(struct platform_device *pdev)
-{
- int err;
- dev_t dev = 0;
-#ifdef CONFIG_TIDSPBRIDGE_DVFS
- int i = 0;
-#endif
-
- omap_dspbridge_dev = pdev;
-
- /* Global bridge device */
- bridge = &omap_dspbridge_dev->dev;
-
- /* Bridge low level initializations */
- err = omap3_bridge_startup(pdev);
- if (err)
- goto err1;
-
- /* use 2.6 device model */
- err = alloc_chrdev_region(&dev, 0, 1, "DspBridge");
- if (err) {
- pr_err("%s: Can't get major %d\n", __func__, driver_major);
- goto err1;
- }
-
- cdev_init(&bridge_cdev, &bridge_fops);
- bridge_cdev.owner = THIS_MODULE;
-
- err = cdev_add(&bridge_cdev, dev, 1);
- if (err) {
- pr_err("%s: Failed to add bridge device\n", __func__);
- goto err2;
- }
-
- /* udev support */
- bridge_class = class_create(THIS_MODULE, "ti_bridge");
- if (IS_ERR(bridge_class)) {
- pr_err("%s: Error creating bridge class\n", __func__);
- err = PTR_ERR(bridge_class);
- goto err3;
- }
-
- driver_major = MAJOR(dev);
- device_create(bridge_class, NULL, MKDEV(driver_major, 0),
- NULL, "DspBridge");
- pr_info("DSP Bridge driver loaded\n");
-
- return 0;
-
-err3:
- cdev_del(&bridge_cdev);
-err2:
- unregister_chrdev_region(dev, 1);
-err1:
- return err;
-}
-
-static int omap34_xx_bridge_remove(struct platform_device *pdev)
-{
- dev_t devno;
- int status = 0;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
-
- /* Retrieve the Object handle from the driver data */
- if (!drv_datap || !drv_datap->drv_object) {
- status = -ENODATA;
- pr_err("%s: Failed to retrieve the object handle\n", __func__);
- goto func_cont;
- }
-
-#ifdef CONFIG_TIDSPBRIDGE_DVFS
- if (cpufreq_unregister_notifier(&iva_clk_notifier,
- CPUFREQ_TRANSITION_NOTIFIER))
- pr_err("%s: cpufreq_unregister_notifier failed for iva2_ck\n",
- __func__);
-#endif /* #ifdef CONFIG_TIDSPBRIDGE_DVFS */
-
- if (driver_context) {
- /* Put the DSP in reset state */
- dsp_deinit(driver_context);
- driver_context = 0;
- }
-
- kfree(drv_datap);
- dev_set_drvdata(bridge, NULL);
-
-func_cont:
- mem_ext_phys_pool_release();
-
- dsp_clk_exit();
-
- devno = MKDEV(driver_major, 0);
- cdev_del(&bridge_cdev);
- unregister_chrdev_region(devno, 1);
- if (bridge_class) {
- /* remove the device from sysfs */
- device_destroy(bridge_class, MKDEV(driver_major, 0));
- class_destroy(bridge_class);
-
- }
- return status;
-}
-
-#ifdef CONFIG_PM
-static int bridge_suspend(struct platform_device *pdev, pm_message_t state)
-{
- u32 status;
- u32 command = PWR_EMERGENCYDEEPSLEEP;
-
- status = pwr_sleep_dsp(command, time_out);
- if (status)
- return -1;
-
- bridge_suspend_data.suspended = 1;
- return 0;
-}
-
-static int bridge_resume(struct platform_device *pdev)
-{
- u32 status;
-
- status = pwr_wake_dsp(time_out);
- if (status)
- return -1;
-
- bridge_suspend_data.suspended = 0;
- wake_up(&bridge_suspend_data.suspend_wq);
- return 0;
-}
-#endif
-
-static struct platform_driver bridge_driver = {
- .driver = {
- .name = "omap-dsp",
- },
- .probe = omap34_xx_bridge_probe,
- .remove = omap34_xx_bridge_remove,
-#ifdef CONFIG_PM
- .suspend = bridge_suspend,
- .resume = bridge_resume,
-#endif
-};
-
-/* To remove all process resources before removing the process from the
- * process context list */
-int drv_remove_all_resources(void *process_ctxt)
-{
- int status = 0;
- struct process_context *ctxt = (struct process_context *)process_ctxt;
-
- drv_remove_all_strm_res_elements(ctxt);
- drv_remove_all_node_res_elements(ctxt);
- drv_remove_all_dmm_res_elements(ctxt);
- ctxt->res_state = PROC_RES_FREED;
- return status;
-}
-
-module_platform_driver(bridge_driver);
diff --git a/drivers/staging/tidspbridge/rmgr/dspdrv.c b/drivers/staging/tidspbridge/rmgr/dspdrv.c
deleted file mode 100644
index 012e4a38d2db..000000000000
--- a/drivers/staging/tidspbridge/rmgr/dspdrv.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * dspdrv.c
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * Interface to allocate and free bridge resources.
- *
- * 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.
- */
-
-/* ----------------------------------- Host OS */
-#include <linux/types.h>
-#include <dspbridge/host_os.h>
-
-/* ----------------------------------- DSP/BIOS Bridge */
-#include <dspbridge/dbdefs.h>
-
-/* ----------------------------------- Platform Manager */
-#include <dspbridge/drv.h>
-#include <dspbridge/dev.h>
-#include <dspbridge/dspapi.h>
-
-/* ----------------------------------- Resource Manager */
-#include <dspbridge/mgr.h>
-
-/* ----------------------------------- This */
-#include <dspbridge/dspdrv.h>
-
-/*
- * ======== dsp_init ========
- * Allocates bridge resources. Loads a base image onto DSP, if specified.
- */
-u32 dsp_init(u32 *init_status)
-{
- char dev_node[MAXREGPATHLENGTH] = "TIOMAP1510";
- int status = -EPERM;
- struct drv_object *drv_obj = NULL;
- u32 device_node;
- u32 device_node_string;
-
- if (!api_init())
- goto func_cont;
-
- status = drv_create(&drv_obj);
- if (status) {
- api_exit();
- goto func_cont;
- }
-
- /* End drv_create */
- /* Request Resources */
- status = drv_request_resources((u32) &dev_node, &device_node_string);
- if (!status) {
- /* Attempt to Start the Device */
- status = dev_start_device((struct cfg_devnode *)
- device_node_string);
- if (status)
- (void)drv_release_resources
- ((u32) device_node_string, drv_obj);
- } else {
- dev_dbg(bridge, "%s: drv_request_resources Failed\n", __func__);
- status = -EPERM;
- }
-
- /* Unwind whatever was loaded */
- if (status) {
- /* irrespective of the status of dev_remove_device we continue
- * unloading. Get the Driver Object iterate through and remove.
- * Reset the status to E_FAIL to avoid going through
- * api_init_complete2. */
- for (device_node = drv_get_first_dev_extension();
- device_node != 0;
- device_node = drv_get_next_dev_extension(device_node)) {
- (void)dev_remove_device((struct cfg_devnode *)
- device_node);
- (void)drv_release_resources((u32) device_node, drv_obj);
- }
- /* Remove the Driver Object */
- (void)drv_destroy(drv_obj);
- drv_obj = NULL;
- api_exit();
- dev_dbg(bridge, "%s: Logical device failed init\n", __func__);
- } /* Unwinding the loaded drivers */
-func_cont:
- /* Attempt to Start the Board */
- if (!status) {
- /* BRD_AutoStart could fail if the dsp executable is not the
- * correct one. We should not propagate that error
- * into the device loader. */
- (void)api_init_complete2();
- } else {
- dev_dbg(bridge, "%s: Failed\n", __func__);
- } /* End api_init_complete2 */
- *init_status = status;
- /* Return the Driver Object */
- return (u32) drv_obj;
-}
-
-/*
- * ======== dsp_deinit ========
- * Frees the resources allocated for bridge.
- */
-bool dsp_deinit(u32 device_context)
-{
- bool ret = true;
- u32 device_node;
- struct mgr_object *mgr_obj = NULL;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
-
- while ((device_node = drv_get_first_dev_extension()) != 0) {
- (void)dev_remove_device((struct cfg_devnode *)device_node);
-
- (void)drv_release_resources((u32) device_node,
- (struct drv_object *)device_context);
- }
-
- (void)drv_destroy((struct drv_object *)device_context);
-
- /* Get the Manager Object from driver data
- * MGR Destroy will unload the DCD dll */
- if (drv_datap && drv_datap->mgr_object) {
- mgr_obj = drv_datap->mgr_object;
- (void)mgr_destroy(mgr_obj);
- } else {
- pr_err("%s: Failed to retrieve the object handle\n", __func__);
- }
-
- api_exit();
-
- return ret;
-}
diff --git a/drivers/staging/tidspbridge/rmgr/mgr.c b/drivers/staging/tidspbridge/rmgr/mgr.c
deleted file mode 100644
index 93e6282f122b..000000000000
--- a/drivers/staging/tidspbridge/rmgr/mgr.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * mgr.c
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * Implementation of Manager interface to the device object at the
- * driver level. This queries the NDB data base and retrieves the
- * data about Node and Processor.
- *
- * 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>
-
-/* ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/sync.h>
-
-/* ----------------------------------- Others */
-#include <dspbridge/dbdcd.h>
-#include <dspbridge/drv.h>
-#include <dspbridge/dev.h>
-
-/* ----------------------------------- This */
-#include <dspbridge/mgr.h>
-
-/* ----------------------------------- Defines, Data Structures, Typedefs */
-#define ZLDLLNAME ""
-
-struct mgr_object {
- struct dcd_manager *dcd_mgr; /* Proc/Node data manager */
-};
-
-/* ----------------------------------- Globals */
-static u32 refs;
-
-/*
- * ========= mgr_create =========
- * Purpose:
- * MGR Object gets created only once during driver Loading.
- */
-int mgr_create(struct mgr_object **mgr_obj,
- struct cfg_devnode *dev_node_obj)
-{
- int status = 0;
- struct mgr_object *pmgr_obj = NULL;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
-
- pmgr_obj = kzalloc(sizeof(struct mgr_object), GFP_KERNEL);
- if (pmgr_obj) {
- status = dcd_create_manager(ZLDLLNAME, &pmgr_obj->dcd_mgr);
- if (!status) {
- /* If succeeded store the handle in the MGR Object */
- if (drv_datap) {
- drv_datap->mgr_object = (void *)pmgr_obj;
- } else {
- status = -EPERM;
- pr_err("%s: Failed to store MGR object\n",
- __func__);
- }
-
- if (!status) {
- *mgr_obj = pmgr_obj;
- } else {
- dcd_destroy_manager(pmgr_obj->dcd_mgr);
- kfree(pmgr_obj);
- }
- } else {
- /* failed to Create DCD Manager */
- kfree(pmgr_obj);
- }
- } else {
- status = -ENOMEM;
- }
-
- return status;
-}
-
-/*
- * ========= mgr_destroy =========
- * This function is invoked during bridge driver unloading.Frees MGR object.
- */
-int mgr_destroy(struct mgr_object *hmgr_obj)
-{
- int status = 0;
- struct mgr_object *pmgr_obj = (struct mgr_object *)hmgr_obj;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
-
- /* Free resources */
- if (hmgr_obj->dcd_mgr)
- dcd_destroy_manager(hmgr_obj->dcd_mgr);
-
- kfree(pmgr_obj);
- /* Update the driver data with NULL for MGR Object */
- if (drv_datap) {
- drv_datap->mgr_object = NULL;
- } else {
- status = -EPERM;
- pr_err("%s: Failed to store MGR object\n", __func__);
- }
-
- return status;
-}
-
-/*
- * ======== mgr_enum_node_info ========
- * Enumerate and get configuration information about nodes configured
- * in the node database.
- */
-int mgr_enum_node_info(u32 node_id, struct dsp_ndbprops *pndb_props,
- u32 undb_props_size, u32 *pu_num_nodes)
-{
- int status = 0;
- struct dsp_uuid node_uuid;
- u32 node_index = 0;
- struct dcd_genericobj gen_obj;
- struct mgr_object *pmgr_obj = NULL;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
-
- *pu_num_nodes = 0;
- /* Get the Manager Object from the driver data */
- if (!drv_datap || !drv_datap->mgr_object) {
- pr_err("%s: Failed to retrieve the object handle\n", __func__);
- return -ENODATA;
- }
- pmgr_obj = drv_datap->mgr_object;
-
- /* Forever loop till we hit failed or no more items in the
- * Enumeration. We will exit the loop other than 0; */
- while (!status) {
- status = dcd_enumerate_object(node_index++, DSP_DCDNODETYPE,
- &node_uuid);
- if (status)
- break;
- *pu_num_nodes = node_index;
- if (node_id == (node_index - 1)) {
- status = dcd_get_object_def(pmgr_obj->dcd_mgr,
- &node_uuid, DSP_DCDNODETYPE, &gen_obj);
- if (status)
- break;
- /* Get the Obj def */
- *pndb_props = gen_obj.obj_data.node_obj.ndb_props;
- }
- }
-
- /* the last status is not 0, but neither an error */
- if (status > 0)
- status = 0;
-
- return status;
-}
-
-/*
- * ======== mgr_enum_processor_info ========
- * Enumerate and get configuration information about available
- * DSP processors.
- */
-int mgr_enum_processor_info(u32 processor_id,
- struct dsp_processorinfo *
- processor_info, u32 processor_info_size,
- u8 *pu_num_procs)
-{
- int status = 0;
- int status1 = 0;
- int status2 = 0;
- struct dsp_uuid temp_uuid;
- u32 temp_index = 0;
- u32 proc_index = 0;
- struct dcd_genericobj gen_obj;
- struct mgr_object *pmgr_obj = NULL;
- struct mgr_processorextinfo *ext_info;
- struct dev_object *hdev_obj;
- struct drv_object *hdrv_obj;
- u8 dev_type;
- struct cfg_devnode *dev_node;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
- bool proc_detect = false;
-
- *pu_num_procs = 0;
-
- /* Retrieve the Object handle from the driver data */
- if (!drv_datap || !drv_datap->drv_object) {
- status = -ENODATA;
- pr_err("%s: Failed to retrieve the object handle\n", __func__);
- } else {
- hdrv_obj = drv_datap->drv_object;
- }
-
- if (!status) {
- status = drv_get_dev_object(processor_id, hdrv_obj, &hdev_obj);
- if (!status) {
- status = dev_get_dev_type(hdev_obj, (u8 *) &dev_type);
- status = dev_get_dev_node(hdev_obj, &dev_node);
- if (dev_type != DSP_UNIT)
- status = -EPERM;
-
- if (!status)
- processor_info->processor_type = DSPTYPE64;
- }
- }
- if (status)
- goto func_end;
-
- /* Get The Manager Object from the driver data */
- if (drv_datap && drv_datap->mgr_object) {
- pmgr_obj = drv_datap->mgr_object;
- } else {
- dev_dbg(bridge, "%s: Failed to get MGR Object\n", __func__);
- goto func_end;
- }
- /* Forever loop till we hit no more items in the
- * Enumeration. We will exit the loop other than 0; */
- while (status1 == 0) {
- status1 = dcd_enumerate_object(temp_index++,
- DSP_DCDPROCESSORTYPE,
- &temp_uuid);
- if (status1 != 0)
- break;
-
- proc_index++;
- /* Get the Object properties to find the Device/Processor
- * Type */
- if (proc_detect != false)
- continue;
-
- status2 = dcd_get_object_def(pmgr_obj->dcd_mgr,
- (struct dsp_uuid *)&temp_uuid,
- DSP_DCDPROCESSORTYPE, &gen_obj);
- if (!status2) {
- /* Get the Obj def */
- if (processor_info_size <
- sizeof(struct mgr_processorextinfo)) {
- *processor_info = gen_obj.obj_data.proc_info;
- } else {
- /* extended info */
- ext_info = (struct mgr_processorextinfo *)
- processor_info;
- *ext_info = gen_obj.obj_data.ext_proc_obj;
- }
- dev_dbg(bridge, "%s: Got proctype from DCD %x\n",
- __func__, processor_info->processor_type);
- /* See if we got the needed processor */
- if (dev_type == DSP_UNIT) {
- if (processor_info->processor_type ==
- DSPPROCTYPE_C64)
- proc_detect = true;
- } else if (dev_type == IVA_UNIT) {
- if (processor_info->processor_type ==
- IVAPROCTYPE_ARM7)
- proc_detect = true;
- }
- /* User applications only check for chip type, so
- * this is a clumsy overwrite */
- processor_info->processor_type = DSPTYPE64;
- } else {
- dev_dbg(bridge, "%s: Failed to get DCD processor info %x\n",
- __func__, status2);
- status = -EPERM;
- }
- }
- *pu_num_procs = proc_index;
- if (proc_detect == false) {
- dev_dbg(bridge, "%s: Failed to get proc info from DCD, so use CFG registry\n",
- __func__);
- processor_info->processor_type = DSPTYPE64;
- }
-func_end:
- return status;
-}
-
-/*
- * ======== mgr_exit ========
- * Decrement reference count, and free resources when reference count is
- * 0.
- */
-void mgr_exit(void)
-{
- refs--;
- if (refs == 0)
- dcd_exit();
-}
-
-/*
- * ======== mgr_get_dcd_handle ========
- * Retrieves the MGR handle. Accessor Function.
- */
-int mgr_get_dcd_handle(struct mgr_object *mgr_handle,
- u32 *dcd_handle)
-{
- int status = -EPERM;
- struct mgr_object *pmgr_obj = (struct mgr_object *)mgr_handle;
-
- *dcd_handle = (u32) NULL;
- if (pmgr_obj) {
- *dcd_handle = (u32) pmgr_obj->dcd_mgr;
- status = 0;
- }
-
- return status;
-}
-
-/*
- * ======== mgr_init ========
- * Initialize MGR's private state, keeping a reference count on each call.
- */
-bool mgr_init(void)
-{
- bool ret = true;
-
- if (refs == 0)
- ret = dcd_init(); /* DCD Module */
-
- if (ret)
- refs++;
-
- return ret;
-}
-
-/*
- * ======== mgr_wait_for_bridge_events ========
- * Block on any Bridge event(s)
- */
-int mgr_wait_for_bridge_events(struct dsp_notification **anotifications,
- u32 count, u32 *pu_index,
- u32 utimeout)
-{
- int status;
- struct sync_object *sync_events[MAX_EVENTS];
- u32 i;
-
- for (i = 0; i < count; i++)
- sync_events[i] = anotifications[i]->handle;
-
- status = sync_wait_on_multiple_events(sync_events, count, utimeout,
- pu_index);
-
- return status;
-
-}
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, &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
diff --git a/drivers/staging/tidspbridge/rmgr/node.c b/drivers/staging/tidspbridge/rmgr/node.c
deleted file mode 100644
index 133f2dbc3762..000000000000
--- a/drivers/staging/tidspbridge/rmgr/node.c
+++ /dev/null
@@ -1,3031 +0,0 @@
-/*
- * node.c
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * DSP/BIOS Bridge Node Manager.
- *
- * 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 <linux/bitmap.h>
-#include <linux/list.h>
-
-/* ----------------------------------- Host OS */
-#include <dspbridge/host_os.h>
-
-/* ----------------------------------- DSP/BIOS Bridge */
-#include <dspbridge/dbdefs.h>
-
-/* ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/memdefs.h>
-#include <dspbridge/proc.h>
-#include <dspbridge/strm.h>
-#include <dspbridge/sync.h>
-#include <dspbridge/ntfy.h>
-
-/* ----------------------------------- Platform Manager */
-#include <dspbridge/cmm.h>
-#include <dspbridge/cod.h>
-#include <dspbridge/dev.h>
-#include <dspbridge/msg.h>
-
-/* ----------------------------------- Resource Manager */
-#include <dspbridge/dbdcd.h>
-#include <dspbridge/disp.h>
-#include <dspbridge/rms_sh.h>
-
-/* ----------------------------------- Link Driver */
-#include <dspbridge/dspdefs.h>
-#include <dspbridge/dspioctl.h>
-
-/* ----------------------------------- Others */
-#include <dspbridge/uuidutil.h>
-
-/* ----------------------------------- This */
-#include <dspbridge/nodepriv.h>
-#include <dspbridge/node.h>
-#include <dspbridge/dmm.h>
-
-/* Static/Dynamic Loader includes */
-#include <dspbridge/dbll.h>
-#include <dspbridge/nldr.h>
-
-#include <dspbridge/drv.h>
-#include <dspbridge/resourcecleanup.h>
-#include <_tiomap.h>
-
-#include <dspbridge/dspdeh.h>
-
-#define HOSTPREFIX "/host"
-#define PIPEPREFIX "/dbpipe"
-
-#define MAX_INPUTS(h) \
- ((h)->dcd_props.obj_data.node_obj.ndb_props.num_input_streams)
-#define MAX_OUTPUTS(h) \
- ((h)->dcd_props.obj_data.node_obj.ndb_props.num_output_streams)
-
-#define NODE_GET_PRIORITY(h) ((h)->prio)
-#define NODE_SET_PRIORITY(hnode, prio) ((hnode)->prio = prio)
-#define NODE_SET_STATE(hnode, state) ((hnode)->node_state = state)
-
-#define MAXPIPES 100 /* Max # of /pipe connections (CSL limit) */
-#define MAXDEVSUFFIXLEN 2 /* Max(Log base 10 of MAXPIPES, MAXSTREAMS) */
-
-#define PIPENAMELEN (sizeof(PIPEPREFIX) + MAXDEVSUFFIXLEN)
-#define HOSTNAMELEN (sizeof(HOSTPREFIX) + MAXDEVSUFFIXLEN)
-
-#define MAXDEVNAMELEN 32 /* dsp_ndbprops.ac_name size */
-#define CREATEPHASE 1
-#define EXECUTEPHASE 2
-#define DELETEPHASE 3
-
-/* Define default STRM parameters */
-/*
- * TBD: Put in header file, make global DSP_STRMATTRS with defaults,
- * or make defaults configurable.
- */
-#define DEFAULTBUFSIZE 32
-#define DEFAULTNBUFS 2
-#define DEFAULTSEGID 0
-#define DEFAULTALIGNMENT 0
-#define DEFAULTTIMEOUT 10000
-
-#define RMSQUERYSERVER 0
-#define RMSCONFIGURESERVER 1
-#define RMSCREATENODE 2
-#define RMSEXECUTENODE 3
-#define RMSDELETENODE 4
-#define RMSCHANGENODEPRIORITY 5
-#define RMSREADMEMORY 6
-#define RMSWRITEMEMORY 7
-#define RMSCOPY 8
-#define MAXTIMEOUT 2000
-
-#define NUMRMSFXNS 9
-
-#define PWR_TIMEOUT 500 /* default PWR timeout in msec */
-
-#define STACKSEGLABEL "L1DSRAM_HEAP" /* Label for DSP Stack Segment Addr */
-
-/*
- * ======== node_mgr ========
- */
-struct node_mgr {
- struct dev_object *dev_obj; /* Device object */
- /* Function interface to Bridge driver */
- struct bridge_drv_interface *intf_fxns;
- struct dcd_manager *dcd_mgr; /* Proc/Node data manager */
- struct disp_object *disp_obj; /* Node dispatcher */
- struct list_head node_list; /* List of all allocated nodes */
- u32 num_nodes; /* Number of nodes in node_list */
- u32 num_created; /* Number of nodes *created* on DSP */
- DECLARE_BITMAP(pipe_map, MAXPIPES); /* Pipe connection bitmap */
- DECLARE_BITMAP(pipe_done_map, MAXPIPES); /* Pipes that are half free */
- /* Channel allocation bitmap */
- DECLARE_BITMAP(chnl_map, CHNL_MAXCHANNELS);
- /* DMA Channel allocation bitmap */
- DECLARE_BITMAP(dma_chnl_map, CHNL_MAXCHANNELS);
- /* Zero-Copy Channel alloc bitmap */
- DECLARE_BITMAP(zc_chnl_map, CHNL_MAXCHANNELS);
- struct ntfy_object *ntfy_obj; /* Manages registered notifications */
- struct mutex node_mgr_lock; /* For critical sections */
- u32 fxn_addrs[NUMRMSFXNS]; /* RMS function addresses */
- struct msg_mgr *msg_mgr_obj;
-
- /* Processor properties needed by Node Dispatcher */
- u32 num_chnls; /* Total number of channels */
- u32 chnl_offset; /* Offset of chnl ids rsvd for RMS */
- u32 chnl_buf_size; /* Buffer size for data to RMS */
- int proc_family; /* eg, 5000 */
- int proc_type; /* eg, 5510 */
- u32 dsp_word_size; /* Size of DSP word on host bytes */
- u32 dsp_data_mau_size; /* Size of DSP data MAU */
- u32 dsp_mau_size; /* Size of MAU */
- s32 min_pri; /* Minimum runtime priority for node */
- s32 max_pri; /* Maximum runtime priority for node */
-
- struct strm_mgr *strm_mgr_obj; /* STRM manager */
-
- /* Loader properties */
- struct nldr_object *nldr_obj; /* Handle to loader */
- struct node_ldr_fxns nldr_fxns; /* Handle to loader functions */
-};
-
-/*
- * ======== connecttype ========
- */
-enum connecttype {
- NOTCONNECTED = 0,
- NODECONNECT,
- HOSTCONNECT,
- DEVICECONNECT,
-};
-
-/*
- * ======== stream_chnl ========
- */
-struct stream_chnl {
- enum connecttype type; /* Type of stream connection */
- u32 dev_id; /* pipe or channel id */
-};
-
-/*
- * ======== node_object ========
- */
-struct node_object {
- struct list_head list_elem;
- struct node_mgr *node_mgr; /* The manager of this node */
- struct proc_object *processor; /* Back pointer to processor */
- struct dsp_uuid node_uuid; /* Node's ID */
- s32 prio; /* Node's current priority */
- u32 timeout; /* Timeout for blocking NODE calls */
- u32 heap_size; /* Heap Size */
- u32 dsp_heap_virt_addr; /* Heap Size */
- u32 gpp_heap_virt_addr; /* Heap Size */
- enum node_type ntype; /* Type of node: message, task, etc */
- enum node_state node_state; /* NODE_ALLOCATED, NODE_CREATED, ... */
- u32 num_inputs; /* Current number of inputs */
- u32 num_outputs; /* Current number of outputs */
- u32 max_input_index; /* Current max input stream index */
- u32 max_output_index; /* Current max output stream index */
- struct stream_chnl *inputs; /* Node's input streams */
- struct stream_chnl *outputs; /* Node's output streams */
- struct node_createargs create_args; /* Args for node create func */
- nodeenv node_env; /* Environment returned by RMS */
- struct dcd_genericobj dcd_props; /* Node properties from DCD */
- struct dsp_cbdata *args; /* Optional args to pass to node */
- struct ntfy_object *ntfy_obj; /* Manages registered notifications */
- char *str_dev_name; /* device name, if device node */
- struct sync_object *sync_done; /* Synchronize node_terminate */
- s32 exit_status; /* execute function return status */
-
- /* Information needed for node_get_attr() */
- void *device_owner; /* If dev node, task that owns it */
- u32 num_gpp_inputs; /* Current # of from GPP streams */
- u32 num_gpp_outputs; /* Current # of to GPP streams */
- /* Current stream connections */
- struct dsp_streamconnect *stream_connect;
-
- /* Message queue */
- struct msg_queue *msg_queue_obj;
-
- /* These fields used for SM messaging */
- struct cmm_xlatorobject *xlator; /* Node's SM addr translator */
-
- /* Handle to pass to dynamic loader */
- struct nldr_nodeobject *nldr_node_obj;
- bool loaded; /* Code is (dynamically) loaded */
- bool phase_split; /* Phases split in many libs or ovly */
-
-};
-
-/* Default buffer attributes */
-static struct dsp_bufferattr node_dfltbufattrs = {
- .cb_struct = 0,
- .segment_id = 1,
- .buf_alignment = 0,
-};
-
-static void delete_node(struct node_object *hnode,
- struct process_context *pr_ctxt);
-static void delete_node_mgr(struct node_mgr *hnode_mgr);
-static void fill_stream_connect(struct node_object *node1,
- struct node_object *node2, u32 stream1,
- u32 stream2);
-static void fill_stream_def(struct node_object *hnode,
- struct node_strmdef *pstrm_def,
- struct dsp_strmattr *pattrs);
-static void free_stream(struct node_mgr *hnode_mgr, struct stream_chnl stream);
-static int get_fxn_address(struct node_object *hnode, u32 *fxn_addr,
- u32 phase);
-static int get_node_props(struct dcd_manager *hdcd_mgr,
- struct node_object *hnode,
- const struct dsp_uuid *node_uuid,
- struct dcd_genericobj *dcd_prop);
-static int get_proc_props(struct node_mgr *hnode_mgr,
- struct dev_object *hdev_obj);
-static int get_rms_fxns(struct node_mgr *hnode_mgr);
-static u32 ovly(void *priv_ref, u32 dsp_run_addr, u32 dsp_load_addr,
- u32 ul_num_bytes, u32 mem_space);
-static u32 mem_write(void *priv_ref, u32 dsp_add, void *pbuf,
- u32 ul_num_bytes, u32 mem_space);
-
-/* Dynamic loader functions. */
-static struct node_ldr_fxns nldr_fxns = {
- nldr_allocate,
- nldr_create,
- nldr_delete,
- nldr_get_fxn_addr,
- nldr_load,
- nldr_unload,
-};
-
-enum node_state node_get_state(void *hnode)
-{
- struct node_object *pnode = (struct node_object *)hnode;
-
- if (!pnode)
- return -1;
- return pnode->node_state;
-}
-
-/*
- * ======== node_allocate ========
- * Purpose:
- * Allocate GPP resources to manage a node on the DSP.
- */
-int node_allocate(struct proc_object *hprocessor,
- const struct dsp_uuid *node_uuid,
- const struct dsp_cbdata *pargs,
- const struct dsp_nodeattrin *attr_in,
- struct node_res_object **noderes,
- struct process_context *pr_ctxt)
-{
- struct node_mgr *hnode_mgr;
- struct dev_object *hdev_obj;
- struct node_object *pnode = NULL;
- enum node_type node_type = NODE_TASK;
- struct node_msgargs *pmsg_args;
- struct node_taskargs *ptask_args;
- u32 num_streams;
- struct bridge_drv_interface *intf_fxns;
- int status = 0;
- struct cmm_object *hcmm_mgr = NULL; /* Shared memory manager hndl */
- u32 proc_id;
- u32 pul_value;
- u32 dynext_base;
- u32 off_set = 0;
- u32 ul_stack_seg_val;
- struct cfg_hostres *host_res;
- struct bridge_dev_context *pbridge_context;
- u32 mapped_addr = 0;
- u32 map_attrs = 0x0;
- struct dsp_processorstate proc_state;
-#ifdef DSP_DMM_DEBUG
- struct dmm_object *dmm_mgr;
- struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
-#endif
-
- void *node_res;
-
- *noderes = NULL;
-
- status = proc_get_processor_id(hprocessor, &proc_id);
-
- if (proc_id != DSP_UNIT)
- goto func_end;
-
- status = proc_get_dev_object(hprocessor, &hdev_obj);
- if (!status) {
- status = dev_get_node_manager(hdev_obj, &hnode_mgr);
- if (hnode_mgr == NULL)
- status = -EPERM;
-
- }
-
- if (status)
- goto func_end;
-
- status = dev_get_bridge_context(hdev_obj, &pbridge_context);
- if (!pbridge_context) {
- status = -EFAULT;
- goto func_end;
- }
-
- status = proc_get_state(hprocessor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_end;
- /* If processor is in error state then don't attempt
- to send the message */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_end;
- }
-
- /* Assuming that 0 is not a valid function address */
- if (hnode_mgr->fxn_addrs[0] == 0) {
- /* No RMS on target - we currently can't handle this */
- pr_err("%s: Failed, no RMS in base image\n", __func__);
- status = -EPERM;
- } else {
- /* Validate attr_in fields, if non-NULL */
- if (attr_in) {
- /* Check if attr_in->prio is within range */
- if (attr_in->prio < hnode_mgr->min_pri ||
- attr_in->prio > hnode_mgr->max_pri)
- status = -EDOM;
- }
- }
- /* Allocate node object and fill in */
- if (status)
- goto func_end;
-
- pnode = kzalloc(sizeof(struct node_object), GFP_KERNEL);
- if (pnode == NULL) {
- status = -ENOMEM;
- goto func_end;
- }
- pnode->node_mgr = hnode_mgr;
- /* This critical section protects get_node_props */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- /* Get dsp_ndbprops from node database */
- status = get_node_props(hnode_mgr->dcd_mgr, pnode, node_uuid,
- &(pnode->dcd_props));
- if (status)
- goto func_cont;
-
- pnode->node_uuid = *node_uuid;
- pnode->processor = hprocessor;
- pnode->ntype = pnode->dcd_props.obj_data.node_obj.ndb_props.ntype;
- pnode->timeout = pnode->dcd_props.obj_data.node_obj.ndb_props.timeout;
- pnode->prio = pnode->dcd_props.obj_data.node_obj.ndb_props.prio;
-
- /* Currently only C64 DSP builds support Node Dynamic * heaps */
- /* Allocate memory for node heap */
- pnode->create_args.asa.task_arg_obj.heap_size = 0;
- pnode->create_args.asa.task_arg_obj.dsp_heap_addr = 0;
- pnode->create_args.asa.task_arg_obj.dsp_heap_res_addr = 0;
- pnode->create_args.asa.task_arg_obj.gpp_heap_addr = 0;
- if (!attr_in)
- goto func_cont;
-
- /* Check if we have a user allocated node heap */
- if (!(attr_in->pgpp_virt_addr))
- goto func_cont;
-
- /* check for page aligned Heap size */
- if (((attr_in->heap_size) & (PG_SIZE4K - 1))) {
- pr_err("%s: node heap size not aligned to 4K, size = 0x%x\n",
- __func__, attr_in->heap_size);
- status = -EINVAL;
- } else {
- pnode->create_args.asa.task_arg_obj.heap_size =
- attr_in->heap_size;
- pnode->create_args.asa.task_arg_obj.gpp_heap_addr =
- (u32) attr_in->pgpp_virt_addr;
- }
- if (status)
- goto func_cont;
-
- status = proc_reserve_memory(hprocessor,
- pnode->create_args.asa.task_arg_obj.
- heap_size + PAGE_SIZE,
- (void **)&(pnode->create_args.asa.
- task_arg_obj.dsp_heap_res_addr),
- pr_ctxt);
- if (status) {
- pr_err("%s: Failed to reserve memory for heap: 0x%x\n",
- __func__, status);
- goto func_cont;
- }
-#ifdef DSP_DMM_DEBUG
- status = dmm_get_handle(p_proc_object, &dmm_mgr);
- if (!dmm_mgr) {
- status = DSP_EHANDLE;
- goto func_cont;
- }
-
- dmm_mem_map_dump(dmm_mgr);
-#endif
-
- map_attrs |= DSP_MAPLITTLEENDIAN;
- map_attrs |= DSP_MAPELEMSIZE32;
- map_attrs |= DSP_MAPVIRTUALADDR;
- status = proc_map(hprocessor, (void *)attr_in->pgpp_virt_addr,
- pnode->create_args.asa.task_arg_obj.heap_size,
- (void *)pnode->create_args.asa.task_arg_obj.
- dsp_heap_res_addr, (void **)&mapped_addr, map_attrs,
- pr_ctxt);
- if (status)
- pr_err("%s: Failed to map memory for Heap: 0x%x\n",
- __func__, status);
- else
- pnode->create_args.asa.task_arg_obj.dsp_heap_addr =
- (u32) mapped_addr;
-
-func_cont:
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- if (attr_in != NULL) {
- /* Overrides of NBD properties */
- pnode->timeout = attr_in->timeout;
- pnode->prio = attr_in->prio;
- }
- /* Create object to manage notifications */
- if (!status) {
- pnode->ntfy_obj = kmalloc(sizeof(struct ntfy_object),
- GFP_KERNEL);
- if (pnode->ntfy_obj)
- ntfy_init(pnode->ntfy_obj);
- else
- status = -ENOMEM;
- }
-
- if (!status) {
- node_type = node_get_type(pnode);
- /* Allocate dsp_streamconnect array for device, task, and
- * dais socket nodes. */
- if (node_type != NODE_MESSAGE) {
- num_streams = MAX_INPUTS(pnode) + MAX_OUTPUTS(pnode);
- pnode->stream_connect = kzalloc(num_streams *
- sizeof(struct dsp_streamconnect),
- GFP_KERNEL);
- if (num_streams > 0 && pnode->stream_connect == NULL)
- status = -ENOMEM;
-
- }
- if (!status && (node_type == NODE_TASK ||
- node_type == NODE_DAISSOCKET)) {
- /* Allocate arrays for maintainig stream connections */
- pnode->inputs = kzalloc(MAX_INPUTS(pnode) *
- sizeof(struct stream_chnl), GFP_KERNEL);
- pnode->outputs = kzalloc(MAX_OUTPUTS(pnode) *
- sizeof(struct stream_chnl), GFP_KERNEL);
- ptask_args = &(pnode->create_args.asa.task_arg_obj);
- ptask_args->strm_in_def = kzalloc(MAX_INPUTS(pnode) *
- sizeof(struct node_strmdef),
- GFP_KERNEL);
- ptask_args->strm_out_def = kzalloc(MAX_OUTPUTS(pnode) *
- sizeof(struct node_strmdef),
- GFP_KERNEL);
- if ((MAX_INPUTS(pnode) > 0 && (pnode->inputs == NULL ||
- ptask_args->strm_in_def
- == NULL))
- || (MAX_OUTPUTS(pnode) > 0
- && (pnode->outputs == NULL
- || ptask_args->strm_out_def == NULL)))
- status = -ENOMEM;
- }
- }
- if (!status && (node_type != NODE_DEVICE)) {
- /* Create an event that will be posted when RMS_EXIT is
- * received. */
- pnode->sync_done = kzalloc(sizeof(struct sync_object),
- GFP_KERNEL);
- if (pnode->sync_done)
- sync_init_event(pnode->sync_done);
- else
- status = -ENOMEM;
-
- if (!status) {
- /*Get the shared mem mgr for this nodes dev object */
- status = cmm_get_handle(hprocessor, &hcmm_mgr);
- if (!status) {
- /* Allocate a SM addr translator for this node
- * w/ deflt attr */
- status = cmm_xlator_create(&pnode->xlator,
- hcmm_mgr, NULL);
- }
- }
- if (!status) {
- /* Fill in message args */
- if ((pargs != NULL) && (pargs->cb_data > 0)) {
- pmsg_args =
- &(pnode->create_args.asa.node_msg_args);
- pmsg_args->pdata = kzalloc(pargs->cb_data,
- GFP_KERNEL);
- if (pmsg_args->pdata == NULL) {
- status = -ENOMEM;
- } else {
- pmsg_args->arg_length = pargs->cb_data;
- memcpy(pmsg_args->pdata,
- pargs->node_data,
- pargs->cb_data);
- }
- }
- }
- }
-
- if (!status && node_type != NODE_DEVICE) {
- /* Create a message queue for this node */
- intf_fxns = hnode_mgr->intf_fxns;
- status =
- (*intf_fxns->msg_create_queue) (hnode_mgr->msg_mgr_obj,
- &pnode->msg_queue_obj,
- 0,
- pnode->create_args.asa.
- node_msg_args.max_msgs,
- pnode);
- }
-
- if (!status) {
- /* Create object for dynamic loading */
-
- status = hnode_mgr->nldr_fxns.allocate(hnode_mgr->nldr_obj,
- (void *)pnode,
- &pnode->dcd_props.
- obj_data.node_obj,
- &pnode->
- nldr_node_obj,
- &pnode->phase_split);
- }
-
- /* Compare value read from Node Properties and check if it is same as
- * STACKSEGLABEL, if yes read the Address of STACKSEGLABEL, calculate
- * GPP Address, Read the value in that address and override the
- * stack_seg value in task args */
- if (!status &&
- (char *)pnode->dcd_props.obj_data.node_obj.ndb_props.
- stack_seg_name != NULL) {
- if (strcmp((char *)
- pnode->dcd_props.obj_data.node_obj.ndb_props.
- stack_seg_name, STACKSEGLABEL) == 0) {
- void __iomem *stack_seg;
- u32 stack_seg_pa;
-
- status =
- hnode_mgr->nldr_fxns.
- get_fxn_addr(pnode->nldr_node_obj, "DYNEXT_BEG",
- &dynext_base);
- if (status)
- pr_err("%s: Failed to get addr for DYNEXT_BEG"
- " status = 0x%x\n", __func__, status);
-
- status =
- hnode_mgr->nldr_fxns.
- get_fxn_addr(pnode->nldr_node_obj,
- "L1DSRAM_HEAP", &pul_value);
-
- if (status)
- pr_err("%s: Failed to get addr for L1DSRAM_HEAP"
- " status = 0x%x\n", __func__, status);
-
- host_res = pbridge_context->resources;
- if (!host_res)
- status = -EPERM;
-
- if (status) {
- pr_err("%s: Failed to get host resource, status"
- " = 0x%x\n", __func__, status);
- goto func_end;
- }
-
- off_set = pul_value - dynext_base;
- stack_seg_pa = host_res->mem_phys[1] + off_set;
- stack_seg = ioremap(stack_seg_pa, SZ_32);
- if (!stack_seg) {
- status = -ENOMEM;
- goto func_end;
- }
-
- ul_stack_seg_val = readl(stack_seg);
-
- iounmap(stack_seg);
-
- dev_dbg(bridge, "%s: StackSegVal = 0x%x, StackSegAddr ="
- " 0x%x\n", __func__, ul_stack_seg_val,
- host_res->mem_base[1] + off_set);
-
- pnode->create_args.asa.task_arg_obj.stack_seg =
- ul_stack_seg_val;
-
- }
- }
-
- if (!status) {
- /* Add the node to the node manager's list of allocated
- * nodes. */
- NODE_SET_STATE(pnode, NODE_ALLOCATED);
-
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- list_add_tail(&pnode->list_elem, &hnode_mgr->node_list);
- ++(hnode_mgr->num_nodes);
-
- /* Exit critical section */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
-
- /* Preset this to assume phases are split
- * (for overlay and dll) */
- pnode->phase_split = true;
-
- /* Notify all clients registered for DSP_NODESTATECHANGE. */
- proc_notify_all_clients(hprocessor, DSP_NODESTATECHANGE);
- } else {
- /* Cleanup */
- if (pnode)
- delete_node(pnode, pr_ctxt);
-
- }
-
- if (!status) {
- status = drv_insert_node_res_element(pnode, &node_res, pr_ctxt);
- if (status) {
- delete_node(pnode, pr_ctxt);
- goto func_end;
- }
-
- *noderes = (struct node_res_object *)node_res;
- drv_proc_node_update_heap_status(node_res, true);
- drv_proc_node_update_status(node_res, true);
- }
-func_end:
- dev_dbg(bridge, "%s: hprocessor: %p pNodeId: %p pargs: %p attr_in: %p "
- "node_res: %p status: 0x%x\n", __func__, hprocessor,
- node_uuid, pargs, attr_in, noderes, status);
- return status;
-}
-
-/*
- * ======== node_alloc_msg_buf ========
- * Purpose:
- * Allocates buffer for zero copy messaging.
- */
-DBAPI node_alloc_msg_buf(struct node_object *hnode, u32 usize,
- struct dsp_bufferattr *pattr,
- u8 **pbuffer)
-{
- struct node_object *pnode = (struct node_object *)hnode;
- int status = 0;
- bool va_flag = false;
- bool set_info;
- u32 proc_id;
-
- if (!pnode)
- status = -EFAULT;
- else if (node_get_type(pnode) == NODE_DEVICE)
- status = -EPERM;
-
- if (status)
- goto func_end;
-
- if (pattr == NULL)
- pattr = &node_dfltbufattrs; /* set defaults */
-
- status = proc_get_processor_id(pnode->processor, &proc_id);
- if (proc_id != DSP_UNIT)
- goto func_end;
-
- /* If segment ID includes MEM_SETVIRTUALSEGID then pbuffer is a
- * virt address, so set this info in this node's translator
- * object for future ref. If MEM_GETVIRTUALSEGID then retrieve
- * virtual address from node's translator. */
- if ((pattr->segment_id & MEM_SETVIRTUALSEGID) ||
- (pattr->segment_id & MEM_GETVIRTUALSEGID)) {
- va_flag = true;
- set_info = (pattr->segment_id & MEM_SETVIRTUALSEGID) ?
- true : false;
- /* Clear mask bits */
- pattr->segment_id &= ~MEM_MASKVIRTUALSEGID;
- /* Set/get this node's translators virtual address base/size */
- status = cmm_xlator_info(pnode->xlator, pbuffer, usize,
- pattr->segment_id, set_info);
- }
- if (!status && (!va_flag)) {
- if (pattr->segment_id != 1) {
- /* Node supports single SM segment only. */
- status = -EBADR;
- }
- /* Arbitrary SM buffer alignment not supported for host side
- * allocs, but guaranteed for the following alignment
- * values. */
- switch (pattr->buf_alignment) {
- case 0:
- case 1:
- case 2:
- case 4:
- break;
- default:
- /* alignment value not supportted */
- status = -EPERM;
- break;
- }
- if (!status) {
- /* allocate physical buffer from seg_id in node's
- * translator */
- (void)cmm_xlator_alloc_buf(pnode->xlator, pbuffer,
- usize);
- if (*pbuffer == NULL) {
- pr_err("%s: error - Out of shared memory\n",
- __func__);
- status = -ENOMEM;
- }
- }
- }
-func_end:
- return status;
-}
-
-/*
- * ======== node_change_priority ========
- * Purpose:
- * Change the priority of a node in the allocated state, or that is
- * currently running or paused on the target.
- */
-int node_change_priority(struct node_object *hnode, s32 prio)
-{
- struct node_object *pnode = (struct node_object *)hnode;
- struct node_mgr *hnode_mgr = NULL;
- enum node_type node_type;
- enum node_state state;
- int status = 0;
- u32 proc_id;
-
- if (!hnode || !hnode->node_mgr) {
- status = -EFAULT;
- } else {
- hnode_mgr = hnode->node_mgr;
- node_type = node_get_type(hnode);
- if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET)
- status = -EPERM;
- else if (prio < hnode_mgr->min_pri || prio > hnode_mgr->max_pri)
- status = -EDOM;
- }
- if (status)
- goto func_end;
-
- /* Enter critical section */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- state = node_get_state(hnode);
- if (state == NODE_ALLOCATED || state == NODE_PAUSED) {
- NODE_SET_PRIORITY(hnode, prio);
- } else {
- if (state != NODE_RUNNING) {
- status = -EBADR;
- goto func_cont;
- }
- status = proc_get_processor_id(pnode->processor, &proc_id);
- if (proc_id == DSP_UNIT) {
- status =
- disp_node_change_priority(hnode_mgr->disp_obj,
- hnode,
- hnode_mgr->fxn_addrs
- [RMSCHANGENODEPRIORITY],
- hnode->node_env, prio);
- }
- if (status >= 0)
- NODE_SET_PRIORITY(hnode, prio);
-
- }
-func_cont:
- /* Leave critical section */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
-func_end:
- return status;
-}
-
-/*
- * ======== node_connect ========
- * Purpose:
- * Connect two nodes on the DSP, or a node on the DSP to the GPP.
- */
-int node_connect(struct node_object *node1, u32 stream1,
- struct node_object *node2,
- u32 stream2, struct dsp_strmattr *pattrs,
- struct dsp_cbdata *conn_param)
-{
- struct node_mgr *hnode_mgr;
- char *pstr_dev_name = NULL;
- enum node_type node1_type = NODE_TASK;
- enum node_type node2_type = NODE_TASK;
- enum dsp_strmmode strm_mode;
- struct node_strmdef *pstrm_def;
- struct node_strmdef *input = NULL;
- struct node_strmdef *output = NULL;
- struct node_object *dev_node_obj;
- struct node_object *hnode;
- struct stream_chnl *pstream;
- u32 pipe_id;
- u32 chnl_id;
- s8 chnl_mode;
- u32 dw_length;
- int status = 0;
-
- if (!node1 || !node2)
- return -EFAULT;
-
- /* The two nodes must be on the same processor */
- if (node1 != (struct node_object *)DSP_HGPPNODE &&
- node2 != (struct node_object *)DSP_HGPPNODE &&
- node1->node_mgr != node2->node_mgr)
- return -EPERM;
-
- /* Cannot connect a node to itself */
- if (node1 == node2)
- return -EPERM;
-
- /* node_get_type() will return NODE_GPP if hnode = DSP_HGPPNODE. */
- node1_type = node_get_type(node1);
- node2_type = node_get_type(node2);
- /* Check stream indices ranges */
- if ((node1_type != NODE_GPP && node1_type != NODE_DEVICE &&
- stream1 >= MAX_OUTPUTS(node1)) ||
- (node2_type != NODE_GPP && node2_type != NODE_DEVICE &&
- stream2 >= MAX_INPUTS(node2)))
- return -EINVAL;
-
- /*
- * Only the following types of connections are allowed:
- * task/dais socket < == > task/dais socket
- * task/dais socket < == > device
- * task/dais socket < == > GPP
- *
- * ie, no message nodes, and at least one task or dais
- * socket node.
- */
- if (node1_type == NODE_MESSAGE || node2_type == NODE_MESSAGE ||
- (node1_type != NODE_TASK &&
- node1_type != NODE_DAISSOCKET &&
- node2_type != NODE_TASK &&
- node2_type != NODE_DAISSOCKET))
- return -EPERM;
- /*
- * Check stream mode. Default is STRMMODE_PROCCOPY.
- */
- if (pattrs && pattrs->strm_mode != STRMMODE_PROCCOPY)
- return -EPERM; /* illegal stream mode */
-
- if (node1_type != NODE_GPP)
- hnode_mgr = node1->node_mgr;
- else
- hnode_mgr = node2->node_mgr;
-
- /* Enter critical section */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- /* Nodes must be in the allocated state */
- if (node1_type != NODE_GPP &&
- node_get_state(node1) != NODE_ALLOCATED) {
- status = -EBADR;
- goto out_unlock;
- }
-
- if (node2_type != NODE_GPP &&
- node_get_state(node2) != NODE_ALLOCATED) {
- status = -EBADR;
- goto out_unlock;
- }
-
- /*
- * Check that stream indices for task and dais socket nodes
- * are not already be used. (Device nodes checked later)
- */
- if (node1_type == NODE_TASK || node1_type == NODE_DAISSOCKET) {
- output = &(node1->create_args.asa.
- task_arg_obj.strm_out_def[stream1]);
- if (output->sz_device) {
- status = -EISCONN;
- goto out_unlock;
- }
-
- }
- if (node2_type == NODE_TASK || node2_type == NODE_DAISSOCKET) {
- input = &(node2->create_args.asa.
- task_arg_obj.strm_in_def[stream2]);
- if (input->sz_device) {
- status = -EISCONN;
- goto out_unlock;
- }
-
- }
- /* Connecting two task nodes? */
- if ((node1_type == NODE_TASK || node1_type == NODE_DAISSOCKET) &&
- (node2_type == NODE_TASK ||
- node2_type == NODE_DAISSOCKET)) {
- /* Find available pipe */
- pipe_id = find_first_zero_bit(hnode_mgr->pipe_map, MAXPIPES);
- if (pipe_id == MAXPIPES) {
- status = -ECONNREFUSED;
- goto out_unlock;
- }
- set_bit(pipe_id, hnode_mgr->pipe_map);
- node1->outputs[stream1].type = NODECONNECT;
- node2->inputs[stream2].type = NODECONNECT;
- node1->outputs[stream1].dev_id = pipe_id;
- node2->inputs[stream2].dev_id = pipe_id;
- output->sz_device = kzalloc(PIPENAMELEN + 1, GFP_KERNEL);
- input->sz_device = kzalloc(PIPENAMELEN + 1, GFP_KERNEL);
- if (!output->sz_device || !input->sz_device) {
- /* Undo the connection */
- kfree(output->sz_device);
- kfree(input->sz_device);
- clear_bit(pipe_id, hnode_mgr->pipe_map);
- status = -ENOMEM;
- goto out_unlock;
- }
- /* Copy "/dbpipe<pipId>" name to device names */
- sprintf(output->sz_device, "%s%d", PIPEPREFIX, pipe_id);
- strcpy(input->sz_device, output->sz_device);
- }
- /* Connecting task node to host? */
- if (node1_type == NODE_GPP || node2_type == NODE_GPP) {
- pstr_dev_name = kzalloc(HOSTNAMELEN + 1, GFP_KERNEL);
- if (!pstr_dev_name) {
- status = -ENOMEM;
- goto out_unlock;
- }
-
- chnl_mode = (node1_type == NODE_GPP) ?
- CHNL_MODETODSP : CHNL_MODEFROMDSP;
-
- /*
- * Reserve a channel id. We need to put the name "/host<id>"
- * in the node's create_args, but the host
- * side channel will not be opened until DSPStream_Open is
- * called for this node.
- */
- strm_mode = pattrs ? pattrs->strm_mode : STRMMODE_PROCCOPY;
- switch (strm_mode) {
- case STRMMODE_RDMA:
- chnl_id = find_first_zero_bit(hnode_mgr->dma_chnl_map,
- CHNL_MAXCHANNELS);
- if (chnl_id < CHNL_MAXCHANNELS) {
- set_bit(chnl_id, hnode_mgr->dma_chnl_map);
- /* dma chans are 2nd transport chnl set
- * ids(e.g. 16-31) */
- chnl_id = chnl_id + hnode_mgr->num_chnls;
- }
- break;
- case STRMMODE_ZEROCOPY:
- chnl_id = find_first_zero_bit(hnode_mgr->zc_chnl_map,
- CHNL_MAXCHANNELS);
- if (chnl_id < CHNL_MAXCHANNELS) {
- set_bit(chnl_id, hnode_mgr->zc_chnl_map);
- /* zero-copy chans are 3nd transport set
- * (e.g. 32-47) */
- chnl_id = chnl_id +
- (2 * hnode_mgr->num_chnls);
- }
- break;
- case STRMMODE_PROCCOPY:
- chnl_id = find_first_zero_bit(hnode_mgr->chnl_map,
- CHNL_MAXCHANNELS);
- if (chnl_id < CHNL_MAXCHANNELS)
- set_bit(chnl_id, hnode_mgr->chnl_map);
- break;
- default:
- status = -EINVAL;
- goto out_unlock;
- }
- if (chnl_id == CHNL_MAXCHANNELS) {
- status = -ECONNREFUSED;
- goto out_unlock;
- }
-
- if (node1 == (struct node_object *)DSP_HGPPNODE) {
- node2->inputs[stream2].type = HOSTCONNECT;
- node2->inputs[stream2].dev_id = chnl_id;
- input->sz_device = pstr_dev_name;
- } else {
- node1->outputs[stream1].type = HOSTCONNECT;
- node1->outputs[stream1].dev_id = chnl_id;
- output->sz_device = pstr_dev_name;
- }
- sprintf(pstr_dev_name, "%s%d", HOSTPREFIX, chnl_id);
- }
- /* Connecting task node to device node? */
- if ((node1_type == NODE_DEVICE) || (node2_type == NODE_DEVICE)) {
- if (node2_type == NODE_DEVICE) {
- /* node1 == > device */
- dev_node_obj = node2;
- hnode = node1;
- pstream = &(node1->outputs[stream1]);
- pstrm_def = output;
- } else {
- /* device == > node2 */
- dev_node_obj = node1;
- hnode = node2;
- pstream = &(node2->inputs[stream2]);
- pstrm_def = input;
- }
- /* Set up create args */
- pstream->type = DEVICECONNECT;
- dw_length = strlen(dev_node_obj->str_dev_name);
- if (conn_param)
- pstrm_def->sz_device = kzalloc(dw_length + 1 +
- conn_param->cb_data,
- GFP_KERNEL);
- else
- pstrm_def->sz_device = kzalloc(dw_length + 1,
- GFP_KERNEL);
- if (!pstrm_def->sz_device) {
- status = -ENOMEM;
- goto out_unlock;
- }
- /* Copy device name */
- strncpy(pstrm_def->sz_device,
- dev_node_obj->str_dev_name, dw_length);
- if (conn_param)
- strncat(pstrm_def->sz_device,
- (char *)conn_param->node_data,
- (u32) conn_param->cb_data);
- dev_node_obj->device_owner = hnode;
- }
- /* Fill in create args */
- if (node1_type == NODE_TASK || node1_type == NODE_DAISSOCKET) {
- node1->create_args.asa.task_arg_obj.num_outputs++;
- fill_stream_def(node1, output, pattrs);
- }
- if (node2_type == NODE_TASK || node2_type == NODE_DAISSOCKET) {
- node2->create_args.asa.task_arg_obj.num_inputs++;
- fill_stream_def(node2, input, pattrs);
- }
- /* Update node1 and node2 stream_connect */
- if (node1_type != NODE_GPP && node1_type != NODE_DEVICE) {
- node1->num_outputs++;
- if (stream1 > node1->max_output_index)
- node1->max_output_index = stream1;
-
- }
- if (node2_type != NODE_GPP && node2_type != NODE_DEVICE) {
- node2->num_inputs++;
- if (stream2 > node2->max_input_index)
- node2->max_input_index = stream2;
-
- }
- fill_stream_connect(node1, node2, stream1, stream2);
- /* end of sync_enter_cs */
- /* Exit critical section */
-out_unlock:
- if (status && pstr_dev_name)
- kfree(pstr_dev_name);
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- dev_dbg(bridge, "%s: node1: %p stream1: %d node2: %p stream2: %d"
- "pattrs: %p status: 0x%x\n", __func__, node1,
- stream1, node2, stream2, pattrs, status);
- return status;
-}
-
-/*
- * ======== node_create ========
- * Purpose:
- * Create a node on the DSP by remotely calling the node's create function.
- */
-int node_create(struct node_object *hnode)
-{
- struct node_object *pnode = (struct node_object *)hnode;
- struct node_mgr *hnode_mgr;
- struct bridge_drv_interface *intf_fxns;
- u32 ul_create_fxn;
- enum node_type node_type;
- int status = 0;
- int status1 = 0;
- struct dsp_cbdata cb_data;
- u32 proc_id = 255;
- struct dsp_processorstate proc_state;
- struct proc_object *hprocessor;
-#if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
- struct dspbridge_platform_data *pdata =
- omap_dspbridge_dev->dev.platform_data;
-#endif
-
- if (!pnode) {
- status = -EFAULT;
- goto func_end;
- }
- hprocessor = hnode->processor;
- status = proc_get_state(hprocessor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_end;
- /* If processor is in error state then don't attempt to create
- new node */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_end;
- }
- /* create struct dsp_cbdata struct for PWR calls */
- cb_data.cb_data = PWR_TIMEOUT;
- node_type = node_get_type(hnode);
- hnode_mgr = hnode->node_mgr;
- intf_fxns = hnode_mgr->intf_fxns;
- /* Get access to node dispatcher */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- /* Check node state */
- if (node_get_state(hnode) != NODE_ALLOCATED)
- status = -EBADR;
-
- if (!status)
- status = proc_get_processor_id(pnode->processor, &proc_id);
-
- if (status)
- goto func_cont2;
-
- if (proc_id != DSP_UNIT)
- goto func_cont2;
-
- /* Make sure streams are properly connected */
- if ((hnode->num_inputs && hnode->max_input_index >
- hnode->num_inputs - 1) ||
- (hnode->num_outputs && hnode->max_output_index >
- hnode->num_outputs - 1))
- status = -ENOTCONN;
-
- if (!status) {
- /* If node's create function is not loaded, load it */
- /* Boost the OPP level to max level that DSP can be requested */
-#if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
- if (pdata->cpu_set_freq)
- (*pdata->cpu_set_freq) (pdata->mpu_speed[VDD1_OPP3]);
-#endif
- status = hnode_mgr->nldr_fxns.load(hnode->nldr_node_obj,
- NLDR_CREATE);
- /* Get address of node's create function */
- if (!status) {
- hnode->loaded = true;
- if (node_type != NODE_DEVICE) {
- status = get_fxn_address(hnode, &ul_create_fxn,
- CREATEPHASE);
- }
- } else {
- pr_err("%s: failed to load create code: 0x%x\n",
- __func__, status);
- }
- /* Request the lowest OPP level */
-#if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
- if (pdata->cpu_set_freq)
- (*pdata->cpu_set_freq) (pdata->mpu_speed[VDD1_OPP1]);
-#endif
- /* Get address of iAlg functions, if socket node */
- if (!status) {
- if (node_type == NODE_DAISSOCKET) {
- status = hnode_mgr->nldr_fxns.get_fxn_addr
- (hnode->nldr_node_obj,
- hnode->dcd_props.obj_data.node_obj.
- str_i_alg_name,
- &hnode->create_args.asa.
- task_arg_obj.dais_arg);
- }
- }
- }
- if (!status) {
- if (node_type != NODE_DEVICE) {
- status = disp_node_create(hnode_mgr->disp_obj, hnode,
- hnode_mgr->fxn_addrs
- [RMSCREATENODE],
- ul_create_fxn,
- &(hnode->create_args),
- &(hnode->node_env));
- if (status >= 0) {
- /* Set the message queue id to the node env
- * pointer */
- intf_fxns = hnode_mgr->intf_fxns;
- (*intf_fxns->msg_set_queue_id) (hnode->
- msg_queue_obj,
- hnode->node_env);
- }
- }
- }
- /* Phase II/Overlays: Create, execute, delete phases possibly in
- * different files/sections. */
- if (hnode->loaded && hnode->phase_split) {
- /* If create code was dynamically loaded, we can now unload
- * it. */
- status1 = hnode_mgr->nldr_fxns.unload(hnode->nldr_node_obj,
- NLDR_CREATE);
- hnode->loaded = false;
- }
- if (status1)
- pr_err("%s: Failed to unload create code: 0x%x\n",
- __func__, status1);
-func_cont2:
- /* Update node state and node manager state */
- if (status >= 0) {
- NODE_SET_STATE(hnode, NODE_CREATED);
- hnode_mgr->num_created++;
- goto func_cont;
- }
- if (status != -EBADR) {
- /* Put back in NODE_ALLOCATED state if error occurred */
- NODE_SET_STATE(hnode, NODE_ALLOCATED);
- }
-func_cont:
- /* Free access to node dispatcher */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
-func_end:
- if (status >= 0) {
- proc_notify_clients(hnode->processor, DSP_NODESTATECHANGE);
- ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
- }
-
- dev_dbg(bridge, "%s: hnode: %p status: 0x%x\n", __func__,
- hnode, status);
- return status;
-}
-
-/*
- * ======== node_create_mgr ========
- * Purpose:
- * Create a NODE Manager object.
- */
-int node_create_mgr(struct node_mgr **node_man,
- struct dev_object *hdev_obj)
-{
- u32 i;
- struct node_mgr *node_mgr_obj = NULL;
- struct disp_attr disp_attr_obj;
- char *sz_zl_file = "";
- struct nldr_attrs nldr_attrs_obj;
- int status = 0;
- u8 dev_type;
-
- *node_man = NULL;
- /* Allocate Node manager object */
- node_mgr_obj = kzalloc(sizeof(struct node_mgr), GFP_KERNEL);
- if (!node_mgr_obj)
- return -ENOMEM;
-
- node_mgr_obj->dev_obj = hdev_obj;
-
- node_mgr_obj->ntfy_obj = kmalloc(sizeof(struct ntfy_object),
- GFP_KERNEL);
- if (!node_mgr_obj->ntfy_obj) {
- status = -ENOMEM;
- goto out_err;
- }
- ntfy_init(node_mgr_obj->ntfy_obj);
-
- INIT_LIST_HEAD(&node_mgr_obj->node_list);
-
- dev_get_dev_type(hdev_obj, &dev_type);
-
- status = dcd_create_manager(sz_zl_file, &node_mgr_obj->dcd_mgr);
- if (status)
- goto out_err;
-
- status = get_proc_props(node_mgr_obj, hdev_obj);
- if (status)
- goto out_err;
-
- /* Create NODE Dispatcher */
- disp_attr_obj.chnl_offset = node_mgr_obj->chnl_offset;
- disp_attr_obj.chnl_buf_size = node_mgr_obj->chnl_buf_size;
- disp_attr_obj.proc_family = node_mgr_obj->proc_family;
- disp_attr_obj.proc_type = node_mgr_obj->proc_type;
-
- status = disp_create(&node_mgr_obj->disp_obj, hdev_obj, &disp_attr_obj);
- if (status)
- goto out_err;
-
- /* Create a STRM Manager */
- status = strm_create(&node_mgr_obj->strm_mgr_obj, hdev_obj);
- if (status)
- goto out_err;
-
- dev_get_intf_fxns(hdev_obj, &node_mgr_obj->intf_fxns);
- /* Get msg_ctrl queue manager */
- dev_get_msg_mgr(hdev_obj, &node_mgr_obj->msg_mgr_obj);
- mutex_init(&node_mgr_obj->node_mgr_lock);
-
- /* Block out reserved channels */
- for (i = 0; i < node_mgr_obj->chnl_offset; i++)
- set_bit(i, node_mgr_obj->chnl_map);
-
- /* Block out channels reserved for RMS */
- set_bit(node_mgr_obj->chnl_offset, node_mgr_obj->chnl_map);
- set_bit(node_mgr_obj->chnl_offset + 1, node_mgr_obj->chnl_map);
-
- /* NO RM Server on the IVA */
- if (dev_type != IVA_UNIT) {
- /* Get addresses of any RMS functions loaded */
- status = get_rms_fxns(node_mgr_obj);
- if (status)
- goto out_err;
- }
-
- /* Get loader functions and create loader */
- node_mgr_obj->nldr_fxns = nldr_fxns; /* Dyn loader funcs */
-
- nldr_attrs_obj.ovly = ovly;
- nldr_attrs_obj.write = mem_write;
- nldr_attrs_obj.dsp_word_size = node_mgr_obj->dsp_word_size;
- nldr_attrs_obj.dsp_mau_size = node_mgr_obj->dsp_mau_size;
- status = node_mgr_obj->nldr_fxns.create(&node_mgr_obj->nldr_obj,
- hdev_obj,
- &nldr_attrs_obj);
- if (status)
- goto out_err;
-
- *node_man = node_mgr_obj;
-
- return status;
-out_err:
- delete_node_mgr(node_mgr_obj);
- return status;
-}
-
-/*
- * ======== node_delete ========
- * Purpose:
- * Delete a node on the DSP by remotely calling the node's delete function.
- * Loads the node's delete function if necessary. Free GPP side resources
- * after node's delete function returns.
- */
-int node_delete(struct node_res_object *noderes,
- struct process_context *pr_ctxt)
-{
- struct node_object *pnode = noderes->node;
- struct node_mgr *hnode_mgr;
- struct proc_object *hprocessor;
- struct disp_object *disp_obj;
- u32 ul_delete_fxn;
- enum node_type node_type;
- enum node_state state;
- int status = 0;
- int status1 = 0;
- struct dsp_cbdata cb_data;
- u32 proc_id;
- struct bridge_drv_interface *intf_fxns;
-
- void *node_res = noderes;
-
- struct dsp_processorstate proc_state;
-
- if (!pnode) {
- status = -EFAULT;
- goto func_end;
- }
- /* create struct dsp_cbdata struct for PWR call */
- cb_data.cb_data = PWR_TIMEOUT;
- hnode_mgr = pnode->node_mgr;
- hprocessor = pnode->processor;
- disp_obj = hnode_mgr->disp_obj;
- node_type = node_get_type(pnode);
- intf_fxns = hnode_mgr->intf_fxns;
- /* Enter critical section */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- state = node_get_state(pnode);
- /* Execute delete phase code for non-device node in all cases
- * except when the node was only allocated. Delete phase must be
- * executed even if create phase was executed, but failed.
- * If the node environment pointer is non-NULL, the delete phase
- * code must be executed. */
- if (!(state == NODE_ALLOCATED && pnode->node_env == (u32) NULL) &&
- node_type != NODE_DEVICE) {
- status = proc_get_processor_id(pnode->processor, &proc_id);
- if (status)
- goto func_cont1;
-
- if (proc_id == DSP_UNIT || proc_id == IVA_UNIT) {
- /* If node has terminated, execute phase code will
- * have already been unloaded in node_on_exit(). If the
- * node is PAUSED, the execute phase is loaded, and it
- * is now ok to unload it. If the node is running, we
- * will unload the execute phase only after deleting
- * the node. */
- if (state == NODE_PAUSED && pnode->loaded &&
- pnode->phase_split) {
- /* Ok to unload execute code as long as node
- * is not * running */
- status1 =
- hnode_mgr->nldr_fxns.
- unload(pnode->nldr_node_obj,
- NLDR_EXECUTE);
- pnode->loaded = false;
- NODE_SET_STATE(pnode, NODE_DONE);
- }
- /* Load delete phase code if not loaded or if haven't
- * * unloaded EXECUTE phase */
- if ((!(pnode->loaded) || (state == NODE_RUNNING)) &&
- pnode->phase_split) {
- status =
- hnode_mgr->nldr_fxns.
- load(pnode->nldr_node_obj, NLDR_DELETE);
- if (!status)
- pnode->loaded = true;
- else
- pr_err("%s: fail - load delete code:"
- " 0x%x\n", __func__, status);
- }
- }
-func_cont1:
- if (!status) {
- /* Unblock a thread trying to terminate the node */
- (void)sync_set_event(pnode->sync_done);
- if (proc_id == DSP_UNIT) {
- /* ul_delete_fxn = address of node's delete
- * function */
- status = get_fxn_address(pnode, &ul_delete_fxn,
- DELETEPHASE);
- } else if (proc_id == IVA_UNIT)
- ul_delete_fxn = (u32) pnode->node_env;
- if (!status) {
- status = proc_get_state(hprocessor,
- &proc_state,
- sizeof(struct
- dsp_processorstate));
- if (proc_state.proc_state != PROC_ERROR) {
- status =
- disp_node_delete(disp_obj, pnode,
- hnode_mgr->
- fxn_addrs
- [RMSDELETENODE],
- ul_delete_fxn,
- pnode->node_env);
- } else
- NODE_SET_STATE(pnode, NODE_DONE);
-
- /* Unload execute, if not unloaded, and delete
- * function */
- if (state == NODE_RUNNING &&
- pnode->phase_split) {
- status1 =
- hnode_mgr->nldr_fxns.
- unload(pnode->nldr_node_obj,
- NLDR_EXECUTE);
- }
- if (status1)
- pr_err("%s: fail - unload execute code:"
- " 0x%x\n", __func__, status1);
-
- status1 =
- hnode_mgr->nldr_fxns.unload(pnode->
- nldr_node_obj,
- NLDR_DELETE);
- pnode->loaded = false;
- if (status1)
- pr_err("%s: fail - unload delete code: "
- "0x%x\n", __func__, status1);
- }
- }
- }
- /* Free host side resources even if a failure occurred */
- /* Remove node from hnode_mgr->node_list */
- list_del(&pnode->list_elem);
- hnode_mgr->num_nodes--;
- /* Decrement count of nodes created on DSP */
- if ((state != NODE_ALLOCATED) || ((state == NODE_ALLOCATED) &&
- (pnode->node_env != (u32) NULL)))
- hnode_mgr->num_created--;
- /* Free host-side resources allocated by node_create()
- * delete_node() fails if SM buffers not freed by client! */
- drv_proc_node_update_status(node_res, false);
- delete_node(pnode, pr_ctxt);
-
- /*
- * Release all Node resources and its context
- */
- idr_remove(pr_ctxt->node_id, ((struct node_res_object *)node_res)->id);
- kfree(node_res);
-
- /* Exit critical section */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- proc_notify_clients(hprocessor, DSP_NODESTATECHANGE);
-func_end:
- dev_dbg(bridge, "%s: pnode: %p status 0x%x\n", __func__, pnode, status);
- return status;
-}
-
-/*
- * ======== node_delete_mgr ========
- * Purpose:
- * Delete the NODE Manager.
- */
-int node_delete_mgr(struct node_mgr *hnode_mgr)
-{
- if (!hnode_mgr)
- return -EFAULT;
-
- delete_node_mgr(hnode_mgr);
-
- return 0;
-}
-
-/*
- * ======== node_enum_nodes ========
- * Purpose:
- * Enumerate currently allocated nodes.
- */
-int node_enum_nodes(struct node_mgr *hnode_mgr, void **node_tab,
- u32 node_tab_size, u32 *pu_num_nodes,
- u32 *pu_allocated)
-{
- struct node_object *hnode;
- u32 i = 0;
- int status = 0;
-
- if (!hnode_mgr) {
- status = -EFAULT;
- goto func_end;
- }
- /* Enter critical section */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- if (hnode_mgr->num_nodes > node_tab_size) {
- *pu_allocated = hnode_mgr->num_nodes;
- *pu_num_nodes = 0;
- status = -EINVAL;
- } else {
- list_for_each_entry(hnode, &hnode_mgr->node_list, list_elem)
- node_tab[i++] = hnode;
- *pu_allocated = *pu_num_nodes = hnode_mgr->num_nodes;
- }
- /* end of sync_enter_cs */
- /* Exit critical section */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
-func_end:
- return status;
-}
-
-/*
- * ======== node_free_msg_buf ========
- * Purpose:
- * Frees the message buffer.
- */
-int node_free_msg_buf(struct node_object *hnode, u8 *pbuffer,
- struct dsp_bufferattr *pattr)
-{
- struct node_object *pnode = (struct node_object *)hnode;
- int status = 0;
- u32 proc_id;
-
- if (!hnode) {
- status = -EFAULT;
- goto func_end;
- }
- status = proc_get_processor_id(pnode->processor, &proc_id);
- if (proc_id == DSP_UNIT) {
- if (!status) {
- if (pattr == NULL) {
- /* set defaults */
- pattr = &node_dfltbufattrs;
- }
- /* Node supports single SM segment only */
- if (pattr->segment_id != 1)
- status = -EBADR;
-
- /* pbuffer is clients Va. */
- status = cmm_xlator_free_buf(pnode->xlator, pbuffer);
- }
- } else {
- }
-func_end:
- return status;
-}
-
-/*
- * ======== node_get_attr ========
- * Purpose:
- * Copy the current attributes of the specified node into a dsp_nodeattr
- * structure.
- */
-int node_get_attr(struct node_object *hnode,
- struct dsp_nodeattr *pattr, u32 attr_size)
-{
- struct node_mgr *hnode_mgr;
-
- if (!hnode)
- return -EFAULT;
-
- hnode_mgr = hnode->node_mgr;
- /* Enter hnode_mgr critical section since we're accessing
- * data that could be changed by node_change_priority() and
- * node_connect(). */
- mutex_lock(&hnode_mgr->node_mgr_lock);
- pattr->cb_struct = sizeof(struct dsp_nodeattr);
- /* dsp_nodeattrin */
- pattr->in_node_attr_in.cb_struct =
- sizeof(struct dsp_nodeattrin);
- pattr->in_node_attr_in.prio = hnode->prio;
- pattr->in_node_attr_in.timeout = hnode->timeout;
- pattr->in_node_attr_in.heap_size =
- hnode->create_args.asa.task_arg_obj.heap_size;
- pattr->in_node_attr_in.pgpp_virt_addr = (void *)
- hnode->create_args.asa.task_arg_obj.gpp_heap_addr;
- pattr->node_attr_inputs = hnode->num_gpp_inputs;
- pattr->node_attr_outputs = hnode->num_gpp_outputs;
- /* dsp_nodeinfo */
- get_node_info(hnode, &(pattr->node_info));
- /* end of sync_enter_cs */
- /* Exit critical section */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
-
- return 0;
-}
-
-/*
- * ======== node_get_channel_id ========
- * Purpose:
- * Get the channel index reserved for a stream connection between the
- * host and a node.
- */
-int node_get_channel_id(struct node_object *hnode, u32 dir, u32 index,
- u32 *chan_id)
-{
- enum node_type node_type;
- int status = -EINVAL;
-
- if (!hnode) {
- status = -EFAULT;
- return status;
- }
- node_type = node_get_type(hnode);
- if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET) {
- status = -EPERM;
- return status;
- }
- if (dir == DSP_TONODE) {
- if (index < MAX_INPUTS(hnode)) {
- if (hnode->inputs[index].type == HOSTCONNECT) {
- *chan_id = hnode->inputs[index].dev_id;
- status = 0;
- }
- }
- } else {
- if (index < MAX_OUTPUTS(hnode)) {
- if (hnode->outputs[index].type == HOSTCONNECT) {
- *chan_id = hnode->outputs[index].dev_id;
- status = 0;
- }
- }
- }
- return status;
-}
-
-/*
- * ======== node_get_message ========
- * Purpose:
- * Retrieve a message from a node on the DSP.
- */
-int node_get_message(struct node_object *hnode,
- struct dsp_msg *message, u32 utimeout)
-{
- struct node_mgr *hnode_mgr;
- enum node_type node_type;
- struct bridge_drv_interface *intf_fxns;
- int status = 0;
- void *tmp_buf;
- struct dsp_processorstate proc_state;
- struct proc_object *hprocessor;
-
- if (!hnode) {
- status = -EFAULT;
- goto func_end;
- }
- hprocessor = hnode->processor;
- status = proc_get_state(hprocessor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_end;
- /* If processor is in error state then don't attempt to get the
- message */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_end;
- }
- hnode_mgr = hnode->node_mgr;
- node_type = node_get_type(hnode);
- if (node_type != NODE_MESSAGE && node_type != NODE_TASK &&
- node_type != NODE_DAISSOCKET) {
- status = -EPERM;
- goto func_end;
- }
- /* This function will block unless a message is available. Since
- * DSPNode_RegisterNotify() allows notification when a message
- * is available, the system can be designed so that
- * DSPNode_GetMessage() is only called when a message is
- * available. */
- intf_fxns = hnode_mgr->intf_fxns;
- status =
- (*intf_fxns->msg_get) (hnode->msg_queue_obj, message, utimeout);
- /* Check if message contains SM descriptor */
- if (status || !(message->cmd & DSP_RMSBUFDESC))
- goto func_end;
-
- /* Translate DSP byte addr to GPP Va. */
- tmp_buf = cmm_xlator_translate(hnode->xlator,
- (void *)(message->arg1 *
- hnode->node_mgr->
- dsp_word_size), CMM_DSPPA2PA);
- if (tmp_buf != NULL) {
- /* now convert this GPP Pa to Va */
- tmp_buf = cmm_xlator_translate(hnode->xlator, tmp_buf,
- CMM_PA2VA);
- if (tmp_buf != NULL) {
- /* Adjust SM size in msg */
- message->arg1 = (u32) tmp_buf;
- message->arg2 *= hnode->node_mgr->dsp_word_size;
- } else {
- status = -ESRCH;
- }
- } else {
- status = -ESRCH;
- }
-func_end:
- dev_dbg(bridge, "%s: hnode: %p message: %p utimeout: 0x%x\n", __func__,
- hnode, message, utimeout);
- return status;
-}
-
-/*
- * ======== node_get_nldr_obj ========
- */
-int node_get_nldr_obj(struct node_mgr *hnode_mgr,
- struct nldr_object **nldr_ovlyobj)
-{
- int status = 0;
- struct node_mgr *node_mgr_obj = hnode_mgr;
-
- if (!hnode_mgr)
- status = -EFAULT;
- else
- *nldr_ovlyobj = node_mgr_obj->nldr_obj;
-
- return status;
-}
-
-/*
- * ======== node_get_strm_mgr ========
- * Purpose:
- * Returns the Stream manager.
- */
-int node_get_strm_mgr(struct node_object *hnode,
- struct strm_mgr **strm_man)
-{
- int status = 0;
-
- if (!hnode)
- status = -EFAULT;
- else
- *strm_man = hnode->node_mgr->strm_mgr_obj;
-
- return status;
-}
-
-/*
- * ======== node_get_load_type ========
- */
-enum nldr_loadtype node_get_load_type(struct node_object *hnode)
-{
- if (!hnode) {
- dev_dbg(bridge, "%s: Failed. hnode: %p\n", __func__, hnode);
- return -1;
- } else {
- return hnode->dcd_props.obj_data.node_obj.load_type;
- }
-}
-
-/*
- * ======== node_get_timeout ========
- * Purpose:
- * Returns the timeout value for this node.
- */
-u32 node_get_timeout(struct node_object *hnode)
-{
- if (!hnode) {
- dev_dbg(bridge, "%s: failed. hnode: %p\n", __func__, hnode);
- return 0;
- } else {
- return hnode->timeout;
- }
-}
-
-/*
- * ======== node_get_type ========
- * Purpose:
- * Returns the node type.
- */
-enum node_type node_get_type(struct node_object *hnode)
-{
- enum node_type node_type;
-
- if (hnode == (struct node_object *)DSP_HGPPNODE)
- node_type = NODE_GPP;
- else {
- if (!hnode)
- node_type = -1;
- else
- node_type = hnode->ntype;
- }
- return node_type;
-}
-
-/*
- * ======== node_on_exit ========
- * Purpose:
- * Gets called when RMS_EXIT is received for a node.
- */
-void node_on_exit(struct node_object *hnode, s32 node_status)
-{
- if (!hnode)
- return;
-
- /* Set node state to done */
- NODE_SET_STATE(hnode, NODE_DONE);
- hnode->exit_status = node_status;
- if (hnode->loaded && hnode->phase_split) {
- (void)hnode->node_mgr->nldr_fxns.unload(hnode->
- nldr_node_obj,
- NLDR_EXECUTE);
- hnode->loaded = false;
- }
- /* Unblock call to node_terminate */
- (void)sync_set_event(hnode->sync_done);
- /* Notify clients */
- proc_notify_clients(hnode->processor, DSP_NODESTATECHANGE);
- ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
-}
-
-/*
- * ======== node_pause ========
- * Purpose:
- * Suspend execution of a node currently running on the DSP.
- */
-int node_pause(struct node_object *hnode)
-{
- struct node_object *pnode = (struct node_object *)hnode;
- enum node_type node_type;
- enum node_state state;
- struct node_mgr *hnode_mgr;
- int status = 0;
- u32 proc_id;
- struct dsp_processorstate proc_state;
- struct proc_object *hprocessor;
-
- if (!hnode) {
- status = -EFAULT;
- } else {
- node_type = node_get_type(hnode);
- if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET)
- status = -EPERM;
- }
- if (status)
- goto func_end;
-
- status = proc_get_processor_id(pnode->processor, &proc_id);
-
- if (proc_id == IVA_UNIT)
- status = -ENOSYS;
-
- if (!status) {
- hnode_mgr = hnode->node_mgr;
-
- /* Enter critical section */
- mutex_lock(&hnode_mgr->node_mgr_lock);
- state = node_get_state(hnode);
- /* Check node state */
- if (state != NODE_RUNNING)
- status = -EBADR;
-
- if (status)
- goto func_cont;
- hprocessor = hnode->processor;
- status = proc_get_state(hprocessor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_cont;
- /* If processor is in error state then don't attempt
- to send the message */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_cont;
- }
-
- status = disp_node_change_priority(hnode_mgr->disp_obj, hnode,
- hnode_mgr->fxn_addrs[RMSCHANGENODEPRIORITY],
- hnode->node_env, NODE_SUSPENDEDPRI);
-
- /* Update state */
- if (status >= 0)
- NODE_SET_STATE(hnode, NODE_PAUSED);
-
-func_cont:
- /* End of sync_enter_cs */
- /* Leave critical section */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- if (status >= 0) {
- proc_notify_clients(hnode->processor,
- DSP_NODESTATECHANGE);
- ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
- }
- }
-func_end:
- dev_dbg(bridge, "%s: hnode: %p status 0x%x\n", __func__, hnode, status);
- return status;
-}
-
-/*
- * ======== node_put_message ========
- * Purpose:
- * Send a message to a message node, task node, or XDAIS socket node. This
- * function will block until the message stream can accommodate the
- * message, or a timeout occurs.
- */
-int node_put_message(struct node_object *hnode,
- const struct dsp_msg *pmsg, u32 utimeout)
-{
- struct node_mgr *hnode_mgr = NULL;
- enum node_type node_type;
- struct bridge_drv_interface *intf_fxns;
- enum node_state state;
- int status = 0;
- void *tmp_buf;
- struct dsp_msg new_msg;
- struct dsp_processorstate proc_state;
- struct proc_object *hprocessor;
-
- if (!hnode) {
- status = -EFAULT;
- goto func_end;
- }
- hprocessor = hnode->processor;
- status = proc_get_state(hprocessor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_end;
- /* If processor is in bad state then don't attempt sending the
- message */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_end;
- }
- hnode_mgr = hnode->node_mgr;
- node_type = node_get_type(hnode);
- if (node_type != NODE_MESSAGE && node_type != NODE_TASK &&
- node_type != NODE_DAISSOCKET)
- status = -EPERM;
-
- if (!status) {
- /* Check node state. Can't send messages to a node after
- * we've sent the RMS_EXIT command. There is still the
- * possibility that node_terminate can be called after we've
- * checked the state. Could add another SYNC object to
- * prevent this (can't use node_mgr_lock, since we don't
- * want to block other NODE functions). However, the node may
- * still exit on its own, before this message is sent. */
- mutex_lock(&hnode_mgr->node_mgr_lock);
- state = node_get_state(hnode);
- if (state == NODE_TERMINATING || state == NODE_DONE)
- status = -EBADR;
-
- /* end of sync_enter_cs */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- }
- if (status)
- goto func_end;
-
- /* assign pmsg values to new msg */
- new_msg = *pmsg;
- /* Now, check if message contains a SM buffer descriptor */
- if (pmsg->cmd & DSP_RMSBUFDESC) {
- /* Translate GPP Va to DSP physical buf Ptr. */
- tmp_buf = cmm_xlator_translate(hnode->xlator,
- (void *)new_msg.arg1,
- CMM_VA2DSPPA);
- if (tmp_buf != NULL) {
- /* got translation, convert to MAUs in msg */
- if (hnode->node_mgr->dsp_word_size != 0) {
- new_msg.arg1 =
- (u32) tmp_buf /
- hnode->node_mgr->dsp_word_size;
- /* MAUs */
- new_msg.arg2 /= hnode->node_mgr->
- dsp_word_size;
- } else {
- pr_err("%s: dsp_word_size is zero!\n",
- __func__);
- status = -EPERM; /* bad DSPWordSize */
- }
- } else { /* failed to translate buffer address */
- status = -ESRCH;
- }
- }
- if (!status) {
- intf_fxns = hnode_mgr->intf_fxns;
- status = (*intf_fxns->msg_put) (hnode->msg_queue_obj,
- &new_msg, utimeout);
- }
-func_end:
- dev_dbg(bridge, "%s: hnode: %p pmsg: %p utimeout: 0x%x, "
- "status 0x%x\n", __func__, hnode, pmsg, utimeout, status);
- return status;
-}
-
-/*
- * ======== node_register_notify ========
- * Purpose:
- * Register to be notified on specific events for this node.
- */
-int node_register_notify(struct node_object *hnode, u32 event_mask,
- u32 notify_type,
- struct dsp_notification *hnotification)
-{
- struct bridge_drv_interface *intf_fxns;
- int status = 0;
-
- if (!hnode) {
- status = -EFAULT;
- } else {
- /* Check if event mask is a valid node related event */
- if (event_mask & ~(DSP_NODESTATECHANGE | DSP_NODEMESSAGEREADY))
- status = -EINVAL;
-
- /* Check if notify type is valid */
- if (notify_type != DSP_SIGNALEVENT)
- status = -EINVAL;
-
- /* Only one Notification can be registered at a
- * time - Limitation */
- if (event_mask == (DSP_NODESTATECHANGE | DSP_NODEMESSAGEREADY))
- status = -EINVAL;
- }
- if (!status) {
- if (event_mask == DSP_NODESTATECHANGE) {
- status = ntfy_register(hnode->ntfy_obj, hnotification,
- event_mask & DSP_NODESTATECHANGE,
- notify_type);
- } else {
- /* Send Message part of event mask to msg_ctrl */
- intf_fxns = hnode->node_mgr->intf_fxns;
- status = (*intf_fxns->msg_register_notify)
- (hnode->msg_queue_obj,
- event_mask & DSP_NODEMESSAGEREADY, notify_type,
- hnotification);
- }
-
- }
- dev_dbg(bridge, "%s: hnode: %p event_mask: 0x%x notify_type: 0x%x "
- "hnotification: %p status 0x%x\n", __func__, hnode,
- event_mask, notify_type, hnotification, status);
- return status;
-}
-
-/*
- * ======== node_run ========
- * Purpose:
- * Start execution of a node's execute phase, or resume execution of a node
- * that has been suspended (via NODE_NodePause()) on the DSP. Load the
- * node's execute function if necessary.
- */
-int node_run(struct node_object *hnode)
-{
- struct node_object *pnode = (struct node_object *)hnode;
- struct node_mgr *hnode_mgr;
- enum node_type node_type;
- enum node_state state;
- u32 ul_execute_fxn;
- u32 ul_fxn_addr;
- int status = 0;
- u32 proc_id;
- struct bridge_drv_interface *intf_fxns;
- struct dsp_processorstate proc_state;
- struct proc_object *hprocessor;
-
- if (!hnode) {
- status = -EFAULT;
- goto func_end;
- }
- hprocessor = hnode->processor;
- status = proc_get_state(hprocessor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_end;
- /* If processor is in error state then don't attempt to run the node */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_end;
- }
- node_type = node_get_type(hnode);
- if (node_type == NODE_DEVICE)
- status = -EPERM;
- if (status)
- goto func_end;
-
- hnode_mgr = hnode->node_mgr;
- if (!hnode_mgr) {
- status = -EFAULT;
- goto func_end;
- }
- intf_fxns = hnode_mgr->intf_fxns;
- /* Enter critical section */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- state = node_get_state(hnode);
- if (state != NODE_CREATED && state != NODE_PAUSED)
- status = -EBADR;
-
- if (!status)
- status = proc_get_processor_id(pnode->processor, &proc_id);
-
- if (status)
- goto func_cont1;
-
- if ((proc_id != DSP_UNIT) && (proc_id != IVA_UNIT))
- goto func_cont1;
-
- if (state == NODE_CREATED) {
- /* If node's execute function is not loaded, load it */
- if (!(hnode->loaded) && hnode->phase_split) {
- status =
- hnode_mgr->nldr_fxns.load(hnode->nldr_node_obj,
- NLDR_EXECUTE);
- if (!status) {
- hnode->loaded = true;
- } else {
- pr_err("%s: fail - load execute code: 0x%x\n",
- __func__, status);
- }
- }
- if (!status) {
- /* Get address of node's execute function */
- if (proc_id == IVA_UNIT)
- ul_execute_fxn = (u32) hnode->node_env;
- else {
- status = get_fxn_address(hnode, &ul_execute_fxn,
- EXECUTEPHASE);
- }
- }
- if (!status) {
- ul_fxn_addr = hnode_mgr->fxn_addrs[RMSEXECUTENODE];
- status =
- disp_node_run(hnode_mgr->disp_obj, hnode,
- ul_fxn_addr, ul_execute_fxn,
- hnode->node_env);
- }
- } else if (state == NODE_PAUSED) {
- ul_fxn_addr = hnode_mgr->fxn_addrs[RMSCHANGENODEPRIORITY];
- status = disp_node_change_priority(hnode_mgr->disp_obj, hnode,
- ul_fxn_addr, hnode->node_env,
- NODE_GET_PRIORITY(hnode));
- } else {
- /* We should never get here */
- }
-func_cont1:
- /* Update node state. */
- if (status >= 0)
- NODE_SET_STATE(hnode, NODE_RUNNING);
- else /* Set state back to previous value */
- NODE_SET_STATE(hnode, state);
- /*End of sync_enter_cs */
- /* Exit critical section */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- if (status >= 0) {
- proc_notify_clients(hnode->processor, DSP_NODESTATECHANGE);
- ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
- }
-func_end:
- dev_dbg(bridge, "%s: hnode: %p status 0x%x\n", __func__, hnode, status);
- return status;
-}
-
-/*
- * ======== node_terminate ========
- * Purpose:
- * Signal a node running on the DSP that it should exit its execute phase
- * function.
- */
-int node_terminate(struct node_object *hnode, int *pstatus)
-{
- struct node_object *pnode = (struct node_object *)hnode;
- struct node_mgr *hnode_mgr = NULL;
- enum node_type node_type;
- struct bridge_drv_interface *intf_fxns;
- enum node_state state;
- struct dsp_msg msg, killmsg;
- int status = 0;
- u32 proc_id, kill_time_out;
- struct deh_mgr *hdeh_mgr;
- struct dsp_processorstate proc_state;
-
- if (!hnode || !hnode->node_mgr) {
- status = -EFAULT;
- goto func_end;
- }
- if (pnode->processor == NULL) {
- status = -EFAULT;
- goto func_end;
- }
- status = proc_get_processor_id(pnode->processor, &proc_id);
-
- if (!status) {
- hnode_mgr = hnode->node_mgr;
- node_type = node_get_type(hnode);
- if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET)
- status = -EPERM;
- }
- if (!status) {
- /* Check node state */
- mutex_lock(&hnode_mgr->node_mgr_lock);
- state = node_get_state(hnode);
- if (state != NODE_RUNNING) {
- status = -EBADR;
- /* Set the exit status if node terminated on
- * its own. */
- if (state == NODE_DONE)
- *pstatus = hnode->exit_status;
-
- } else {
- NODE_SET_STATE(hnode, NODE_TERMINATING);
- }
- /* end of sync_enter_cs */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- }
- if (!status) {
- /*
- * Send exit message. Do not change state to NODE_DONE
- * here. That will be done in callback.
- */
- status = proc_get_state(pnode->processor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_cont;
- /* If processor is in error state then don't attempt to send
- * A kill task command */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_cont;
- }
-
- msg.cmd = RMS_EXIT;
- msg.arg1 = hnode->node_env;
- killmsg.cmd = RMS_KILLTASK;
- killmsg.arg1 = hnode->node_env;
- intf_fxns = hnode_mgr->intf_fxns;
-
- if (hnode->timeout > MAXTIMEOUT)
- kill_time_out = MAXTIMEOUT;
- else
- kill_time_out = (hnode->timeout) * 2;
-
- status = (*intf_fxns->msg_put) (hnode->msg_queue_obj, &msg,
- hnode->timeout);
- if (status)
- goto func_cont;
-
- /*
- * Wait on synchronization object that will be
- * posted in the callback on receiving RMS_EXIT
- * message, or by node_delete. Check for valid hnode,
- * in case posted by node_delete().
- */
- status = sync_wait_on_event(hnode->sync_done,
- kill_time_out / 2);
- if (status != ETIME)
- goto func_cont;
-
- status = (*intf_fxns->msg_put)(hnode->msg_queue_obj,
- &killmsg, hnode->timeout);
- if (status)
- goto func_cont;
- status = sync_wait_on_event(hnode->sync_done,
- kill_time_out / 2);
- if (status) {
- /*
- * Here it goes the part of the simulation of
- * the DSP exception.
- */
- dev_get_deh_mgr(hnode_mgr->dev_obj, &hdeh_mgr);
- if (!hdeh_mgr)
- goto func_cont;
-
- bridge_deh_notify(hdeh_mgr, DSP_SYSERROR,
- DSP_EXCEPTIONABORT);
- }
- }
-func_cont:
- if (!status) {
- /* Enter CS before getting exit status, in case node was
- * deleted. */
- mutex_lock(&hnode_mgr->node_mgr_lock);
- /* Make sure node wasn't deleted while we blocked */
- if (!hnode) {
- status = -EPERM;
- } else {
- *pstatus = hnode->exit_status;
- dev_dbg(bridge, "%s: hnode: %p env 0x%x status 0x%x\n",
- __func__, hnode, hnode->node_env, status);
- }
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- } /*End of sync_enter_cs */
-func_end:
- return status;
-}
-
-/*
- * ======== delete_node ========
- * Purpose:
- * Free GPP resources allocated in node_allocate() or node_connect().
- */
-static void delete_node(struct node_object *hnode,
- struct process_context *pr_ctxt)
-{
- struct node_mgr *hnode_mgr;
- struct bridge_drv_interface *intf_fxns;
- u32 i;
- enum node_type node_type;
- struct stream_chnl stream;
- struct node_msgargs node_msg_args;
- struct node_taskargs task_arg_obj;
-#ifdef DSP_DMM_DEBUG
- struct dmm_object *dmm_mgr;
- struct proc_object *p_proc_object =
- (struct proc_object *)hnode->processor;
-#endif
- int status;
-
- if (!hnode)
- goto func_end;
- hnode_mgr = hnode->node_mgr;
- if (!hnode_mgr)
- goto func_end;
-
- node_type = node_get_type(hnode);
- if (node_type != NODE_DEVICE) {
- node_msg_args = hnode->create_args.asa.node_msg_args;
- kfree(node_msg_args.pdata);
-
- /* Free msg_ctrl queue */
- if (hnode->msg_queue_obj) {
- intf_fxns = hnode_mgr->intf_fxns;
- (*intf_fxns->msg_delete_queue) (hnode->
- msg_queue_obj);
- hnode->msg_queue_obj = NULL;
- }
-
- kfree(hnode->sync_done);
-
- /* Free all stream info */
- if (hnode->inputs) {
- for (i = 0; i < MAX_INPUTS(hnode); i++) {
- stream = hnode->inputs[i];
- free_stream(hnode_mgr, stream);
- }
- kfree(hnode->inputs);
- hnode->inputs = NULL;
- }
- if (hnode->outputs) {
- for (i = 0; i < MAX_OUTPUTS(hnode); i++) {
- stream = hnode->outputs[i];
- free_stream(hnode_mgr, stream);
- }
- kfree(hnode->outputs);
- hnode->outputs = NULL;
- }
- task_arg_obj = hnode->create_args.asa.task_arg_obj;
- if (task_arg_obj.strm_in_def) {
- for (i = 0; i < MAX_INPUTS(hnode); i++) {
- kfree(task_arg_obj.strm_in_def[i].sz_device);
- task_arg_obj.strm_in_def[i].sz_device = NULL;
- }
- kfree(task_arg_obj.strm_in_def);
- task_arg_obj.strm_in_def = NULL;
- }
- if (task_arg_obj.strm_out_def) {
- for (i = 0; i < MAX_OUTPUTS(hnode); i++) {
- kfree(task_arg_obj.strm_out_def[i].sz_device);
- task_arg_obj.strm_out_def[i].sz_device = NULL;
- }
- kfree(task_arg_obj.strm_out_def);
- task_arg_obj.strm_out_def = NULL;
- }
- if (task_arg_obj.dsp_heap_res_addr) {
- status = proc_un_map(hnode->processor, (void *)
- task_arg_obj.dsp_heap_addr,
- pr_ctxt);
-
- status = proc_un_reserve_memory(hnode->processor,
- (void *)
- task_arg_obj.
- dsp_heap_res_addr,
- pr_ctxt);
-#ifdef DSP_DMM_DEBUG
- status = dmm_get_handle(p_proc_object, &dmm_mgr);
- if (dmm_mgr)
- dmm_mem_map_dump(dmm_mgr);
- else
- status = DSP_EHANDLE;
-#endif
- }
- }
- if (node_type != NODE_MESSAGE) {
- kfree(hnode->stream_connect);
- hnode->stream_connect = NULL;
- }
- kfree(hnode->str_dev_name);
- hnode->str_dev_name = NULL;
-
- if (hnode->ntfy_obj) {
- ntfy_delete(hnode->ntfy_obj);
- kfree(hnode->ntfy_obj);
- hnode->ntfy_obj = NULL;
- }
-
- /* These were allocated in dcd_get_object_def (via node_allocate) */
- kfree(hnode->dcd_props.obj_data.node_obj.str_create_phase_fxn);
- hnode->dcd_props.obj_data.node_obj.str_create_phase_fxn = NULL;
-
- kfree(hnode->dcd_props.obj_data.node_obj.str_execute_phase_fxn);
- hnode->dcd_props.obj_data.node_obj.str_execute_phase_fxn = NULL;
-
- kfree(hnode->dcd_props.obj_data.node_obj.str_delete_phase_fxn);
- hnode->dcd_props.obj_data.node_obj.str_delete_phase_fxn = NULL;
-
- kfree(hnode->dcd_props.obj_data.node_obj.str_i_alg_name);
- hnode->dcd_props.obj_data.node_obj.str_i_alg_name = NULL;
-
- /* Free all SM address translator resources */
- kfree(hnode->xlator);
- kfree(hnode->nldr_node_obj);
- hnode->nldr_node_obj = NULL;
- hnode->node_mgr = NULL;
- kfree(hnode);
- hnode = NULL;
-func_end:
- return;
-}
-
-/*
- * ======== delete_node_mgr ========
- * Purpose:
- * Frees the node manager.
- */
-static void delete_node_mgr(struct node_mgr *hnode_mgr)
-{
- struct node_object *hnode, *tmp;
-
- if (hnode_mgr) {
- /* Free resources */
- if (hnode_mgr->dcd_mgr)
- dcd_destroy_manager(hnode_mgr->dcd_mgr);
-
- /* Remove any elements remaining in lists */
- list_for_each_entry_safe(hnode, tmp, &hnode_mgr->node_list,
- list_elem) {
- list_del(&hnode->list_elem);
- delete_node(hnode, NULL);
- }
- mutex_destroy(&hnode_mgr->node_mgr_lock);
- if (hnode_mgr->ntfy_obj) {
- ntfy_delete(hnode_mgr->ntfy_obj);
- kfree(hnode_mgr->ntfy_obj);
- }
-
- if (hnode_mgr->disp_obj)
- disp_delete(hnode_mgr->disp_obj);
-
- if (hnode_mgr->strm_mgr_obj)
- strm_delete(hnode_mgr->strm_mgr_obj);
-
- /* Delete the loader */
- if (hnode_mgr->nldr_obj)
- hnode_mgr->nldr_fxns.delete(hnode_mgr->nldr_obj);
-
- kfree(hnode_mgr);
- }
-}
-
-/*
- * ======== fill_stream_connect ========
- * Purpose:
- * Fills stream information.
- */
-static void fill_stream_connect(struct node_object *node1,
- struct node_object *node2,
- u32 stream1, u32 stream2)
-{
- u32 strm_index;
- struct dsp_streamconnect *strm1 = NULL;
- struct dsp_streamconnect *strm2 = NULL;
- enum node_type node1_type = NODE_TASK;
- enum node_type node2_type = NODE_TASK;
-
- node1_type = node_get_type(node1);
- node2_type = node_get_type(node2);
- if (node1 != (struct node_object *)DSP_HGPPNODE) {
-
- if (node1_type != NODE_DEVICE) {
- strm_index = node1->num_inputs +
- node1->num_outputs - 1;
- strm1 = &(node1->stream_connect[strm_index]);
- strm1->cb_struct = sizeof(struct dsp_streamconnect);
- strm1->this_node_stream_index = stream1;
- }
-
- if (node2 != (struct node_object *)DSP_HGPPNODE) {
- /* NODE == > NODE */
- if (node1_type != NODE_DEVICE) {
- strm1->connected_node = node2;
- strm1->ui_connected_node_id = node2->node_uuid;
- strm1->connected_node_stream_index = stream2;
- strm1->connect_type = CONNECTTYPE_NODEOUTPUT;
- }
- if (node2_type != NODE_DEVICE) {
- strm_index = node2->num_inputs +
- node2->num_outputs - 1;
- strm2 = &(node2->stream_connect[strm_index]);
- strm2->cb_struct =
- sizeof(struct dsp_streamconnect);
- strm2->this_node_stream_index = stream2;
- strm2->connected_node = node1;
- strm2->ui_connected_node_id = node1->node_uuid;
- strm2->connected_node_stream_index = stream1;
- strm2->connect_type = CONNECTTYPE_NODEINPUT;
- }
- } else if (node1_type != NODE_DEVICE)
- strm1->connect_type = CONNECTTYPE_GPPOUTPUT;
- } else {
- /* GPP == > NODE */
- strm_index = node2->num_inputs + node2->num_outputs - 1;
- strm2 = &(node2->stream_connect[strm_index]);
- strm2->cb_struct = sizeof(struct dsp_streamconnect);
- strm2->this_node_stream_index = stream2;
- strm2->connect_type = CONNECTTYPE_GPPINPUT;
- }
-}
-
-/*
- * ======== fill_stream_def ========
- * Purpose:
- * Fills Stream attributes.
- */
-static void fill_stream_def(struct node_object *hnode,
- struct node_strmdef *pstrm_def,
- struct dsp_strmattr *pattrs)
-{
- struct node_mgr *hnode_mgr = hnode->node_mgr;
-
- if (pattrs != NULL) {
- pstrm_def->num_bufs = pattrs->num_bufs;
- pstrm_def->buf_size =
- pattrs->buf_size / hnode_mgr->dsp_data_mau_size;
- pstrm_def->seg_id = pattrs->seg_id;
- pstrm_def->buf_alignment = pattrs->buf_alignment;
- pstrm_def->timeout = pattrs->timeout;
- } else {
- pstrm_def->num_bufs = DEFAULTNBUFS;
- pstrm_def->buf_size =
- DEFAULTBUFSIZE / hnode_mgr->dsp_data_mau_size;
- pstrm_def->seg_id = DEFAULTSEGID;
- pstrm_def->buf_alignment = DEFAULTALIGNMENT;
- pstrm_def->timeout = DEFAULTTIMEOUT;
- }
-}
-
-/*
- * ======== free_stream ========
- * Purpose:
- * Updates the channel mask and frees the pipe id.
- */
-static void free_stream(struct node_mgr *hnode_mgr, struct stream_chnl stream)
-{
- /* Free up the pipe id unless other node has not yet been deleted. */
- if (stream.type == NODECONNECT) {
- if (test_bit(stream.dev_id, hnode_mgr->pipe_done_map)) {
- /* The other node has already been deleted */
- clear_bit(stream.dev_id, hnode_mgr->pipe_done_map);
- clear_bit(stream.dev_id, hnode_mgr->pipe_map);
- } else {
- /* The other node has not been deleted yet */
- set_bit(stream.dev_id, hnode_mgr->pipe_done_map);
- }
- } else if (stream.type == HOSTCONNECT) {
- if (stream.dev_id < hnode_mgr->num_chnls) {
- clear_bit(stream.dev_id, hnode_mgr->chnl_map);
- } else if (stream.dev_id < (2 * hnode_mgr->num_chnls)) {
- /* dsp-dma */
- clear_bit(stream.dev_id - (1 * hnode_mgr->num_chnls),
- hnode_mgr->dma_chnl_map);
- } else if (stream.dev_id < (3 * hnode_mgr->num_chnls)) {
- /* zero-copy */
- clear_bit(stream.dev_id - (2 * hnode_mgr->num_chnls),
- hnode_mgr->zc_chnl_map);
- }
- }
-}
-
-/*
- * ======== get_fxn_address ========
- * Purpose:
- * Retrieves the address for create, execute or delete phase for a node.
- */
-static int get_fxn_address(struct node_object *hnode, u32 *fxn_addr,
- u32 phase)
-{
- char *pstr_fxn_name = NULL;
- struct node_mgr *hnode_mgr = hnode->node_mgr;
- int status = 0;
-
- switch (phase) {
- case CREATEPHASE:
- pstr_fxn_name =
- hnode->dcd_props.obj_data.node_obj.str_create_phase_fxn;
- break;
- case EXECUTEPHASE:
- pstr_fxn_name =
- hnode->dcd_props.obj_data.node_obj.str_execute_phase_fxn;
- break;
- case DELETEPHASE:
- pstr_fxn_name =
- hnode->dcd_props.obj_data.node_obj.str_delete_phase_fxn;
- break;
- default:
- /* Should never get here */
- break;
- }
-
- status =
- hnode_mgr->nldr_fxns.get_fxn_addr(hnode->nldr_node_obj,
- pstr_fxn_name, fxn_addr);
-
- return status;
-}
-
-/*
- * ======== get_node_info ========
- * Purpose:
- * Retrieves the node information.
- */
-void get_node_info(struct node_object *hnode, struct dsp_nodeinfo *node_info)
-{
- u32 i;
-
- node_info->cb_struct = sizeof(struct dsp_nodeinfo);
- node_info->nb_node_database_props =
- hnode->dcd_props.obj_data.node_obj.ndb_props;
- node_info->execution_priority = hnode->prio;
- node_info->device_owner = hnode->device_owner;
- node_info->number_streams = hnode->num_inputs + hnode->num_outputs;
- node_info->node_env = hnode->node_env;
-
- node_info->ns_execution_state = node_get_state(hnode);
-
- /* Copy stream connect data */
- for (i = 0; i < hnode->num_inputs + hnode->num_outputs; i++)
- node_info->sc_stream_connection[i] = hnode->stream_connect[i];
-
-}
-
-/*
- * ======== get_node_props ========
- * Purpose:
- * Retrieve node properties.
- */
-static int get_node_props(struct dcd_manager *hdcd_mgr,
- struct node_object *hnode,
- const struct dsp_uuid *node_uuid,
- struct dcd_genericobj *dcd_prop)
-{
- u32 len;
- struct node_msgargs *pmsg_args;
- struct node_taskargs *task_arg_obj;
- enum node_type node_type = NODE_TASK;
- struct dsp_ndbprops *pndb_props =
- &(dcd_prop->obj_data.node_obj.ndb_props);
- int status = 0;
- char sz_uuid[MAXUUIDLEN];
-
- status = dcd_get_object_def(hdcd_mgr, (struct dsp_uuid *)node_uuid,
- DSP_DCDNODETYPE, dcd_prop);
-
- if (!status) {
- hnode->ntype = node_type = pndb_props->ntype;
-
- /* Create UUID value to set in registry. */
- snprintf(sz_uuid, MAXUUIDLEN, "%pUL", node_uuid);
- dev_dbg(bridge, "(node) UUID: %s\n", sz_uuid);
-
- /* Fill in message args that come from NDB */
- if (node_type != NODE_DEVICE) {
- pmsg_args = &(hnode->create_args.asa.node_msg_args);
- pmsg_args->seg_id =
- dcd_prop->obj_data.node_obj.msg_segid;
- pmsg_args->notify_type =
- dcd_prop->obj_data.node_obj.msg_notify_type;
- pmsg_args->max_msgs = pndb_props->message_depth;
- dev_dbg(bridge, "(node) Max Number of Messages: 0x%x\n",
- pmsg_args->max_msgs);
- } else {
- /* Copy device name */
- len = strlen(pndb_props->ac_name);
- hnode->str_dev_name = kzalloc(len + 1, GFP_KERNEL);
- if (hnode->str_dev_name == NULL) {
- status = -ENOMEM;
- } else {
- strncpy(hnode->str_dev_name,
- pndb_props->ac_name, len);
- }
- }
- }
- if (!status) {
- /* Fill in create args that come from NDB */
- if (node_type == NODE_TASK || node_type == NODE_DAISSOCKET) {
- task_arg_obj = &(hnode->create_args.asa.task_arg_obj);
- task_arg_obj->prio = pndb_props->prio;
- task_arg_obj->stack_size = pndb_props->stack_size;
- task_arg_obj->sys_stack_size =
- pndb_props->sys_stack_size;
- task_arg_obj->stack_seg = pndb_props->stack_seg;
- dev_dbg(bridge, "(node) Priority: 0x%x Stack Size: "
- "0x%x words System Stack Size: 0x%x words "
- "Stack Segment: 0x%x profile count : 0x%x\n",
- task_arg_obj->prio, task_arg_obj->stack_size,
- task_arg_obj->sys_stack_size,
- task_arg_obj->stack_seg,
- pndb_props->count_profiles);
- }
- }
-
- return status;
-}
-
-/*
- * ======== get_proc_props ========
- * Purpose:
- * Retrieve the processor properties.
- */
-static int get_proc_props(struct node_mgr *hnode_mgr,
- struct dev_object *hdev_obj)
-{
- struct cfg_hostres *host_res;
- struct bridge_dev_context *pbridge_context;
- int status = 0;
-
- status = dev_get_bridge_context(hdev_obj, &pbridge_context);
- if (!pbridge_context)
- status = -EFAULT;
-
- if (!status) {
- host_res = pbridge_context->resources;
- if (!host_res)
- return -EPERM;
- hnode_mgr->chnl_offset = host_res->chnl_offset;
- hnode_mgr->chnl_buf_size = host_res->chnl_buf_size;
- hnode_mgr->num_chnls = host_res->num_chnls;
-
- /*
- * PROC will add an API to get dsp_processorinfo.
- * Fill in default values for now.
- */
- /* TODO -- Instead of hard coding, take from registry */
- hnode_mgr->proc_family = 6000;
- hnode_mgr->proc_type = 6410;
- hnode_mgr->min_pri = DSP_NODE_MIN_PRIORITY;
- hnode_mgr->max_pri = DSP_NODE_MAX_PRIORITY;
- hnode_mgr->dsp_word_size = DSPWORDSIZE;
- hnode_mgr->dsp_data_mau_size = DSPWORDSIZE;
- hnode_mgr->dsp_mau_size = 1;
-
- }
- return status;
-}
-
-/*
- * ======== node_get_uuid_props ========
- * Purpose:
- * Fetch Node UUID properties from DCD/DOF file.
- */
-int node_get_uuid_props(void *hprocessor,
- const struct dsp_uuid *node_uuid,
- struct dsp_ndbprops *node_props)
-{
- struct node_mgr *hnode_mgr = NULL;
- struct dev_object *hdev_obj;
- int status = 0;
- struct dcd_nodeprops dcd_node_props;
- struct dsp_processorstate proc_state;
-
- if (hprocessor == NULL || node_uuid == NULL) {
- status = -EFAULT;
- goto func_end;
- }
- status = proc_get_state(hprocessor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_end;
- /* If processor is in error state then don't attempt
- to send the message */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_end;
- }
-
- status = proc_get_dev_object(hprocessor, &hdev_obj);
- if (hdev_obj) {
- status = dev_get_node_manager(hdev_obj, &hnode_mgr);
- if (hnode_mgr == NULL) {
- status = -EFAULT;
- goto func_end;
- }
- }
-
- /*
- * Enter the critical section. This is needed because
- * dcd_get_object_def will ultimately end up calling dbll_open/close,
- * which needs to be protected in order to not corrupt the zlib manager
- * (COD).
- */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- dcd_node_props.str_create_phase_fxn = NULL;
- dcd_node_props.str_execute_phase_fxn = NULL;
- dcd_node_props.str_delete_phase_fxn = NULL;
- dcd_node_props.str_i_alg_name = NULL;
-
- status = dcd_get_object_def(hnode_mgr->dcd_mgr,
- (struct dsp_uuid *)node_uuid, DSP_DCDNODETYPE,
- (struct dcd_genericobj *)&dcd_node_props);
-
- if (!status) {
- *node_props = dcd_node_props.ndb_props;
- kfree(dcd_node_props.str_create_phase_fxn);
-
- kfree(dcd_node_props.str_execute_phase_fxn);
-
- kfree(dcd_node_props.str_delete_phase_fxn);
-
- kfree(dcd_node_props.str_i_alg_name);
- }
- /* Leave the critical section, we're done. */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
-func_end:
- return status;
-}
-
-/*
- * ======== get_rms_fxns ========
- * Purpose:
- * Retrieve the RMS functions.
- */
-static int get_rms_fxns(struct node_mgr *hnode_mgr)
-{
- s32 i;
- struct dev_object *dev_obj = hnode_mgr->dev_obj;
- int status = 0;
-
- static char *psz_fxns[NUMRMSFXNS] = {
- "RMS_queryServer", /* RMSQUERYSERVER */
- "RMS_configureServer", /* RMSCONFIGURESERVER */
- "RMS_createNode", /* RMSCREATENODE */
- "RMS_executeNode", /* RMSEXECUTENODE */
- "RMS_deleteNode", /* RMSDELETENODE */
- "RMS_changeNodePriority", /* RMSCHANGENODEPRIORITY */
- "RMS_readMemory", /* RMSREADMEMORY */
- "RMS_writeMemory", /* RMSWRITEMEMORY */
- "RMS_copy", /* RMSCOPY */
- };
-
- for (i = 0; i < NUMRMSFXNS; i++) {
- status = dev_get_symbol(dev_obj, psz_fxns[i],
- &(hnode_mgr->fxn_addrs[i]));
- if (status) {
- if (status == -ESPIPE) {
- /*
- * May be loaded dynamically (in the future),
- * but return an error for now.
- */
- dev_dbg(bridge, "%s: RMS function: %s currently"
- " not loaded\n", __func__, psz_fxns[i]);
- } else {
- dev_dbg(bridge, "%s: Symbol not found: %s "
- "status = 0x%x\n", __func__,
- psz_fxns[i], status);
- break;
- }
- }
- }
-
- return status;
-}
-
-/*
- * ======== ovly ========
- * Purpose:
- * Called during overlay.Sends command to RMS to copy a block of data.
- */
-static u32 ovly(void *priv_ref, u32 dsp_run_addr, u32 dsp_load_addr,
- u32 ul_num_bytes, u32 mem_space)
-{
- struct node_object *hnode = (struct node_object *)priv_ref;
- struct node_mgr *hnode_mgr;
- u32 ul_bytes = 0;
- u32 ul_size;
- u32 ul_timeout;
- int status = 0;
- struct bridge_dev_context *hbridge_context;
- /* Function interface to Bridge driver*/
- struct bridge_drv_interface *intf_fxns;
-
- hnode_mgr = hnode->node_mgr;
-
- ul_size = ul_num_bytes / hnode_mgr->dsp_word_size;
- ul_timeout = hnode->timeout;
-
- /* Call new MemCopy function */
- intf_fxns = hnode_mgr->intf_fxns;
- status = dev_get_bridge_context(hnode_mgr->dev_obj, &hbridge_context);
- if (!status) {
- status =
- (*intf_fxns->brd_mem_copy) (hbridge_context,
- dsp_run_addr, dsp_load_addr,
- ul_num_bytes, (u32) mem_space);
- if (!status)
- ul_bytes = ul_num_bytes;
- else
- pr_debug("%s: failed to copy brd memory, status 0x%x\n",
- __func__, status);
- } else {
- pr_debug("%s: failed to get Bridge context, status 0x%x\n",
- __func__, status);
- }
-
- return ul_bytes;
-}
-
-/*
- * ======== mem_write ========
- */
-static u32 mem_write(void *priv_ref, u32 dsp_add, void *pbuf,
- u32 ul_num_bytes, u32 mem_space)
-{
- struct node_object *hnode = (struct node_object *)priv_ref;
- struct node_mgr *hnode_mgr;
- u16 mem_sect_type;
- u32 ul_timeout;
- int status = 0;
- struct bridge_dev_context *hbridge_context;
- /* Function interface to Bridge driver */
- struct bridge_drv_interface *intf_fxns;
-
- hnode_mgr = hnode->node_mgr;
-
- ul_timeout = hnode->timeout;
- mem_sect_type = (mem_space & DBLL_CODE) ? RMS_CODE : RMS_DATA;
-
- /* Call new MemWrite function */
- intf_fxns = hnode_mgr->intf_fxns;
- status = dev_get_bridge_context(hnode_mgr->dev_obj, &hbridge_context);
- status = (*intf_fxns->brd_mem_write) (hbridge_context, pbuf,
- dsp_add, ul_num_bytes, mem_sect_type);
-
- return ul_num_bytes;
-}
-
-#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
-/*
- * ======== node_find_addr ========
- */
-int node_find_addr(struct node_mgr *node_mgr, u32 sym_addr,
- u32 offset_range, void *sym_addr_output, char *sym_name)
-{
- struct node_object *node_obj;
- int status = -ENOENT;
-
- list_for_each_entry(node_obj, &node_mgr->node_list, list_elem) {
- status = nldr_find_addr(node_obj->nldr_node_obj, sym_addr,
- offset_range, sym_addr_output, sym_name);
- if (!status) {
- pr_debug("%s(0x%x, 0x%x, 0x%x, 0x%x, %s)\n", __func__,
- (unsigned int) node_mgr,
- sym_addr, offset_range,
- (unsigned int) sym_addr_output, sym_name);
- break;
- }
- }
-
- return status;
-}
-#endif
diff --git a/drivers/staging/tidspbridge/rmgr/proc.c b/drivers/staging/tidspbridge/rmgr/proc.c
deleted file mode 100644
index 23e5146989b1..000000000000
--- a/drivers/staging/tidspbridge/rmgr/proc.c
+++ /dev/null
@@ -1,1836 +0,0 @@
-/*
- * proc.c
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * Processor interface at the driver level.
- *
- * 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 <linux/dma-mapping.h>
-#include <linux/scatterlist.h>
-#include <dspbridge/host_os.h>
-
-/* ----------------------------------- DSP/BIOS Bridge */
-#include <dspbridge/dbdefs.h>
-
-/* ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/ntfy.h>
-#include <dspbridge/sync.h>
-/* ----------------------------------- Bridge Driver */
-#include <dspbridge/dspdefs.h>
-#include <dspbridge/dspdeh.h>
-/* ----------------------------------- Platform Manager */
-#include <dspbridge/cod.h>
-#include <dspbridge/dev.h>
-#include <dspbridge/procpriv.h>
-#include <dspbridge/dmm.h>
-
-/* ----------------------------------- Resource Manager */
-#include <dspbridge/mgr.h>
-#include <dspbridge/node.h>
-#include <dspbridge/nldr.h>
-#include <dspbridge/rmm.h>
-
-/* ----------------------------------- Others */
-#include <dspbridge/dbdcd.h>
-#include <dspbridge/msg.h>
-#include <dspbridge/dspioctl.h>
-#include <dspbridge/drv.h>
-
-/* ----------------------------------- This */
-#include <dspbridge/proc.h>
-#include <dspbridge/pwr.h>
-
-#include <dspbridge/resourcecleanup.h>
-/* ----------------------------------- Defines, Data Structures, Typedefs */
-#define MAXCMDLINELEN 255
-#define PROC_ENVPROCID "PROC_ID=%d"
-#define MAXPROCIDLEN (8 + 5)
-#define PROC_DFLT_TIMEOUT 10000 /* Time out in milliseconds */
-#define PWR_TIMEOUT 500 /* Sleep/wake timout in msec */
-#define EXTEND "_EXT_END" /* Extmem end addr in DSP binary */
-
-#define DSP_CACHE_LINE 128
-
-#define BUFMODE_MASK (3 << 14)
-
-/* Buffer modes from DSP perspective */
-#define RBUF 0x4000 /* Input buffer */
-#define WBUF 0x8000 /* Output Buffer */
-
-extern struct device *bridge;
-
-/* ----------------------------------- Globals */
-
-/* The proc_object structure. */
-struct proc_object {
- struct list_head link; /* Link to next proc_object */
- struct dev_object *dev_obj; /* Device this PROC represents */
- u32 process; /* Process owning this Processor */
- struct mgr_object *mgr_obj; /* Manager Object Handle */
- u32 attach_count; /* Processor attach count */
- u32 processor_id; /* Processor number */
- u32 timeout; /* Time out count */
- enum dsp_procstate proc_state; /* Processor state */
- u32 unit; /* DDSP unit number */
- bool is_already_attached; /*
- * True if the Device below has
- * GPP Client attached
- */
- struct ntfy_object *ntfy_obj; /* Manages notifications */
- /* Bridge Context Handle */
- struct bridge_dev_context *bridge_context;
- /* Function interface to Bridge driver */
- struct bridge_drv_interface *intf_fxns;
- char *last_coff;
- struct list_head proc_list;
-};
-
-DEFINE_MUTEX(proc_lock); /* For critical sections */
-
-/* ----------------------------------- Function Prototypes */
-static int proc_monitor(struct proc_object *proc_obj);
-static s32 get_envp_count(char **envp);
-static char **prepend_envp(char **new_envp, char **envp, s32 envp_elems,
- s32 cnew_envp, char *sz_var);
-
-/* remember mapping information */
-static struct dmm_map_object *add_mapping_info(struct process_context *pr_ctxt,
- u32 mpu_addr, u32 dsp_addr, u32 size)
-{
- struct dmm_map_object *map_obj;
-
- u32 num_usr_pgs = size / PG_SIZE4K;
-
- pr_debug("%s: adding map info: mpu_addr 0x%x virt 0x%x size 0x%x\n",
- __func__, mpu_addr,
- dsp_addr, size);
-
- map_obj = kzalloc(sizeof(struct dmm_map_object), GFP_KERNEL);
- if (!map_obj)
- return NULL;
-
- INIT_LIST_HEAD(&map_obj->link);
-
- map_obj->pages = kcalloc(num_usr_pgs, sizeof(struct page *),
- GFP_KERNEL);
- if (!map_obj->pages) {
- kfree(map_obj);
- return NULL;
- }
-
- map_obj->mpu_addr = mpu_addr;
- map_obj->dsp_addr = dsp_addr;
- map_obj->size = size;
- map_obj->num_usr_pgs = num_usr_pgs;
-
- spin_lock(&pr_ctxt->dmm_map_lock);
- list_add(&map_obj->link, &pr_ctxt->dmm_map_list);
- spin_unlock(&pr_ctxt->dmm_map_lock);
-
- return map_obj;
-}
-
-static int match_exact_map_obj(struct dmm_map_object *map_obj,
- u32 dsp_addr, u32 size)
-{
- if (map_obj->dsp_addr == dsp_addr && map_obj->size != size)
- pr_err("%s: addr match (0x%x), size don't (0x%x != 0x%x)\n",
- __func__, dsp_addr, map_obj->size, size);
-
- return map_obj->dsp_addr == dsp_addr &&
- map_obj->size == size;
-}
-
-static void remove_mapping_information(struct process_context *pr_ctxt,
- u32 dsp_addr, u32 size)
-{
- struct dmm_map_object *map_obj;
-
- pr_debug("%s: looking for virt 0x%x size 0x%x\n", __func__,
- dsp_addr, size);
-
- spin_lock(&pr_ctxt->dmm_map_lock);
- list_for_each_entry(map_obj, &pr_ctxt->dmm_map_list, link) {
- pr_debug("%s: candidate: mpu_addr 0x%x virt 0x%x size 0x%x\n",
- __func__,
- map_obj->mpu_addr,
- map_obj->dsp_addr,
- map_obj->size);
-
- if (match_exact_map_obj(map_obj, dsp_addr, size)) {
- pr_debug("%s: match, deleting map info\n", __func__);
- list_del(&map_obj->link);
- kfree(map_obj->dma_info.sg);
- kfree(map_obj->pages);
- kfree(map_obj);
- goto out;
- }
- pr_debug("%s: candidate didn't match\n", __func__);
- }
-
- pr_err("%s: failed to find given map info\n", __func__);
-out:
- spin_unlock(&pr_ctxt->dmm_map_lock);
-}
-
-static int match_containing_map_obj(struct dmm_map_object *map_obj,
- u32 mpu_addr, u32 size)
-{
- u32 map_obj_end = map_obj->mpu_addr + map_obj->size;
-
- return mpu_addr >= map_obj->mpu_addr &&
- mpu_addr + size <= map_obj_end;
-}
-
-static struct dmm_map_object *find_containing_mapping(
- struct process_context *pr_ctxt,
- u32 mpu_addr, u32 size)
-{
- struct dmm_map_object *map_obj;
-
- pr_debug("%s: looking for mpu_addr 0x%x size 0x%x\n", __func__,
- mpu_addr, size);
-
- spin_lock(&pr_ctxt->dmm_map_lock);
- list_for_each_entry(map_obj, &pr_ctxt->dmm_map_list, link) {
- pr_debug("%s: candidate: mpu_addr 0x%x virt 0x%x size 0x%x\n",
- __func__,
- map_obj->mpu_addr,
- map_obj->dsp_addr,
- map_obj->size);
- if (match_containing_map_obj(map_obj, mpu_addr, size)) {
- pr_debug("%s: match!\n", __func__);
- goto out;
- }
-
- pr_debug("%s: no match!\n", __func__);
- }
-
- map_obj = NULL;
-out:
- spin_unlock(&pr_ctxt->dmm_map_lock);
- return map_obj;
-}
-
-static int find_first_page_in_cache(struct dmm_map_object *map_obj,
- unsigned long mpu_addr)
-{
- u32 mapped_base_page = map_obj->mpu_addr >> PAGE_SHIFT;
- u32 requested_base_page = mpu_addr >> PAGE_SHIFT;
- int pg_index = requested_base_page - mapped_base_page;
-
- if (pg_index < 0 || pg_index >= map_obj->num_usr_pgs) {
- pr_err("%s: failed (got %d)\n", __func__, pg_index);
- return -1;
- }
-
- pr_debug("%s: first page is %d\n", __func__, pg_index);
- return pg_index;
-}
-
-static inline struct page *get_mapping_page(struct dmm_map_object *map_obj,
- int pg_i)
-{
- pr_debug("%s: looking for pg_i %d, num_usr_pgs: %d\n", __func__,
- pg_i, map_obj->num_usr_pgs);
-
- if (pg_i < 0 || pg_i >= map_obj->num_usr_pgs) {
- pr_err("%s: requested pg_i %d is out of mapped range\n",
- __func__, pg_i);
- return NULL;
- }
-
- return map_obj->pages[pg_i];
-}
-
-/*
- * ======== proc_attach ========
- * Purpose:
- * Prepare for communication with a particular DSP processor, and return
- * a handle to the processor object.
- */
-int
-proc_attach(u32 processor_id,
- const struct dsp_processorattrin *attr_in,
- void **ph_processor, struct process_context *pr_ctxt)
-{
- int status = 0;
- struct dev_object *hdev_obj;
- struct proc_object *p_proc_object = NULL;
- struct mgr_object *hmgr_obj = NULL;
- struct drv_object *hdrv_obj = NULL;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
- u8 dev_type;
-
- if (pr_ctxt->processor) {
- *ph_processor = pr_ctxt->processor;
- return status;
- }
-
- /* Get the Driver and Manager Object Handles */
- if (!drv_datap || !drv_datap->drv_object || !drv_datap->mgr_object) {
- status = -ENODATA;
- pr_err("%s: Failed to get object handles\n", __func__);
- } else {
- hdrv_obj = drv_datap->drv_object;
- hmgr_obj = drv_datap->mgr_object;
- }
-
- if (!status) {
- /* Get the Device Object */
- status = drv_get_dev_object(processor_id, hdrv_obj, &hdev_obj);
- }
- if (!status)
- status = dev_get_dev_type(hdev_obj, &dev_type);
-
- if (status)
- goto func_end;
-
- /* If we made it this far, create the Processor object: */
- p_proc_object = kzalloc(sizeof(struct proc_object), GFP_KERNEL);
- /* Fill out the Processor Object: */
- if (p_proc_object == NULL) {
- status = -ENOMEM;
- goto func_end;
- }
- p_proc_object->dev_obj = hdev_obj;
- p_proc_object->mgr_obj = hmgr_obj;
- p_proc_object->processor_id = dev_type;
- /* Store TGID instead of process handle */
- p_proc_object->process = current->tgid;
-
- INIT_LIST_HEAD(&p_proc_object->proc_list);
-
- if (attr_in)
- p_proc_object->timeout = attr_in->timeout;
- else
- p_proc_object->timeout = PROC_DFLT_TIMEOUT;
-
- status = dev_get_intf_fxns(hdev_obj, &p_proc_object->intf_fxns);
- if (!status) {
- status = dev_get_bridge_context(hdev_obj,
- &p_proc_object->bridge_context);
- if (status)
- kfree(p_proc_object);
- } else
- kfree(p_proc_object);
-
- if (status)
- goto func_end;
-
- /* Create the Notification Object */
- /* This is created with no event mask, no notify mask
- * and no valid handle to the notification. They all get
- * filled up when proc_register_notify is called */
- p_proc_object->ntfy_obj = kmalloc(sizeof(struct ntfy_object),
- GFP_KERNEL);
- if (p_proc_object->ntfy_obj)
- ntfy_init(p_proc_object->ntfy_obj);
- else
- status = -ENOMEM;
-
- if (!status) {
- /* Insert the Processor Object into the DEV List.
- * Return handle to this Processor Object:
- * Find out if the Device is already attached to a
- * Processor. If so, return AlreadyAttached status */
- status = dev_insert_proc_object(p_proc_object->dev_obj,
- (u32) p_proc_object,
- &p_proc_object->
- is_already_attached);
- if (!status) {
- if (p_proc_object->is_already_attached)
- status = 0;
- } else {
- if (p_proc_object->ntfy_obj) {
- ntfy_delete(p_proc_object->ntfy_obj);
- kfree(p_proc_object->ntfy_obj);
- }
-
- kfree(p_proc_object);
- }
- if (!status) {
- *ph_processor = (void *)p_proc_object;
- pr_ctxt->processor = *ph_processor;
- (void)proc_notify_clients(p_proc_object,
- DSP_PROCESSORATTACH);
- }
- } else {
- /* Don't leak memory if status is failed */
- kfree(p_proc_object);
- }
-func_end:
- return status;
-}
-
-static int get_exec_file(struct cfg_devnode *dev_node_obj,
- struct dev_object *hdev_obj,
- u32 size, char *exec_file)
-{
- u8 dev_type;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
-
- dev_get_dev_type(hdev_obj, (u8 *) &dev_type);
-
- if (!exec_file)
- return -EFAULT;
-
- if (dev_type == DSP_UNIT) {
- if (!drv_datap || !drv_datap->base_img)
- return -EFAULT;
-
- if (strlen(drv_datap->base_img) >= size)
- return -EINVAL;
-
- strcpy(exec_file, drv_datap->base_img);
- } else {
- return -ENOENT;
- }
-
- return 0;
-}
-
-/*
- * ======== proc_auto_start ======== =
- * Purpose:
- * A Particular device gets loaded with the default image
- * if the AutoStart flag is set.
- * Parameters:
- * hdev_obj: Handle to the Device
- * Returns:
- * 0: On Successful Loading
- * -EPERM General Failure
- * Requires:
- * hdev_obj != NULL
- * Ensures:
- */
-int proc_auto_start(struct cfg_devnode *dev_node_obj,
- struct dev_object *hdev_obj)
-{
- int status = -EPERM;
- struct proc_object *p_proc_object;
- char sz_exec_file[MAXCMDLINELEN];
- char *argv[2];
- struct mgr_object *hmgr_obj = NULL;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
- u8 dev_type;
-
- /* Create a Dummy PROC Object */
- if (!drv_datap || !drv_datap->mgr_object) {
- status = -ENODATA;
- pr_err("%s: Failed to retrieve the object handle\n", __func__);
- goto func_end;
- } else {
- hmgr_obj = drv_datap->mgr_object;
- }
-
- p_proc_object = kzalloc(sizeof(struct proc_object), GFP_KERNEL);
- if (p_proc_object == NULL) {
- status = -ENOMEM;
- goto func_end;
- }
- p_proc_object->dev_obj = hdev_obj;
- p_proc_object->mgr_obj = hmgr_obj;
- status = dev_get_intf_fxns(hdev_obj, &p_proc_object->intf_fxns);
- if (!status)
- status = dev_get_bridge_context(hdev_obj,
- &p_proc_object->bridge_context);
- if (status)
- goto func_cont;
-
- /* Stop the Device, put it into standby mode */
- status = proc_stop(p_proc_object);
-
- if (status)
- goto func_cont;
-
- /* Get the default executable for this board... */
- dev_get_dev_type(hdev_obj, (u8 *) &dev_type);
- p_proc_object->processor_id = dev_type;
- status = get_exec_file(dev_node_obj, hdev_obj, sizeof(sz_exec_file),
- sz_exec_file);
- if (!status) {
- argv[0] = sz_exec_file;
- argv[1] = NULL;
- /* ...and try to load it: */
- status = proc_load(p_proc_object, 1, (const char **)argv, NULL);
- if (!status)
- status = proc_start(p_proc_object);
- }
- kfree(p_proc_object->last_coff);
- p_proc_object->last_coff = NULL;
-func_cont:
- kfree(p_proc_object);
-func_end:
- return status;
-}
-
-/*
- * ======== proc_ctrl ========
- * Purpose:
- * Pass control information to the GPP device driver managing the
- * DSP processor.
- *
- * This will be an OEM-only function, and not part of the DSP/BIOS Bridge
- * application developer's API.
- * Call the bridge_dev_ctrl fxn with the Argument. This is a Synchronous
- * Operation. arg can be null.
- */
-int proc_ctrl(void *hprocessor, u32 dw_cmd, struct dsp_cbdata *arg)
-{
- int status = 0;
- struct proc_object *p_proc_object = hprocessor;
- u32 timeout = 0;
-
- if (p_proc_object) {
- /* intercept PWR deep sleep command */
- if (dw_cmd == BRDIOCTL_DEEPSLEEP) {
- timeout = arg->cb_data;
- status = pwr_sleep_dsp(PWR_DEEPSLEEP, timeout);
- }
- /* intercept PWR emergency sleep command */
- else if (dw_cmd == BRDIOCTL_EMERGENCYSLEEP) {
- timeout = arg->cb_data;
- status = pwr_sleep_dsp(PWR_EMERGENCYDEEPSLEEP, timeout);
- } else if (dw_cmd == PWR_DEEPSLEEP) {
- /* timeout = arg->cb_data; */
- status = pwr_sleep_dsp(PWR_DEEPSLEEP, timeout);
- }
- /* intercept PWR wake commands */
- else if (dw_cmd == BRDIOCTL_WAKEUP) {
- timeout = arg->cb_data;
- status = pwr_wake_dsp(timeout);
- } else if (dw_cmd == PWR_WAKEUP) {
- /* timeout = arg->cb_data; */
- status = pwr_wake_dsp(timeout);
- } else
- if (!((*p_proc_object->intf_fxns->dev_cntrl)
- (p_proc_object->bridge_context, dw_cmd,
- arg))) {
- status = 0;
- } else {
- status = -EPERM;
- }
- } else {
- status = -EFAULT;
- }
-
- return status;
-}
-
-/*
- * ======== proc_detach ========
- * Purpose:
- * Destroys the Processor Object. Removes the notification from the Dev
- * List.
- */
-int proc_detach(struct process_context *pr_ctxt)
-{
- int status = 0;
- struct proc_object *p_proc_object = NULL;
-
- p_proc_object = (struct proc_object *)pr_ctxt->processor;
-
- if (p_proc_object) {
- /* Notify the Client */
- ntfy_notify(p_proc_object->ntfy_obj, DSP_PROCESSORDETACH);
- /* Remove the notification memory */
- if (p_proc_object->ntfy_obj) {
- ntfy_delete(p_proc_object->ntfy_obj);
- kfree(p_proc_object->ntfy_obj);
- }
-
- kfree(p_proc_object->last_coff);
- p_proc_object->last_coff = NULL;
- /* Remove the Proc from the DEV List */
- (void)dev_remove_proc_object(p_proc_object->dev_obj,
- (u32) p_proc_object);
- /* Free the Processor Object */
- kfree(p_proc_object);
- pr_ctxt->processor = NULL;
- } else {
- status = -EFAULT;
- }
-
- return status;
-}
-
-/*
- * ======== proc_enum_nodes ========
- * Purpose:
- * Enumerate and get configuration information about nodes allocated
- * on a DSP processor.
- */
-int proc_enum_nodes(void *hprocessor, void **node_tab,
- u32 node_tab_size, u32 *pu_num_nodes,
- u32 *pu_allocated)
-{
- int status = -EPERM;
- struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
- struct node_mgr *hnode_mgr = NULL;
-
- if (p_proc_object) {
- if (!(dev_get_node_manager(p_proc_object->dev_obj,
- &hnode_mgr))) {
- if (hnode_mgr) {
- status = node_enum_nodes(hnode_mgr, node_tab,
- node_tab_size,
- pu_num_nodes,
- pu_allocated);
- }
- }
- } else {
- status = -EFAULT;
- }
-
- return status;
-}
-
-/* Cache operation against kernel address instead of users */
-static int build_dma_sg(struct dmm_map_object *map_obj, unsigned long start,
- ssize_t len, int pg_i)
-{
- struct page *page;
- unsigned long offset;
- ssize_t rest;
- int ret = 0, i = 0;
- struct scatterlist *sg = map_obj->dma_info.sg;
-
- while (len) {
- page = get_mapping_page(map_obj, pg_i);
- if (!page) {
- pr_err("%s: no page for %08lx\n", __func__, start);
- ret = -EINVAL;
- goto out;
- } else if (IS_ERR(page)) {
- pr_err("%s: err page for %08lx(%lu)\n", __func__, start,
- PTR_ERR(page));
- ret = PTR_ERR(page);
- goto out;
- }
-
- offset = start & ~PAGE_MASK;
- rest = min_t(ssize_t, PAGE_SIZE - offset, len);
-
- sg_set_page(&sg[i], page, rest, offset);
-
- len -= rest;
- start += rest;
- pg_i++, i++;
- }
-
- if (i != map_obj->dma_info.num_pages) {
- pr_err("%s: bad number of sg iterations\n", __func__);
- ret = -EFAULT;
- goto out;
- }
-
-out:
- return ret;
-}
-
-static int memory_regain_ownership(struct dmm_map_object *map_obj,
- unsigned long start, ssize_t len, enum dma_data_direction dir)
-{
- int ret = 0;
- unsigned long first_data_page = start >> PAGE_SHIFT;
- unsigned long last_data_page = ((u32)(start + len - 1) >> PAGE_SHIFT);
- /* calculating the number of pages this area spans */
- unsigned long num_pages = last_data_page - first_data_page + 1;
- struct bridge_dma_map_info *dma_info = &map_obj->dma_info;
-
- if (!dma_info->sg)
- goto out;
-
- if (dma_info->dir != dir || dma_info->num_pages != num_pages) {
- pr_err("%s: dma info doesn't match given params\n", __func__);
- return -EINVAL;
- }
-
- dma_unmap_sg(bridge, dma_info->sg, num_pages, dma_info->dir);
-
- pr_debug("%s: dma_map_sg unmapped\n", __func__);
-
- kfree(dma_info->sg);
-
- map_obj->dma_info.sg = NULL;
-
-out:
- return ret;
-}
-
-/* Cache operation against kernel address instead of users */
-static int memory_give_ownership(struct dmm_map_object *map_obj,
- unsigned long start, ssize_t len, enum dma_data_direction dir)
-{
- int pg_i, ret, sg_num;
- struct scatterlist *sg;
- unsigned long first_data_page = start >> PAGE_SHIFT;
- unsigned long last_data_page = ((u32)(start + len - 1) >> PAGE_SHIFT);
- /* calculating the number of pages this area spans */
- unsigned long num_pages = last_data_page - first_data_page + 1;
-
- pg_i = find_first_page_in_cache(map_obj, start);
- if (pg_i < 0) {
- pr_err("%s: failed to find first page in cache\n", __func__);
- ret = -EINVAL;
- goto out;
- }
-
- sg = kcalloc(num_pages, sizeof(*sg), GFP_KERNEL);
- if (!sg) {
- ret = -ENOMEM;
- goto out;
- }
-
- sg_init_table(sg, num_pages);
-
- /* cleanup a previous sg allocation */
- /* this may happen if application doesn't signal for e/o DMA */
- kfree(map_obj->dma_info.sg);
-
- map_obj->dma_info.sg = sg;
- map_obj->dma_info.dir = dir;
- map_obj->dma_info.num_pages = num_pages;
-
- ret = build_dma_sg(map_obj, start, len, pg_i);
- if (ret)
- goto kfree_sg;
-
- sg_num = dma_map_sg(bridge, sg, num_pages, dir);
- if (sg_num < 1) {
- pr_err("%s: dma_map_sg failed: %d\n", __func__, sg_num);
- ret = -EFAULT;
- goto kfree_sg;
- }
-
- pr_debug("%s: dma_map_sg mapped %d elements\n", __func__, sg_num);
- map_obj->dma_info.sg_num = sg_num;
-
- return 0;
-
-kfree_sg:
- kfree(sg);
- map_obj->dma_info.sg = NULL;
-out:
- return ret;
-}
-
-int proc_begin_dma(void *hprocessor, void *pmpu_addr, u32 ul_size,
- enum dma_data_direction dir)
-{
- /* Keep STATUS here for future additions to this function */
- int status = 0;
- struct process_context *pr_ctxt = (struct process_context *) hprocessor;
- struct dmm_map_object *map_obj;
-
- if (!pr_ctxt) {
- status = -EFAULT;
- goto err_out;
- }
-
- pr_debug("%s: addr 0x%x, size 0x%x, type %d\n", __func__,
- (u32)pmpu_addr,
- ul_size, dir);
-
- mutex_lock(&proc_lock);
-
- /* find requested memory are in cached mapping information */
- map_obj = find_containing_mapping(pr_ctxt, (u32) pmpu_addr, ul_size);
- if (!map_obj) {
- pr_err("%s: find_containing_mapping failed\n", __func__);
- status = -EFAULT;
- goto no_map;
- }
-
- if (memory_give_ownership(map_obj, (u32) pmpu_addr, ul_size, dir)) {
- pr_err("%s: InValid address parameters %p %x\n",
- __func__, pmpu_addr, ul_size);
- status = -EFAULT;
- }
-
-no_map:
- mutex_unlock(&proc_lock);
-err_out:
-
- return status;
-}
-
-int proc_end_dma(void *hprocessor, void *pmpu_addr, u32 ul_size,
- enum dma_data_direction dir)
-{
- /* Keep STATUS here for future additions to this function */
- int status = 0;
- struct process_context *pr_ctxt = (struct process_context *) hprocessor;
- struct dmm_map_object *map_obj;
-
- if (!pr_ctxt) {
- status = -EFAULT;
- goto err_out;
- }
-
- pr_debug("%s: addr 0x%x, size 0x%x, type %d\n", __func__,
- (u32)pmpu_addr,
- ul_size, dir);
-
- mutex_lock(&proc_lock);
-
- /* find requested memory are in cached mapping information */
- map_obj = find_containing_mapping(pr_ctxt, (u32) pmpu_addr, ul_size);
- if (!map_obj) {
- pr_err("%s: find_containing_mapping failed\n", __func__);
- status = -EFAULT;
- goto no_map;
- }
-
- if (memory_regain_ownership(map_obj, (u32) pmpu_addr, ul_size, dir)) {
- pr_err("%s: InValid address parameters %p %x\n",
- __func__, pmpu_addr, ul_size);
- status = -EFAULT;
- }
-
-no_map:
- mutex_unlock(&proc_lock);
-err_out:
- return status;
-}
-
-/*
- * ======== proc_flush_memory ========
- * Purpose:
- * Flush cache
- */
-int proc_flush_memory(void *hprocessor, void *pmpu_addr,
- u32 ul_size, u32 ul_flags)
-{
- enum dma_data_direction dir = DMA_BIDIRECTIONAL;
-
- return proc_begin_dma(hprocessor, pmpu_addr, ul_size, dir);
-}
-
-/*
- * ======== proc_invalidate_memory ========
- * Purpose:
- * Invalidates the memory specified
- */
-int proc_invalidate_memory(void *hprocessor, void *pmpu_addr, u32 size)
-{
- enum dma_data_direction dir = DMA_FROM_DEVICE;
-
- return proc_begin_dma(hprocessor, pmpu_addr, size, dir);
-}
-
-/*
- * ======== proc_get_resource_info ========
- * Purpose:
- * Enumerate the resources currently available on a processor.
- */
-int proc_get_resource_info(void *hprocessor, u32 resource_type,
- struct dsp_resourceinfo *resource_info,
- u32 resource_info_size)
-{
- int status = -EPERM;
- struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
- struct node_mgr *hnode_mgr = NULL;
- struct nldr_object *nldr_obj = NULL;
- struct rmm_target_obj *rmm = NULL;
- struct io_mgr *hio_mgr = NULL; /* IO manager handle */
-
- if (!p_proc_object) {
- status = -EFAULT;
- goto func_end;
- }
- switch (resource_type) {
- case DSP_RESOURCE_DYNDARAM:
- case DSP_RESOURCE_DYNSARAM:
- case DSP_RESOURCE_DYNEXTERNAL:
- case DSP_RESOURCE_DYNSRAM:
- status = dev_get_node_manager(p_proc_object->dev_obj,
- &hnode_mgr);
- if (!hnode_mgr) {
- status = -EFAULT;
- goto func_end;
- }
-
- status = node_get_nldr_obj(hnode_mgr, &nldr_obj);
- if (!status) {
- status = nldr_get_rmm_manager(nldr_obj, &rmm);
- if (rmm) {
- if (!rmm_stat(rmm,
- (enum dsp_memtype)resource_type,
- (struct dsp_memstat *)
- &(resource_info->result.
- mem_stat)))
- status = -EINVAL;
- } else {
- status = -EFAULT;
- }
- }
- break;
- case DSP_RESOURCE_PROCLOAD:
- status = dev_get_io_mgr(p_proc_object->dev_obj, &hio_mgr);
- if (hio_mgr)
- status =
- p_proc_object->intf_fxns->
- io_get_proc_load(hio_mgr,
- (struct dsp_procloadstat *)
- &(resource_info->result.
- proc_load_stat));
- else
- status = -EFAULT;
- break;
- default:
- status = -EPERM;
- break;
- }
-func_end:
- return status;
-}
-
-/*
- * ======== proc_get_dev_object ========
- * Purpose:
- * Return the Dev Object handle for a given Processor.
- *
- */
-int proc_get_dev_object(void *hprocessor,
- struct dev_object **device_obj)
-{
- int status = -EPERM;
- struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
-
- if (p_proc_object) {
- *device_obj = p_proc_object->dev_obj;
- status = 0;
- } else {
- *device_obj = NULL;
- status = -EFAULT;
- }
-
- return status;
-}
-
-/*
- * ======== proc_get_state ========
- * Purpose:
- * Report the state of the specified DSP processor.
- */
-int proc_get_state(void *hprocessor,
- struct dsp_processorstate *proc_state_obj,
- u32 state_info_size)
-{
- int status = 0;
- struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
- int brd_status;
-
- if (p_proc_object) {
- /* First, retrieve BRD state information */
- status = (*p_proc_object->intf_fxns->brd_status)
- (p_proc_object->bridge_context, &brd_status);
- if (!status) {
- switch (brd_status) {
- case BRD_STOPPED:
- proc_state_obj->proc_state = PROC_STOPPED;
- break;
- case BRD_SLEEP_TRANSITION:
- case BRD_DSP_HIBERNATION:
- /* Fall through */
- case BRD_RUNNING:
- proc_state_obj->proc_state = PROC_RUNNING;
- break;
- case BRD_LOADED:
- proc_state_obj->proc_state = PROC_LOADED;
- break;
- case BRD_ERROR:
- proc_state_obj->proc_state = PROC_ERROR;
- break;
- default:
- proc_state_obj->proc_state = 0xFF;
- status = -EPERM;
- break;
- }
- }
- } else {
- status = -EFAULT;
- }
- dev_dbg(bridge, "%s, results: status: 0x%x proc_state_obj: 0x%x\n",
- __func__, status, proc_state_obj->proc_state);
- return status;
-}
-
-/*
- * ======== proc_get_trace ========
- * Purpose:
- * Retrieve the current contents of the trace buffer, located on the
- * Processor. Predefined symbols for the trace buffer must have been
- * configured into the DSP executable.
- * Details:
- * We support using the symbols SYS_PUTCBEG and SYS_PUTCEND to define a
- * trace buffer, only. Treat it as an undocumented feature.
- * This call is destructive, meaning the processor is placed in the monitor
- * state as a result of this function.
- */
-int proc_get_trace(void *hprocessor, u8 *pbuf, u32 max_size)
-{
- int status;
-
- status = -ENOSYS;
- return status;
-}
-
-/*
- * ======== proc_load ========
- * Purpose:
- * Reset a processor and load a new base program image.
- * This will be an OEM-only function, and not part of the DSP/BIOS Bridge
- * application developer's API.
- */
-int proc_load(void *hprocessor, const s32 argc_index,
- const char **user_args, const char **user_envp)
-{
- int status = 0;
- struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
- struct io_mgr *hio_mgr; /* IO manager handle */
- struct msg_mgr *hmsg_mgr;
- struct cod_manager *cod_mgr; /* Code manager handle */
- char *pargv0; /* temp argv[0] ptr */
- char **new_envp; /* Updated envp[] array. */
- char sz_proc_id[MAXPROCIDLEN]; /* Size of "PROC_ID=<n>" */
- s32 envp_elems; /* Num elements in envp[]. */
- s32 cnew_envp; /* " " in new_envp[] */
- s32 nproc_id = 0; /* Anticipate MP version. */
- struct dcd_manager *hdcd_handle;
- struct dmm_object *dmm_mgr;
- u32 dw_ext_end;
- u32 proc_id;
- int brd_state;
- struct drv_data *drv_datap = dev_get_drvdata(bridge);
-
-#ifdef OPT_LOAD_TIME_INSTRUMENTATION
- struct timeval tv1;
- struct timeval tv2;
-#endif
-
-#if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
- struct dspbridge_platform_data *pdata =
- omap_dspbridge_dev->dev.platform_data;
-#endif
-
-#ifdef OPT_LOAD_TIME_INSTRUMENTATION
- do_gettimeofday(&tv1);
-#endif
- if (!p_proc_object) {
- status = -EFAULT;
- goto func_end;
- }
- dev_get_cod_mgr(p_proc_object->dev_obj, &cod_mgr);
- if (!cod_mgr) {
- status = -EPERM;
- goto func_end;
- }
- status = proc_stop(hprocessor);
- if (status)
- goto func_end;
-
- /* Place the board in the monitor state. */
- status = proc_monitor(hprocessor);
- if (status)
- goto func_end;
-
- /* Save ptr to original argv[0]. */
- pargv0 = (char *)user_args[0];
- /*Prepend "PROC_ID=<nproc_id>"to envp array for target. */
- envp_elems = get_envp_count((char **)user_envp);
- cnew_envp = (envp_elems ? (envp_elems + 1) : (envp_elems + 2));
- new_envp = kzalloc(cnew_envp * sizeof(char **), GFP_KERNEL);
- if (new_envp) {
- status = snprintf(sz_proc_id, MAXPROCIDLEN, PROC_ENVPROCID,
- nproc_id);
- if (status == -1) {
- dev_dbg(bridge, "%s: Proc ID string overflow\n",
- __func__);
- status = -EPERM;
- } else {
- new_envp =
- prepend_envp(new_envp, (char **)user_envp,
- envp_elems, cnew_envp, sz_proc_id);
- /* Get the DCD Handle */
- status = mgr_get_dcd_handle(p_proc_object->mgr_obj,
- (u32 *) &hdcd_handle);
- if (!status) {
- /* Before proceeding with new load,
- * check if a previously registered COFF
- * exists.
- * If yes, unregister nodes in previously
- * registered COFF. If any error occurred,
- * set previously registered COFF to NULL. */
- if (p_proc_object->last_coff != NULL) {
- status =
- dcd_auto_unregister(hdcd_handle,
- p_proc_object->
- last_coff);
- /* Regardless of auto unregister status,
- * free previously allocated
- * memory. */
- kfree(p_proc_object->last_coff);
- p_proc_object->last_coff = NULL;
- }
- }
- /* On success, do cod_open_base() */
- status = cod_open_base(cod_mgr, (char *)user_args[0],
- COD_SYMB);
- }
- } else {
- status = -ENOMEM;
- }
- if (!status) {
- /* Auto-register data base */
- /* Get the DCD Handle */
- status = mgr_get_dcd_handle(p_proc_object->mgr_obj,
- (u32 *) &hdcd_handle);
- if (!status) {
- /* Auto register nodes in specified COFF
- * file. If registration did not fail,
- * (status = 0 or -EACCES)
- * save the name of the COFF file for
- * de-registration in the future. */
- status =
- dcd_auto_register(hdcd_handle,
- (char *)user_args[0]);
- if (status == -EACCES)
- status = 0;
-
- if (status) {
- status = -EPERM;
- } else {
- /* Allocate memory for pszLastCoff */
- p_proc_object->last_coff =
- kzalloc((strlen(user_args[0]) +
- 1), GFP_KERNEL);
- /* If memory allocated, save COFF file name */
- if (p_proc_object->last_coff) {
- strncpy(p_proc_object->last_coff,
- (char *)user_args[0],
- (strlen((char *)user_args[0]) +
- 1));
- }
- }
- }
- }
- /* Update shared memory address and size */
- if (!status) {
- /* Create the message manager. This must be done
- * before calling the IOOnLoaded function. */
- dev_get_msg_mgr(p_proc_object->dev_obj, &hmsg_mgr);
- if (!hmsg_mgr) {
- status = msg_create(&hmsg_mgr, p_proc_object->dev_obj,
- (msg_onexit) node_on_exit);
- dev_set_msg_mgr(p_proc_object->dev_obj, hmsg_mgr);
- }
- }
- if (!status) {
- /* Set the Device object's message manager */
- status = dev_get_io_mgr(p_proc_object->dev_obj, &hio_mgr);
- if (hio_mgr)
- status = (*p_proc_object->intf_fxns->io_on_loaded)
- (hio_mgr);
- else
- status = -EFAULT;
- }
- if (!status) {
- /* Now, attempt to load an exec: */
-
- /* Boost the OPP level to Maximum level supported by baseport */
-#if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
- if (pdata->cpu_set_freq)
- (*pdata->cpu_set_freq) (pdata->mpu_speed[VDD1_OPP5]);
-#endif
- status = cod_load_base(cod_mgr, argc_index, (char **)user_args,
- dev_brd_write_fxn,
- p_proc_object->dev_obj, NULL);
- if (status) {
- if (status == -EBADF) {
- dev_dbg(bridge, "%s: Failure to Load the EXE\n",
- __func__);
- }
- if (status == -ESPIPE) {
- pr_err("%s: Couldn't parse the file\n",
- __func__);
- }
- }
- /* Requesting the lowest opp supported */
-#if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
- if (pdata->cpu_set_freq)
- (*pdata->cpu_set_freq) (pdata->mpu_speed[VDD1_OPP1]);
-#endif
-
- }
- if (!status) {
- /* Update the Processor status to loaded */
- status = (*p_proc_object->intf_fxns->brd_set_state)
- (p_proc_object->bridge_context, BRD_LOADED);
- if (!status) {
- p_proc_object->proc_state = PROC_LOADED;
- if (p_proc_object->ntfy_obj)
- proc_notify_clients(p_proc_object,
- DSP_PROCESSORSTATECHANGE);
- }
- }
- if (!status) {
- status = proc_get_processor_id(hprocessor, &proc_id);
- if (proc_id == DSP_UNIT) {
- /* Use all available DSP address space after EXTMEM
- * for DMM */
- if (!status)
- status = cod_get_sym_value(cod_mgr, EXTEND,
- &dw_ext_end);
-
- /* Reset DMM structs and add an initial free chunk */
- if (!status) {
- status =
- dev_get_dmm_mgr(p_proc_object->dev_obj,
- &dmm_mgr);
- if (dmm_mgr) {
- /* Set dw_ext_end to DMM START u8
- * address */
- dw_ext_end =
- (dw_ext_end + 1) * DSPWORDSIZE;
- /* DMM memory is from EXT_END */
- status = dmm_create_tables(dmm_mgr,
- dw_ext_end,
- DMMPOOLSIZE);
- } else {
- status = -EFAULT;
- }
- }
- }
- }
- /* Restore the original argv[0] */
- kfree(new_envp);
- user_args[0] = pargv0;
- if (!status) {
- if (!((*p_proc_object->intf_fxns->brd_status)
- (p_proc_object->bridge_context, &brd_state))) {
- pr_info("%s: Processor Loaded %s\n", __func__, pargv0);
- kfree(drv_datap->base_img);
- drv_datap->base_img = kstrdup(pargv0, GFP_KERNEL);
- if (!drv_datap->base_img)
- status = -ENOMEM;
- }
- }
-
-func_end:
- if (status) {
- pr_err("%s: Processor failed to load\n", __func__);
- proc_stop(p_proc_object);
- }
-#ifdef OPT_LOAD_TIME_INSTRUMENTATION
- do_gettimeofday(&tv2);
- if (tv2.tv_usec < tv1.tv_usec) {
- tv2.tv_usec += 1000000;
- tv2.tv_sec--;
- }
- dev_dbg(bridge, "%s: time to load %d sec and %d usec\n", __func__,
- tv2.tv_sec - tv1.tv_sec, tv2.tv_usec - tv1.tv_usec);
-#endif
- return status;
-}
-
-/*
- * ======== proc_map ========
- * Purpose:
- * Maps a MPU buffer to DSP address space.
- */
-int proc_map(void *hprocessor, void *pmpu_addr, u32 ul_size,
- void *req_addr, void **pp_map_addr, u32 ul_map_attr,
- struct process_context *pr_ctxt)
-{
- u32 va_align;
- u32 pa_align;
- struct dmm_object *dmm_mgr;
- u32 size_align;
- int status = 0;
- struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
- struct dmm_map_object *map_obj;
- u32 tmp_addr = 0;
-
-#ifdef CONFIG_TIDSPBRIDGE_CACHE_LINE_CHECK
- if ((ul_map_attr & BUFMODE_MASK) != RBUF) {
- if (!IS_ALIGNED((u32)pmpu_addr, DSP_CACHE_LINE) ||
- !IS_ALIGNED(ul_size, DSP_CACHE_LINE)) {
- pr_err("%s: not aligned: 0x%x (%d)\n", __func__,
- (u32)pmpu_addr, ul_size);
- return -EFAULT;
- }
- }
-#endif
-
- /* Calculate the page-aligned PA, VA and size */
- va_align = PG_ALIGN_LOW((u32) req_addr, PG_SIZE4K);
- pa_align = PG_ALIGN_LOW((u32) pmpu_addr, PG_SIZE4K);
- size_align = PG_ALIGN_HIGH(ul_size + (u32) pmpu_addr - pa_align,
- PG_SIZE4K);
-
- if (!p_proc_object) {
- status = -EFAULT;
- goto func_end;
- }
- /* Critical section */
- mutex_lock(&proc_lock);
- dmm_get_handle(p_proc_object, &dmm_mgr);
- if (dmm_mgr)
- status = dmm_map_memory(dmm_mgr, va_align, size_align);
- else
- status = -EFAULT;
-
- /* Add mapping to the page tables. */
- if (!status) {
-
- /* Mapped address = MSB of VA | LSB of PA */
- tmp_addr = (va_align | ((u32) pmpu_addr & (PG_SIZE4K - 1)));
- /* mapped memory resource tracking */
- map_obj = add_mapping_info(pr_ctxt, pa_align, tmp_addr,
- size_align);
- if (!map_obj)
- status = -ENOMEM;
- else
- status = (*p_proc_object->intf_fxns->brd_mem_map)
- (p_proc_object->bridge_context, pa_align, va_align,
- size_align, ul_map_attr, map_obj->pages);
- }
- if (!status) {
- /* Mapped address = MSB of VA | LSB of PA */
- *pp_map_addr = (void *) tmp_addr;
- } else {
- remove_mapping_information(pr_ctxt, tmp_addr, size_align);
- dmm_un_map_memory(dmm_mgr, va_align, &size_align);
- }
- mutex_unlock(&proc_lock);
-
- if (status)
- goto func_end;
-
-func_end:
- dev_dbg(bridge, "%s: hprocessor %p, pmpu_addr %p, ul_size %x, "
- "req_addr %p, ul_map_attr %x, pp_map_addr %p, va_align %x, "
- "pa_align %x, size_align %x status 0x%x\n", __func__,
- hprocessor, pmpu_addr, ul_size, req_addr, ul_map_attr,
- pp_map_addr, va_align, pa_align, size_align, status);
-
- return status;
-}
-
-/*
- * ======== proc_register_notify ========
- * Purpose:
- * Register to be notified of specific processor events.
- */
-int proc_register_notify(void *hprocessor, u32 event_mask,
- u32 notify_type, struct dsp_notification
- *hnotification)
-{
- int status = 0;
- struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
- struct deh_mgr *hdeh_mgr;
-
- /* Check processor handle */
- if (!p_proc_object) {
- status = -EFAULT;
- goto func_end;
- }
- /* Check if event mask is a valid processor related event */
- if (event_mask & ~(DSP_PROCESSORSTATECHANGE | DSP_PROCESSORATTACH |
- DSP_PROCESSORDETACH | DSP_PROCESSORRESTART |
- DSP_MMUFAULT | DSP_SYSERROR | DSP_PWRERROR |
- DSP_WDTOVERFLOW))
- status = -EINVAL;
-
- /* Check if notify type is valid */
- if (notify_type != DSP_SIGNALEVENT)
- status = -EINVAL;
-
- if (!status) {
- /* If event mask is not DSP_SYSERROR, DSP_MMUFAULT,
- * or DSP_PWRERROR then register event immediately. */
- if (event_mask &
- ~(DSP_SYSERROR | DSP_MMUFAULT | DSP_PWRERROR |
- DSP_WDTOVERFLOW)) {
- status = ntfy_register(p_proc_object->ntfy_obj,
- hnotification, event_mask,
- notify_type);
- /* Special case alert, special case alert!
- * If we're trying to *deregister* (i.e. event_mask
- * is 0), a DSP_SYSERROR or DSP_MMUFAULT notification,
- * we have to deregister with the DEH manager.
- * There's no way to know, based on event_mask which
- * manager the notification event was registered with,
- * so if we're trying to deregister and ntfy_register
- * failed, we'll give the deh manager a shot.
- */
- if ((event_mask == 0) && status) {
- status =
- dev_get_deh_mgr(p_proc_object->dev_obj,
- &hdeh_mgr);
- status =
- bridge_deh_register_notify(hdeh_mgr,
- event_mask,
- notify_type,
- hnotification);
- }
- } else {
- status = dev_get_deh_mgr(p_proc_object->dev_obj,
- &hdeh_mgr);
- status =
- bridge_deh_register_notify(hdeh_mgr,
- event_mask,
- notify_type,
- hnotification);
-
- }
- }
-func_end:
- return status;
-}
-
-/*
- * ======== proc_reserve_memory ========
- * Purpose:
- * Reserve a virtually contiguous region of DSP address space.
- */
-int proc_reserve_memory(void *hprocessor, u32 ul_size,
- void **pp_rsv_addr,
- struct process_context *pr_ctxt)
-{
- struct dmm_object *dmm_mgr;
- int status = 0;
- struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
- struct dmm_rsv_object *rsv_obj;
-
- if (!p_proc_object) {
- status = -EFAULT;
- goto func_end;
- }
-
- status = dmm_get_handle(p_proc_object, &dmm_mgr);
- if (!dmm_mgr) {
- status = -EFAULT;
- goto func_end;
- }
-
- status = dmm_reserve_memory(dmm_mgr, ul_size, (u32 *) pp_rsv_addr);
- if (status != 0)
- goto func_end;
-
- /*
- * A successful reserve should be followed by insertion of rsv_obj
- * into dmm_rsv_list, so that reserved memory resource tracking
- * remains uptodate
- */
- rsv_obj = kmalloc(sizeof(struct dmm_rsv_object), GFP_KERNEL);
- if (rsv_obj) {
- rsv_obj->dsp_reserved_addr = (u32) *pp_rsv_addr;
- spin_lock(&pr_ctxt->dmm_rsv_lock);
- list_add(&rsv_obj->link, &pr_ctxt->dmm_rsv_list);
- spin_unlock(&pr_ctxt->dmm_rsv_lock);
- }
-
-func_end:
- dev_dbg(bridge, "%s: hprocessor: 0x%p ul_size: 0x%x pp_rsv_addr: 0x%p "
- "status 0x%x\n", __func__, hprocessor,
- ul_size, pp_rsv_addr, status);
- return status;
-}
-
-/*
- * ======== proc_start ========
- * Purpose:
- * Start a processor running.
- */
-int proc_start(void *hprocessor)
-{
- int status = 0;
- struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
- struct cod_manager *cod_mgr; /* Code manager handle */
- u32 dw_dsp_addr; /* Loaded code's entry point. */
- int brd_state;
-
- if (!p_proc_object) {
- status = -EFAULT;
- goto func_end;
- }
- /* Call the bridge_brd_start */
- if (p_proc_object->proc_state != PROC_LOADED) {
- status = -EBADR;
- goto func_end;
- }
- status = dev_get_cod_mgr(p_proc_object->dev_obj, &cod_mgr);
- if (!cod_mgr) {
- status = -EFAULT;
- goto func_cont;
- }
-
- status = cod_get_entry(cod_mgr, &dw_dsp_addr);
- if (status)
- goto func_cont;
-
- status = (*p_proc_object->intf_fxns->brd_start)
- (p_proc_object->bridge_context, dw_dsp_addr);
- if (status)
- goto func_cont;
-
- /* Call dev_create2 */
- status = dev_create2(p_proc_object->dev_obj);
- if (!status) {
- p_proc_object->proc_state = PROC_RUNNING;
- /* Deep sleep switces off the peripheral clocks.
- * we just put the DSP CPU in idle in the idle loop.
- * so there is no need to send a command to DSP */
-
- if (p_proc_object->ntfy_obj) {
- proc_notify_clients(p_proc_object,
- DSP_PROCESSORSTATECHANGE);
- }
- } else {
- /* Failed to Create Node Manager and DISP Object
- * Stop the Processor from running. Put it in STOPPED State */
- (void)(*p_proc_object->intf_fxns->
- brd_stop) (p_proc_object->bridge_context);
- p_proc_object->proc_state = PROC_STOPPED;
- }
-func_cont:
- if (!status) {
- if (!((*p_proc_object->intf_fxns->brd_status)
- (p_proc_object->bridge_context, &brd_state))) {
- pr_info("%s: dsp in running state\n", __func__);
- }
- } else {
- pr_err("%s: Failed to start the dsp\n", __func__);
- proc_stop(p_proc_object);
- }
-
-func_end:
- return status;
-}
-
-/*
- * ======== proc_stop ========
- * Purpose:
- * Stop a processor running.
- */
-int proc_stop(void *hprocessor)
-{
- int status = 0;
- struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
- struct msg_mgr *hmsg_mgr;
- struct node_mgr *hnode_mgr;
- void *hnode;
- u32 node_tab_size = 1;
- u32 num_nodes = 0;
- u32 nodes_allocated = 0;
-
- if (!p_proc_object) {
- status = -EFAULT;
- goto func_end;
- }
- /* check if there are any running nodes */
- status = dev_get_node_manager(p_proc_object->dev_obj, &hnode_mgr);
- if (!status && hnode_mgr) {
- status = node_enum_nodes(hnode_mgr, &hnode, node_tab_size,
- &num_nodes, &nodes_allocated);
- if ((status == -EINVAL) || (nodes_allocated > 0)) {
- pr_err("%s: Can't stop device, active nodes = %d\n",
- __func__, nodes_allocated);
- return -EBADR;
- }
- }
- /* Call the bridge_brd_stop */
- /* It is OK to stop a device that does n't have nodes OR not started */
- status =
- (*p_proc_object->intf_fxns->
- brd_stop) (p_proc_object->bridge_context);
- if (!status) {
- dev_dbg(bridge, "%s: processor in standby mode\n", __func__);
- p_proc_object->proc_state = PROC_STOPPED;
- /* Destroy the Node Manager, msg_ctrl Manager */
- if (!(dev_destroy2(p_proc_object->dev_obj))) {
- /* Destroy the msg_ctrl by calling msg_delete */
- dev_get_msg_mgr(p_proc_object->dev_obj, &hmsg_mgr);
- if (hmsg_mgr) {
- msg_delete(hmsg_mgr);
- dev_set_msg_mgr(p_proc_object->dev_obj, NULL);
- }
- }
- } else {
- pr_err("%s: Failed to stop the processor\n", __func__);
- }
-func_end:
-
- return status;
-}
-
-/*
- * ======== proc_un_map ========
- * Purpose:
- * Removes a MPU buffer mapping from the DSP address space.
- */
-int proc_un_map(void *hprocessor, void *map_addr,
- struct process_context *pr_ctxt)
-{
- int status = 0;
- struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
- struct dmm_object *dmm_mgr;
- u32 va_align;
- u32 size_align;
-
- va_align = PG_ALIGN_LOW((u32) map_addr, PG_SIZE4K);
- if (!p_proc_object) {
- status = -EFAULT;
- goto func_end;
- }
-
- status = dmm_get_handle(hprocessor, &dmm_mgr);
- if (!dmm_mgr) {
- status = -EFAULT;
- goto func_end;
- }
-
- /* Critical section */
- mutex_lock(&proc_lock);
- /*
- * Update DMM structures. Get the size to unmap.
- * This function returns error if the VA is not mapped
- */
- status = dmm_un_map_memory(dmm_mgr, (u32) va_align, &size_align);
- /* Remove mapping from the page tables. */
- if (!status) {
- status = (*p_proc_object->intf_fxns->brd_mem_un_map)
- (p_proc_object->bridge_context, va_align, size_align);
- }
-
- if (status)
- goto unmap_failed;
-
- /*
- * A successful unmap should be followed by removal of map_obj
- * from dmm_map_list, so that mapped memory resource tracking
- * remains uptodate
- */
- remove_mapping_information(pr_ctxt, (u32) map_addr, size_align);
-
-unmap_failed:
- mutex_unlock(&proc_lock);
-
-func_end:
- dev_dbg(bridge, "%s: hprocessor: 0x%p map_addr: 0x%p status: 0x%x\n",
- __func__, hprocessor, map_addr, status);
- return status;
-}
-
-/*
- * ======== proc_un_reserve_memory ========
- * Purpose:
- * Frees a previously reserved region of DSP address space.
- */
-int proc_un_reserve_memory(void *hprocessor, void *prsv_addr,
- struct process_context *pr_ctxt)
-{
- struct dmm_object *dmm_mgr;
- int status = 0;
- struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
- struct dmm_rsv_object *rsv_obj;
-
- if (!p_proc_object) {
- status = -EFAULT;
- goto func_end;
- }
-
- status = dmm_get_handle(p_proc_object, &dmm_mgr);
- if (!dmm_mgr) {
- status = -EFAULT;
- goto func_end;
- }
-
- status = dmm_un_reserve_memory(dmm_mgr, (u32) prsv_addr);
- if (status != 0)
- goto func_end;
-
- /*
- * A successful unreserve should be followed by removal of rsv_obj
- * from dmm_rsv_list, so that reserved memory resource tracking
- * remains uptodate
- */
- spin_lock(&pr_ctxt->dmm_rsv_lock);
- list_for_each_entry(rsv_obj, &pr_ctxt->dmm_rsv_list, link) {
- if (rsv_obj->dsp_reserved_addr == (u32) prsv_addr) {
- list_del(&rsv_obj->link);
- kfree(rsv_obj);
- break;
- }
- }
- spin_unlock(&pr_ctxt->dmm_rsv_lock);
-
-func_end:
- dev_dbg(bridge, "%s: hprocessor: 0x%p prsv_addr: 0x%p status: 0x%x\n",
- __func__, hprocessor, prsv_addr, status);
- return status;
-}
-
-/*
- * ======== = proc_monitor ======== ==
- * Purpose:
- * Place the Processor in Monitor State. This is an internal
- * function and a requirement before Processor is loaded.
- * This does a bridge_brd_stop, dev_destroy2 and bridge_brd_monitor.
- * In dev_destroy2 we delete the node manager.
- * Parameters:
- * p_proc_object: Pointer to Processor Object
- * Returns:
- * 0: Processor placed in monitor mode.
- * !0: Failed to place processor in monitor mode.
- * Requires:
- * Valid Processor Handle
- * Ensures:
- * Success: ProcObject state is PROC_IDLE
- */
-static int proc_monitor(struct proc_object *proc_obj)
-{
- int status = -EPERM;
- struct msg_mgr *hmsg_mgr;
-
- /* This is needed only when Device is loaded when it is
- * already 'ACTIVE' */
- /* Destroy the Node Manager, msg_ctrl Manager */
- if (!dev_destroy2(proc_obj->dev_obj)) {
- /* Destroy the msg_ctrl by calling msg_delete */
- dev_get_msg_mgr(proc_obj->dev_obj, &hmsg_mgr);
- if (hmsg_mgr) {
- msg_delete(hmsg_mgr);
- dev_set_msg_mgr(proc_obj->dev_obj, NULL);
- }
- }
- /* Place the Board in the Monitor State */
- if (!((*proc_obj->intf_fxns->brd_monitor)
- (proc_obj->bridge_context))) {
- status = 0;
- }
-
- return status;
-}
-
-/*
- * ======== get_envp_count ========
- * Purpose:
- * Return the number of elements in the envp array, including the
- * terminating NULL element.
- */
-static s32 get_envp_count(char **envp)
-{
- s32 ret = 0;
-
- if (envp) {
- while (*envp++)
- ret++;
-
- ret += 1; /* Include the terminating NULL in the count. */
- }
-
- return ret;
-}
-
-/*
- * ======== prepend_envp ========
- * Purpose:
- * Prepend an environment variable=value pair to the new envp array, and
- * copy in the existing var=value pairs in the old envp array.
- */
-static char **prepend_envp(char **new_envp, char **envp, s32 envp_elems,
- s32 cnew_envp, char *sz_var)
-{
- char **pp_envp = new_envp;
-
- /* Prepend new environ var=value string */
- *new_envp++ = sz_var;
-
- /* Copy user's environment into our own. */
- while (envp_elems--)
- *new_envp++ = *envp++;
-
- /* Ensure NULL terminates the new environment strings array. */
- if (envp_elems == 0)
- *new_envp = NULL;
-
- return pp_envp;
-}
-
-/*
- * ======== proc_notify_clients ========
- * Purpose:
- * Notify the processor the events.
- */
-int proc_notify_clients(void *proc, u32 events)
-{
- int status = 0;
- struct proc_object *p_proc_object = (struct proc_object *)proc;
-
- if (!p_proc_object) {
- status = -EFAULT;
- goto func_end;
- }
-
- ntfy_notify(p_proc_object->ntfy_obj, events);
-func_end:
- return status;
-}
-
-/*
- * ======== proc_notify_all_clients ========
- * Purpose:
- * Notify the processor the events. This includes notifying all clients
- * attached to a particulat DSP.
- */
-int proc_notify_all_clients(void *proc, u32 events)
-{
- int status = 0;
- struct proc_object *p_proc_object = (struct proc_object *)proc;
-
- if (!p_proc_object) {
- status = -EFAULT;
- goto func_end;
- }
-
- dev_notify_clients(p_proc_object->dev_obj, events);
-
-func_end:
- return status;
-}
-
-/*
- * ======== proc_get_processor_id ========
- * Purpose:
- * Retrieves the processor ID.
- */
-int proc_get_processor_id(void *proc, u32 *proc_id)
-{
- int status = 0;
- struct proc_object *p_proc_object = (struct proc_object *)proc;
-
- if (p_proc_object)
- *proc_id = p_proc_object->processor_id;
- else
- status = -EFAULT;
-
- return status;
-}
diff --git a/drivers/staging/tidspbridge/rmgr/pwr.c b/drivers/staging/tidspbridge/rmgr/pwr.c
deleted file mode 100644
index 17748df351b9..000000000000
--- a/drivers/staging/tidspbridge/rmgr/pwr.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * pwr.c
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * PWR API for controlling DSP power states.
- *
- * 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.
- */
-
-/* ----------------------------------- Host OS */
-#include <dspbridge/host_os.h>
-
-/* ----------------------------------- This */
-#include <dspbridge/pwr.h>
-
-/* ----------------------------------- Resource Manager */
-#include <dspbridge/devdefs.h>
-#include <dspbridge/drv.h>
-
-/* ----------------------------------- Platform Manager */
-#include <dspbridge/dev.h>
-
-/* ----------------------------------- Link Driver */
-#include <dspbridge/dspioctl.h>
-
-/*
- * ======== pwr_sleep_dsp ========
- * Send command to DSP to enter sleep state.
- */
-int pwr_sleep_dsp(const u32 sleep_code, const u32 timeout)
-{
- struct bridge_drv_interface *intf_fxns;
- struct bridge_dev_context *dw_context;
- int status = -EPERM;
- struct dev_object *hdev_obj = NULL;
- u32 ioctlcode = 0;
- u32 arg = timeout;
-
- for (hdev_obj = (struct dev_object *)drv_get_first_dev_object();
- hdev_obj != NULL;
- hdev_obj =
- (struct dev_object *)drv_get_next_dev_object((u32) hdev_obj)) {
- if (dev_get_bridge_context(hdev_obj,
- (struct bridge_dev_context **)
- &dw_context)) {
- continue;
- }
- if (dev_get_intf_fxns(hdev_obj,
- (struct bridge_drv_interface **)
- &intf_fxns)) {
- continue;
- }
- if (sleep_code == PWR_DEEPSLEEP)
- ioctlcode = BRDIOCTL_DEEPSLEEP;
- else if (sleep_code == PWR_EMERGENCYDEEPSLEEP)
- ioctlcode = BRDIOCTL_EMERGENCYSLEEP;
- else
- status = -EINVAL;
-
- if (status != -EINVAL) {
- status = (*intf_fxns->dev_cntrl) (dw_context,
- ioctlcode,
- (void *)&arg);
- }
- }
- return status;
-}
-
-/*
- * ======== pwr_wake_dsp ========
- * Send command to DSP to wake it from sleep.
- */
-int pwr_wake_dsp(const u32 timeout)
-{
- struct bridge_drv_interface *intf_fxns;
- struct bridge_dev_context *dw_context;
- int status = -EPERM;
- struct dev_object *hdev_obj = NULL;
- u32 arg = timeout;
-
- for (hdev_obj = (struct dev_object *)drv_get_first_dev_object();
- hdev_obj != NULL;
- hdev_obj = (struct dev_object *)drv_get_next_dev_object
- ((u32) hdev_obj)) {
- if (!(dev_get_bridge_context(hdev_obj,
- (struct bridge_dev_context
- **)&dw_context))) {
- if (!(dev_get_intf_fxns(hdev_obj,
- (struct bridge_drv_interface **)&intf_fxns))) {
- status =
- (*intf_fxns->dev_cntrl) (dw_context,
- BRDIOCTL_WAKEUP,
- (void *)&arg);
- }
- }
- }
- return status;
-}
-
-/*
- * ======== pwr_pm_pre_scale========
- * Sends pre-notification message to DSP.
- */
-int pwr_pm_pre_scale(u16 voltage_domain, u32 level)
-{
- struct bridge_drv_interface *intf_fxns;
- struct bridge_dev_context *dw_context;
- int status = -EPERM;
- struct dev_object *hdev_obj = NULL;
- u32 arg[2];
-
- arg[0] = voltage_domain;
- arg[1] = level;
-
- for (hdev_obj = (struct dev_object *)drv_get_first_dev_object();
- hdev_obj != NULL;
- hdev_obj = (struct dev_object *)drv_get_next_dev_object
- ((u32) hdev_obj)) {
- if (!(dev_get_bridge_context(hdev_obj,
- (struct bridge_dev_context
- **)&dw_context))) {
- if (!(dev_get_intf_fxns(hdev_obj,
- (struct bridge_drv_interface **)&intf_fxns))) {
- status =
- (*intf_fxns->dev_cntrl) (dw_context,
- BRDIOCTL_PRESCALE_NOTIFY,
- (void *)&arg);
- }
- }
- }
- return status;
-}
-
-/*
- * ======== pwr_pm_post_scale========
- * Sends post-notification message to DSP.
- */
-int pwr_pm_post_scale(u16 voltage_domain, u32 level)
-{
- struct bridge_drv_interface *intf_fxns;
- struct bridge_dev_context *dw_context;
- int status = -EPERM;
- struct dev_object *hdev_obj = NULL;
- u32 arg[2];
-
- arg[0] = voltage_domain;
- arg[1] = level;
-
- for (hdev_obj = (struct dev_object *)drv_get_first_dev_object();
- hdev_obj != NULL;
- hdev_obj = (struct dev_object *)drv_get_next_dev_object
- ((u32) hdev_obj)) {
- if (!(dev_get_bridge_context(hdev_obj,
- (struct bridge_dev_context
- **)&dw_context))) {
- if (!(dev_get_intf_fxns(hdev_obj,
- (struct bridge_drv_interface **)&intf_fxns))) {
- status =
- (*intf_fxns->dev_cntrl) (dw_context,
- BRDIOCTL_POSTSCALE_NOTIFY,
- (void *)&arg);
- }
- }
- }
- return status;
-
-}
diff --git a/drivers/staging/tidspbridge/rmgr/rmm.c b/drivers/staging/tidspbridge/rmgr/rmm.c
deleted file mode 100644
index 52187bd97729..000000000000
--- a/drivers/staging/tidspbridge/rmgr/rmm.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * rmm.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.
- */
-
-/*
- * This memory manager provides general heap management and arbitrary
- * alignment for any number of memory segments.
- *
- * Notes:
- *
- * Memory blocks are allocated from the end of the first free memory
- * block large enough to satisfy the request. Alignment requirements
- * are satisfied by "sliding" the block forward until its base satisfies
- * the alignment specification; if this is not possible then the next
- * free block large enough to hold the request is tried.
- *
- * Since alignment can cause the creation of a new free block - the
- * unused memory formed between the start of the original free block
- * and the start of the allocated block - the memory manager must free
- * this memory to prevent a memory leak.
- *
- * Overlay memory is managed by reserving through rmm_alloc, and freeing
- * it through rmm_free. The memory manager prevents DSP code/data that is
- * overlayed from being overwritten as long as the memory it runs at has
- * been allocated, and not yet freed.
- */
-
-#include <linux/types.h>
-#include <linux/list.h>
-
-/* ----------------------------------- Host OS */
-#include <dspbridge/host_os.h>
-
-/* ----------------------------------- DSP/BIOS Bridge */
-#include <dspbridge/dbdefs.h>
-
-/* ----------------------------------- This */
-#include <dspbridge/rmm.h>
-
-/*
- * ======== rmm_header ========
- * This header is used to maintain a list of free memory blocks.
- */
-struct rmm_header {
- struct rmm_header *next; /* form a free memory link list */
- u32 size; /* size of the free memory */
- u32 addr; /* DSP address of memory block */
-};
-
-/*
- * ======== rmm_ovly_sect ========
- * Keeps track of memory occupied by overlay section.
- */
-struct rmm_ovly_sect {
- struct list_head list_elem;
- u32 addr; /* Start of memory section */
- u32 size; /* Length (target MAUs) of section */
- s32 page; /* Memory page */
-};
-
-/*
- * ======== rmm_target_obj ========
- */
-struct rmm_target_obj {
- struct rmm_segment *seg_tab;
- struct rmm_header **free_list;
- u32 num_segs;
- struct list_head ovly_list; /* List of overlay memory in use */
-};
-
-static bool alloc_block(struct rmm_target_obj *target, u32 segid, u32 size,
- u32 align, u32 *dsp_address);
-static bool free_block(struct rmm_target_obj *target, u32 segid, u32 addr,
- u32 size);
-
-/*
- * ======== rmm_alloc ========
- */
-int rmm_alloc(struct rmm_target_obj *target, u32 segid, u32 size,
- u32 align, u32 *dsp_address, bool reserve)
-{
- struct rmm_ovly_sect *sect, *prev_sect = NULL;
- struct rmm_ovly_sect *new_sect;
- u32 addr;
- int status = 0;
-
- if (!reserve) {
- if (!alloc_block(target, segid, size, align, dsp_address)) {
- status = -ENOMEM;
- } else {
- /* Increment the number of allocated blocks in this
- * segment */
- target->seg_tab[segid].number++;
- }
- goto func_end;
- }
- /* An overlay section - See if block is already in use. If not,
- * insert into the list in ascending address size. */
- addr = *dsp_address;
- /* Find place to insert new list element. List is sorted from
- * smallest to largest address. */
- list_for_each_entry(sect, &target->ovly_list, list_elem) {
- if (addr <= sect->addr) {
- /* Check for overlap with sect */
- if ((addr + size > sect->addr) || (prev_sect &&
- (prev_sect->addr +
- prev_sect->size >
- addr))) {
- status = -ENXIO;
- }
- break;
- }
- prev_sect = sect;
- }
- if (!status) {
- /* No overlap - allocate list element for new section. */
- new_sect = kzalloc(sizeof(struct rmm_ovly_sect), GFP_KERNEL);
- if (new_sect == NULL) {
- status = -ENOMEM;
- } else {
- new_sect->addr = addr;
- new_sect->size = size;
- new_sect->page = segid;
- if (list_is_last(&sect->list_elem, &target->ovly_list))
- /* Put new section at the end of the list */
- list_add_tail(&new_sect->list_elem,
- &target->ovly_list);
- else
- /* Put new section just before sect */
- list_add_tail(&new_sect->list_elem,
- &sect->list_elem);
- }
- }
-func_end:
- return status;
-}
-
-/*
- * ======== rmm_create ========
- */
-int rmm_create(struct rmm_target_obj **target_obj,
- struct rmm_segment seg_tab[], u32 num_segs)
-{
- struct rmm_header *hptr;
- struct rmm_segment *sptr, *tmp;
- struct rmm_target_obj *target;
- s32 i;
- int status = 0;
-
- /* Allocate DBL target object */
- target = kzalloc(sizeof(struct rmm_target_obj), GFP_KERNEL);
-
- if (target == NULL)
- status = -ENOMEM;
-
- if (status)
- goto func_cont;
-
- target->num_segs = num_segs;
- if (!(num_segs > 0))
- goto func_cont;
-
- /* Allocate the memory for freelist from host's memory */
- target->free_list = kzalloc(num_segs * sizeof(struct rmm_header *),
- GFP_KERNEL);
- if (target->free_list == NULL) {
- status = -ENOMEM;
- } else {
- /* Allocate headers for each element on the free list */
- for (i = 0; i < (s32) num_segs; i++) {
- target->free_list[i] =
- kzalloc(sizeof(struct rmm_header), GFP_KERNEL);
- if (target->free_list[i] == NULL) {
- status = -ENOMEM;
- break;
- }
- }
- /* Allocate memory for initial segment table */
- target->seg_tab = kzalloc(num_segs * sizeof(struct rmm_segment),
- GFP_KERNEL);
- if (target->seg_tab == NULL) {
- status = -ENOMEM;
- } else {
- /* Initialize segment table and free list */
- sptr = target->seg_tab;
- for (i = 0, tmp = seg_tab; num_segs > 0;
- num_segs--, i++) {
- *sptr = *tmp;
- hptr = target->free_list[i];
- hptr->addr = tmp->base;
- hptr->size = tmp->length;
- hptr->next = NULL;
- tmp++;
- sptr++;
- }
- }
- }
-func_cont:
- /* Initialize overlay memory list */
- if (!status)
- INIT_LIST_HEAD(&target->ovly_list);
-
- if (!status) {
- *target_obj = target;
- } else {
- *target_obj = NULL;
- if (target)
- rmm_delete(target);
-
- }
-
- return status;
-}
-
-/*
- * ======== rmm_delete ========
- */
-void rmm_delete(struct rmm_target_obj *target)
-{
- struct rmm_ovly_sect *sect, *tmp;
- struct rmm_header *hptr;
- struct rmm_header *next;
- u32 i;
-
- kfree(target->seg_tab);
-
- list_for_each_entry_safe(sect, tmp, &target->ovly_list, list_elem) {
- list_del(&sect->list_elem);
- kfree(sect);
- }
-
- if (target->free_list != NULL) {
- /* Free elements on freelist */
- for (i = 0; i < target->num_segs; i++) {
- hptr = next = target->free_list[i];
- while (next) {
- hptr = next;
- next = hptr->next;
- kfree(hptr);
- }
- }
- kfree(target->free_list);
- }
-
- kfree(target);
-}
-
-/*
- * ======== rmm_free ========
- */
-bool rmm_free(struct rmm_target_obj *target, u32 segid, u32 dsp_addr, u32 size,
- bool reserved)
-{
- struct rmm_ovly_sect *sect, *tmp;
- bool ret = false;
-
- /*
- * Free or unreserve memory.
- */
- if (!reserved) {
- ret = free_block(target, segid, dsp_addr, size);
- if (ret)
- target->seg_tab[segid].number--;
-
- } else {
- /* Unreserve memory */
- list_for_each_entry_safe(sect, tmp, &target->ovly_list,
- list_elem) {
- if (dsp_addr == sect->addr) {
- /* Remove from list */
- list_del(&sect->list_elem);
- kfree(sect);
- return true;
- }
- }
- }
- return ret;
-}
-
-/*
- * ======== rmm_stat ========
- */
-bool rmm_stat(struct rmm_target_obj *target, enum dsp_memtype segid,
- struct dsp_memstat *mem_stat_buf)
-{
- struct rmm_header *head;
- bool ret = false;
- u32 max_free_size = 0;
- u32 total_free_size = 0;
- u32 free_blocks = 0;
-
- if ((u32) segid < target->num_segs) {
- head = target->free_list[segid];
-
- /* Collect data from free_list */
- while (head != NULL) {
- max_free_size = max(max_free_size, head->size);
- total_free_size += head->size;
- free_blocks++;
- head = head->next;
- }
-
- /* ul_size */
- mem_stat_buf->size = target->seg_tab[segid].length;
-
- /* num_free_blocks */
- mem_stat_buf->num_free_blocks = free_blocks;
-
- /* total_free_size */
- mem_stat_buf->total_free_size = total_free_size;
-
- /* len_max_free_block */
- mem_stat_buf->len_max_free_block = max_free_size;
-
- /* num_alloc_blocks */
- mem_stat_buf->num_alloc_blocks =
- target->seg_tab[segid].number;
-
- ret = true;
- }
-
- return ret;
-}
-
-/*
- * ======== balloc ========
- * This allocation function allocates memory from the lowest addresses
- * first.
- */
-static bool alloc_block(struct rmm_target_obj *target, u32 segid, u32 size,
- u32 align, u32 *dsp_address)
-{
- struct rmm_header *head;
- struct rmm_header *prevhead = NULL;
- struct rmm_header *next;
- u32 tmpalign;
- u32 alignbytes;
- u32 hsize;
- u32 allocsize;
- u32 addr;
-
- alignbytes = (align == 0) ? 1 : align;
- prevhead = NULL;
- head = target->free_list[segid];
-
- do {
- hsize = head->size;
- next = head->next;
-
- addr = head->addr; /* alloc from the bottom */
-
- /* align allocation */
- (tmpalign = (u32) addr % alignbytes);
- if (tmpalign != 0)
- tmpalign = alignbytes - tmpalign;
-
- allocsize = size + tmpalign;
-
- if (hsize >= allocsize) { /* big enough */
- if (hsize == allocsize && prevhead != NULL) {
- prevhead->next = next;
- kfree(head);
- } else {
- head->size = hsize - allocsize;
- head->addr += allocsize;
- }
-
- /* free up any hole created by alignment */
- if (tmpalign)
- free_block(target, segid, addr, tmpalign);
-
- *dsp_address = addr + tmpalign;
- return true;
- }
-
- prevhead = head;
- head = next;
-
- } while (head != NULL);
-
- return false;
-}
-
-/*
- * ======== free_block ========
- * TO DO: free_block() allocates memory, which could result in failure.
- * Could allocate an rmm_header in rmm_alloc(), to be kept in a pool.
- * free_block() could use an rmm_header from the pool, freeing as blocks
- * are coalesced.
- */
-static bool free_block(struct rmm_target_obj *target, u32 segid, u32 addr,
- u32 size)
-{
- struct rmm_header *head;
- struct rmm_header *thead;
- struct rmm_header *rhead;
- bool ret = true;
-
- /* Create a memory header to hold the newly free'd block. */
- rhead = kzalloc(sizeof(struct rmm_header), GFP_KERNEL);
- if (rhead == NULL) {
- ret = false;
- } else {
- /* search down the free list to find the right place for addr */
- head = target->free_list[segid];
-
- if (addr >= head->addr) {
- while (head->next != NULL && addr > head->next->addr)
- head = head->next;
-
- thead = head->next;
-
- head->next = rhead;
- rhead->next = thead;
- rhead->addr = addr;
- rhead->size = size;
- } else {
- *rhead = *head;
- head->next = rhead;
- head->addr = addr;
- head->size = size;
- thead = rhead->next;
- }
-
- /* join with upper block, if possible */
- if (thead != NULL && (rhead->addr + rhead->size) ==
- thead->addr) {
- head->next = rhead->next;
- thead->size = size + thead->size;
- thead->addr = addr;
- kfree(rhead);
- rhead = thead;
- }
-
- /* join with the lower block, if possible */
- if ((head->addr + head->size) == rhead->addr) {
- head->next = rhead->next;
- head->size = head->size + rhead->size;
- kfree(rhead);
- }
- }
-
- return ret;
-}
diff --git a/drivers/staging/tidspbridge/rmgr/strm.c b/drivers/staging/tidspbridge/rmgr/strm.c
deleted file mode 100644
index b88b27bbe2e7..000000000000
--- a/drivers/staging/tidspbridge/rmgr/strm.c
+++ /dev/null
@@ -1,733 +0,0 @@
-/*
- * strm.c
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * DSP/BIOS Bridge Stream Manager.
- *
- * 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>
-
-/* ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/sync.h>
-
-/* ----------------------------------- Bridge Driver */
-#include <dspbridge/dspdefs.h>
-
-/* ----------------------------------- Resource Manager */
-#include <dspbridge/nodepriv.h>
-
-/* ----------------------------------- Others */
-#include <dspbridge/cmm.h>
-
-/* ----------------------------------- This */
-#include <dspbridge/strm.h>
-
-#include <dspbridge/resourcecleanup.h>
-
-/* ----------------------------------- Defines, Data Structures, Typedefs */
-#define DEFAULTTIMEOUT 10000
-#define DEFAULTNUMBUFS 2
-
-/*
- * ======== strm_mgr ========
- * The strm_mgr contains device information needed to open the underlying
- * channels of a stream.
- */
-struct strm_mgr {
- struct dev_object *dev_obj; /* Device for this processor */
- struct chnl_mgr *chnl_mgr; /* Channel manager */
- /* Function interface to Bridge driver */
- struct bridge_drv_interface *intf_fxns;
-};
-
-/*
- * ======== strm_object ========
- * This object is allocated in strm_open().
- */
-struct strm_object {
- struct strm_mgr *strm_mgr_obj;
- struct chnl_object *chnl_obj;
- u32 dir; /* DSP_TONODE or DSP_FROMNODE */
- u32 timeout;
- u32 num_bufs; /* Max # of bufs allowed in stream */
- u32 bufs_in_strm; /* Current # of bufs in stream */
- u32 bytes; /* bytes transferred since idled */
- /* STREAM_IDLE, STREAM_READY, ... */
- enum dsp_streamstate strm_state;
- void *user_event; /* Saved for strm_get_info() */
- enum dsp_strmmode strm_mode; /* STRMMODE_[PROCCOPY][ZEROCOPY]... */
- u32 dma_chnl_id; /* DMA chnl id */
- u32 dma_priority; /* DMA priority:DMAPRI_[LOW][HIGH] */
- u32 segment_id; /* >0 is SM segment.=0 is local heap */
- u32 buf_alignment; /* Alignment for stream bufs */
- /* Stream's SM address translator */
- struct cmm_xlatorobject *xlator;
-};
-
-/* ----------------------------------- Function Prototypes */
-static int delete_strm(struct strm_object *stream_obj);
-
-/*
- * ======== strm_allocate_buffer ========
- * Purpose:
- * Allocates buffers for a stream.
- */
-int strm_allocate_buffer(struct strm_res_object *strmres, u32 usize,
- u8 **ap_buffer, u32 num_bufs,
- struct process_context *pr_ctxt)
-{
- int status = 0;
- u32 alloc_cnt = 0;
- u32 i;
- struct strm_object *stream_obj = strmres->stream;
-
- if (stream_obj) {
- /*
- * Allocate from segment specified at time of stream open.
- */
- if (usize == 0)
- status = -EINVAL;
-
- } else {
- status = -EFAULT;
- }
-
- if (status)
- goto func_end;
-
- for (i = 0; i < num_bufs; i++) {
- (void)cmm_xlator_alloc_buf(stream_obj->xlator, &ap_buffer[i],
- usize);
- if (ap_buffer[i] == NULL) {
- status = -ENOMEM;
- alloc_cnt = i;
- break;
- }
- }
- if (status)
- strm_free_buffer(strmres, ap_buffer, alloc_cnt, pr_ctxt);
-
- if (status)
- goto func_end;
-
- drv_proc_update_strm_res(num_bufs, strmres);
-
-func_end:
- return status;
-}
-
-/*
- * ======== strm_close ========
- * Purpose:
- * Close a stream opened with strm_open().
- */
-int strm_close(struct strm_res_object *strmres,
- struct process_context *pr_ctxt)
-{
- struct bridge_drv_interface *intf_fxns;
- struct chnl_info chnl_info_obj;
- int status = 0;
- struct strm_object *stream_obj = strmres->stream;
-
- if (!stream_obj) {
- status = -EFAULT;
- } else {
- /* Have all buffers been reclaimed? If not, return
- * -EPIPE */
- intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
- status =
- (*intf_fxns->chnl_get_info) (stream_obj->chnl_obj,
- &chnl_info_obj);
-
- if (chnl_info_obj.cio_cs > 0 || chnl_info_obj.cio_reqs > 0)
- status = -EPIPE;
- else
- status = delete_strm(stream_obj);
- }
-
- if (status)
- goto func_end;
-
- idr_remove(pr_ctxt->stream_id, strmres->id);
-func_end:
- dev_dbg(bridge, "%s: stream_obj: %p, status 0x%x\n", __func__,
- stream_obj, status);
- return status;
-}
-
-/*
- * ======== strm_create ========
- * Purpose:
- * Create a STRM manager object.
- */
-int strm_create(struct strm_mgr **strm_man,
- struct dev_object *dev_obj)
-{
- struct strm_mgr *strm_mgr_obj;
- int status = 0;
-
- *strm_man = NULL;
- /* Allocate STRM manager object */
- strm_mgr_obj = kzalloc(sizeof(struct strm_mgr), GFP_KERNEL);
- if (strm_mgr_obj == NULL)
- status = -ENOMEM;
- else
- strm_mgr_obj->dev_obj = dev_obj;
-
- /* Get Channel manager and Bridge function interface */
- if (!status) {
- status = dev_get_chnl_mgr(dev_obj, &(strm_mgr_obj->chnl_mgr));
- if (!status) {
- (void)dev_get_intf_fxns(dev_obj,
- &(strm_mgr_obj->intf_fxns));
- }
- }
-
- if (!status)
- *strm_man = strm_mgr_obj;
- else
- kfree(strm_mgr_obj);
-
- return status;
-}
-
-/*
- * ======== strm_delete ========
- * Purpose:
- * Delete the STRM Manager Object.
- */
-void strm_delete(struct strm_mgr *strm_mgr_obj)
-{
- kfree(strm_mgr_obj);
-}
-
-/*
- * ======== strm_free_buffer ========
- * Purpose:
- * Frees the buffers allocated for a stream.
- */
-int strm_free_buffer(struct strm_res_object *strmres, u8 **ap_buffer,
- u32 num_bufs, struct process_context *pr_ctxt)
-{
- int status = 0;
- u32 i = 0;
- struct strm_object *stream_obj = strmres->stream;
-
- if (!stream_obj)
- status = -EFAULT;
-
- if (!status) {
- for (i = 0; i < num_bufs; i++) {
- status =
- cmm_xlator_free_buf(stream_obj->xlator,
- ap_buffer[i]);
- if (status)
- break;
- ap_buffer[i] = NULL;
- }
- }
- drv_proc_update_strm_res(num_bufs - i, strmres);
-
- return status;
-}
-
-/*
- * ======== strm_get_info ========
- * Purpose:
- * Retrieves information about a stream.
- */
-int strm_get_info(struct strm_object *stream_obj,
- struct stream_info *stream_info,
- u32 stream_info_size)
-{
- struct bridge_drv_interface *intf_fxns;
- struct chnl_info chnl_info_obj;
- int status = 0;
- void *virt_base = NULL; /* NULL if no SM used */
-
- if (!stream_obj) {
- status = -EFAULT;
- } else {
- if (stream_info_size < sizeof(struct stream_info)) {
- /* size of users info */
- status = -EINVAL;
- }
- }
- if (status)
- goto func_end;
-
- intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
- status =
- (*intf_fxns->chnl_get_info) (stream_obj->chnl_obj,
- &chnl_info_obj);
- if (status)
- goto func_end;
-
- if (stream_obj->xlator) {
- /* We have a translator */
- cmm_xlator_info(stream_obj->xlator, (u8 **) &virt_base, 0,
- stream_obj->segment_id, false);
- }
- stream_info->segment_id = stream_obj->segment_id;
- stream_info->strm_mode = stream_obj->strm_mode;
- stream_info->virt_base = virt_base;
- stream_info->user_strm->number_bufs_allowed = stream_obj->num_bufs;
- stream_info->user_strm->number_bufs_in_stream = chnl_info_obj.cio_cs +
- chnl_info_obj.cio_reqs;
- /* # of bytes transferred since last call to DSPStream_Idle() */
- stream_info->user_strm->number_bytes = chnl_info_obj.bytes_tx;
- stream_info->user_strm->sync_object_handle = chnl_info_obj.event_obj;
- /* Determine stream state based on channel state and info */
- if (chnl_info_obj.state & CHNL_STATEEOS) {
- stream_info->user_strm->ss_stream_state = STREAM_DONE;
- } else {
- if (chnl_info_obj.cio_cs > 0)
- stream_info->user_strm->ss_stream_state = STREAM_READY;
- else if (chnl_info_obj.cio_reqs > 0)
- stream_info->user_strm->ss_stream_state =
- STREAM_PENDING;
- else
- stream_info->user_strm->ss_stream_state = STREAM_IDLE;
-
- }
-func_end:
- return status;
-}
-
-/*
- * ======== strm_idle ========
- * Purpose:
- * Idles a particular stream.
- */
-int strm_idle(struct strm_object *stream_obj, bool flush_data)
-{
- struct bridge_drv_interface *intf_fxns;
- int status = 0;
-
- if (!stream_obj) {
- status = -EFAULT;
- } else {
- intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
-
- status = (*intf_fxns->chnl_idle) (stream_obj->chnl_obj,
- stream_obj->timeout,
- flush_data);
- }
-
- dev_dbg(bridge, "%s: stream_obj: %p flush_data: 0x%x status: 0x%x\n",
- __func__, stream_obj, flush_data, status);
- return status;
-}
-
-/*
- * ======== strm_issue ========
- * Purpose:
- * Issues a buffer on a stream
- */
-int strm_issue(struct strm_object *stream_obj, u8 *pbuf, u32 ul_bytes,
- u32 ul_buf_size, u32 dw_arg)
-{
- struct bridge_drv_interface *intf_fxns;
- int status = 0;
- void *tmp_buf = NULL;
-
- if (!stream_obj) {
- status = -EFAULT;
- } else {
- intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
-
- if (stream_obj->segment_id != 0) {
- tmp_buf = cmm_xlator_translate(stream_obj->xlator,
- (void *)pbuf,
- CMM_VA2DSPPA);
- if (tmp_buf == NULL)
- status = -ESRCH;
-
- }
- if (!status) {
- status = (*intf_fxns->chnl_add_io_req)
- (stream_obj->chnl_obj, pbuf, ul_bytes, ul_buf_size,
- (u32) tmp_buf, dw_arg);
- }
- if (status == -EIO)
- status = -ENOSR;
- }
-
- dev_dbg(bridge, "%s: stream_obj: %p pbuf: %p ul_bytes: 0x%x dw_arg:"
- " 0x%x status: 0x%x\n", __func__, stream_obj, pbuf,
- ul_bytes, dw_arg, status);
- return status;
-}
-
-/*
- * ======== strm_open ========
- * Purpose:
- * Open a stream for sending/receiving data buffers to/from a task or
- * XDAIS socket node on the DSP.
- */
-int strm_open(struct node_object *hnode, u32 dir, u32 index,
- struct strm_attr *pattr,
- struct strm_res_object **strmres,
- struct process_context *pr_ctxt)
-{
- struct strm_mgr *strm_mgr_obj;
- struct bridge_drv_interface *intf_fxns;
- u32 ul_chnl_id;
- struct strm_object *strm_obj = NULL;
- s8 chnl_mode;
- struct chnl_attr chnl_attr_obj;
- int status = 0;
- struct cmm_object *hcmm_mgr = NULL; /* Shared memory manager hndl */
-
- void *stream_res;
-
- *strmres = NULL;
- if (dir != DSP_TONODE && dir != DSP_FROMNODE) {
- status = -EPERM;
- } else {
- /* Get the channel id from the node (set in node_connect()) */
- status = node_get_channel_id(hnode, dir, index, &ul_chnl_id);
- }
- if (!status)
- status = node_get_strm_mgr(hnode, &strm_mgr_obj);
-
- if (!status) {
- strm_obj = kzalloc(sizeof(struct strm_object), GFP_KERNEL);
- if (strm_obj == NULL) {
- status = -ENOMEM;
- } else {
- strm_obj->strm_mgr_obj = strm_mgr_obj;
- strm_obj->dir = dir;
- strm_obj->strm_state = STREAM_IDLE;
- strm_obj->user_event = pattr->user_event;
- if (pattr->stream_attr_in != NULL) {
- strm_obj->timeout =
- pattr->stream_attr_in->timeout;
- strm_obj->num_bufs =
- pattr->stream_attr_in->num_bufs;
- strm_obj->strm_mode =
- pattr->stream_attr_in->strm_mode;
- strm_obj->segment_id =
- pattr->stream_attr_in->segment_id;
- strm_obj->buf_alignment =
- pattr->stream_attr_in->buf_alignment;
- strm_obj->dma_chnl_id =
- pattr->stream_attr_in->dma_chnl_id;
- strm_obj->dma_priority =
- pattr->stream_attr_in->dma_priority;
- chnl_attr_obj.uio_reqs =
- pattr->stream_attr_in->num_bufs;
- } else {
- strm_obj->timeout = DEFAULTTIMEOUT;
- strm_obj->num_bufs = DEFAULTNUMBUFS;
- strm_obj->strm_mode = STRMMODE_PROCCOPY;
- strm_obj->segment_id = 0; /* local mem */
- strm_obj->buf_alignment = 0;
- strm_obj->dma_chnl_id = 0;
- strm_obj->dma_priority = 0;
- chnl_attr_obj.uio_reqs = DEFAULTNUMBUFS;
- }
- chnl_attr_obj.reserved1 = NULL;
- /* DMA chnl flush timeout */
- chnl_attr_obj.reserved2 = strm_obj->timeout;
- chnl_attr_obj.event_obj = NULL;
- if (pattr->user_event != NULL)
- chnl_attr_obj.event_obj = pattr->user_event;
-
- }
- }
- if (status)
- goto func_cont;
-
- if ((pattr->virt_base == NULL) || !(pattr->virt_size > 0))
- goto func_cont;
-
- /* No System DMA */
- /* Get the shared mem mgr for this streams dev object */
- status = dev_get_cmm_mgr(strm_mgr_obj->dev_obj, &hcmm_mgr);
- if (!status) {
- /*Allocate a SM addr translator for this strm. */
- status = cmm_xlator_create(&strm_obj->xlator, hcmm_mgr, NULL);
- if (!status) {
- /* Set translators Virt Addr attributes */
- status = cmm_xlator_info(strm_obj->xlator,
- (u8 **) &pattr->virt_base,
- pattr->virt_size,
- strm_obj->segment_id, true);
- }
- }
-func_cont:
- if (!status) {
- /* Open channel */
- chnl_mode = (dir == DSP_TONODE) ?
- CHNL_MODETODSP : CHNL_MODEFROMDSP;
- intf_fxns = strm_mgr_obj->intf_fxns;
- status = (*intf_fxns->chnl_open) (&(strm_obj->chnl_obj),
- strm_mgr_obj->chnl_mgr,
- chnl_mode, ul_chnl_id,
- &chnl_attr_obj);
- if (status) {
- /*
- * over-ride non-returnable status codes so we return
- * something documented
- */
- if (status != -ENOMEM && status !=
- -EINVAL && status != -EPERM) {
- /*
- * We got a status that's not return-able.
- * Assert that we got something we were
- * expecting (-EFAULT isn't acceptable,
- * strm_mgr_obj->chnl_mgr better be valid or we
- * assert here), and then return -EPERM.
- */
- status = -EPERM;
- }
- }
- }
- if (!status) {
- status = drv_proc_insert_strm_res_element(strm_obj,
- &stream_res, pr_ctxt);
- if (status)
- delete_strm(strm_obj);
- else
- *strmres = (struct strm_res_object *)stream_res;
- } else {
- (void)delete_strm(strm_obj);
- }
-
- dev_dbg(bridge, "%s: hnode: %p dir: 0x%x index: 0x%x pattr: %p "
- "strmres: %p status: 0x%x\n", __func__,
- hnode, dir, index, pattr, strmres, status);
- return status;
-}
-
-/*
- * ======== strm_reclaim ========
- * Purpose:
- * Relcaims a buffer from a stream.
- */
-int strm_reclaim(struct strm_object *stream_obj, u8 **buf_ptr,
- u32 *nbytes, u32 *buff_size, u32 *pdw_arg)
-{
- struct bridge_drv_interface *intf_fxns;
- struct chnl_ioc chnl_ioc_obj;
- int status = 0;
- void *tmp_buf = NULL;
-
- if (!stream_obj) {
- status = -EFAULT;
- goto func_end;
- }
- intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
-
- status =
- (*intf_fxns->chnl_get_ioc) (stream_obj->chnl_obj,
- stream_obj->timeout,
- &chnl_ioc_obj);
- if (!status) {
- *nbytes = chnl_ioc_obj.byte_size;
- if (buff_size)
- *buff_size = chnl_ioc_obj.buf_size;
-
- *pdw_arg = chnl_ioc_obj.arg;
- if (!CHNL_IS_IO_COMPLETE(chnl_ioc_obj)) {
- if (CHNL_IS_TIMED_OUT(chnl_ioc_obj)) {
- status = -ETIME;
- } else {
- /* Allow reclaims after idle to succeed */
- if (!CHNL_IS_IO_CANCELLED(chnl_ioc_obj))
- status = -EPERM;
-
- }
- }
- /* Translate zerocopy buffer if channel not canceled. */
- if (!status
- && (!CHNL_IS_IO_CANCELLED(chnl_ioc_obj))
- && (stream_obj->strm_mode == STRMMODE_ZEROCOPY)) {
- /*
- * This is a zero-copy channel so chnl_ioc_obj.buf
- * contains the DSP address of SM. We need to
- * translate it to a virtual address for the user
- * thread to access.
- * Note: Could add CMM_DSPPA2VA to CMM in the future.
- */
- tmp_buf = cmm_xlator_translate(stream_obj->xlator,
- chnl_ioc_obj.buf,
- CMM_DSPPA2PA);
- if (tmp_buf != NULL) {
- /* now convert this GPP Pa to Va */
- tmp_buf = cmm_xlator_translate(stream_obj->
- xlator,
- tmp_buf,
- CMM_PA2VA);
- }
- if (tmp_buf == NULL)
- status = -ESRCH;
-
- chnl_ioc_obj.buf = tmp_buf;
- }
- *buf_ptr = chnl_ioc_obj.buf;
- }
-func_end:
- dev_dbg(bridge, "%s: stream_obj: %p buf_ptr: %p nbytes: %p "
- "pdw_arg: %p status 0x%x\n", __func__, stream_obj,
- buf_ptr, nbytes, pdw_arg, status);
- return status;
-}
-
-/*
- * ======== strm_register_notify ========
- * Purpose:
- * Register to be notified on specific events for this stream.
- */
-int strm_register_notify(struct strm_object *stream_obj, u32 event_mask,
- u32 notify_type, struct dsp_notification
- *hnotification)
-{
- struct bridge_drv_interface *intf_fxns;
- int status = 0;
-
- if (!stream_obj) {
- status = -EFAULT;
- } else if ((event_mask & ~((DSP_STREAMIOCOMPLETION) |
- DSP_STREAMDONE)) != 0) {
- status = -EINVAL;
- } else {
- if (notify_type != DSP_SIGNALEVENT)
- status = -ENOSYS;
-
- }
- if (!status) {
- intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
-
- status =
- (*intf_fxns->chnl_register_notify) (stream_obj->
- chnl_obj,
- event_mask,
- notify_type,
- hnotification);
- }
-
- return status;
-}
-
-/*
- * ======== strm_select ========
- * Purpose:
- * Selects a ready stream.
- */
-int strm_select(struct strm_object **strm_tab, u32 strms,
- u32 *pmask, u32 utimeout)
-{
- u32 index;
- struct chnl_info chnl_info_obj;
- struct bridge_drv_interface *intf_fxns;
- struct sync_object **sync_events = NULL;
- u32 i;
- int status = 0;
-
- *pmask = 0;
- for (i = 0; i < strms; i++) {
- if (!strm_tab[i]) {
- status = -EFAULT;
- break;
- }
- }
- if (status)
- goto func_end;
-
- /* Determine which channels have IO ready */
- for (i = 0; i < strms; i++) {
- intf_fxns = strm_tab[i]->strm_mgr_obj->intf_fxns;
- status = (*intf_fxns->chnl_get_info) (strm_tab[i]->chnl_obj,
- &chnl_info_obj);
- if (status) {
- break;
- } else {
- if (chnl_info_obj.cio_cs > 0)
- *pmask |= (1 << i);
-
- }
- }
- if (!status && utimeout > 0 && *pmask == 0) {
- /* Non-zero timeout */
- sync_events = kmalloc(strms * sizeof(struct sync_object *),
- GFP_KERNEL);
-
- if (sync_events == NULL) {
- status = -ENOMEM;
- } else {
- for (i = 0; i < strms; i++) {
- intf_fxns =
- strm_tab[i]->strm_mgr_obj->intf_fxns;
- status = (*intf_fxns->chnl_get_info)
- (strm_tab[i]->chnl_obj, &chnl_info_obj);
- if (status)
- break;
- else
- sync_events[i] =
- chnl_info_obj.sync_event;
-
- }
- }
- if (!status) {
- status =
- sync_wait_on_multiple_events(sync_events, strms,
- utimeout, &index);
- if (!status) {
- /* Since we waited on the event, we have to
- * reset it */
- sync_set_event(sync_events[index]);
- *pmask = 1 << index;
- }
- }
- }
-func_end:
- kfree(sync_events);
-
- return status;
-}
-
-/*
- * ======== delete_strm ========
- * Purpose:
- * Frees the resources allocated for a stream.
- */
-static int delete_strm(struct strm_object *stream_obj)
-{
- struct bridge_drv_interface *intf_fxns;
- int status = 0;
-
- if (stream_obj) {
- if (stream_obj->chnl_obj) {
- intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
- /* Channel close can fail only if the channel handle
- * is invalid. */
- status = (*intf_fxns->chnl_close)
- (stream_obj->chnl_obj);
- }
- /* Free all SM address translator resources */
- kfree(stream_obj->xlator);
- kfree(stream_obj);
- } else {
- status = -EFAULT;
- }
- return status;
-}