]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
platform: nvadsp: Common code for ADSP dynamic app
authorAjay Nandakumar <anandakumarm@nvidia.com>
Thu, 8 Jan 2015 14:46:40 +0000 (20:16 +0530)
committerAjay Nandakumar M <anandakumarm@nvidia.com>
Mon, 13 Apr 2015 04:43:51 +0000 (21:43 -0700)
Use commom ADSP app framework code for adsp run APIs and nvadsp_app_*
APIs. This makes it easier to maintain and also reduces sizes of text
data and bss.

Bug 200069519

Change-Id: I35c838b6d4aab4288176573b7a5b8b663ec84584
Signed-off-by: Ajay Nandakumar <anandakumarm@nvidia.com>
Reviewed-on: http://git-master/r/720018
(cherry picked from commit edfa9e7dbd3ca495ec3a3930c0b6d6469c66ac03)
Reviewed-on: http://git-master/r/668876
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
drivers/platform/tegra/nvadsp/Makefile
drivers/platform/tegra/nvadsp/app.c
drivers/platform/tegra/nvadsp/dev.c
drivers/platform/tegra/nvadsp/os.c
drivers/platform/tegra/nvadsp/os.h
drivers/platform/tegra/nvadsp/run_app.c [deleted file]
include/linux/tegra_nvadsp.h

index 1416d531c8a7c2e86b602e71ab4a340184e3b265..11e681ac47f869a1439f5ededd1bc09c177723b7 100644 (file)
@@ -6,8 +6,7 @@ nvadsp-objs += dev.o os.o app.o app_loader_linker.o\
         amc.o nvadsp_dram.o \
         nvadsp_shared_sema.o nvadsp_arb_sema.o \
         hwmailbox.o mailbox.o msgq.o \
-        mem_manager.o aram_manager.o dram_app_mem_manager.o \
-        run_app.o
+        mem_manager.o aram_manager.o dram_app_mem_manager.o
 
 ifeq ($(CONFIG_TEGRA_ADSP_DFS),y)
 nvadsp-objs += adsp_dfs.o
index 74f053a58ec6d41bb4b57aacb1633cbc9f811c01..7a3b679186544ca1f804fddb924da3a17efa688d 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * app.c
+ * run_app.c
  *
  * ADSP OS App management
  *
- * Copyright (C) 2014 NVIDIA Corporation. All rights reserved.
+ * Copyright (C) 2014-2015 NVIDIA Corporation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
 #define ADSP_OS_LOAD_TIMEOUT           5000 /* 5000 ms */
 #define APP_FRAME_WAIT_TIMEOUT         5000 /* 5000 ms */
 
-#define OS_LOAD_COMPLETE               0x01
-#define LOAD_APP                       0x03
-#define APP_LOAD_RET_STATUS            0x04
-#define APP_INIT                       0x05
-#define APP_INIT_STATUS                        0x06
-#define APP_START                      0x07
-#define APP_START_STATUS               0x08
-#define APP_DEINIT                     0x09
-#define APP_DEINIT_STATUS              0x0A
-#define APP_COMPLETE                   0x0B
-#define APP_UNLOAD                     0x0C
-#define APP_UNLOAD_STATUS              0x0D
+/*ADSP message pool structure */
+union app_loader_msgq {
+       msgq_t msgq;
+       struct {
+               int32_t header[MSGQ_HEADER_WSIZE];
+               int32_t queue[MSGQ_MAX_QUEUE_WSIZE];
+       };
+};
+
+struct adsp_app_shared_msg_pool {
+       union app_loader_msgq           app_loader_send_message;
+       union app_loader_msgq           app_loader_recv_message;
+} __packed;
+
+/* ADSP app loader message queue */
+struct run_app_instance_data {
+       uint32_t adsp_mod_ptr;
+       uint64_t host_ref;
+       uint32_t adsp_ref;
+       uint32_t dram_data_ptr;
+       uint32_t dram_shared_ptr;
+       uint32_t dram_shared_wc_ptr;
+       uint32_t aram_ptr;
+       uint32_t aram_flag;
+       uint32_t aram_x_ptr;
+       uint32_t aram_x_flag;
+       struct app_mem_size mem_size;
+       nvadsp_app_args_t app_args;
+       uint32_t stack_size;
+       uint32_t message;
+} __packed;
+
+struct app_loader_data {
+       int32_t header[MSGQ_MESSAGE_HEADER_WSIZE];
+       struct run_app_instance_data    app_init;
+} __packed;
+
+#pragma pack(4)
+union app_loader_message {
+       msgq_message_t msgq_msg;
+       struct app_loader_data data;
+};
 
