diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c index f41e68efeef2f594bc4bc0a021b25d20beea0fdb..b044e685f2760508c4e795230bb7e258faad8e95 100644 --- a/drivers/media/platform/msm/vidc/hfi_response_handler.c +++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c @@ -78,6 +78,26 @@ static enum vidc_status hfi_map_err_status(int hfi_err) return vidc_err; } +static int sanitize_session_pkt(struct list_head *sessions, + struct hal_session *sess, struct mutex *session_lock) +{ + struct hal_session *session; + int invalid = 1; + if (session_lock) { + mutex_lock(session_lock); + list_for_each_entry(session, sessions, list) { + if (session == sess) { + invalid = 0; + break; + } + } + mutex_unlock(session_lock); + } + if (invalid) + dprintk(VIDC_WARN, "Invalid session from FW: %p\n", sess); + return invalid; +} + static void hfi_process_sess_evt_seq_changed( msm_vidc_callback callback, u32 device_id, struct hfi_msg_event_notify_packet *pkt) @@ -1183,9 +1203,11 @@ void hfi_process_sys_property_info( u32 hfi_process_msg_packet( msm_vidc_callback callback, u32 device_id, - struct vidc_hal_msg_pkt_hdr *msg_hdr) + struct vidc_hal_msg_pkt_hdr *msg_hdr, + struct list_head *sessions, struct mutex *session_lock) { u32 rc = 0; + struct hal_session *sess; if (!callback || !msg_hdr || msg_hdr->size < VIDC_IFACEQ_MIN_PKT_SIZE) { dprintk(VIDC_ERR, "hal_process_msg_packet:bad" @@ -1194,10 +1216,19 @@ u32 hfi_process_msg_packet( return rc; } +#define SANITIZE_SESSION_PKT(msg_pkt) ({ \ + sess = (struct hal_session *) \ + (((struct vidc_hal_session_cmd_pkt *) \ + msg_pkt)->session_id); \ + if (sanitize_session_pkt(sessions, sess, session_lock)) \ + break; \ + }) + dprintk(VIDC_INFO, "Received: 0x%x in ", msg_hdr->packet); rc = (u32) msg_hdr->packet; switch (msg_hdr->packet) { case HFI_MSG_EVENT_NOTIFY: + SANITIZE_SESSION_PKT(msg_hdr); hfi_process_event_notify(callback, device_id, (struct hfi_msg_event_notify_packet *) msg_hdr); break; @@ -1209,6 +1240,7 @@ u32 hfi_process_msg_packet( case HFI_MSG_SYS_IDLE: break; case HFI_MSG_SYS_SESSION_INIT_DONE: + SANITIZE_SESSION_PKT(msg_hdr); hfi_process_session_init_done(callback, device_id, (struct hfi_msg_sys_session_init_done_packet *) msg_hdr); @@ -1219,44 +1251,53 @@ u32 hfi_process_msg_packet( msg_hdr); break; case HFI_MSG_SYS_SESSION_END_DONE: + SANITIZE_SESSION_PKT(msg_hdr); hfi_process_session_end_done(callback, device_id, (struct hfi_msg_sys_session_end_done_packet *) msg_hdr); break; case HFI_MSG_SESSION_LOAD_RESOURCES_DONE: + SANITIZE_SESSION_PKT(msg_hdr); hfi_process_session_load_res_done(callback, device_id, (struct hfi_msg_session_load_resources_done_packet *) msg_hdr); break; case HFI_MSG_SESSION_START_DONE: + SANITIZE_SESSION_PKT(msg_hdr); hfi_process_session_start_done(callback, device_id, (struct hfi_msg_session_start_done_packet *) msg_hdr); break; case HFI_MSG_SESSION_STOP_DONE: + SANITIZE_SESSION_PKT(msg_hdr); hfi_process_session_stop_done(callback, device_id, (struct hfi_msg_session_stop_done_packet *) msg_hdr); break; case HFI_MSG_SESSION_EMPTY_BUFFER_DONE: + SANITIZE_SESSION_PKT(msg_hdr); hfi_process_session_etb_done(callback, device_id, (struct hfi_msg_session_empty_buffer_done_packet *) msg_hdr); break; case HFI_MSG_SESSION_FILL_BUFFER_DONE: + SANITIZE_SESSION_PKT(msg_hdr); hfi_process_session_ftb_done(callback, device_id, msg_hdr); break; case HFI_MSG_SESSION_FLUSH_DONE: + SANITIZE_SESSION_PKT(msg_hdr); hfi_process_session_flush_done(callback, device_id, (struct hfi_msg_session_flush_done_packet *) msg_hdr); break; case HFI_MSG_SESSION_PROPERTY_INFO: + SANITIZE_SESSION_PKT(msg_hdr); hfi_process_session_prop_info(callback, device_id, (struct hfi_msg_session_property_info_packet *) msg_hdr); break; case HFI_MSG_SESSION_RELEASE_RESOURCES_DONE: + SANITIZE_SESSION_PKT(msg_hdr); hfi_process_session_rel_res_done(callback, device_id, (struct hfi_msg_session_release_resources_done_packet *) msg_hdr); @@ -1267,18 +1308,21 @@ u32 hfi_process_msg_packet( msg_hdr); break; case HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE: + SANITIZE_SESSION_PKT(msg_hdr); hfi_process_session_get_seq_hdr_done( callback, device_id, (struct hfi_msg_session_get_sequence_header_done_packet*) msg_hdr); break; case HFI_MSG_SESSION_RELEASE_BUFFERS_DONE: + SANITIZE_SESSION_PKT(msg_hdr); hfi_process_session_rel_buf_done( callback, device_id, (struct hfi_msg_session_release_buffers_done_packet*) msg_hdr); break; case HFI_MSG_SYS_SESSION_ABORT_DONE: + SANITIZE_SESSION_PKT(msg_hdr); hfi_process_session_abort_done(callback, device_id, (struct hfi_msg_sys_session_abort_done_packet*) msg_hdr); break; @@ -1286,5 +1330,6 @@ u32 hfi_process_msg_packet( dprintk(VIDC_DBG, "UNKNOWN_MSG_TYPE : %d", msg_hdr->packet); break; } +#undef SANITIZE_SESSION_PKT return rc; } diff --git a/drivers/media/platform/msm/vidc/q6_hfi.c b/drivers/media/platform/msm/vidc/q6_hfi.c index bc3b93d2448e5e4b2c97d077535214a7392e1135..9148846f5af08475fd5df3ed82fa683343ccaa73 100644 --- a/drivers/media/platform/msm/vidc/q6_hfi.c +++ b/drivers/media/platform/msm/vidc/q6_hfi.c @@ -184,7 +184,8 @@ static void q6_hfi_core_work_handler(struct work_struct *work) if (!rc) hfi_process_msg_packet(device->callback, device->device_id, - (struct vidc_hal_msg_pkt_hdr *) packet); + (struct vidc_hal_msg_pkt_hdr *) packet, + &device->sess_head, &device->session_lock); } while (!rc); if (rc != -ENODATA) @@ -483,6 +484,7 @@ static int q6_hfi_core_init(void *device) } INIT_LIST_HEAD(&dev->sess_head); + mutex_init(&dev->session_lock); if (!dev->event_queue.buffer) { rc = q6_init_event_queue(dev); @@ -583,7 +585,9 @@ static void *q6_hfi_session_init(void *device, u32 session_id, rc = -EBADE; goto err_session_init; } + mutex_lock(&dev->session_lock); list_add_tail(&new_session->list, &dev->sess_head); + mutex_unlock(&dev->session_lock); return new_session; err_session_init: @@ -646,7 +650,11 @@ static int q6_hfi_session_clean(void *session) sess_close = session; dprintk(VIDC_DBG, "deleted the session: 0x%x", sess_close->session_id); + mutex_lock(&((struct q6_hfi_device *) + sess_close->device)->session_lock); list_del(&sess_close->list); + mutex_unlock(&((struct q6_hfi_device *) + sess_close->device)->session_lock); kfree(sess_close); return 0; } diff --git a/drivers/media/platform/msm/vidc/q6_hfi.h b/drivers/media/platform/msm/vidc/q6_hfi.h index 3dc4607130a4149da13c6fa9bed374d2b195733e..c2ed9183df9aba04f371ab5d7b3fb8e2df1ac64c 100644 --- a/drivers/media/platform/msm/vidc/q6_hfi.h +++ b/drivers/media/platform/msm/vidc/q6_hfi.h @@ -43,6 +43,7 @@ struct q6_hfi_device { struct q6_resources resources; struct msm_vidc_platform_resources *res; void *apr; + struct mutex session_lock; }; struct q6_apr_cmd_sys_init_packet { diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index ea2d6df861a60dc5d5c58784203c009fb39c5cc9..c33bfa07689d3d6ef0c0c8650d97b1e3aa801fce 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -1045,6 +1045,7 @@ static int venus_hfi_core_init(void *device) INIT_LIST_HEAD(&dev->sess_head); mutex_init(&dev->read_lock); mutex_init(&dev->write_lock); + mutex_init(&dev->session_lock); venus_hfi_set_registers(dev); if (!dev->hal_client) { @@ -1484,7 +1485,10 @@ static void *venus_hfi_session_init(void *device, u32 session_id, else if (session_type == 2) new_session->is_decoder = 1; new_session->device = dev; + + mutex_lock(&dev->session_lock); list_add_tail(&new_session->list, &dev->sess_head); + mutex_unlock(&dev->session_lock); if (create_pkt_cmd_sys_session_init(&pkt, (u32)new_session, session_type, codec_type)) { @@ -1554,7 +1558,11 @@ static int venus_hfi_session_clean(void *session) sess_close = session; dprintk(VIDC_DBG, "deleted the session: 0x%p", sess_close); + mutex_lock(&((struct venus_hfi_device *) + sess_close->device)->session_lock); list_del(&sess_close->list); + mutex_unlock(&((struct venus_hfi_device *) + sess_close->device)->session_lock); kfree(sess_close); return 0; } @@ -1985,7 +1993,8 @@ static void venus_hfi_response_handler(struct venus_hfi_device *device) while (!venus_hfi_iface_msgq_read(device, packet)) { rc = hfi_process_msg_packet(device->callback, device->device_id, - (struct vidc_hal_msg_pkt_hdr *) packet); + (struct vidc_hal_msg_pkt_hdr *) packet, + &device->sess_head, &device->session_lock); if (rc == HFI_MSG_EVENT_NOTIFY) venus_hfi_process_msg_event_notify( device, (void *)packet); diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h index a59a053f94c8e92f7bfd329cd7e92ba8791aa7c9..44cdf313a14a4d95d8e80480a6161ec7a004a2d7 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.h +++ b/drivers/media/platform/msm/vidc/venus_hfi.h @@ -188,6 +188,7 @@ struct venus_hfi_device { struct mutex read_lock; struct mutex write_lock; struct mutex clock_lock; + struct mutex session_lock; msm_vidc_callback callback; struct vidc_mem_addr iface_q_table; struct vidc_mem_addr qdss; diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h index 8a03751d3b27365b98896a38ecce6e18fb726b50..a6646220de49081da1ac638179fd60078ab49bf0 100644 --- a/drivers/media/platform/msm/vidc/vidc_hfi.h +++ b/drivers/media/platform/msm/vidc/vidc_hfi.h @@ -848,6 +848,7 @@ struct msm_vidc_fw { }; u32 hfi_process_msg_packet(msm_vidc_callback callback, - u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr); + u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr, + struct list_head *sessions, struct mutex *session_lock); #endif