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

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

Merge "msm: camera2: cpp: Added protection for Timeout processing."

parents db1c6802 aea138d2
Loading
Loading
Loading
Loading
+46 −90
Original line number Diff line number Diff line
@@ -106,14 +106,12 @@ struct msm_cpp_timer_data_t {
};

struct msm_cpp_timer_t {
	uint8_t used;
	atomic_t used;
	struct msm_cpp_timer_data_t data;
	struct timer_list cpp_timer;
};

struct msm_cpp_timer_t cpp_timers[2];
static int del_timer_idx;
static int set_timer_idx;
struct msm_cpp_timer_t cpp_timer;

static void msm_queue_init(struct msm_device_queue *queue, const char *name)
{
@@ -611,24 +609,20 @@ void msm_cpp_do_tasklet(unsigned long data)
				if (msg_id == MSM_CPP_MSG_ID_FRAME_ACK) {
					CPP_DBG("Frame done!!\n");
					/* delete CPP timer */
					CPP_DBG("delete timer %d.\n",
						del_timer_idx);
					timer = &cpp_timers[del_timer_idx];
					CPP_DBG("delete timer.\n");
					timer = &cpp_timer;
					atomic_set(&timer->used, 0);
					del_timer(&timer->cpp_timer);
					timer->used = 0;
					timer->data.processed_frame = NULL;
					del_timer_idx = 1 - del_timer_idx;
					msm_cpp_notify_frame_done(cpp_dev);
				} else if (msg_id ==
					MSM_CPP_MSG_ID_FRAME_NACK) {
					pr_err("NACK error from hw!!\n");
					CPP_DBG("delete timer %d.\n",
						del_timer_idx);
					timer = &cpp_timers[del_timer_idx];
					CPP_DBG("delete timer.\n");
					timer = &cpp_timer;
					atomic_set(&timer->used, 0);
					del_timer(&timer->cpp_timer);
					timer->used = 0;
					timer->data.processed_frame = NULL;
					del_timer_idx = 1 - del_timer_idx;
					msm_cpp_notify_frame_done(cpp_dev);
				}
				i += cmd_len + 2;
@@ -1108,95 +1102,61 @@ static void msm_cpp_do_timeout_work(struct work_struct *work)
{
	int ret;
	uint32_t i = 0;
	struct msm_cpp_frame_info_t *this_frame =
		cpp_timers[del_timer_idx].data.processed_frame;
	struct msm_cpp_frame_info_t *second_frame = NULL;

	pr_err("cpp_timer_callback called idx:%d. (jiffies=%lu)\n",
		del_timer_idx, jiffies);
	if (!work || !this_frame) {
		pr_err("Invalid work:%p, this_frame:%p, del_idx:%d\n",
			work, this_frame, del_timer_idx);
	struct msm_cpp_frame_info_t *this_frame = NULL;

	pr_err("cpp_timer_callback called. (jiffies=%lu)\n",
		jiffies);
	if (!work) {
		pr_err("Invalid work:%p\n", work);
		return;
	}
	pr_err("fatal: cpp_timer expired for identity=0x%x, frame_id=%03d",
		this_frame->identity, this_frame->frame_id);
	cpp_timers[del_timer_idx].used = 0;
	cpp_timers[del_timer_idx].data.processed_frame = NULL;
	del_timer_idx = 1 - del_timer_idx;

	if (cpp_timers[del_timer_idx].used == 1) {
		pr_err("deleting cpp_timer %d.\n", del_timer_idx);
		del_timer(&cpp_timers[del_timer_idx].cpp_timer);
		cpp_timers[del_timer_idx].used = 0;
		second_frame = cpp_timers[del_timer_idx].data.processed_frame;
		cpp_timers[del_timer_idx].data.processed_frame = NULL;
		del_timer_idx = 1 - del_timer_idx;
	if (!atomic_read(&cpp_timer.used)) {
		pr_err("Delayed trigger, IRQ serviced\n");
		return;
	}

	disable_irq(cpp_timers[del_timer_idx].data.cpp_dev->irq->start);
	disable_irq(cpp_timer.data.cpp_dev->irq->start);
	pr_err("Reloading firmware\n");
	cpp_load_fw(cpp_timers[del_timer_idx].data.cpp_dev, NULL);
	cpp_load_fw(cpp_timer.data.cpp_dev, NULL);
	pr_err("Firmware loading done\n");
	enable_irq(cpp_timers[del_timer_idx].data.cpp_dev->irq->start);
	msm_camera_io_w_mb(0x8, cpp_timers[del_timer_idx].data.cpp_dev->base +
	enable_irq(cpp_timer.data.cpp_dev->irq->start);
	msm_camera_io_w_mb(0x8, cpp_timer.data.cpp_dev->base +
		MSM_CPP_MICRO_IRQGEN_MASK);
	msm_camera_io_w_mb(0xFFFF,
		cpp_timers[del_timer_idx].data.cpp_dev->base +
		cpp_timer.data.cpp_dev->base +
		MSM_CPP_MICRO_IRQGEN_CLR);

	cpp_timers[set_timer_idx].data.processed_frame = this_frame;
	cpp_timers[set_timer_idx].used = 1;
	pr_err("ReInstalling cpp_timer %d\n", set_timer_idx);
	setup_timer(&cpp_timers[set_timer_idx].cpp_timer, cpp_timer_callback,
		(unsigned long)&cpp_timers[0]);
	if (!atomic_read(&cpp_timer.used)) {
		pr_err("Delayed trigger, IRQ serviced\n");
		return;
	}

	this_frame = cpp_timer.data.processed_frame;
	pr_err("ReInstalling cpp_timer\n");
	setup_timer(&cpp_timer.cpp_timer, cpp_timer_callback,
		(unsigned long)&cpp_timer);
	pr_err("Starting timer to fire in %d ms. (jiffies=%lu)\n",
		CPP_CMD_TIMEOUT_MS, jiffies);
	ret = mod_timer(&cpp_timers[set_timer_idx].cpp_timer,
	ret = mod_timer(&cpp_timer.cpp_timer,
		jiffies + msecs_to_jiffies(CPP_CMD_TIMEOUT_MS));
	if (ret)
		pr_err("error in mod_timer\n");

	set_timer_idx = 1 - set_timer_idx;
	pr_err("Rescheduling for identity=0x%x, frame_id=%03d",
	pr_err("Rescheduling for identity=0x%x, frame_id=%03d\n",
		this_frame->identity, this_frame->frame_id);
	msm_cpp_write(0x6, cpp_timers[set_timer_idx].data.cpp_dev->base);
	msm_cpp_write(0x6, cpp_timer.data.cpp_dev->base);
	msm_cpp_dump_frame_cmd(this_frame);
	for (i = 0; i < this_frame->msg_len; i++)
		msm_cpp_write(this_frame->cpp_cmd_msg[i],
			cpp_timers[set_timer_idx].data.cpp_dev->base);


	if (second_frame != NULL) {
		cpp_timers[set_timer_idx].data.processed_frame = second_frame;
		cpp_timers[set_timer_idx].used = 1;
		pr_err("ReInstalling cpp_timer %d\n", set_timer_idx);
		setup_timer(&cpp_timers[set_timer_idx].cpp_timer,
			cpp_timer_callback, (unsigned long)&cpp_timers[0]);
		pr_err("Starting timer to fire in %d ms. (jiffies=%lu)\n",
			CPP_CMD_TIMEOUT_MS, jiffies);
		ret = mod_timer(&cpp_timers[set_timer_idx].cpp_timer,
			jiffies + msecs_to_jiffies(CPP_CMD_TIMEOUT_MS));
		if (ret)
			pr_err("error in mod_timer\n");

		set_timer_idx = 1 - set_timer_idx;
		pr_err("Rescheduling for identity=0x%x, frame_id=%03d",
			second_frame->identity, second_frame->frame_id);
		msm_cpp_write(0x6,
			cpp_timers[set_timer_idx].data.cpp_dev->base);
		msm_cpp_dump_frame_cmd(second_frame);
		for (i = 0; i < second_frame->msg_len; i++)
			msm_cpp_write(second_frame->cpp_cmd_msg[i],
				cpp_timers[set_timer_idx].data.cpp_dev->base);
	}
			cpp_timer.data.cpp_dev->base);
	return;
}

void cpp_timer_callback(unsigned long data)
{
	struct msm_cpp_work_t *work =
		cpp_timers[set_timer_idx].data.cpp_dev->work;
	queue_work(cpp_timers[set_timer_idx].data.cpp_dev->timer_wq,
		cpp_timer.data.cpp_dev->work;
	queue_work(cpp_timer.data.cpp_dev->timer_wq,
		(struct work_struct *)work);
}

@@ -1213,21 +1173,19 @@ static int msm_cpp_send_frame_to_hardware(struct cpp_device *cpp_dev,
		msm_enqueue(&cpp_dev->processing_q,
					&frame_qcmd->list_frame);

		cpp_timers[set_timer_idx].data.processed_frame = process_frame;
		cpp_timers[set_timer_idx].used = 1;
		cpp_timer.data.processed_frame = process_frame;
		atomic_set(&cpp_timer.used, 1);
		/* install timer for cpp timeout */
		CPP_DBG("Installing cpp_timer %d\n", set_timer_idx);
		setup_timer(&cpp_timers[set_timer_idx].cpp_timer,
			cpp_timer_callback, (unsigned long)&cpp_timers[0]);
		CPP_DBG("Installing cpp_timer\n");
		setup_timer(&cpp_timer.cpp_timer,
			cpp_timer_callback, (unsigned long)&cpp_timer);
		CPP_DBG("Starting timer to fire in %d ms. (jiffies=%lu)\n",
			CPP_CMD_TIMEOUT_MS, jiffies);
		ret = mod_timer(&cpp_timers[set_timer_idx].cpp_timer,
		ret = mod_timer(&cpp_timer.cpp_timer,
			jiffies + msecs_to_jiffies(CPP_CMD_TIMEOUT_MS));
		if (ret)
			pr_err("error in mod_timer\n");

		set_timer_idx = 1 - set_timer_idx;

		msm_cpp_write(0x6, cpp_dev->base);
		msm_cpp_dump_frame_cmd(process_frame);
		for (i = 0; i < process_frame->msg_len; i++) {
@@ -2062,10 +2020,8 @@ static int cpp_probe(struct platform_device *pdev)
	INIT_WORK((struct work_struct *)cpp_dev->work, msm_cpp_do_timeout_work);
	cpp_dev->cpp_open_cnt = 0;
	cpp_dev->is_firmware_loaded = 0;
	cpp_timers[0].data.cpp_dev = cpp_dev;
	cpp_timers[1].data.cpp_dev = cpp_dev;
	cpp_timers[0].used = 0;
	cpp_timers[1].used = 0;
	cpp_timer.data.cpp_dev = cpp_dev;
	atomic_set(&cpp_timer.used, 0);
	cpp_dev->fw_name_bin = NULL;
	if (rc == 0)
		CPP_DBG("SUCCESS.");