Loading drivers/media/platform/msm/camera/cam_req_mgr/Makefile +7 −1 Original line number Diff line number Diff line ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_req_mgr_dev.o cam_req_mgr_util.o cam_req_mgr_core.o cam_req_mgr_workq.o cam_mem_mgr.o obj-$(CONFIG_SPECTRA_CAMERA) += cam_req_mgr_dev.o \ cam_req_mgr_util.o \ cam_req_mgr_core.o \ cam_req_mgr_workq.o \ cam_mem_mgr.o \ cam_req_mgr_timer.o \ cam_req_mgr_debug.o drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c +1789 −361 File changed.Preview size limit exceeded, changes collapsed. Show changes drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h +264 −133 Original line number Diff line number Diff line Loading @@ -14,94 +14,224 @@ #include "cam_req_mgr_interface.h" #include "cam_req_mgr_core_defs.h" #include "cam_req_mgr_timer.h" #define CAM_REQ_MGR_MAX_LINKED_DEV 16 #define MAX_REQ_SLOTS 48 #define CAM_REQ_MGR_WATCHDOG_TIMEOUT 5000 #define CAM_REQ_MGR_SCHED_REQ_TIMEOUT 1000 #define CAM_REQ_MGR_SIMULATE_SCHED_REQ 30 #define FORCE_DISABLE_RECOVERY 2 #define FORCE_ENABLE_RECOVERY 1 #define AUTO_RECOVERY 0 #define CRM_WORKQ_NUM_TASKS 30 /** * enum crm_workq_task_type * @codes: to identify which type of task is present */ enum crm_workq_task_type { CRM_WORKQ_TASK_GET_DEV_INFO, CRM_WORKQ_TASK_SETUP_LINK, CRM_WORKQ_TASK_DEV_ADD_REQ, CRM_WORKQ_TASK_APPLY_REQ, CRM_WORKQ_TASK_NOTIFY_SOF, CRM_WORKQ_TASK_NOTIFY_ERR, CRM_WORKQ_TASK_SCHED_REQ, CRM_WORKQ_TASK_FLUSH_REQ, CRM_WORKQ_TASK_INVALID, }; /** * struct crm_task_payload * @type : to identify which type of task is present * @u : union of payload of all types of tasks supported * @sched_req : contains info of incoming reqest from CSL to CRM * @flush_info : contains info of cancelled reqest * @dev_req : contains tracking info of available req id at device * @send_req : contains info of apply settings to be sent to devs in link * @apply_req : contains info of which request is applied at device * @notify_sof : contains notification from IFE to CRM about SOF trigger * @notify_err : contains error info happened while processing request * - */ struct crm_task_payload { enum crm_workq_task_type type; union { struct cam_req_mgr_sched_request sched_req; struct cam_req_mgr_flush_info flush_info; struct cam_req_mgr_add_request dev_req; struct cam_req_mgr_send_request send_req; struct cam_req_mgr_sof_notify notify_sof; struct cam_req_mgr_error_notify notify_err; } u; }; /** * enum crm_req_state * State machine for life cycle of request in pd table * EMPTY : indicates req slot is empty * PENDING : indicates req slot is waiting for reqs from all devs * READY : indicates req slot is ready to be sent to devs * INVALID : indicates req slot is not in valid state */ enum crm_req_state { CRM_REQ_STATE_EMPTY, CRM_REQ_STATE_PENDING, CRM_REQ_STATE_READY, CRM_REQ_STATE_INVALID, }; /** * enum crm_req_status * State machine for life cycle of request in link * EMPTY - indicates req slot is empty * PENDING - indicates req slot is waiting for reqs from all devs * READY - indicates req slot is ready to be sent to devs * APPLIED - indicates req slot is sent to devices * INVALID - indicates req slot is not in valid state * enum crm_slot_status * State machine for life cycle of request in input queue * NO_REQ : empty slot * REQ_ADDED : new entry in slot * INCOMPLETE : waiting for * APPLIED : req is sent to devices * INVALID : invalid state */ enum crm_req_status { CRM_REQ_STATUS_EMPTY, CRM_REQ_STATUS_PENDING, CRM_REQ_STATUS_READY, CRM_REQ_STATUS_APPLIED, CRM_REQ_STATUS_INVALID, enum crm_slot_status { CRM_SLOT_STATUS_NO_REQ, CRM_SLOT_STATUS_REQ_ADDED, CRM_SLOT_STATUS_REQ_PENDING, CRM_SLOT_STATUS_REQ_APPLIED, CRM_SLOT_STATUS_INVALID, }; /** * enum cam_req_mgr_link_state * State machine for life cycle of link in crm * AVAILABLE - indicates link is not in use * IDLE - indicates link is reserved but not initialized * READY - indicates link is initialized and ready for operation * STREAMING - indicates link is receiving triggers and requests * BUBBLE_DETECTED - indicates device on link is in bad shape * ROLLBACK_STARTED - indicates link had triggered error recovery * MAX - indicates link max as invalid * AVAILABLE : link available * IDLE : link initialized but not ready yet * READY : link is ready for use * ERR : link has encountered error * MAX : invalid state */ enum cam_req_mgr_link_state { CAM_CRM_LINK_STATE_AVAILABLE, CAM_CRM_LINK_STATE_IDLE, CAM_CRM_LINK_STATE_READY, CAM_CRM_LINK_STATE_STREAMING, CAM_CRM_LINK_STATE_BUBBLE_DETECTED, CAM_CRM_LINK_STATE_ROLLBACK_STARTED, CAM_CRM_LINK_STATE_DEVICE_STATE_MAX, CAM_CRM_LINK_STATE_ERR, CAM_CRM_LINK_STATE_MAX, }; /** * struct cam_req_mgr_request_slot * @idx: device handle * @req_status: state machine for life cycle of a request * @request_id: request id value * struct cam_req_mgr_traverse * @idx : slot index * @result : contains which all tables were able to apply successfully * @tbl : pointer of pipeline delay based request table * @apply_data : pointer which various tables will update during traverse * @in_q : input request queue pointer */ struct cam_req_mgr_request_slot { struct cam_req_mgr_traverse { int32_t idx; enum crm_req_status req_status; int64_t request_id; uint32_t result; struct cam_req_mgr_req_tbl *tbl; struct cam_req_mgr_apply *apply_data; struct cam_req_mgr_req_queue *in_q; }; /** * struct cam_req_mgr_request_queue * @read_index: idx currently being processed * @write_index: idx at which incoming req is stored * @num_slots: num of req slots i.e. queue depth * @req_slot: slots which hold the request info * struct cam_req_mgr_apply * @idx : corresponding input queue slot index * @pd : pipeline delay of device * @req_id : req id for dev with above pd to process * @skip_idx: skip applying settings when this is set. */ struct cam_req_mgr_request_queue { int32_t read_index; int32_t write_index; uint32_t num_slots; struct cam_req_mgr_request_slot *req_slot; struct cam_req_mgr_apply { int32_t idx; int32_t pd; int64_t req_id; int32_t skip_idx; }; /** * struct cam_req_mgr_frame_settings * @request_id: request id to apply * @frame_id: frame id for debug purpose * struct cam_req_mgr_tbl_slot * @idx : slot index * @req_ready_map : mask tracking which all devices have request ready * @state : state machine for life cycle of a slot */ struct cam_req_mgr_frame_settings { int64_t request_id; int64_t frame_id; struct cam_req_mgr_tbl_slot { int32_t idx; uint32_t req_ready_map; enum crm_req_state state; }; /** * struct cam_req_mgr_req_tbl * @id : table indetifier * @pd : pipeline delay of table * @dev_count : num of devices having same pipeline delay * @dev_mask : mask to track which devices are linked * @skip_traverse : to indicate how many traverses need to be dropped * by this table especially in the beginning or bubble recovery * @next : pointer to next pipeline delay request table * @pd_delta : differnce between this table's pipeline delay and next * @num_slots : number of request slots present in the table * @slot : array of slots tracking requests availability at devices */ struct cam_req_mgr_req_tbl { int32_t id; int32_t pd; int32_t dev_count; int32_t dev_mask; int32_t skip_traverse; struct cam_req_mgr_req_tbl *next; int32_t pd_delta; int32_t num_slots; struct cam_req_mgr_tbl_slot slot[MAX_REQ_SLOTS]; }; /** * struct cam_req_mgr_request_table * @pipeline_delay: pipeline delay of this req table * @l_devices: list of devices belonging to this p_delay * @dev_mask: each dev hdl has unique bit assigned, dev mask tracks if all devs * received req id packet from UMD to process * struct cam_req_mgr_slot * - Internal Book keeping * @idx : slot index * @skip_idx : if req id in this slot needs to be skipped/not applied * @status : state machine for life cycle of a slot * - members updated due to external events * @recover : if user enabled recovery for this request. * @req_id : mask tracking which all devices have request ready */ struct cam_req_mgr_request_table { uint32_t pipeline_delay; struct list_head l_devices; uint32_t dev_mask; struct cam_req_mgr_slot { int32_t idx; int32_t skip_idx; enum crm_slot_status status; int32_t recover; int64_t req_id; }; /** * struct cam_req_mgr_req_queue * @num_slots : max num of input queue slots * @slot : request slot holding incoming request id and bubble info. * @rd_idx : indicates slot index currently in process. * @wr_idx : indicates slot index to hold new upcoming req. */ struct cam_req_mgr_req_queue { int32_t num_slots; struct cam_req_mgr_slot slot[MAX_REQ_SLOTS]; int32_t rd_idx; int32_t wr_idx; }; /** * struct cam_req_mgr_req_data * @in_q : Poiner to Input request queue * @l_tbl : unique pd request tables. * @num_tbl : how many unique pd value devices are present * @apply_data : Holds information about request id for a request * @lock : mutex lock protecting request data ops. */ struct cam_req_mgr_req_data { struct cam_req_mgr_req_queue *in_q; struct cam_req_mgr_req_tbl *l_tbl; int32_t num_tbl; struct cam_req_mgr_apply apply_data[CAM_PIPELINE_DELAY_MAX]; struct mutex lock; }; /** Loading @@ -109,77 +239,81 @@ struct cam_req_mgr_request_table { * - Device Properties * @dev_hdl : device handle * @dev_bit : unique bit assigned to device in link * -Device progress status * @available_req_id: tracks latest available req id at this device * @processing_req_id: tracks request id currently processed * - Device characteristics * @pd_tbl : tracks latest available req id at this device * @dev_info : holds dev characteristics such as pipeline delay, dev name * @ops : holds func pointer to call methods on this device * @parent: pvt data - Pointer to parent link device its connected with * @entry: entry to the list of connected devices in link * @parent : pvt data - like link which this dev hdl belongs to */ struct cam_req_mgr_connected_device { int32_t dev_hdl; int64_t dev_bit; int64_t available_req_id; int64_t processing_req_id; struct cam_req_mgr_req_tbl *pd_tbl; struct cam_req_mgr_device_info dev_info; struct cam_req_mgr_kmd_ops *ops; void *parent; struct list_head entry; }; /** * struct cam_req_mgr_core_link * - Link Properties * @link_hdl : Link identifier * @num_connections: num of connected devices to this link * @max_pipeline_delay: Max of pipeline delay of all connected devs * - Input request queue * @in_requests: Queue to hold incoming request hints from CSL * @num_devs : num of connected devices to this link * @max_delay : Max of pipeline delay of all connected devs * @workq : Pointer to handle workq related jobs * @pd_mask : each set bit indicates the device with pd equal to bit * position is available. * - List of connected devices * @l_devices: List of connected devices to this link * @fs_list: Holds the request id which each device in link will consume. * @req_table: table to keep track of req ids recived at each dev handle * @l_dev : List of connected devices to this link * - Request handling data struct * @req : req data holder. * - Timer * @watchdog : watchdog timer to recover from sof freeze * - Link private data * @link_state: link state cycle * @parent: pvt data - like session info * @link_head: List head of connected devices * @lock: spin lock to guard link data operations * @workq_comp : conditional variable to block user thread for workq to * finish schedule request processing * @state : link state machine * @parent : pvt data - link's parent is session * @lock : mutex lock to guard link data operations */ struct cam_req_mgr_core_link { int32_t link_hdl; int32_t num_connections; enum cam_pipeline_delay max_pipeline_delay; struct cam_req_mgr_request_queue in_requests; int32_t num_devs; enum cam_pipeline_delay max_delay; struct cam_req_mgr_core_workq *workq; struct cam_req_mgr_connected_device *l_devices; struct cam_req_mgr_frame_settings fs_list[CAM_REQ_MGR_MAX_LINKED_DEV]; struct cam_req_mgr_request_table req_table[CAM_PIPELINE_DELAY_MAX]; enum cam_req_mgr_link_state link_state; int32_t pd_mask; struct cam_req_mgr_connected_device *l_dev; struct cam_req_mgr_req_data req; struct cam_req_mgr_timer *watchdog; struct completion workq_comp; enum cam_req_mgr_link_state state; void *parent; struct list_head link_head; spinlock_t lock; struct mutex lock; }; /** * struct cam_req_mgr_core_session * - Session Properties * @session_hdl : session identifier * @num_active_links: num of active links for current session * @num_links : num of active links for current session * - Links of this session * @links : pointer to array of links within session * @in_q : Input request queue one per session * - Session private data * @entry : pvt data - entry in the list of sessions * @lock : pvt data - spin lock to guard session data * - Debug data * @force_err_recovery : For debugging, we can force bubble recovery * to be always ON or always OFF using debugfs. */ struct cam_req_mgr_core_session { int32_t session_hdl; uint32_t num_active_links; struct cam_req_mgr_core_link links[MAX_LINKS_PER_SESSION]; uint32_t num_links; struct cam_req_mgr_core_link *links[MAX_LINKS_PER_SESSION]; struct cam_req_mgr_req_queue in_q; struct list_head entry; spinlock_t lock; struct mutex lock; int32_t force_err_recovery; }; /** Loading @@ -193,16 +327,14 @@ struct cam_req_mgr_core_device { struct mutex crm_lock; }; /* cam_req_mgr_dev to cam_req_mgr_core internal functions */ /** * cam_req_mgr_create_session() * @brief : creates session * @ses_info : output param for session handle * * Called as part of session creation. * called as part of session creation. */ int cam_req_mgr_create_session( struct cam_req_mgr_session_info *ses_info); int cam_req_mgr_create_session(struct cam_req_mgr_session_info *ses_info); /** * cam_req_mgr_destroy_session() Loading @@ -212,15 +344,14 @@ int cam_req_mgr_create_session( * Called as part of session destroy * return success/failure */ int cam_req_mgr_destroy_session( struct cam_req_mgr_session_info *ses_info); int cam_req_mgr_destroy_session(struct cam_req_mgr_session_info *ses_info); /** * cam_req_mgr_link() * @brief : creates a link for a session * @link_info : handle and session info to create a link * * Link is formed in a session for multiple devices. It creates * link is formed in a session for multiple devices. it creates * a unique link handle for the link and is specific to a * session. Returns link handle */ Loading @@ -231,7 +362,7 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info); * @brief : destroy a link in a session * @unlink_info : session and link handle info * * Link is destroyed in a session * link is destroyed in a session */ int cam_req_mgr_unlink(struct cam_req_mgr_unlink_info *unlink_info); Loading @@ -244,11 +375,11 @@ int cam_req_mgr_schedule_request( struct cam_req_mgr_sched_request *sched_req); /** * cam_req_mgr_sync_mode() * cam_req_mgr_sync_link() * @brief: sync for links in a session * @sync_links: session, links info and master link info */ int cam_req_mgr_sync_mode(struct cam_req_mgr_sync_mode *sync_links); int cam_req_mgr_sync_link(struct cam_req_mgr_sync_mode *sync_links); /** * cam_req_mgr_flush_requests() Loading drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core_defs.h +10 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,16 @@ #define CRM_TRACE_ENABLE 0 #define CRM_DEBUG_MUTEX 0 #define SET_SUCCESS_BIT(ret, pd) {\ (ret) |= (1 << (pd)); \ } #define SET_FAILURE_BIT(ret, pd) {\ (ret) &= (0 << (pd)); \ } #define CRM_GET_REQ_ID(in_q, idx) in_q->slot[idx].req_id #if (CRM_TRACE_ENABLE == 1) #define CRM_DBG(fmt, args...) do { \ trace_printk("%d: [crm_dbg] "fmt"\n", __LINE__, ##args); \ Loading drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_debug.c 0 → 100644 +139 −0 Original line number Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * 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 "cam_req_mgr_debug.h" #define MAX_SESS_INFO_LINE_BUFF_LEN 256 static char sess_info_buffer[MAX_SESS_INFO_LINE_BUFF_LEN]; static int cam_req_mgr_debug_set_bubble_recovery(void *data, u64 val) { struct cam_req_mgr_core_device *core_dev = data; struct cam_req_mgr_core_session *session; int rc = 0; mutex_lock(&core_dev->crm_lock); if (!list_empty(&core_dev->session_head)) { list_for_each_entry(session, &core_dev->session_head, entry) { session->force_err_recovery = val; } } mutex_unlock(&core_dev->crm_lock); return rc; } static int cam_req_mgr_debug_get_bubble_recovery(void *data, u64 *val) { struct cam_req_mgr_core_device *core_dev = data; struct cam_req_mgr_core_session *session; mutex_lock(&core_dev->crm_lock); if (!list_empty(&core_dev->session_head)) { session = list_first_entry(&core_dev->session_head, struct cam_req_mgr_core_session, entry); *val = session->force_err_recovery; } mutex_unlock(&core_dev->crm_lock); return 0; } DEFINE_SIMPLE_ATTRIBUTE(bubble_recovery, cam_req_mgr_debug_get_bubble_recovery, cam_req_mgr_debug_set_bubble_recovery, "%lld\n"); static int session_info_open(struct inode *inode, struct file *file) { file->private_data = inode->i_private; return 0; } static ssize_t session_info_read(struct file *t_file, char *t_char, size_t t_size_t, loff_t *t_loff_t) { int i; char *out_buffer = sess_info_buffer; char line_buffer[MAX_SESS_INFO_LINE_BUFF_LEN] = {0}; struct cam_req_mgr_core_device *core_dev = (struct cam_req_mgr_core_device *) t_file->private_data; struct cam_req_mgr_core_session *session; memset(out_buffer, 0, MAX_SESS_INFO_LINE_BUFF_LEN); mutex_lock(&core_dev->crm_lock); if (!list_empty(&core_dev->session_head)) { list_for_each_entry(session, &core_dev->session_head, entry) { snprintf(line_buffer, sizeof(line_buffer), "session_hdl = %x \t" "num_links = %d\n", session->session_hdl, session->num_links); strlcat(out_buffer, line_buffer, sizeof(sess_info_buffer)); for (i = 0; i < session->num_links; i++) { snprintf(line_buffer, sizeof(line_buffer), "link_hdl[%d] = 0x%x, num_devs connected = %d\n", i, session->links[i]->link_hdl, session->links[i]->num_devs); strlcat(out_buffer, line_buffer, sizeof(sess_info_buffer)); } } } mutex_unlock(&core_dev->crm_lock); return simple_read_from_buffer(t_char, t_size_t, t_loff_t, out_buffer, strlen(out_buffer)); } static ssize_t session_info_write(struct file *t_file, const char *t_char, size_t t_size_t, loff_t *t_loff_t) { memset(sess_info_buffer, 0, MAX_SESS_INFO_LINE_BUFF_LEN); return 0; } static const struct file_operations session_info = { .open = session_info_open, .read = session_info_read, .write = session_info_write, }; int cam_req_mgr_debug_register(struct cam_req_mgr_core_device *core_dev) { struct dentry *debugfs_root; char dirname[32] = {0}; snprintf(dirname, sizeof(dirname), "cam_req_mgr"); debugfs_root = debugfs_create_dir(dirname, NULL); if (!debugfs_root) return -ENOMEM; if (!debugfs_create_file("sessions_info", 0644, debugfs_root, core_dev, &session_info)) return -ENOMEM; if (!debugfs_create_file("bubble_recovery", 0644, debugfs_root, core_dev, &bubble_recovery)) return -ENOMEM; return 0; } Loading
drivers/media/platform/msm/camera/cam_req_mgr/Makefile +7 −1 Original line number Diff line number Diff line ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_req_mgr_dev.o cam_req_mgr_util.o cam_req_mgr_core.o cam_req_mgr_workq.o cam_mem_mgr.o obj-$(CONFIG_SPECTRA_CAMERA) += cam_req_mgr_dev.o \ cam_req_mgr_util.o \ cam_req_mgr_core.o \ cam_req_mgr_workq.o \ cam_mem_mgr.o \ cam_req_mgr_timer.o \ cam_req_mgr_debug.o
drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c +1789 −361 File changed.Preview size limit exceeded, changes collapsed. Show changes
drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h +264 −133 Original line number Diff line number Diff line Loading @@ -14,94 +14,224 @@ #include "cam_req_mgr_interface.h" #include "cam_req_mgr_core_defs.h" #include "cam_req_mgr_timer.h" #define CAM_REQ_MGR_MAX_LINKED_DEV 16 #define MAX_REQ_SLOTS 48 #define CAM_REQ_MGR_WATCHDOG_TIMEOUT 5000 #define CAM_REQ_MGR_SCHED_REQ_TIMEOUT 1000 #define CAM_REQ_MGR_SIMULATE_SCHED_REQ 30 #define FORCE_DISABLE_RECOVERY 2 #define FORCE_ENABLE_RECOVERY 1 #define AUTO_RECOVERY 0 #define CRM_WORKQ_NUM_TASKS 30 /** * enum crm_workq_task_type * @codes: to identify which type of task is present */ enum crm_workq_task_type { CRM_WORKQ_TASK_GET_DEV_INFO, CRM_WORKQ_TASK_SETUP_LINK, CRM_WORKQ_TASK_DEV_ADD_REQ, CRM_WORKQ_TASK_APPLY_REQ, CRM_WORKQ_TASK_NOTIFY_SOF, CRM_WORKQ_TASK_NOTIFY_ERR, CRM_WORKQ_TASK_SCHED_REQ, CRM_WORKQ_TASK_FLUSH_REQ, CRM_WORKQ_TASK_INVALID, }; /** * struct crm_task_payload * @type : to identify which type of task is present * @u : union of payload of all types of tasks supported * @sched_req : contains info of incoming reqest from CSL to CRM * @flush_info : contains info of cancelled reqest * @dev_req : contains tracking info of available req id at device * @send_req : contains info of apply settings to be sent to devs in link * @apply_req : contains info of which request is applied at device * @notify_sof : contains notification from IFE to CRM about SOF trigger * @notify_err : contains error info happened while processing request * - */ struct crm_task_payload { enum crm_workq_task_type type; union { struct cam_req_mgr_sched_request sched_req; struct cam_req_mgr_flush_info flush_info; struct cam_req_mgr_add_request dev_req; struct cam_req_mgr_send_request send_req; struct cam_req_mgr_sof_notify notify_sof; struct cam_req_mgr_error_notify notify_err; } u; }; /** * enum crm_req_state * State machine for life cycle of request in pd table * EMPTY : indicates req slot is empty * PENDING : indicates req slot is waiting for reqs from all devs * READY : indicates req slot is ready to be sent to devs * INVALID : indicates req slot is not in valid state */ enum crm_req_state { CRM_REQ_STATE_EMPTY, CRM_REQ_STATE_PENDING, CRM_REQ_STATE_READY, CRM_REQ_STATE_INVALID, }; /** * enum crm_req_status * State machine for life cycle of request in link * EMPTY - indicates req slot is empty * PENDING - indicates req slot is waiting for reqs from all devs * READY - indicates req slot is ready to be sent to devs * APPLIED - indicates req slot is sent to devices * INVALID - indicates req slot is not in valid state * enum crm_slot_status * State machine for life cycle of request in input queue * NO_REQ : empty slot * REQ_ADDED : new entry in slot * INCOMPLETE : waiting for * APPLIED : req is sent to devices * INVALID : invalid state */ enum crm_req_status { CRM_REQ_STATUS_EMPTY, CRM_REQ_STATUS_PENDING, CRM_REQ_STATUS_READY, CRM_REQ_STATUS_APPLIED, CRM_REQ_STATUS_INVALID, enum crm_slot_status { CRM_SLOT_STATUS_NO_REQ, CRM_SLOT_STATUS_REQ_ADDED, CRM_SLOT_STATUS_REQ_PENDING, CRM_SLOT_STATUS_REQ_APPLIED, CRM_SLOT_STATUS_INVALID, }; /** * enum cam_req_mgr_link_state * State machine for life cycle of link in crm * AVAILABLE - indicates link is not in use * IDLE - indicates link is reserved but not initialized * READY - indicates link is initialized and ready for operation * STREAMING - indicates link is receiving triggers and requests * BUBBLE_DETECTED - indicates device on link is in bad shape * ROLLBACK_STARTED - indicates link had triggered error recovery * MAX - indicates link max as invalid * AVAILABLE : link available * IDLE : link initialized but not ready yet * READY : link is ready for use * ERR : link has encountered error * MAX : invalid state */ enum cam_req_mgr_link_state { CAM_CRM_LINK_STATE_AVAILABLE, CAM_CRM_LINK_STATE_IDLE, CAM_CRM_LINK_STATE_READY, CAM_CRM_LINK_STATE_STREAMING, CAM_CRM_LINK_STATE_BUBBLE_DETECTED, CAM_CRM_LINK_STATE_ROLLBACK_STARTED, CAM_CRM_LINK_STATE_DEVICE_STATE_MAX, CAM_CRM_LINK_STATE_ERR, CAM_CRM_LINK_STATE_MAX, }; /** * struct cam_req_mgr_request_slot * @idx: device handle * @req_status: state machine for life cycle of a request * @request_id: request id value * struct cam_req_mgr_traverse * @idx : slot index * @result : contains which all tables were able to apply successfully * @tbl : pointer of pipeline delay based request table * @apply_data : pointer which various tables will update during traverse * @in_q : input request queue pointer */ struct cam_req_mgr_request_slot { struct cam_req_mgr_traverse { int32_t idx; enum crm_req_status req_status; int64_t request_id; uint32_t result; struct cam_req_mgr_req_tbl *tbl; struct cam_req_mgr_apply *apply_data; struct cam_req_mgr_req_queue *in_q; }; /** * struct cam_req_mgr_request_queue * @read_index: idx currently being processed * @write_index: idx at which incoming req is stored * @num_slots: num of req slots i.e. queue depth * @req_slot: slots which hold the request info * struct cam_req_mgr_apply * @idx : corresponding input queue slot index * @pd : pipeline delay of device * @req_id : req id for dev with above pd to process * @skip_idx: skip applying settings when this is set. */ struct cam_req_mgr_request_queue { int32_t read_index; int32_t write_index; uint32_t num_slots; struct cam_req_mgr_request_slot *req_slot; struct cam_req_mgr_apply { int32_t idx; int32_t pd; int64_t req_id; int32_t skip_idx; }; /** * struct cam_req_mgr_frame_settings * @request_id: request id to apply * @frame_id: frame id for debug purpose * struct cam_req_mgr_tbl_slot * @idx : slot index * @req_ready_map : mask tracking which all devices have request ready * @state : state machine for life cycle of a slot */ struct cam_req_mgr_frame_settings { int64_t request_id; int64_t frame_id; struct cam_req_mgr_tbl_slot { int32_t idx; uint32_t req_ready_map; enum crm_req_state state; }; /** * struct cam_req_mgr_req_tbl * @id : table indetifier * @pd : pipeline delay of table * @dev_count : num of devices having same pipeline delay * @dev_mask : mask to track which devices are linked * @skip_traverse : to indicate how many traverses need to be dropped * by this table especially in the beginning or bubble recovery * @next : pointer to next pipeline delay request table * @pd_delta : differnce between this table's pipeline delay and next * @num_slots : number of request slots present in the table * @slot : array of slots tracking requests availability at devices */ struct cam_req_mgr_req_tbl { int32_t id; int32_t pd; int32_t dev_count; int32_t dev_mask; int32_t skip_traverse; struct cam_req_mgr_req_tbl *next; int32_t pd_delta; int32_t num_slots; struct cam_req_mgr_tbl_slot slot[MAX_REQ_SLOTS]; }; /** * struct cam_req_mgr_request_table * @pipeline_delay: pipeline delay of this req table * @l_devices: list of devices belonging to this p_delay * @dev_mask: each dev hdl has unique bit assigned, dev mask tracks if all devs * received req id packet from UMD to process * struct cam_req_mgr_slot * - Internal Book keeping * @idx : slot index * @skip_idx : if req id in this slot needs to be skipped/not applied * @status : state machine for life cycle of a slot * - members updated due to external events * @recover : if user enabled recovery for this request. * @req_id : mask tracking which all devices have request ready */ struct cam_req_mgr_request_table { uint32_t pipeline_delay; struct list_head l_devices; uint32_t dev_mask; struct cam_req_mgr_slot { int32_t idx; int32_t skip_idx; enum crm_slot_status status; int32_t recover; int64_t req_id; }; /** * struct cam_req_mgr_req_queue * @num_slots : max num of input queue slots * @slot : request slot holding incoming request id and bubble info. * @rd_idx : indicates slot index currently in process. * @wr_idx : indicates slot index to hold new upcoming req. */ struct cam_req_mgr_req_queue { int32_t num_slots; struct cam_req_mgr_slot slot[MAX_REQ_SLOTS]; int32_t rd_idx; int32_t wr_idx; }; /** * struct cam_req_mgr_req_data * @in_q : Poiner to Input request queue * @l_tbl : unique pd request tables. * @num_tbl : how many unique pd value devices are present * @apply_data : Holds information about request id for a request * @lock : mutex lock protecting request data ops. */ struct cam_req_mgr_req_data { struct cam_req_mgr_req_queue *in_q; struct cam_req_mgr_req_tbl *l_tbl; int32_t num_tbl; struct cam_req_mgr_apply apply_data[CAM_PIPELINE_DELAY_MAX]; struct mutex lock; }; /** Loading @@ -109,77 +239,81 @@ struct cam_req_mgr_request_table { * - Device Properties * @dev_hdl : device handle * @dev_bit : unique bit assigned to device in link * -Device progress status * @available_req_id: tracks latest available req id at this device * @processing_req_id: tracks request id currently processed * - Device characteristics * @pd_tbl : tracks latest available req id at this device * @dev_info : holds dev characteristics such as pipeline delay, dev name * @ops : holds func pointer to call methods on this device * @parent: pvt data - Pointer to parent link device its connected with * @entry: entry to the list of connected devices in link * @parent : pvt data - like link which this dev hdl belongs to */ struct cam_req_mgr_connected_device { int32_t dev_hdl; int64_t dev_bit; int64_t available_req_id; int64_t processing_req_id; struct cam_req_mgr_req_tbl *pd_tbl; struct cam_req_mgr_device_info dev_info; struct cam_req_mgr_kmd_ops *ops; void *parent; struct list_head entry; }; /** * struct cam_req_mgr_core_link * - Link Properties * @link_hdl : Link identifier * @num_connections: num of connected devices to this link * @max_pipeline_delay: Max of pipeline delay of all connected devs * - Input request queue * @in_requests: Queue to hold incoming request hints from CSL * @num_devs : num of connected devices to this link * @max_delay : Max of pipeline delay of all connected devs * @workq : Pointer to handle workq related jobs * @pd_mask : each set bit indicates the device with pd equal to bit * position is available. * - List of connected devices * @l_devices: List of connected devices to this link * @fs_list: Holds the request id which each device in link will consume. * @req_table: table to keep track of req ids recived at each dev handle * @l_dev : List of connected devices to this link * - Request handling data struct * @req : req data holder. * - Timer * @watchdog : watchdog timer to recover from sof freeze * - Link private data * @link_state: link state cycle * @parent: pvt data - like session info * @link_head: List head of connected devices * @lock: spin lock to guard link data operations * @workq_comp : conditional variable to block user thread for workq to * finish schedule request processing * @state : link state machine * @parent : pvt data - link's parent is session * @lock : mutex lock to guard link data operations */ struct cam_req_mgr_core_link { int32_t link_hdl; int32_t num_connections; enum cam_pipeline_delay max_pipeline_delay; struct cam_req_mgr_request_queue in_requests; int32_t num_devs; enum cam_pipeline_delay max_delay; struct cam_req_mgr_core_workq *workq; struct cam_req_mgr_connected_device *l_devices; struct cam_req_mgr_frame_settings fs_list[CAM_REQ_MGR_MAX_LINKED_DEV]; struct cam_req_mgr_request_table req_table[CAM_PIPELINE_DELAY_MAX]; enum cam_req_mgr_link_state link_state; int32_t pd_mask; struct cam_req_mgr_connected_device *l_dev; struct cam_req_mgr_req_data req; struct cam_req_mgr_timer *watchdog; struct completion workq_comp; enum cam_req_mgr_link_state state; void *parent; struct list_head link_head; spinlock_t lock; struct mutex lock; }; /** * struct cam_req_mgr_core_session * - Session Properties * @session_hdl : session identifier * @num_active_links: num of active links for current session * @num_links : num of active links for current session * - Links of this session * @links : pointer to array of links within session * @in_q : Input request queue one per session * - Session private data * @entry : pvt data - entry in the list of sessions * @lock : pvt data - spin lock to guard session data * - Debug data * @force_err_recovery : For debugging, we can force bubble recovery * to be always ON or always OFF using debugfs. */ struct cam_req_mgr_core_session { int32_t session_hdl; uint32_t num_active_links; struct cam_req_mgr_core_link links[MAX_LINKS_PER_SESSION]; uint32_t num_links; struct cam_req_mgr_core_link *links[MAX_LINKS_PER_SESSION]; struct cam_req_mgr_req_queue in_q; struct list_head entry; spinlock_t lock; struct mutex lock; int32_t force_err_recovery; }; /** Loading @@ -193,16 +327,14 @@ struct cam_req_mgr_core_device { struct mutex crm_lock; }; /* cam_req_mgr_dev to cam_req_mgr_core internal functions */ /** * cam_req_mgr_create_session() * @brief : creates session * @ses_info : output param for session handle * * Called as part of session creation. * called as part of session creation. */ int cam_req_mgr_create_session( struct cam_req_mgr_session_info *ses_info); int cam_req_mgr_create_session(struct cam_req_mgr_session_info *ses_info); /** * cam_req_mgr_destroy_session() Loading @@ -212,15 +344,14 @@ int cam_req_mgr_create_session( * Called as part of session destroy * return success/failure */ int cam_req_mgr_destroy_session( struct cam_req_mgr_session_info *ses_info); int cam_req_mgr_destroy_session(struct cam_req_mgr_session_info *ses_info); /** * cam_req_mgr_link() * @brief : creates a link for a session * @link_info : handle and session info to create a link * * Link is formed in a session for multiple devices. It creates * link is formed in a session for multiple devices. it creates * a unique link handle for the link and is specific to a * session. Returns link handle */ Loading @@ -231,7 +362,7 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info); * @brief : destroy a link in a session * @unlink_info : session and link handle info * * Link is destroyed in a session * link is destroyed in a session */ int cam_req_mgr_unlink(struct cam_req_mgr_unlink_info *unlink_info); Loading @@ -244,11 +375,11 @@ int cam_req_mgr_schedule_request( struct cam_req_mgr_sched_request *sched_req); /** * cam_req_mgr_sync_mode() * cam_req_mgr_sync_link() * @brief: sync for links in a session * @sync_links: session, links info and master link info */ int cam_req_mgr_sync_mode(struct cam_req_mgr_sync_mode *sync_links); int cam_req_mgr_sync_link(struct cam_req_mgr_sync_mode *sync_links); /** * cam_req_mgr_flush_requests() Loading
drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core_defs.h +10 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,16 @@ #define CRM_TRACE_ENABLE 0 #define CRM_DEBUG_MUTEX 0 #define SET_SUCCESS_BIT(ret, pd) {\ (ret) |= (1 << (pd)); \ } #define SET_FAILURE_BIT(ret, pd) {\ (ret) &= (0 << (pd)); \ } #define CRM_GET_REQ_ID(in_q, idx) in_q->slot[idx].req_id #if (CRM_TRACE_ENABLE == 1) #define CRM_DBG(fmt, args...) do { \ trace_printk("%d: [crm_dbg] "fmt"\n", __LINE__, ##args); \ Loading
drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_debug.c 0 → 100644 +139 −0 Original line number Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * 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 "cam_req_mgr_debug.h" #define MAX_SESS_INFO_LINE_BUFF_LEN 256 static char sess_info_buffer[MAX_SESS_INFO_LINE_BUFF_LEN]; static int cam_req_mgr_debug_set_bubble_recovery(void *data, u64 val) { struct cam_req_mgr_core_device *core_dev = data; struct cam_req_mgr_core_session *session; int rc = 0; mutex_lock(&core_dev->crm_lock); if (!list_empty(&core_dev->session_head)) { list_for_each_entry(session, &core_dev->session_head, entry) { session->force_err_recovery = val; } } mutex_unlock(&core_dev->crm_lock); return rc; } static int cam_req_mgr_debug_get_bubble_recovery(void *data, u64 *val) { struct cam_req_mgr_core_device *core_dev = data; struct cam_req_mgr_core_session *session; mutex_lock(&core_dev->crm_lock); if (!list_empty(&core_dev->session_head)) { session = list_first_entry(&core_dev->session_head, struct cam_req_mgr_core_session, entry); *val = session->force_err_recovery; } mutex_unlock(&core_dev->crm_lock); return 0; } DEFINE_SIMPLE_ATTRIBUTE(bubble_recovery, cam_req_mgr_debug_get_bubble_recovery, cam_req_mgr_debug_set_bubble_recovery, "%lld\n"); static int session_info_open(struct inode *inode, struct file *file) { file->private_data = inode->i_private; return 0; } static ssize_t session_info_read(struct file *t_file, char *t_char, size_t t_size_t, loff_t *t_loff_t) { int i; char *out_buffer = sess_info_buffer; char line_buffer[MAX_SESS_INFO_LINE_BUFF_LEN] = {0}; struct cam_req_mgr_core_device *core_dev = (struct cam_req_mgr_core_device *) t_file->private_data; struct cam_req_mgr_core_session *session; memset(out_buffer, 0, MAX_SESS_INFO_LINE_BUFF_LEN); mutex_lock(&core_dev->crm_lock); if (!list_empty(&core_dev->session_head)) { list_for_each_entry(session, &core_dev->session_head, entry) { snprintf(line_buffer, sizeof(line_buffer), "session_hdl = %x \t" "num_links = %d\n", session->session_hdl, session->num_links); strlcat(out_buffer, line_buffer, sizeof(sess_info_buffer)); for (i = 0; i < session->num_links; i++) { snprintf(line_buffer, sizeof(line_buffer), "link_hdl[%d] = 0x%x, num_devs connected = %d\n", i, session->links[i]->link_hdl, session->links[i]->num_devs); strlcat(out_buffer, line_buffer, sizeof(sess_info_buffer)); } } } mutex_unlock(&core_dev->crm_lock); return simple_read_from_buffer(t_char, t_size_t, t_loff_t, out_buffer, strlen(out_buffer)); } static ssize_t session_info_write(struct file *t_file, const char *t_char, size_t t_size_t, loff_t *t_loff_t) { memset(sess_info_buffer, 0, MAX_SESS_INFO_LINE_BUFF_LEN); return 0; } static const struct file_operations session_info = { .open = session_info_open, .read = session_info_read, .write = session_info_write, }; int cam_req_mgr_debug_register(struct cam_req_mgr_core_device *core_dev) { struct dentry *debugfs_root; char dirname[32] = {0}; snprintf(dirname, sizeof(dirname), "cam_req_mgr"); debugfs_root = debugfs_create_dir(dirname, NULL); if (!debugfs_root) return -ENOMEM; if (!debugfs_create_file("sessions_info", 0644, debugfs_root, core_dev, &session_info)) return -ENOMEM; if (!debugfs_create_file("bubble_recovery", 0644, debugfs_root, core_dev, &bubble_recovery)) return -ENOMEM; return 0; }