Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a8b9150f authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: vidc: Fix race condition during concurrent sessions"

parents 52256f6a f950a20c
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -322,7 +322,6 @@ static int msm_vidc_initialize_core(struct platform_device *pdev,
	}

	INIT_LIST_HEAD(&core->instances);
	mutex_init(&core->sync_lock);
	mutex_init(&core->lock);

	core->state = VIDC_CORE_UNINIT;
+2 −6
Original line number Diff line number Diff line
@@ -1090,9 +1090,8 @@ int msm_vdec_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a)
		dprintk(VIDC_PROF, "reported fps changed for %p: %d->%d\n",
				inst, inst->prop.fps, fps);
		inst->prop.fps = fps;
		mutex_lock(&inst->core->sync_lock);

		msm_comm_scale_clocks_and_bus(inst);
		mutex_unlock(&inst->core->sync_lock);
	}
exit:
	return rc;
@@ -1446,9 +1445,8 @@ static inline int start_streaming(struct msm_vidc_inst *inst)
			goto fail_start;
		}
	}
	mutex_lock(&inst->core->sync_lock);

	msm_comm_scale_clocks_and_bus(inst);
	mutex_unlock(&inst->core->sync_lock);

	rc = msm_comm_try_state(inst, MSM_VIDC_START_DONE);
	if (rc) {
@@ -1555,9 +1553,7 @@ static int msm_vdec_stop_streaming(struct vb2_queue *q)
		break;
	}

	mutex_lock(&inst->core->sync_lock);
	msm_comm_scale_clocks_and_bus(inst);
	mutex_unlock(&inst->core->sync_lock);

	if (rc)
		dprintk(VIDC_ERR,
+1 −6
Original line number Diff line number Diff line
@@ -1213,9 +1213,7 @@ static inline int start_streaming(struct msm_vidc_inst *inst)
		goto fail_start;
	}

	mutex_lock(&inst->core->sync_lock);
	msm_comm_scale_clocks_and_bus(inst);
	mutex_unlock(&inst->core->sync_lock);

	rc = msm_comm_try_state(inst, MSM_VIDC_START_DONE);
	if (rc) {
@@ -1292,9 +1290,7 @@ static int msm_venc_stop_streaming(struct vb2_queue *q)
		break;
	}

	mutex_lock(&inst->core->sync_lock);
	msm_comm_scale_clocks_and_bus(inst);
	mutex_unlock(&inst->core->sync_lock);

	if (rc)
		dprintk(VIDC_ERR,
@@ -2774,9 +2770,8 @@ int msm_venc_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a)
			dprintk(VIDC_WARN,
				"Failed to set frame rate %d\n", rc);
		}
		mutex_lock(&inst->core->sync_lock);

		msm_comm_scale_clocks_and_bus(inst);
		mutex_unlock(&inst->core->sync_lock);
	}
exit:
	return rc;
+4 −4
Original line number Diff line number Diff line
@@ -1313,9 +1313,9 @@ void *msm_vidc_open(int core_id, int session_type)

	setup_event_queue(inst, &core->vdev[session_type].vdev);

	mutex_lock(&core->sync_lock);
	mutex_lock(&core->lock);
	list_add_tail(&inst->list, &core->instances);
	mutex_unlock(&core->sync_lock);
	mutex_unlock(&core->lock);
	return inst;
fail_init:
	vb2_queue_release(&inst->bufq[OUTPUT_PORT].vb2_bufq);
@@ -1412,13 +1412,13 @@ int msm_vidc_close(void *instance)
	}

	core = inst->core;
	mutex_lock(&core->sync_lock);
	mutex_lock(&core->lock);
	list_for_each_safe(ptr, next, &core->instances) {
		temp = list_entry(ptr, struct msm_vidc_inst, list);
		if (temp == inst)
			list_del(&inst->list);
	}
	mutex_unlock(&core->sync_lock);
	mutex_unlock(&core->lock);

	if (inst->session_type == MSM_VIDC_DECODER)
		msm_vdec_ctrl_deinit(inst);
