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

Commit bd375fb3 authored by George Shen's avatar George Shen
Browse files

msm: cvp: Fix reported cvp reliability issue



Fixed coding problems reported by static analysis and
improve driver stability and debugability.

Change-Id: I1c52533948cfff5174a8ccc1f7a27c6472dbf9b4
Signed-off-by: default avatarGeorge Shen <sqiao@codeaurora.org>
parent 976a7fa9
Loading
Loading
Loading
Loading
+95 −70
Original line number Diff line number Diff line
@@ -238,8 +238,6 @@ const struct msm_cvp_hfi_defs cvp_hfi_defs[] = {

};

static struct cvp_hal_device_data hal_ctxt;

struct cvp_tzbsp_memprot {
	u32 cp_start;
	u32 cp_size;
@@ -1382,6 +1380,30 @@ static int iris_hfi_suspend(void *dev)
	return rc;
}

static void cvp_dump_csr(struct iris_hfi_device *dev)
{
	u32 reg;

	if (!dev)
		return;
	reg = __read_register(dev, CVP_WRAPPER_CPU_STATUS);
	dprintk(CVP_ERR, "CVP_WRAPPER_CPU_STATUS: %x\n", reg);
	reg = __read_register(dev, CVP_CPU_CS_SCIACMDARG0);
	dprintk(CVP_ERR, "CVP_CPU_CS_SCIACMDARG0: %x\n", reg);
	reg = __read_register(dev, CVP_WRAPPER_CPU_CLOCK_CONFIG);
	dprintk(CVP_ERR, "CVP_WRAPPER_CPU_CLOCK_CONFIG: %x\n", reg);
	reg = __read_register(dev, CVP_WRAPPER_INTR_STATUS);
	dprintk(CVP_ERR, "CVP_WRAPPER_INTR_STATUS: %x\n", reg);
	reg = __read_register(dev, CVP_CPU_CS_H2ASOFTINT);
	dprintk(CVP_ERR, "CVP_CPU_CS_H2ASOFTINT: %x\n", reg);
	reg = __read_register(dev, CVP_CPU_CS_A2HSOFTINT);
	dprintk(CVP_ERR, "CVP_CPU_CS_A2HSOFTINT: %x\n", reg);
	reg = __read_register(dev, CVP_CC_MVS0C_GDSCR);
	dprintk(CVP_ERR, "CVP_CC_MVS0C_GDSCR: %x\n", reg);
	reg = __read_register(dev, CVP_CC_MVS1C_GDSCR);
	dprintk(CVP_ERR, "CVP_CC_MVS1C_GDSCR: %x\n", reg);
}

