コード例 #1
0
void cmdq_core_dump_secure_metadata(cmdqSecDataStruct *pSecData)
{
	uint32_t i = 0;
	cmdqSecAddrMetadataStruct *pAddr = NULL;

	if (NULL == pSecData) {
		return;
	}

	pAddr = (cmdqSecAddrMetadataStruct *)(CMDQ_U32_PTR(pSecData->addrMetadatas));

	CMDQ_LOG("========= pSecData: %p dump =========\n", pSecData);
	CMDQ_LOG("count:%d(%d), enginesNeedDAPC:0x%llx, enginesPortSecurity:0x%llx\n",
		pSecData->addrMetadataCount, pSecData->addrMetadataMaxCount,
		pSecData->enginesNeedDAPC, pSecData->enginesNeedPortSecurity);

	if (NULL == pAddr) {
		return;
	}

	for (i = 0; i < pSecData->addrMetadataCount; i++) {
		CMDQ_LOG("idx:%d, type:%d, baseHandle:%x, offset:%d, size:%d, port:%d\n",
			i, pAddr[i].type, pAddr[i].baseHandle, pAddr[i].offset, pAddr[i].size, pAddr[i].port);
	}
}
コード例 #2
0
int32_t cmdqRecDumpCommand(cmdqRecHandle handle)
{
	int32_t status = 0;
	struct TaskStruct *pTask = handle->pRunningTask;

	if (pTask) {
		/* running, so dump from core task direct */
		status = cmdqCoreDebugDumpCommand(pTask);
	} else {
		/* not running, dump from rec->pBuffer */
		const uint32_t *pCmd = NULL;
		static char textBuf[128] = { 0 };
		int i = 0;

		CMDQ_LOG("======REC 0x%p command buffer:\n", handle->pBuffer);
		print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 4,
			       handle->pBuffer, handle->blockSize, false);

		CMDQ_LOG("======REC 0x%p command buffer END\n", handle->pBuffer);
		CMDQ_LOG("REC 0x%p command buffer TRANSLATED:\n", handle->pBuffer);
		for (i = 0, pCmd = handle->pBuffer; i < handle->blockSize; i += 8, pCmd += 2) {
			cmdq_core_parse_instruction(pCmd, textBuf, 128);
			CMDQ_LOG("%s", textBuf);
		}
		CMDQ_LOG("======REC 0x%p command END\n", handle->pBuffer);

		return 0;
	}

	return status;
}
コード例 #3
0
void cmdq_core_enable_common_clock_locked_impl(bool enable)
{
#ifdef CMDQ_PWR_AWARE
	if (enable) {
		CMDQ_VERBOSE("[CLOCK] Enable SMI & LARB0 Clock\n");
		cmdq_dev_enable_clock_SMI_COMMON(enable);
		cmdq_dev_enable_clock_SMI_LARB0(enable);

		#if 0
		/* MT_CG_DISP0_MUTEX_32K is removed in this platform */
		CMDQ_LOG("[CLOCK] enable MT_CG_DISP0_MUTEX_32K\n");
		enable_clock(MT_CG_DISP0_MUTEX_32K, "CMDQ_MDP");
		#endif
	} else {
		CMDQ_VERBOSE("[CLOCK] Disable SMI & LARB0 Clock\n");
		/* disable, reverse the sequence */
		cmdq_dev_enable_clock_SMI_LARB0(enable);
		cmdq_dev_enable_clock_SMI_COMMON(enable);

		#if 0
		/* MT_CG_DISP0_MUTEX_32K is removed in this platform */
		CMDQ_LOG("[CLOCK] disable MT_CG_DISP0_MUTEX_32K\n");
		disable_clock(MT_CG_DISP0_MUTEX_32K, "CMDQ_MDP");
		#endif
	}
#endif /* CMDQ_PWR_AWARE */
}
コード例 #4
0
static void cmdq_driver_process_read_address_request(struct cmdqReadAddressStruct *req_user)
{
	/* create kernel-space buffer for working */
	uint32_t *addrs = NULL;
	uint32_t *values = NULL;
	dma_addr_t pa = 0;
	int i = 0;

	CMDQ_LOG("[READ_PA] cmdq_driver_process_read_address_request()\n");

	do {
		if (NULL == req_user ||
		    0 == req_user->count || NULL == CMDQ_U32_PTR(req_user->values)
		    || NULL == CMDQ_U32_PTR(req_user->dmaAddresses)) {
			CMDQ_ERR("[READ_PA] invalid req_user\n");
			break;
		}

		addrs = kcalloc(req_user->count, sizeof(uint32_t), GFP_KERNEL);
		if (NULL == addrs) {
			CMDQ_ERR("[READ_PA] fail to alloc addr buf\n");
			break;
		}

		values = kcalloc(req_user->count, sizeof(uint32_t), GFP_KERNEL);
		if (NULL == values) {
			CMDQ_ERR("[READ_PA] fail to alloc value buf\n");
			break;
		}
		/* copy from user */
		if (copy_from_user
		    (addrs, CMDQ_U32_PTR(req_user->dmaAddresses),
		     req_user->count * sizeof(uint32_t))) {
			CMDQ_ERR("[READ_PA] fail to copy user dmaAddresses\n");
			break;
		}
		/* actually read these PA write buffers */
		for (i = 0; i < req_user->count; ++i) {
			pa = (0xFFFFFFFF & addrs[i]);
			CMDQ_LOG("[READ_PA] req read dma address 0x%pa\n", &pa);
			values[i] = cmdqCoreReadWriteAddress(pa);
		}

		/* copy value to user */
		if (copy_to_user
		    (CMDQ_U32_PTR(req_user->values), values, req_user->count * sizeof(uint32_t))) {
			CMDQ_ERR("[READ_PA] fail to copy to user value buf\n");
			break;
		}

	} while (0);

	kfree(addrs);
	kfree(values);
}
コード例 #5
0
ファイル: cmdq_virtual.c プロジェクト: John677/Kernal_k3note
void cmdq_virtual_dump_gpr(void)
{
	int i = 0;
	long offset = 0;
	uint32_t value = 0;

	CMDQ_LOG("========= GPR dump =========\n");
	for (i = 0; i < 16; i++) {
		offset = CMDQ_GPR_R32(i);
		value = CMDQ_REG_GET32(offset);
		CMDQ_LOG("[GPR %2d]+0x%lx = 0x%08x\n", i, offset, value);
	}
	CMDQ_LOG("========= GPR dump =========\n");
}
コード例 #6
0
int32_t cmdqRecEstimateCommandExecTime(const cmdqRecHandle handle)
{
	int32_t time = 0;

	if (NULL == handle) {
		return -EFAULT;
	}

	CMDQ_LOG("======REC 0x%p command execution time ESTIMATE:\n", handle);
	time = cmdq_prof_estimate_command_exe_time(handle->pBuffer, handle->blockSize);
	CMDQ_LOG("======REC 0x%p  END\n", handle);

	return time;
}
コード例 #7
0
static int cmdq_sec_sectrace_transact(void)
{
	int status;

	CMDQ_LOG("[sectrace]-->transact\n");

	status = cmdq_sec_submit_to_secure_world_async_unlocked(
				CMD_CMDQ_TL_SECTRACE_TRANSACT,
				NULL, CMDQ_INVALID_THREAD,
				cmdq_sec_fill_iwc_command_sectrace_unlocked, NULL);

	CMDQ_LOG("[sectrace]<--transact: status: %d\n", status);

	return status;
}
コード例 #8
0
static int cmdq_sec_sectrace_map(void *va, size_t size)
{
	int status;
	enum mc_result mcRet;

	CMDQ_LOG("[sectrace]-->map: start, va:%p, size:%d\n", va, (int)size);

	status = 0;
	cmdq_sec_lock_secure_path();
	do {
		/* HACK: submit a dummy message to ensure secure path init done */
		status = cmdq_sec_submit_to_secure_world_async_unlocked(
			CMD_CMDQ_TL_TEST_HELLO_TL, NULL, CMDQ_INVALID_THREAD, NULL, NULL);

		/* map log buffer in NWd */
		mcRet = mc_map(&(gCmdqSecContextHandle->sessionHandle),
					va,
					(uint32_t)size,
					&gCmdqSectraceMappedInfo);
		if (MC_DRV_OK != mcRet) {
			CMDQ_ERR("[sectrace]map: failed in NWd, mc_map err: 0x%x\n", mcRet);
			status = -EFAULT;
			break;
		}

		CMDQ_LOG("[sectrace]map: mc_map sectrace buffer done, gCmdqSectraceMappedInfo(va:0x%08x, size:%d)\n",
			gCmdqSectraceMappedInfo.secure_virt_addr, gCmdqSectraceMappedInfo.secure_virt_len);

		/* ask secure CMDQ to map sectrace log buffer */
		status = cmdq_sec_submit_to_secure_world_async_unlocked(
					CMD_CMDQ_TL_SECTRACE_MAP,
					NULL, CMDQ_INVALID_THREAD,
					cmdq_sec_fill_iwc_command_sectrace_unlocked,
					NULL);
		if(0 > status) {
			CMDQ_ERR("[sectrace]map: failed in SWd: %d\n", status);
			mc_unmap(&(gCmdqSecContextHandle->sessionHandle), va, &gCmdqSectraceMappedInfo);
			status = -EFAULT;
			break;
		}
	} while(0);

	cmdq_sec_unlock_secure_path();

	CMDQ_LOG("[sectrace]<--map: status: %d\n", status);

	return status;
}
コード例 #9
0
int32_t cmdq_sec_sectrace_init(void)
{
#ifdef CMDQ_SECTRACE_SUPPORT
	int32_t status;
	const uint32_t CMDQ_SECTRACE_BUFFER_SIZE_KB = 64;
	union callback_func sectraceCB;

	/* use callback_tl_function becuase CMDQ use "TCI" for inter-world communication */
	sectraceCB.tl.map = cmdq_sec_sectrace_map;
	sectraceCB.tl.unmap = cmdq_sec_sectrace_unmap;
	sectraceCB.tl.transact = cmdq_sec_sectrace_transact;

	/* create sectrace entry in debug FS */
	status = init_sectrace("CMDQ_SEC",
		if_tci, /* use TCI for inter world communication */
		usage_tl_dr, /* print sectrace log for tl and driver */
		CMDQ_SECTRACE_BUFFER_SIZE_KB,
		&sectraceCB);

	CMDQ_LOG("cmdq_sec_trace_init, status:%d\n", status);
	return 0;
#else
	return 0;
#endif
}
コード例 #10
0
int32_t cmdq_sec_fill_iwc_command_sectrace_unlocked(int32_t iwcCommand, void *_pTask, int32_t thread, void *_pIwc)
{
	iwcCmdqMessage_t *pIwc;

	pIwc = (iwcCmdqMessage_t *)_pIwc;

	/* specify command id only, don't care other other */
	memset(pIwc, 0x0, sizeof(iwcCmdqMessage_t));
	pIwc->cmd = iwcCommand;

	switch (iwcCommand){
	case CMD_CMDQ_TL_SECTRACE_MAP:
		pIwc->sectracBuffer.addr = (uint32_t)(gCmdqSectraceMappedInfo.secure_virt_addr);
		pIwc->sectracBuffer.size = (gCmdqSectraceMappedInfo.secure_virt_len);
		break;
	case CMD_CMDQ_TL_SECTRACE_UNMAP:
	case CMD_CMDQ_TL_SECTRACE_TRANSACT:
	default:
		pIwc->sectracBuffer.addr = 0;
		pIwc->sectracBuffer.size = 0;
		break;
	}

	/* medatada: debug config */
	pIwc->debug.logLevel = (cmdq_core_should_print_msg()) ? (1) : (0);
	pIwc->debug.enableProfile = cmdq_core_profile_enabled();

	CMDQ_LOG("[sectrace]SESSION_MSG: iwcCommand:%d, msg(sectraceBuffer, addr:0x%x, size:%d)\n",
		iwcCommand, pIwc->sectracBuffer.addr, pIwc->sectracBuffer.size);

	return 0;
}
コード例 #11
0
/********************************************************************************
 * common part: for general projects
 *******************************************************************************/