+45 −38
Original line number Diff line number Diff line
@@ -133,6 +133,7 @@ static int msm_comm_get_load(struct msm_vidc_core *core,
		return -EINVAL;
	}

	mutex_lock(&core->lock);
	list_for_each_entry(inst, &core->instances, list) {
		if (inst->session_type != type)
			continue;
@@ -141,6 +142,7 @@ static int msm_comm_get_load(struct msm_vidc_core *core,
		num_mbs_per_sec += msm_comm_get_inst_load(inst, quirks);
		mutex_unlock(&inst->lock);
	}
	mutex_unlock(&core->lock);

	return num_mbs_per_sec;
}
@@ -235,6 +237,7 @@ static int msm_comm_vote_bus(struct msm_vidc_core *core)
		return -EINVAL;
	}

	mutex_lock(&core->lock);
	list_for_each_entry(inst, &core->instances, list) {
		++vote_data_count;
	}
@@ -243,7 +246,8 @@ static int msm_comm_vote_bus(struct msm_vidc_core *core)
			GFP_TEMPORARY);
	if (!vote_data) {
		dprintk(VIDC_ERR, "%s: failed to allocate memory\n", __func__);
		return -ENOMEM;
		rc = -ENOMEM;
		goto fail_alloc;
	}

	list_for_each_entry(inst, &core->instances, list) {
@@ -265,6 +269,7 @@ static int msm_comm_vote_bus(struct msm_vidc_core *core)

		i++;
	}
	mutex_unlock(&core->lock);

	rc = call_hfi_op(hdev, vote_bus, hdev->hfi_device_data, vote_data,
			vote_data_count);
@@ -273,6 +278,10 @@ static int msm_comm_vote_bus(struct msm_vidc_core *core)

	kfree(vote_data);
	return rc;

fail_alloc:
	mutex_unlock(&core->lock);
	return rc;
}

static void msm_comm_unvote_buses(struct msm_vidc_core *core)
@@ -1013,13 +1022,12 @@ void hw_sys_error_handler(struct work_struct *work)
	core = handler->core;
	hdev = core->device;

	mutex_lock(&core->sync_lock);
	mutex_lock(&core->lock);
	/*
	* Restart the firmware to bring out of bad state.
	*/
	if ((core->state == VIDC_CORE_INVALID) &&
		hdev->resurrect_fw) {
		mutex_lock(&core->lock);
		rc = call_hfi_op(hdev, resurrect_fw,
				hdev->hfi_device_data);
		if (rc) {
@@ -1028,12 +1036,11 @@ void hw_sys_error_handler(struct work_struct *work)
				__func__, rc);
		}
		core->state = VIDC_CORE_LOADED;
		mutex_unlock(&core->lock);
	} else {
		dprintk(VIDC_DBG,
			"fw unloaded after sys error, no need to resurrect\n");
	}
	mutex_unlock(&core->sync_lock);
	mutex_unlock(&core->lock);

exit:
	/* free sys error handler, allocated in handle_sys_err */
@@ -1066,14 +1073,11 @@ static void handle_sys_error(enum command_response cmd, void *data)
	dprintk(VIDC_WARN, "SYS_ERROR %d received for core %p\n", cmd, core);
	mutex_lock(&core->lock);
	core->state = VIDC_CORE_INVALID;
	mutex_unlock(&core->lock);


	/*
	* 1. Delete each instance session from hfi list
	* 2. Notify all clients about hardware error.
	*/
	mutex_lock(&core->sync_lock);
	list_for_each_entry(inst, &core->instances,
			list) {
		mutex_lock(&inst->lock);
@@ -1095,7 +1099,7 @@ static void handle_sys_error(enum command_response cmd, void *data)
		msm_vidc_queue_v4l2_event(inst,
				V4L2_EVENT_MSM_VIDC_SYS_ERROR);
	}
	mutex_unlock(&core->sync_lock);
	mutex_unlock(&core->lock);


	handler = kzalloc(sizeof(*handler), GFP_KERNEL);
