Loading drivers/media/platform/msm/camera/cam_sync/cam_sync.c +2 −16 Original line number Diff line number Diff line Loading @@ -230,6 +230,8 @@ int cam_sync_signal(int32_t sync_obj, uint32_t status) spin_unlock_bh( &sync_dev->row_spinlocks[ parent_info->sync_id]); spin_unlock_bh( &sync_dev->row_spinlocks[sync_obj]); return rc; } } Loading Loading @@ -344,24 +346,8 @@ int cam_sync_merge(int32_t *sync_obj, uint32_t num_objs, int32_t *merged_obj) int cam_sync_destroy(int32_t sync_obj) { struct sync_table_row *row = NULL; if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) return -EINVAL; spin_lock_bh(&sync_dev->row_spinlocks[sync_obj]); row = sync_dev->sync_table + sync_obj; if (row->state == CAM_SYNC_STATE_INVALID) { CAM_ERR(CAM_SYNC, "Error: accessing an uninitialized sync obj: idx = %d", sync_obj); spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); return -EINVAL; } cam_sync_deinit_object(sync_dev->sync_table, sync_obj); spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); return 0; } Loading drivers/media/platform/msm/camera/cam_sync/cam_sync_private.h +12 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,18 @@ enum sync_type { SYNC_TYPE_GROUP }; /** * enum sync_list_clean_type - Enum to indicate the type of list clean action * to be peformed, i.e. specific sync ID or all list sync ids. * * @SYNC_CLEAN_ID : Specific object to be cleaned in the list * @SYNC_CLEAN_ALL : Clean all objects in the list */ enum sync_list_clean_type { SYNC_LIST_CLEAN_ID, SYNC_LIST_CLEAN_ALL }; /** * struct sync_parent_info - Single node of information about a parent * of a sync object, usually part of the parents linked list Loading drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c +141 −12 Original line number Diff line number Diff line Loading @@ -145,7 +145,7 @@ int cam_sync_init_group_object(struct sync_table_row *table, if (!child_info) { cam_sync_util_cleanup_children_list( &row->children_list); &row->children_list, SYNC_LIST_CLEAN_ALL, 0); return -ENOMEM; } Loading @@ -160,9 +160,10 @@ int cam_sync_init_group_object(struct sync_table_row *table, parent_info = kzalloc(sizeof(*parent_info), GFP_ATOMIC); if (!parent_info) { cam_sync_util_cleanup_parents_list( &child_row->parents_list); &child_row->parents_list, SYNC_LIST_CLEAN_ALL, 0); cam_sync_util_cleanup_children_list( &row->children_list); &row->children_list, SYNC_LIST_CLEAN_ALL, 0); spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]); return -ENOMEM; } Loading Loading @@ -197,27 +198,131 @@ int cam_sync_init_group_object(struct sync_table_row *table, int cam_sync_deinit_object(struct sync_table_row *table, uint32_t idx) { struct sync_table_row *row = table + idx; struct sync_child_info *child_info, *temp_child; struct sync_child_info *child_info, *temp_child, *child_copy_info; struct sync_callback_info *sync_cb, *temp_cb; struct sync_parent_info *parent_info, *temp_parent; struct sync_parent_info *parent_info, *temp_parent, *parent_copy_info; struct sync_user_payload *upayload_info, *temp_upayload; struct sync_table_row *child_row = NULL, *parent_row = NULL; struct list_head child_copy_list, parent_copy_list; if (!table || idx <= 0 || idx >= CAM_SYNC_MAX_OBJS) return -EINVAL; clear_bit(idx, sync_dev->bitmap); list_for_each_entry_safe(child_info, temp_child, &row->children_list, list) { spin_lock_bh(&sync_dev->row_spinlocks[idx]); if (row->state == CAM_SYNC_STATE_INVALID) { CAM_ERR(CAM_SYNC, "Error: accessing an uninitialized sync obj: idx = %d", idx); spin_unlock_bh(&sync_dev->row_spinlocks[idx]); return -EINVAL; } /* Objects child and parent objects will be added into this list */ INIT_LIST_HEAD(&child_copy_list); INIT_LIST_HEAD(&parent_copy_list); list_for_each_entry_safe(child_info, temp_child, &row->children_list, list) { if (child_info->sync_id <= 0) continue; child_copy_info = kzalloc(sizeof(*child_copy_info), GFP_ATOMIC); if (!child_copy_info) { /* No free memory, clean up the child_copy_list */ while (!list_empty(&child_copy_list)) { child_info = list_first_entry(&child_copy_list, struct sync_child_info, list); list_del_init(&child_info->list); kfree(child_info); } spin_unlock_bh(&sync_dev->row_spinlocks[idx]); goto deinit; } child_copy_info->sync_id = child_info->sync_id; list_add_tail(&child_copy_info->list, &child_copy_list); } list_for_each_entry_safe(parent_info, temp_parent, &row->parents_list, list) { if (parent_info->sync_id <= 0) continue; parent_copy_info = kzalloc(sizeof(*parent_copy_info), GFP_ATOMIC); if (!parent_copy_info) { /* No free memory, clean up the parent_copy_list */ while (!list_empty(&parent_copy_list)) { parent_info = list_first_entry( &parent_copy_list, struct sync_parent_info, list); list_del_init(&parent_info->list); kfree(parent_info); } /* No free memory, clean up the child_copy_list */ while (!list_empty(&child_copy_list)) { child_info = list_first_entry(&child_copy_list, struct sync_child_info, list); list_del_init(&child_info->list); kfree(child_info); } spin_unlock_bh(&sync_dev->row_spinlocks[idx]); goto deinit; } parent_copy_info->sync_id = parent_info->sync_id; list_add_tail(&parent_copy_info->list, &parent_copy_list); } spin_unlock_bh(&sync_dev->row_spinlocks[idx]); /* Cleanup the child to parent link from child list*/ while (!list_empty(&child_copy_list)) { child_info = list_first_entry(&child_copy_list, struct sync_child_info, list); child_row = sync_dev->sync_table + child_info->sync_id; spin_lock_bh(&sync_dev->row_spinlocks[child_info->sync_id]); if (child_row->state == CAM_SYNC_STATE_INVALID) { spin_unlock_bh(&sync_dev->row_spinlocks[ child_info->sync_id]); list_del_init(&child_info->list); kfree(child_info); continue; } cam_sync_util_cleanup_parents_list(&child_row->parents_list, SYNC_LIST_CLEAN_ID, idx); spin_unlock_bh(&sync_dev->row_spinlocks[child_info->sync_id]); list_del_init(&child_info->list); kfree(child_info); } list_for_each_entry_safe(parent_info, temp_parent, &row->parents_list, list) { /* Cleanup the parent to child link */ while (!list_empty(&parent_copy_list)) { parent_info = list_first_entry(&parent_copy_list, struct sync_parent_info, list); parent_row = sync_dev->sync_table + parent_info->sync_id; spin_lock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]); if (parent_row->state == CAM_SYNC_STATE_INVALID) { spin_unlock_bh(&sync_dev->row_spinlocks[ parent_info->sync_id]); list_del_init(&parent_info->list); kfree(parent_info); continue; } cam_sync_util_cleanup_children_list(&parent_row->children_list, SYNC_LIST_CLEAN_ID, idx); spin_unlock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]); list_del_init(&parent_info->list); kfree(parent_info); } deinit: spin_lock_bh(&sync_dev->row_spinlocks[idx]); cam_sync_util_cleanup_children_list(&row->children_list, SYNC_LIST_CLEAN_ALL, 0); cam_sync_util_cleanup_parents_list(&row->parents_list, SYNC_LIST_CLEAN_ALL, 0); list_for_each_entry_safe(upayload_info, temp_upayload, &row->user_payload_list, list) { list_del_init(&upayload_info->list); Loading @@ -232,6 +337,8 @@ int cam_sync_deinit_object(struct sync_table_row *table, uint32_t idx) row->state = CAM_SYNC_STATE_INVALID; memset(row, 0, sizeof(*row)); clear_bit(idx, sync_dev->bitmap); spin_unlock_bh(&sync_dev->row_spinlocks[idx]); return 0; } Loading Loading @@ -350,26 +457,48 @@ int cam_sync_util_get_state(int current_state, return result; } void cam_sync_util_cleanup_children_list(struct list_head *list_to_clean) void cam_sync_util_cleanup_children_list(struct list_head *list_to_clean, uint32_t list_clean_type, uint32_t sync_obj) { struct sync_child_info *child_info = NULL; struct sync_child_info *temp_child_info = NULL; uint32_t curr_sync_obj; list_for_each_entry_safe(child_info, temp_child_info, list_to_clean, list) { if ((list_clean_type == SYNC_LIST_CLEAN_ID) && (child_info->sync_id != sync_obj)) continue; curr_sync_obj = child_info->sync_id; list_del_init(&child_info->list); kfree(child_info); if ((list_clean_type == SYNC_LIST_CLEAN_ID) && (curr_sync_obj == sync_obj)) break; } } void cam_sync_util_cleanup_parents_list(struct list_head *list_to_clean) void cam_sync_util_cleanup_parents_list(struct list_head *list_to_clean, uint32_t list_clean_type, uint32_t sync_obj) { struct sync_parent_info *parent_info = NULL; struct sync_parent_info *temp_parent_info = NULL; uint32_t curr_sync_obj; list_for_each_entry_safe(parent_info, temp_parent_info, list_to_clean, list) { if ((list_clean_type == SYNC_LIST_CLEAN_ID) && (parent_info->sync_id != sync_obj)) continue; curr_sync_obj = parent_info->sync_id; list_del_init(&parent_info->list); kfree(parent_info); if ((list_clean_type == SYNC_LIST_CLEAN_ID) && (curr_sync_obj == sync_obj)) break; } } drivers/media/platform/msm/camera/cam_sync/cam_sync_util.h +10 −2 Original line number Diff line number Diff line Loading @@ -141,17 +141,25 @@ int cam_sync_util_get_state(int current_state, /** * @brief: Function to clean up the children of a sync object * @param list_to_clean : List to clean up * @list_clean_type : Clean specific object or clean all objects * @sync_obj : Sync object to be clean if list clean type is * SYNC_LIST_CLEAN_ID * * @return None */ void cam_sync_util_cleanup_children_list(struct list_head *list_to_clean); void cam_sync_util_cleanup_children_list(struct list_head *list_to_clean, uint32_t list_clean_type, uint32_t sync_obj); /** * @brief: Function to clean up the parents of a sync object * @param list_to_clean : List to clean up * @list_clean_type : Clean specific object or clean all objects * @sync_obj : Sync object to be clean if list clean type is * SYNC_LIST_CLEAN_ID * * @return None */ void cam_sync_util_cleanup_parents_list(struct list_head *list_to_clean); void cam_sync_util_cleanup_parents_list(struct list_head *list_to_clean, uint32_t list_clean_type, uint32_t sync_obj); #endif /* __CAM_SYNC_UTIL_H__ */ Loading
drivers/media/platform/msm/camera/cam_sync/cam_sync.c +2 −16 Original line number Diff line number Diff line Loading @@ -230,6 +230,8 @@ int cam_sync_signal(int32_t sync_obj, uint32_t status) spin_unlock_bh( &sync_dev->row_spinlocks[ parent_info->sync_id]); spin_unlock_bh( &sync_dev->row_spinlocks[sync_obj]); return rc; } } Loading Loading @@ -344,24 +346,8 @@ int cam_sync_merge(int32_t *sync_obj, uint32_t num_objs, int32_t *merged_obj) int cam_sync_destroy(int32_t sync_obj) { struct sync_table_row *row = NULL; if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) return -EINVAL; spin_lock_bh(&sync_dev->row_spinlocks[sync_obj]); row = sync_dev->sync_table + sync_obj; if (row->state == CAM_SYNC_STATE_INVALID) { CAM_ERR(CAM_SYNC, "Error: accessing an uninitialized sync obj: idx = %d", sync_obj); spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); return -EINVAL; } cam_sync_deinit_object(sync_dev->sync_table, sync_obj); spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); return 0; } Loading
drivers/media/platform/msm/camera/cam_sync/cam_sync_private.h +12 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,18 @@ enum sync_type { SYNC_TYPE_GROUP }; /** * enum sync_list_clean_type - Enum to indicate the type of list clean action * to be peformed, i.e. specific sync ID or all list sync ids. * * @SYNC_CLEAN_ID : Specific object to be cleaned in the list * @SYNC_CLEAN_ALL : Clean all objects in the list */ enum sync_list_clean_type { SYNC_LIST_CLEAN_ID, SYNC_LIST_CLEAN_ALL }; /** * struct sync_parent_info - Single node of information about a parent * of a sync object, usually part of the parents linked list Loading
drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c +141 −12 Original line number Diff line number Diff line Loading @@ -145,7 +145,7 @@ int cam_sync_init_group_object(struct sync_table_row *table, if (!child_info) { cam_sync_util_cleanup_children_list( &row->children_list); &row->children_list, SYNC_LIST_CLEAN_ALL, 0); return -ENOMEM; } Loading @@ -160,9 +160,10 @@ int cam_sync_init_group_object(struct sync_table_row *table, parent_info = kzalloc(sizeof(*parent_info), GFP_ATOMIC); if (!parent_info) { cam_sync_util_cleanup_parents_list( &child_row->parents_list); &child_row->parents_list, SYNC_LIST_CLEAN_ALL, 0); cam_sync_util_cleanup_children_list( &row->children_list); &row->children_list, SYNC_LIST_CLEAN_ALL, 0); spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]); return -ENOMEM; } Loading Loading @@ -197,27 +198,131 @@ int cam_sync_init_group_object(struct sync_table_row *table, int cam_sync_deinit_object(struct sync_table_row *table, uint32_t idx) { struct sync_table_row *row = table + idx; struct sync_child_info *child_info, *temp_child; struct sync_child_info *child_info, *temp_child, *child_copy_info; struct sync_callback_info *sync_cb, *temp_cb; struct sync_parent_info *parent_info, *temp_parent; struct sync_parent_info *parent_info, *temp_parent, *parent_copy_info; struct sync_user_payload *upayload_info, *temp_upayload; struct sync_table_row *child_row = NULL, *parent_row = NULL; struct list_head child_copy_list, parent_copy_list; if (!table || idx <= 0 || idx >= CAM_SYNC_MAX_OBJS) return -EINVAL; clear_bit(idx, sync_dev->bitmap); list_for_each_entry_safe(child_info, temp_child, &row->children_list, list) { spin_lock_bh(&sync_dev->row_spinlocks[idx]); if (row->state == CAM_SYNC_STATE_INVALID) { CAM_ERR(CAM_SYNC, "Error: accessing an uninitialized sync obj: idx = %d", idx); spin_unlock_bh(&sync_dev->row_spinlocks[idx]); return -EINVAL; } /* Objects child and parent objects will be added into this list */ INIT_LIST_HEAD(&child_copy_list); INIT_LIST_HEAD(&parent_copy_list); list_for_each_entry_safe(child_info, temp_child, &row->children_list, list) { if (child_info->sync_id <= 0) continue; child_copy_info = kzalloc(sizeof(*child_copy_info), GFP_ATOMIC); if (!child_copy_info) { /* No free memory, clean up the child_copy_list */ while (!list_empty(&child_copy_list)) { child_info = list_first_entry(&child_copy_list, struct sync_child_info, list); list_del_init(&child_info->list); kfree(child_info); } spin_unlock_bh(&sync_dev->row_spinlocks[idx]); goto deinit; } child_copy_info->sync_id = child_info->sync_id; list_add_tail(&child_copy_info->list, &child_copy_list); } list_for_each_entry_safe(parent_info, temp_parent, &row->parents_list, list) { if (parent_info->sync_id <= 0) continue; parent_copy_info = kzalloc(sizeof(*parent_copy_info), GFP_ATOMIC); if (!parent_copy_info) { /* No free memory, clean up the parent_copy_list */ while (!list_empty(&parent_copy_list)) { parent_info = list_first_entry( &parent_copy_list, struct sync_parent_info, list); list_del_init(&parent_info->list); kfree(parent_info); } /* No free memory, clean up the child_copy_list */ while (!list_empty(&child_copy_list)) { child_info = list_first_entry(&child_copy_list, struct sync_child_info, list); list_del_init(&child_info->list); kfree(child_info); } spin_unlock_bh(&sync_dev->row_spinlocks[idx]); goto deinit; } parent_copy_info->sync_id = parent_info->sync_id; list_add_tail(&parent_copy_info->list, &parent_copy_list); } spin_unlock_bh(&sync_dev->row_spinlocks[idx]); /* Cleanup the child to parent link from child list*/ while (!list_empty(&child_copy_list)) { child_info = list_first_entry(&child_copy_list, struct sync_child_info, list); child_row = sync_dev->sync_table + child_info->sync_id; spin_lock_bh(&sync_dev->row_spinlocks[child_info->sync_id]); if (child_row->state == CAM_SYNC_STATE_INVALID) { spin_unlock_bh(&sync_dev->row_spinlocks[ child_info->sync_id]); list_del_init(&child_info->list); kfree(child_info); continue; } cam_sync_util_cleanup_parents_list(&child_row->parents_list, SYNC_LIST_CLEAN_ID, idx); spin_unlock_bh(&sync_dev->row_spinlocks[child_info->sync_id]); list_del_init(&child_info->list); kfree(child_info); } list_for_each_entry_safe(parent_info, temp_parent, &row->parents_list, list) { /* Cleanup the parent to child link */ while (!list_empty(&parent_copy_list)) { parent_info = list_first_entry(&parent_copy_list, struct sync_parent_info, list); parent_row = sync_dev->sync_table + parent_info->sync_id; spin_lock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]); if (parent_row->state == CAM_SYNC_STATE_INVALID) { spin_unlock_bh(&sync_dev->row_spinlocks[ parent_info->sync_id]); list_del_init(&parent_info->list); kfree(parent_info); continue; } cam_sync_util_cleanup_children_list(&parent_row->children_list, SYNC_LIST_CLEAN_ID, idx); spin_unlock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]); list_del_init(&parent_info->list); kfree(parent_info); } deinit: spin_lock_bh(&sync_dev->row_spinlocks[idx]); cam_sync_util_cleanup_children_list(&row->children_list, SYNC_LIST_CLEAN_ALL, 0); cam_sync_util_cleanup_parents_list(&row->parents_list, SYNC_LIST_CLEAN_ALL, 0); list_for_each_entry_safe(upayload_info, temp_upayload, &row->user_payload_list, list) { list_del_init(&upayload_info->list); Loading @@ -232,6 +337,8 @@ int cam_sync_deinit_object(struct sync_table_row *table, uint32_t idx) row->state = CAM_SYNC_STATE_INVALID; memset(row, 0, sizeof(*row)); clear_bit(idx, sync_dev->bitmap); spin_unlock_bh(&sync_dev->row_spinlocks[idx]); return 0; } Loading Loading @@ -350,26 +457,48 @@ int cam_sync_util_get_state(int current_state, return result; } void cam_sync_util_cleanup_children_list(struct list_head *list_to_clean) void cam_sync_util_cleanup_children_list(struct list_head *list_to_clean, uint32_t list_clean_type, uint32_t sync_obj) { struct sync_child_info *child_info = NULL; struct sync_child_info *temp_child_info = NULL; uint32_t curr_sync_obj; list_for_each_entry_safe(child_info, temp_child_info, list_to_clean, list) { if ((list_clean_type == SYNC_LIST_CLEAN_ID) && (child_info->sync_id != sync_obj)) continue; curr_sync_obj = child_info->sync_id; list_del_init(&child_info->list); kfree(child_info); if ((list_clean_type == SYNC_LIST_CLEAN_ID) && (curr_sync_obj == sync_obj)) break; } } void cam_sync_util_cleanup_parents_list(struct list_head *list_to_clean) void cam_sync_util_cleanup_parents_list(struct list_head *list_to_clean, uint32_t list_clean_type, uint32_t sync_obj) { struct sync_parent_info *parent_info = NULL; struct sync_parent_info *temp_parent_info = NULL; uint32_t curr_sync_obj; list_for_each_entry_safe(parent_info, temp_parent_info, list_to_clean, list) { if ((list_clean_type == SYNC_LIST_CLEAN_ID) && (parent_info->sync_id != sync_obj)) continue; curr_sync_obj = parent_info->sync_id; list_del_init(&parent_info->list); kfree(parent_info); if ((list_clean_type == SYNC_LIST_CLEAN_ID) && (curr_sync_obj == sync_obj)) break; } }
drivers/media/platform/msm/camera/cam_sync/cam_sync_util.h +10 −2 Original line number Diff line number Diff line Loading @@ -141,17 +141,25 @@ int cam_sync_util_get_state(int current_state, /** * @brief: Function to clean up the children of a sync object * @param list_to_clean : List to clean up * @list_clean_type : Clean specific object or clean all objects * @sync_obj : Sync object to be clean if list clean type is * SYNC_LIST_CLEAN_ID * * @return None */ void cam_sync_util_cleanup_children_list(struct list_head *list_to_clean); void cam_sync_util_cleanup_children_list(struct list_head *list_to_clean, uint32_t list_clean_type, uint32_t sync_obj); /** * @brief: Function to clean up the parents of a sync object * @param list_to_clean : List to clean up * @list_clean_type : Clean specific object or clean all objects * @sync_obj : Sync object to be clean if list clean type is * SYNC_LIST_CLEAN_ID * * @return None */ void cam_sync_util_cleanup_parents_list(struct list_head *list_to_clean); void cam_sync_util_cleanup_parents_list(struct list_head *list_to_clean, uint32_t list_clean_type, uint32_t sync_obj); #endif /* __CAM_SYNC_UTIL_H__ */