static void adsp_rtos_mtoa_cb(void *context, uint32_t param, void *evt_buf, uint32_t len) { struct adsp_rtos_mp_mtoa_s_type *args = NULL; uint32_t event = 0; uint32_t proc_id = 0; uint32_t module_id; uint32_t image; struct msm_adsp_module *module; struct adsp_rtos_mp_mtoa_type *pkt_ptr; struct queue_to_offset_type *qptr; struct queue_to_offset_type *qtbl; struct mod_to_queue_offsets *mqptr; struct mod_to_queue_offsets *mqtbl; uint32_t *mptr; uint32_t *mtbl; uint32_t q_idx; uint32_t num_entries; uint32_t entries_per_image; struct adsp_rtos_mp_mtoa_init_info_type *iptr; struct adsp_rtos_mp_mtoa_init_info_type *sptr; int32_t i_no, e_idx; static uint32_t init_info_completed; static uint32_t init_info_len = sizeof(struct adsp_rtos_mp_mtoa_header_type); static uint32_t next_init_info_byte; static uint32_t expected_byte = 1; uint32_t hdr_len = sizeof(struct adsp_rtos_mp_mtoa_header_type); if (len) { args = (struct adsp_rtos_mp_mtoa_s_type *) evt_buf; event = args->mp_mtoa_header.event; proc_id = args->mp_mtoa_header.proc_id; } if (!init_info_completed && event == RPC_ADSP_RTOS_INIT_INFO) { memcpy(((char *)adsp_info.raw_event) + init_info_len, (char *)evt_buf + hdr_len + 4, len - ((hdr_len + 4))); init_info_len += (len - (hdr_len + 4)); evt_buf += hdr_len; next_init_info_byte = *(uint32_t *) evt_buf; expected_byte += len; if (next_init_info_byte && (expected_byte != next_init_info_byte)) { MM_ERR("INIT_INFO - expecting next byte to be %d\n" "\tbut ADSPSVC indicated next byte to be %d\n", expected_byte, next_init_info_byte); return; } if (!next_init_info_byte) { args = adsp_info.raw_event; args->mp_mtoa_header.event = event; args->mp_mtoa_header.proc_id = proc_id; init_info_completed = 1; } else return; } if (event == RPC_ADSP_RTOS_INIT_INFO) { MM_INFO("INIT_INFO Event\n"); sptr = &args->adsp_rtos_mp_mtoa_data.mp_mtoa_init_packet; iptr = adsp_info.init_info_ptr; iptr->image_count = sptr->image_count; if (iptr->image_count > IMG_MAX) iptr->image_count = IMG_MAX; iptr->num_queue_offsets = sptr->num_queue_offsets; num_entries = iptr->num_queue_offsets; if (num_entries > ENTRIES_MAX) { num_entries = ENTRIES_MAX; iptr->num_queue_offsets = ENTRIES_MAX; } qptr = &sptr->queue_offsets_tbl[0][0]; for (i_no = 0; i_no < iptr->image_count; i_no++) { qtbl = &iptr->queue_offsets_tbl[i_no][0]; for (e_idx = 0; e_idx < num_entries; e_idx++) { qtbl[e_idx].offset = qptr->offset; qtbl[e_idx].queue = qptr->queue; q_idx = qptr->queue; iptr->queue_offsets[i_no][q_idx] = qtbl[e_idx].offset; qptr++; } } num_entries = sptr->num_task_module_entries; if (num_entries > ENTRIES_MAX) num_entries = ENTRIES_MAX; iptr->num_task_module_entries = num_entries; entries_per_image = num_entries / iptr->image_count; mptr = &sptr->task_to_module_tbl[0][0]; for (i_no = 0; i_no < iptr->image_count; i_no++) { mtbl = &iptr->task_to_module_tbl[i_no][0]; for (e_idx = 0; e_idx < entries_per_image; e_idx++) { mtbl[e_idx] = *mptr; mptr++; } } iptr->module_table_size = sptr->module_table_size; if (iptr->module_table_size > MODULES_MAX) iptr->module_table_size = MODULES_MAX; mptr = &sptr->module_entries[0]; for (i_no = 0; i_no < iptr->module_table_size; i_no++) iptr->module_entries[i_no] = mptr[i_no]; mqptr = &sptr->mod_to_q_tbl[0]; mqtbl = &iptr->mod_to_q_tbl[0]; iptr->mod_to_q_entries = sptr->mod_to_q_entries; if (iptr->mod_to_q_entries > ENTRIES_MAX) iptr->mod_to_q_entries = ENTRIES_MAX; for (e_idx = 0; e_idx < iptr->mod_to_q_entries; e_idx++) { mqtbl[e_idx].module = mqptr->module; mqtbl[e_idx].q_type = mqptr->q_type; mqtbl[e_idx].q_max_len = mqptr->q_max_len; mqptr++; } adsp_info.init_info_state = ADSP_STATE_INIT_INFO; kfree(adsp_info.raw_event); wake_up(&adsp_info.init_info_wait); return; } pkt_ptr = &args->adsp_rtos_mp_mtoa_data.mp_mtoa_packet; module_id = pkt_ptr->module; image = pkt_ptr->image; MM_INFO("rpc event=%d, proc_id=%d, module=%d, image=%d\n", event, proc_id, module_id, image); module = find_adsp_module_by_id(&adsp_info, module_id); if (!module) { MM_ERR("module %d is not supported!\n", module_id); return; } mutex_lock(&module->lock); switch (event) { case RPC_ADSP_RTOS_MOD_READY: MM_INFO("module %s: READY\n", module->name); module->state = ADSP_STATE_ENABLED; wake_up(&module->state_wait); adsp_set_image(module->info, image); break; case RPC_ADSP_RTOS_MOD_DISABLE: MM_INFO("module %s: DISABLED\n", module->name); module->state = ADSP_STATE_DISABLED; wake_up(&module->state_wait); break; case RPC_ADSP_RTOS_SERVICE_RESET: MM_INFO("module %s: SERVICE_RESET\n", module->name); module->state = ADSP_STATE_DISABLED; wake_up(&module->state_wait); break; case RPC_ADSP_RTOS_CMD_SUCCESS: MM_INFO("module %s: CMD_SUCCESS\n", module->name); break; case RPC_ADSP_RTOS_CMD_FAIL: MM_INFO("module %s: CMD_FAIL\n", module->name); break; case RPC_ADSP_RTOS_DISABLE_FAIL: MM_INFO("module %s: DISABLE_FAIL\n", module->name); break; default: MM_ERR("unknown event %d\n", event); mutex_unlock(&module->lock); return; } #ifdef CONFIG_MSM_ADSP_REPORT_EVENTS event_addr = (uint32_t *)evt_buf; if (module->ops) module->ops->event(module->driver_data, EVENT_MSG_ID, EVENT_LEN, read_event); #endif mutex_unlock(&module->lock); }
static void handle_adsp_rtos_mtoa_app(struct rpc_request_hdr *req) { struct rpc_adsp_rtos_modem_to_app_args_t *args = (struct rpc_adsp_rtos_modem_to_app_args_t *)req; uint32_t event; uint32_t proc_id; uint32_t module_id; uint32_t image; struct msm_adsp_module *module; struct adsp_rtos_mp_mtoa_type *pkt_ptr; struct queue_to_offset_type *qptr; struct queue_to_offset_type *qtbl; struct mod_to_queue_offsets *mqptr; struct mod_to_queue_offsets *mqtbl; uint32_t *mptr; uint32_t *mtbl; uint32_t q_idx; uint32_t num_entries; uint32_t entries_per_image; struct adsp_rtos_mp_mtoa_init_info_type *iptr; struct adsp_rtos_mp_mtoa_init_info_type *sptr; int32_t i_no, e_idx; event = be32_to_cpu(args->mtoa_pkt.mp_mtoa_header.event); proc_id = be32_to_cpu(args->mtoa_pkt.mp_mtoa_header.proc_id); if (event == RPC_ADSP_RTOS_INIT_INFO) { MM_INFO("INIT_INFO Event\n"); sptr = &args->mtoa_pkt.adsp_rtos_mp_mtoa_data.mp_mtoa_init_packet; iptr = adsp_info.init_info_ptr; iptr->image_count = be32_to_cpu(sptr->image_count); iptr->num_queue_offsets = be32_to_cpu(sptr->num_queue_offsets); num_entries = iptr->num_queue_offsets; qptr = &sptr->queue_offsets_tbl[0][0]; for (i_no = 0; i_no < iptr->image_count; i_no++) { qtbl = &iptr->queue_offsets_tbl[i_no][0]; for (e_idx = 0; e_idx < num_entries; e_idx++) { qtbl[e_idx].offset = be32_to_cpu(qptr->offset); qtbl[e_idx].queue = be32_to_cpu(qptr->queue); q_idx = be32_to_cpu(qptr->queue); iptr->queue_offsets[i_no][q_idx] = qtbl[e_idx].offset; qptr++; } } num_entries = be32_to_cpu(sptr->num_task_module_entries); iptr->num_task_module_entries = num_entries; entries_per_image = num_entries / iptr->image_count; mptr = &sptr->task_to_module_tbl[0][0]; for (i_no = 0; i_no < iptr->image_count; i_no++) { mtbl = &iptr->task_to_module_tbl[i_no][0]; for (e_idx = 0; e_idx < entries_per_image; e_idx++) { mtbl[e_idx] = be32_to_cpu(*mptr); mptr++; } } iptr->module_table_size = be32_to_cpu(sptr->module_table_size); mptr = &sptr->module_entries[0]; for (i_no = 0; i_no < iptr->module_table_size; i_no++) iptr->module_entries[i_no] = be32_to_cpu(mptr[i_no]); mqptr = &sptr->mod_to_q_tbl[0]; mqtbl = &iptr->mod_to_q_tbl[0]; iptr->mod_to_q_entries = be32_to_cpu(sptr->mod_to_q_entries); for (e_idx = 0; e_idx < iptr->mod_to_q_entries; e_idx++) { mqtbl[e_idx].module = be32_to_cpu(mqptr->module); mqtbl[e_idx].q_type = be32_to_cpu(mqptr->q_type); mqtbl[e_idx].q_max_len = be32_to_cpu(mqptr->q_max_len); mqptr++; } adsp_info.init_info_state = ADSP_STATE_INIT_INFO; rpc_send_accepted_void_reply(rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_SUCCESS); wake_up(&adsp_info.init_info_wait); return; } pkt_ptr = &args->mtoa_pkt.adsp_rtos_mp_mtoa_data.mp_mtoa_packet; module_id = be32_to_cpu(pkt_ptr->module); image = be32_to_cpu(pkt_ptr->image); MM_INFO("rpc event=%d, proc_id=%d, module=%d, image=%d\n", event, proc_id, module_id, image); module = find_adsp_module_by_id(&adsp_info, module_id); if (!module) { MM_ERR("module %d is not supported!\n", module_id); rpc_send_accepted_void_reply(rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_GARBAGE_ARGS); return; } mutex_lock(&module->lock); switch (event) { case RPC_ADSP_RTOS_MOD_READY: MM_INFO("module %s: READY\n", module->name); module->state = ADSP_STATE_ENABLED; wake_up(&module->state_wait); adsp_set_image(module->info, image); break; case RPC_ADSP_RTOS_MOD_DISABLE: MM_INFO("module %s: DISABLED\n", module->name); module->state = ADSP_STATE_DISABLED; wake_up(&module->state_wait); break; case RPC_ADSP_RTOS_SERVICE_RESET: MM_INFO("module %s: SERVICE_RESET\n", module->name); module->state = ADSP_STATE_DISABLED; wake_up(&module->state_wait); break; case RPC_ADSP_RTOS_CMD_SUCCESS: MM_INFO("module %s: CMD_SUCCESS\n", module->name); break; case RPC_ADSP_RTOS_CMD_FAIL: MM_INFO("module %s: CMD_FAIL\n", module->name); break; case RPC_ADSP_RTOS_DISABLE_FAIL: MM_INFO("module %s: DISABLE_FAIL\n", module->name); break; default: MM_ERR("unknown event %d\n", event); rpc_send_accepted_void_reply(rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_GARBAGE_ARGS); mutex_unlock(&module->lock); return; } rpc_send_accepted_void_reply(rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_SUCCESS); mutex_unlock(&module->lock); #ifdef CONFIG_MSM_ADSP_REPORT_EVENTS modem_event_addr = (uint32_t *)req; module->ops->event(module->driver_data, EVENT_MSG_ID, EVENT_LEN, read_modem_event); #endif }
static void handle_adsp_rtos_mtoa_app(struct rpc_request_hdr *req) { struct rpc_adsp_rtos_modem_to_app_args_t *args = (struct rpc_adsp_rtos_modem_to_app_args_t *)req; uint32_t event; uint32_t proc_id; #if defined(CONFIG_ARCH_MSM7227) #else uint32_t desc_field; #endif uint32_t module_id; uint32_t image; struct msm_adsp_module *module; struct adsp_rtos_mp_mtoa_type *pkt_ptr; struct queue_to_offset_type *qptr; struct queue_to_offset_type *qtbl; #if defined(CONFIG_ARCH_MSM7227) struct mod_to_queue_offsets *mqptr; struct mod_to_queue_offsets *mqtbl; #endif uint32_t *mptr; uint32_t *mtbl; uint32_t q_idx; uint32_t num_entries; uint32_t entries_per_image; struct adsp_rtos_mp_mtoa_init_info_type *iptr; struct adsp_rtos_mp_mtoa_init_info_type *sptr; int32_t i_no, e_idx; event = be32_to_cpu(args->mtoa_pkt.mp_mtoa_header.event); proc_id = be32_to_cpu(args->mtoa_pkt.mp_mtoa_header.proc_id); #if defined(CONFIG_ARCH_MSM7227) #else desc_field = be32_to_cpu(args->mtoa_pkt.desc_field); #endif #if defined(CONFIG_ARCH_MSM7227) if (event == RPC_ADSP_RTOS_INIT_INFO) { #else if (desc_field == RPC_ADSP_RTOS_INIT_INFO) { #endif pr_info("adsp:INIT_INFO Event\n"); sptr = &args->mtoa_pkt.adsp_rtos_mp_mtoa_data. mp_mtoa_init_packet; iptr = adsp_info.init_info_ptr; iptr->image_count = be32_to_cpu(sptr->image_count); iptr->num_queue_offsets = be32_to_cpu(sptr->num_queue_offsets); num_entries = iptr->num_queue_offsets; qptr = &sptr->queue_offsets_tbl[0][0]; for (i_no = 0; i_no < iptr->image_count; i_no++) { qtbl = &iptr->queue_offsets_tbl[i_no][0]; for (e_idx = 0; e_idx < num_entries; e_idx++) { qtbl[e_idx].offset = be32_to_cpu(qptr->offset); qtbl[e_idx].queue = be32_to_cpu(qptr->queue); q_idx = be32_to_cpu(qptr->queue); iptr->queue_offsets[i_no][q_idx] = qtbl[e_idx].offset; #if 0 pr_info("iptr->queue_offsets[%d][%d] = %x\n", i_no, q_idx, iptr->queue_offsets[i_no][q_idx]); #endif qptr++; } } num_entries = be32_to_cpu(sptr->num_task_module_entries); iptr->num_task_module_entries = num_entries; entries_per_image = num_entries / iptr->image_count; mptr = &sptr->task_to_module_tbl[0][0]; for (i_no = 0; i_no < iptr->image_count; i_no++) { mtbl = &iptr->task_to_module_tbl[i_no][0]; for (e_idx = 0; e_idx < entries_per_image; e_idx++) { mtbl[e_idx] = be32_to_cpu(*mptr); mptr++; #if 0 pr_info("mtbl[%d] = %x\n", e_idx, mtbl[e_idx]); #endif } } iptr->module_table_size = be32_to_cpu(sptr->module_table_size); mptr = &sptr->module_entries[0]; for (i_no = 0; i_no < iptr->module_table_size; i_no++) iptr->module_entries[i_no] = be32_to_cpu(mptr[i_no]); #if defined(CONFIG_ARCH_MSM7227) mqptr = &sptr->mod_to_q_tbl[0]; mqtbl = &iptr->mod_to_q_tbl[0]; iptr->mod_to_q_entries = be32_to_cpu(sptr->mod_to_q_entries); for (e_idx = 0; e_idx < iptr->mod_to_q_entries; e_idx++) { mqtbl[e_idx].module = be32_to_cpu(mqptr->module); mqtbl[e_idx].q_type = be32_to_cpu(mqptr->q_type); mqtbl[e_idx].q_max_len = be32_to_cpu(mqptr->q_max_len); mqptr++; } #endif adsp_info.init_info_state = ADSP_STATE_INIT_INFO; wake_up(&adsp_info.init_info_wait); rpc_send_accepted_void_reply(rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_SUCCESS); return; } pkt_ptr = &args->mtoa_pkt.adsp_rtos_mp_mtoa_data.mp_mtoa_packet; module_id = be32_to_cpu(pkt_ptr->module); image = be32_to_cpu(pkt_ptr->image); pr_info("adsp: rpc event=%d, proc_id=%d, module=%d, image=%d\n", event, proc_id, module_id, image); module = find_adsp_module_by_id(&adsp_info, module_id); if (!module) { pr_err("adsp: module %d is not supported!\n", module_id); rpc_send_accepted_void_reply(rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_GARBAGE_ARGS); return; } mutex_lock(&module->lock); switch (event) { case RPC_ADSP_RTOS_MOD_READY: pr_info("adsp: module %s: READY\n", module->name); module->state = ADSP_STATE_ENABLED; wake_up(&module->state_wait); adsp_set_image(module->info, image); break; case RPC_ADSP_RTOS_MOD_DISABLE: pr_info("adsp: module %s: DISABLED\n", module->name); module->state = ADSP_STATE_DISABLED; wake_up(&module->state_wait); break; case RPC_ADSP_RTOS_SERVICE_RESET: pr_info("adsp: module %s: SERVICE_RESET\n", module->name); module->state = ADSP_STATE_DISABLED; wake_up(&module->state_wait); break; case RPC_ADSP_RTOS_CMD_SUCCESS: pr_info("adsp: module %s: CMD_SUCCESS\n", module->name); break; case RPC_ADSP_RTOS_CMD_FAIL: pr_info("adsp: module %s: CMD_FAIL\n", module->name); break; case RPC_ADSP_RTOS_DISABLE_FAIL: pr_info("adsp: module %s: DISABLE_FAIL\n", module->name); break; default: pr_info("adsp: unknown event %d\n", event); rpc_send_accepted_void_reply(rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_GARBAGE_ARGS); goto done; } rpc_send_accepted_void_reply(rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_SUCCESS); if (module->ops->modem_event != NULL) module->ops->modem_event(module->driver_data, image); done: mutex_unlock(&module->lock); event_addr = (uint32_t *)req; module->ops->event(module->driver_data, EVENT_MSG_ID, EVENT_LEN, read_event); } static int handle_adsp_rtos_mtoa(struct rpc_request_hdr *req) { switch (req->procedure) { case RPC_ADSP_RTOS_MTOA_NULL_PROC: rpc_send_accepted_void_reply(rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_SUCCESS); break; #if defined(CONFIG_ARCH_MSM7227) case RPC_ADSP_RTOS_MODEM_TO_APP_INIT_INFO_PROC: case RPC_ADSP_RTOS_MODEM_TO_APP_EVENT_INFO_PROC: #else case RPC_ADSP_RTOS_MODEM_TO_APP_PROC: #endif handle_adsp_rtos_mtoa_app(req); break; default: pr_err("adsp: unknowned proc %d\n", req->procedure); rpc_send_accepted_void_reply( rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_PROC_UNAVAIL); break; } return 0; } /* this should be common code with rpc_servers.c */ static int adsp_rpc_thread(void *data) { void *buffer; struct rpc_request_hdr *req; int rc, exit = 0; do { rc = msm_rpc_read(rpc_cb_server_client, &buffer, -1, -1); if (rc < 0) { pr_err("adsp: could not read rpc: %d\n", rc); break; } req = (struct rpc_request_hdr *)buffer; req->type = be32_to_cpu(req->type); req->xid = be32_to_cpu(req->xid); req->rpc_vers = be32_to_cpu(req->rpc_vers); req->prog = be32_to_cpu(req->prog); req->vers = be32_to_cpu(req->vers); req->procedure = be32_to_cpu(req->procedure); if (req->type != 0) goto bad_rpc; if (req->rpc_vers != 2) goto bad_rpc; if (req->prog != rpc_adsp_rtos_mtoa_prog) goto bad_rpc; if (req->vers != rpc_adsp_rtos_mtoa_vers) goto bad_rpc; handle_adsp_rtos_mtoa(req); kfree(buffer); continue; bad_rpc: pr_err("adsp: bogus rpc from modem\n"); kfree(buffer); } while (!exit); do_exit(0); }