@@ -1720,7 +1724,7 @@ static int msm_comm_init_core_done(struct msm_vidc_inst *inst)
{
	struct msm_vidc_core *core = inst->core;
	int rc = 0;
	mutex_lock(&core->sync_lock);
	mutex_lock(&core->lock);
	if (core->state >= VIDC_CORE_INIT_DONE) {
		dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
				core->id, core->state);
@@ -1736,16 +1740,14 @@ static int msm_comm_init_core_done(struct msm_vidc_inst *inst)
		rc = -EIO;
		goto exit;
	} else {
		mutex_lock(&core->lock);
		core->state = VIDC_CORE_INIT_DONE;
		mutex_unlock(&core->lock);
	}
	dprintk(VIDC_DBG, "SYS_INIT_DONE!!!\n");
core_already_inited:
	change_inst_state(inst, MSM_VIDC_CORE_INIT_DONE);
	rc = 0;
exit:
	mutex_unlock(&core->sync_lock);
	mutex_unlock(&core->lock);
	return rc;
}

@@ -1759,12 +1761,13 @@ static int msm_comm_init_core(struct msm_vidc_inst *inst)
		return -EINVAL;
	hdev = core->device;

	mutex_lock(&core->sync_lock);
	mutex_lock(&core->lock);
	if (core->state >= VIDC_CORE_INIT) {
		dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
				core->id, core->state);
		goto core_already_inited;
	}
	mutex_unlock(&core->lock);

	rc = msm_comm_vote_bus(core);
	if (rc) {
@@ -1772,13 +1775,16 @@ static int msm_comm_init_core(struct msm_vidc_inst *inst)
		goto fail_vote_bus;
	}

	mutex_lock(&core->lock);
	if (core->state < VIDC_CORE_LOADED) {
		rc = call_hfi_op(hdev, load_fw, hdev->hfi_device_data);
		if (rc) {
			dprintk(VIDC_ERR, "Failed to load video firmware\n");
			goto fail_load_fw;
		}
		core->state = VIDC_CORE_LOADED;
	}
	mutex_unlock(&core->lock);

	rc = msm_comm_scale_clocks(core);
	if (rc) {
@@ -1786,25 +1792,29 @@ static int msm_comm_init_core(struct msm_vidc_inst *inst)
		goto fail_core_init;
	}

	init_completion(&core->completions[SYS_MSG_INDEX(SYS_INIT_DONE)]);
	mutex_lock(&core->lock);
	if (core->state == VIDC_CORE_LOADED) {
		init_completion(&core->completions
			[SYS_MSG_INDEX(SYS_INIT_DONE)]);
		rc = call_hfi_op(hdev, core_init, hdev->hfi_device_data);
		if (rc) {
		dprintk(VIDC_ERR, "Failed to init core, id = %d\n", core->id);
			dprintk(VIDC_ERR, "Failed to init core, id = %d\n",
				core->id);
			goto fail_core_init;
		}
	mutex_lock(&core->lock);
		core->state = VIDC_CORE_INIT;
	mutex_unlock(&core->lock);
	}

core_already_inited:
	change_inst_state(inst, MSM_VIDC_CORE_INIT);
	mutex_unlock(&core->sync_lock);
	mutex_unlock(&core->lock);
	return rc;
fail_core_init:
	call_hfi_op(hdev, unload_fw, hdev->hfi_device_data);
fail_load_fw:
	msm_comm_unvote_buses(core);
fail_vote_bus:
	mutex_unlock(&core->sync_lock);
	mutex_unlock(&core->lock);
	return rc;
}

@@ -1822,14 +1832,17 @@ static int msm_vidc_deinit_core(struct msm_vidc_inst *inst)
	core = inst->core;
	hdev = core->device;

	mutex_lock(&core->sync_lock);
	mutex_lock(&core->lock);
	if (core->state == VIDC_CORE_UNINIT) {
		dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
				core->id, core->state);
		goto core_already_uninited;
	}
	mutex_unlock(&core->lock);

	msm_comm_scale_clocks_and_bus(inst);

	mutex_lock(&core->lock);
	if (list_empty(&core->instances)) {
		if (core->state > VIDC_CORE_INIT) {
			if (core->resources.ocmem_size) {
@@ -1848,9 +1861,9 @@ static int msm_vidc_deinit_core(struct msm_vidc_inst *inst)
				goto exit;
			}
		}
		mutex_lock(&core->lock);

		core->state = VIDC_CORE_UNINIT;
		mutex_unlock(&core->lock);

		call_hfi_op(hdev, unload_fw, hdev->hfi_device_data);
		msm_comm_unvote_buses(core);
	}