+struct app_complete_status_data {
+       int32_t header[MSGQ_MESSAGE_HEADER_WSIZE];
+       uint64_t host_ref;
+       uint32_t adsp_ref;
+       int32_t status;
+       uint32_t message;
+} __packed;
+
+#pragma pack(4)
+union app_complete_status_message {
+       msgq_message_t msgq_msg;
+       struct app_complete_status_data data;
+};
+
+/*
+ * structure to hold the list of app binaries loaded and
+ * its associated instances.
+*/
 struct nvadsp_app_service {
        char name[NVADSP_NAME_SZ];
-       char file[NVADSP_NAME_SZ];
        struct list_head node;
        int instance;
-       spinlock_t lock;
+       struct mutex lock;
        struct list_head app_head;
        const uint32_t token;
        const struct app_mem_size *mem_size;
@@ -61,458 +108,182 @@ struct nvadsp_app_service {
        struct adsp_module *mod;
 };
 
+/* nvadsp app loader private structure */
 struct nvadsp_app_priv_struct {
        struct platform_device *pdev;
+       struct completion os_load_complete;
+       struct nvadsp_mbox mbox;
+       struct list_head service_list;
+       struct mutex service_lock_list;
 };
 
 static struct nvadsp_app_priv_struct priv;
-static struct nvadsp_mbox mbox;
-static struct list_head service_list;
-#if RECORD_STATS
-static u64 ns_time_native_load_complete;
-#endif
-
-static DECLARE_COMPLETION(os_load);
-static DECLARE_COMPLETION(load_app_status);
-static DECLARE_COMPLETION(app_init_status);
-static DECLARE_COMPLETION(app_start_status);
-static DECLARE_COMPLETION(app_deinit_status);
-static DECLARE_COMPLETION(app_unload_status);
-
-static DEFINE_MUTEX(load_app_mutex);
-static DEFINE_MUTEX(app_init_mutex);
-static DEFINE_MUTEX(app_start_mutex);
-static DEFINE_MUTEX(app_deinit_mutex);
-static DEFINE_MUTEX(app_unload_mutex);
-
-/* app states need to be changed atomically */
-static DEFINE_SPINLOCK(state_lock);
-
-static DEFINE_MUTEX(service_lock_list);
-
-static struct shared_mem_struct *shared;
-
-static inline void print_load_stats(const char *appfile,
-       struct app_load_stats *stats, struct device *dev)
-{
-#if RECORD_STATS
-       dev_info(dev, "%s total load time %lld us\n",
-               appfile, stats->ns_time_load / 1000);
-       dev_info(dev, "%s parse load time %lld us\n",
-               appfile, stats->ns_time_service_parse / 1000);
-       dev_info(dev, "%s module load time %lld us\n",
-               appfile, stats->ns_time_module_load / 1000);
-       dev_info(dev, "\t request firmware %lld us\n",
-               stats->ns_time_req_firmware / 1000);
-       dev_info(dev, "\t layout and allocate  %lld us\n",
-               stats->ns_time_layout / 1000);
-       dev_info(dev, "%s native load time %lld us\n",
-               appfile, stats->ns_time_native_load / 1000);
-       dev_info(dev, "\t load mbox_send time %lld us\n",
-               stats->ns_time_load_mbox_send_time / 1000);
-       dev_info(dev, "\t load native wait time %lld us\n",
-               stats->ns_time_load_wait_time / 1000);
-       dev_info(dev, "\t\t load native load complete %lld us\n",
-               stats->ns_time_native_load_complete / 1000);
-       dev_info(dev, "\t\t\t adsp map %llu us\n",
-               stats->ns_time_adsp_map);
-       dev_info(dev, "\t\t\t adsp app load %llu us\n",
-               stats->ns_time_adsp_app_load);
-       dev_info(dev, "\t\t\t adsp app load send ack %llu us\n",
-               stats->ns_time_adsp_send_status);
-       dev_info(dev, "\t\t\t latency in receiveing the mbox on adsp %llu\n",
-               stats->adsp_receive_timestamp - stats->host_send_timestamp);
-       dev_info(dev, "\t\t\t latency in receiveing the mbox on host %llu\n",
-               stats->host_receive_timestamp - stats->adsp_receive_timestamp);
-       dev_info(dev, "%s timestamp before send %llu\n",
-               appfile, stats->host_send_timestamp);
-       dev_info(dev, "%s timestamp on adsp receive %llu\n",
-               appfile, stats->adsp_receive_timestamp);
-       dev_info(dev, "%s timestamp on adsp receive %llu\n",
-               appfile, stats->host_receive_timestamp);
-#endif
-}
-
-static inline void print_init_stats(const char *appfile,
-       struct app_init_stats *stats, struct device *dev)
-{
-#if RECORD_STATS
-       dev_info(dev, "%s app takes %lld us to init\n",
-               appfile, stats->ns_time_app_init / 1000);
-       dev_info(dev, "\t app instance allocation %lld us\n",
-               stats->ns_time_app_alloc / 1000);
-       dev_info(dev, "\t app instance memory allocation %lld us\n",
-               stats->ns_time_instance_memory / 1000);
-       dev_info(dev, "\t app instance native init call %lld us\n",
-               stats->ns_time_native_call / 1000);
-       dev_info(dev, "\t\t app init call on adsp %llu us\n",
-               stats->ns_time_adsp_app_init);
-       dev_info(dev, "\t\t\t app instance map on adsp %llu us\n",
-               stats->ns_time_adsp_mem_instance_map);
-       dev_info(dev, "\t\t\t app actual init call on adsp %llu us\n",
-               stats->ns_time_adsp_init_call);
-       dev_info(dev, "\t\t app send init status ack %llu us\n",
-               stats->ns_time_adsp_send_status);
-#endif
-}
-
-static inline void print_start_stats(const char *appfile,
-       struct app_start_stats *stats, struct device *dev)
-{
-#if RECORD_STATS
-       dev_info(dev, "%s app takes %lld us to start\n",
-               appfile, stats->ns_time_app_start / 1000);
-       dev_info(dev, "\t app instance native init call %lld us\n",
-               stats->ns_time_native_call / 1000);
-       dev_info(dev, "\t\t app start call on adsp %llu us\n",
-               stats->ns_time_adsp_app_start);
-       dev_info(dev, "\t\t\t app thread creation %llu us\n",
-               stats->ns_time_app_thread_creation);
-       dev_info(dev, "\t\t\t app thread detach %llu us\n",
-               stats->ns_time_app_thread_detach);
-       dev_info(dev, "\t\t\t app threaad resume %llu us\n",
-               stats->ns_time_app_thread_resume);
-       dev_info(dev, "\t\t app send start status ack %llu us\n",
-               stats->ns_time_adsp_send_status);
-#endif
-}
-
-
-static inline int wait_for_app_frame_timeout(struct completion *complete)
-{
-       unsigned long timeout = msecs_to_jiffies(APP_FRAME_WAIT_TIMEOUT);
-       return wait_for_completion_interruptible_timeout(complete, timeout);
-}
 
-
-static void app_complete_notifier(struct work_struct *work)
-{
-       nvadsp_app_info_t *app = container_of(work,
-                       struct nvadsp_app_info, complete_work);
-
-       app->complete_status_notifier(app, ADSP_APP_COMPLETE_STATUS,
-                       app->return_status);
-}
-
-static void notify_update_nvadsp_app_complete(struct app_complete_data *data)
+static struct nvadsp_app_service *get_loaded_service(const char *appfile)
 {
-       nvadsp_app_info_t *app = (nvadsp_app_info_t *)data->host_ref;
-       int *state;
-       unsigned long flags;
-
-       app->return_status = data->app_status;
-
-       /* notify adsp can process next data */
-       data->copy_complete = 0;
-
-       /* set the app instance as initialized to be reused or deinit */
-       state = (int *)&app->state;
-       spin_lock_irqsave(&state_lock, flags);
-       *state = NVADSP_APP_STATE_INITIALIZED;
-       spin_unlock_irqrestore(&state_lock, flags);
-       /*
-        * schedule the work if there is notifier call back and adsp app
-        * instance has started
-        */
-       if (app->complete_status_notifier)
-               schedule_work(&app->complete_work);
-
-       /* notify app instance has completed */
-       complete_all(&app->wait_for_app_complete);
-}
-
-static status_t nvadsp_app_receive_handler(uint32_t data, void *hdata)
-{
-       struct nvadsp_app_priv_struct *priv = hdata;
-       struct device *dev = &priv->pdev->dev;
-       struct app_load_data *load;
-
-       load = &shared->app_load;
-       RECORD_TIMESTAMP(load->receive_timestamp);
-       switch (data) {
-       case OS_LOAD_COMPLETE:
-               dev_dbg(dev, "in OS_LOAD_COMPLETE\n");
-               complete(&os_load);
-               break;
-
-       case APP_LOAD_RET_STATUS:
-               dev_dbg(dev, "in APP_LOAD_RET_STATUS\n");
-               RECORD_STAT(ns_time_native_load_complete);
-               complete(&load_app_status);
-               break;
-
-       case APP_UNLOAD_STATUS:
-               dev_dbg(dev, "in APP_LOAD_RET_STATUS\n");
-               complete(&app_unload_status);
-               break;
-
-       case APP_INIT_STATUS:
-               dev_dbg(dev, "in APP_INIT_STATUS\n");
-               complete(&app_init_status);
-               break;
-
-       case APP_DEINIT_STATUS:
-               dev_dbg(dev, "in APP_DEINIT_STATUS\n");
-               complete(&app_deinit_status);
-               break;
-
-       case APP_START_STATUS:
-               dev_dbg(dev, "in APP_START_STATUS\n");
-               complete(&app_start_status);
-               break;
-
-       case APP_COMPLETE:
-               dev_dbg(dev, "in APP_COMPLETE\n");
-               notify_update_nvadsp_app_complete(&shared->app_complete);
-               break;
+       struct device *dev = &priv.pdev->dev;
+       struct nvadsp_app_service *ser;
 
-       default:
-               dev_err(dev, "received wrong data\n");
+       list_for_each_entry(ser, &priv.service_list, node) {
+               if (!strcmp(appfile, ser->name)) {
+                       dev_dbg(dev, "module %s already loaded\n", appfile);
+                       return ser;
+               }
        }
-       return 0;
+       dev_dbg(dev, "module %s will be loaded\n", appfile);
+       return NULL;
 }
 
-int wait_for_adsp_os_load_complete(void)
+static nvadsp_app_handle_t app_load(const char *appfile)
 {
        struct device *dev = &priv.pdev->dev;
-       unsigned long timeout;
-       int ret;
-
-       timeout = msecs_to_jiffies(ADSP_OS_LOAD_TIMEOUT);
-       ret = wait_for_completion_timeout(&os_load, timeout);
-       if (!ret) {
-               dev_err(dev, "ADSP OS loading timed out\n");
-               ret = -ETIMEDOUT;
-       } else
-               ret = 0;
-
-       return ret;
-}
-static inline void native_adsp_app_start_stats(struct app_start_stats *stats,
-       struct app_start_data *data)
-{
-       EQUATE_STAT(stats->ns_time_adsp_app_start, data->app_start_time);
-       EQUATE_STAT(stats->ns_time_app_thread_creation,
-               data->app_thread_creation_time);
-       EQUATE_STAT(stats->ns_time_app_thread_detach,
-               data->app_thread_detach_time);
-       EQUATE_STAT(stats->ns_time_app_thread_resume,
-               data->app_thread_resume_time);
-       EQUATE_STAT(stats->ns_time_adsp_send_status,
-               data->adsp_send_status_time);
-       EQUATE_STAT(stats->adsp_receive_timestamp, data->timestamp);
-}
-
-static int native_adsp_app_start(nvadsp_app_info_t *app,
-       struct app_start_stats *stats)
-{
-       struct app_start_data *data = &shared->app_start;
-       int32_t status = -EINVAL;
+       struct nvadsp_app_service *ser;
+       struct app_load_stats stats;
 
-       data->ptr = app->token;
-       data->stack_size = app->stack_size;
+       mutex_lock(&priv.service_lock_list);
+       ser = get_loaded_service(appfile);
+       if (!ser) {
+               dev_dbg(dev, "loading app %s\n", appfile);
 
-       nvadsp_mbox_send(&mbox, APP_START, NVADSP_MBOX_SMSG, true, 100);
-       status = (wait_for_app_frame_timeout(&app_start_status) <= 0)
-                       ? status : data->status;
-       native_adsp_app_start_stats(stats, data);
-       memset(data, 0, sizeof(struct app_start_data));
+               ser = devm_kzalloc(dev, sizeof(*ser), GFP_KERNEL);
+               if (!ser)
+                       goto err;
+               strncpy(ser->name, appfile, NVADSP_NAME_SZ);
 
-       return status;
-}
+               /*load the module in to memory */
+               ser->mod = load_adsp_module(appfile, appfile, dev, &stats);
+               if (IS_ERR_OR_NULL(ser->mod))
+                       goto err_free_service;
+               ser->mem_size = &ser->mod->mem_size;
 
-static struct nvadsp_app_service
-*get_loaded_service(const char *appname)
-{
-       struct device *dev = &priv.pdev->dev;
-       struct nvadsp_app_service *ser;
+               mutex_init(&ser->lock);
+               INIT_LIST_HEAD(&ser->app_head);
 
-       mutex_lock(&service_lock_list);
-       list_for_each_entry(ser, &service_list, node) {
-               if (!strcmp(appname, ser->name)) {
-                       dev_dbg(dev, "module %s already loaded\n", appname);
-                       mutex_unlock(&service_lock_list);
-                       return ser;
-               }
+               /* add the app instance service to the list */
+               list_add_tail(&ser->node, &priv.service_list);
+               dev_dbg(dev, "loaded app %s\n", ser->name);
        }
-       mutex_unlock(&service_lock_list);
-       dev_dbg(dev, "module %s can be loaded\n", appname);
-       return NULL;
-}
-
-static inline void native_adsp_load_stats(struct app_load_stats *stats,
-       struct app_load_data *data)
-{
-       EQUATE_STAT(stats->ns_time_native_load_complete,
-               ns_time_native_load_complete);
-       EQUATE_STAT(stats->ns_time_adsp_map, data->map_time);
-       EQUATE_STAT(stats->ns_time_adsp_app_load, data->app_load_time);
-       EQUATE_STAT(stats->ns_time_adsp_send_status,
-               data->adsp_send_status_time);
-       EQUATE_STAT(stats->adsp_receive_timestamp, data->timestamp);
-       EQUATE_STAT(stats->host_receive_timestamp, data->receive_timestamp);
-       EQUATE_STAT(ns_time_native_load_complete, 0);
-}
+       mutex_unlock(&priv.service_lock_list);
 
-static uint32_t native_adsp_load_app(struct nvadsp_app_service *ser,
-       struct app_load_stats *stats)
-{
-       uint32_t status = 0;
-       struct app_load_data *data = &shared->app_load;
+       return ser;
 
-       memcpy(&data->mem_size, ser->mem_size,
-                                       sizeof(struct app_mem_size));
-#if !CONFIG_USE_STATIC_APP_LOAD
-       data->adsp_mod_ptr = ser->mod->adsp_module_ptr;
-       data->adsp_mod_size = ser->mod->size;
-#else
-       strncpy(data->service_name, ser->name, NVADSP_NAME_SZ);
-#endif
-
-       RECORD_TIMESTAMP(stats->host_send_timestamp);
-       RECORD_STAT(stats->ns_time_load_mbox_send_time);
-       nvadsp_mbox_send(&mbox, LOAD_APP, NVADSP_MBOX_SMSG, true, 100);
-       RECORD_STAT(stats->ns_time_load_mbox_send_time);
-
-       RECORD_STAT(stats->ns_time_load_wait_time);
-       RECORD_STAT(ns_time_native_load_complete);
-       status = (wait_for_app_frame_timeout(&load_app_status) <= 0)
-                       ? status : data->ser;
-       RECORD_STAT(stats->ns_time_load_wait_time);
-       native_adsp_load_stats(stats, data);
-       memset(data, 0, sizeof(struct app_load_data));
-
-       return status;
+err_free_service:
+       devm_kfree(dev, ser);
+err:
+       mutex_unlock(&priv.service_lock_list);
+       return NULL;
 }
 
-void update_nvadsp_app_shared_ptr(void *ptr)
-{
-       shared = (struct shared_mem_struct *)ptr;
-}
 
-nvadsp_app_handle_t
-nvadsp_app_load(const char *appname, const char *appfile)
+nvadsp_app_handle_t nvadsp_app_load(const char *appname, const char *appfile)
 {
-       struct nvadsp_app_service *ser = NULL;
-       struct app_load_stats stats = { };
        struct nvadsp_drv_data *drv_data;
-       struct adsp_module *mod;
-       struct device *dev;
-       uint32_t *token;
 
-       if (!priv.pdev) {
+       if (IS_ERR_OR_NULL(priv.pdev)) {
                pr_err("ADSP Driver is not initialized\n");
-               goto end;
+               return NULL;
        }
 
        drv_data = platform_get_drvdata(priv.pdev);
-       dev = &priv.pdev->dev;
 
        if (!drv_data->adsp_os_running)
-               goto end;
+               return NULL;
 
+       return app_load(appfile);
+}
+EXPORT_SYMBOL(nvadsp_app_load);
 
-       RECORD_STAT(stats.ns_time_load);
-       RECORD_STAT(stats.ns_time_service_parse);
-       ser = get_loaded_service(appname);
-       RECORD_STAT(stats.ns_time_service_parse);
-       if (!ser) {
-               dev_dbg(dev, "loading app %s\n", appname);
+static void free_instance_memory(nvadsp_app_info_t *app,
+               const struct app_mem_size *sz)
+{
+       adsp_app_mem_t *mem = &app->mem;
+       adsp_app_iova_mem_t *iova_mem = &app->iova_mem;
 
-               RECORD_STAT(stats.ns_time_module_load);
-               mod = load_adsp_module(appname, appfile, dev, &stats);
-               if (IS_ERR_OR_NULL(mod))
-                       goto end;
-               RECORD_STAT(stats.ns_time_module_load);
-
-               ser = kzalloc(sizeof(struct nvadsp_app_service), GFP_KERNEL);
-               strncpy(ser->name, appname, NVADSP_NAME_SZ);
-               strncpy(ser->file, appfile, NVADSP_NAME_SZ);
-               ser->mod = mod;
-
-               ser->mem_size = &mod->mem_size;
-               token = (void *)&ser->token;
-               RECORD_STAT(stats.ns_time_native_load);
-               mutex_lock(&load_app_mutex);
-               *token = native_adsp_load_app(ser, &stats);
-               mutex_unlock(&load_app_mutex);
-               RECORD_STAT(stats.ns_time_native_load);
-               if (!ser->token) {
-                       dev_err(dev, "unable to load app %s\n", appname);
-                       goto err;
-               }
-               spin_lock_init(&ser->lock);
-               INIT_LIST_HEAD(&ser->app_head);
+       if (mem->dram) {
+               nvadsp_free_coherent(sz->dram, mem->dram, iova_mem->dram);
+               mem->dram = NULL;
+               iova_mem->dram = 0;
+       }
 
-               /* add the app instance service to the list */
-               mutex_lock(&service_lock_list);
-               list_add_tail(&ser->node, &service_list);
-               mutex_unlock(&service_lock_list);
+       if (mem->shared) {
+               nvadsp_free_coherent(sz->dram_shared, mem->shared,
+                               iova_mem->shared);
+               mem->shared = NULL;
+               iova_mem->shared = 0;
+       }
 
-               dev_dbg(dev, "loaded app %s\n", ser->name);
+       if (mem->shared_wc) {
+               nvadsp_free_coherent(sz->dram_shared_wc, mem->shared_wc,
+                               iova_mem->shared_wc);
+               mem->shared_wc = NULL;
+               iova_mem->shared_wc = 0;
+       }
+
+       if (mem->aram_flag)
+               aram_release(mem->aram);
+       else if (mem->aram)
+               nvadsp_free_coherent(sz->aram, mem->aram, iova_mem->aram);
+       mem->aram = NULL;
+       iova_mem->aram = 0;
+       mem->aram_flag = 0;
+
+       if (mem->aram_x_flag) {
+               aram_release(mem->aram_x);
+               mem->aram_x = NULL;
+               iova_mem->aram_x = 0;
+               mem->aram_flag = 0;
        }
 
-       RECORD_STAT(stats.ns_time_load);
-       print_load_stats(appfile, &stats, dev);
-end:
-       return ser;
-err:
-       kfree(ser);
-       return NULL;
 }
-EXPORT_SYMBOL(nvadsp_app_load);
 
-static int
-create_instance_memory(nvadsp_app_info_t *app, const struct app_mem_size *sz)
+static int create_instance_memory(nvadsp_app_info_t *app,
+               const struct app_mem_size *sz)
 {
+       adsp_app_iova_mem_t *iova_mem = &app->iova_mem;
        struct device *dev = &priv.pdev->dev;
        adsp_app_mem_t *mem = &app->mem;
-       adsp_app_iova_mem_t *iova_mem = &app->iova_mem;
-       dma_addr_t da;
-       void *aram_handle;
        char name[NVADSP_NAME_SZ];
+       void *aram_handle;
+       dma_addr_t da;
 
        snprintf(name, NVADSP_NAME_SZ, "%s:%d", app->name, app->instance_id);
 
        if (sz->dram) {
                mem->dram = nvadsp_alloc_coherent(sz->dram, &da, GFP_KERNEL);
+               iova_mem->dram = (uint32_t)da;
                if (!mem->dram) {
-                       dev_err(dev,
-                       "cannot allocate dram memory for app %s instance\n",
-                       name);
+                       dev_err(dev, "app %s dram alloc failed\n",
+                               name);
                        goto end;
                }
-               iova_mem->dram = (uint32_t)da;
-               dev_dbg(dev, "%s :: mem.dram %p 0x%x\n",
-                               name, mem->dram, iova_mem->dram);
+               dev_dbg(dev, "%s :: mem.dram %p 0x%x\n", name,
+                       mem->dram, iova_mem->dram);
        }
 
        if (sz->dram_shared) {
                mem->shared = nvadsp_alloc_coherent(sz->dram_shared,
-                                                       &da, GFP_KERNEL);
+                               &da, GFP_KERNEL);
                if (!mem->shared) {
-                       dev_err(dev,
-                       "cannot allocate dram shared for app %s instance\n",
-                       name);
-                       goto free_dram;
+                       dev_err(dev, "app %s shared dram alloc failed\n",
+                               name);
+                       goto end;
                }
                iova_mem->shared = (uint32_t)da;
-               dev_dbg(dev, "%s :: mem.shared %p 0x%x\n",
-                               name, mem->shared, iova_mem->shared);
+               dev_dbg(dev, "%s :: mem.shared %p 0x%x\n", name,
+                       mem->shared, iova_mem->shared);
        }
 
        if (sz->dram_shared_wc) {
-               mem->shared_wc = nvadsp_alloc_coherent(
-                               sz->dram_shared_wc, &da, GFP_KERNEL);
+               mem->shared_wc = nvadsp_alloc_coherent(sz->dram_shared_wc,
+                                       &da, GFP_KERNEL);
                if (!mem->shared_wc) {
-                       dev_err(dev,
-                       "cannot allocate dram shared for app %s instance\n",
-                                               name);
-                       goto free_dram_shared;
+                       dev_err(dev, "app %s shared dram wc alloc failed\n",
+                               name);
+                       goto end;
                }
                iova_mem->shared_wc = (uint32_t)da;
-               dev_dbg(dev, "%s: :: mem.shared_wc %p 0x%x\n",
-                               name, mem->shared_wc, iova_mem->shared_wc);
+               dev_dbg(dev, "%s :: mem.shared_wc %p 0x%x\n", name,
+                       mem->shared_wc, iova_mem->shared_wc);
        }
 
        if (sz->aram) {
@@ -523,21 +294,20 @@ create_instance_memory(nvadsp_app_info_t *app, const struct app_mem_size *sz)
                        iova_mem->aram_flag = mem->aram_flag = 1;
                        dev_dbg(dev, "%s aram %x\n", name, iova_mem->aram);
                } else {
-                       dev_info(dev,
-                       "No ARAM memory avialable ! allocating from DRAM for app %s instance\n",
-                       name);
+                       dev_dbg(dev, "app %s no ARAM memory ! using DRAM\n",
+                               name);
                        mem->aram = nvadsp_alloc_coherent(sz->aram,
                                        &da, GFP_KERNEL);
                        if (!mem->aram) {
+                               iova_mem->aram_flag = mem->aram_flag = 0;
                                dev_err(dev,
-                               "cannot allocate aram memory from dram for app %s instance\n",
-                               name);
-                               goto free_dram_shared_wc;
+                                       "app %s aram memory alloc failed\n",
+                                       name);
+                               goto end;
                        }
                        iova_mem->aram = (uint32_t)da;
-                       iova_mem->aram_flag = mem->aram_flag = 0;
-                       dev_dbg(dev, "mem.aram %p 0x%x\n",
-                                       mem->aram, iova_mem->aram);
+                       dev_dbg(dev, "%s :: mem.aram %p 0x%x\n", name,
+                               mem->aram, iova_mem->aram);
                }
        }
 
@@ -551,77 +321,24 @@ create_instance_memory(nvadsp_app_info_t *app, const struct app_mem_size *sz)
                } else {
                        iova_mem->aram_x = 0;
                        iova_mem->aram_x_flag = mem->aram_x_flag = 0;
-                       dev_err(dev,
-                       "unable to allocate exclusive memory for app instance %s\n",
-                       name);
+                       dev_err(dev, "app %s aram x memory alloc failed\n",
+                               name);
                }
        }
        return 0;
 
-free_dram_shared_wc:
-       if (sz->dram_shared_wc)
-               nvadsp_free_coherent(sz->dram_shared_wc, mem->shared_wc,
-                               iova_mem->shared_wc);
-free_dram_shared:
-       if (sz->dram_shared)
-               nvadsp_free_coherent(sz->dram_shared, mem->shared,
-                               iova_mem->shared);
-free_dram:
-       if (sz->dram)
-               nvadsp_free_coherent(sz->dram, mem->dram, iova_mem->dram);
 end:
+       free_instance_memory(app, sz);
        return -ENOMEM;
 }
 
