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

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

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

parents 99d5011c b9d7ebb0
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");
	}
@@ -2940,12 +2981,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",