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

Commit b9d7ebb0 authored by Krishnankutty Kolathappilly's avatar Krishnankutty Kolathappilly
Browse files

msm: cpp: Reset vbif and load firmware on poll failures



CPP poll failure can happen if vbif reset is not proper. Reset vbif
and load firmware on poll failures to recover from error scenario.

CRs-Fixed: 1098549
Change-Id: I38ef1c9478450c98c8379d8b1c085b31209cb48e
Signed-off-by: default avatarKrishnankutty Kolathappilly <kkolatha@codeaurora.org>
parent 64de89c6
Loading
Loading
Loading
Loading
+66 −22
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ static void msm_cpp_flush_queue_and_release_buffer(struct cpp_device *cpp_dev,
static int msm_cpp_dump_frame_cmd(struct msm_cpp_frame_info_t *frame_info);
static int msm_cpp_dump_addr(struct cpp_device *cpp_dev,
	struct msm_cpp_frame_info_t *frame_info);
static int32_t msm_cpp_reset_vbif_and_load_fw(struct cpp_device *cpp_dev);

#if CONFIG_MSM_CPP_DBG
#define CPP_DBG(fmt, args...) pr_err(fmt, ##args)
@@ -750,6 +751,7 @@ static void msm_cpp_iommu_fault_handler(struct iommu_domain *domain,
	struct msm_cpp_frame_info_t *processed_frame[MAX_CPP_PROCESSING_FRAME];
	int32_t i = 0, queue_len = 0;
	struct msm_device_queue *queue = NULL;
	int32_t rc = 0;

	if (token) {
		cpp_dev = token;
@@ -760,7 +762,16 @@ static void msm_cpp_iommu_fault_handler(struct iommu_domain *domain,
		}
		mutex_lock(&cpp_dev->mutex);
		tasklet_kill(&cpp_dev->cpp_tasklet);
		cpp_load_fw(cpp_dev, cpp_dev->fw_name_bin);
		rc = cpp_load_fw(cpp_dev, cpp_dev->fw_name_bin);
		if (rc < 0) {
			pr_err("load fw failure %d-retry\n", rc);
			rc = msm_cpp_reset_vbif_and_load_fw(cpp_dev);
			if (rc < 0) {
				msm_cpp_set_micro_irq_mask(cpp_dev, 1, 0x8);
				mutex_unlock(&cpp_dev->mutex);
				return;
			}
		}
		queue = &cpp_timer.data.cpp_dev->processing_q;
		queue_len = queue->len;
		if (!queue_len) {
@@ -1014,11 +1025,16 @@ static int cpp_init_hardware(struct cpp_device *cpp_dev)
	if (cpp_dev->fw_name_bin) {
		msm_camera_enable_irq(cpp_dev->irq, false);
		rc = cpp_load_fw(cpp_dev, cpp_dev->fw_name_bin);
		msm_camera_enable_irq(cpp_dev->irq, true);
		if (rc < 0) {
			pr_err("%s: load firmware failure %d\n", __func__, rc);
			pr_err("%s: load firmware failure %d-retry\n",
				__func__, rc);
			rc = msm_cpp_reset_vbif_and_load_fw(cpp_dev);
			if (rc < 0) {
				msm_camera_enable_irq(cpp_dev->irq, true);
				goto pwr_collapse_reset;
			}
		}
		msm_camera_enable_irq(cpp_dev->irq, true);
		msm_camera_io_w_mb(0x7C8, cpp_dev->base +
			MSM_CPP_MICRO_IRQGEN_MASK);
		msm_camera_io_w_mb(0xFFFF, cpp_dev->base +
@@ -1030,6 +1046,7 @@ static int cpp_init_hardware(struct cpp_device *cpp_dev)

pwr_collapse_reset:
	msm_cpp_update_gdscr_status(cpp_dev, false);
	msm_camera_unregister_irq(cpp_dev->pdev, cpp_dev->irq, cpp_dev);
req_irq_fail:
	msm_camera_clk_enable(&cpp_dev->pdev->dev, cpp_dev->clk_info,
		cpp_dev->cpp_clk, cpp_dev->num_clks, false);
@@ -1194,6 +1211,34 @@ end:
	return rc;
}

int32_t msm_cpp_reset_vbif_clients(struct cpp_device *cpp_dev)
{
	uint32_t i;

	pr_warn("%s: handle vbif hang...\n", __func__);
	for (i = 0; i < VBIF_CLIENT_MAX; i++) {
		if (cpp_dev->vbif_data->err_handler[i] == NULL)
			continue;

		cpp_dev->vbif_data->err_handler[i](
			cpp_dev->vbif_data->dev[i], CPP_VBIF_ERROR_HANG);
	}
	return 0;
}

int32_t msm_cpp_reset_vbif_and_load_fw(struct cpp_device *cpp_dev)
{
	int32_t rc = 0;

	msm_cpp_reset_vbif_clients(cpp_dev);

	rc = cpp_load_fw(cpp_dev, cpp_dev->fw_name_bin);
	if (rc < 0)
		pr_err("Reset and load fw failed %d\n", rc);

	return rc;
}

int cpp_vbif_error_handler(void *dev, uint32_t vbif_error)
{
	struct cpp_device *cpp_dev = NULL;
@@ -1259,6 +1304,10 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)

	CPP_DBG("open %d %pK\n", i, &fh->vfh);
	cpp_dev->cpp_open_cnt++;

	msm_cpp_vbif_register_error_handler(cpp_dev,
		VBIF_CLIENT_CPP, cpp_vbif_error_handler);

	if (cpp_dev->cpp_open_cnt == 1) {
		rc = cpp_init_hardware(cpp_dev);
		if (rc < 0) {
@@ -1281,9 +1330,6 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
		cpp_dev->state = CPP_STATE_IDLE;
	}

	msm_cpp_vbif_register_error_handler(cpp_dev,
		VBIF_CLIENT_CPP, cpp_vbif_error_handler);

	mutex_unlock(&cpp_dev->mutex);
	return 0;
}
@@ -1632,21 +1678,16 @@ static void msm_cpp_do_timeout_work(struct work_struct *work)
		goto end;
	}

	pr_err("%s: handle vbif hang...\n", __func__);
	for (i = 0; i < VBIF_CLIENT_MAX; i++) {
		if (cpp_dev->vbif_data->err_handler[i] == NULL)
			continue;

		cpp_dev->vbif_data->err_handler[i](
			cpp_dev->vbif_data->dev[i], CPP_VBIF_ERROR_HANG);
	}

	pr_debug("Reloading firmware %d\n", queue_len);
	rc = cpp_load_fw(cpp_timer.data.cpp_dev,
		cpp_timer.data.cpp_dev->fw_name_bin);
	if (rc) {
		pr_warn("Firmware loading failed\n");
		pr_warn("Firmware loading failed-retry\n");
		rc = msm_cpp_reset_vbif_and_load_fw(cpp_dev);
		if (rc < 0) {
			pr_err("Firmware loading failed\n");
			goto error;
		}
	} else {
		pr_debug("Firmware loading done\n");
	}
@@ -2932,12 +2973,15 @@ long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd,
			msm_camera_enable_irq(cpp_dev->irq, false);
			rc = cpp_load_fw(cpp_dev, cpp_dev->fw_name_bin);
			if (rc < 0) {
				pr_err("%s: load firmware failure %d\n",
				pr_err("%s: load firmware failure %d-retry\n",
					__func__, rc);
				rc = msm_cpp_reset_vbif_and_load_fw(cpp_dev);
				if (rc < 0) {
					enable_irq(cpp_dev->irq->start);
					mutex_unlock(&cpp_dev->mutex);
					return rc;
				}
			}
			rc = msm_cpp_fw_version(cpp_dev);
			if (rc < 0) {
				pr_err("%s: get firmware failure %d\n",