int32_t cmdq_sec_create_shared_memory(cmdqSecSharedMemoryHandle *pHandle, const uint32_t size)
{
	cmdqSecSharedMemoryHandle handle = NULL;
	void *pVA = NULL;
	dma_addr_t PA = 0;

	handle = kzalloc(sizeof(uint8_t *) * sizeof(cmdqSecSharedMemoryStruct), GFP_KERNEL);
	if (NULL == handle) {
		return -ENOMEM;
	}

	CMDQ_LOG("%s\n", __func__);

	/* allocate non-cachable memory */
	pVA = cmdq_core_alloc_hw_buffer(
				cmdq_dev_get(), size, &PA, GFP_KERNEL);

	CMDQ_MSG("%s, MVA:%pa, pVA:%p, size:%d\n", __func__, &PA, pVA, size);

	if(NULL == pVA) {
		kfree(handle);
		return -ENOMEM;
	}

	/* update memory information */
	handle->size = size;
	handle->pVABase = pVA;
	handle->MVABase = PA;

	*pHandle = handle;

	return 0;
}
コード例 #12
0
void cmdq_dev_init(struct platform_device *pDevice)
{
	struct device_node *node = pDevice->dev.of_node;

	/* init cmdq device dependent data */
	do {
		memset(&gCmdqDev, 0x0, sizeof(CmdqDeviceStruct));

		gCmdqDev.pDev = &pDevice->dev;
#ifdef CMDQ_OF_SUPPORT
		gCmdqDev.regBaseVA = (unsigned long)of_iomap(node, 0);
		gCmdqDev.regBasePA = (0L | 0x10212000);
		gCmdqDev.irqId = irq_of_parse_and_map(node, 0);
		gCmdqDev.irqSecId = irq_of_parse_and_map(node, 1);
#else
		gCmdqDev.regBaseVA = (0L | GCE_BASE);
		gCmdqDev.regBasePA = (0L | 0x10212000);
		gCmdqDev.irqId = CQ_DMA_IRQ_BIT_ID;
		gCmdqDev.irqSecId = CQ_DMA_SEC_IRQ_BIT_ID;
#endif

		CMDQ_LOG
		    ("[CMDQ] platform_dev: dev: %p, PA: %lx, VA: %lx, irqId: %d,  irqSecId:%d\n",
		     gCmdqDev.pDev, gCmdqDev.regBasePA, gCmdqDev.regBaseVA, gCmdqDev.irqId,
		     gCmdqDev.irqSecId);
	} while (0);

	/* init module VA */
	cmdq_dev_init_module_base_VA();
}
コード例 #13
0
const long cmdq_dev_alloc_module_base_VA_by_name(const char *name)
{
	unsigned long VA;
	struct device_node *node = NULL;

	node = of_find_compatible_node(NULL, NULL, name);
	VA = (unsigned long)of_iomap(node, 0);
	CMDQ_LOG("DEV: VA(%s): 0x%lx\n", name, VA);

	return VA;
}
コード例 #14
0
void cmdq_dev_alloc_disp_module_PA_by_name(const char *name, int index, long *startPA, long *endPA)
{
	struct device_node *node = NULL;
	struct resource res;

	node = of_find_compatible_node(NULL, NULL, name);
	of_address_to_resource(node, index, &res);
	*startPA = res.start;
	*endPA = res.end;
	CMDQ_LOG("DEV: PA(%s): start = 0x%lx, end = 0x%lx\n", name, *startPA, *endPA);
}
コード例 #15
0
ファイル: cmdq_virtual.c プロジェクト: John677/Kernal_k3note
int cmdq_virtual_dump_smi(const int showSmiDump)
{
	int isSMIHang = 0;

#if defined(CMDQ_CONFIG_SMI) && !defined(CONFIG_MTK_FPGA)
	isSMIHang =
	    smi_debug_bus_hanging_detect_ext(SMI_DBG_DISPSYS | SMI_DBG_VDEC | SMI_DBG_IMGSYS |
					     SMI_DBG_VENC | SMI_DBG_MJC, showSmiDump, 1);
	CMDQ_ERR("SMI Hang? = %d\n", isSMIHang);
#else
	CMDQ_LOG("[WARNING]not enable SMI dump now\n");
#endif

	return isSMIHang;
}
コード例 #16
0
void cmdqSecEnableProfile(const bool enable)
{
#ifdef CMDQ_SECURE_PATH_SUPPORT
	CMDQ_LOG("[sectrace]enable profile %d\n", enable)

	mutex_lock(&gCmdqSecProfileLock);

	if (enable) {
		cmdq_sec_sectrace_init();
	} else {
		cmdq_sec_sectrace_deinit();
	}

	mutex_unlock(&gCmdqSecProfileLock);
#endif
}
コード例 #17
0
int cmdq_core_dump_smi(const int showSmiDump)
{
#if 0
	int isSMIHang = 0;
#ifndef CONFIG_MTK_FPGA
	/* isSMIHang = smi_debug_bus_hanging_detect(
						SMI_DBG_DISPSYS | SMI_DBG_VDEC | SMI_DBG_IMGSYS | SMI_DBG_VENC | SMI_DBG_MJC,
						showSmiDump); */
	isSMIHang = smi_debug_bus_hanging_detect_ext(
						SMI_DBG_DISPSYS | SMI_DBG_VDEC | SMI_DBG_IMGSYS | SMI_DBG_VENC | SMI_DBG_MJC,
						showSmiDump, 1);
	CMDQ_ERR("SMI Hang? = %d\n", isSMIHang);
#endif
	return isSMIHang;
#else
	CMDQ_LOG("[WARNING]not enable SMI dump now\n");
	return 0;
#endif
}
コード例 #18
0
int32_t cmdq_sec_fill_iwc_cancel_msg_unlocked(int32_t iwcCommand, void *_pTask, int32_t thread, void *_pIwc)
{
	const TaskStruct *pTask = (TaskStruct *)_pTask;
	iwcCmdqMessage_t *pIwc;

	pIwc = (iwcCmdqMessage_t *)_pIwc;
	memset(pIwc, 0x0, sizeof(iwcCmdqMessage_t));

	pIwc->cmd = iwcCommand;
	pIwc->cancelTask.waitCookie = pTask->secData.waitCookie;
	pIwc->cancelTask.thread = thread;

	/* medatada: debug config */
	pIwc->debug.logLevel = (cmdq_core_should_print_msg()) ? (1) : (0);
	pIwc->debug.enableProfile = cmdq_core_profile_enabled();

	CMDQ_LOG("FILL:CANCEL_TASK: task: %p, thread:%d, cookie:%d\n",
		pTask, thread, pTask->secData.waitCookie);

	return 0;
}
コード例 #19
0
static int cmdq_sec_sectrace_unmap(void *va, size_t size)
{
	int status;
	enum mc_result mcRet;

	status = 0;
	cmdq_sec_lock_secure_path();
	do {
		if(NULL == gCmdqSecContextHandle) {
			status = -EFAULT;
			break;
		}

		/* ask secure CMDQ to unmap sectrace log buffer */
		status = cmdq_sec_submit_to_secure_world_async_unlocked(
					CMD_CMDQ_TL_SECTRACE_UNMAP,
					NULL, CMDQ_INVALID_THREAD,
					cmdq_sec_fill_iwc_command_sectrace_unlocked,
					NULL);
		if(0 > status) {
			CMDQ_ERR("[sectrace]unmap: failed in SWd: %d\n", status);
			mc_unmap(&(gCmdqSecContextHandle->sessionHandle), va, &gCmdqSectraceMappedInfo);
			status = -EFAULT;
			break;
		}

		mcRet = mc_unmap(&(gCmdqSecContextHandle->sessionHandle), va, &gCmdqSectraceMappedInfo);

	} while(0);

	cmdq_sec_unlock_secure_path();

	CMDQ_LOG("[sectrace]unmap: status: %d\n", status);

	return status;
}
コード例 #20
0
ファイル: cmdq_driver.c プロジェクト: John677/Kernal_k3note
static long cmdq_ioctl(struct file *pFile, unsigned int code, unsigned long param)
{
	struct cmdqCommandStruct command;
	struct cmdqJobStruct job;
	int count[CMDQ_MAX_ENGINE_COUNT];
	struct TaskStruct *pTask;
	int32_t status;
	struct cmdqJobResultStruct jobResult;
	uint32_t *userRegValue = NULL;
	uint32_t userRegCount = 0;
	/* backup value after task release */
	uint32_t regCount = 0, regCountUserSpace = 0, regUserToken = 0;

	switch (code) {
	case CMDQ_IOCTL_EXEC_COMMAND:
		if (copy_from_user(&command, (void *)param, sizeof(cmdqCommandStruct)))
			return -EFAULT;

		/* insert private_data for resource reclaim */
		command.privateData = (cmdqU32Ptr_t) (unsigned long)(pFile->private_data);

		if (cmdq_driver_process_command_request(&command))
			return -EFAULT;
		break;
	case CMDQ_IOCTL_QUERY_USAGE:
		if (cmdqCoreQueryUsage(count))
			return -EFAULT;

		if (copy_to_user((void *)param, count, sizeof(int32_t) * CMDQ_MAX_ENGINE_COUNT)) {
			CMDQ_ERR("CMDQ_IOCTL_QUERY_USAGE copy_to_user failed\n");
			return -EFAULT;
		}
		break;
	case CMDQ_IOCTL_ASYNC_JOB_EXEC:
		if (copy_from_user(&job, (void *)param, sizeof(cmdqJobStruct)))
			return -EFAULT;

		/* not support secure path for async ioctl yet */
		if (true == job.command.secData.isSecure) {
			CMDQ_ERR("not support secure path for CMDQ_IOCTL_ASYNC_JOB_EXEC\n");
			return -EFAULT;
		}

		/* backup */
		userRegCount = job.command.regRequest.count;

		/* insert private_data for resource reclaim */
		job.command.privateData = (cmdqU32Ptr_t) (unsigned long)(pFile->private_data);

		/* create kernel-space address buffer */
		status = cmdq_driver_create_reg_address_buffer(&job.command);
		if (0 != status)
			return status;

		/* scenario id fixup */
		cmdq_core_fix_command_scenario_for_user_space(&job.command);

		status = cmdqCoreSubmitTaskAsync(&job.command, NULL, 0, &pTask);

		/* store user space request count in TaskStruct */
		/* for later retrieval */
		if (pTask) {
			pTask->regCountUserSpace = userRegCount;
			pTask->regUserToken = job.command.debugRegDump;
		}

		/* we don't need regAddress anymore, free it now */
		kfree(CMDQ_U32_PTR(job.command.regRequest.regAddresses));
		job.command.regRequest.regAddresses = (cmdqU32Ptr_t) (unsigned long)(NULL);

		if (status >= 0) {
			job.hJob = (unsigned long)pTask;
			if (copy_to_user((void *)param, (void *)&job, sizeof(cmdqJobStruct))) {
				CMDQ_ERR("CMDQ_IOCTL_ASYNC_JOB_EXEC copy_to_user failed\n");
				return -EFAULT;
			}
		} else {
			job.hJob = (unsigned long)NULL;
			return -EFAULT;
		}
		break;
	case CMDQ_IOCTL_ASYNC_JOB_WAIT_AND_CLOSE:
		if (copy_from_user(&jobResult, (void *)param, sizeof(jobResult))) {
			CMDQ_ERR("copy_from_user jobResult fail\n");
			return -EFAULT;
		}

		/* verify job handle */
		if (!cmdqIsValidTaskPtr((TaskStruct *) (unsigned long)jobResult.hJob)) {
			CMDQ_ERR("invalid task ptr = 0x%llx\n", jobResult.hJob);
			return -EFAULT;
		}
		pTask = (TaskStruct *) (unsigned long)jobResult.hJob;

		/* utility service, fill the engine flag. */
		/* this is required by MDP. */
		jobResult.engineFlag = pTask->engineFlag;

		/* check if reg buffer suffices */
		if (jobResult.regValue.count < pTask->regCountUserSpace) {
			jobResult.regValue.count = pTask->regCountUserSpace;
			if (copy_to_user((void *)param, (void *)&jobResult, sizeof(jobResult))) {
				CMDQ_ERR("copy_to_user fail, line=%d\n", __LINE__);
				return -EINVAL;
			}
			CMDQ_ERR("insufficient register buffer\n");
			return -ENOMEM;
		}

		/* inform client the actual read register count */
		jobResult.regValue.count = pTask->regCountUserSpace;
		/* update user space before we replace the regValues pointer. */
		if (copy_to_user((void *)param, (void *)&jobResult, sizeof(jobResult))) {
			CMDQ_ERR("copy_to_user fail line=%d\n", __LINE__);
			return -EINVAL;
		}

		/* allocate kernel space result buffer */
		/* which contains kernel + user space requests */
		userRegValue = CMDQ_U32_PTR(jobResult.regValue.regValues);
		jobResult.regValue.regValues = (cmdqU32Ptr_t) (unsigned long)
		    (kzalloc(pTask->regCount * sizeof(uint32_t), GFP_KERNEL));
		jobResult.regValue.count = pTask->regCount;
		if (NULL == CMDQ_U32_PTR(jobResult.regValue.regValues)) {
			CMDQ_ERR("no reg value buffer\n");
			return -ENOMEM;
		}

		/* backup value after task release */
		regCount = pTask->regCount;
		regCountUserSpace = pTask->regCountUserSpace;
		regUserToken = pTask->regUserToken;

		/* make sure the task is running and wait for it */
		status = cmdqCoreWaitResultAndReleaseTask(pTask,
							  &jobResult.regValue,
							  msecs_to_jiffies
							  (CMDQ_DEFAULT_TIMEOUT_MS));
		if (status < 0) {
			CMDQ_ERR("waitResultAndReleaseTask fail=%d\n", status);
			/* free kernel space result buffer */
			kfree(CMDQ_U32_PTR(jobResult.regValue.regValues));
			return status;
		}

		/* pTask is released, do not access it any more */
		pTask = NULL;

		/* notify kernel space dump callback */
		if (regCount > regCountUserSpace) {
			CMDQ_VERBOSE("kernel space reg dump = %d, %d, %d\n", regCount,
				     regCountUserSpace, regUserToken);
			status = cmdqCoreDebugRegDumpEnd(regUserToken,
							 regCount - regCountUserSpace,
							 CMDQ_U32_PTR(jobResult.regValue.regValues +
								      regCountUserSpace));
			if (0 != status) {
				/* Error status print */
				CMDQ_ERR("cmdqCoreDebugRegDumpEnd returns %d\n", status);
			}
		}

		/* copy result to user space */
		if (copy_to_user
		    ((void *)userRegValue, (void *)(unsigned long)jobResult.regValue.regValues,
		     regCountUserSpace * sizeof(uint32_t))) {
			CMDQ_ERR("Copy REGVALUE to user space failed\n");
			return -EFAULT;
		}

		if (jobResult.readAddress.count > 0)
			cmdq_driver_process_read_address_request(&jobResult.readAddress);

		/* free kernel space result buffer */
		kfree(CMDQ_U32_PTR(jobResult.regValue.regValues));
		break;
	case CMDQ_IOCTL_ALLOC_WRITE_ADDRESS:
		do {
			cmdqWriteAddressStruct addrReq;
			dma_addr_t paStart = 0;

			CMDQ_LOG("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS\n");

			if (copy_from_user(&addrReq, (void *)param, sizeof(addrReq))) {
				CMDQ_ERR("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS copy_from_user failed\n");
				return -EFAULT;
			}

			status = cmdqCoreAllocWriteAddress(addrReq.count, &paStart);
			if (0 != status) {
				CMDQ_ERR
				    ("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS cmdqCoreAllocWriteAddress() failed\n");
				return status;
			}


			addrReq.startPA = (uint32_t) paStart;
			CMDQ_LOG("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS get 0x%08x\n", addrReq.startPA);

			if (copy_to_user((void *)param, &addrReq, sizeof(addrReq))) {
				CMDQ_ERR("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS copy_to_user failed\n");
				return -EFAULT;
			}
			status = 0;
		} while (0);
		break;
	case CMDQ_IOCTL_FREE_WRITE_ADDRESS:
		do {
			cmdqWriteAddressStruct freeReq;

			CMDQ_LOG("CMDQ_IOCTL_FREE_WRITE_ADDRESS\n");

			if (copy_from_user(&freeReq, (void *)param, sizeof(freeReq))) {
				CMDQ_ERR("CMDQ_IOCTL_FREE_WRITE_ADDRESS copy_from_user failed\n");
				return -EFAULT;
			}

			status = cmdqCoreFreeWriteAddress(freeReq.startPA);
			if (0 != status)
				return status;

			status = 0;
		} while (0);
		break;
	case CMDQ_IOCTL_READ_ADDRESS_VALUE:
		do {
			cmdqReadAddressStruct readReq;

			CMDQ_LOG("CMDQ_IOCTL_READ_ADDRESS_VALUE\n");

			if (copy_from_user(&readReq, (void *)param, sizeof(readReq))) {
				CMDQ_ERR("CMDQ_IOCTL_READ_ADDRESS_VALUE copy_from_user failed\n");
				return -EFAULT;
			}

			/* this will copy result to readReq->values buffer */
			cmdq_driver_process_read_address_request(&readReq);

			status = 0;

		} while (0);
		break;
	case CMDQ_IOCTL_QUERY_CAP_BITS:
		do {
			int capBits = 0;

			if (cmdq_driver_support_wait_and_receive_event_in_same_tick())
				capBits |= (1L << CMDQ_CAP_WFE);
			else
				capBits &= ~(1L << CMDQ_CAP_WFE);

			if (copy_to_user((void *)param, &capBits, sizeof(int))) {
				CMDQ_ERR("Copy capacity bits to user space failed\n");
				return -EFAULT;
			}
		} while (0);
		break;
	case CMDQ_IOCTL_QUERY_DTS:
		do {
			cmdqDTSDataStruct *pDtsData;

			pDtsData = cmdq_core_get_whole_DTS_Data();

			if (copy_to_user((void *)param, pDtsData, sizeof(cmdqDTSDataStruct))) {
				CMDQ_ERR("Copy device tree information to user space failed\n");
				return -EFAULT;
			}
		} while (0);
		break;
	case CMDQ_IOCTL_NOTIFY_ENGINE:
		do {
			uint64_t engineFlag;

			if (copy_from_user(&engineFlag, (void *)param, sizeof(uint64_t))) {
				CMDQ_ERR("CMDQ_IOCTL_NOTIFY_ENGINE copy_from_user failed\n");
				return -EFAULT;
			}
			cmdqCoreLockResource(engineFlag, true);
		} while (0);
		break;
	default:
		CMDQ_ERR("unrecognized ioctl 0x%08x\n", code);
		return -ENOIOCTLCMD;
	}

	return 0;
}
コード例 #21
0
static long cmdq_ioctl(struct file *pFile, unsigned int code, unsigned long param)
{
	int mutex;
	struct cmdqCommandStruct command;
	struct cmdqJobStruct job;
	struct cmdqFileNodeStruct *pNode;
	unsigned long flags;
	int count[CMDQ_MAX_ENGINE_COUNT];
	struct TaskStruct *pTask;
	int32_t status;
	struct cmdqJobResultStruct jobResult;
	uint32_t *userRegValue = NULL;
	uint32_t userRegCount = 0;
	/* backup value after task release */
	uint32_t regCount = 0, regCountUserSpace = 0, regUserToken = 0;

	switch (code) {
	case CMDQ_IOCTL_LOCK_MUTEX:
		mutex = cmdqMutexAcquire();
		if (-1 == mutex)
			return -IOCTL_RET_LOCK_MUTEX_FAIL;


		if (copy_to_user((void *)param, &mutex, sizeof(int))) {
			CMDQ_ERR("Copy mutex number to user failed\n");
			cmdqMutexRelease(mutex);
			return -IOCTL_RET_COPY_MUTEX_NUM_TO_USER_FAIL;
		}
		/* register mutex into file node data */
		pNode = (struct cmdqFileNodeStruct *)pFile->private_data;
		if (pNode) {
			spin_lock_irqsave(&pNode->nodeLock, flags);
			pNode->mutexFlag |= (1 << mutex);
			spin_unlock_irqrestore(&pNode->nodeLock, flags);
		}
		break;
	case CMDQ_IOCTL_UNLOCK_MUTEX:
		if (copy_from_user(&mutex, (void *)param, sizeof(int))) {
			CMDQ_ERR("Copy mutex number from user failed\n");
			return -IOCLT_RET_COPY_MUTEX_NUM_FROM_USER_FAIL;
		}

		status = cmdqMutexRelease(mutex);
		if (status < 0)
			return -IOCTL_RET_RELEASE_MUTEX_FAIL;


		if (-1 != mutex) {
			pNode = (struct cmdqFileNodeStruct *)pFile->private_data;
			spin_lock_irqsave(&pNode->nodeLock, flags);
			pNode->mutexFlag &= ~(1 << mutex);
			spin_unlock_irqrestore(&pNode->nodeLock, flags);
		}

		break;
	case CMDQ_IOCTL_EXEC_COMMAND:
		if (copy_from_user(&command, (void *)param, sizeof(struct cmdqCommandStruct)))
			return -IOCTL_RET_COPY_EXEC_CMD_FROM_USER_FAIL;

		if (cmdqCoreIsEarlySuspended() && (CMDQ_SCENARIO_USER_MDP == command.scenario))
			return -IOCTL_RET_IS_SUSPEND_WHEN_EXEC_CMD;


		/* insert private_data for resource reclaim */
		command.privateData = (cmdqU32Ptr_t) pFile->private_data;

		if (cmdq_driver_process_command_request(&command))
			return -IOCTL_RET_PROCESS_CMD_REQUEST_FAIL;


		break;
	case CMDQ_IOCTL_QUERY_USAGE:
		if (cmdqCoreQueryUsage(count))
			return -IOCLT_RET_QUERY_USAGE_FAIL;


		if (copy_to_user((void *)param, count, sizeof(int32_t) * CMDQ_MAX_ENGINE_COUNT)) {
			CMDQ_ERR("CMDQ_IOCTL_QUERY_USAGE copy_to_user failed\n");
			return -IOCTL_RET_COPY_USAGE_TO_USER_FAIL;
		}
		break;
	case CMDQ_IOCTL_ASYNC_JOB_EXEC:
		if (copy_from_user(&job, (void *)param, sizeof(struct cmdqJobStruct)))
			return -IOCTL_RET_COPY_ASYNC_JOB_EXEC_FROM_USER_FAIL;

		if (cmdqCoreIsEarlySuspended() && (CMDQ_SCENARIO_USER_MDP == job.command.scenario)) {
			CMDQ_ERR("CMDQ_IOCTL_ASYNC_JOB_EXEC suspended, return\n");
			return -IOCTL_RET_IS_SUSPEND_WHEN_ASYNC_JOB_EXEC;
		}

		/* not support secure path for async ioctl yet */
		if (true == job.command.secData.isSecure) {
			CMDQ_ERR("not support secure path for CMDQ_IOCTL_ASYNC_JOB_EXEC\n");
			return -IOCTL_RET_NOT_SUPPORT_SEC_PATH_FOR_ASYNC_JOB_EXEC;
		}

		/* backup */
		userRegCount = job.command.regRequest.count;

		/* insert private_data for resource reclaim */
		job.command.privateData = (cmdqU32Ptr_t) (unsigned long)(pFile->private_data);

		/* create kernel-space address buffer */
		status = cmdq_driver_create_reg_address_buffer(&job.command);
		if (0 != status)
			return -IOCTL_RET_CREATE_REG_ADDR_BUF_FAIL;

		/* scenario id fixup */
		if ((CMDQ_SCENARIO_USER_DISP_COLOR == job.command.scenario)
		    || (CMDQ_SCENARIO_USER_MDP == job.command.scenario)) {
			CMDQ_VERBOSE("user space request, scenario:%d\n", job.command.scenario);
		} else {
			CMDQ_LOG("[WARNING]fix user space request to CMDQ_SCENARIO_USER_SPACE\n");
			job.command.scenario = CMDQ_SCENARIO_USER_SPACE;
		}
		status = cmdqCoreSubmitTaskAsync(&job.command, NULL, 0, &pTask);

		/* store user space request count in struct TaskStruct */
		/* for later retrieval */
		if (pTask) {
			pTask->regCountUserSpace = userRegCount;
			pTask->regUserToken = job.command.debugRegDump;
		}
		/* we don't need regAddress anymore, free it now */
		kfree(CMDQ_U32_PTR(job.command.regRequest.regAddresses));
		job.command.regRequest.regAddresses = (cmdqU32Ptr_t) (unsigned long)(NULL);

		if (status >= 0) {
			job.hJob = (unsigned long)pTask;
			if (copy_to_user((void *)param, (void *)&job, sizeof(struct cmdqJobStruct))) {
				CMDQ_ERR("CMDQ_IOCTL_ASYNC_JOB_EXEC copy_to_user failed\n");
				return -IOCLT_RET_COPY_ASYNC_JOB_EXEC_TO_USER_FAIL;
			}
		} else {
			job.hJob = (unsigned long)NULL;
			return -IOCTL_RET_SUBMIT_TASK_ASYNC_FAILED;
		}
		break;
	case CMDQ_IOCTL_ASYNC_JOB_WAIT_AND_CLOSE:
		if (copy_from_user(&jobResult, (void *)param, sizeof(jobResult))) {
			CMDQ_ERR("copy_from_user jobResult fail\n");
			return -IOCTL_RET_COPY_ASYNC_JOB_WAIT_AND_CLOSE_FROM_USER_FAIL;
		}

		if (cmdqCoreIsEarlySuspended() && (CMDQ_SCENARIO_USER_MDP == job.command.scenario)) {
			CMDQ_ERR("CMDQ_IOCTL_ASYNC_JOB_WAIT_AND_CLOSE suspended, return\n");
			return -IOCTL_RET_IS_SUSPEND_WHEN_ASYNC_JOB_WAIT_AND_CLOSE;
		}

		/* verify job handle */
		if (!cmdqIsValidTaskPtr((struct TaskStruct *)(unsigned long)jobResult.hJob)) {
			CMDQ_ERR("invalid task ptr = 0x%llx\n", jobResult.hJob);
			return -IOCTL_RET_INVALID_TASK_PTR;
		}
		pTask = (struct TaskStruct *)(unsigned long)jobResult.hJob;

		/* utility service, fill the engine flag. */
		/* this is required by MDP. */
		jobResult.engineFlag = pTask->engineFlag;

		/* check if reg buffer suffices */
		if (jobResult.regValue.count < pTask->regCountUserSpace) {
			jobResult.regValue.count = pTask->regCountUserSpace;
			if (copy_to_user((void *)param, (void *)&jobResult, sizeof(jobResult))) {
				CMDQ_ERR("copy_to_user fail, line=%d\n", __LINE__);
				return -IOCTL_RET_COPY_JOB_RESULT_TO_USER1_FAIL;
			}
			CMDQ_ERR("insufficient register buffer\n");
			return -IOCTL_RET_NOT_ENOUGH_REGISTER_BUFFER;
		}
		/* inform client the actual read register count */
		jobResult.regValue.count = pTask->regCountUserSpace;
		/* update user space before we replace the regValues pointer. */
		if (copy_to_user((void *)param, (void *)&jobResult, sizeof(jobResult))) {
			CMDQ_ERR("copy_to_user fail line=%d\n", __LINE__);
			return -IOCTL_RET_COPY_JOB_RESULT_TO_USER2_FAIL;
		}
		/* allocate kernel space result buffer */
		/* which contains kernel + user space requests */
		userRegValue = CMDQ_U32_PTR(jobResult.regValue.regValues);
		jobResult.regValue.regValues =
		    (cmdqU32Ptr_t) (unsigned
				    long)(kzalloc(pTask->regCount * sizeof(uint32_t), GFP_KERNEL));
		jobResult.regValue.count = pTask->regCount;
		if (NULL == CMDQ_U32_PTR(jobResult.regValue.regValues)) {
			CMDQ_ERR("no reg value buffer\n");
			return -IOCTL_RET_NO_REG_VAL_BUFFER;
		}
		/* backup value after task release */
		regCount = pTask->regCount;
		regCountUserSpace = pTask->regCountUserSpace;
		regUserToken = pTask->regUserToken;

		/* make sure the task is running and wait for it */
		status = cmdqCoreWaitResultAndReleaseTask(pTask,
							  &jobResult.regValue,
							  msecs_to_jiffies
							  (CMDQ_DEFAULT_TIMEOUT_MS));
		if (status < 0) {
			CMDQ_ERR("waitResultAndReleaseTask fail=%d\n", status);
			/* free kernel space result buffer */
			kfree(CMDQ_U32_PTR(jobResult.regValue.regValues));
			return -IOCTL_RET_WAIT_RESULT_AND_RELEASE_TASK_FAIL;
		}
		/* pTask is released, do not access it any more */
		pTask = NULL;

		/* notify kernel space dump callback */
		if (regCount > regCountUserSpace) {
			CMDQ_VERBOSE("kernel space reg dump = %d, %d, %d\n", regCount,
				     regCountUserSpace, regUserToken);
			status = cmdqCoreDebugRegDumpEnd(regUserToken,
							 regCount - regCountUserSpace,
							 CMDQ_U32_PTR(jobResult.regValue.regValues +
								      regCountUserSpace));
			if (0 != status)
				CMDQ_ERR("cmdqCoreDebugRegDumpEnd returns %d\n", status);

		}
		/* copy result to user space */
		if (copy_to_user
		    ((void *)userRegValue, (void *)(unsigned long)jobResult.regValue.regValues,
		     regCountUserSpace * sizeof(uint32_t))) {
			CMDQ_ERR("Copy REGVALUE to user space failed\n");
			return -IOCLT_RET_COPY_REG_VALUE_TO_USER_FAIL;
		}

		if (jobResult.readAddress.count > 0)
			cmdq_driver_process_read_address_request(&jobResult.readAddress);

		/* free kernel space result buffer */
		kfree(CMDQ_U32_PTR(jobResult.regValue.regValues));
		break;
	case CMDQ_IOCTL_ALLOC_WRITE_ADDRESS:
		do {
			struct cmdqWriteAddressStruct addrReq;
			dma_addr_t paStart = 0;

			CMDQ_LOG("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS\n");

			if (copy_from_user(&addrReq, (void *)param, sizeof(addrReq))) {
				CMDQ_ERR("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS copy_from_user failed\n");
				return -IOCTL_RET_COPY_ALLOC_WRITE_ADDR_FROM_USER_FAIL;
			}

			status = cmdqCoreAllocWriteAddress(addrReq.count, &paStart);
			if (0 != status) {
				CMDQ_ERR
				    ("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS cmdqCoreAllocWriteAddress() failed\n");
				return -IOCTL_RET_ALLOC_WRITE_ADDR_FAIL;
			}


			addrReq.startPA = (uint32_t) paStart;
			CMDQ_LOG("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS get 0x%08x\n", addrReq.startPA);

			if (copy_to_user((void *)param, &addrReq, sizeof(addrReq))) {
				CMDQ_ERR("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS copy_to_user failed\n");
				return -IOCTL_RET_COPY_ALLOC_WRITE_ADDR_TO_USER_FAIL;
			}
			status = 0;
		} while (0);
		break;
	case CMDQ_IOCTL_FREE_WRITE_ADDRESS:
		do {
			struct cmdqWriteAddressStruct freeReq;

			CMDQ_LOG("CMDQ_IOCTL_FREE_WRITE_ADDRESS\n");

			if (copy_from_user(&freeReq, (void *)param, sizeof(freeReq))) {
				CMDQ_ERR("CMDQ_IOCTL_FREE_WRITE_ADDRESS copy_from_user failed\n");
				return -IOCTL_RET_COPY_FREE_WRITE_ADDR_FROM_USER_FAIL;
			}

			status = cmdqCoreFreeWriteAddress(freeReq.startPA);
			if (0 != status)
				return -IOCTL_RET_FREE_WRITE_ADDR_FAIL;

			status = 0;
		} while (0);
		break;
	case CMDQ_IOCTL_READ_ADDRESS_VALUE:
		do {
			struct cmdqReadAddressStruct readReq;

			CMDQ_LOG("CMDQ_IOCTL_READ_ADDRESS_VALUE\n");

			if (copy_from_user(&readReq, (void *)param, sizeof(readReq))) {
				CMDQ_ERR("CMDQ_IOCTL_READ_ADDRESS_VALUE copy_from_user failed\n");
				return -IOCTL_RET_COPY_READ_ADDR_VAL_FROM_USER_FAIL;
			}
			/* this will copy result to readReq->values buffer */
			cmdq_driver_process_read_address_request(&readReq);

			status = 0;

		} while (0);
		break;
	case CMDQ_IOCTL_QUERY_CAP_BITS:
		do {
			int capBits = 0;

			if (cmdq_core_support_wait_and_receive_event_in_same_tick())
				capBits |= (1L << CMDQ_CAP_WFE);
			else
				capBits &= ~(1L << CMDQ_CAP_WFE);


			if (copy_to_user((void *)param, &capBits, sizeof(int))) {
				CMDQ_ERR("Copy capacity bits to user space failed\n");
				return -IOCTL_RET_COPY_CAP_BITS_TO_USER_FAIL;
			}
		} while (0);
		break;
	case CMDQ_IOCTL_SYNC_BUF_HDCP_VERSION:
#ifdef CMDQ_SECURE_PATH_SUPPORT
		do {
			struct cmdqSyncHandleHdcpStruct syncHandle;

			if (copy_from_user(&syncHandle, (void *)param, sizeof(syncHandle))) {
				CMDQ_ERR
				    ("CMDQ_IOCTL_SYNC_BUF_HDCP_VERSION copy_from_user failed\n");
				return -IOCTL_RET_COPY_HDCP_VERSION_FROM_USER_FAIL;
			}
			status = cmdq_sec_sync_handle_hdcp_unlock(syncHandle);
			if (0 != status)
				CMDQ_ERR("cmdq_sec_sync_handle_hdcp_unlock returns %d\n", status);

		} while (0);
#else
		CMDQ_ERR("SVP not supported\n");
		return -IOCTL_RET_SVP_NOT_SUPPORT;
#endif
		break;
	default:
		CMDQ_ERR("unrecognized ioctl 0x%08x\n", code);
		CMDQ_ERR("CMDQ_IOCTL_LOCK_MUTEX:0x%08lx sizeof(int) = %ld\n",
			CMDQ_IOCTL_LOCK_MUTEX, sizeof(int));
		CMDQ_ERR("CMDQ_IOCTL_UNLOCK_MUTEX:0x%08lx sizeof(int) = %ld\n",
			CMDQ_IOCTL_UNLOCK_MUTEX, sizeof(int));
		CMDQ_ERR("CMDQ_IOCTL_EXEC_COMMAND:0x%08lx sizeof(struct cmdqCommandStruct) = %ld\n",
			CMDQ_IOCTL_EXEC_COMMAND, sizeof(struct cmdqCommandStruct));
		CMDQ_ERR("CMDQ_IOCTL_QUERY_USAGE:0x%08lx sizeof(struct cmdqUsageInfoStruct) = %ld\n",
			CMDQ_IOCTL_QUERY_USAGE, sizeof(struct cmdqUsageInfoStruct));
		CMDQ_ERR("CMDQ_IOCTL_ASYNC_JOB_EXEC:0x%08lx sizeof(struct cmdqJobStruct) = %ld\n",
			CMDQ_IOCTL_ASYNC_JOB_EXEC, sizeof(struct cmdqJobStruct));
		CMDQ_ERR("CMDQ_IOCTL_ASYNC_JOB_WAIT_AND_CLOSE:0x%08lx sizeof(struct cmdqJobResultStruct) = %ld\n",
			CMDQ_IOCTL_ASYNC_JOB_WAIT_AND_CLOSE, sizeof(struct cmdqJobResultStruct));
		CMDQ_ERR("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS:0x%08lx sizeof(struct cmdqWriteAddressStruct) = %ld\n",
			CMDQ_IOCTL_ALLOC_WRITE_ADDRESS, sizeof(struct cmdqWriteAddressStruct));
		CMDQ_ERR("CMDQ_IOCTL_FREE_WRITE_ADDRESS:0x%08lx sizeof(struct cmdqWriteAddressStruct) = %ld\n",
			CMDQ_IOCTL_FREE_WRITE_ADDRESS, sizeof(struct cmdqWriteAddressStruct));
		CMDQ_ERR("CMDQ_IOCTL_READ_ADDRESS_VALUE:0x%08lx sizeof(struct cmdqReadAddressStruct) = %ld\n",
			CMDQ_IOCTL_READ_ADDRESS_VALUE, sizeof(struct cmdqReadAddressStruct));
		CMDQ_ERR("CMDQ_IOCTL_QUERY_CAP_BITS:0x%08lx sizeof(int) = %ld\n",
			CMDQ_IOCTL_QUERY_CAP_BITS, sizeof(int));
		CMDQ_ERR("CMDQ_IOCTL_SYNC_BUF_HDCP_VERSION:0x%08lx sizeof(struct cmdqSyncHandleHdcpStruct) = %ld\n",
			CMDQ_IOCTL_SYNC_BUF_HDCP_VERSION, sizeof(struct cmdqSyncHandleHdcpStruct));
		return -IOCTL_RET_UNRECOGNIZED_IOCTL;
	}

	return IOCTL_RET_SUCCESS;
}
コード例 #22
0
static long cmdq_driver_process_command_request(struct cmdqCommandStruct *pCommand)
{
	int32_t status = 0;
	uint32_t *userRegValue = NULL;
	uint32_t userRegCount = 0;

	if (pCommand->regRequest.count != pCommand->regValue.count) {
		CMDQ_ERR("mismatch regRequest and regValue\n");
		return -EFAULT;
	}

	/* allocate secure medatata */
	status = cmdq_driver_create_secure_medadata(pCommand);
	if (0 != status)
		return status;


	/* backup since we are going to replace these */
	userRegValue = CMDQ_U32_PTR(pCommand->regValue.regValues);
	userRegCount = pCommand->regValue.count;

	/* create kernel-space address buffer */
	status = cmdq_driver_create_reg_address_buffer(pCommand);
	if (0 != status) {
		/* free secure path metadata */
		cmdq_driver_destroy_secure_medadata(pCommand);
		return status;
	}

	/* create kernel-space value buffer */
	pCommand->regValue.regValues = (cmdqU32Ptr_t) (unsigned long)
	    kzalloc(pCommand->regRequest.count * sizeof(uint32_t), GFP_KERNEL);
	pCommand->regValue.count = pCommand->regRequest.count;
	if (NULL == CMDQ_U32_PTR(pCommand->regValue.regValues)) {
		kfree(CMDQ_U32_PTR(pCommand->regRequest.regAddresses));
		return -ENOMEM;
	}

	/* scenario id fixup */
	if ((CMDQ_SCENARIO_USER_DISP_COLOR == pCommand->scenario)
	    || (CMDQ_SCENARIO_USER_MDP == pCommand->scenario)) {
		CMDQ_VERBOSE("user space request, scenario:%d\n", pCommand->scenario);
	} else {
		CMDQ_LOG("[WARNING]fix user space request to CMDQ_SCENARIO_USER_SPACE\n");
		pCommand->scenario = CMDQ_SCENARIO_USER_SPACE;
	}

	if (CMDQ_SCENARIO_USER_MDP == pCommand->scenario)
		CMDQ_MSG("srcHandle=0x%08x, dstHandle=0x%08x\n",
			 pCommand->secData.srcHandle, pCommand->secData.dstHandle);

	status = cmdqCoreSubmitTask(pCommand);
	if (0 > status) {
		CMDQ_ERR("Submit user commands for execution failed = %d\n", status);
		cmdq_driver_destroy_secure_medadata(pCommand);
		kfree(CMDQ_U32_PTR(pCommand->regRequest.regAddresses));
		kfree(CMDQ_U32_PTR(pCommand->regValue.regValues));
		return -EFAULT;
	}

	/* notify kernel space dump callback */
	if (0 != pCommand->debugRegDump) {
		status = cmdqCoreDebugRegDumpEnd(pCommand->debugRegDump,
						 pCommand->regRequest.count - userRegCount,
						 CMDQ_U32_PTR(pCommand->regValue.regValues) +
						 userRegCount);
		if (0 != status)
			CMDQ_ERR("cmdqCoreDebugRegDumpEnd returns %d\n", status);

	}

	/* copy back to user space buffer */
	if (userRegValue && userRegCount) {
		/* copy results back to user space */
		CMDQ_VERBOSE("regValue[0] is %d\n", CMDQ_U32_PTR(pCommand->regValue.regValues)[0]);
		if (copy_to_user
		    (userRegValue, CMDQ_U32_PTR(pCommand->regValue.regValues),
		     userRegCount * sizeof(uint32_t))) {
			CMDQ_ERR("Copy REGVALUE to user space failed\n");
		}
	}

	/* free allocated kernel buffers */
	kfree(CMDQ_U32_PTR(pCommand->regRequest.regAddresses));
	kfree(CMDQ_U32_PTR(pCommand->regValue.regValues));

	if (pCommand->readAddress.count > 0)
		cmdq_driver_process_read_address_request(&pCommand->readAddress);


	/* free allocated secure metadata */
	cmdq_driver_destroy_secure_medadata(pCommand);

	return 0;
}
コード例 #23
0
static int cmdq_probe(struct platform_device *pDevice)
{
	int status;
	struct device *object;

	CMDQ_MSG("CMDQ driver probe begin\n");

	/* init cmdq device related data */
	cmdq_dev_init(pDevice);

	/* init cmdq context */
	cmdqCoreInitialize();

	status = alloc_chrdev_region(&gCmdqDevNo, 0, 1, CMDQ_DRIVER_DEVICE_NAME);
	if (status != 0)
		CMDQ_ERR("Get CMDQ device major number(%d) failed(%d)\n", gCmdqDevNo, status);
	else
		CMDQ_MSG("Get CMDQ device major number(%d) success(%d)\n", gCmdqDevNo, status);


	/* ioctl access point (/dev/mtk_cmdq) */
	gCmdqCDev = cdev_alloc();
	gCmdqCDev->owner = THIS_MODULE;
	gCmdqCDev->ops = &cmdqOP;

	status = cdev_add(gCmdqCDev, gCmdqDevNo, 1);

	gCMDQClass = class_create(THIS_MODULE, CMDQ_DRIVER_DEVICE_NAME);
	object = device_create(gCMDQClass, NULL, gCmdqDevNo, NULL, CMDQ_DRIVER_DEVICE_NAME);

	CMDQ_LOG("register IRQ:%d\n", cmdq_dev_get_irq_id());
	status =
	    request_irq(cmdq_dev_get_irq_id(), cmdq_irq_handler, IRQF_TRIGGER_LOW,
			CMDQ_DRIVER_DEVICE_NAME, gCmdqCDev);
	if (status != 0) {
		CMDQ_ERR("Register cmdq driver irq handler(%d) failed(%d)\n", gCmdqDevNo, status);
		return -EFAULT;
	}
#if 0				/* remove register secure IRQ in Normal world . TZ register instead */
	/* although secusre CMDQ driver is responsible for handle secure IRQ, */
	/* MUST registet secure IRQ to GIC in normal world to ensure it will be initialize correctly */
	/* (that's because t-base does not support GIC init IRQ in secure world...) */
	CMDQ_LOG("register sec IRQ:%d\n", cmdq_dev_get_irq_secure_id());
	status =
	    request_irq(cmdq_dev_get_irq_secure_id(), cmdq_sec_irq_handler, IRQF_TRIGGER_LOW,
			"TEE IRQ", gCmdqCDev);
	if (status != 0) {
		CMDQ_ERR("Register cmdq driver secure irq handler(%d) failed(%d)\n", gCmdqDevNo,
			 status);
		return -EFAULT;
	}
#endif
	/* CMDQ_ERR("prepare to create device mtk_cmdq\n"); */
	/* global ioctl access point (/proc/mtk_cmdq) */
	if (NULL == proc_create(CMDQ_DRIVER_DEVICE_NAME, 0644, NULL, &cmdqOP)) {
		CMDQ_ERR("CMDQ procfs node create failed\n");
		return -EFAULT;
	}
#ifdef CMDQ_OF_SUPPORT
	/* CCF - Common Clock Framework */
	cmdq_core_get_clk_map(pDevice);
#endif
	/* proc debug access point */
	cmdq_create_debug_entries();

	/* device attributes for debugging */
	device_create_file(&pDevice->dev, &dev_attr_status);
	device_create_file(&pDevice->dev, &dev_attr_error);
	device_create_file(&pDevice->dev, &dev_attr_record);
	device_create_file(&pDevice->dev, &dev_attr_log_level);
	device_create_file(&pDevice->dev, &dev_attr_profile_enable);

	CMDQ_MSG("CMDQ driver probe end\n");

	return 0;
}
コード例 #24
0
int32_t cmdq_sec_submit_to_secure_world_async_unlocked(uint32_t iwcCommand,
				TaskStruct *pTask, int32_t thread, CmdqSecFillIwcCB iwcFillCB, void *data)
{
	const int32_t tgid = current->tgid;
	const int32_t pid = current->pid;
	cmdqSecContextHandle handle = NULL;
	int32_t status = 0;
	int32_t duration = 0;

	CMDQ_TIME tEntrySec;
	CMDQ_TIME tExitSec;

	CMDQ_MSG("[SEC]-->SEC_SUBMIT: tgid[%d:%d]\n", tgid, pid);
	do {
		/* find handle first */

		/* Unlike tBase user space API,
		 * tBase kernel API maintains a GLOBAL table to control mobicore device reference count.
		 * For kernel spece user, mc_open_device and session_handle don't depend on the process context.
		 * Therefore we use global secssion handle to inter-world commumication. */
		if(NULL == gCmdqSecContextHandle) {
			gCmdqSecContextHandle = cmdq_sec_context_handle_create(current->tgid);
		}
		handle = gCmdqSecContextHandle;

		if (NULL == handle) {
			CMDQ_ERR("SEC_SUBMIT: tgid %d err[NULL secCtxHandle]\n", tgid);
			status = -(CMDQ_ERR_NULL_SEC_CTX_HANDLE);
			break;
		}

		if (0 > cmdq_sec_setup_context_session(handle)) {
			status = -(CMDQ_ERR_SEC_CTX_SETUP);
			break;
		}

		tEntrySec = sched_clock();

		status = cmdq_sec_send_context_session_message(
					handle, iwcCommand, pTask, thread, iwcFillCB, data);

		tExitSec = sched_clock();
		CMDQ_GET_TIME_IN_US_PART(tEntrySec, tExitSec, duration);
		cmdq_sec_track_task_record(iwcCommand, pTask, &tEntrySec, &tExitSec);

		/* release resource */
#if !(CMDQ_OPEN_SESSION_ONCE)
		cmdq_sec_teardown_context_session(handle)
#endif

		/* Note we entry secure for config only and wait result in normal world. */
		/* No need reset module HW for config failed case*/
	} while (0);


	if (-ETIMEDOUT == status) {
		/* t-base strange issue, mc_wait_notification false timeout when secure world has done */
		/* becuase retry may failed, give up retry method */
		CMDQ_AEE("CMDQ",
			"[SEC]<--SEC_SUBMIT: err[%d][mc_wait_notification timeout], pTask[0x%p], THR[%d], tgid[%d:%d], config_duration_ms[%d], cmdId[%d]\n",
			 status, pTask, thread, tgid, pid, duration, iwcCommand);

	} else if (0 > status) {
		/* dump metadata first */
		if (pTask) {
			cmdq_core_dump_secure_metadata(&(pTask->secData));
		}

		/* throw AEE */
		CMDQ_AEE("CMDQ",
			 "[SEC]<--SEC_SUBMIT: err[%d], pTask[0x%p], THR[%d], tgid[%d:%d], config_duration_ms[%d], cmdId[%d]\n",
			 status, pTask, thread, tgid, pid, duration, iwcCommand);
	} else {
		CMDQ_LOG
		    ("[SEC]<--SEC_SUBMIT: err[%d], pTask[0x%p], THR[%d], tgid[%d:%d], config_duration_ms[%d], cmdId[%d]\n",
		     status, pTask, thread, tgid, pid, duration, iwcCommand);
	}
	return status;
}