@@ -1858,7 +1871,7 @@ static int msm_vidc_deinit_core(struct msm_vidc_inst *inst)
core_already_uninited:
	change_inst_state(inst, MSM_VIDC_CORE_UNINIT);
exit:
	mutex_unlock(&core->sync_lock);
	mutex_unlock(&core->lock);
	return rc;
}

@@ -1920,6 +1933,7 @@ static void msm_vidc_print_running_insts(struct msm_vidc_core *core)
	dprintk(VIDC_ERR, "%4s|%4s|%4s|%4s|%4s\n",
			"type", "w", "h", "fps", "prop");

	mutex_lock(&core->lock);
	list_for_each_entry(temp, &core->instances, list) {
		mutex_lock(&temp->lock);
		if (temp->state >= MSM_VIDC_OPEN_DONE &&
@@ -1940,6 +1954,7 @@ static void msm_vidc_print_running_insts(struct msm_vidc_core *core)
		}
		mutex_unlock(&temp->lock);
	}
	mutex_unlock(&core->lock);
}

static int msm_vidc_load_resources(int flipped_state,
@@ -1971,11 +1986,9 @@ static int msm_vidc_load_resources(int flipped_state,
		return -EINVAL;
	}

	mutex_lock(&core->sync_lock);
	num_mbs_per_sec =
		msm_comm_get_load(core, MSM_VIDC_DECODER, quirks) +
		msm_comm_get_load(core, MSM_VIDC_ENCODER, quirks);
	mutex_unlock(&core->sync_lock);

	if (num_mbs_per_sec > core->resources.max_load) {
		dprintk(VIDC_ERR, "HW is overloaded, needed: %d max: %d\n",
@@ -1993,19 +2006,17 @@ static int msm_vidc_load_resources(int flipped_state,
		goto exit;
	}
	if (core->resources.ocmem_size) {
		mutex_lock(&core->sync_lock);
		height = max(inst->prop.height[CAPTURE_PORT],
			inst->prop.height[OUTPUT_PORT]);
		width = max(inst->prop.width[CAPTURE_PORT],
			inst->prop.width[OUTPUT_PORT]);
		rc = msm_comm_vote_bus(core);
		mutex_unlock(&core->sync_lock);
		if (!rc) {
			mutex_lock(&core->sync_lock);
			mutex_lock(&core->lock);
			rc = call_hfi_op(hdev, alloc_ocmem,
					hdev->hfi_device_data,
					core->resources.ocmem_size);
			mutex_unlock(&core->sync_lock);
			mutex_unlock(&core->lock);
			if (rc) {
				dprintk(VIDC_WARN,
				"Failed to allocate OCMEM. Performance will be impacted\n");
@@ -3531,20 +3542,16 @@ static int msm_vidc_load_supported(struct msm_vidc_inst *inst)
		LOAD_CALC_IGNORE_THUMBNAIL_LOAD;

	if (inst->state == MSM_VIDC_OPEN_DONE) {
		mutex_lock(&inst->core->sync_lock);
		num_mbs_per_sec = msm_comm_get_load(inst->core,
					MSM_VIDC_DECODER, quirks);
		num_mbs_per_sec += msm_comm_get_load(inst->core,
					MSM_VIDC_ENCODER, quirks);
		mutex_unlock(&inst->core->sync_lock);
		if (num_mbs_per_sec > inst->core->resources.max_load) {
			dprintk(VIDC_ERR,
				"H/W is overloaded. needed: %d max: %d\n",
				num_mbs_per_sec,
				inst->core->resources.max_load);
			mutex_lock(&inst->sync_lock);
			msm_vidc_print_running_insts(inst->core);
			mutex_unlock(&inst->sync_lock);
			return -EINVAL;
		}
	}
Loading