static int iris_hfi_flush_debug_queue(void *dev)
{
	int rc = 0;
@@ -1392,6 +1414,7 @@ static int iris_hfi_flush_debug_queue(void *dev)
		return -EINVAL;
	}

	cvp_dump_csr(device);
	mutex_lock(&device->lock);

	if (!device->power_enabled) {
@@ -2653,24 +2676,22 @@ static int iris_hfi_session_send(void *sess,
	return rc;
}

static int __check_core_registered(struct cvp_hal_device_data core,
static int __check_core_registered(struct iris_hfi_device *device,
		phys_addr_t fw_addr, u8 *reg_addr, u32 reg_size,
		phys_addr_t irq)
{
	struct iris_hfi_device *device;
	struct cvp_hal_data *cvp_hal_data;
	struct list_head *curr, *next;

	if (!core.dev_count) {
	if (!device) {
		dprintk(CVP_INFO, "no device Registered\n");
		return -EINVAL;
	}

	list_for_each_safe(curr, next, &core.dev_head) {
		device = list_entry(curr,
			struct iris_hfi_device, list);
	cvp_hal_data = device->cvp_hal_data;
		if (device && cvp_hal_data->irq == irq &&
	if (!cvp_hal_data)
		return -EINVAL;

	if (cvp_hal_data->irq == irq &&
		(CONTAINS(cvp_hal_data->firmware_base,
				FIRMWARE_SIZE, fw_addr) ||
		CONTAINS(fw_addr, FIRMWARE_SIZE,
@@ -2696,8 +2717,6 @@ static int __check_core_registered(struct cvp_hal_device_data core,
	dprintk(CVP_INFO, "Device not registered\n");
	return -EINVAL;
}
	return -EINVAL;
}

static void __process_fatal_error(
		struct iris_hfi_device *device)
@@ -2730,8 +2749,14 @@ static int __prepare_pc(struct iris_hfi_device *device)
static void iris_hfi_pm_handler(struct work_struct *work)
{
	int rc = 0;
	struct iris_hfi_device *device = list_first_entry(
			&hal_ctxt.dev_head, struct iris_hfi_device, list);
	struct msm_cvp_core *core;
	struct iris_hfi_device *device;

	core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
	if (core)
		device = core->device->hfi_device_data;
	else
		return;

	if (!device) {
		dprintk(CVP_ERR, "%s: NULL device\n", __func__);
@@ -2790,7 +2815,7 @@ static int __power_collapse(struct iris_hfi_device *device, bool force)
	u32 wfi_status = 0, idle_status = 0, pc_ready = 0;
	u32 flags = 0;
	int count = 0;
	const int max_tries = 10;
	const int max_tries = 150;

	if (!device) {
		dprintk(CVP_ERR, "%s: invalid params\n", __func__);
@@ -3234,11 +3259,17 @@ static int __response_handler(struct iris_hfi_device *device)

static void iris_hfi_core_work_handler(struct work_struct *work)
{
	struct iris_hfi_device *device = list_first_entry(
		&hal_ctxt.dev_head, struct iris_hfi_device, list);
	struct msm_cvp_core *core;
	struct iris_hfi_device *device;
	int num_responses = 0, i = 0;
	u32 intr_status;

	core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
	if (core)
		device = core->device->hfi_device_data;
	else
		return;

	mutex_lock(&device->lock);


@@ -3315,7 +3346,7 @@ static int __init_regs_and_interrupts(struct iris_hfi_device *device,
	struct cvp_hal_data *hal = NULL;
	int rc = 0;

	rc = __check_core_registered(hal_ctxt, res->firmware_base,
	rc = __check_core_registered(device, res->firmware_base,
			(u8 *)(uintptr_t)res->register_base,
			res->register_size, res->irq);
	if (!rc) {
@@ -4372,7 +4403,7 @@ static void power_off_iris2(struct iris_hfi_device *device)
				CVP_AON_WRAPPER_MVP_NOC_LPI_STATUS);
		reg_status = lpi_status & BIT(0);
		dprintk(CVP_DBG,
			"Noc: lpi_status %d noc_status %d (count %d)\n",
			"Noc: lpi_status %x noc_status %x (count %d)\n",
			lpi_status, reg_status, count);

		/* Wait for noc lpi status to be set */
@@ -4381,7 +4412,8 @@ static void power_off_iris2(struct iris_hfi_device *device)
	}
	if (count == max_count) {
		dprintk(CVP_WARN,
			"NOC not in qaccept status %d\n", reg_status);
			"NOC not in qaccept status %x %x\n",
			reg_status, lpi_status);
	}

	/* HPG 6.1.2 Step 3, debug bridge to low power */
@@ -4403,7 +4435,7 @@ static void power_off_iris2(struct iris_hfi_device *device)
	}
	if (count == max_count) {
		dprintk(CVP_WARN,
			"DBLP Set: status %d\n", reg_status);
			"DBLP Set: status %x %x\n", reg_status, lpi_status);
	}

	/* HPG 6.1.2 Step 4, debug bridge to lpi release */
@@ -4422,7 +4454,7 @@ static void power_off_iris2(struct iris_hfi_device *device)
	}
	if (count == max_count) {
		dprintk(CVP_WARN,
			"DBLP Release: lpi_status %d\n", lpi_status);
			"DBLP Release: lpi_status %x\n", lpi_status);
	}

	/* HPG 6.1.2 Step 6 */
@@ -4817,14 +4849,8 @@ static struct iris_hfi_device *__add_device(u32 device_id,
		goto err_cleanup;
	}

	if (!hal_ctxt.dev_count)
		INIT_LIST_HEAD(&hal_ctxt.dev_head);

	mutex_init(&hdevice->lock);
	INIT_LIST_HEAD(&hdevice->list);
	INIT_LIST_HEAD(&hdevice->sess_head);
	list_add_tail(&hdevice->list, &hal_ctxt.dev_head);
	hal_ctxt.dev_count++;

	return hdevice;

@@ -4854,30 +4880,29 @@ static struct iris_hfi_device *__get_device(u32 device_id,

void cvp_iris_hfi_delete_device(void *device)
{
	struct iris_hfi_device *close, *tmp, *dev;
	struct msm_cvp_core *core;
	struct iris_hfi_device *dev = NULL;

	if (!device)
		return;

	dev = (struct iris_hfi_device *) device;
	core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
	if (core)
		dev = core->device->hfi_device_data;

	if (!dev)
		return;

	list_for_each_entry_safe(close, tmp, &hal_ctxt.dev_head, list) {
		if (close->cvp_hal_data->irq == dev->cvp_hal_data->irq) {
			hal_ctxt.dev_count--;
			list_del(&close->list);
			mutex_destroy(&close->lock);
			destroy_workqueue(close->cvp_workq);
			destroy_workqueue(close->iris_pm_workq);
			free_irq(dev->cvp_hal_data->irq, close);
	mutex_destroy(&dev->lock);
	destroy_workqueue(dev->cvp_workq);
	destroy_workqueue(dev->iris_pm_workq);
	free_irq(dev->cvp_hal_data->irq, dev);
	iounmap(dev->cvp_hal_data->register_base);
	iounmap(dev->cvp_hal_data->gcc_reg_base);
			kfree(close->cvp_hal_data);
			kfree(close->response_pkt);
			kfree(close->raw_packet);
			kfree(close);
			break;
		}
	}
	kfree(dev->cvp_hal_data);
	kfree(dev->response_pkt);
	kfree(dev->raw_packet);
	kfree(dev);
}

static int iris_hfi_validate_session(void *sess, const char *func)
+1 −6
Original line number Diff line number Diff line
@@ -174,7 +174,7 @@ struct cvp_hfi_msg_sys_property_info_packet {
	u32 size;
	u32 packet_type;
	u32 num_properties;
	u32 rg_property_data[1];
	u32 rg_property_data[128];
};

enum session_flags {
@@ -188,11 +188,6 @@ struct cvp_hal_session {
	void *device;
};

struct cvp_hal_device_data {
	struct list_head dev_head;
	int dev_count;
};

struct msm_cvp_fw {
	void *cookie;
};
+4 −1
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@
#define CVP_WRAPPER_INTR_CLEAR_A2H_BMSK	0x4
#define CVP_WRAPPER_INTR_CLEAR_A2H_SHFT	0x2
#define CVP_WRAPPER_CPU_STATUS		(CVP_WRAPPER_TZ_BASE_OFFS + 0x10)
#define CVP_WRAPPER_CPU_CLOCK_CONFIG	(CVP_WRAPPER_TZ_BASE_OFFS + 0x0)
#define CVP_WRAPPER_CPU_CLOCK_CONFIG	(CVP_WRAPPER_TZ_BASE_OFFS + 0x50)
#define CVP_WRAPPER_CPU_CGC_DIS	(CVP_WRAPPER_BASE_OFFS + 0x2010)

#define CVP_WRAPPER_DEBUG_BRIDGE_LPI_CONTROL	(CVP_WRAPPER_BASE_OFFS + 0x54)
@@ -210,4 +210,7 @@
#define CVP_AON_WRAPPER_MVP_NOC_LPI_CONTROL	(CVP_AON_BASE_OFFS)
#define CVP_AON_WRAPPER_MVP_NOC_LPI_STATUS	(CVP_AON_BASE_OFFS + 0x4)

#define CVP_CC_BASE_OFFS			0x000F0000
#define CVP_CC_MVS0C_GDSCR			(CVP_CC_BASE_OFFS + 0xBF8)
#define CVP_CC_MVS1C_GDSCR			(CVP_CC_BASE_OFFS + 0xC98)
#endif
+7 −7
Original line number Diff line number Diff line
@@ -394,21 +394,21 @@ int cvp_create_pkt_cmd_session_send(
	if (!out_pkt || !in_pkt || !session)
		return -EINVAL;

	if (ptr->size > MAX_HFI_PKT_SIZE * sizeof(unsigned int))
		goto error_hfi_packet;

	if (ptr->session_id != hash32_ptr(session))
		goto error_hfi_packet;

	def_idx = get_pkt_index(ptr);
	if (def_idx < 0 && ptr->size < MAX_HFI_PKT_SIZE * sizeof(u32)) {
	if (def_idx < 0) {
		memcpy(out_pkt, in_pkt, ptr->size);
		return 0;
	}

	if (ptr->size > MAX_HFI_PKT_SIZE * sizeof(unsigned int))
		goto error_hfi_packet;

	if (cvp_hfi_defs[def_idx].type != ptr->packet_type)
		goto error_hfi_packet;

	if (ptr->session_id != hash32_ptr(session))
		goto error_hfi_packet;

	memcpy(out_pkt, in_pkt, ptr->size);

	return 0;
+22 −10
Original line number Diff line number Diff line
@@ -420,11 +420,13 @@ static struct msm_cvp_inst *cvp_get_inst_from_id(struct msm_cvp_core *core,
{
	struct msm_cvp_inst *inst = NULL;
	bool match = false;
	int count = 0;

	if (!core || !session_id)
		return NULL;

	mutex_lock(&core->lock);
retry:
	if (mutex_trylock(&core->lock)) {
		list_for_each_entry(inst, &core->instances, list) {
			if (hash32_ptr(inst->session) == session_id) {
				match = true;
@@ -434,6 +436,16 @@ static struct msm_cvp_inst *cvp_get_inst_from_id(struct msm_cvp_core *core,

		inst = match ? inst : NULL;
		mutex_unlock(&core->lock);
	} else {
		if (core->state == CVP_CORE_UNINIT)
			return NULL;
		usleep_range(100, 200);
		count++;
		if (count < 1000)
			goto retry;
		else
			dprintk(CVP_ERR, "timeout locking core mutex\n");
	}

	return inst;

@@ -677,9 +689,9 @@ static int hfi_process_sys_property_info(u32 device_id,
	if (!pkt) {
		dprintk(CVP_ERR, "%s: invalid param\n", __func__);
		return -EINVAL;
	} else if (pkt->size < sizeof(*pkt)) {
	} else if (pkt->size > sizeof(*pkt)) {
		dprintk(CVP_ERR,
				"%s: bad_pkt_size\n", __func__);
				"%s: bad_pkt_size %d\n", __func__, pkt->size);
		return -E2BIG;
	} else if (!pkt->num_properties) {
		dprintk(CVP_WARN,
Loading