-static void free_instance_memory(nvadsp_app_info_t *app,
-               const struct app_mem_size *sz)
-{
-       adsp_app_mem_t *mem = &app->mem;
-       adsp_app_iova_mem_t *iova_mem = &app->iova_mem;
-
-       if (sz->dram)
-               nvadsp_free_coherent(sz->dram, mem->dram, iova_mem->dram);
-
-       if (sz->dram_shared)
-               nvadsp_free_coherent(sz->dram_shared, mem->shared,
-                               iova_mem->shared);
-       if (sz->dram_shared_wc)
-               nvadsp_free_coherent(sz->dram_shared_wc, mem->shared_wc,
-                               iova_mem->shared_wc);
-       if (sz->aram) {
-               if (mem->aram_flag)
-                       aram_release(mem->aram);
-               else
-                       nvadsp_free_coherent(sz->aram,
-                                       mem->aram, iova_mem->aram);
-       }
-
-       if (sz->aram_x && mem->aram_x_flag)
-               aram_release(mem->aram_x);
-
-}
-
-static inline void native_adsp_init_stats(struct app_init_stats *stats,
-       struct app_init_data *data)
+static void fill_app_instance_data(nvadsp_app_info_t *app,
+       struct nvadsp_app_service *ser, nvadsp_app_args_t *app_args,
+       struct run_app_instance_data *data, uint32_t stack_sz)
 {
-       EQUATE_STAT(stats->ns_time_adsp_app_init, data->app_init_time);
-       EQUATE_STAT(stats->ns_time_adsp_mem_instance_map,
-               data->app_mem_instance_map);
-       EQUATE_STAT(stats->ns_time_adsp_init_call, data->app_init_call);
-       EQUATE_STAT(stats->ns_time_adsp_send_status,
-               data->adsp_send_status_time);
-       EQUATE_STAT(stats->adsp_receive_timestamp, data->timestamp);
-}
-
-static uint32_t
-native_adsp_app_init(nvadsp_app_info_t *app,
-       const struct nvadsp_app_service *ser, nvadsp_app_args_t *app_args,
-       struct app_init_stats *stats)
-{
-       uint32_t token = 0;
-       struct app_init_data *data = &shared->app_init;
        adsp_app_iova_mem_t *iova_mem = &app->iova_mem;
 
+       data->adsp_mod_ptr = ser->mod->adsp_module_ptr;
        /* copy the iova address to adsp so that adsp can access the memory */
        data->dram_data_ptr = iova_mem->dram;
        data->dram_shared_ptr = iova_mem->shared;
@@ -633,10 +350,6 @@ native_adsp_app_init(nvadsp_app_info_t *app,
 
        if (app_args)
                memcpy(&data->app_args, app_args, sizeof(nvadsp_app_args_t));
-       /*
-        * app on adsp needs to know the service from which it should instance
-        */
-       data->ser = ser->token;
        /*
         * app on adsp holds the reference of host app instance to communicate
         * back when completed. This way we do not need to iterate through the
@@ -644,144 +357,202 @@ native_adsp_app_init(nvadsp_app_info_t *app,
         */
        data->host_ref = (uint64_t)app;
 
-       /* call the adsp app init function on ADSP */
-       nvadsp_mbox_send(&mbox, APP_INIT, NVADSP_MBOX_SMSG, true, 100);
-       /* store the app instance structure if successful */
-       token = (wait_for_app_frame_timeout(&app_init_status) <= 0)
-                       ? token : data->app_token;
-       native_adsp_init_stats(stats, data);
-       /* clear shared app init data structure */
-       memset(data, 0, sizeof(struct app_init_data));
-       return token;
+       /* copy instance mem_size */
+       memcpy(&data->mem_size, ser->mem_size, sizeof(struct app_mem_size));
 }
 
-nvadsp_app_info_t *nvadsp_app_init(nvadsp_app_handle_t handle,
-                                       nvadsp_app_args_t *app_args)
+static nvadsp_app_info_t *create_app_instance(nvadsp_app_handle_t handle,
+       nvadsp_app_args_t *app_args, struct run_app_instance_data *data,
+       app_complete_status_notifier notifier, uint32_t stack_size)
 {
        struct nvadsp_app_service *ser = (void *)handle;
-       struct app_init_stats stats = { };
-       struct nvadsp_drv_data *drv_data;
+       struct device *dev = &priv.pdev->dev;
        nvadsp_app_info_t *app;
-       unsigned long flags;
-       struct device *dev;
-       uint32_t *token;
        int *state;
        int *id;
 
-       if (!priv.pdev) {
-               pr_err("ADSP Driver is not initialized\n");
-               goto err_value;
-       }
-
-       drv_data = platform_get_drvdata(priv.pdev);
-       dev = &priv.pdev->dev;
-
-       if (!drv_data->adsp_os_running)
-               goto err_value;
-
-       if (IS_ERR_OR_NULL(handle))
-               goto err_value;
-
-       RECORD_STAT(stats.ns_time_app_init);
-       EQUATE_STAT(stats.ns_time_app_alloc, stats.ns_time_app_init);
-       app = kzalloc(sizeof(nvadsp_app_info_t), GFP_KERNEL);
+       app = kzalloc(sizeof(*app), GFP_KERNEL);
        if (unlikely(!app)) {
                dev_err(dev, "cannot allocate memory for app %s instance\n",
                                ser->name);
                goto err_value;
        }
-       RECORD_STAT(stats.ns_time_app_alloc);
-
        /* set the instance name with the app name */
        app->name = ser->name;
        /* associate a unique id */
        id = (int *)&app->instance_id;
        *id = ser->generated_instance_id++;
+       /*
+        * hold the pointer to the service, to dereference later during deinit
+        */
+       app->handle = ser;
 
        /* create the instance memory required by the app instance */
-       RECORD_STAT(stats.ns_time_instance_memory);
        if (create_instance_memory(app, ser->mem_size)) {
                dev_err(dev, "instance creation failed for app %s:%d\n",
                                app->name, app->instance_id);
                goto free_app;
        }
-       RECORD_STAT(stats.ns_time_instance_memory);
-
-       /* token holds the app instance pointer created on adsp */
-       token = (void *)&app->token;
-       RECORD_STAT(stats.ns_time_native_call);
-       mutex_lock(&app_init_mutex);
-       *token = native_adsp_app_init(app, ser, app_args, &stats);
-       mutex_unlock(&app_init_mutex);
-       RECORD_STAT(stats.ns_time_native_call);
-
-       if (!app->token) {
-               dev_err(dev, "app failed to initilize %s\n", app->name);
-               goto free_instance_memory;
-       }
 
-       /*
-        * hold the pointer to the service, to dereference later during deinit
-        */
-       app->handle = ser;
-
-       /*
-        * Initilize the complete work which returns the return value after
-        * execution
-        */
-       INIT_WORK(&app->complete_work, app_complete_notifier);
+       /* assign the stack that is needed by the app */
+       data->stack_size  = stack_size;
 
        /* set the state to INITIALIZED. No need to do it in a spin lock */
        state = (int *)&app->state;
        *state = NVADSP_APP_STATE_INITIALIZED;
 
        /* increment instance count and add the app instance to service list */
-       spin_lock_irqsave(&ser->lock, flags);
+       mutex_lock(&ser->lock);
        list_add_tail(&app->node, &ser->app_head);
        ser->instance++;
-       spin_unlock_irqrestore(&ser->lock, flags);
+       mutex_unlock(&ser->lock);
+
+       fill_app_instance_data(app, ser, app_args, data, stack_size);
+
+       init_completion(&app->wait_for_app_start);
+       init_completion(&app->wait_for_app_complete);
+       set_app_complete_notifier(app, notifier);
 
        dev_dbg(dev, "app %s instance %d initilized\n",
                        app->name, app->instance_id);
        dev_dbg(dev, "app %s has %d instances\n", ser->name, ser->instance);
+       goto end;
 
-       RECORD_STAT(stats.ns_time_app_init);
-       print_init_stats(ser->file, &stats, dev);
-       return app;
-
-free_instance_memory:
-       free_instance_memory(app, ser->mem_size);
 free_app:
        kfree(app);
 err_value:
        app = ERR_PTR(-ENOMEM);
+end:
        return app;
 }
+
+nvadsp_app_info_t __must_check *nvadsp_app_init(nvadsp_app_handle_t handle,
+       nvadsp_app_args_t *args)
+{
+       struct adsp_app_shared_msg_pool *msg_pool;
+       union app_loader_message *message;
+       struct nvadsp_drv_data *drv_data;
+       struct app_loader_data *data;
+       nvadsp_app_info_t *app;
+       msgq_t *msgq_send;
+       int *state;
+
+       if (IS_ERR_OR_NULL(priv.pdev)) {
+               pr_err("ADSP Driver is not initialized\n");
+               goto err;
+       }
+
+       drv_data = platform_get_drvdata(priv.pdev);
+
+       if (!drv_data->adsp_os_running)
+               goto err;
+
+       message = kzalloc(sizeof(*message), GFP_KERNEL);
+       if (!message)
+               goto err;
+
+       msg_pool = drv_data->shared_adsp_os_data;
+       msgq_send = &msg_pool->app_loader_send_message.msgq;
+       data = &message->data;
+
+       app = create_app_instance(handle, args, &data->app_init, NULL, 0);
+       if (IS_ERR_OR_NULL(app)) {
+               kfree(message);
+               goto err;
+       }
+       app->priv = data;
+       data->app_init.message = ADSP_APP_INIT;
+
+       message->msgq_msg.size = MSGQ_MSG_PAYLOAD_WSIZE(*message);
+       msgq_queue_message(msgq_send, &message->msgq_msg);
+
+       if (app->return_status) {
+               state = (int *)&app->state;
+               *state = NVADSP_APP_STATE_STARTED;
+       }
+
+       nvadsp_mbox_send(&priv.mbox, 0, NVADSP_MBOX_SMSG, false, 0);
+
+       wait_for_completion(&app->wait_for_app_start);
+       init_completion(&app->wait_for_app_start);
+       return app;
+err:
+       return ERR_PTR(-ENOMEM);
+}
 EXPORT_SYMBOL(nvadsp_app_init);
 
-static int native_adsp_app_deinit(nvadsp_app_info_t *app)
+static void start_app_on_adsp(nvadsp_app_info_t *app,
+       union app_loader_message *message, bool block)
 {
-       struct app_deinit_data *data = &shared->app_deinit;
-       int32_t status = -EINVAL;
-
-       data->ptr = app->token;
-       nvadsp_mbox_send(&mbox, APP_DEINIT, NVADSP_MBOX_SMSG, true, 100);
-       status = (wait_for_app_frame_timeout(&app_deinit_status) <= 0)
-                       ? status : data->status;
-       memset(data, 0, sizeof(struct app_deinit_data));
-       return status;
+       struct adsp_app_shared_msg_pool *msg_pool;
+       struct nvadsp_drv_data *drv_data;
+       msgq_t *msgq_send;
+       int *state;
+
+       drv_data = platform_get_drvdata(priv.pdev);
+       msg_pool = drv_data->shared_adsp_os_data;
+       msgq_send = &msg_pool->app_loader_send_message.msgq;
+
+       message->msgq_msg.size = MSGQ_MSG_PAYLOAD_WSIZE(*message);
+       msgq_queue_message(msgq_send, &message->msgq_msg);
+
+       state = (int *)&app->state;
+       *state = NVADSP_APP_STATE_STARTED;
+
+       nvadsp_mbox_send(&priv.mbox, 0, NVADSP_MBOX_SMSG, false, 0);
+
+       if (block) {
+               wait_for_completion(&app->wait_for_app_start);
+               if (app->return_status) {
+                       pr_info("app instance failed to start\n");
+                       state = (int *)&app->state;
+                       *state = NVADSP_APP_STATE_INITIALIZED;
+               }
+       }
 }
 
-int nvadsp_app_deinit(nvadsp_app_info_t *app)
+int nvadsp_app_start(nvadsp_app_info_t *app)
 {
+       union app_loader_message *message = app->priv;
+       struct app_loader_data *data = &message->data;
        struct nvadsp_drv_data *drv_data;
-       unsigned long flags;
+
+       if (IS_ERR_OR_NULL(app))
+               return -EINVAL;
+
+       if (IS_ERR_OR_NULL(priv.pdev)) {
+               pr_err("ADSP Driver is not initialized\n");
+               goto err;
+       }
+
+       drv_data = platform_get_drvdata(priv.pdev);
+
+       if (!drv_data->adsp_os_running)
+               goto err;
+
+       data->app_init.message = ADSP_APP_START;
+       data->app_init.adsp_ref = app->token;
+       data->app_init.stack_size = app->stack_size;
+       start_app_on_adsp(app, app->priv, true);
+err:
+       return (app->state == NVADSP_APP_STATE_STARTED) ? 0 : -EINVAL;
+}
+EXPORT_SYMBOL(nvadsp_app_start);
+
+nvadsp_app_info_t *nvadsp_run_app(nvadsp_os_handle_t os_handle,
+       const char *appfile, nvadsp_app_args_t *app_args,
+       app_complete_status_notifier notifier, uint32_t stack_sz, bool block)
+{
+       union app_loader_message message = {};
+       nvadsp_app_handle_t service_handle;
+       struct nvadsp_drv_data *drv_data;
+       nvadsp_app_info_t *info =  NULL;
+       struct app_loader_data *data;
        struct device *dev;
-       int ret = -EINVAL;
-       int *state;
 
-       if (!priv.pdev) {
+       if (IS_ERR_OR_NULL(priv.pdev)) {
                pr_err("ADSP Driver is not initialized\n");
+               info = ERR_PTR(-EINVAL);
                goto end;
        }
 
@@ -791,76 +562,89 @@ int nvadsp_app_deinit(nvadsp_app_info_t *app)
        if (!drv_data->adsp_os_running)
                goto end;
 
-       if (IS_ERR_OR_NULL(app))
+       if (IS_ERR_OR_NULL(appfile))
                goto end;
 
-       state = (int *)&app->state;
-       /* check and update state of app atomically */
-       spin_lock_irqsave(&state_lock, flags);
-       if (*state == NVADSP_APP_STATE_INITIALIZED) {
-               *state = NVADSP_APP_STATE_UNKNOWN;
-               spin_unlock_irqrestore(&state_lock, flags);
-
-               /* free the adsp instance from app side */
-               mutex_lock(&app_deinit_mutex);
-               ret = native_adsp_app_deinit(app);
-               mutex_unlock(&app_deinit_mutex);
-
-               if (likely(!ret)) {
-                       struct nvadsp_app_service *ser =
-                               (struct nvadsp_app_service *)app->handle;
-                       dev_dbg(dev, "%s:freeing app %s:%d\n",
-                                       __func__, app->name, app->instance_id);
-
-                       /* update the service app instance manager atomically */
-                       spin_lock_irqsave(&ser->lock, flags);
-                       ser->instance--;
-                       list_del(&app->node);
-                       dev_dbg(dev, "%s: the app %s has instance %d\n",
-                                       __func__, ser->name, ser->instance);
-                       spin_unlock_irqrestore(&ser->lock, flags);
-
-                       /* free instance memory */
-                       free_instance_memory(app, ser->mem_size);
-                       kfree(app);
-               } else {
-                       /*
-                        * this should not happen, This means there is something
-                        * wrong.
-                        */
-                       WARN(1, "invalid states maintained on ADSP and HOST for app %s:%d",
-                                       app->name, app->instance_id);
-                       spin_lock_irqsave(&state_lock, flags);
-                       *state = NVADSP_APP_STATE_INITIALIZED;
-                       spin_unlock_irqrestore(&state_lock, flags);
-               }
-       } else {
-               spin_unlock_irqrestore(&state_lock, flags);
+       data = &message.data;
+       service_handle = app_load(appfile);
+       if (!service_handle) {
+               dev_err(dev, "unable to load the app %s\n", appfile);
+               goto end;
+       }
+
+       info = create_app_instance(service_handle, app_args,
+               &data->app_init, notifier, stack_sz);
+       if (IS_ERR_OR_NULL(info)) {
+               dev_err(dev, "unable to create instance for app %s\n", appfile);
+               goto end;
        }
+       data->app_init.message = RUN_ADSP_APP;
+
+       start_app_on_adsp(info, &message, block);
 end:
-       return ret;
+       return info;
+}
+EXPORT_SYMBOL(nvadsp_run_app);
+
+static void delete_app_instance(nvadsp_app_info_t *app)
+{
+       struct nvadsp_app_service *ser =
+               (struct nvadsp_app_service *)app->handle;
+       struct device *dev = &priv.pdev->dev;
+
+       dev_dbg(dev, "%s:freeing app %s:%d\n",
+               __func__, app->name, app->instance_id);
+
+       /* update the service app instance manager atomically */
+       mutex_lock(&ser->lock);
+       ser->instance--;
+       list_del(&app->node);
+       mutex_unlock(&ser->lock);
+
+       /* free instance memory */
+       free_instance_memory(app, ser->mem_size);
+       kfree(app->priv);
+       kfree(app);
+}
+
+void nvadsp_exit_app(nvadsp_app_info_t *app, bool terminate)
+{
+       int *state;
+
+       if (IS_ERR_OR_NULL(priv.pdev)) {
+               pr_err("ADSP Driver is not initialized\n");
+               return;
+       }
+
+       if (IS_ERR_OR_NULL(app))
+               return;
+
+       /* TODO: add termination if possible to kill thread on adsp */
+       wait_for_completion(&app->wait_for_app_complete);
+       state = (int *)&app->state;
+       *state = NVADSP_APP_STATE_INITIALIZED;
+       delete_app_instance(app);
+}
+EXPORT_SYMBOL(nvadsp_exit_app);
+
+int nvadsp_app_deinit(nvadsp_app_info_t *app)
+{
+       nvadsp_exit_app(app, false);
+       return 0;
 }
 EXPORT_SYMBOL(nvadsp_app_deinit);
 
-static int native_adsp_app_unload(struct nvadsp_app_service *ser)
+int nvadsp_app_stop(nvadsp_app_info_t *app)
 {
-       struct app_unload_data *data = &shared->app_unload;
-       int32_t status = -EINVAL;
-
-       data->ser = ser->token;
-       nvadsp_mbox_send(&mbox, APP_UNLOAD, NVADSP_MBOX_SMSG, true, 100);
-       status = (wait_for_app_frame_timeout(&app_unload_status) <= 0)
-                       ? status : data->status;
-       memset(data, 0, sizeof(struct app_deinit_data));
-       return status;
+       return -ENOENT;
 }
+EXPORT_SYMBOL(nvadsp_app_stop);
 
 void nvadsp_app_unload(nvadsp_app_handle_t handle)
 {
        struct nvadsp_drv_data *drv_data;
        struct nvadsp_app_service *ser;
        struct device *dev;
-       int ret;
 
        if (!priv.pdev) {
                pr_err("ADSP Driver is not initialized\n");
@@ -876,6 +660,7 @@ void nvadsp_app_unload(nvadsp_app_handle_t handle)
        if (IS_ERR_OR_NULL(handle))
                return;
 
+       mutex_lock(&priv.service_lock_list);
        ser = (struct nvadsp_app_service *)handle;
        if (ser->instance) {
                dev_err(dev, "cannot unload app %s, has instances %d\n",
@@ -883,110 +668,101 @@ void nvadsp_app_unload(nvadsp_app_handle_t handle)
                return;
        }
 
-       mutex_lock(&service_lock_list);
        list_del(&ser->node);
-       mutex_unlock(&service_lock_list);
-
-       mutex_lock(&app_unload_mutex);
-       ret = native_adsp_app_unload(ser);
-       mutex_unlock(&app_unload_mutex);
-
-       if (ret)
-               WARN(1, "%s:invalid counts maintained %s", __func__, ser->name);
-
        unload_adsp_module(ser->mod);
-       kfree(ser);
+       devm_kfree(dev, ser);
+       mutex_unlock(&priv.service_lock_list);
 }
 EXPORT_SYMBOL(nvadsp_app_unload);
 
-int nvadsp_app_start(nvadsp_app_info_t *app)
+static status_t nvadsp_app_receive_handler(uint32_t msg, void *hdata)
 {
-       struct app_start_stats stats = { };
+       union app_complete_status_message message = { };
+       struct adsp_app_shared_msg_pool *msg_pool;
+       struct app_complete_status_data *data;
        struct nvadsp_drv_data *drv_data;
-       struct nvadsp_app_service *ser;
-       unsigned long flags;
+       struct platform_device *pdev;
+       nvadsp_app_info_t *app;
        struct device *dev;
-       int ret = -EINVAL;
-       int *state;
+       msgq_t *msgq_recv;
+       uint32_t *token;
 
-       if (!priv.pdev) {
-               pr_err("ADSP Driver is not initialized\n");
-               goto end;
+       pdev = hdata;
+       dev = &pdev->dev;
+       drv_data = platform_get_drvdata(pdev);
+       msg_pool = drv_data->shared_adsp_os_data;
+       msgq_recv = &msg_pool->app_loader_recv_message.msgq;
+       data = &message.data;
+
+       message.msgq_msg.size = MSGQ_MSG_PAYLOAD_WSIZE(*data);
+       if (msgq_dequeue_message(msgq_recv, &message.msgq_msg)) {
+               dev_err(dev, "unable to dequeue app status message\n");
+               return 0;
        }
 
-       drv_data = platform_get_drvdata(priv.pdev);
-       dev = &priv.pdev->dev;
+       if (unlikely(data->message == OS_LOAD_COMPLETE)) {
+               complete(&priv.os_load_complete);
+               return 0;
+       }
 
-       if (!drv_data->adsp_os_running)
-               goto end;
+       app = (nvadsp_app_info_t *)data->host_ref;
+       app->return_status = data->status;
+       app->status_msg = data->message;
+       token = (uint32_t *)&app->token;
+       *token = data->adsp_ref;
 
-       if (IS_ERR_OR_NULL(app))
-               goto end;
+       if (app->complete_status_notifier) {
+               app->complete_status_notifier(app,
+                       app->status_msg, app->return_status);
+       }
 
-       ser = (void *)app->handle;
-       state = (int *)&app->state;
+       switch (data->message) {
+       case ADSP_APP_START_STATUS:
+               complete_all(&app->wait_for_app_start);
+               break;
+       case ADSP_APP_COMPLETE_STATUS:
+               complete_all(&app->wait_for_app_complete);
+               break;
+       }
 
-       /*
-        * possiblity is that after deinit start is called ! need to check app
-        * pointer
-        */
-       spin_lock_irqsave(&state_lock, flags);
-       if (IS_ERR_OR_NULL(app)) {
-               dev_err(dev, "unable to start app instance %s:%d\n",
-                               app->name, app->instance_id);
-               spin_unlock_irqrestore(&state_lock, flags);
-       } else if (*state == NVADSP_APP_STATE_INITIALIZED) {
-               *state = NVADSP_APP_STATE_STARTED;
-               spin_unlock_irqrestore(&state_lock, flags);
+       return 0;
+}
 
-               /* initilize the complete structure */
-               init_completion(&app->wait_for_app_complete);
+int wait_for_adsp_os_load_complete(void)
+{
+       struct device *dev = &priv.pdev->dev;
+       unsigned long timeout;
+       int ret;
 
-               /* start the app from adsp side by creating a thread */
-               RECORD_STAT(stats.ns_time_native_call);
-               mutex_lock(&app_start_mutex);
-               ret = native_adsp_app_start(app, &stats);
-               mutex_unlock(&app_start_mutex);
-               RECORD_STAT(stats.ns_time_native_call);
+       timeout = msecs_to_jiffies(ADSP_OS_LOAD_TIMEOUT);
+       ret = wait_for_completion_timeout(&priv.os_load_complete, timeout);
+       if (!ret) {
+               dev_err(dev, "ADSP OS loading timed out\n");
+               ret = -ETIMEDOUT;
+       } else
+               ret = 0;
 
-               if (ret) {
-                       dev_err(dev,
-                               "Unable to start app instance adsp thread %s:%d\n",
-                               app->name, app->instance_id);
-                       spin_lock_irqsave(&state_lock, flags);
-                       *state = NVADSP_APP_STATE_INITIALIZED;
-                       spin_unlock_irqrestore(&state_lock, flags);
-                       goto end;
-               }
-       } else {
-               spin_unlock_irqrestore(&state_lock, flags);
-       }
-       print_start_stats(ser->file, &stats, dev);
-end:
        return ret;
 }
-EXPORT_SYMBOL(nvadsp_app_start);
-
-int nvadsp_app_stop(nvadsp_app_info_t *app)
-{
-       return -ENOENT;
-}
 
 int nvadsp_app_module_probe(struct platform_device *pdev)
 {
        int ret;
        uint16_t mbox_id = APP_LOADER_MBOX_ID;
+       struct device *dev = &pdev->dev;
 
-       dev_info(&pdev->dev, "%s\n", __func__);
+       dev_info(dev, "%s\n", __func__);
 
-       ret = nvadsp_mbox_open(&mbox, &mbox_id, "app_service",
-               nvadsp_app_receive_handler, &priv);
+       ret = nvadsp_mbox_open(&priv.mbox, &mbox_id,
+               "app_service", nvadsp_app_receive_handler, pdev);
        if (ret) {
-               dev_err(&pdev->dev, "unable to open mailbox\n");
+               dev_err(dev, "unable to open mailbox\n");
                goto end;
        }
        priv.pdev = pdev;
-       INIT_LIST_HEAD(&service_list);
+       INIT_LIST_HEAD(&priv.service_list);
+       init_completion(&priv.os_load_complete);
+       mutex_init(&priv.service_lock_list);
 end:
        return ret;
 }
index 2a3305752d48e9fe2fc284d78574644f6cc3fa5a..c86f3f262a285a50e1150c6db2c8c0614fb9c8a2 100644 (file)
@@ -476,15 +476,10 @@ static int __init nvadsp_probe(struct platform_device *pdev)
        if (ret)
                goto err;
 #endif
-
        ret = nvadsp_app_module_probe(pdev);
        if (ret)
                goto err;
 
-       ret = nvadsp_run_app_module_probe(pdev);
-       if (ret)
-               goto err;
-
        ret = aram_init();
        if (ret)
                dev_err(dev, "Failed to init aram\n");
index 5dbc36bf2cee98dca9af47941e7b57baf53d702b..1ffc42d8d2af04a6ec5ec383cab8c57807169eee 100644 (file)
@@ -645,7 +645,6 @@ int nvadsp_os_load(void)
                goto deallocate_os_memory;
        }
        ptr = get_mailbox_shared_region(fw);
-       update_nvadsp_app_shared_ptr(ptr);
        drv_data->shared_adsp_os_data = ptr;
        priv.os_firmware = fw;
        priv.adsp_os_fw_loaded = true;
index 44aab3eb2a75014052deb8cc24e8055c4e9e8729..fe229e39b2f296e696948c02c27b2df2a7388f99 100644 (file)
@@ -3,7 +3,7 @@
  *
  * A header file containing data structures shared with ADSP OS
  *
- * Copyright (C) 2014 NVIDIA Corporation. All rights reserved.
+ * Copyright (C) 2014-2015 NVIDIA Corporation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -66,102 +66,6 @@ struct app_mem_size {
        uint64_t aram_x;
 };
 
-struct app_load_data {
-       struct app_mem_size mem_size;
-#if CONFIG_USE_STATIC_APP_LOAD
-       int8_t service_name[NVADSP_NAME_SZ];
-#else
-       uint32_t adsp_mod_ptr;
-       uint64_t adsp_mod_size;
-#endif
-       uint32_t ser;
-#if RECORD_STATS
-       uint64_t map_time;
-       uint64_t app_load_time;
-       uint64_t adsp_send_status_time;
-       uint64_t timestamp;
-       uint64_t receive_timestamp;
-#endif
-} __packed;
-
-struct app_init_data {
-       uint32_t ser;
-       uint64_t host_ref;
-       uint32_t app_token; /* holds the address of the app structure */
-       uint32_t dram_data_ptr;
-       uint32_t dram_shared_ptr;
-       uint32_t dram_shared_wc_ptr;
-       uint32_t aram_ptr;
-       uint32_t aram_flag;
-       uint32_t aram_x_ptr;
-       uint32_t aram_x_flag;
-       nvadsp_app_args_t app_args;
-#if RECORD_STATS
-       uint64_t app_init_time;
-       uint64_t app_mem_instance_map;
-       uint64_t app_init_call;
-       uint64_t adsp_send_status_time;
-       uint64_t timestamp;
-       uint64_t receive_timestamp;
-#endif
-} __packed;
-
-
-struct app_deinit_data {
-       uint32_t ptr;
-       uint32_t status;
-} __packed;
-
-struct app_start_data {
-       uint32_t ptr;
-       uint32_t stack_size;
-       uint32_t status;
-#if RECORD_STATS
-       uint64_t app_start_time;
-       uint64_t app_thread_creation_time;
-       uint64_t app_thread_detach_time;
-       uint64_t app_thread_resume_time;
-       uint64_t insert_queue_head_time;
-       uint64_t thread_yield_time;
-       uint64_t thread_resched_time;
-       uint64_t kevlog_thread_switch_time;
-       uint64_t thread_context_switch_time;
-       uint64_t adsp_send_status_time;
-       uint64_t timestamp;
-       uint64_t receive_timestamp;
-#endif
-} __packed;
-
-struct app_complete_data {
-       uint64_t host_ref;
-       int32_t app_status;
-       int32_t copy_complete;
-} __packed;
-
-struct app_unload_data {
-       uint32_t        ser;
-       int32_t         status;
-} __packed;
-
-union app_loader_msgq {
-       msgq_t msgq;
-       struct {
-               int32_t header[MSGQ_HEADER_WSIZE];
-               int32_t queue[MSGQ_MAX_QUEUE_WSIZE];
-       };
-};
-
-struct shared_mem_struct {
-       struct app_load_data            app_load;
-       struct app_init_data            app_init;
-       struct app_start_data           app_start;
-       struct app_deinit_data          app_deinit;
-       struct app_complete_data        app_complete;
-       struct app_unload_data          app_unload;
-       union app_loader_msgq           app_loader_send_message;
-       union app_loader_msgq           app_loader_recv_message;
-} __packed;
-
 enum adsp_os_cmd {
        ADSP_OS_SUSPEND,
 };
@@ -243,7 +147,6 @@ struct app_start_stats {
 
 int nvadsp_os_probe(struct platform_device *);
 int nvadsp_app_module_probe(struct platform_device *);
-int nvadsp_run_app_module_probe(struct platform_device *);
 int adsp_add_load_mappings(phys_addr_t, void *, int);
 struct elf32_shdr *nvadsp_get_section(const struct firmware *, char *);
 struct global_sym_info *find_global_symbol(const char *);
diff --git a/drivers/platform/tegra/nvadsp/run_app.c b/drivers/platform/tegra/nvadsp/run_app.c
deleted file mode 100644 (file)
index 9f328ff..0000000
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- * run_app.c
- *
- * ADSP OS App management
- *
- * Copyright (C) 2014 NVIDIA Corporation. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/platform_device.h>
-#include <linux/tegra_nvadsp.h>
-#include <linux/dma-mapping.h>
-#include <linux/completion.h>
-#include <linux/workqueue.h>
-#include <linux/firmware.h>
-#include <linux/dma-buf.h>
-#include <linux/slab.h>
-#include <linux/elf.h>
-
-#include "aram_manager.h"
-#include "os.h"
-#include "dev.h"
-
-#define APP_LOADER_MBOX_ID             10
-
-#define APP_START                      0x07
-
-struct nvadsp_app_service {
-       char name[NVADSP_NAME_SZ];
-       struct list_head node;
-       int instance;
-       spinlock_t lock;
-       struct list_head app_head;
-       const uint32_t token;
-       const struct app_mem_size *mem_size;
-       int generated_instance_id;
-       struct adsp_module *mod;
-};
-
-static struct nvadsp_drv_data *drv_data;
-static struct device *dev;
-
-struct nvadsp_app_priv_struct {
-       struct platform_device *pdev;
-};
-
-struct run_app_instance_data {
-       uint32_t adsp_mod_ptr;
-       uint64_t host_ref;
-       uint32_t dram_data_ptr;
-       uint32_t dram_shared_ptr;
-       uint32_t dram_shared_wc_ptr;
-       uint32_t aram_ptr;
-       uint32_t aram_flag;
-       uint32_t aram_x_ptr;
-       uint32_t aram_x_flag;
-       struct app_mem_size mem_size;
-       nvadsp_app_args_t app_args;
-       uint32_t stack_size;
-} __packed;
-
-struct app_loader_data {
-       int32_t header[MSGQ_MESSAGE_HEADER_WSIZE];
-       struct run_app_instance_data    app_init;
-} __packed;
-
-#pragma pack(4)
-union app_loader_message {
-       msgq_message_t msgq_msg;
-       struct app_loader_data data;
-};
-
-struct app_complete_status_data {
-       int32_t header[MSGQ_MESSAGE_HEADER_WSIZE];
-       uint64_t host_ref;
-       int32_t status;
-} __packed;
-
-#pragma pack(4)
-union app_complete_status_message {
-       msgq_message_t msgq_msg;
-       struct app_complete_status_data data;
-};
-
-static struct nvadsp_app_priv_struct priv;
-static struct nvadsp_mbox mbox;
-static struct list_head service_list;
-
-static DEFINE_MUTEX(service_lock_list);
-
-static struct nvadsp_app_service *get_loaded_service(const char *appfile)
-{
-       struct device *dev = &priv.pdev->dev;
-       struct nvadsp_app_service *ser;
-
-       list_for_each_entry(ser, &service_list, node) {
-               if (!strcmp(appfile, ser->name)) {
-                       dev_dbg(dev, "module %s already loaded\n", appfile);
-                       return ser;
-               }
-       }
-       dev_dbg(dev, "module %s will be loaded\n", appfile);
-       return NULL;
-}
-
-static nvadsp_app_handle_t app_load(const char *appfile)
-{
-       struct device *dev = &priv.pdev->dev;
-       struct nvadsp_app_service *ser;
-       struct app_load_stats stats;
-
-       mutex_lock(&service_lock_list);
-       ser = get_loaded_service(appfile);
-       if (!ser) {
-               dev_dbg(dev, "loading app %s\n", appfile);
-
-               ser = devm_kzalloc(dev, sizeof(*ser), GFP_KERNEL);
-               if (!ser)
-                       goto err;
-               strncpy(ser->name, appfile, NVADSP_NAME_SZ);
-
-               /*load the module in to memory */
-               ser->mod = load_adsp_module(appfile, appfile, dev, &stats);
-               if (IS_ERR_OR_NULL(ser->mod))
-                       goto err_free_service;
-               ser->mem_size = &ser->mod->mem_size;
-
-               spin_lock_init(&ser->lock);
-               INIT_LIST_HEAD(&ser->app_head);
-
-               /* add the app instance service to the list */
-               list_add_tail(&ser->node, &service_list);
-               dev_dbg(dev, "loaded app %s\n", ser->name);
-       }
-       mutex_unlock(&service_lock_list);
-
-       return ser;
-
-err_free_service:
-       devm_kfree(dev, ser);
-err:
-       mutex_unlock(&service_lock_list);
-       return NULL;
-}
-
-static void free_instance_memory(nvadsp_app_info_t *app,
-               const struct app_mem_size *sz)
-{
-       adsp_app_mem_t *mem = &app->mem;
-       adsp_app_iova_mem_t *iova_mem = &app->iova_mem;
-
-       if (mem->dram) {
-               nvadsp_free_coherent(sz->dram, mem->dram, iova_mem->dram);
-               mem->dram = NULL;
-               iova_mem->dram = 0;
-       }
-
-       if (mem->shared) {
-               nvadsp_free_coherent(sz->dram_shared, mem->shared,
-                               iova_mem->shared);
-               mem->shared = NULL;
-               iova_mem->shared = 0;
-       }
-
-       if (mem->shared_wc) {
-               nvadsp_free_coherent(sz->dram_shared_wc, mem->shared_wc,
-                               iova_mem->shared_wc);
-               mem->shared_wc = NULL;
-               iova_mem->shared_wc = 0;
-       }
-
-       if (mem->aram_flag)
-               aram_release(mem->aram);
-       else if (mem->aram)
-               nvadsp_free_coherent(sz->aram, mem->aram, iova_mem->aram);
-       mem->aram = NULL;
-       iova_mem->aram = 0;
-       mem->aram_flag = 0;
-
-       if (mem->aram_x_flag) {
-               aram_release(mem->aram_x);
-               mem->aram_x = NULL;
-               iova_mem->aram_x = 0;
-               mem->aram_flag = 0;
-       }
-
-}
-
-static int create_instance_memory(nvadsp_app_info_t *app,
-               const struct app_mem_size *sz)
-{
-       adsp_app_iova_mem_t *iova_mem = &app->iova_mem;
-       struct device *dev = &priv.pdev->dev;
-       adsp_app_mem_t *mem = &app->mem;
-       char name[NVADSP_NAME_SZ];
-       void *aram_handle;
-       dma_addr_t da;
-
-       snprintf(name, NVADSP_NAME_SZ, "%s:%d", app->name, app->instance_id);
-
-       if (sz->dram) {
-               mem->dram = nvadsp_alloc_coherent(sz->dram, &da, GFP_KERNEL);
-               iova_mem->dram = (uint32_t)da;
-               if (!mem->dram) {
-                       dev_err(dev, "app %s dram alloc failed\n",
-                               name);
-                       goto end;
-               }
-               dev_dbg(dev, "%s :: mem.dram %p 0x%x\n", name,
-                       mem->dram, iova_mem->dram);
-       }
-
-       if (sz->dram_shared) {
-               mem->shared = nvadsp_alloc_coherent(sz->dram_shared,
-                               &da, GFP_KERNEL);
-               if (!mem->shared) {
-                       dev_err(dev, "app %s shared dram alloc failed\n",
-                               name);
-                       goto end;
-               }
-               iova_mem->shared = (uint32_t)da;
-               dev_dbg(dev, "%s :: mem.shared %p 0x%x\n", name,
-                       mem->shared, iova_mem->shared);
-       }
-
-       if (sz->dram_shared_wc) {
-               mem->shared_wc = nvadsp_alloc_coherent(sz->dram_shared_wc,
-                                       &da, GFP_KERNEL);
-               if (!mem->shared_wc) {
-                       dev_err(dev, "app %s shared dram wc alloc failed\n",
-                               name);
-                       goto end;
-               }
-               iova_mem->shared_wc = (uint32_t)da;
-               dev_dbg(dev, "%s :: mem.shared_wc %p 0x%x\n", name,
-                       mem->shared_wc, iova_mem->shared_wc);
-       }
-
-       if (sz->aram) {
-               aram_handle = aram_request(name, sz->aram);
-               if (!IS_ERR_OR_NULL(aram_handle)) {
-                       iova_mem->aram = aram_get_address(aram_handle);
-                       mem->aram = aram_handle;
-                       iova_mem->aram_flag = mem->aram_flag = 1;
-                       dev_dbg(dev, "%s aram %x\n", name, iova_mem->aram);
-               } else {
-                       dev_dbg(dev, "app %s no ARAM memory ! using DRAM\n",
-                               name);
-                       mem->aram = nvadsp_alloc_coherent(sz->aram,
-                                       &da, GFP_KERNEL);
-                       if (!mem->aram) {
-                               iova_mem->aram_flag = mem->aram_flag = 0;
-                               dev_err(dev,
-                                       "app %s aram memory alloc failed\n",
-                                       name);
-                               goto end;
-                       }
-                       iova_mem->aram = (uint32_t)da;
-                       dev_dbg(dev, "%s :: mem.aram %p 0x%x\n", name,
-                               mem->aram, iova_mem->aram);
-               }
-       }
-
-       if (sz->aram_x) {
-               aram_handle = aram_request(name, sz->aram);
-               if (!IS_ERR_OR_NULL(aram_handle)) {
-                       iova_mem->aram_x = aram_get_address(aram_handle);
-                       mem->aram_x = aram_handle;
-                       iova_mem->aram_x_flag = mem->aram_x_flag = 1;
-                       dev_dbg(dev, "aram_x %x\n", iova_mem->aram_x);
-               } else {
-                       iova_mem->aram_x = 0;
-                       iova_mem->aram_x_flag = mem->aram_x_flag = 0;
-                       dev_err(dev, "app %s aram x memory alloc failed\n",
-                               name);
-               }
-       }
-       return 0;
-
-end:
-       free_instance_memory(app, sz);
-       return -ENOMEM;
-}
-
-static void fill_app_instance_data(nvadsp_app_info_t *app,
-       struct nvadsp_app_service *ser, nvadsp_app_args_t *app_args,
-       struct run_app_instance_data *data, uint32_t stack_sz)
-{
-       adsp_app_iova_mem_t *iova_mem = &app->iova_mem;
-
-       data->adsp_mod_ptr = ser->mod->adsp_module_ptr;
-       /* copy the iova address to adsp so that adsp can access the memory */
-       data->dram_data_ptr = iova_mem->dram;
-       data->dram_shared_ptr = iova_mem->shared;
-       data->dram_shared_wc_ptr = iova_mem->shared_wc;
-       data->aram_ptr = iova_mem->aram;
-       data->aram_flag = iova_mem->aram_flag;
-       data->aram_x_ptr = iova_mem->aram_x;
-       data->aram_x_flag = iova_mem->aram_x_flag;
-
-       if (app_args)
-               memcpy(&data->app_args, app_args, sizeof(nvadsp_app_args_t));
-       /*
-        * app on adsp holds the reference of host app instance to communicate
-        * back when completed. This way we do not need to iterate through the
-        * list to find the instance.
-        */
-       data->host_ref = (uint64_t)app;
-
-       /* copy instance mem_size */
-       memcpy(&data->mem_size, ser->mem_size, sizeof(struct app_mem_size));
-}
-
-static nvadsp_app_info_t *create_app_instance(nvadsp_app_handle_t handle,
-       nvadsp_app_args_t *app_args, struct run_app_instance_data *data,
-       app_complete_status_notifier notifier, uint32_t stack_size)
-{
-       struct nvadsp_app_service *ser = (void *)handle;
-       struct device *dev = &priv.pdev->dev;
-       nvadsp_app_info_t *app;
-       unsigned long flags;
-       int *state;
-       int *id;
-
-       app = kzalloc(sizeof(*app), GFP_KERNEL);
-       if (unlikely(!app)) {
-               dev_err(dev, "cannot allocate memory for app %s instance\n",
-                               ser->name);
-               goto err_value;
-       }
-       /* set the instance name with the app name */
-       app->name = ser->name;
-       /* associate a unique id */
-       id = (int *)&app->instance_id;
-       *id = ser->generated_instance_id++;
-       /*
-        * hold the pointer to the service, to dereference later during deinit
-        */
-       app->handle = ser;
-
-       /* create the instance memory required by the app instance */
-       if (create_instance_memory(app, ser->mem_size)) {
-               dev_err(dev, "instance creation failed for app %s:%d\n",
-                               app->name, app->instance_id);
-               goto free_app;
-       }
-
-       /* assign the stack that is needed by the app */
-       data->stack_size  = stack_size;
-
-       /* set the state to INITIALIZED. No need to do it in a spin lock */
-       state = (int *)&app->state;
-       *state = NVADSP_APP_STATE_INITIALIZED;
-
-       /* increment instance count and add the app instance to service list */
-       spin_lock_irqsave(&ser->lock, flags);
-       list_add_tail(&app->node, &ser->app_head);
-       ser->instance++;
-       spin_unlock_irqrestore(&ser->lock, flags);
-
-       fill_app_instance_data(app, ser, app_args, data, stack_size);
-
-       init_completion(&app->wait_for_app_start);
-       init_completion(&app->wait_for_app_complete);
-       set_app_complete_notifier(app, notifier);
-
-       dev_dbg(dev, "app %s instance %d initilized\n",
-                       app->name, app->instance_id);
-       dev_dbg(dev, "app %s has %d instances\n", ser->name, ser->instance);
-       goto end;
-
-free_app:
-       kfree(app);
-err_value:
-       app = ERR_PTR(-ENOMEM);
-end:
-       return app;
-}
-
-static void start_app_on_adsp(nvadsp_app_info_t *app,
-       union app_loader_message *message, bool block)
-{
-       struct shared_mem_struct *shared_struct = drv_data->shared_adsp_os_data;
-       msgq_t *msgq_send = &shared_struct->app_loader_send_message.msgq;
-       int *state;
-
-       message->msgq_msg.size = MSGQ_MSG_PAYLOAD_WSIZE(*message);
-       msgq_queue_message(msgq_send, &message->msgq_msg);
-
-       if (app->return_status) {
-               state = (int *)&app->state;
-               *state = NVADSP_APP_STATE_STARTED;
-       }
-
-       nvadsp_mbox_send(&mbox, APP_START, NVADSP_MBOX_SMSG, false, 0);
-
-       if (block) {
-               wait_for_completion(&app->wait_for_app_start);
-               if (app->return_status) {
-                       state = (int *)&app->state;
-                       *state = NVADSP_APP_STATE_INITIALIZED;
-               }
-       }
-}
-
-nvadsp_app_info_t *nvadsp_run_app(nvadsp_os_handle_t os_handle,
-       const char *appfile, nvadsp_app_args_t *app_args,
-       app_complete_status_notifier notifier, uint32_t stack_sz, bool block)
-{
-       union app_loader_message message = {};
-       nvadsp_app_handle_t service_handle;
-       struct nvadsp_drv_data *drv_data;
-       nvadsp_app_info_t *info =  NULL;
-       struct app_loader_data *data;
-       struct device *dev;
-
-       if (IS_ERR_OR_NULL(priv.pdev)) {
-               pr_err("ADSP Driver is not initialized\n");
-               info = ERR_PTR(-EINVAL);
-               goto end;
-       }
-
-       drv_data = platform_get_drvdata(priv.pdev);
-       dev = &priv.pdev->dev;
-
-       if (!drv_data->adsp_os_running)
-               goto end;
-
-       if (IS_ERR_OR_NULL(appfile))
-               goto end;
-
-       data = &message.data;
-       service_handle = app_load(appfile);
-       if (!service_handle) {
-               dev_err(dev, "unable to load the app %s\n", appfile);
-               goto end;
-       }
-
-       info = create_app_instance(service_handle, app_args,
-               &data->app_init, notifier, stack_sz);
-       if (IS_ERR_OR_NULL(info)) {
-               dev_err(dev, "unable to create instance for app %s\n", appfile);
-               goto end;
-       }
-
-       start_app_on_adsp(info, &message, block);
-end:
-       return info;
-}
-EXPORT_SYMBOL(nvadsp_run_app);
-
-static void delete_app_instance(nvadsp_app_info_t *app)
-{
-       struct nvadsp_app_service *ser =
-               (struct nvadsp_app_service *)app->handle;
-       struct device *dev = &priv.pdev->dev;
-       unsigned long flags;
-
-       dev_dbg(dev, "%s:freeing app %s:%d\n",
-               __func__, app->name, app->instance_id);
-
-       /* update the service app instance manager atomically */
-       spin_lock_irqsave(&ser->lock, flags);
-       ser->instance--;
-       list_del(&app->node);
-       spin_unlock_irqrestore(&ser->lock, flags);
-
-       /* free instance memory */
-       free_instance_memory(app, ser->mem_size);
-       kfree(app);
-}
-
-void nvadsp_exit_app(nvadsp_app_info_t *app, bool terminate)
-{
-       int *state;
-
-       if (IS_ERR_OR_NULL(priv.pdev)) {
-               pr_err("ADSP Driver is not initialized\n");
-               return;
-       }
-
-       if (IS_ERR_OR_NULL(app))
-               return;
-
-       /* TODO: add termination if possible to kill thread on adsp */
-       wait_for_completion(&app->wait_for_app_complete);
-       state = (int *)&app->state;
-       *state = NVADSP_APP_STATE_INITIALIZED;
-       delete_app_instance(app);
-}
-EXPORT_SYMBOL(nvadsp_exit_app);
-
-static status_t nvadsp_app_receive_handler(uint32_t msg, void *hdata)
-{
-       union app_complete_status_message message = { };
-       struct shared_mem_struct *shared_adsp_struct;
-       struct app_complete_status_data *data;
-       struct nvadsp_drv_data *drv_data;
-       struct platform_device *pdev;
-       nvadsp_app_info_t *app;
-       struct device *dev;
-       msgq_t *msgq_recv;
-
-       pdev = hdata;
-       dev = &pdev->dev;
-       drv_data = platform_get_drvdata(pdev);
-       shared_adsp_struct = drv_data->shared_adsp_os_data;
-       msgq_recv = &shared_adsp_struct->app_loader_recv_message.msgq;
-       data = &message.data;
-
-       message.msgq_msg.size = MSGQ_MSG_PAYLOAD_WSIZE(*data);
-       if (msgq_dequeue_message(msgq_recv, &message.msgq_msg)) {
-               dev_err(dev, "unable to dequeue app status message\n");
-               return 0;
-       }
-       app = (nvadsp_app_info_t *)data->host_ref;
-       app->return_status = data->status;
-       app->status_msg = msg;
-
-       if (app->complete_status_notifier) {
-               app->complete_status_notifier(app,
-                       app->status_msg, app->return_status);
-       }
-
-       switch (msg) {
-       case ADSP_APP_START_STATUS:
-               complete_all(&app->wait_for_app_start);
-               break;
-       case ADSP_APP_COMPLETE_STATUS:
-               complete_all(&app->wait_for_app_complete);
-               break;
-       }
-
-       return 0;
-}
-
-int nvadsp_run_app_module_probe(struct platform_device *pdev)
-{
-       int ret;
-       uint16_t mbox_id = APP_LOADER_MBOX_ID;
-
-       dev_info(&pdev->dev, "%s\n", __func__);
-
-       dev = &pdev->dev;
-       ret = nvadsp_mbox_open(&mbox, &mbox_id,
-               "app_service", nvadsp_app_receive_handler, pdev);
-       if (ret) {
-               dev_err(dev, "unable to open mailbox\n");
-               goto end;
-       }
-       priv.pdev = pdev;
-       INIT_LIST_HEAD(&service_list);
-       drv_data = platform_get_drvdata(pdev);
-end:
-       return ret;
-}
index b9427f1e054690ad97eb7c8ec5578e7019000b87..164d16bc2bd5212052d4bd1cdddc8d4905dd7558 100644 (file)
@@ -213,6 +213,10 @@ enum {
 };
 
 enum adsp_app_status_msg {
+       OS_LOAD_COMPLETE,
+       RUN_ADSP_APP,
+       ADSP_APP_INIT,
+       ADSP_APP_START,
        ADSP_APP_START_STATUS,
        ADSP_APP_COMPLETE_STATUS
 };
@@ -285,12 +289,12 @@ typedef struct nvadsp_app_info {
        app_complete_status_notifier complete_status_notifier;
        struct work_struct complete_work;
        enum adsp_app_status_msg status_msg;
+       void *priv;
 } nvadsp_app_info_t;
 
-nvadsp_app_handle_t __must_check
-nvadsp_app_load(const char *, const char *);
-nvadsp_app_info_t __must_check
-*nvadsp_app_init(nvadsp_app_handle_t, nvadsp_app_args_t *);
+nvadsp_app_handle_t __must_check nvadsp_app_load(const char *, const char *);
+nvadsp_app_info_t __must_check *nvadsp_app_init(nvadsp_app_handle_t,
+               nvadsp_app_args_t *);
 void nvadsp_app_unload(nvadsp_app_handle_t);
 int __must_check nvadsp_app_start(nvadsp_app_info_t *);
 int nvadsp_app_stop(nvadsp_app_info_t *);