From cc1308fff7aa3d95579a992c176e89894cd89749 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 21 Oct 2011 11:03:05 +0200 Subject: staging: nmf-cm: Add NMF/CM driver This is driver for loading code to a DSP Signed-off-by: Philippe Langlais Signed-off-by: Robert Marklund --- drivers/staging/nmf-cm/cm_syscall.c | 1390 +++++++++++++++++++++++++++++++++++ 1 file changed, 1390 insertions(+) create mode 100644 drivers/staging/nmf-cm/cm_syscall.c (limited to 'drivers/staging/nmf-cm/cm_syscall.c') diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c new file mode 100644 index 00000000000..d1ad3a1f935 --- /dev/null +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -0,0 +1,1390 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Pierre Peiffer for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +#include +#include +#include +#include +#include "cmioctl.h" +#include "osal-kernel.h" +#include "cmld.h" +#include +#include + +/** Dequeue and free per-process messages for specific binding + * + * \note + * This is only safe if the per process mutex is held when called. + */ +static inline void freeMessages(struct cm_channel_priv* cPriv, t_skelwrapper* binding) +{ + struct osal_msg *this, *next; + + spin_lock_bh(&cPriv->bh_lock); + + /* free any pending messages */ + plist_for_each_entry_safe(this, next, &cPriv->messageQueue, msg_entry) { + if (this->msg_type == MSG_INTERFACE + && this->d.itf.skelwrap == binding) { + plist_del(&this->msg_entry, &cPriv->messageQueue); + kfree(this); + } + } + spin_unlock_bh(&cPriv->bh_lock); +} + +static t_cm_error copy_string_from_user(char *dst, const char __user *src, int len) +{ + int ret; + + ret = strncpy_from_user(dst, src, len); + if (ret < 0) /* -EFAULT */ + return CM_INVALID_PARAMETER; + + if (ret >= len) + return CM_OUT_OF_LIMITS; + + return 0; +} + +inline int cmld_InstantiateComponent(struct cm_process_priv* procPriv, + CM_InstantiateComponent_t __user *param) +{ + CM_InstantiateComponent_t data; + char templateName[MAX_TEMPLATE_NAME_LENGTH]; + char localName[MAX_COMPONENT_NAME_LENGTH]; + char *dataFile = NULL; + + /* Copy all user data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if (data.in.dataFile != NULL) { + dataFile = OSAL_Alloc(data.in.dataFileSize); + if (dataFile == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + /* coverity[tainted_data : FALSE] */ + if (copy_from_user(dataFile, data.in.dataFile, data.in.dataFileSize)) { + data.out.error = CM_INVALID_PARAMETER; + goto out; + } + } + + if ((data.out.error = copy_string_from_user(templateName, + data.in.templateName, + sizeof(templateName)))) + goto out; + + if ((data.in.localName != NULL) && + (data.out.error = copy_string_from_user(localName, + data.in.localName, + sizeof(localName)))) + goto out; + + /* Do appropriate CM Engine call */ + data.out.error = CM_ENGINE_InstantiateComponent(templateName, + data.in.domainId, + procPriv->pid, + data.in.priority, + data.in.localName ? localName : NULL, + dataFile, + &data.out.component); + +out: + if (dataFile) + OSAL_Free(dataFile); + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_BindComponentFromCMCore(struct cm_process_priv* procPriv, + CM_BindComponentFromCMCore_t __user *param) +{ + CM_BindComponentFromCMCore_t data; + char providedItfServerName[MAX_INTERFACE_NAME_LENGTH]; + char *dataFileSkeleton = NULL; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(providedItfServerName, + data.in.providedItfServerName, + sizeof(providedItfServerName)))) + goto out; + + if (data.in.dataFileSkeleton != NULL) { + dataFileSkeleton = OSAL_Alloc(data.in.dataFileSkeletonSize); + if (dataFileSkeleton == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + /* coverity[tainted_data : FALSE] */ + if (copy_from_user(dataFileSkeleton, data.in.dataFileSkeleton, + data.in.dataFileSkeletonSize)) { + data.out.error = CM_INVALID_PARAMETER; + goto out; + } + } + + data.out.error = CM_ENGINE_BindComponentFromCMCore(data.in.server, + providedItfServerName, + data.in.fifosize, + data.in.eventMemType, + &data.out.host2mpcId, + procPriv->pid, + dataFileSkeleton); +out: + if (dataFileSkeleton) + OSAL_Free(dataFileSkeleton); + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + + return 0; +} + +inline int cmld_UnbindComponentFromCMCore(CM_UnbindComponentFromCMCore_t __user *param) +{ + CM_UnbindComponentFromCMCore_t data; + + /* Copy all user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_UnbindComponentFromCMCore(data.in.host2mpcId); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_BindComponentToCMCore(struct cm_channel_priv* channelPriv, + CM_BindComponentToCMCore_t __user *param) +{ + CM_BindComponentToCMCore_t data; + t_skelwrapper *skelwrapper; + struct cm_process_priv *procPriv = channelPriv->proc; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + char *dataFileStub = NULL; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + /* Do appropriate CM Engine call */ + skelwrapper = (t_skelwrapper *)OSAL_Alloc(sizeof(*skelwrapper)); + if (skelwrapper == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + + if (data.in.dataFileStub != NULL) { + dataFileStub = OSAL_Alloc(data.in.dataFileStubSize); + if (dataFileStub == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + /* coverity[tainted_data : FALSE] */ + if (copy_from_user(dataFileStub, data.in.dataFileStub, data.in.dataFileStubSize)) { + data.out.error = CM_INVALID_PARAMETER; + goto out; + } + } + + if ((data.out.error = CM_ENGINE_BindComponentToCMCore( + data.in.client, + requiredItfClientName, + data.in.fifosize, + (t_nmf_mpc2host_handle)skelwrapper, + dataFileStub, + &data.out.mpc2hostId, + procPriv->pid)) != CM_OK) { + OSAL_Free(skelwrapper); + goto out; + } + + skelwrapper->upperLayerThis = data.in.upLayerThis; + skelwrapper->mpc2hostId = data.out.mpc2hostId; + skelwrapper->channelPriv = channelPriv; + mutex_lock(&channelPriv->skelListLock); + list_add(&skelwrapper->entry, &channelPriv->skelList); + mutex_unlock(&channelPriv->skelListLock); +out: + if (dataFileStub != NULL) + OSAL_Free(dataFileStub); + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_UnbindComponentToCMCore(struct cm_process_priv* procPriv, + CM_UnbindComponentToCMCore_t __user *param) +{ + CM_UnbindComponentToCMCore_t data; + t_skelwrapper *skelwrapper; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + data.out.error = CM_ENGINE_UnbindComponentToCMCore( + data.in.client, requiredItfClientName, + (t_nmf_mpc2host_handle*)&skelwrapper, + procPriv->pid); + + if (data.out.error != CM_OK && data.out.error != CM_MPC_NOT_RESPONDING) + goto out; + + data.out.upLayerThis = skelwrapper->upperLayerThis; + + mutex_lock(&skelwrapper->channelPriv->msgQueueLock); + freeMessages(skelwrapper->channelPriv, skelwrapper); + mutex_lock(&skelwrapper->channelPriv->skelListLock); + list_del(&skelwrapper->entry); + mutex_unlock(&skelwrapper->channelPriv->skelListLock); + mutex_unlock(&skelwrapper->channelPriv->msgQueueLock); + OSAL_Free(skelwrapper); +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_BindComponentAsynchronous(struct cm_process_priv* procPriv, + CM_BindComponentAsynchronous_t __user *param) +{ + CM_BindComponentAsynchronous_t data; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + char providedItfServerName[MAX_INTERFACE_NAME_LENGTH]; + char *dataFileSkeletonOrEvent = NULL; + char *dataFileStub = NULL; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + if ((data.out.error = copy_string_from_user(providedItfServerName, + data.in.providedItfServerName, + sizeof(providedItfServerName)))) + goto out; + + if (data.in.dataFileSkeletonOrEvent != NULL) { + dataFileSkeletonOrEvent = + OSAL_Alloc(data.in.dataFileSkeletonOrEventSize); + if (dataFileSkeletonOrEvent == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + /* coverity[tainted_data : FALSE] */ + if (copy_from_user(dataFileSkeletonOrEvent, data.in.dataFileSkeletonOrEvent, data.in.dataFileSkeletonOrEventSize)) { + data.out.error = CM_INVALID_PARAMETER; + goto out; + } + } + + if (data.in.dataFileStub != NULL) { + dataFileStub = OSAL_Alloc(data.in.dataFileStubSize); + if (dataFileStub == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + /* coverity[tainted_data : FALSE] */ + if (copy_from_user(dataFileStub, data.in.dataFileStub, data.in.dataFileStubSize)) { + data.out.error = CM_INVALID_PARAMETER; + goto out; + } + } + + /* Do appropriate CM Engine call */ + data.out.error = CM_ENGINE_BindComponentAsynchronous(data.in.client, + requiredItfClientName, + data.in.server, + providedItfServerName, + data.in.fifosize, + data.in.eventMemType, + procPriv->pid, + dataFileSkeletonOrEvent, + dataFileStub); + +out: + if (dataFileSkeletonOrEvent != NULL) + OSAL_Free(dataFileSkeletonOrEvent); + if (dataFileStub != NULL) + OSAL_Free(dataFileStub); + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_UnbindComponentAsynchronous(struct cm_process_priv* procPriv, + CM_UnbindComponentAsynchronous_t __user *param) +{ + CM_UnbindComponentAsynchronous_t data; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + + /* Copy all user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + /* Do appropriate CM Engine call */ + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_UnbindComponentAsynchronous(data.in.client, + requiredItfClientName, + procPriv->pid); +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_BindComponent(struct cm_process_priv* procPriv, + CM_BindComponent_t __user *param) +{ + CM_BindComponent_t data; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + char providedItfServerName[MAX_INTERFACE_NAME_LENGTH]; + char *dataFileTrace = NULL; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + if ((data.out.error = copy_string_from_user(providedItfServerName, + data.in.providedItfServerName, + sizeof(providedItfServerName)))) + goto out; + + if (data.in.dataFileTrace != NULL) { + dataFileTrace = OSAL_Alloc(data.in.dataFileTraceSize); + if (dataFileTrace == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + /* coverity[tainted_data : FALSE] */ + if (copy_from_user(dataFileTrace, data.in.dataFileTrace, + data.in.dataFileTraceSize)) { + data.out.error = CM_INVALID_PARAMETER; + goto out; + } + } + + /* Do appropriate CM Engine call */ + data.out.error = CM_ENGINE_BindComponent(data.in.client, + requiredItfClientName, + data.in.server, + providedItfServerName, + data.in.traced, + procPriv->pid, + dataFileTrace); +out: + if (dataFileTrace != NULL) + OSAL_Free(dataFileTrace); + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_UnbindComponent(struct cm_process_priv* procPriv, + CM_UnbindComponent_t __user *param) +{ + CM_UnbindComponent_t data; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + /* Do appropriate CM Engine call */ + data.out.error = CM_ENGINE_UnbindComponent(data.in.client, + requiredItfClientName, + procPriv->pid); + +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_BindComponentToVoid(struct cm_process_priv* procPriv, + CM_BindComponentToVoid_t __user *param) +{ + CM_BindComponentToVoid_t data; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + data.out.error = CM_ENGINE_BindComponentToVoid(data.in.client, + requiredItfClientName, + procPriv->pid); + +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_DestroyComponent(struct cm_process_priv* procPriv, + CM_DestroyComponent_t __user *param) +{ + CM_DestroyComponent_t data; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_DestroyComponent(data.in.component, + procPriv->pid); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_CreateMemoryDomain(struct cm_process_priv *procPriv, + CM_CreateMemoryDomain_t __user *param) +{ + CM_CreateMemoryDomain_t data; + t_cm_domain_memory domain; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if (copy_from_user(&domain, data.in.domain, sizeof(domain))) + return -EFAULT; + + if (data.in.client == NMF_CURRENT_CLIENT) + data.out.error = CM_ENGINE_CreateMemoryDomain(procPriv->pid, + &domain, + &data.out.handle); + else + data.out.error = CM_ENGINE_CreateMemoryDomain(data.in.client, + &domain, + &data.out.handle); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_CreateMemoryDomainScratch(struct cm_process_priv *procPriv, + CM_CreateMemoryDomainScratch_t __user *param) +{ + CM_CreateMemoryDomainScratch_t data; + t_cm_domain_memory domain; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if (copy_from_user(&domain, data.in.domain, sizeof(domain))) + return -EFAULT; + + data.out.error = CM_ENGINE_CreateMemoryDomainScratch(procPriv->pid, + data.in.parentId, + &domain, + &data.out.handle); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_DestroyMemoryDomain(CM_DestroyMemoryDomain_t __user *param) +{ + CM_DestroyMemoryDomain_t data; + + /* Copy all user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_DestroyMemoryDomain(data.in.domainId); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetDomainCoreId(CM_GetDomainCoreId_t __user *param) +{ + CM_GetDomainCoreId_t data; + + /* Copy all user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_GetDomainCoreId(data.in.domainId, + &data.out.coreId); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_AllocMpcMemory(struct cm_process_priv *procPriv, + CM_AllocMpcMemory_t __user *param) +{ + t_cm_error err; + CM_AllocMpcMemory_t data; + t_cm_memory_handle handle = 0; + struct memAreaDesc_t* memAreaDesc; + t_cm_system_address systemAddress; + t_uint32 mpcAddress; + + /* Copy all user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + /* Disregard alignment information and force 4kB memory alignment, + in any case (see devnotes.txt) */ + /* PP: Disable this 'force' for now, because of the low amount of + available MPC Memory */ + //data.in.memAlignment = CM_MM_MPC_ALIGN_1024WORDS; + + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_AllocMpcMemory(data.in.domainId, + procPriv->pid, + data.in.memType, + data.in.size, + data.in.memAlignment, + &handle); + + data.out.pHandle = handle; + + if (data.out.error != CM_OK) + goto out; + + /* Get memory area decriptors in advance + so to fill in list elements right now */ + err = CM_ENGINE_GetMpcMemorySystemAddress(handle, &systemAddress); + if (err != CM_OK) { + pr_err("%s: failed CM_ENGINE_GetMpcMemorySystemAddress (%i)\n", __func__, err); + /* If we can't manage internally this allocated memory latter, it's + better to report the error now. + Free the handle to not let the driver in an inconsistent state */ + CM_ENGINE_FreeMpcMemory(handle); + return -EFAULT; + } + + /* Get MPC address in advance so to fill in list elements right now */ + err = CM_ENGINE_GetMpcMemoryMpcAddress(handle, &mpcAddress); + if (err != CM_OK) { + pr_err("%s: failed CM_ENGINE_GetMpcMemoryMpcAddress (%i)\n", __func__, err); + /* see comments above */ + CM_ENGINE_FreeMpcMemory(handle); + return -EFAULT; + } + + /* Allocate and fill a new memory area descriptor. Add it to the list */ + memAreaDesc = OSAL_Alloc(sizeof(struct memAreaDesc_t)); + if (memAreaDesc == NULL) { + pr_err("%s: failed allocating memAreaDesc\n", __func__); + /* see comments above */ + CM_ENGINE_FreeMpcMemory(handle); + return -ENOMEM; + } + + memAreaDesc->procPriv = procPriv; + memAreaDesc->handle = handle; + memAreaDesc->tid = 0; + memAreaDesc->physAddr = systemAddress.physical; + memAreaDesc->kernelLogicalAddr = systemAddress.logical; + memAreaDesc->userLogicalAddr = 0; + memAreaDesc->mpcPhysAddr = mpcAddress; + memAreaDesc->size = data.in.size * ((data.in.memType % 2) ? 4 : 2); // betzw: set size in bytes for host (ugly version) + atomic_set(&memAreaDesc->count, 0); + + if (lock_process(procPriv)) { + /* may be rather call lock_process_uninterruptible() */ + CM_ENGINE_FreeMpcMemory(handle); + OSAL_Free(memAreaDesc); + return -ERESTARTSYS; + } + list_add(&memAreaDesc->list, &procPriv->memAreaDescList); + unlock_process(procPriv); +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_FreeMpcMemory(struct cm_process_priv *procPriv, + CM_FreeMpcMemory_t __user *param) +{ + CM_FreeMpcMemory_t data; + struct list_head *cursor, *next; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + /* check that it is actually owned by the process */ + data.out.error = CM_UNKNOWN_MEMORY_HANDLE; + + if (lock_process(procPriv)) + return -ERESTARTSYS; + list_for_each_safe(cursor, next, &procPriv->memAreaDescList){ + struct memAreaDesc_t* curr; + curr = list_entry(cursor, struct memAreaDesc_t, list); + if (curr->handle == data.in.handle){ + if (atomic_read(&curr->count) != 0) { + pr_err("%s: Memory area (phyAddr: %x, size: %d) " + "still in use (count=%d)!\n", __func__, + curr->physAddr, curr->size, + atomic_read(&curr->count)); + data.out.error = CM_INVALID_PARAMETER; + } else { + data.out.error = + CM_ENGINE_FreeMpcMemory(data.in.handle); + if (data.out.error == CM_OK) { + list_del(cursor); + OSAL_Free(curr); + } + } + break; + } + } + unlock_process(procPriv); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetMpcMemoryStatus(CM_GetMpcMemoryStatus_t __user *param) +{ + CM_GetMpcMemoryStatus_t data; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_GetMpcMemoryStatus(data.in.coreId, + data.in.memType, + &data.out.pStatus); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_StartComponent(struct cm_process_priv *procPriv, + CM_StartComponent_t __user *param) +{ + CM_StartComponent_t data; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_StartComponent(data.in.client, + procPriv->pid); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_StopComponent(struct cm_process_priv *procPriv, + CM_StopComponent_t __user *param) +{ + CM_StopComponent_t data; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_StopComponent(data.in.client, + procPriv->pid); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetMpcLoadCounter(CM_GetMpcLoadCounter_t __user *param) +{ + CM_GetMpcLoadCounter_t data; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_getMpcLoadCounter(data.in.coreId, + &data.out.pMpcLoadCounter); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentDescription(struct cm_process_priv *procPriv, + CM_GetComponentDescription_t __user *param) +{ + CM_GetComponentDescription_t data; + char templateName[MAX_TEMPLATE_NAME_LENGTH]; + char localName[MAX_COMPONENT_NAME_LENGTH]; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentDescription(data.in.component, + templateName, + data.in.templateNameLength, + &data.out.coreId, + localName, + data.in.localNameLength, + &data.out.priority); + + /* Copy results back to userspace */ + if (data.out.error == CM_OK) { + /* coverity[tainted_data : FALSE] */ + if (copy_to_user(data.in.templateName, templateName, data.in.templateNameLength)) + return -EFAULT; + /* coverity[tainted_data : FALSE] */ + if (copy_to_user(data.in.localName, localName, data.in.localNameLength)) + return -EFAULT; + } + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentListHeader(struct cm_process_priv *procPriv, + CM_GetComponentListHeader_t __user *param) +{ + CM_GetComponentListHeader_t data; + + data.out.error = CM_ENGINE_GetComponentListHeader(procPriv->pid, + &data.out.headerComponent); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentListNext(struct cm_process_priv *procPriv, + CM_GetComponentListNext_t __user *param) +{ + CM_GetComponentListNext_t data; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentListNext(procPriv->pid, + data.in.prevComponent, + &data.out.nextComponent); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentRequiredInterfaceNumber(struct cm_process_priv *procPriv, + CM_GetComponentRequiredInterfaceNumber_t __user *param) +{ + CM_GetComponentRequiredInterfaceNumber_t data; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentRequiredInterfaceNumber(data.in.component, + &data.out.numberRequiredInterfaces); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentRequiredInterface(struct cm_process_priv *procPriv, + CM_GetComponentRequiredInterface_t __user *param) +{ + CM_GetComponentRequiredInterface_t data; + char itfName[MAX_INTERFACE_NAME_LENGTH]; + char itfType[MAX_INTERFACE_TYPE_NAME_LENGTH]; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentRequiredInterface(data.in.component, + data.in.index, + itfName, + data.in.itfNameLength, + itfType, + data.in.itfTypeLength, + &data.out.requireState, + &data.out.collectionSize); + + /* Copy results back to userspace */ + if (data.out.error == CM_OK) { + /* coverity[tainted_data : FALSE] */ + if (copy_to_user(data.in.itfName, itfName, data.in.itfNameLength)) + return -EFAULT; + /* coverity[tainted_data : FALSE] */ + if (copy_to_user(data.in.itfType, itfType, data.in.itfTypeLength)) + return -EFAULT; + } + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentRequiredInterfaceBinding(struct cm_process_priv *procPriv, + CM_GetComponentRequiredInterfaceBinding_t __user *param) +{ + CM_GetComponentRequiredInterfaceBinding_t data; + char itfName[MAX_INTERFACE_NAME_LENGTH]; + char serverItfName[MAX_INTERFACE_NAME_LENGTH]; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + if ((data.out.error = copy_string_from_user(itfName, + data.in.itfName, + sizeof(itfName)))) + goto out; + + data.out.error = CM_ENGINE_GetComponentRequiredInterfaceBinding(data.in.component, + itfName, + &data.out.server, + serverItfName, + data.in.serverItfNameLength); + + /* Copy results back to userspace */ + if (data.out.error != CM_OK) + goto out; + + /* coverity[tainted_data : FALSE] */ + if (copy_to_user(data.in.serverItfName, serverItfName, data.in.serverItfNameLength)) + return -EFAULT; +out: + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentProvidedInterfaceNumber(struct cm_process_priv *procPriv, + CM_GetComponentProvidedInterfaceNumber_t __user *param) +{ + CM_GetComponentProvidedInterfaceNumber_t data; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentProvidedInterfaceNumber(data.in.component, + &data.out.numberProvidedInterfaces); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentProvidedInterface(struct cm_process_priv *procPriv, + CM_GetComponentProvidedInterface_t __user *param) +{ + CM_GetComponentProvidedInterface_t data; + char itfName[MAX_INTERFACE_NAME_LENGTH]; + char itfType[MAX_INTERFACE_TYPE_NAME_LENGTH]; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentProvidedInterface(data.in.component, + data.in.index, + itfName, + data.in.itfNameLength, + itfType, + data.in.itfTypeLength, + &data.out.collectionSize); + + /* Copy results back to userspace */ + if (data.out.error == CM_OK) { + /* coverity[tainted_data : FALSE] */ + if (copy_to_user(data.in.itfName, itfName, data.in.itfNameLength)) + return -EFAULT; + /* coverity[tainted_data : FALSE] */ + if (copy_to_user(data.in.itfType, itfType, data.in.itfTypeLength)) + return -EFAULT; + } + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentPropertyNumber(struct cm_process_priv *procPriv, + CM_GetComponentPropertyNumber_t __user *param) +{ + CM_GetComponentPropertyNumber_t data; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentPropertyNumber(data.in.component, + &data.out.numberProperties); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentPropertyName(struct cm_process_priv *procPriv, + CM_GetComponentPropertyName_t __user *param) +{ + CM_GetComponentPropertyName_t data; + char propertyName[MAX_PROPERTY_NAME_LENGTH]; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentPropertyName(data.in.component, + data.in.index, + propertyName, + data.in.propertyNameLength); + + /* Copy results back to userspace */ + /* coverity[tainted_data : FALSE] */ + if ((data.out.error == CM_OK) && + copy_to_user(data.in.propertyName, propertyName, data.in.propertyNameLength)) + return -EFAULT; + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentPropertyValue(struct cm_process_priv *procPriv, + CM_GetComponentPropertyValue_t __user *param) +{ + CM_GetComponentPropertyValue_t data; + char propertyName[MAX_PROPERTY_NAME_LENGTH]; + char propertyValue[MAX_PROPERTY_VALUE_LENGTH]; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(propertyName, + data.in.propertyName, + sizeof(propertyName)))) + goto out; + + data.out.error = CM_ENGINE_GetComponentPropertyValue(data.in.component, + propertyName, + propertyValue, + data.in.propertyValueLength); + /* Copy results back to userspace */ + /* coverity[tainted_data : FALSE] */ + if ((data.out.error == CM_OK) && + copy_to_user(data.in.propertyValue, propertyValue, data.in.propertyValueLength)) + return -EFAULT; +out: + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_ReadComponentAttribute(struct cm_process_priv *procPriv, + CM_ReadComponentAttribute_t __user *param) +{ + CM_ReadComponentAttribute_t data; + char attrName[MAX_ATTRIBUTE_NAME_LENGTH]; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(attrName, + data.in.attrName, + sizeof(attrName)))) + goto out; + + data.out.error = CM_ENGINE_ReadComponentAttribute(data.in.component, + attrName, + &data.out.value); +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetExecutiveEngineHandle(struct cm_process_priv *procPriv, + CM_GetExecutiveEngineHandle_t __user *param) +{ + CM_GetExecutiveEngineHandle_t data; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_GetExecutiveEngineHandle(data.in.domainId, + &data.out.executiveEngineHandle); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_SetMode(CM_SetMode_t __user *param) +{ + CM_SetMode_t data; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_SetMode(data.in.aCmdID, data.in.aParam); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetRequiredComponentFiles(struct cm_process_priv *procPriv, + CM_GetRequiredComponentFiles_t __user *param) +{ + CM_GetRequiredComponentFiles_t data; + char components[4][MAX_INTERFACE_TYPE_NAME_LENGTH]; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + char providedItfServerName[MAX_INTERFACE_NAME_LENGTH]; + char type[MAX_INTERFACE_TYPE_NAME_LENGTH]; + unsigned int i; + int err; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if (data.in.requiredItfClientName && + (data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + if (data.in.providedItfServerName && + (data.out.error = copy_string_from_user(providedItfServerName, + data.in.providedItfServerName, + sizeof(providedItfServerName)))) + goto out; + + data.out.error = CM_ENGINE_GetRequiredComponentFiles(data.in.action, + data.in.client, + requiredItfClientName, + data.in.server, + providedItfServerName, + components, + data.in.listSize, + data.in.type ? type : NULL, + &data.out.methodNumber); + + if (data.out.error) + goto out; + + if (data.in.fileList) { + /* Copy results back to userspace */ + for (i=0; iout, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_Migrate(CM_Migrate_t __user *param) +{ + CM_Migrate_t data; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_Migrate(data.in.srcShared, data.in.src, data.in.dst); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_Unmigrate(CM_Unmigrate_t __user *param) +{ + CM_Unmigrate_t data; + + data.out.error = CM_ENGINE_Unmigrate(); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +int cmld_SetupRelinkArea(CM_SetupRelinkArea_t __user *param) +{ + CM_SetupRelinkArea_t data; + t_cm_system_address systemAddress; + t_uint32 size; + + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + + data.out.error = CM_ENGINE_GetMpcMemorySystemAddress( + data.in.mem_handle, &systemAddress); + + if (data.out.error != CM_OK) + return 0; + + data.out.error = CM_ENGINE_GetMpcMemorySize(data.in.mem_handle, &size); + if (data.out.error != CM_OK) + return 0; + + if (size < data.in.segments * data.in.segmentsize) + { + return -EINVAL; + } + + data.out.error = cmdma_setup_relink_area( + systemAddress.physical, + data.in.peripheral_addr, + data.in.segments, + data.in.segmentsize, + data.in.LOS, + data.in.type); + + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + + return 0; +} + + +inline int cmld_PushComponent(CM_PushComponent_t __user *param) +{ + CM_PushComponent_t data; + char name[MAX_INTERFACE_TYPE_NAME_LENGTH]; + void *dataFile = NULL; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(name, + data.in.name, + sizeof(name)))) + goto out; + + if (data.in.data != NULL) { + dataFile = OSAL_Alloc(data.in.size); + if (dataFile == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + /* coverity[tainted_data : FALSE] */ + if (copy_from_user(dataFile, data.in.data, data.in.size)) + data.out.error = CM_INVALID_PARAMETER; + else + data.out.error = CM_ENGINE_PushComponent(name, dataFile, + data.in.size); + OSAL_Free(dataFile); + } + +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_ReleaseComponent(CM_ReleaseComponent_t __user *param) +{ + CM_ReleaseComponent_t data; + char name[MAX_INTERFACE_TYPE_NAME_LENGTH]; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(name, + data.in.name, + sizeof(name)))) + goto out; + + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_ReleaseComponent(name); + +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_PrivGetMPCMemoryDesc(struct cm_process_priv *procPriv, CM_PrivGetMPCMemoryDesc_t __user *param) +{ + CM_PrivGetMPCMemoryDesc_t data; + struct list_head* cursor; + + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if (lock_process(procPriv)) + return -ERESTARTSYS; + /* Scan the memory descriptors list looking for the requested handle */ + data.out.error = CM_UNKNOWN_MEMORY_HANDLE; + list_for_each(cursor, &procPriv->memAreaDescList) { + struct memAreaDesc_t* curr; + curr = list_entry(cursor, struct memAreaDesc_t, list); + if (curr->handle == data.in.handle) { + data.out.size = curr->size; + data.out.physAddr = curr->physAddr; + data.out.kernelLogicalAddr = curr->kernelLogicalAddr; + data.out.userLogicalAddr = curr->userLogicalAddr; + data.out.mpcPhysAddr = curr->mpcPhysAddr; + data.out.error = CM_OK; + break; + } + } + unlock_process(procPriv); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +int cmld_PrivReserveMemory(struct cm_process_priv *procPriv, unsigned int physAddr) +{ + struct list_head* cursor; + struct memAreaDesc_t* curr; + int err = -ENXIO; + + if (lock_process(procPriv)) + return -ERESTARTSYS; + list_for_each(cursor, &procPriv->memAreaDescList) { + curr = list_entry(cursor, struct memAreaDesc_t, list); + if (curr->physAddr == physAddr) { + /* Mark this memory area reserved for a mapping for this thread ID */ + /* It must not be already reserved but this should not happen */ + if (curr->tid) { + pr_err("%s: thread %d can't reseveved memory %x already " + "reserved for %d\n", + __func__, current->pid, physAddr, curr->tid); + err = -EBUSY; + } else { + curr->tid = current->pid; + err = 0; + } + break; + } + } + unlock_process(procPriv); + return err; +} -- cgit v1.2.3 From d54742621b8341aeeeb5524664fbdd0f9c23b588 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Thu, 23 Jun 2011 13:20:42 +0200 Subject: staging: nmf-cm: Update for api changes in 3.0 Temp fix to make driver build until its fixed properly Change-Id: I095a907abed7175180cbfa4bd2bc389060afceb1 Signed-off-by: Robert Marklund --- drivers/staging/nmf-cm/cm_service.c | 1 + drivers/staging/nmf-cm/cm_syscall.c | 7 ++++--- drivers/staging/nmf-cm/cmld.c | 1 + drivers/staging/nmf-cm/osal-kernel.h | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/staging/nmf-cm/cm_syscall.c') diff --git a/drivers/staging/nmf-cm/cm_service.c b/drivers/staging/nmf-cm/cm_service.c index 1b5ee111e09..cd7602a6cec 100644 --- a/drivers/staging/nmf-cm/cm_service.c +++ b/drivers/staging/nmf-cm/cm_service.c @@ -14,6 +14,7 @@ #include #include #include +#include #include diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index d1ad3a1f935..8a48ac10c60 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -1374,12 +1374,13 @@ int cmld_PrivReserveMemory(struct cm_process_priv *procPriv, unsigned int physAd /* Mark this memory area reserved for a mapping for this thread ID */ /* It must not be already reserved but this should not happen */ if (curr->tid) { - pr_err("%s: thread %d can't reseveved memory %x already " + /*pr_err("%s: thread %d can't reseveved memory %x already " "reserved for %d\n", - __func__, current->pid, physAddr, curr->tid); + __func__, current->pid, physAddr, (int)curr->tid);*/ err = -EBUSY; } else { - curr->tid = current->pid; + curr->tid = 0; + //current->pid; err = 0; } break; diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index 04433f10f0c..9a7183c14fc 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include diff --git a/drivers/staging/nmf-cm/osal-kernel.h b/drivers/staging/nmf-cm/osal-kernel.h index fd3b0acc301..36baf893fcc 100644 --- a/drivers/staging/nmf-cm/osal-kernel.h +++ b/drivers/staging/nmf-cm/osal-kernel.h @@ -18,6 +18,7 @@ #include #include #include +#include #include "configuration.h" -- cgit v1.2.3 From e8763447ba6e394ffbb5d49e2f50bc952e19730c Mon Sep 17 00:00:00 2001 From: psen Date: Fri, 26 Aug 2011 10:45:17 +0530 Subject: Set Current Pid to Tid * in case of tid is zero * Check for KERNELRLEASE instead of MM_MAKEFILES_DIR in Makefile --- drivers/staging/nmf-cm/Makefile | 2 +- drivers/staging/nmf-cm/cm_syscall.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/staging/nmf-cm/cm_syscall.c') diff --git a/drivers/staging/nmf-cm/Makefile b/drivers/staging/nmf-cm/Makefile index 82fa97f81d1..0728ac5bc3f 100644 --- a/drivers/staging/nmf-cm/Makefile +++ b/drivers/staging/nmf-cm/Makefile @@ -7,7 +7,7 @@ # # Rules to build kernel modules # -ifndef MM_MAKEFILES_DIR +ifdef KERNELRELEASE # $(src): current relative dir; $(kbuild-dir): cur absolute dir ifdef kbuild-dir diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index 8a48ac10c60..70f73e8ad97 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -13,6 +13,7 @@ #include "cmld.h" #include #include +#include /** Dequeue and free per-process messages for specific binding * @@ -1379,8 +1380,8 @@ int cmld_PrivReserveMemory(struct cm_process_priv *procPriv, unsigned int physAd __func__, current->pid, physAddr, (int)curr->tid);*/ err = -EBUSY; } else { - curr->tid = 0; //current->pid; + curr->tid = current->pid; err = 0; } break; -- cgit v1.2.3 From fb6f98c1efa2559f6d31551e93296570c66eeb7a Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Mon, 11 Jul 2011 11:05:42 +0200 Subject: u8500 CM: use vmalloc() for big allocations Use vmalloc() instead of OSAL_Alloc() for "big" allocations. OSAL_Alloc() uses kmalloc by default and default to vmalloc() if kmalloc() fails. The logic works, but an ugly print appears in the console each time kmalloc() fails. We use now directly vmalloc() to avoid these ugly prints ST-Ericsson Linux next: - ST-Ericsson ID: 343810 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Pierre Peiffer --- drivers/staging/nmf-cm/cm_syscall.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/staging/nmf-cm/cm_syscall.c') diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index 70f73e8ad97..0d1bf8ffe4e 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "cmioctl.h" #include "osal-kernel.h" @@ -65,7 +66,7 @@ inline int cmld_InstantiateComponent(struct cm_process_priv* procPriv, return -EFAULT; if (data.in.dataFile != NULL) { - dataFile = OSAL_Alloc(data.in.dataFileSize); + dataFile = vmalloc(data.in.dataFileSize); if (dataFile == NULL) { data.out.error = CM_NO_MORE_MEMORY; goto out; @@ -99,7 +100,7 @@ inline int cmld_InstantiateComponent(struct cm_process_priv* procPriv, out: if (dataFile) - OSAL_Free(dataFile); + vfree(dataFile); /* Copy results back to userspace */ if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) return -EFAULT; -- cgit v1.2.3 From a9c1100ab6b248b69da7e67a2eacdccff39c76cd Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Mon, 18 Jul 2011 11:28:53 +0200 Subject: U8500 NMF-CM: rework the DMA part The addition of the DMA part within the driver has broken the OSI part. This prevents all easy merge of any new changes in this OSI part. This patch reworks this part by moving everything in linux specific files. ST-Ericsson ID: 343776 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Iafaa4b36539729826442d0c2dd95c5bbc52bfddb Signed-off-by: Pierre Peiffer --- .../staging/nmf-cm/cm/engine/api/memory_engine.h | 5 -- .../nmf-cm/cm/engine/memory/src/memory_wrapper.c | 22 -------- drivers/staging/nmf-cm/cm_dma.c | 59 +++++++++++++++++++--- drivers/staging/nmf-cm/cm_dma.h | 9 ++-- drivers/staging/nmf-cm/cm_service.c | 8 +++ drivers/staging/nmf-cm/cm_syscall.c | 51 ++++++++++--------- drivers/staging/nmf-cm/cmioctl.h | 7 ++- drivers/staging/nmf-cm/cmld.c | 9 +++- drivers/staging/nmf-cm/cmld.h | 2 +- drivers/staging/nmf-cm/osal-kernel.c | 5 ++ 10 files changed, 112 insertions(+), 65 deletions(-) (limited to 'drivers/staging/nmf-cm/cm_syscall.c') diff --git a/drivers/staging/nmf-cm/cm/engine/api/memory_engine.h b/drivers/staging/nmf-cm/cm/engine/api/memory_engine.h index 49c0c815669..9f5e25b3ebf 100644 --- a/drivers/staging/nmf-cm/cm/engine/api/memory_engine.h +++ b/drivers/staging/nmf-cm/cm/engine/api/memory_engine.h @@ -75,10 +75,6 @@ PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemoryMpcAddress( t_cm_memory_handle handle, t_uint32 *pMpcAddress); -PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemorySize( - t_cm_memory_handle handle, - t_uint32 *pSize); - /*! * \brief Get the memory status for given memory type of a given Media Processor Core * @@ -93,6 +89,5 @@ PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemoryStatus( t_cm_mpc_memory_type memType, t_cm_allocator_status *pStatus); - #endif /* CM_MEMORY_ENGINE_H_ */ diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c b/drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c index 15961aea516..f7d47be924d 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c @@ -175,28 +175,6 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemoryMpcAddress(t_cm_memory_han return CM_OK; } -PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemorySize( - t_cm_memory_handle handle, - t_uint32 *pSize) -{ - t_cm_error error; - t_memory_handle validHandle; - - OSAL_LOCK_API(); - - if((error = cm_MM_getValidMemoryHandle(handle, &validHandle)) != CM_OK) - { - OSAL_UNLOCK_API(); - return error; - } - - *pSize = validHandle->size; - - OSAL_UNLOCK_API(); - return CM_OK; -} - - PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemoryStatus(t_nmf_core_id coreId, t_cm_mpc_memory_type memType, t_cm_allocator_status *pStatus) { t_dsp_memory_type_id dspMemType; diff --git a/drivers/staging/nmf-cm/cm_dma.c b/drivers/staging/nmf-cm/cm_dma.c index 1db5a3cf951..c460728e6a0 100644 --- a/drivers/staging/nmf-cm/cm_dma.c +++ b/drivers/staging/nmf-cm/cm_dma.c @@ -6,15 +6,16 @@ #include #include #include +#include #include +#include - #include "cm_dma.h" +#include "cm_dma.h" - #define CMDMA_LIDX (2) - #define CMDMA_BASE (0x801C0000) - #define CMDMA_REG_LCLA (0x024) +#define CMDMA_LIDX (2) +#define CMDMA_REG_LCLA (0x024) -void __iomem *virtbase = NULL; +static void __iomem *virtbase = NULL; static int cmdma_write_cyclic_list_mem2per( unsigned int from_addr, @@ -30,6 +31,8 @@ static int cmdma_write_cyclic_list_per2mem( unsigned int segmentsize, unsigned int LOS); +static bool cmdma_setup_relink_area_called = false; + int cmdma_setup_relink_area( unsigned int mem_addr, unsigned int per_addr, unsigned int segments, @@ -37,6 +40,9 @@ int cmdma_setup_relink_area( unsigned int mem_addr, unsigned int LOS, enum cmdma_type type) { + if (!cmdma_setup_relink_area_called) + cmdma_setup_relink_area_called = true; + switch (type) { case CMDMA_MEM_2_PER: @@ -63,7 +69,7 @@ int cmdma_setup_relink_area( unsigned int mem_addr, static unsigned int cmdma_getlcla( void) { if(!virtbase) - virtbase = ioremap(CMDMA_BASE, CMDMA_REG_LCLA + sizeof(int) ); + virtbase = ioremap(U8500_DMA_BASE, CMDMA_REG_LCLA + sizeof(int) ); return readl(virtbase + CMDMA_REG_LCLA); } @@ -87,6 +93,8 @@ int cmdma_setup_relink_area( unsigned int mem_addr, relink[3] = (((dst_addr >> 16) & 0xFFFFUL) << 16 ) | 0x8201UL | ((LOS+1) << 1) | (burst_size<<10); + + (void) dma_map_single(NULL, relink, 16, DMA_TO_DEVICE); } static void cmdma_write_relink_params_per2mem ( @@ -108,6 +116,8 @@ static void cmdma_write_relink_params_per2mem ( relink[3] = (((dst_addr >> 16) & 0xFFFFUL) << 16 ) | 0x1200UL | ((LOS+1) << 1) | (burst_size<<10); + + (void) dma_map_single(NULL, relink, 16, DMA_TO_DEVICE); } static int cmdma_write_cyclic_list_mem2per( @@ -176,3 +186,40 @@ static int cmdma_write_cyclic_list_per2mem( return 0; } + +static void __iomem *dmabase = 0; +int cmdma_init(void) +{ + dmabase = ioremap_nocache(U8500_DMA_BASE, PAGE_SIZE); + if (dmabase == NULL) + return -ENOMEM; + else + return 0; +} + +void cmdma_destroy(void) +{ + iounmap(dmabase); +} + +#define SSLNK_CHAN_2 (0x40C + 0x20 * 2) +#define SDLNK_CHAN_2 (0x41C + 0x20 * 2) + +void cmdma_stop_dma(void) +{ + if(cmdma_setup_relink_area_called) { + cmdma_setup_relink_area_called = false; + if (readl(dmabase + SSLNK_CHAN_2) & (0x3 << 28)) { + printk(KERN_ERR "CM: ERROR - RX DMA was running\n"); + } + if (readl(dmabase + SDLNK_CHAN_2) & (0x3 << 28)) { + printk(KERN_ERR "CM: ERROR - TX DMA was running\n"); + } + + writel(~(1 << 28), dmabase + SSLNK_CHAN_2); + while (readl(dmabase + SSLNK_CHAN_2) & (0x3 << 28)); + + writel(~(1 << 28), dmabase + SDLNK_CHAN_2); + while (readl(dmabase + SDLNK_CHAN_2) & (0x3 << 28)); + } +} diff --git a/drivers/staging/nmf-cm/cm_dma.h b/drivers/staging/nmf-cm/cm_dma.h index 6ee4caafeae..92f67b05c77 100644 --- a/drivers/staging/nmf-cm/cm_dma.h +++ b/drivers/staging/nmf-cm/cm_dma.h @@ -7,11 +7,7 @@ #ifndef __CMDMA_H #define __CMDMA_H - -enum cmdma_type { - CMDMA_MEM_2_PER, - CMDMA_PER_2_MEM -}; +#include "cmioctl.h" int cmdma_setup_relink_area( unsigned int mem_addr, @@ -21,4 +17,7 @@ int cmdma_setup_relink_area( unsigned int LOS, enum cmdma_type type); +void cmdma_stop_dma(void); +int cmdma_init(void); +void cmdma_destroy(void); #endif diff --git a/drivers/staging/nmf-cm/cm_service.c b/drivers/staging/nmf-cm/cm_service.c index cd7602a6cec..bc70afe10a0 100644 --- a/drivers/staging/nmf-cm/cm_service.c +++ b/drivers/staging/nmf-cm/cm_service.c @@ -21,6 +21,7 @@ #include "osal-kernel.h" #include "cmld.h" #include "cm_service.h" +#include "cm_dma.h" /* Panic managment */ static void service_tasklet_func(unsigned long); @@ -75,6 +76,13 @@ static void service_tasklet_func(unsigned long unused) msg.d.srv.srvData.panic = desc.u.panic; dispatch_service_msg(&msg); + /* + * Stop DMA directly before shutdown, to avoid bad sound. + * Should be called after DSP has stopped executing, to avoid the DSP + * re-starting DMA + */ + if (osalEnv.mpc[i].coreId == SIA_CORE_ID) + cmdma_stop_dma(); break; } case CM_MPC_SERVICE_PRINT: { diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index 0d1bf8ffe4e..f4be2c2d3d1 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -9,12 +9,11 @@ #include #include #include +#include #include "cmioctl.h" #include "osal-kernel.h" #include "cmld.h" -#include -#include -#include +#include "cm_dma.h" /** Dequeue and free per-process messages for specific binding * @@ -1225,40 +1224,47 @@ inline int cmld_Unmigrate(CM_Unmigrate_t __user *param) return 0; } -int cmld_SetupRelinkArea(CM_SetupRelinkArea_t __user *param) +int cmld_SetupRelinkArea(struct cm_process_priv *procPriv, + CM_SetupRelinkArea_t __user *param) { CM_SetupRelinkArea_t data; - t_cm_system_address systemAddress; - t_uint32 size; + struct list_head *cursor, *next; + struct memAreaDesc_t *entry = NULL; /* coverity[tainted_data_argument : FALSE] */ if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) return -EFAULT; - data.out.error = CM_ENGINE_GetMpcMemorySystemAddress( - data.in.mem_handle, &systemAddress); + /* check that it is actually owned by the process */ + data.out.error = CM_UNKNOWN_MEMORY_HANDLE; - if (data.out.error != CM_OK) - return 0; + if (lock_process(procPriv)) + return -ERESTARTSYS; + list_for_each_safe(cursor, next, &procPriv->memAreaDescList){ + entry = list_entry(cursor, struct memAreaDesc_t, list); + if (entry->handle == data.in.mem_handle) + break; + } + unlock_process(procPriv); - data.out.error = CM_ENGINE_GetMpcMemorySize(data.in.mem_handle, &size); - if (data.out.error != CM_OK) - return 0; + if ((entry == NULL) || (entry->handle != data.in.mem_handle)) + goto out; - if (size < data.in.segments * data.in.segmentsize) + if (entry->size < data.in.segments * data.in.segmentsize) { - return -EINVAL; + data.out.error = CM_INVALID_PARAMETER; + goto out; } data.out.error = cmdma_setup_relink_area( - systemAddress.physical, - data.in.peripheral_addr, - data.in.segments, - data.in.segmentsize, - data.in.LOS, - data.in.type); - + entry->physAddr, + data.in.peripheral_addr, + data.in.segments, + data.in.segmentsize, + data.in.LOS, + data.in.type); +out: if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) return -EFAULT; @@ -1381,7 +1387,6 @@ int cmld_PrivReserveMemory(struct cm_process_priv *procPriv, unsigned int physAd __func__, current->pid, physAddr, (int)curr->tid);*/ err = -EBUSY; } else { - //current->pid; curr->tid = current->pid; err = 0; } diff --git a/drivers/staging/nmf-cm/cmioctl.h b/drivers/staging/nmf-cm/cmioctl.h index 7ca46fc25e8..15de0e50ca4 100644 --- a/drivers/staging/nmf-cm/cmioctl.h +++ b/drivers/staging/nmf-cm/cmioctl.h @@ -16,7 +16,12 @@ #include #include #include -#include "cm_dma.h" + + +enum cmdma_type { + CMDMA_MEM_2_PER, + CMDMA_PER_2_MEM +}; #define CMLD_DEV_NAME \ { "cm_control", \ diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index 5b26762677d..158524ddcb4 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -27,6 +27,7 @@ #include "osal-kernel.h" #include "cmld.h" #include "cm_service.h" +#include "cm_dma.h" #define CMDRIVER_PATCH_VERSION 106 #define O_FLUSH 0x1000000 @@ -624,7 +625,8 @@ static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long return cmld_Unmigrate((CM_Unmigrate_t *)arg); case CM_SETUPRELINKAREA: - return cmld_SetupRelinkArea((CM_SetupRelinkArea_t *)arg); + return cmld_SetupRelinkArea(procPriv, + (CM_SetupRelinkArea_t *)arg); case CM_PUSHCOMPONENT: return cmld_PushComponent((CM_PushComponent_t *)arg); @@ -1226,7 +1228,9 @@ static int __init cmld_init_module(void) } } - return 0; + err = cmdma_init(); + if (err == 0) + return 0; out_all: if (err) { @@ -1303,6 +1307,7 @@ static void __exit cmld_cleanup_module(void) CM_ENGINE_Destroy(); + cmdma_destroy(); unmapRegions(); #ifdef CM_DEBUG_ALLOC cleanup_debug_alloc(); diff --git a/drivers/staging/nmf-cm/cmld.h b/drivers/staging/nmf-cm/cmld.h index 234e30db503..cf183328ad6 100644 --- a/drivers/staging/nmf-cm/cmld.h +++ b/drivers/staging/nmf-cm/cmld.h @@ -126,7 +126,7 @@ int cmld_GetRequiredComponentFiles(struct cm_process_priv *cmPriv, CM_GetRequiredComponentFiles_t __user *); int cmld_Migrate(CM_Migrate_t __user *); int cmld_Unmigrate(CM_Unmigrate_t __user *); -int cmld_SetupRelinkArea(CM_SetupRelinkArea_t __user *); +int cmld_SetupRelinkArea(struct cm_process_priv *, CM_SetupRelinkArea_t __user *); int cmld_PushComponent(CM_PushComponent_t __user *); int cmld_ReleaseComponent(CM_ReleaseComponent_t __user *); int cmld_PrivGetMPCMemoryDesc(struct cm_process_priv *, CM_PrivGetMPCMemoryDesc_t __user *); diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index 8f547ba0ad9..5027ac7d9f8 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -28,6 +28,7 @@ #include "osal-kernel.h" #include "cm_service.h" #include "cmld.h" +#include "cm_dma.h" __iomem void *prcmu_base = NULL; __iomem void *prcmu_tcdm_base = NULL; @@ -831,6 +832,10 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam osalEnv.mpc[idx].monitor_tsk = NULL; } + /* Stop the DMA (normally done on DSP side, but be safe) */ + if (firstParam == SIA_CORE_ID) + cmdma_stop_dma(); + /* Stop the DSP */ if (regulator_disable(osalEnv.mpc[idx].mmdsp_regulator) < 0) pr_err("CM Driver(%s): can't disable regulator %s-mmsdp\n", -- cgit v1.2.3 From 3f4e102901beba5e65e1bd355434a577a928f088 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Mon, 18 Jul 2011 18:29:14 +0200 Subject: U8500 NMF-CM: make creation of domains more robust CM_ENGINE_CreateMemoryDomain() allows the creation of domains for some other client (process ID). Today, it doesn't check the existance of the target client, what can lead to an unused domain. This patch fixes it for forbidding the creation of domain for a non-existing client. ST-Ericsson ID: 352761 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Pierre Peiffer Change-Id: Icf81e9a9c18ce204d0f3c472a1ee05b140567738 --- drivers/staging/nmf-cm/cm_syscall.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'drivers/staging/nmf-cm/cm_syscall.c') diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index f4be2c2d3d1..a687e0206a3 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -514,10 +514,25 @@ inline int cmld_CreateMemoryDomain(struct cm_process_priv *procPriv, data.out.error = CM_ENGINE_CreateMemoryDomain(procPriv->pid, &domain, &data.out.handle); - else - data.out.error = CM_ENGINE_CreateMemoryDomain(data.in.client, - &domain, - &data.out.handle); + else { + /* Check if client is valid (ie already registered) */ + struct list_head* head; + struct cm_process_priv *entry; + + list_for_each(head, &process_list) { + entry = list_entry(head, struct cm_process_priv, + entry); + if (entry->pid == data.in.client) + break; + } + if (head == &process_list) + data.out.error = CM_INVALID_PARAMETER; + else + data.out.error = + CM_ENGINE_CreateMemoryDomain(data.in.client, + &domain, + &data.out.handle); + } /* Copy results back to userspace */ if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) -- cgit v1.2.3 From 9e59fad3a482cabf425e7d6eff6a94756e1021d4 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Fri, 28 Oct 2011 11:12:48 +0200 Subject: U8500 CM: Add support to get DSP OST Trace on ARM Provide two new devices /dev/cm_sia_trace and /dev/cm_sva_trace that allow any user to retrieve live OST traces coming from DSP component by doing 'cat /dev/cm_sia_trace > file.bin'. This traces are till now available through XTI device. This feature also requires some change in OSTTrace component to be fully operationnal. ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson ID: 324035 ST-Ericsson Linux next: NA Change-Id: I351d3b294667116b8b6900ef7292f4a62d911b9a Signed-off-by: Pierre Peiffer Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/35778 Reviewed-by: QABUILD --- .../nmf-cm/cm/engine/api/control/irq_engine.h | 14 +- .../inc/executive_engine_mgt.h | 6 + .../src/executive_engine_mgt.c | 13 + .../os_adaptation_layer/inc/os_adaptation_layer.h | 4 + .../staging/nmf-cm/cm/engine/trace/inc/xtitrace.h | 8 + drivers/staging/nmf-cm/cm/engine/trace/src/panic.c | 109 +++++ drivers/staging/nmf-cm/cm_debug.c | 2 +- drivers/staging/nmf-cm/cm_service.c | 10 +- drivers/staging/nmf-cm/cm_syscall.c | 6 +- drivers/staging/nmf-cm/cmioctl.h | 8 +- drivers/staging/nmf-cm/cmld.c | 450 ++++++++++++++------- drivers/staging/nmf-cm/cmld.h | 46 +++ drivers/staging/nmf-cm/configuration.c | 46 ++- drivers/staging/nmf-cm/configuration.h | 4 +- drivers/staging/nmf-cm/ee/api/panic.idt | 3 +- drivers/staging/nmf-cm/ee/api/trace.idt | 31 ++ drivers/staging/nmf-cm/inc/nmf-def.h | 2 +- drivers/staging/nmf-cm/osal-kernel.c | 22 +- drivers/staging/nmf-cm/osal-kernel.h | 5 +- .../nmf-cm/share/communication/inc/nmf_service.h | 1 + 20 files changed, 593 insertions(+), 197 deletions(-) create mode 100644 drivers/staging/nmf-cm/ee/api/trace.idt (limited to 'drivers/staging/nmf-cm/cm_syscall.c') diff --git a/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h b/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h index 20313f13256..e3974764e91 100644 --- a/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h +++ b/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h @@ -14,6 +14,7 @@ #include #include #include +#include /*! * \brief MPCs -> HOST communication handler @@ -49,7 +50,8 @@ PUBLIC IMPORT_SHARED void CM_ProcessMpcEvent(t_nmf_core_id coreId); typedef enum { // Allowed since i CM_MPC_SERVICE_NONE = 0, //!< No service found CM_MPC_SERVICE_PANIC = 1, //!< Panic service found - CM_MPC_SERVICE_PRINT = 2 //!< Print service found + CM_MPC_SERVICE_PRINT = 2, //!< Print service found + CM_MPC_SERVICE_TRACE = 3 //!< Trace service found } t_cm_service_type; //!< Service description type /*! @@ -105,4 +107,14 @@ PUBLIC IMPORT_SHARED t_cm_error CM_ReadMPCString( char * buffer, t_uint32 bufferSize); +typedef enum { + CM_MPC_TRACE_NONE = 0, + CM_MPC_TRACE_READ = 1, + CM_MPC_TRACE_READ_OVERRUN = 2 +} t_cm_trace_type; + +PUBLIC IMPORT_SHARED t_cm_trace_type CM_ENGINE_GetNextTrace( + t_nmf_core_id coreId, + struct t_nmf_trace *trace); + #endif /* CONTROL_IRQ_ENGINE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h index aacffd15a17..0894410ae0d 100644 --- a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h @@ -24,6 +24,12 @@ typedef struct { t_memory_handle handle; t_cm_logical_address addr; } panicArea; + + // Trace Management + t_uint32 readTracePointer; + t_uint32 lastReadedTraceRevision; + t_memory_handle traceDataHandle; + struct t_nmf_trace *traceDataAddr; } t_ee_state; //TODO, juraj, this should be done more properly, like accessor method, instead making this global variable.. diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c index f2c833ff7dc..4df3d7ee0f5 100644 --- a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c @@ -21,6 +21,8 @@ #include #include +#include + #include t_ee_state eeState[NB_CORE_IDS]; @@ -130,6 +132,16 @@ PUBLIC t_cm_error cm_EEM_Init( return error; } + if((error = cm_SRV_allocateTraceBufferMemory(coreId, cm_DSP_GetState(coreId)->domainEE)) != CM_OK) + { + cm_PFM_deallocatePerfmeterDataMemory(coreId); + cm_EEM_freePanicArea(coreId); + cm_delayedDestroyComponent(eeState[coreId].instance); + eeState[coreId].instance = (t_component_instance *)0; + cm_DSP_Shutdown(coreId); + return error; + } + /* set initial stack value */ cm_writeAttribute(eeState[coreId].instance, "rtos/scheduler/topOfStack", cm_DSP_getStackAddr(coreId)); @@ -179,6 +191,7 @@ PUBLIC void cm_EEM_Close(t_nmf_core_id coreId) cm_DSP_setStackSize(coreId, 0); cm_delayedDestroyComponent(eeState[coreId].instance); eeState[coreId].instance = (t_component_instance *)0; + cm_SRV_deallocateTraceBufferMemory(coreId); cm_PFM_deallocatePerfmeterDataMemory(coreId); cm_EEM_freePanicArea(coreId); cm_DSP_Shutdown(coreId); diff --git a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h index f57c92ea41b..c9ec864795f 100644 --- a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h +++ b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h @@ -44,6 +44,10 @@ typedef t_uint8 t_nmf_osal_sync_error; #define SEM_TIMEOUT_NORMAL 3000 #define SEM_TIMEOUT_DEBUG 300000 +/*! + * \brief Operations used to support additionnal OS-specific debug feature + * \ingroup CM_ENGINE_OSAL_API + */ struct osal_debug_operations { void (*component_create)(t_component_instance *component); void (*component_destroy)(t_component_instance *component); diff --git a/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h b/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h index 6ab960b69b2..1efd4f1e699 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h +++ b/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h @@ -39,4 +39,12 @@ void cm_TRC_traceMemAlloc(t_nmfTraceAllocatorCommandDescription command, t_uint8 void cm_TRC_traceMem(t_nmfTraceAllocCommandDescription command, t_uint8 allocId, t_uint32 startAddress, t_uint32 memorySize); +/*************************/ +/* MMDSP trace buffer */ +/*************************/ +PUBLIC t_cm_error cm_SRV_allocateTraceBufferMemory(t_nmf_core_id coreId, t_cm_domain_id domainId); +PUBLIC void cm_SRV_deallocateTraceBufferMemory(t_nmf_core_id coreId); + + + #endif /* __INC_CM_TRACE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c index 9cb1a729a92..e59d9f8b1ba 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c @@ -13,6 +13,111 @@ #include #include +PUBLIC t_cm_error cm_SRV_allocateTraceBufferMemory(t_nmf_core_id coreId, t_cm_domain_id domainId) +{ + t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); + + state->traceDataHandle = cm_DM_Alloc(domainId, SDRAM_EXT16, + TRACE_BUFFER_SIZE * sizeof(struct t_nmf_trace) / 2, CM_MM_ALIGN_WORD, TRUE); + if (state->traceDataHandle == INVALID_MEMORY_HANDLE) + return CM_NO_MORE_MEMORY; + else + { + t_uint32 mmdspAddr; + int i; + + state->traceDataAddr = (struct t_nmf_trace*)cm_DSP_GetHostLogicalAddress(state->traceDataHandle); + cm_DSP_GetDspAddress(state->traceDataHandle, &mmdspAddr); + cm_writeAttribute(state->instance, "rtos/commonpart/traceDataAddr", mmdspAddr); + + eeState[coreId].readTracePointer = 0; + eeState[coreId].lastReadedTraceRevision = 0; + + for(i = 0; i < TRACE_BUFFER_SIZE; i++) + state->traceDataAddr[i].revision = 0; + + return CM_OK; + } +} + +PUBLIC void cm_SRV_deallocateTraceBufferMemory(t_nmf_core_id coreId) +{ + t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); + + state->traceDataAddr = 0; + cm_DM_Free(state->traceDataHandle, TRUE); +} + +static t_uint32 swapHalfWord(t_uint32 word) +{ + return (word >> 16) | (word << 16); +} + +PUBLIC EXPORT_SHARED t_cm_trace_type CM_ENGINE_GetNextTrace( + t_nmf_core_id coreId, + struct t_nmf_trace *trace) +{ + t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); + t_uint32 foundRevision; + t_cm_trace_type type; + + OSAL_LOCK_API(); + if (state->traceDataAddr == NULL) { + type = CM_MPC_TRACE_NONE; + goto out; + } + + foundRevision = swapHalfWord(state->traceDataAddr[state->readTracePointer].revision); + + if(foundRevision <= state->lastReadedTraceRevision) + { + // It's an old trace forgot it + type = CM_MPC_TRACE_NONE; + } + else + { + struct t_nmf_trace *traceRaw; + + if(foundRevision == state->lastReadedTraceRevision + 1) + { + type = CM_MPC_TRACE_READ; + } + else + { + type = CM_MPC_TRACE_READ_OVERRUN; + /* + * If we find that revision is bigger, thus we are in overrun, then we take the writePointer + 1 which + * correspond to the older one. + * => Here there is a window where the MMDSP could update writePointer just after + */ + state->readTracePointer = (cm_readAttributeNoError(state->instance, "rtos/commonpart/writePointer") + 1) % TRACE_BUFFER_SIZE; + } + + traceRaw = &state->traceDataAddr[state->readTracePointer]; + + trace->timeStamp = swapHalfWord(traceRaw->timeStamp); + trace->componentId = swapHalfWord(traceRaw->componentId); + trace->traceId = swapHalfWord(traceRaw->traceId); + trace->paramOpt = swapHalfWord(traceRaw->paramOpt); + trace->componentHandle = swapHalfWord(traceRaw->componentHandle); + trace->parentHandle = swapHalfWord(traceRaw->parentHandle); + + trace->params[0] = swapHalfWord(traceRaw->params[0]); + trace->params[1] = swapHalfWord(traceRaw->params[1]); + trace->params[2] = swapHalfWord(traceRaw->params[2]); + trace->params[3] = swapHalfWord(traceRaw->params[3]); + + state->readTracePointer = (state->readTracePointer + 1) % TRACE_BUFFER_SIZE; + state->lastReadedTraceRevision = swapHalfWord(traceRaw->revision); + trace->revision = state->lastReadedTraceRevision; + } + +out: + OSAL_UNLOCK_API(); + + return type; +} + /* * Panic @@ -139,6 +244,10 @@ PUBLIC EXPORT_SHARED t_cm_error CM_getServiceDescription( srcDescr->u.print.value1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); srcDescr->u.print.value2 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo2"); } + else if(serviceReason == MPC_SERVICE_TRACE) + { + *srcType = CM_MPC_SERVICE_TRACE; + } else if(serviceReason != MPC_SERVICE_NONE) { t_uint32 panicThis; diff --git a/drivers/staging/nmf-cm/cm_debug.c b/drivers/staging/nmf-cm/cm_debug.c index a934aa33e92..26446e19cdb 100644 --- a/drivers/staging/nmf-cm/cm_debug.c +++ b/drivers/staging/nmf-cm/cm_debug.c @@ -5,12 +5,12 @@ */ #include -#include #include "osal-kernel.h" #include "cm_debug.h" #ifdef CONFIG_DEBUG_FS +#include static struct dentry *cm_dir; /* nmf-cm/ */ static struct dentry *proc_dir; /* nmf-cm/proc/ */ diff --git a/drivers/staging/nmf-cm/cm_service.c b/drivers/staging/nmf-cm/cm_service.c index 70cf6f37524..a2a6ffa5b57 100644 --- a/drivers/staging/nmf-cm/cm_service.c +++ b/drivers/staging/nmf-cm/cm_service.c @@ -12,9 +12,9 @@ #include #include +#include #include #include -#include #include @@ -71,7 +71,7 @@ void dispatch_service_msg(struct osal_msg *msg) spin_lock_bh(&channelPriv->bh_lock); plist_add(&new_msg->msg_entry, &channelPriv->messageQueue); spin_unlock_bh(&channelPriv->bh_lock); - wake_up_interruptible(&channelPriv->waitq); + wake_up(&channelPriv->waitq); } } @@ -113,6 +113,12 @@ static void service_tasklet_func(unsigned long unused) desc.u.print.value2); break; } + case CM_MPC_SERVICE_TRACE: + spin_lock_bh(&osalEnv.mpc[i].trace_reader_lock); + if (osalEnv.mpc[i].trace_reader) + wake_up_process(osalEnv.mpc[i].trace_reader); + spin_unlock_bh(&osalEnv.mpc[i].trace_reader_lock); + break; default: pr_err("[CM] %s: MPC Service Type %d not supported\n", __func__, type); } diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index a687e0206a3..ca8d664abb4 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -5,11 +5,11 @@ */ #include +#include #include #include #include #include -#include #include "cmioctl.h" #include "osal-kernel.h" #include "cmld.h" @@ -1397,9 +1397,9 @@ int cmld_PrivReserveMemory(struct cm_process_priv *procPriv, unsigned int physAd /* Mark this memory area reserved for a mapping for this thread ID */ /* It must not be already reserved but this should not happen */ if (curr->tid) { - /*pr_err("%s: thread %d can't reseveved memory %x already " + pr_err("%s: thread %d can't reseveved memory %x already " "reserved for %d\n", - __func__, current->pid, physAddr, (int)curr->tid);*/ + __func__, current->pid, physAddr, curr->tid); err = -EBUSY; } else { curr->tid = current->pid; diff --git a/drivers/staging/nmf-cm/cmioctl.h b/drivers/staging/nmf-cm/cmioctl.h index 96481be38b8..5f7d5b6a349 100644 --- a/drivers/staging/nmf-cm/cmioctl.h +++ b/drivers/staging/nmf-cm/cmioctl.h @@ -29,9 +29,11 @@ enum cmdma_type { CMDMA_PER_2_MEM }; -#define CMLD_DEV_NAME \ - { "cm_control", \ - "cm_channel" \ +#define CMLD_DEV_NAME \ + { "cm_control", \ + "cm_channel", \ + "cm_sia_trace", \ + "cm_sva_trace", \ } /* diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index ef9753de7a4..17af63ac407 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -14,9 +14,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -29,7 +29,7 @@ #include "cm_service.h" #include "cm_dma.h" -#define CMDRIVER_PATCH_VERSION 117 +#define CMDRIVER_PATCH_VERSION 121 #define O_FLUSH 0x1000000 static int cmld_major; @@ -233,111 +233,6 @@ static void freeProcessPriv(struct kref *ref) OSAL_Free(entry); } -/** Driver's open method - * Allocates per-process resources: private data, wait queue, - * memory area descriptors linked list, message queue. - * - * \return POSIX error code - */ -static int cmld_open(struct inode *inode, struct file *file) -{ - struct cm_process_priv *procPriv = getProcessPriv(); - - if (IS_ERR(procPriv)) - return PTR_ERR(procPriv); - - if (iminor(inode) == 0) - file->private_data = procPriv; - else { - struct cm_channel_priv *channelPriv = (struct cm_channel_priv*)OSAL_Alloc(sizeof(*channelPriv)); - if (channelPriv == NULL) { - kref_put(&procPriv->ref, freeProcessPriv); - return -ENOMEM; - } - - channelPriv->proc = procPriv; - channelPriv->state = CHANNEL_OPEN; - - /* Initialize wait_queue, lists and mutexes */ - init_waitqueue_head(&channelPriv->waitq); - plist_head_init(&channelPriv->messageQueue); - INIT_LIST_HEAD(&channelPriv->skelList); - spin_lock_init(&channelPriv->bh_lock); - mutex_init(&channelPriv->msgQueueLock); - mutex_init(&channelPriv->skelListLock); - - tasklet_disable(&cmld_service_tasklet); - mutex_lock(&channel_lock); - list_add(&channelPriv->entry, &channel_list); - mutex_unlock(&channel_lock); - tasklet_enable(&cmld_service_tasklet); - - file->private_data = channelPriv; // store channel private struct in file descriptor - } - return 0; -} - -/** Driver's release method. - * Frees any per-process pending resource: components, bindings, memory areas. - * - * \return POSIX error code - */ -static int cmld_release(struct inode *inode, struct file *file) -{ - struct cm_process_priv* procPriv; - - /* The driver must guarantee that all related resources are released. - Thus all these checks below are necessary to release all remaining - resources still linked to this 'client', in case of abnormal process - exit. - => These are error cases ! - In the usual case, nothing should be done except the free of - the cmPriv itself - */ - - if (iminor(inode) != 0) { - struct cm_channel_priv* channelPriv; - channelPriv = file->private_data; - procPriv = channelPriv->proc; - - /* We don't need to synchronize here by using the skelListLock: - the list is only accessed during ioctl() and we can't be here - if an ioctl() is on-going */ - if (list_empty(&channelPriv->skelList)) { - /* There is no pending MPC->HOST binding - => we can quietly delete the channel */ - tasklet_disable(&cmld_service_tasklet); - mutex_lock(&channel_lock); - list_del(&channelPriv->entry); - mutex_unlock(&channel_lock); - tasklet_enable(&cmld_service_tasklet); - - /* Free all remaining messages if any */ - freeMessages(channelPriv); - - /* Free the per-channel descriptor */ - OSAL_Free(channelPriv); - } else { - /* Uh: there are still some MPC->HOST binding but we don't have the - required info to unbind them. - => we must keep all skel structures because possibly used in OSAL_PostDfc - (incoming callback msg) */ - /* We flag the channel as closed to discard any new msg that will never be read anyway */ - channelPriv->state = CHANNEL_CLOSED; - - /* Already Free all remaining messages if any, - they will never be read anyway */ - freeMessages(channelPriv); - } - } else - procPriv = file->private_data; - - kref_put(&procPriv->ref, freeProcessPriv); - file->private_data = NULL; - - return 0; -} - /** Reads Component Manager messages destinated to this process. * The message is composed by three fields: * 1) mpc2host handle (distinguishes interfaces) @@ -347,19 +242,16 @@ static int cmld_release(struct inode *inode, struct file *file) * \note cfr GetEvent() * \return POSIX error code */ -static ssize_t cmld_read(struct file *file, char *buf, size_t count, loff_t *ppos) +static ssize_t cmld_channel_read(struct file *file, char *buf, size_t count, loff_t *ppos) { int err = 0; - struct cm_channel_priv* channelPriv = (struct cm_channel_priv*)(file->private_data); + struct cm_channel_priv* channelPriv = file->private_data; int msgSize = 0; struct plist_head* messageQueue; struct osal_msg* msg; t_os_message *os_msg = (t_os_message *)buf; int block = !(file->f_flags & O_NONBLOCK); - if (iminor(file->f_dentry->d_inode) == 0) - return -ENOSYS; - messageQueue = &channelPriv->messageQueue; if (mutex_lock_killable(&channelPriv->msgQueueLock)) @@ -371,7 +263,7 @@ wait: if (block == 0) return -EAGAIN; /* Wait until there is a message to ferry up */ - if (wait_event_interruptible(channelPriv->waitq, ((!plist_head_empty(messageQueue)) || (file->f_flags & O_FLUSH)))) + if (wait_event_killable(channelPriv->waitq, ((!plist_head_empty(messageQueue)) || (file->f_flags & O_FLUSH)))) return -ERESTARTSYS; if (file->f_flags & O_FLUSH) { file->f_flags &= ~O_FLUSH; @@ -459,19 +351,21 @@ out: * * \return POSIX error code */ -static int cmld_flush(struct file *file, fl_owner_t id) +static int cmld_channel_flush(struct file *file, fl_owner_t id) { - if (iminor(file->f_dentry->d_inode) != 0) { - struct cm_channel_priv* channelPriv = (struct cm_channel_priv*)(file->private_data); - file->f_flags |= O_FLUSH; - wake_up_interruptible(&channelPriv->waitq); - } + struct cm_channel_priv* channelPriv = file->private_data; + file->f_flags |= O_FLUSH; + wake_up(&channelPriv->waitq); return 0; } -static long cmld_channel_ctl(struct file *file, unsigned int cmd, unsigned long arg) +static long cmld_channel_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cm_channel_priv *channelPriv = file->private_data; +#ifdef CONFIG_DEBUG_FS + if (wait_event_killable(dump_waitq, (!cmld_dump_ongoing))) + return -ERESTARTSYS; +#endif switch(cmd) { /* @@ -480,7 +374,7 @@ static long cmld_channel_ctl(struct file *file, unsigned int cmd, unsigned long case CM_BINDCOMPONENTTOCMCORE: return cmld_BindComponentToCMCore(channelPriv, (CM_BindComponentToCMCore_t *)arg); case CM_FLUSHCHANNEL: - return cmld_flush(file, 0); + return cmld_channel_flush(file, 0); default: pr_err("CM(%s): unsupported command %i\n", __func__, cmd); return -EINVAL; @@ -488,9 +382,18 @@ static long cmld_channel_ctl(struct file *file, unsigned int cmd, unsigned long return 0; } -static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long arg) +static long cmld_control_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cm_process_priv* procPriv = file->private_data; +#ifdef CONFIG_DEBUG_FS + if (cmd == CM_PRIV_DEBUGFS_DUMP_DONE) { + cmld_dump_ongoing = false; + wake_up(&dump_waitq); + return 0; + } else if (wait_event_killable(dump_waitq, (!cmld_dump_ongoing))) + return -ERESTARTSYS; +#endif + switch(cmd) { /* * All wrapped CM SYSCALL @@ -695,7 +598,6 @@ static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long cmld_user_has_debugfs = true; #endif return 0; - case CM_PRIV_DEBUGFS_DUMP_DONE: case CM_PRIV_DEBUGFS_WAIT_DUMP: return 0; default: @@ -706,29 +608,6 @@ static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long return 0; } -/** Driver's ioctl method - * Implements user/kernel crossing for SYSCALL API. - * - * \return POSIX error code - */ -static long cmld_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ -#ifdef CONFIG_DEBUG_FS - if (cmd == CM_PRIV_DEBUGFS_DUMP_DONE) { - cmld_dump_ongoing = false; - wake_up_interruptible(&dump_waitq); - return 0; - } else if (wait_event_interruptible(dump_waitq, (!cmld_dump_ongoing))) - return -ERESTARTSYS; -#endif - - if (iminor(filp->f_dentry->d_inode) == 0) { - return cmld_control_ctl(filp, cmd, arg); - } else { - return cmld_channel_ctl(filp, cmd, arg); - } -} - /** VMA open callback function */ static void cmld_vma_open(struct vm_area_struct* vma) { @@ -755,7 +634,7 @@ static struct vm_operations_struct cmld_remap_vm_ops = { * * \return POSIX error code */ -static int cmld_mmap(struct file* file, struct vm_area_struct* vma) +static int cmld_control_mmap(struct file *file, struct vm_area_struct *vma) { unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; struct list_head* listHead; @@ -827,6 +706,278 @@ static int cmld_mmap(struct file* file, struct vm_area_struct* vma) return 0; } +/* Driver's release method for /dev/cm_channel */ +static int cmld_channel_release(struct inode *inode, struct file *file) +{ + struct cm_channel_priv* channelPriv = file->private_data; + struct cm_process_priv* procPriv = channelPriv->proc; + + /* + * The driver must guarantee that all related resources are released. + * Thus all these checks below are necessary to release all remaining + * resources still linked to this 'client', in case of abnormal process + * exit. + * => These are error cases ! + * In the usual case, nothing should be done except the free of + * the cmPriv itself + */ + + /* We don't need to synchronize here by using the skelListLock: + the list is only accessed during ioctl() and we can't be here + if an ioctl() is on-going */ + if (list_empty(&channelPriv->skelList)) { + /* There is no pending MPC->HOST binding + => we can quietly delete the channel */ + tasklet_disable(&cmld_service_tasklet); + mutex_lock(&channel_lock); + list_del(&channelPriv->entry); + mutex_unlock(&channel_lock); + tasklet_enable(&cmld_service_tasklet); + + /* Free all remaining messages if any */ + freeMessages(channelPriv); + + /* Free the per-channel descriptor */ + OSAL_Free(channelPriv); + } else { + /* + * Uh: there are still some MPC->HOST binding but we don't have + * the required info to unbind them. + * => we must keep all skel structures because possibly used in + * OSAL_PostDfc (incoming callback msg). We flag the channel as + * closed to discard any new msg that will never be read anyway + */ + channelPriv->state = CHANNEL_CLOSED; + + /* Already Free all remaining messages if any, + they will never be read anyway */ + freeMessages(channelPriv); + } + + kref_put(&procPriv->ref, freeProcessPriv); + file->private_data = NULL; + + return 0; +} + +/* Driver's release method for /dev/cm_control */ +static int cmld_control_release(struct inode *inode, struct file *file) +{ + struct cm_process_priv* procPriv = file->private_data; + + kref_put(&procPriv->ref, freeProcessPriv); + file->private_data = NULL; + + return 0; +} + +static struct file_operations cmld_control_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = cmld_control_ioctl, + .mmap = cmld_control_mmap, + .release = cmld_control_release, +}; + +static int cmld_control_open(struct file *file) +{ + struct cm_process_priv *procPriv = getProcessPriv(); + if (IS_ERR(procPriv)) + return PTR_ERR(procPriv); + file->private_data = procPriv; + file->f_op = &cmld_control_fops; + return 0; +} + +static struct file_operations cmld_channel_fops = { + .owner = THIS_MODULE, + .read = cmld_channel_read, + .unlocked_ioctl = cmld_channel_ioctl, + .flush = cmld_channel_flush, + .release = cmld_channel_release, +}; + +static int cmld_channel_open(struct file *file) +{ + struct cm_process_priv *procPriv = getProcessPriv(); + struct cm_channel_priv *channelPriv; + + if (IS_ERR(procPriv)) + return PTR_ERR(procPriv); + + channelPriv = (struct cm_channel_priv*)OSAL_Alloc(sizeof(*channelPriv)); + if (channelPriv == NULL) { + kref_put(&procPriv->ref, freeProcessPriv); + return -ENOMEM; + } + + channelPriv->proc = procPriv; + channelPriv->state = CHANNEL_OPEN; + + /* Initialize wait_queue, lists and mutexes */ + init_waitqueue_head(&channelPriv->waitq); + plist_head_init(&channelPriv->messageQueue); + INIT_LIST_HEAD(&channelPriv->skelList); + spin_lock_init(&channelPriv->bh_lock); + mutex_init(&channelPriv->msgQueueLock); + mutex_init(&channelPriv->skelListLock); + + tasklet_disable(&cmld_service_tasklet); + mutex_lock(&channel_lock); + list_add(&channelPriv->entry, &channel_list); + mutex_unlock(&channel_lock); + tasklet_enable(&cmld_service_tasklet); + + file->private_data = channelPriv; + file->f_op = &cmld_channel_fops; + return 0; +} + +static ssize_t cmld_sxa_trace_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + struct mpcConfig *mpc = file->private_data; + size_t written = 0; + struct t_nmf_trace trace; + t_cm_trace_type traceType; + struct mmdsp_trace mmdsp_tr = { + .media = TB_MEDIA_FILE, + .receiver_dev = TB_DEV_PC, + .sender_dev = TB_DEV_TRACEBOX, + .unused = TB_TRACEBOX, + .receiver_obj = DEFAULT_RECEIVERR_OBJ, + .sender_obj = DEFAULT_SENDER_OBJ, + .transaction_id = 0, + .message_id = TB_TRACE_MSG, + .master_id = mpc->coreId+1, + .channel_id = 0, + .ost_version = OST_VERSION, + .entity = ENTITY, + .protocol_id = PROTOCOL_ID, + .btrace_hdr_flag = 0, + .btrace_hdr_subcategory = 0, + }; + + while ((count - written) >= sizeof(mmdsp_tr)) { + traceType = CM_ENGINE_GetNextTrace(mpc->coreId, &trace); + + switch (traceType) { + case CM_MPC_TRACE_READ_OVERRUN: + mmdsp_tr.size = + cpu_to_be16(offsetof(struct mmdsp_trace, + ost_version) + -offsetof(struct mmdsp_trace, + receiver_obj)); + mmdsp_tr.message_id = TB_TRACE_EXCEPTION_MSG; + mmdsp_tr.ost_master_id = TB_EXCEPTION_LONG_OVRF_PACKET; + if (copy_to_user(&buf[written], &mmdsp_tr, + offsetof(struct mmdsp_trace, + ost_version))) + return -EFAULT; + written += offsetof(struct mmdsp_trace, ost_version); + if ((count - written) < sizeof(mmdsp_tr)) + break; + case CM_MPC_TRACE_READ: { + u16 param_nr = (u16)trace.paramOpt; + u16 handle_valid = (u16)(trace.paramOpt >> 16); + u32 to_write = offsetof(struct mmdsp_trace, + parent_handle); + mmdsp_tr.transaction_id = trace.revision%256; + mmdsp_tr.message_id = TB_TRACE_MSG; + mmdsp_tr.ost_master_id = OST_MASTERID; + mmdsp_tr.timestamp = cpu_to_be64(trace.timeStamp); + mmdsp_tr.timestamp2 = cpu_to_be64(trace.timeStamp); + mmdsp_tr.component_id = cpu_to_be32(trace.componentId); + mmdsp_tr.trace_id = cpu_to_be32(trace.traceId); + mmdsp_tr.btrace_hdr_category = (trace.traceId>>16)&0xFF; + mmdsp_tr.btrace_hdr_size = BTRACE_HEADER_SIZE + + sizeof(trace.params[0]) * param_nr; + if (handle_valid) { + mmdsp_tr.parent_handle = trace.parentHandle; + mmdsp_tr.component_handle = + trace.componentHandle; + to_write += sizeof(trace.parentHandle) + + sizeof(trace.componentHandle); + mmdsp_tr.btrace_hdr_size += + sizeof(trace.parentHandle) + + sizeof(trace.componentHandle); + } + mmdsp_tr.size = + cpu_to_be16(to_write + + (sizeof(trace.params[0])*param_nr) + - offsetof(struct mmdsp_trace, + receiver_obj)); + mmdsp_tr.length = to_write + + (sizeof(trace.params[0])*param_nr) + - offsetof(struct mmdsp_trace, + timestamp2); + if (copy_to_user(&buf[written], &mmdsp_tr, to_write)) + return -EFAULT; + written += to_write; + /* write param */ + to_write = sizeof(trace.params[0]) * param_nr; + if (copy_to_user(&buf[written], trace.params, to_write)) + return -EFAULT; + written += to_write; + break; + } + case CM_MPC_TRACE_NONE: + default: + if ((file->f_flags & O_NONBLOCK) || written) + return written; + spin_lock_bh(&mpc->trace_reader_lock); + mpc->trace_reader = current; + spin_unlock_bh(&mpc->trace_reader_lock); + schedule_timeout_killable(msecs_to_jiffies(200)); + spin_lock_bh(&mpc->trace_reader_lock); + mpc->trace_reader = NULL; + spin_unlock_bh(&mpc->trace_reader_lock); + if (signal_pending(current)) + return -ERESTARTSYS; + } + } + return written; +} + +/* Driver's release method for /dev/cm_sxa_trace */ +static int cmld_sxa_trace_release(struct inode *inode, struct file *file) +{ + struct mpcConfig *mpc = file->private_data; + atomic_dec(&mpc->trace_read_count); + return 0; +} + +static struct file_operations cmld_sxa_trace_fops = { + .owner = THIS_MODULE, + .read = cmld_sxa_trace_read, + .release = cmld_sxa_trace_release, +}; + +static int cmld_sxa_trace_open(struct file *file, struct mpcConfig *mpc) +{ + if (atomic_add_unless(&mpc->trace_read_count, 1, 1) == 0) + return -EBUSY; + + file->private_data = mpc; + file->f_op = &cmld_sxa_trace_fops; + return 0; +} + +/* driver open() call: specific */ +static int cmld_open(struct inode *inode, struct file *file) +{ + switch (iminor(inode)) { + case 0: + return cmld_control_open(file); + case 1: + return cmld_channel_open(file); + case 2: + return cmld_sxa_trace_open(file, &osalEnv.mpc[SIA]); + case 3: + return cmld_sxa_trace_open(file, &osalEnv.mpc[SVA]); + default: + return -ENOSYS; + } +} + /** MPC Events tasklet * The parameter is used to know from which interrupts we're comming * and which core to pass to CM_ProcessMpcEvent(): @@ -882,12 +1033,7 @@ static irqreturn_t panic_handler(int irq, void *idx) */ static struct file_operations cmld_fops = { .owner = THIS_MODULE, - .read = cmld_read, - .unlocked_ioctl = cmld_ioctl, - .mmap = cmld_mmap, .open = cmld_open, - .flush = cmld_flush, - .release = cmld_release, }; /** diff --git a/drivers/staging/nmf-cm/cmld.h b/drivers/staging/nmf-cm/cmld.h index 4c5a5bed7e6..17e6c55ff61 100644 --- a/drivers/staging/nmf-cm/cmld.h +++ b/drivers/staging/nmf-cm/cmld.h @@ -79,6 +79,52 @@ extern bool cmld_user_has_debugfs; /**< Whether user side has proper support of extern bool cmld_dump_ongoing; /**< Whether a dump is on-going */ #endif +/* Structure used to embed DSP traces */ +#define TB_MEDIA_FILE 0x1C +#define TB_DEV_PC 0x10 +#define TB_DEV_TRACEBOX 0x4C +#define TB_TRACEBOX 0x7C +#define DEFAULT_RECEIVERR_OBJ 0x0 +#define DEFAULT_SENDER_OBJ 0x0A +#define TB_TRACE_MSG 0x94 +#define TB_TRACE_EXCEPTION_MSG 0x95 +#define TB_EXCEPTION_LONG_OVRF_PACKET 0x07 +#define OST_MASTERID 0x08 +#define OST_VERSION 0x05 +#define ENTITY 0xAA +#define PROTOCOL_ID 0x03 +#define BTRACE_HEADER_SIZE 4 + +struct __attribute__ ((__packed__)) mmdsp_trace { + u8 media; + u8 receiver_dev; + u8 sender_dev; + u8 unused; + u16 size; + u8 receiver_obj; + u8 sender_obj; + u8 transaction_id; + u8 message_id; + u8 master_id; + u8 channel_id; + u64 timestamp; + u8 ost_master_id; + u8 ost_version; + u8 entity; + u8 protocol_id; + u8 length; + u64 timestamp2; + u32 component_id; + u32 trace_id; + u8 btrace_hdr_size; + u8 btrace_hdr_flag; + u8 btrace_hdr_category; + u8 btrace_hdr_subcategory; + u32 parent_handle; + u32 component_handle; + u32 params[4]; +}; + /** Lock/unlock per process mutex * * \note Must be taken before tasklet_disable (if necessary)! diff --git a/drivers/staging/nmf-cm/configuration.c b/drivers/staging/nmf-cm/configuration.c index d62bcb45500..523874fc586 100644 --- a/drivers/staging/nmf-cm/configuration.c +++ b/drivers/staging/nmf-cm/configuration.c @@ -21,28 +21,30 @@ struct OsalEnvironment osalEnv = { .mpc = { { - .coreId = SVA_CORE_ID, - .name = "sva", - .base_phys = (void*)U8500_SVA_BASE, - .interrupt0 = IRQ_DB8500_SVA, - .interrupt1 = IRQ_DB8500_SVA2, - .mmdsp_regulator = NULL, - .pipe_regulator = NULL, - .monitor_tsk = NULL, - .hwmem_code = NULL, - .hwmem_data = NULL, + .coreId = SVA_CORE_ID, + .name = "sva", + .base_phys = (void*)U8500_SVA_BASE, + .interrupt0 = IRQ_DB8500_SVA, + .interrupt1 = IRQ_DB8500_SVA2, + .mmdsp_regulator = NULL, + .pipe_regulator = NULL, + .monitor_tsk = NULL, + .hwmem_code = NULL, + .hwmem_data = NULL, + .trace_read_count = ATOMIC_INIT(0), }, { - .coreId = SIA_CORE_ID, - .name = "sia", - .base_phys = (void*)U8500_SIA_BASE, - .interrupt0 = IRQ_DB8500_SIA, - .interrupt1 = IRQ_DB8500_SIA2, - .mmdsp_regulator = NULL, - .pipe_regulator = NULL, - .monitor_tsk = NULL, - .hwmem_code = NULL, - .hwmem_data = NULL, + .coreId = SIA_CORE_ID, + .name = "sia", + .base_phys = (void*)U8500_SIA_BASE, + .interrupt0 = IRQ_DB8500_SIA, + .interrupt1 = IRQ_DB8500_SIA2, + .mmdsp_regulator = NULL, + .pipe_regulator = NULL, + .monitor_tsk = NULL, + .hwmem_code = NULL, + .hwmem_data = NULL, + .trace_read_count = ATOMIC_INIT(0), } }, .esram_regulator = { NULL, NULL}, @@ -125,16 +127,20 @@ int init_config(void) pr_err("SDRAM data size for SVA must be greater than 0\n"); return -EINVAL; } + osalEnv.mpc[SVA].nbYramBanks = cfgMpcYBanks_SVA; osalEnv.mpc[SVA].eeId = cfgSchedulerTypeHybrid_SVA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; osalEnv.mpc[SVA].sdram_code.size = cfgMpcSDRAMCodeSize_SVA * ONE_KB; osalEnv.mpc[SVA].sdram_data.size = cfgMpcSDRAMDataSize_SVA * ONE_KB; osalEnv.mpc[SVA].base.size = 128*ONE_KB; //we expose only TCM24 + spin_lock_init(&osalEnv.mpc[SVA].trace_reader_lock); + osalEnv.mpc[SIA].nbYramBanks = cfgMpcYBanks_SIA; osalEnv.mpc[SIA].eeId = cfgSchedulerTypeHybrid_SIA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; osalEnv.mpc[SIA].sdram_code.size = cfgMpcSDRAMCodeSize_SIA * ONE_KB; osalEnv.mpc[SIA].sdram_data.size = cfgMpcSDRAMDataSize_SIA * ONE_KB; osalEnv.mpc[SIA].base.size = 128*ONE_KB; //we expose only TCM24 + spin_lock_init(&osalEnv.mpc[SIA].trace_reader_lock); return 0; } diff --git a/drivers/staging/nmf-cm/configuration.h b/drivers/staging/nmf-cm/configuration.h index 35072831a13..f4146dc6117 100644 --- a/drivers/staging/nmf-cm/configuration.h +++ b/drivers/staging/nmf-cm/configuration.h @@ -20,12 +20,14 @@ #endif /* Embedded Static RAM base address */ -#define ESRAM_BASE (U8500_ESRAM_BASE + 0x10000) // V1/V2 config: 0-64k: secure; +/* config: 0-64k: secure */ +#define ESRAM_BASE (U8500_ESRAM_BASE + U8500_ESRAM_DMA_LCPA_OFFSET) /* * Embedded ram size for CM (in Kb) * 5 banks of 128k: skip the first half bank (secure) and the last * one (used for MCDE/B2R2), but include DMA part (4k after the secure part) + * to give access from DSP side */ #define ESRAM_SIZE 448 enum { diff --git a/drivers/staging/nmf-cm/ee/api/panic.idt b/drivers/staging/nmf-cm/ee/api/panic.idt index f971fdad8c5..53135819f4a 100644 --- a/drivers/staging/nmf-cm/ee/api/panic.idt +++ b/drivers/staging/nmf-cm/ee/api/panic.idt @@ -55,7 +55,8 @@ typedef enum { INTERFACE_NOT_BINDED = 8, USER_PANIC = 9, UNBIND_INTERRUPT = 10, - EVENT_FIFO_IN_USE = 11 + EVENT_FIFO_IN_USE = 11, + RESERVED_PANIC = 2 //for COMPATIBILITY with previous versions of NMF, to be deprecated } t_panic_reasonDescription; /*! diff --git a/drivers/staging/nmf-cm/ee/api/trace.idt b/drivers/staging/nmf-cm/ee/api/trace.idt new file mode 100644 index 00000000000..3c21c6a860f --- /dev/null +++ b/drivers/staging/nmf-cm/ee/api/trace.idt @@ -0,0 +1,31 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \defgroup NMF_EE_TYPE Execution Engine Common Type Definitions + * \ingroup COMMON + */ + +#ifndef __INC_TRACE_IDT +#define __INC_TRACE_IDT + +struct t_nmf_trace +{ + t_uint32 revision; + t_uint32 timeStamp; + t_uint32 componentId; + t_uint32 traceId; + t_uint32 paramOpt; + t_uint32 componentHandle; + t_uint32 parentHandle; + t_uint32 params[4]; +}; + +#define TRACE_BUFFER_SIZE 128 + +#endif diff --git a/drivers/staging/nmf-cm/inc/nmf-def.h b/drivers/staging/nmf-cm/inc/nmf-def.h index e671198f7b9..5cb1ec7fcec 100644 --- a/drivers/staging/nmf-cm/inc/nmf-def.h +++ b/drivers/staging/nmf-cm/inc/nmf-def.h @@ -21,7 +21,7 @@ * * \ingroup NMF_VERSION */ -#define NMF_VERSION ((2 << 16) | (10 << 8) | (118)) +#define NMF_VERSION ((2 << 16) | (10 << 8) | (121)) /*! * \brief Get NMF major version corresponding to NMF version number diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index 94aa11fc91c..e79e35db106 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -353,7 +353,7 @@ void OSAL_PostDfc(t_nmf_mpc2host_handle upLayerTHIS, t_uint32 methodIndex, t_eve spin_unlock_bh(&skelwrapper->channelPriv->bh_lock); /* Wake up process' wait queue */ - wake_up_interruptible(&skelwrapper->channelPriv->waitq); + wake_up(&skelwrapper->channelPriv->waitq); } @@ -755,8 +755,8 @@ static int dspload_monitor(void *idx) /* init counter */ if (CM_GetMpcLoadCounter(mpc->coreId, &mpc->oldLoadCounter) != CM_OK) - pr_err("CM Driver: Failed to init load counter for %s\n", - mpc->name); + pr_warn("CM Driver: Failed to init load counter for %s\n", + mpc->name); while (!kthread_should_stop()) { t_cm_mpc_load_counter loadCounter; @@ -919,7 +919,7 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam /* Compute the relative end address of the range, relative to base address of BANK1 */ - secondParam = (firstParam+secondParam-(U8500_ESRAM_BASE+0x20000)-1); + secondParam = (firstParam+secondParam-U8500_ESRAM_BANK1-1); /* if end is below base address of BANK1, it means that full range of addresses is on Bank0 */ @@ -927,16 +927,16 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam break; /* Compute the index of the last bank accessed among esram 1+2 and esram 3+4 banks */ - secondParam /= 0x40000; + secondParam /= (2*U8500_ESRAM_BANK_SIZE); WARN_ON(secondParam > 1); /* Compute the index of the first bank accessed among esram 1+2 and esram 3+4 banks Do not manage Bank 0 (secured, must be always ON) */ - if (firstParam < (U8500_ESRAM_BASE+0x20000)) + if (firstParam < U8500_ESRAM_BANK1) firstParam = 0; else - firstParam = (firstParam-(U8500_ESRAM_BASE+0x20000))/0x40000; + firstParam = (firstParam-U8500_ESRAM_BANK1)/(2*U8500_ESRAM_BANK_SIZE); /* power off the banks 1+2 and 3+4 if accessed. */ for (i=firstParam; i<=secondParam; i++) { @@ -1032,7 +1032,7 @@ t_cm_error OSAL_EnablePwrRessource(t_nmf_power_resource resource, t_uint32 first /* Compute the relative end address of the range, relative to base address of BANK1 */ - secondParam = (firstParam+secondParam-(U8500_ESRAM_BASE+0x20000)-1); + secondParam = (firstParam+secondParam-U8500_ESRAM_BANK1-1); /* if end is below base address of BANK1, it means that full range of addresses is on Bank0 */ @@ -1040,16 +1040,16 @@ t_cm_error OSAL_EnablePwrRessource(t_nmf_power_resource resource, t_uint32 first break; /* Compute the index of the last bank accessed among esram 1+2 and esram 3+4 banks */ - secondParam /= 0x40000; + secondParam /= (2*U8500_ESRAM_BANK_SIZE); WARN_ON(secondParam > 1); /* Compute the index of the first bank accessed among esram 1+2 and esram 3+4 banks Do not manage Bank 0 (secured, must be always ON) */ - if (firstParam < (U8500_ESRAM_BASE+0x20000)) + if (firstParam < U8500_ESRAM_BANK1) firstParam = 0; else - firstParam = (firstParam-(U8500_ESRAM_BASE+0x20000))/0x40000; + firstParam = (firstParam-U8500_ESRAM_BANK1)/(2*U8500_ESRAM_BANK_SIZE); /* power on the banks 1+2 and 3+4 if accessed. */ for (i=firstParam; i<=secondParam; i++) { diff --git a/drivers/staging/nmf-cm/osal-kernel.h b/drivers/staging/nmf-cm/osal-kernel.h index 7a71bdd591d..dc9bc8445ac 100644 --- a/drivers/staging/nmf-cm/osal-kernel.h +++ b/drivers/staging/nmf-cm/osal-kernel.h @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef CONFIG_HAS_WAKELOCK #include #endif @@ -24,7 +25,6 @@ */ #define _CM_ELF_H #include -#include #include "configuration.h" @@ -56,6 +56,9 @@ struct mpcConfig { #endif struct task_struct *monitor_tsk; /**< task to monitor the dsp load; */ t_cm_mpc_load_counter oldLoadCounter; /**< previous load counter of the DSP */ + atomic_t trace_read_count; /**< number of trace reader */ + spinlock_t trace_reader_lock; + struct task_struct *trace_reader;/**< current reader task */ #ifdef CONFIG_DEBUG_FS struct dentry *dir; /**< debugfs dir entry */ struct dentry *comp_dir; /**< debugfs component dir entry */ diff --git a/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h b/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h index 5ec08434492..71dfc534f97 100644 --- a/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h +++ b/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h @@ -12,5 +12,6 @@ #define MPC_SERVICE_NONE 0 #define MPC_SERVICE_BOOT 0xB001 #define MPC_SERVICE_PRINT 0x1234 +#define MPC_SERVICE_TRACE 0x789 #endif -- cgit v1.2.3 From 04b1247ada3eca9aef2a976b1778f571f878c121 Mon Sep 17 00:00:00 2001 From: himansh Date: Wed, 9 Nov 2011 16:11:59 +0530 Subject: Revert "U8500 CM: Add support to get DSP OST Trace on ARM" This reverts commit 6cfa5e388f0250764e7b9d11d2c3f141b408a93e. ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson ID: 373198 ST-Ericsson Linux next: NA Change-Id: I0ff4c175c3e1c0c7070b76719e1ad51d390221c9 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/37036 Reviewed-by: Himanshu AGRAWAL Reviewed-by: Swinder Pal SINGH Tested-by: Himanshu AGRAWAL Reviewed-by: Sarvesh SANT --- .../nmf-cm/cm/engine/api/control/irq_engine.h | 14 +- .../inc/executive_engine_mgt.h | 6 - .../src/executive_engine_mgt.c | 13 - .../os_adaptation_layer/inc/os_adaptation_layer.h | 4 - .../staging/nmf-cm/cm/engine/trace/inc/xtitrace.h | 8 - drivers/staging/nmf-cm/cm/engine/trace/src/panic.c | 109 ----- drivers/staging/nmf-cm/cm_debug.c | 2 +- drivers/staging/nmf-cm/cm_service.c | 10 +- drivers/staging/nmf-cm/cm_syscall.c | 6 +- drivers/staging/nmf-cm/cmioctl.h | 8 +- drivers/staging/nmf-cm/cmld.c | 450 +++++++-------------- drivers/staging/nmf-cm/cmld.h | 46 --- drivers/staging/nmf-cm/configuration.c | 46 +-- drivers/staging/nmf-cm/configuration.h | 4 +- drivers/staging/nmf-cm/ee/api/panic.idt | 3 +- drivers/staging/nmf-cm/ee/api/trace.idt | 31 -- drivers/staging/nmf-cm/inc/nmf-def.h | 2 +- drivers/staging/nmf-cm/osal-kernel.c | 22 +- drivers/staging/nmf-cm/osal-kernel.h | 5 +- .../nmf-cm/share/communication/inc/nmf_service.h | 1 - 20 files changed, 197 insertions(+), 593 deletions(-) delete mode 100644 drivers/staging/nmf-cm/ee/api/trace.idt (limited to 'drivers/staging/nmf-cm/cm_syscall.c') diff --git a/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h b/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h index e3974764e91..20313f13256 100644 --- a/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h +++ b/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h @@ -14,7 +14,6 @@ #include #include #include -#include /*! * \brief MPCs -> HOST communication handler @@ -50,8 +49,7 @@ PUBLIC IMPORT_SHARED void CM_ProcessMpcEvent(t_nmf_core_id coreId); typedef enum { // Allowed since i CM_MPC_SERVICE_NONE = 0, //!< No service found CM_MPC_SERVICE_PANIC = 1, //!< Panic service found - CM_MPC_SERVICE_PRINT = 2, //!< Print service found - CM_MPC_SERVICE_TRACE = 3 //!< Trace service found + CM_MPC_SERVICE_PRINT = 2 //!< Print service found } t_cm_service_type; //!< Service description type /*! @@ -107,14 +105,4 @@ PUBLIC IMPORT_SHARED t_cm_error CM_ReadMPCString( char * buffer, t_uint32 bufferSize); -typedef enum { - CM_MPC_TRACE_NONE = 0, - CM_MPC_TRACE_READ = 1, - CM_MPC_TRACE_READ_OVERRUN = 2 -} t_cm_trace_type; - -PUBLIC IMPORT_SHARED t_cm_trace_type CM_ENGINE_GetNextTrace( - t_nmf_core_id coreId, - struct t_nmf_trace *trace); - #endif /* CONTROL_IRQ_ENGINE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h index 0894410ae0d..aacffd15a17 100644 --- a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h @@ -24,12 +24,6 @@ typedef struct { t_memory_handle handle; t_cm_logical_address addr; } panicArea; - - // Trace Management - t_uint32 readTracePointer; - t_uint32 lastReadedTraceRevision; - t_memory_handle traceDataHandle; - struct t_nmf_trace *traceDataAddr; } t_ee_state; //TODO, juraj, this should be done more properly, like accessor method, instead making this global variable.. diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c index 4df3d7ee0f5..f2c833ff7dc 100644 --- a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c @@ -21,8 +21,6 @@ #include #include -#include - #include t_ee_state eeState[NB_CORE_IDS]; @@ -132,16 +130,6 @@ PUBLIC t_cm_error cm_EEM_Init( return error; } - if((error = cm_SRV_allocateTraceBufferMemory(coreId, cm_DSP_GetState(coreId)->domainEE)) != CM_OK) - { - cm_PFM_deallocatePerfmeterDataMemory(coreId); - cm_EEM_freePanicArea(coreId); - cm_delayedDestroyComponent(eeState[coreId].instance); - eeState[coreId].instance = (t_component_instance *)0; - cm_DSP_Shutdown(coreId); - return error; - } - /* set initial stack value */ cm_writeAttribute(eeState[coreId].instance, "rtos/scheduler/topOfStack", cm_DSP_getStackAddr(coreId)); @@ -191,7 +179,6 @@ PUBLIC void cm_EEM_Close(t_nmf_core_id coreId) cm_DSP_setStackSize(coreId, 0); cm_delayedDestroyComponent(eeState[coreId].instance); eeState[coreId].instance = (t_component_instance *)0; - cm_SRV_deallocateTraceBufferMemory(coreId); cm_PFM_deallocatePerfmeterDataMemory(coreId); cm_EEM_freePanicArea(coreId); cm_DSP_Shutdown(coreId); diff --git a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h index c9ec864795f..f57c92ea41b 100644 --- a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h +++ b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h @@ -44,10 +44,6 @@ typedef t_uint8 t_nmf_osal_sync_error; #define SEM_TIMEOUT_NORMAL 3000 #define SEM_TIMEOUT_DEBUG 300000 -/*! - * \brief Operations used to support additionnal OS-specific debug feature - * \ingroup CM_ENGINE_OSAL_API - */ struct osal_debug_operations { void (*component_create)(t_component_instance *component); void (*component_destroy)(t_component_instance *component); diff --git a/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h b/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h index 1efd4f1e699..6ab960b69b2 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h +++ b/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h @@ -39,12 +39,4 @@ void cm_TRC_traceMemAlloc(t_nmfTraceAllocatorCommandDescription command, t_uint8 void cm_TRC_traceMem(t_nmfTraceAllocCommandDescription command, t_uint8 allocId, t_uint32 startAddress, t_uint32 memorySize); -/*************************/ -/* MMDSP trace buffer */ -/*************************/ -PUBLIC t_cm_error cm_SRV_allocateTraceBufferMemory(t_nmf_core_id coreId, t_cm_domain_id domainId); -PUBLIC void cm_SRV_deallocateTraceBufferMemory(t_nmf_core_id coreId); - - - #endif /* __INC_CM_TRACE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c index e59d9f8b1ba..9cb1a729a92 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c @@ -13,111 +13,6 @@ #include #include -PUBLIC t_cm_error cm_SRV_allocateTraceBufferMemory(t_nmf_core_id coreId, t_cm_domain_id domainId) -{ - t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); - - state->traceDataHandle = cm_DM_Alloc(domainId, SDRAM_EXT16, - TRACE_BUFFER_SIZE * sizeof(struct t_nmf_trace) / 2, CM_MM_ALIGN_WORD, TRUE); - if (state->traceDataHandle == INVALID_MEMORY_HANDLE) - return CM_NO_MORE_MEMORY; - else - { - t_uint32 mmdspAddr; - int i; - - state->traceDataAddr = (struct t_nmf_trace*)cm_DSP_GetHostLogicalAddress(state->traceDataHandle); - cm_DSP_GetDspAddress(state->traceDataHandle, &mmdspAddr); - cm_writeAttribute(state->instance, "rtos/commonpart/traceDataAddr", mmdspAddr); - - eeState[coreId].readTracePointer = 0; - eeState[coreId].lastReadedTraceRevision = 0; - - for(i = 0; i < TRACE_BUFFER_SIZE; i++) - state->traceDataAddr[i].revision = 0; - - return CM_OK; - } -} - -PUBLIC void cm_SRV_deallocateTraceBufferMemory(t_nmf_core_id coreId) -{ - t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); - - state->traceDataAddr = 0; - cm_DM_Free(state->traceDataHandle, TRUE); -} - -static t_uint32 swapHalfWord(t_uint32 word) -{ - return (word >> 16) | (word << 16); -} - -PUBLIC EXPORT_SHARED t_cm_trace_type CM_ENGINE_GetNextTrace( - t_nmf_core_id coreId, - struct t_nmf_trace *trace) -{ - t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); - t_uint32 foundRevision; - t_cm_trace_type type; - - OSAL_LOCK_API(); - if (state->traceDataAddr == NULL) { - type = CM_MPC_TRACE_NONE; - goto out; - } - - foundRevision = swapHalfWord(state->traceDataAddr[state->readTracePointer].revision); - - if(foundRevision <= state->lastReadedTraceRevision) - { - // It's an old trace forgot it - type = CM_MPC_TRACE_NONE; - } - else - { - struct t_nmf_trace *traceRaw; - - if(foundRevision == state->lastReadedTraceRevision + 1) - { - type = CM_MPC_TRACE_READ; - } - else - { - type = CM_MPC_TRACE_READ_OVERRUN; - /* - * If we find that revision is bigger, thus we are in overrun, then we take the writePointer + 1 which - * correspond to the older one. - * => Here there is a window where the MMDSP could update writePointer just after - */ - state->readTracePointer = (cm_readAttributeNoError(state->instance, "rtos/commonpart/writePointer") + 1) % TRACE_BUFFER_SIZE; - } - - traceRaw = &state->traceDataAddr[state->readTracePointer]; - - trace->timeStamp = swapHalfWord(traceRaw->timeStamp); - trace->componentId = swapHalfWord(traceRaw->componentId); - trace->traceId = swapHalfWord(traceRaw->traceId); - trace->paramOpt = swapHalfWord(traceRaw->paramOpt); - trace->componentHandle = swapHalfWord(traceRaw->componentHandle); - trace->parentHandle = swapHalfWord(traceRaw->parentHandle); - - trace->params[0] = swapHalfWord(traceRaw->params[0]); - trace->params[1] = swapHalfWord(traceRaw->params[1]); - trace->params[2] = swapHalfWord(traceRaw->params[2]); - trace->params[3] = swapHalfWord(traceRaw->params[3]); - - state->readTracePointer = (state->readTracePointer + 1) % TRACE_BUFFER_SIZE; - state->lastReadedTraceRevision = swapHalfWord(traceRaw->revision); - trace->revision = state->lastReadedTraceRevision; - } - -out: - OSAL_UNLOCK_API(); - - return type; -} - /* * Panic @@ -244,10 +139,6 @@ PUBLIC EXPORT_SHARED t_cm_error CM_getServiceDescription( srcDescr->u.print.value1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); srcDescr->u.print.value2 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo2"); } - else if(serviceReason == MPC_SERVICE_TRACE) - { - *srcType = CM_MPC_SERVICE_TRACE; - } else if(serviceReason != MPC_SERVICE_NONE) { t_uint32 panicThis; diff --git a/drivers/staging/nmf-cm/cm_debug.c b/drivers/staging/nmf-cm/cm_debug.c index 26446e19cdb..a934aa33e92 100644 --- a/drivers/staging/nmf-cm/cm_debug.c +++ b/drivers/staging/nmf-cm/cm_debug.c @@ -5,12 +5,12 @@ */ #include +#include #include "osal-kernel.h" #include "cm_debug.h" #ifdef CONFIG_DEBUG_FS -#include static struct dentry *cm_dir; /* nmf-cm/ */ static struct dentry *proc_dir; /* nmf-cm/proc/ */ diff --git a/drivers/staging/nmf-cm/cm_service.c b/drivers/staging/nmf-cm/cm_service.c index a2a6ffa5b57..70cf6f37524 100644 --- a/drivers/staging/nmf-cm/cm_service.c +++ b/drivers/staging/nmf-cm/cm_service.c @@ -12,9 +12,9 @@ #include #include -#include #include #include +#include #include @@ -71,7 +71,7 @@ void dispatch_service_msg(struct osal_msg *msg) spin_lock_bh(&channelPriv->bh_lock); plist_add(&new_msg->msg_entry, &channelPriv->messageQueue); spin_unlock_bh(&channelPriv->bh_lock); - wake_up(&channelPriv->waitq); + wake_up_interruptible(&channelPriv->waitq); } } @@ -113,12 +113,6 @@ static void service_tasklet_func(unsigned long unused) desc.u.print.value2); break; } - case CM_MPC_SERVICE_TRACE: - spin_lock_bh(&osalEnv.mpc[i].trace_reader_lock); - if (osalEnv.mpc[i].trace_reader) - wake_up_process(osalEnv.mpc[i].trace_reader); - spin_unlock_bh(&osalEnv.mpc[i].trace_reader_lock); - break; default: pr_err("[CM] %s: MPC Service Type %d not supported\n", __func__, type); } diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index ca8d664abb4..a687e0206a3 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -5,11 +5,11 @@ */ #include -#include #include #include #include #include +#include #include "cmioctl.h" #include "osal-kernel.h" #include "cmld.h" @@ -1397,9 +1397,9 @@ int cmld_PrivReserveMemory(struct cm_process_priv *procPriv, unsigned int physAd /* Mark this memory area reserved for a mapping for this thread ID */ /* It must not be already reserved but this should not happen */ if (curr->tid) { - pr_err("%s: thread %d can't reseveved memory %x already " + /*pr_err("%s: thread %d can't reseveved memory %x already " "reserved for %d\n", - __func__, current->pid, physAddr, curr->tid); + __func__, current->pid, physAddr, (int)curr->tid);*/ err = -EBUSY; } else { curr->tid = current->pid; diff --git a/drivers/staging/nmf-cm/cmioctl.h b/drivers/staging/nmf-cm/cmioctl.h index 5f7d5b6a349..96481be38b8 100644 --- a/drivers/staging/nmf-cm/cmioctl.h +++ b/drivers/staging/nmf-cm/cmioctl.h @@ -29,11 +29,9 @@ enum cmdma_type { CMDMA_PER_2_MEM }; -#define CMLD_DEV_NAME \ - { "cm_control", \ - "cm_channel", \ - "cm_sia_trace", \ - "cm_sva_trace", \ +#define CMLD_DEV_NAME \ + { "cm_control", \ + "cm_channel" \ } /* diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index 17af63ac407..ef9753de7a4 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -14,9 +14,9 @@ #include #include #include -#include #include #include +#include #include #include @@ -29,7 +29,7 @@ #include "cm_service.h" #include "cm_dma.h" -#define CMDRIVER_PATCH_VERSION 121 +#define CMDRIVER_PATCH_VERSION 117 #define O_FLUSH 0x1000000 static int cmld_major; @@ -233,6 +233,111 @@ static void freeProcessPriv(struct kref *ref) OSAL_Free(entry); } +/** Driver's open method + * Allocates per-process resources: private data, wait queue, + * memory area descriptors linked list, message queue. + * + * \return POSIX error code + */ +static int cmld_open(struct inode *inode, struct file *file) +{ + struct cm_process_priv *procPriv = getProcessPriv(); + + if (IS_ERR(procPriv)) + return PTR_ERR(procPriv); + + if (iminor(inode) == 0) + file->private_data = procPriv; + else { + struct cm_channel_priv *channelPriv = (struct cm_channel_priv*)OSAL_Alloc(sizeof(*channelPriv)); + if (channelPriv == NULL) { + kref_put(&procPriv->ref, freeProcessPriv); + return -ENOMEM; + } + + channelPriv->proc = procPriv; + channelPriv->state = CHANNEL_OPEN; + + /* Initialize wait_queue, lists and mutexes */ + init_waitqueue_head(&channelPriv->waitq); + plist_head_init(&channelPriv->messageQueue); + INIT_LIST_HEAD(&channelPriv->skelList); + spin_lock_init(&channelPriv->bh_lock); + mutex_init(&channelPriv->msgQueueLock); + mutex_init(&channelPriv->skelListLock); + + tasklet_disable(&cmld_service_tasklet); + mutex_lock(&channel_lock); + list_add(&channelPriv->entry, &channel_list); + mutex_unlock(&channel_lock); + tasklet_enable(&cmld_service_tasklet); + + file->private_data = channelPriv; // store channel private struct in file descriptor + } + return 0; +} + +/** Driver's release method. + * Frees any per-process pending resource: components, bindings, memory areas. + * + * \return POSIX error code + */ +static int cmld_release(struct inode *inode, struct file *file) +{ + struct cm_process_priv* procPriv; + + /* The driver must guarantee that all related resources are released. + Thus all these checks below are necessary to release all remaining + resources still linked to this 'client', in case of abnormal process + exit. + => These are error cases ! + In the usual case, nothing should be done except the free of + the cmPriv itself + */ + + if (iminor(inode) != 0) { + struct cm_channel_priv* channelPriv; + channelPriv = file->private_data; + procPriv = channelPriv->proc; + + /* We don't need to synchronize here by using the skelListLock: + the list is only accessed during ioctl() and we can't be here + if an ioctl() is on-going */ + if (list_empty(&channelPriv->skelList)) { + /* There is no pending MPC->HOST binding + => we can quietly delete the channel */ + tasklet_disable(&cmld_service_tasklet); + mutex_lock(&channel_lock); + list_del(&channelPriv->entry); + mutex_unlock(&channel_lock); + tasklet_enable(&cmld_service_tasklet); + + /* Free all remaining messages if any */ + freeMessages(channelPriv); + + /* Free the per-channel descriptor */ + OSAL_Free(channelPriv); + } else { + /* Uh: there are still some MPC->HOST binding but we don't have the + required info to unbind them. + => we must keep all skel structures because possibly used in OSAL_PostDfc + (incoming callback msg) */ + /* We flag the channel as closed to discard any new msg that will never be read anyway */ + channelPriv->state = CHANNEL_CLOSED; + + /* Already Free all remaining messages if any, + they will never be read anyway */ + freeMessages(channelPriv); + } + } else + procPriv = file->private_data; + + kref_put(&procPriv->ref, freeProcessPriv); + file->private_data = NULL; + + return 0; +} + /** Reads Component Manager messages destinated to this process. * The message is composed by three fields: * 1) mpc2host handle (distinguishes interfaces) @@ -242,16 +347,19 @@ static void freeProcessPriv(struct kref *ref) * \note cfr GetEvent() * \return POSIX error code */ -static ssize_t cmld_channel_read(struct file *file, char *buf, size_t count, loff_t *ppos) +static ssize_t cmld_read(struct file *file, char *buf, size_t count, loff_t *ppos) { int err = 0; - struct cm_channel_priv* channelPriv = file->private_data; + struct cm_channel_priv* channelPriv = (struct cm_channel_priv*)(file->private_data); int msgSize = 0; struct plist_head* messageQueue; struct osal_msg* msg; t_os_message *os_msg = (t_os_message *)buf; int block = !(file->f_flags & O_NONBLOCK); + if (iminor(file->f_dentry->d_inode) == 0) + return -ENOSYS; + messageQueue = &channelPriv->messageQueue; if (mutex_lock_killable(&channelPriv->msgQueueLock)) @@ -263,7 +371,7 @@ wait: if (block == 0) return -EAGAIN; /* Wait until there is a message to ferry up */ - if (wait_event_killable(channelPriv->waitq, ((!plist_head_empty(messageQueue)) || (file->f_flags & O_FLUSH)))) + if (wait_event_interruptible(channelPriv->waitq, ((!plist_head_empty(messageQueue)) || (file->f_flags & O_FLUSH)))) return -ERESTARTSYS; if (file->f_flags & O_FLUSH) { file->f_flags &= ~O_FLUSH; @@ -351,21 +459,19 @@ out: * * \return POSIX error code */ -static int cmld_channel_flush(struct file *file, fl_owner_t id) +static int cmld_flush(struct file *file, fl_owner_t id) { - struct cm_channel_priv* channelPriv = file->private_data; - file->f_flags |= O_FLUSH; - wake_up(&channelPriv->waitq); + if (iminor(file->f_dentry->d_inode) != 0) { + struct cm_channel_priv* channelPriv = (struct cm_channel_priv*)(file->private_data); + file->f_flags |= O_FLUSH; + wake_up_interruptible(&channelPriv->waitq); + } return 0; } -static long cmld_channel_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long cmld_channel_ctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cm_channel_priv *channelPriv = file->private_data; -#ifdef CONFIG_DEBUG_FS - if (wait_event_killable(dump_waitq, (!cmld_dump_ongoing))) - return -ERESTARTSYS; -#endif switch(cmd) { /* @@ -374,7 +480,7 @@ static long cmld_channel_ioctl(struct file *file, unsigned int cmd, unsigned lon case CM_BINDCOMPONENTTOCMCORE: return cmld_BindComponentToCMCore(channelPriv, (CM_BindComponentToCMCore_t *)arg); case CM_FLUSHCHANNEL: - return cmld_channel_flush(file, 0); + return cmld_flush(file, 0); default: pr_err("CM(%s): unsupported command %i\n", __func__, cmd); return -EINVAL; @@ -382,18 +488,9 @@ static long cmld_channel_ioctl(struct file *file, unsigned int cmd, unsigned lon return 0; } -static long cmld_control_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cm_process_priv* procPriv = file->private_data; -#ifdef CONFIG_DEBUG_FS - if (cmd == CM_PRIV_DEBUGFS_DUMP_DONE) { - cmld_dump_ongoing = false; - wake_up(&dump_waitq); - return 0; - } else if (wait_event_killable(dump_waitq, (!cmld_dump_ongoing))) - return -ERESTARTSYS; -#endif - switch(cmd) { /* * All wrapped CM SYSCALL @@ -598,6 +695,7 @@ static long cmld_control_ioctl(struct file *file, unsigned int cmd, unsigned lon cmld_user_has_debugfs = true; #endif return 0; + case CM_PRIV_DEBUGFS_DUMP_DONE: case CM_PRIV_DEBUGFS_WAIT_DUMP: return 0; default: @@ -608,6 +706,29 @@ static long cmld_control_ioctl(struct file *file, unsigned int cmd, unsigned lon return 0; } +/** Driver's ioctl method + * Implements user/kernel crossing for SYSCALL API. + * + * \return POSIX error code + */ +static long cmld_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ +#ifdef CONFIG_DEBUG_FS + if (cmd == CM_PRIV_DEBUGFS_DUMP_DONE) { + cmld_dump_ongoing = false; + wake_up_interruptible(&dump_waitq); + return 0; + } else if (wait_event_interruptible(dump_waitq, (!cmld_dump_ongoing))) + return -ERESTARTSYS; +#endif + + if (iminor(filp->f_dentry->d_inode) == 0) { + return cmld_control_ctl(filp, cmd, arg); + } else { + return cmld_channel_ctl(filp, cmd, arg); + } +} + /** VMA open callback function */ static void cmld_vma_open(struct vm_area_struct* vma) { @@ -634,7 +755,7 @@ static struct vm_operations_struct cmld_remap_vm_ops = { * * \return POSIX error code */ -static int cmld_control_mmap(struct file *file, struct vm_area_struct *vma) +static int cmld_mmap(struct file* file, struct vm_area_struct* vma) { unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; struct list_head* listHead; @@ -706,278 +827,6 @@ static int cmld_control_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -/* Driver's release method for /dev/cm_channel */ -static int cmld_channel_release(struct inode *inode, struct file *file) -{ - struct cm_channel_priv* channelPriv = file->private_data; - struct cm_process_priv* procPriv = channelPriv->proc; - - /* - * The driver must guarantee that all related resources are released. - * Thus all these checks below are necessary to release all remaining - * resources still linked to this 'client', in case of abnormal process - * exit. - * => These are error cases ! - * In the usual case, nothing should be done except the free of - * the cmPriv itself - */ - - /* We don't need to synchronize here by using the skelListLock: - the list is only accessed during ioctl() and we can't be here - if an ioctl() is on-going */ - if (list_empty(&channelPriv->skelList)) { - /* There is no pending MPC->HOST binding - => we can quietly delete the channel */ - tasklet_disable(&cmld_service_tasklet); - mutex_lock(&channel_lock); - list_del(&channelPriv->entry); - mutex_unlock(&channel_lock); - tasklet_enable(&cmld_service_tasklet); - - /* Free all remaining messages if any */ - freeMessages(channelPriv); - - /* Free the per-channel descriptor */ - OSAL_Free(channelPriv); - } else { - /* - * Uh: there are still some MPC->HOST binding but we don't have - * the required info to unbind them. - * => we must keep all skel structures because possibly used in - * OSAL_PostDfc (incoming callback msg). We flag the channel as - * closed to discard any new msg that will never be read anyway - */ - channelPriv->state = CHANNEL_CLOSED; - - /* Already Free all remaining messages if any, - they will never be read anyway */ - freeMessages(channelPriv); - } - - kref_put(&procPriv->ref, freeProcessPriv); - file->private_data = NULL; - - return 0; -} - -/* Driver's release method for /dev/cm_control */ -static int cmld_control_release(struct inode *inode, struct file *file) -{ - struct cm_process_priv* procPriv = file->private_data; - - kref_put(&procPriv->ref, freeProcessPriv); - file->private_data = NULL; - - return 0; -} - -static struct file_operations cmld_control_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = cmld_control_ioctl, - .mmap = cmld_control_mmap, - .release = cmld_control_release, -}; - -static int cmld_control_open(struct file *file) -{ - struct cm_process_priv *procPriv = getProcessPriv(); - if (IS_ERR(procPriv)) - return PTR_ERR(procPriv); - file->private_data = procPriv; - file->f_op = &cmld_control_fops; - return 0; -} - -static struct file_operations cmld_channel_fops = { - .owner = THIS_MODULE, - .read = cmld_channel_read, - .unlocked_ioctl = cmld_channel_ioctl, - .flush = cmld_channel_flush, - .release = cmld_channel_release, -}; - -static int cmld_channel_open(struct file *file) -{ - struct cm_process_priv *procPriv = getProcessPriv(); - struct cm_channel_priv *channelPriv; - - if (IS_ERR(procPriv)) - return PTR_ERR(procPriv); - - channelPriv = (struct cm_channel_priv*)OSAL_Alloc(sizeof(*channelPriv)); - if (channelPriv == NULL) { - kref_put(&procPriv->ref, freeProcessPriv); - return -ENOMEM; - } - - channelPriv->proc = procPriv; - channelPriv->state = CHANNEL_OPEN; - - /* Initialize wait_queue, lists and mutexes */ - init_waitqueue_head(&channelPriv->waitq); - plist_head_init(&channelPriv->messageQueue); - INIT_LIST_HEAD(&channelPriv->skelList); - spin_lock_init(&channelPriv->bh_lock); - mutex_init(&channelPriv->msgQueueLock); - mutex_init(&channelPriv->skelListLock); - - tasklet_disable(&cmld_service_tasklet); - mutex_lock(&channel_lock); - list_add(&channelPriv->entry, &channel_list); - mutex_unlock(&channel_lock); - tasklet_enable(&cmld_service_tasklet); - - file->private_data = channelPriv; - file->f_op = &cmld_channel_fops; - return 0; -} - -static ssize_t cmld_sxa_trace_read(struct file *file, char *buf, size_t count, loff_t *ppos) -{ - struct mpcConfig *mpc = file->private_data; - size_t written = 0; - struct t_nmf_trace trace; - t_cm_trace_type traceType; - struct mmdsp_trace mmdsp_tr = { - .media = TB_MEDIA_FILE, - .receiver_dev = TB_DEV_PC, - .sender_dev = TB_DEV_TRACEBOX, - .unused = TB_TRACEBOX, - .receiver_obj = DEFAULT_RECEIVERR_OBJ, - .sender_obj = DEFAULT_SENDER_OBJ, - .transaction_id = 0, - .message_id = TB_TRACE_MSG, - .master_id = mpc->coreId+1, - .channel_id = 0, - .ost_version = OST_VERSION, - .entity = ENTITY, - .protocol_id = PROTOCOL_ID, - .btrace_hdr_flag = 0, - .btrace_hdr_subcategory = 0, - }; - - while ((count - written) >= sizeof(mmdsp_tr)) { - traceType = CM_ENGINE_GetNextTrace(mpc->coreId, &trace); - - switch (traceType) { - case CM_MPC_TRACE_READ_OVERRUN: - mmdsp_tr.size = - cpu_to_be16(offsetof(struct mmdsp_trace, - ost_version) - -offsetof(struct mmdsp_trace, - receiver_obj)); - mmdsp_tr.message_id = TB_TRACE_EXCEPTION_MSG; - mmdsp_tr.ost_master_id = TB_EXCEPTION_LONG_OVRF_PACKET; - if (copy_to_user(&buf[written], &mmdsp_tr, - offsetof(struct mmdsp_trace, - ost_version))) - return -EFAULT; - written += offsetof(struct mmdsp_trace, ost_version); - if ((count - written) < sizeof(mmdsp_tr)) - break; - case CM_MPC_TRACE_READ: { - u16 param_nr = (u16)trace.paramOpt; - u16 handle_valid = (u16)(trace.paramOpt >> 16); - u32 to_write = offsetof(struct mmdsp_trace, - parent_handle); - mmdsp_tr.transaction_id = trace.revision%256; - mmdsp_tr.message_id = TB_TRACE_MSG; - mmdsp_tr.ost_master_id = OST_MASTERID; - mmdsp_tr.timestamp = cpu_to_be64(trace.timeStamp); - mmdsp_tr.timestamp2 = cpu_to_be64(trace.timeStamp); - mmdsp_tr.component_id = cpu_to_be32(trace.componentId); - mmdsp_tr.trace_id = cpu_to_be32(trace.traceId); - mmdsp_tr.btrace_hdr_category = (trace.traceId>>16)&0xFF; - mmdsp_tr.btrace_hdr_size = BTRACE_HEADER_SIZE - + sizeof(trace.params[0]) * param_nr; - if (handle_valid) { - mmdsp_tr.parent_handle = trace.parentHandle; - mmdsp_tr.component_handle = - trace.componentHandle; - to_write += sizeof(trace.parentHandle) - + sizeof(trace.componentHandle); - mmdsp_tr.btrace_hdr_size += - sizeof(trace.parentHandle) - + sizeof(trace.componentHandle); - } - mmdsp_tr.size = - cpu_to_be16(to_write - + (sizeof(trace.params[0])*param_nr) - - offsetof(struct mmdsp_trace, - receiver_obj)); - mmdsp_tr.length = to_write - + (sizeof(trace.params[0])*param_nr) - - offsetof(struct mmdsp_trace, - timestamp2); - if (copy_to_user(&buf[written], &mmdsp_tr, to_write)) - return -EFAULT; - written += to_write; - /* write param */ - to_write = sizeof(trace.params[0]) * param_nr; - if (copy_to_user(&buf[written], trace.params, to_write)) - return -EFAULT; - written += to_write; - break; - } - case CM_MPC_TRACE_NONE: - default: - if ((file->f_flags & O_NONBLOCK) || written) - return written; - spin_lock_bh(&mpc->trace_reader_lock); - mpc->trace_reader = current; - spin_unlock_bh(&mpc->trace_reader_lock); - schedule_timeout_killable(msecs_to_jiffies(200)); - spin_lock_bh(&mpc->trace_reader_lock); - mpc->trace_reader = NULL; - spin_unlock_bh(&mpc->trace_reader_lock); - if (signal_pending(current)) - return -ERESTARTSYS; - } - } - return written; -} - -/* Driver's release method for /dev/cm_sxa_trace */ -static int cmld_sxa_trace_release(struct inode *inode, struct file *file) -{ - struct mpcConfig *mpc = file->private_data; - atomic_dec(&mpc->trace_read_count); - return 0; -} - -static struct file_operations cmld_sxa_trace_fops = { - .owner = THIS_MODULE, - .read = cmld_sxa_trace_read, - .release = cmld_sxa_trace_release, -}; - -static int cmld_sxa_trace_open(struct file *file, struct mpcConfig *mpc) -{ - if (atomic_add_unless(&mpc->trace_read_count, 1, 1) == 0) - return -EBUSY; - - file->private_data = mpc; - file->f_op = &cmld_sxa_trace_fops; - return 0; -} - -/* driver open() call: specific */ -static int cmld_open(struct inode *inode, struct file *file) -{ - switch (iminor(inode)) { - case 0: - return cmld_control_open(file); - case 1: - return cmld_channel_open(file); - case 2: - return cmld_sxa_trace_open(file, &osalEnv.mpc[SIA]); - case 3: - return cmld_sxa_trace_open(file, &osalEnv.mpc[SVA]); - default: - return -ENOSYS; - } -} - /** MPC Events tasklet * The parameter is used to know from which interrupts we're comming * and which core to pass to CM_ProcessMpcEvent(): @@ -1033,7 +882,12 @@ static irqreturn_t panic_handler(int irq, void *idx) */ static struct file_operations cmld_fops = { .owner = THIS_MODULE, + .read = cmld_read, + .unlocked_ioctl = cmld_ioctl, + .mmap = cmld_mmap, .open = cmld_open, + .flush = cmld_flush, + .release = cmld_release, }; /** diff --git a/drivers/staging/nmf-cm/cmld.h b/drivers/staging/nmf-cm/cmld.h index 17e6c55ff61..4c5a5bed7e6 100644 --- a/drivers/staging/nmf-cm/cmld.h +++ b/drivers/staging/nmf-cm/cmld.h @@ -79,52 +79,6 @@ extern bool cmld_user_has_debugfs; /**< Whether user side has proper support of extern bool cmld_dump_ongoing; /**< Whether a dump is on-going */ #endif -/* Structure used to embed DSP traces */ -#define TB_MEDIA_FILE 0x1C -#define TB_DEV_PC 0x10 -#define TB_DEV_TRACEBOX 0x4C -#define TB_TRACEBOX 0x7C -#define DEFAULT_RECEIVERR_OBJ 0x0 -#define DEFAULT_SENDER_OBJ 0x0A -#define TB_TRACE_MSG 0x94 -#define TB_TRACE_EXCEPTION_MSG 0x95 -#define TB_EXCEPTION_LONG_OVRF_PACKET 0x07 -#define OST_MASTERID 0x08 -#define OST_VERSION 0x05 -#define ENTITY 0xAA -#define PROTOCOL_ID 0x03 -#define BTRACE_HEADER_SIZE 4 - -struct __attribute__ ((__packed__)) mmdsp_trace { - u8 media; - u8 receiver_dev; - u8 sender_dev; - u8 unused; - u16 size; - u8 receiver_obj; - u8 sender_obj; - u8 transaction_id; - u8 message_id; - u8 master_id; - u8 channel_id; - u64 timestamp; - u8 ost_master_id; - u8 ost_version; - u8 entity; - u8 protocol_id; - u8 length; - u64 timestamp2; - u32 component_id; - u32 trace_id; - u8 btrace_hdr_size; - u8 btrace_hdr_flag; - u8 btrace_hdr_category; - u8 btrace_hdr_subcategory; - u32 parent_handle; - u32 component_handle; - u32 params[4]; -}; - /** Lock/unlock per process mutex * * \note Must be taken before tasklet_disable (if necessary)! diff --git a/drivers/staging/nmf-cm/configuration.c b/drivers/staging/nmf-cm/configuration.c index 523874fc586..d62bcb45500 100644 --- a/drivers/staging/nmf-cm/configuration.c +++ b/drivers/staging/nmf-cm/configuration.c @@ -21,30 +21,28 @@ struct OsalEnvironment osalEnv = { .mpc = { { - .coreId = SVA_CORE_ID, - .name = "sva", - .base_phys = (void*)U8500_SVA_BASE, - .interrupt0 = IRQ_DB8500_SVA, - .interrupt1 = IRQ_DB8500_SVA2, - .mmdsp_regulator = NULL, - .pipe_regulator = NULL, - .monitor_tsk = NULL, - .hwmem_code = NULL, - .hwmem_data = NULL, - .trace_read_count = ATOMIC_INIT(0), + .coreId = SVA_CORE_ID, + .name = "sva", + .base_phys = (void*)U8500_SVA_BASE, + .interrupt0 = IRQ_DB8500_SVA, + .interrupt1 = IRQ_DB8500_SVA2, + .mmdsp_regulator = NULL, + .pipe_regulator = NULL, + .monitor_tsk = NULL, + .hwmem_code = NULL, + .hwmem_data = NULL, }, { - .coreId = SIA_CORE_ID, - .name = "sia", - .base_phys = (void*)U8500_SIA_BASE, - .interrupt0 = IRQ_DB8500_SIA, - .interrupt1 = IRQ_DB8500_SIA2, - .mmdsp_regulator = NULL, - .pipe_regulator = NULL, - .monitor_tsk = NULL, - .hwmem_code = NULL, - .hwmem_data = NULL, - .trace_read_count = ATOMIC_INIT(0), + .coreId = SIA_CORE_ID, + .name = "sia", + .base_phys = (void*)U8500_SIA_BASE, + .interrupt0 = IRQ_DB8500_SIA, + .interrupt1 = IRQ_DB8500_SIA2, + .mmdsp_regulator = NULL, + .pipe_regulator = NULL, + .monitor_tsk = NULL, + .hwmem_code = NULL, + .hwmem_data = NULL, } }, .esram_regulator = { NULL, NULL}, @@ -127,20 +125,16 @@ int init_config(void) pr_err("SDRAM data size for SVA must be greater than 0\n"); return -EINVAL; } - osalEnv.mpc[SVA].nbYramBanks = cfgMpcYBanks_SVA; osalEnv.mpc[SVA].eeId = cfgSchedulerTypeHybrid_SVA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; osalEnv.mpc[SVA].sdram_code.size = cfgMpcSDRAMCodeSize_SVA * ONE_KB; osalEnv.mpc[SVA].sdram_data.size = cfgMpcSDRAMDataSize_SVA * ONE_KB; osalEnv.mpc[SVA].base.size = 128*ONE_KB; //we expose only TCM24 - spin_lock_init(&osalEnv.mpc[SVA].trace_reader_lock); - osalEnv.mpc[SIA].nbYramBanks = cfgMpcYBanks_SIA; osalEnv.mpc[SIA].eeId = cfgSchedulerTypeHybrid_SIA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; osalEnv.mpc[SIA].sdram_code.size = cfgMpcSDRAMCodeSize_SIA * ONE_KB; osalEnv.mpc[SIA].sdram_data.size = cfgMpcSDRAMDataSize_SIA * ONE_KB; osalEnv.mpc[SIA].base.size = 128*ONE_KB; //we expose only TCM24 - spin_lock_init(&osalEnv.mpc[SIA].trace_reader_lock); return 0; } diff --git a/drivers/staging/nmf-cm/configuration.h b/drivers/staging/nmf-cm/configuration.h index f4146dc6117..35072831a13 100644 --- a/drivers/staging/nmf-cm/configuration.h +++ b/drivers/staging/nmf-cm/configuration.h @@ -20,14 +20,12 @@ #endif /* Embedded Static RAM base address */ -/* config: 0-64k: secure */ -#define ESRAM_BASE (U8500_ESRAM_BASE + U8500_ESRAM_DMA_LCPA_OFFSET) +#define ESRAM_BASE (U8500_ESRAM_BASE + 0x10000) // V1/V2 config: 0-64k: secure; /* * Embedded ram size for CM (in Kb) * 5 banks of 128k: skip the first half bank (secure) and the last * one (used for MCDE/B2R2), but include DMA part (4k after the secure part) - * to give access from DSP side */ #define ESRAM_SIZE 448 enum { diff --git a/drivers/staging/nmf-cm/ee/api/panic.idt b/drivers/staging/nmf-cm/ee/api/panic.idt index 53135819f4a..f971fdad8c5 100644 --- a/drivers/staging/nmf-cm/ee/api/panic.idt +++ b/drivers/staging/nmf-cm/ee/api/panic.idt @@ -55,8 +55,7 @@ typedef enum { INTERFACE_NOT_BINDED = 8, USER_PANIC = 9, UNBIND_INTERRUPT = 10, - EVENT_FIFO_IN_USE = 11, - RESERVED_PANIC = 2 //for COMPATIBILITY with previous versions of NMF, to be deprecated + EVENT_FIFO_IN_USE = 11 } t_panic_reasonDescription; /*! diff --git a/drivers/staging/nmf-cm/ee/api/trace.idt b/drivers/staging/nmf-cm/ee/api/trace.idt deleted file mode 100644 index 3c21c6a860f..00000000000 --- a/drivers/staging/nmf-cm/ee/api/trace.idt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * Author: Jean-Philippe FASSINO for ST-Ericsson. - * License terms: GNU General Public License (GPL), version 2, with - * user space exemption described in the top-level COPYING file in - * the Linux kernel source tree. - */ - -/*! - * \defgroup NMF_EE_TYPE Execution Engine Common Type Definitions - * \ingroup COMMON - */ - -#ifndef __INC_TRACE_IDT -#define __INC_TRACE_IDT - -struct t_nmf_trace -{ - t_uint32 revision; - t_uint32 timeStamp; - t_uint32 componentId; - t_uint32 traceId; - t_uint32 paramOpt; - t_uint32 componentHandle; - t_uint32 parentHandle; - t_uint32 params[4]; -}; - -#define TRACE_BUFFER_SIZE 128 - -#endif diff --git a/drivers/staging/nmf-cm/inc/nmf-def.h b/drivers/staging/nmf-cm/inc/nmf-def.h index 5cb1ec7fcec..e671198f7b9 100644 --- a/drivers/staging/nmf-cm/inc/nmf-def.h +++ b/drivers/staging/nmf-cm/inc/nmf-def.h @@ -21,7 +21,7 @@ * * \ingroup NMF_VERSION */ -#define NMF_VERSION ((2 << 16) | (10 << 8) | (121)) +#define NMF_VERSION ((2 << 16) | (10 << 8) | (118)) /*! * \brief Get NMF major version corresponding to NMF version number diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index e79e35db106..94aa11fc91c 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -353,7 +353,7 @@ void OSAL_PostDfc(t_nmf_mpc2host_handle upLayerTHIS, t_uint32 methodIndex, t_eve spin_unlock_bh(&skelwrapper->channelPriv->bh_lock); /* Wake up process' wait queue */ - wake_up(&skelwrapper->channelPriv->waitq); + wake_up_interruptible(&skelwrapper->channelPriv->waitq); } @@ -755,8 +755,8 @@ static int dspload_monitor(void *idx) /* init counter */ if (CM_GetMpcLoadCounter(mpc->coreId, &mpc->oldLoadCounter) != CM_OK) - pr_warn("CM Driver: Failed to init load counter for %s\n", - mpc->name); + pr_err("CM Driver: Failed to init load counter for %s\n", + mpc->name); while (!kthread_should_stop()) { t_cm_mpc_load_counter loadCounter; @@ -919,7 +919,7 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam /* Compute the relative end address of the range, relative to base address of BANK1 */ - secondParam = (firstParam+secondParam-U8500_ESRAM_BANK1-1); + secondParam = (firstParam+secondParam-(U8500_ESRAM_BASE+0x20000)-1); /* if end is below base address of BANK1, it means that full range of addresses is on Bank0 */ @@ -927,16 +927,16 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam break; /* Compute the index of the last bank accessed among esram 1+2 and esram 3+4 banks */ - secondParam /= (2*U8500_ESRAM_BANK_SIZE); + secondParam /= 0x40000; WARN_ON(secondParam > 1); /* Compute the index of the first bank accessed among esram 1+2 and esram 3+4 banks Do not manage Bank 0 (secured, must be always ON) */ - if (firstParam < U8500_ESRAM_BANK1) + if (firstParam < (U8500_ESRAM_BASE+0x20000)) firstParam = 0; else - firstParam = (firstParam-U8500_ESRAM_BANK1)/(2*U8500_ESRAM_BANK_SIZE); + firstParam = (firstParam-(U8500_ESRAM_BASE+0x20000))/0x40000; /* power off the banks 1+2 and 3+4 if accessed. */ for (i=firstParam; i<=secondParam; i++) { @@ -1032,7 +1032,7 @@ t_cm_error OSAL_EnablePwrRessource(t_nmf_power_resource resource, t_uint32 first /* Compute the relative end address of the range, relative to base address of BANK1 */ - secondParam = (firstParam+secondParam-U8500_ESRAM_BANK1-1); + secondParam = (firstParam+secondParam-(U8500_ESRAM_BASE+0x20000)-1); /* if end is below base address of BANK1, it means that full range of addresses is on Bank0 */ @@ -1040,16 +1040,16 @@ t_cm_error OSAL_EnablePwrRessource(t_nmf_power_resource resource, t_uint32 first break; /* Compute the index of the last bank accessed among esram 1+2 and esram 3+4 banks */ - secondParam /= (2*U8500_ESRAM_BANK_SIZE); + secondParam /= 0x40000; WARN_ON(secondParam > 1); /* Compute the index of the first bank accessed among esram 1+2 and esram 3+4 banks Do not manage Bank 0 (secured, must be always ON) */ - if (firstParam < U8500_ESRAM_BANK1) + if (firstParam < (U8500_ESRAM_BASE+0x20000)) firstParam = 0; else - firstParam = (firstParam-U8500_ESRAM_BANK1)/(2*U8500_ESRAM_BANK_SIZE); + firstParam = (firstParam-(U8500_ESRAM_BASE+0x20000))/0x40000; /* power on the banks 1+2 and 3+4 if accessed. */ for (i=firstParam; i<=secondParam; i++) { diff --git a/drivers/staging/nmf-cm/osal-kernel.h b/drivers/staging/nmf-cm/osal-kernel.h index dc9bc8445ac..7a71bdd591d 100644 --- a/drivers/staging/nmf-cm/osal-kernel.h +++ b/drivers/staging/nmf-cm/osal-kernel.h @@ -11,7 +11,6 @@ #include #include #include -#include #ifdef CONFIG_HAS_WAKELOCK #include #endif @@ -25,6 +24,7 @@ */ #define _CM_ELF_H #include +#include #include "configuration.h" @@ -56,9 +56,6 @@ struct mpcConfig { #endif struct task_struct *monitor_tsk; /**< task to monitor the dsp load; */ t_cm_mpc_load_counter oldLoadCounter; /**< previous load counter of the DSP */ - atomic_t trace_read_count; /**< number of trace reader */ - spinlock_t trace_reader_lock; - struct task_struct *trace_reader;/**< current reader task */ #ifdef CONFIG_DEBUG_FS struct dentry *dir; /**< debugfs dir entry */ struct dentry *comp_dir; /**< debugfs component dir entry */ diff --git a/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h b/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h index 71dfc534f97..5ec08434492 100644 --- a/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h +++ b/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h @@ -12,6 +12,5 @@ #define MPC_SERVICE_NONE 0 #define MPC_SERVICE_BOOT 0xB001 #define MPC_SERVICE_PRINT 0x1234 -#define MPC_SERVICE_TRACE 0x789 #endif -- cgit v1.2.3 From fc537f23e54cca6bcb8840731c55c8e947d40730 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Fri, 28 Oct 2011 11:12:48 +0200 Subject: U8500 CM: Add support to get DSP OST Trace on ARM Provide two new devices /dev/cm_sia_trace and /dev/cm_sva_trace that allow any user to retrieve live OST traces coming from DSP components by doing 'cat /dev/cm_sia_trace > file.bin'. This traces are till now available through XTI device. This feature also requires some change in OSTTrace component to be fully operationnal. ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson ID: 324035 ST-Ericsson Linux next: NA Change-Id: I593c2f82be750bc1738281ee25d875b5a784ea04 Signed-off-by: Pierre Peiffer Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/42605 Reviewed-by: QABUILD --- .../nmf-cm/cm/engine/api/control/irq_engine.h | 14 +- .../engine/communication/inc/communication_type.h | 1 - .../cm/engine/component/inc/component_type.h | 1 - .../engine/configuration/inc/configuration_type.h | 1 - drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c | 22 +- .../inc/executive_engine_mgt.h | 6 + .../src/executive_engine_mgt.c | 13 + .../nmf-cm/cm/engine/memory/inc/domain_type.h | 1 - .../nmf-cm/cm/engine/memory/inc/memory_type.h | 1 - .../os_adaptation_layer/inc/os_adaptation_layer.h | 4 + .../cm/engine/perfmeter/inc/perfmeter_type.h | 1 - .../cm/engine/repository_mgt/inc/repository_type.h | 1 - .../staging/nmf-cm/cm/engine/trace/inc/xtitrace.h | 8 + drivers/staging/nmf-cm/cm/engine/trace/src/panic.c | 109 +++++ drivers/staging/nmf-cm/cm/inc/cm_type.h | 1 - drivers/staging/nmf-cm/cm_debug.c | 2 +- drivers/staging/nmf-cm/cm_service.c | 10 +- drivers/staging/nmf-cm/cm_syscall.c | 6 +- drivers/staging/nmf-cm/cmioctl.h | 8 +- drivers/staging/nmf-cm/cmld.c | 448 ++++++++++++++------- drivers/staging/nmf-cm/cmld.h | 46 +++ drivers/staging/nmf-cm/configuration.c | 46 ++- drivers/staging/nmf-cm/configuration.h | 4 +- drivers/staging/nmf-cm/ee/api/panic.idt | 4 +- drivers/staging/nmf-cm/ee/api/trace.idt | 30 ++ drivers/staging/nmf-cm/inc/nmf-def.h | 2 +- drivers/staging/nmf-cm/inc/nmf-limits.h | 1 - drivers/staging/nmf-cm/inc/nmf-tracedescription.h | 1 - drivers/staging/nmf-cm/inc/nmf_type.idt | 1 - drivers/staging/nmf-cm/inc/type.h | 1 - drivers/staging/nmf-cm/inc/typedef.h | 1 - drivers/staging/nmf-cm/nmf/inc/channel_type.h | 1 - drivers/staging/nmf-cm/nmf/inc/component_type.h | 1 - drivers/staging/nmf-cm/nmf/inc/service_type.h | 1 - drivers/staging/nmf-cm/osal-kernel.c | 22 +- drivers/staging/nmf-cm/osal-kernel.h | 6 +- .../nmf-cm/share/communication/inc/nmf_service.h | 1 + drivers/staging/nmf-cm/share/inc/macros.h | 1 - drivers/staging/nmf-cm/share/inc/nmf.h | 1 - 39 files changed, 612 insertions(+), 217 deletions(-) create mode 100644 drivers/staging/nmf-cm/ee/api/trace.idt (limited to 'drivers/staging/nmf-cm/cm_syscall.c') diff --git a/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h b/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h index 20313f13256..e3974764e91 100644 --- a/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h +++ b/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h @@ -14,6 +14,7 @@ #include #include #include +#include /*! * \brief MPCs -> HOST communication handler @@ -49,7 +50,8 @@ PUBLIC IMPORT_SHARED void CM_ProcessMpcEvent(t_nmf_core_id coreId); typedef enum { // Allowed since i CM_MPC_SERVICE_NONE = 0, //!< No service found CM_MPC_SERVICE_PANIC = 1, //!< Panic service found - CM_MPC_SERVICE_PRINT = 2 //!< Print service found + CM_MPC_SERVICE_PRINT = 2, //!< Print service found + CM_MPC_SERVICE_TRACE = 3 //!< Trace service found } t_cm_service_type; //!< Service description type /*! @@ -105,4 +107,14 @@ PUBLIC IMPORT_SHARED t_cm_error CM_ReadMPCString( char * buffer, t_uint32 bufferSize); +typedef enum { + CM_MPC_TRACE_NONE = 0, + CM_MPC_TRACE_READ = 1, + CM_MPC_TRACE_READ_OVERRUN = 2 +} t_cm_trace_type; + +PUBLIC IMPORT_SHARED t_cm_trace_type CM_ENGINE_GetNextTrace( + t_nmf_core_id coreId, + struct t_nmf_trace *trace); + #endif /* CONTROL_IRQ_ENGINE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/communication/inc/communication_type.h b/drivers/staging/nmf-cm/cm/engine/communication/inc/communication_type.h index db426845a82..53a6ff39b07 100644 --- a/drivers/staging/nmf-cm/cm/engine/communication/inc/communication_type.h +++ b/drivers/staging/nmf-cm/cm/engine/communication/inc/communication_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Communication Component Manager API type. */ diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/component_type.h b/drivers/staging/nmf-cm/cm/engine/component/inc/component_type.h index 35571dde06d..2e769ec8b22 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/inc/component_type.h +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/component_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Components Component Manager API type. * diff --git a/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_type.h b/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_type.h index abfe452cf78..af29d584ba4 100644 --- a/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_type.h +++ b/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Configuration Component Manager API type. */ diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c index 7950cd99007..274a1b6b59f 100644 --- a/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c @@ -94,8 +94,26 @@ static t_interface_description* getInterfaceDescription(t_tmp_elfdescription *el // Search if interfane already loaded for(itf = interfaceList; itf != NULL; itf = itf->next) { if(itf->type == itfType) { - // TODO Sanity check - + if (itf->methodNumber != elfitf->methodNumber) { + ERROR("When loading component template %s:\n\tNumber of methods in interface type %s\n\tdiffers from previous declaration: was %d, found %d\n", + getElfHeaderReference(elftmp, (void*)elftmp->elfheader->templateName), itfType, itf->methodNumber, elfitf->methodNumber, 0, 0); + //Do not fail for now for compatibility reason + //goto out_itf_type; + } + if (cmIntensiveCheckState) { + for(i = 0; i < itf->methodNumber; i++) { + if (cm_StringCompare(itf->methodNames[i], getElfHeaderReference(elftmp, (void*)elfitf->methodNames[i]), MAX_INTERNAL_STRING_LENGTH) != 0) { + ERROR("When loading component template %s:\n" + "\tName of method number %d in interface type %s\n" + "\tdiffers from previous declaration: previous name was %s, new name found is %s\n", + getElfHeaderReference(elftmp, (void*)elftmp->elfheader->templateName), i, + itfType, itf->methodNames[i], + getElfHeaderReference(elftmp, (void*)elfitf->methodNames[i]), 0); + //Do not fail for now for compatibility reason + //goto out_itf_type; + } + } + } itf->referenceCounter++; cm_StringRelease(itfType); return itf; diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h index aacffd15a17..0894410ae0d 100644 --- a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h @@ -24,6 +24,12 @@ typedef struct { t_memory_handle handle; t_cm_logical_address addr; } panicArea; + + // Trace Management + t_uint32 readTracePointer; + t_uint32 lastReadedTraceRevision; + t_memory_handle traceDataHandle; + struct t_nmf_trace *traceDataAddr; } t_ee_state; //TODO, juraj, this should be done more properly, like accessor method, instead making this global variable.. diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c index f2c833ff7dc..4df3d7ee0f5 100644 --- a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c @@ -21,6 +21,8 @@ #include #include +#include + #include t_ee_state eeState[NB_CORE_IDS]; @@ -130,6 +132,16 @@ PUBLIC t_cm_error cm_EEM_Init( return error; } + if((error = cm_SRV_allocateTraceBufferMemory(coreId, cm_DSP_GetState(coreId)->domainEE)) != CM_OK) + { + cm_PFM_deallocatePerfmeterDataMemory(coreId); + cm_EEM_freePanicArea(coreId); + cm_delayedDestroyComponent(eeState[coreId].instance); + eeState[coreId].instance = (t_component_instance *)0; + cm_DSP_Shutdown(coreId); + return error; + } + /* set initial stack value */ cm_writeAttribute(eeState[coreId].instance, "rtos/scheduler/topOfStack", cm_DSP_getStackAddr(coreId)); @@ -179,6 +191,7 @@ PUBLIC void cm_EEM_Close(t_nmf_core_id coreId) cm_DSP_setStackSize(coreId, 0); cm_delayedDestroyComponent(eeState[coreId].instance); eeState[coreId].instance = (t_component_instance *)0; + cm_SRV_deallocateTraceBufferMemory(coreId); cm_PFM_deallocatePerfmeterDataMemory(coreId); cm_EEM_freePanicArea(coreId); cm_DSP_Shutdown(coreId); diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h index 7463f82eb89..354315d4d72 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /***************************************************************************/ /* file : domain.h * author : NMF team diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/memory_type.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/memory_type.h index 91246f1ec0e..dbdba4c3d9d 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/inc/memory_type.h +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/memory_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Public Component Manager Memory API type. * diff --git a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h index f57c92ea41b..c9ec864795f 100644 --- a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h +++ b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h @@ -44,6 +44,10 @@ typedef t_uint8 t_nmf_osal_sync_error; #define SEM_TIMEOUT_NORMAL 3000 #define SEM_TIMEOUT_DEBUG 300000 +/*! + * \brief Operations used to support additionnal OS-specific debug feature + * \ingroup CM_ENGINE_OSAL_API + */ struct osal_debug_operations { void (*component_create)(t_component_instance *component); void (*component_destroy)(t_component_instance *component); diff --git a/drivers/staging/nmf-cm/cm/engine/perfmeter/inc/perfmeter_type.h b/drivers/staging/nmf-cm/cm/engine/perfmeter/inc/perfmeter_type.h index 78de395acc2..8733c20b21b 100644 --- a/drivers/staging/nmf-cm/cm/engine/perfmeter/inc/perfmeter_type.h +++ b/drivers/staging/nmf-cm/cm/engine/perfmeter/inc/perfmeter_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Public Component Manager Performance Meter API type. * diff --git a/drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h b/drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h index 59abc269236..30ef8004c48 100644 --- a/drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h +++ b/drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Components Component Manager API type. * diff --git a/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h b/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h index 6ab960b69b2..1efd4f1e699 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h +++ b/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h @@ -39,4 +39,12 @@ void cm_TRC_traceMemAlloc(t_nmfTraceAllocatorCommandDescription command, t_uint8 void cm_TRC_traceMem(t_nmfTraceAllocCommandDescription command, t_uint8 allocId, t_uint32 startAddress, t_uint32 memorySize); +/*************************/ +/* MMDSP trace buffer */ +/*************************/ +PUBLIC t_cm_error cm_SRV_allocateTraceBufferMemory(t_nmf_core_id coreId, t_cm_domain_id domainId); +PUBLIC void cm_SRV_deallocateTraceBufferMemory(t_nmf_core_id coreId); + + + #endif /* __INC_CM_TRACE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c index 9cb1a729a92..e59d9f8b1ba 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c @@ -13,6 +13,111 @@ #include #include +PUBLIC t_cm_error cm_SRV_allocateTraceBufferMemory(t_nmf_core_id coreId, t_cm_domain_id domainId) +{ + t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); + + state->traceDataHandle = cm_DM_Alloc(domainId, SDRAM_EXT16, + TRACE_BUFFER_SIZE * sizeof(struct t_nmf_trace) / 2, CM_MM_ALIGN_WORD, TRUE); + if (state->traceDataHandle == INVALID_MEMORY_HANDLE) + return CM_NO_MORE_MEMORY; + else + { + t_uint32 mmdspAddr; + int i; + + state->traceDataAddr = (struct t_nmf_trace*)cm_DSP_GetHostLogicalAddress(state->traceDataHandle); + cm_DSP_GetDspAddress(state->traceDataHandle, &mmdspAddr); + cm_writeAttribute(state->instance, "rtos/commonpart/traceDataAddr", mmdspAddr); + + eeState[coreId].readTracePointer = 0; + eeState[coreId].lastReadedTraceRevision = 0; + + for(i = 0; i < TRACE_BUFFER_SIZE; i++) + state->traceDataAddr[i].revision = 0; + + return CM_OK; + } +} + +PUBLIC void cm_SRV_deallocateTraceBufferMemory(t_nmf_core_id coreId) +{ + t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); + + state->traceDataAddr = 0; + cm_DM_Free(state->traceDataHandle, TRUE); +} + +static t_uint32 swapHalfWord(t_uint32 word) +{ + return (word >> 16) | (word << 16); +} + +PUBLIC EXPORT_SHARED t_cm_trace_type CM_ENGINE_GetNextTrace( + t_nmf_core_id coreId, + struct t_nmf_trace *trace) +{ + t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); + t_uint32 foundRevision; + t_cm_trace_type type; + + OSAL_LOCK_API(); + if (state->traceDataAddr == NULL) { + type = CM_MPC_TRACE_NONE; + goto out; + } + + foundRevision = swapHalfWord(state->traceDataAddr[state->readTracePointer].revision); + + if(foundRevision <= state->lastReadedTraceRevision) + { + // It's an old trace forgot it + type = CM_MPC_TRACE_NONE; + } + else + { + struct t_nmf_trace *traceRaw; + + if(foundRevision == state->lastReadedTraceRevision + 1) + { + type = CM_MPC_TRACE_READ; + } + else + { + type = CM_MPC_TRACE_READ_OVERRUN; + /* + * If we find that revision is bigger, thus we are in overrun, then we take the writePointer + 1 which + * correspond to the older one. + * => Here there is a window where the MMDSP could update writePointer just after + */ + state->readTracePointer = (cm_readAttributeNoError(state->instance, "rtos/commonpart/writePointer") + 1) % TRACE_BUFFER_SIZE; + } + + traceRaw = &state->traceDataAddr[state->readTracePointer]; + + trace->timeStamp = swapHalfWord(traceRaw->timeStamp); + trace->componentId = swapHalfWord(traceRaw->componentId); + trace->traceId = swapHalfWord(traceRaw->traceId); + trace->paramOpt = swapHalfWord(traceRaw->paramOpt); + trace->componentHandle = swapHalfWord(traceRaw->componentHandle); + trace->parentHandle = swapHalfWord(traceRaw->parentHandle); + + trace->params[0] = swapHalfWord(traceRaw->params[0]); + trace->params[1] = swapHalfWord(traceRaw->params[1]); + trace->params[2] = swapHalfWord(traceRaw->params[2]); + trace->params[3] = swapHalfWord(traceRaw->params[3]); + + state->readTracePointer = (state->readTracePointer + 1) % TRACE_BUFFER_SIZE; + state->lastReadedTraceRevision = swapHalfWord(traceRaw->revision); + trace->revision = state->lastReadedTraceRevision; + } + +out: + OSAL_UNLOCK_API(); + + return type; +} + /* * Panic @@ -139,6 +244,10 @@ PUBLIC EXPORT_SHARED t_cm_error CM_getServiceDescription( srcDescr->u.print.value1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); srcDescr->u.print.value2 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo2"); } + else if(serviceReason == MPC_SERVICE_TRACE) + { + *srcType = CM_MPC_SERVICE_TRACE; + } else if(serviceReason != MPC_SERVICE_NONE) { t_uint32 panicThis; diff --git a/drivers/staging/nmf-cm/cm/inc/cm_type.h b/drivers/staging/nmf-cm/cm/inc/cm_type.h index 83a34ecd706..780e27ca600 100644 --- a/drivers/staging/nmf-cm/cm/inc/cm_type.h +++ b/drivers/staging/nmf-cm/cm/inc/cm_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Component Manager types. * diff --git a/drivers/staging/nmf-cm/cm_debug.c b/drivers/staging/nmf-cm/cm_debug.c index a934aa33e92..26446e19cdb 100644 --- a/drivers/staging/nmf-cm/cm_debug.c +++ b/drivers/staging/nmf-cm/cm_debug.c @@ -5,12 +5,12 @@ */ #include -#include #include "osal-kernel.h" #include "cm_debug.h" #ifdef CONFIG_DEBUG_FS +#include static struct dentry *cm_dir; /* nmf-cm/ */ static struct dentry *proc_dir; /* nmf-cm/proc/ */ diff --git a/drivers/staging/nmf-cm/cm_service.c b/drivers/staging/nmf-cm/cm_service.c index 70cf6f37524..a2a6ffa5b57 100644 --- a/drivers/staging/nmf-cm/cm_service.c +++ b/drivers/staging/nmf-cm/cm_service.c @@ -12,9 +12,9 @@ #include #include +#include #include #include -#include #include @@ -71,7 +71,7 @@ void dispatch_service_msg(struct osal_msg *msg) spin_lock_bh(&channelPriv->bh_lock); plist_add(&new_msg->msg_entry, &channelPriv->messageQueue); spin_unlock_bh(&channelPriv->bh_lock); - wake_up_interruptible(&channelPriv->waitq); + wake_up(&channelPriv->waitq); } } @@ -113,6 +113,12 @@ static void service_tasklet_func(unsigned long unused) desc.u.print.value2); break; } + case CM_MPC_SERVICE_TRACE: + spin_lock_bh(&osalEnv.mpc[i].trace_reader_lock); + if (osalEnv.mpc[i].trace_reader) + wake_up_process(osalEnv.mpc[i].trace_reader); + spin_unlock_bh(&osalEnv.mpc[i].trace_reader_lock); + break; default: pr_err("[CM] %s: MPC Service Type %d not supported\n", __func__, type); } diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index a687e0206a3..ca8d664abb4 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -5,11 +5,11 @@ */ #include +#include #include #include #include #include -#include #include "cmioctl.h" #include "osal-kernel.h" #include "cmld.h" @@ -1397,9 +1397,9 @@ int cmld_PrivReserveMemory(struct cm_process_priv *procPriv, unsigned int physAd /* Mark this memory area reserved for a mapping for this thread ID */ /* It must not be already reserved but this should not happen */ if (curr->tid) { - /*pr_err("%s: thread %d can't reseveved memory %x already " + pr_err("%s: thread %d can't reseveved memory %x already " "reserved for %d\n", - __func__, current->pid, physAddr, (int)curr->tid);*/ + __func__, current->pid, physAddr, curr->tid); err = -EBUSY; } else { curr->tid = current->pid; diff --git a/drivers/staging/nmf-cm/cmioctl.h b/drivers/staging/nmf-cm/cmioctl.h index 96481be38b8..5f7d5b6a349 100644 --- a/drivers/staging/nmf-cm/cmioctl.h +++ b/drivers/staging/nmf-cm/cmioctl.h @@ -29,9 +29,11 @@ enum cmdma_type { CMDMA_PER_2_MEM }; -#define CMLD_DEV_NAME \ - { "cm_control", \ - "cm_channel" \ +#define CMLD_DEV_NAME \ + { "cm_control", \ + "cm_channel", \ + "cm_sia_trace", \ + "cm_sva_trace", \ } /* diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index ef9753de7a4..53e07cd3137 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -14,9 +14,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -29,7 +29,7 @@ #include "cm_service.h" #include "cm_dma.h" -#define CMDRIVER_PATCH_VERSION 117 +#define CMDRIVER_PATCH_VERSION 122 #define O_FLUSH 0x1000000 static int cmld_major; @@ -233,111 +233,6 @@ static void freeProcessPriv(struct kref *ref) OSAL_Free(entry); } -/** Driver's open method - * Allocates per-process resources: private data, wait queue, - * memory area descriptors linked list, message queue. - * - * \return POSIX error code - */ -static int cmld_open(struct inode *inode, struct file *file) -{ - struct cm_process_priv *procPriv = getProcessPriv(); - - if (IS_ERR(procPriv)) - return PTR_ERR(procPriv); - - if (iminor(inode) == 0) - file->private_data = procPriv; - else { - struct cm_channel_priv *channelPriv = (struct cm_channel_priv*)OSAL_Alloc(sizeof(*channelPriv)); - if (channelPriv == NULL) { - kref_put(&procPriv->ref, freeProcessPriv); - return -ENOMEM; - } - - channelPriv->proc = procPriv; - channelPriv->state = CHANNEL_OPEN; - - /* Initialize wait_queue, lists and mutexes */ - init_waitqueue_head(&channelPriv->waitq); - plist_head_init(&channelPriv->messageQueue); - INIT_LIST_HEAD(&channelPriv->skelList); - spin_lock_init(&channelPriv->bh_lock); - mutex_init(&channelPriv->msgQueueLock); - mutex_init(&channelPriv->skelListLock); - - tasklet_disable(&cmld_service_tasklet); - mutex_lock(&channel_lock); - list_add(&channelPriv->entry, &channel_list); - mutex_unlock(&channel_lock); - tasklet_enable(&cmld_service_tasklet); - - file->private_data = channelPriv; // store channel private struct in file descriptor - } - return 0; -} - -/** Driver's release method. - * Frees any per-process pending resource: components, bindings, memory areas. - * - * \return POSIX error code - */ -static int cmld_release(struct inode *inode, struct file *file) -{ - struct cm_process_priv* procPriv; - - /* The driver must guarantee that all related resources are released. - Thus all these checks below are necessary to release all remaining - resources still linked to this 'client', in case of abnormal process - exit. - => These are error cases ! - In the usual case, nothing should be done except the free of - the cmPriv itself - */ - - if (iminor(inode) != 0) { - struct cm_channel_priv* channelPriv; - channelPriv = file->private_data; - procPriv = channelPriv->proc; - - /* We don't need to synchronize here by using the skelListLock: - the list is only accessed during ioctl() and we can't be here - if an ioctl() is on-going */ - if (list_empty(&channelPriv->skelList)) { - /* There is no pending MPC->HOST binding - => we can quietly delete the channel */ - tasklet_disable(&cmld_service_tasklet); - mutex_lock(&channel_lock); - list_del(&channelPriv->entry); - mutex_unlock(&channel_lock); - tasklet_enable(&cmld_service_tasklet); - - /* Free all remaining messages if any */ - freeMessages(channelPriv); - - /* Free the per-channel descriptor */ - OSAL_Free(channelPriv); - } else { - /* Uh: there are still some MPC->HOST binding but we don't have the - required info to unbind them. - => we must keep all skel structures because possibly used in OSAL_PostDfc - (incoming callback msg) */ - /* We flag the channel as closed to discard any new msg that will never be read anyway */ - channelPriv->state = CHANNEL_CLOSED; - - /* Already Free all remaining messages if any, - they will never be read anyway */ - freeMessages(channelPriv); - } - } else - procPriv = file->private_data; - - kref_put(&procPriv->ref, freeProcessPriv); - file->private_data = NULL; - - return 0; -} - /** Reads Component Manager messages destinated to this process. * The message is composed by three fields: * 1) mpc2host handle (distinguishes interfaces) @@ -347,19 +242,16 @@ static int cmld_release(struct inode *inode, struct file *file) * \note cfr GetEvent() * \return POSIX error code */ -static ssize_t cmld_read(struct file *file, char *buf, size_t count, loff_t *ppos) +static ssize_t cmld_channel_read(struct file *file, char *buf, size_t count, loff_t *ppos) { int err = 0; - struct cm_channel_priv* channelPriv = (struct cm_channel_priv*)(file->private_data); + struct cm_channel_priv* channelPriv = file->private_data; int msgSize = 0; struct plist_head* messageQueue; struct osal_msg* msg; t_os_message *os_msg = (t_os_message *)buf; int block = !(file->f_flags & O_NONBLOCK); - if (iminor(file->f_dentry->d_inode) == 0) - return -ENOSYS; - messageQueue = &channelPriv->messageQueue; if (mutex_lock_killable(&channelPriv->msgQueueLock)) @@ -459,19 +351,21 @@ out: * * \return POSIX error code */ -static int cmld_flush(struct file *file, fl_owner_t id) +static int cmld_channel_flush(struct file *file, fl_owner_t id) { - if (iminor(file->f_dentry->d_inode) != 0) { - struct cm_channel_priv* channelPriv = (struct cm_channel_priv*)(file->private_data); - file->f_flags |= O_FLUSH; - wake_up_interruptible(&channelPriv->waitq); - } + struct cm_channel_priv* channelPriv = file->private_data; + file->f_flags |= O_FLUSH; + wake_up(&channelPriv->waitq); return 0; } -static long cmld_channel_ctl(struct file *file, unsigned int cmd, unsigned long arg) +static long cmld_channel_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cm_channel_priv *channelPriv = file->private_data; +#ifdef CONFIG_DEBUG_FS + if (wait_event_interruptible(dump_waitq, (!cmld_dump_ongoing))) + return -ERESTARTSYS; +#endif switch(cmd) { /* @@ -480,7 +374,7 @@ static long cmld_channel_ctl(struct file *file, unsigned int cmd, unsigned long case CM_BINDCOMPONENTTOCMCORE: return cmld_BindComponentToCMCore(channelPriv, (CM_BindComponentToCMCore_t *)arg); case CM_FLUSHCHANNEL: - return cmld_flush(file, 0); + return cmld_channel_flush(file, 0); default: pr_err("CM(%s): unsupported command %i\n", __func__, cmd); return -EINVAL; @@ -488,9 +382,18 @@ static long cmld_channel_ctl(struct file *file, unsigned int cmd, unsigned long return 0; } -static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long arg) +static long cmld_control_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cm_process_priv* procPriv = file->private_data; +#ifdef CONFIG_DEBUG_FS + if (cmd == CM_PRIV_DEBUGFS_DUMP_DONE) { + cmld_dump_ongoing = false; + wake_up(&dump_waitq); + return 0; + } else if (wait_event_interruptible(dump_waitq, (!cmld_dump_ongoing))) + return -ERESTARTSYS; +#endif + switch(cmd) { /* * All wrapped CM SYSCALL @@ -695,7 +598,6 @@ static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long cmld_user_has_debugfs = true; #endif return 0; - case CM_PRIV_DEBUGFS_DUMP_DONE: case CM_PRIV_DEBUGFS_WAIT_DUMP: return 0; default: @@ -706,29 +608,6 @@ static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long return 0; } -/** Driver's ioctl method - * Implements user/kernel crossing for SYSCALL API. - * - * \return POSIX error code - */ -static long cmld_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ -#ifdef CONFIG_DEBUG_FS - if (cmd == CM_PRIV_DEBUGFS_DUMP_DONE) { - cmld_dump_ongoing = false; - wake_up_interruptible(&dump_waitq); - return 0; - } else if (wait_event_interruptible(dump_waitq, (!cmld_dump_ongoing))) - return -ERESTARTSYS; -#endif - - if (iminor(filp->f_dentry->d_inode) == 0) { - return cmld_control_ctl(filp, cmd, arg); - } else { - return cmld_channel_ctl(filp, cmd, arg); - } -} - /** VMA open callback function */ static void cmld_vma_open(struct vm_area_struct* vma) { @@ -755,7 +634,7 @@ static struct vm_operations_struct cmld_remap_vm_ops = { * * \return POSIX error code */ -static int cmld_mmap(struct file* file, struct vm_area_struct* vma) +static int cmld_control_mmap(struct file *file, struct vm_area_struct *vma) { unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; struct list_head* listHead; @@ -827,6 +706,278 @@ static int cmld_mmap(struct file* file, struct vm_area_struct* vma) return 0; } +/* Driver's release method for /dev/cm_channel */ +static int cmld_channel_release(struct inode *inode, struct file *file) +{ + struct cm_channel_priv* channelPriv = file->private_data; + struct cm_process_priv* procPriv = channelPriv->proc; + + /* + * The driver must guarantee that all related resources are released. + * Thus all these checks below are necessary to release all remaining + * resources still linked to this 'client', in case of abnormal process + * exit. + * => These are error cases ! + * In the usual case, nothing should be done except the free of + * the cmPriv itself + */ + + /* We don't need to synchronize here by using the skelListLock: + the list is only accessed during ioctl() and we can't be here + if an ioctl() is on-going */ + if (list_empty(&channelPriv->skelList)) { + /* There is no pending MPC->HOST binding + => we can quietly delete the channel */ + tasklet_disable(&cmld_service_tasklet); + mutex_lock(&channel_lock); + list_del(&channelPriv->entry); + mutex_unlock(&channel_lock); + tasklet_enable(&cmld_service_tasklet); + + /* Free all remaining messages if any */ + freeMessages(channelPriv); + + /* Free the per-channel descriptor */ + OSAL_Free(channelPriv); + } else { + /* + * Uh: there are still some MPC->HOST binding but we don't have + * the required info to unbind them. + * => we must keep all skel structures because possibly used in + * OSAL_PostDfc (incoming callback msg). We flag the channel as + * closed to discard any new msg that will never be read anyway + */ + channelPriv->state = CHANNEL_CLOSED; + + /* Already Free all remaining messages if any, + they will never be read anyway */ + freeMessages(channelPriv); + } + + kref_put(&procPriv->ref, freeProcessPriv); + file->private_data = NULL; + + return 0; +} + +/* Driver's release method for /dev/cm_control */ +static int cmld_control_release(struct inode *inode, struct file *file) +{ + struct cm_process_priv* procPriv = file->private_data; + + kref_put(&procPriv->ref, freeProcessPriv); + file->private_data = NULL; + + return 0; +} + +static struct file_operations cmld_control_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = cmld_control_ioctl, + .mmap = cmld_control_mmap, + .release = cmld_control_release, +}; + +static int cmld_control_open(struct file *file) +{ + struct cm_process_priv *procPriv = getProcessPriv(); + if (IS_ERR(procPriv)) + return PTR_ERR(procPriv); + file->private_data = procPriv; + file->f_op = &cmld_control_fops; + return 0; +} + +static struct file_operations cmld_channel_fops = { + .owner = THIS_MODULE, + .read = cmld_channel_read, + .unlocked_ioctl = cmld_channel_ioctl, + .flush = cmld_channel_flush, + .release = cmld_channel_release, +}; + +static int cmld_channel_open(struct file *file) +{ + struct cm_process_priv *procPriv = getProcessPriv(); + struct cm_channel_priv *channelPriv; + + if (IS_ERR(procPriv)) + return PTR_ERR(procPriv); + + channelPriv = (struct cm_channel_priv*)OSAL_Alloc(sizeof(*channelPriv)); + if (channelPriv == NULL) { + kref_put(&procPriv->ref, freeProcessPriv); + return -ENOMEM; + } + + channelPriv->proc = procPriv; + channelPriv->state = CHANNEL_OPEN; + + /* Initialize wait_queue, lists and mutexes */ + init_waitqueue_head(&channelPriv->waitq); + plist_head_init(&channelPriv->messageQueue); + INIT_LIST_HEAD(&channelPriv->skelList); + spin_lock_init(&channelPriv->bh_lock); + mutex_init(&channelPriv->msgQueueLock); + mutex_init(&channelPriv->skelListLock); + + tasklet_disable(&cmld_service_tasklet); + mutex_lock(&channel_lock); + list_add(&channelPriv->entry, &channel_list); + mutex_unlock(&channel_lock); + tasklet_enable(&cmld_service_tasklet); + + file->private_data = channelPriv; + file->f_op = &cmld_channel_fops; + return 0; +} + +static ssize_t cmld_sxa_trace_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + struct mpcConfig *mpc = file->private_data; + size_t written = 0; + struct t_nmf_trace trace; + t_cm_trace_type traceType; + struct mmdsp_trace mmdsp_tr = { + .media = TB_MEDIA_FILE, + .receiver_dev = TB_DEV_PC, + .sender_dev = TB_DEV_TRACEBOX, + .unused = TB_TRACEBOX, + .receiver_obj = DEFAULT_RECEIVERR_OBJ, + .sender_obj = DEFAULT_SENDER_OBJ, + .transaction_id = 0, + .message_id = TB_TRACE_MSG, + .master_id = mpc->coreId+1, + .channel_id = 0, + .ost_version = OST_VERSION, + .entity = ENTITY, + .protocol_id = PROTOCOL_ID, + .btrace_hdr_flag = 0, + .btrace_hdr_subcategory = 0, + }; + + while ((count - written) >= sizeof(mmdsp_tr)) { + traceType = CM_ENGINE_GetNextTrace(mpc->coreId, &trace); + + switch (traceType) { + case CM_MPC_TRACE_READ_OVERRUN: + mmdsp_tr.size = + cpu_to_be16(offsetof(struct mmdsp_trace, + ost_version) + -offsetof(struct mmdsp_trace, + receiver_obj)); + mmdsp_tr.message_id = TB_TRACE_EXCEPTION_MSG; + mmdsp_tr.ost_master_id = TB_EXCEPTION_LONG_OVRF_PACKET; + if (copy_to_user(&buf[written], &mmdsp_tr, + offsetof(struct mmdsp_trace, + ost_version))) + return -EFAULT; + written += offsetof(struct mmdsp_trace, ost_version); + if ((count - written) < sizeof(mmdsp_tr)) + break; + case CM_MPC_TRACE_READ: { + u16 param_nr = (u16)trace.paramOpt; + u16 handle_valid = (u16)(trace.paramOpt >> 16); + u32 to_write = offsetof(struct mmdsp_trace, + parent_handle); + mmdsp_tr.transaction_id = trace.revision%256; + mmdsp_tr.message_id = TB_TRACE_MSG; + mmdsp_tr.ost_master_id = OST_MASTERID; + mmdsp_tr.timestamp = cpu_to_be64(trace.timeStamp); + mmdsp_tr.timestamp2 = cpu_to_be64(trace.timeStamp); + mmdsp_tr.component_id = cpu_to_be32(trace.componentId); + mmdsp_tr.trace_id = cpu_to_be32(trace.traceId); + mmdsp_tr.btrace_hdr_category = (trace.traceId>>16)&0xFF; + mmdsp_tr.btrace_hdr_size = BTRACE_HEADER_SIZE + + sizeof(trace.params[0]) * param_nr; + if (handle_valid) { + mmdsp_tr.parent_handle = trace.parentHandle; + mmdsp_tr.component_handle = + trace.componentHandle; + to_write += sizeof(trace.parentHandle) + + sizeof(trace.componentHandle); + mmdsp_tr.btrace_hdr_size += + sizeof(trace.parentHandle) + + sizeof(trace.componentHandle); + } + mmdsp_tr.size = + cpu_to_be16(to_write + + (sizeof(trace.params[0])*param_nr) + - offsetof(struct mmdsp_trace, + receiver_obj)); + mmdsp_tr.length = to_write + + (sizeof(trace.params[0])*param_nr) + - offsetof(struct mmdsp_trace, + timestamp2); + if (copy_to_user(&buf[written], &mmdsp_tr, to_write)) + return -EFAULT; + written += to_write; + /* write param */ + to_write = sizeof(trace.params[0]) * param_nr; + if (copy_to_user(&buf[written], trace.params, to_write)) + return -EFAULT; + written += to_write; + break; + } + case CM_MPC_TRACE_NONE: + default: + if ((file->f_flags & O_NONBLOCK) || written) + return written; + spin_lock_bh(&mpc->trace_reader_lock); + mpc->trace_reader = current; + spin_unlock_bh(&mpc->trace_reader_lock); + schedule_timeout_killable(msecs_to_jiffies(200)); + spin_lock_bh(&mpc->trace_reader_lock); + mpc->trace_reader = NULL; + spin_unlock_bh(&mpc->trace_reader_lock); + if (signal_pending(current)) + return -ERESTARTSYS; + } + } + return written; +} + +/* Driver's release method for /dev/cm_sxa_trace */ +static int cmld_sxa_trace_release(struct inode *inode, struct file *file) +{ + struct mpcConfig *mpc = file->private_data; + atomic_dec(&mpc->trace_read_count); + return 0; +} + +static struct file_operations cmld_sxa_trace_fops = { + .owner = THIS_MODULE, + .read = cmld_sxa_trace_read, + .release = cmld_sxa_trace_release, +}; + +static int cmld_sxa_trace_open(struct file *file, struct mpcConfig *mpc) +{ + if (atomic_add_unless(&mpc->trace_read_count, 1, 1) == 0) + return -EBUSY; + + file->private_data = mpc; + file->f_op = &cmld_sxa_trace_fops; + return 0; +} + +/* driver open() call: specific */ +static int cmld_open(struct inode *inode, struct file *file) +{ + switch (iminor(inode)) { + case 0: + return cmld_control_open(file); + case 1: + return cmld_channel_open(file); + case 2: + return cmld_sxa_trace_open(file, &osalEnv.mpc[SIA]); + case 3: + return cmld_sxa_trace_open(file, &osalEnv.mpc[SVA]); + default: + return -ENOSYS; + } +} + /** MPC Events tasklet * The parameter is used to know from which interrupts we're comming * and which core to pass to CM_ProcessMpcEvent(): @@ -882,12 +1033,7 @@ static irqreturn_t panic_handler(int irq, void *idx) */ static struct file_operations cmld_fops = { .owner = THIS_MODULE, - .read = cmld_read, - .unlocked_ioctl = cmld_ioctl, - .mmap = cmld_mmap, .open = cmld_open, - .flush = cmld_flush, - .release = cmld_release, }; /** diff --git a/drivers/staging/nmf-cm/cmld.h b/drivers/staging/nmf-cm/cmld.h index 4c5a5bed7e6..17e6c55ff61 100644 --- a/drivers/staging/nmf-cm/cmld.h +++ b/drivers/staging/nmf-cm/cmld.h @@ -79,6 +79,52 @@ extern bool cmld_user_has_debugfs; /**< Whether user side has proper support of extern bool cmld_dump_ongoing; /**< Whether a dump is on-going */ #endif +/* Structure used to embed DSP traces */ +#define TB_MEDIA_FILE 0x1C +#define TB_DEV_PC 0x10 +#define TB_DEV_TRACEBOX 0x4C +#define TB_TRACEBOX 0x7C +#define DEFAULT_RECEIVERR_OBJ 0x0 +#define DEFAULT_SENDER_OBJ 0x0A +#define TB_TRACE_MSG 0x94 +#define TB_TRACE_EXCEPTION_MSG 0x95 +#define TB_EXCEPTION_LONG_OVRF_PACKET 0x07 +#define OST_MASTERID 0x08 +#define OST_VERSION 0x05 +#define ENTITY 0xAA +#define PROTOCOL_ID 0x03 +#define BTRACE_HEADER_SIZE 4 + +struct __attribute__ ((__packed__)) mmdsp_trace { + u8 media; + u8 receiver_dev; + u8 sender_dev; + u8 unused; + u16 size; + u8 receiver_obj; + u8 sender_obj; + u8 transaction_id; + u8 message_id; + u8 master_id; + u8 channel_id; + u64 timestamp; + u8 ost_master_id; + u8 ost_version; + u8 entity; + u8 protocol_id; + u8 length; + u64 timestamp2; + u32 component_id; + u32 trace_id; + u8 btrace_hdr_size; + u8 btrace_hdr_flag; + u8 btrace_hdr_category; + u8 btrace_hdr_subcategory; + u32 parent_handle; + u32 component_handle; + u32 params[4]; +}; + /** Lock/unlock per process mutex * * \note Must be taken before tasklet_disable (if necessary)! diff --git a/drivers/staging/nmf-cm/configuration.c b/drivers/staging/nmf-cm/configuration.c index d62bcb45500..523874fc586 100644 --- a/drivers/staging/nmf-cm/configuration.c +++ b/drivers/staging/nmf-cm/configuration.c @@ -21,28 +21,30 @@ struct OsalEnvironment osalEnv = { .mpc = { { - .coreId = SVA_CORE_ID, - .name = "sva", - .base_phys = (void*)U8500_SVA_BASE, - .interrupt0 = IRQ_DB8500_SVA, - .interrupt1 = IRQ_DB8500_SVA2, - .mmdsp_regulator = NULL, - .pipe_regulator = NULL, - .monitor_tsk = NULL, - .hwmem_code = NULL, - .hwmem_data = NULL, + .coreId = SVA_CORE_ID, + .name = "sva", + .base_phys = (void*)U8500_SVA_BASE, + .interrupt0 = IRQ_DB8500_SVA, + .interrupt1 = IRQ_DB8500_SVA2, + .mmdsp_regulator = NULL, + .pipe_regulator = NULL, + .monitor_tsk = NULL, + .hwmem_code = NULL, + .hwmem_data = NULL, + .trace_read_count = ATOMIC_INIT(0), }, { - .coreId = SIA_CORE_ID, - .name = "sia", - .base_phys = (void*)U8500_SIA_BASE, - .interrupt0 = IRQ_DB8500_SIA, - .interrupt1 = IRQ_DB8500_SIA2, - .mmdsp_regulator = NULL, - .pipe_regulator = NULL, - .monitor_tsk = NULL, - .hwmem_code = NULL, - .hwmem_data = NULL, + .coreId = SIA_CORE_ID, + .name = "sia", + .base_phys = (void*)U8500_SIA_BASE, + .interrupt0 = IRQ_DB8500_SIA, + .interrupt1 = IRQ_DB8500_SIA2, + .mmdsp_regulator = NULL, + .pipe_regulator = NULL, + .monitor_tsk = NULL, + .hwmem_code = NULL, + .hwmem_data = NULL, + .trace_read_count = ATOMIC_INIT(0), } }, .esram_regulator = { NULL, NULL}, @@ -125,16 +127,20 @@ int init_config(void) pr_err("SDRAM data size for SVA must be greater than 0\n"); return -EINVAL; } + osalEnv.mpc[SVA].nbYramBanks = cfgMpcYBanks_SVA; osalEnv.mpc[SVA].eeId = cfgSchedulerTypeHybrid_SVA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; osalEnv.mpc[SVA].sdram_code.size = cfgMpcSDRAMCodeSize_SVA * ONE_KB; osalEnv.mpc[SVA].sdram_data.size = cfgMpcSDRAMDataSize_SVA * ONE_KB; osalEnv.mpc[SVA].base.size = 128*ONE_KB; //we expose only TCM24 + spin_lock_init(&osalEnv.mpc[SVA].trace_reader_lock); + osalEnv.mpc[SIA].nbYramBanks = cfgMpcYBanks_SIA; osalEnv.mpc[SIA].eeId = cfgSchedulerTypeHybrid_SIA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; osalEnv.mpc[SIA].sdram_code.size = cfgMpcSDRAMCodeSize_SIA * ONE_KB; osalEnv.mpc[SIA].sdram_data.size = cfgMpcSDRAMDataSize_SIA * ONE_KB; osalEnv.mpc[SIA].base.size = 128*ONE_KB; //we expose only TCM24 + spin_lock_init(&osalEnv.mpc[SIA].trace_reader_lock); return 0; } diff --git a/drivers/staging/nmf-cm/configuration.h b/drivers/staging/nmf-cm/configuration.h index 35072831a13..f4146dc6117 100644 --- a/drivers/staging/nmf-cm/configuration.h +++ b/drivers/staging/nmf-cm/configuration.h @@ -20,12 +20,14 @@ #endif /* Embedded Static RAM base address */ -#define ESRAM_BASE (U8500_ESRAM_BASE + 0x10000) // V1/V2 config: 0-64k: secure; +/* config: 0-64k: secure */ +#define ESRAM_BASE (U8500_ESRAM_BASE + U8500_ESRAM_DMA_LCPA_OFFSET) /* * Embedded ram size for CM (in Kb) * 5 banks of 128k: skip the first half bank (secure) and the last * one (used for MCDE/B2R2), but include DMA part (4k after the secure part) + * to give access from DSP side */ #define ESRAM_SIZE 448 enum { diff --git a/drivers/staging/nmf-cm/ee/api/panic.idt b/drivers/staging/nmf-cm/ee/api/panic.idt index f971fdad8c5..71996b8a55e 100644 --- a/drivers/staging/nmf-cm/ee/api/panic.idt +++ b/drivers/staging/nmf-cm/ee/api/panic.idt @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \defgroup NMF_EE_TYPE Execution Engine Common Type Definitions * \ingroup COMMON @@ -55,7 +54,8 @@ typedef enum { INTERFACE_NOT_BINDED = 8, USER_PANIC = 9, UNBIND_INTERRUPT = 10, - EVENT_FIFO_IN_USE = 11 + EVENT_FIFO_IN_USE = 11, + RESERVED_PANIC = 2 //for COMPATIBILITY with previous versions of NMF, to be deprecated } t_panic_reasonDescription; /*! diff --git a/drivers/staging/nmf-cm/ee/api/trace.idt b/drivers/staging/nmf-cm/ee/api/trace.idt new file mode 100644 index 00000000000..f4d4c8615e2 --- /dev/null +++ b/drivers/staging/nmf-cm/ee/api/trace.idt @@ -0,0 +1,30 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ +/*! + * \defgroup NMF_EE_TYPE Execution Engine Common Type Definitions + * \ingroup COMMON + */ + +#ifndef __INC_TRACE_IDT +#define __INC_TRACE_IDT + +struct t_nmf_trace +{ + t_uint32 revision; + t_uint32 timeStamp; + t_uint32 componentId; + t_uint32 traceId; + t_uint32 paramOpt; + t_uint32 componentHandle; + t_uint32 parentHandle; + t_uint32 params[4]; +}; + +#define TRACE_BUFFER_SIZE 128 + +#endif diff --git a/drivers/staging/nmf-cm/inc/nmf-def.h b/drivers/staging/nmf-cm/inc/nmf-def.h index e671198f7b9..7cdea18996b 100644 --- a/drivers/staging/nmf-cm/inc/nmf-def.h +++ b/drivers/staging/nmf-cm/inc/nmf-def.h @@ -21,7 +21,7 @@ * * \ingroup NMF_VERSION */ -#define NMF_VERSION ((2 << 16) | (10 << 8) | (118)) +#define NMF_VERSION ((2 << 16) | (10 << 8) | (122)) /*! * \brief Get NMF major version corresponding to NMF version number diff --git a/drivers/staging/nmf-cm/inc/nmf-limits.h b/drivers/staging/nmf-cm/inc/nmf-limits.h index a942e542233..374795f91e0 100644 --- a/drivers/staging/nmf-cm/inc/nmf-limits.h +++ b/drivers/staging/nmf-cm/inc/nmf-limits.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Common Nomadik Multiprocessing Framework limits definition * diff --git a/drivers/staging/nmf-cm/inc/nmf-tracedescription.h b/drivers/staging/nmf-cm/inc/nmf-tracedescription.h index 9611803b978..bce589079b9 100644 --- a/drivers/staging/nmf-cm/inc/nmf-tracedescription.h +++ b/drivers/staging/nmf-cm/inc/nmf-tracedescription.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief NMF xti/stm trace format description * diff --git a/drivers/staging/nmf-cm/inc/nmf_type.idt b/drivers/staging/nmf-cm/inc/nmf_type.idt index e8cc4e09946..dda547a463e 100644 --- a/drivers/staging/nmf-cm/inc/nmf_type.idt +++ b/drivers/staging/nmf-cm/inc/nmf_type.idt @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - #ifndef NMF_TYPE_H_ #define NMF_TYPE_H_ diff --git a/drivers/staging/nmf-cm/inc/type.h b/drivers/staging/nmf-cm/inc/type.h index d6eafe9aea5..3075505aee5 100644 --- a/drivers/staging/nmf-cm/inc/type.h +++ b/drivers/staging/nmf-cm/inc/type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /* inc/type.h - Programming Model. * * Copyright (c) 2006, 2007, 2008 STMicroelectronics. diff --git a/drivers/staging/nmf-cm/inc/typedef.h b/drivers/staging/nmf-cm/inc/typedef.h index 97af9dec2c2..a29e6b88fde 100644 --- a/drivers/staging/nmf-cm/inc/typedef.h +++ b/drivers/staging/nmf-cm/inc/typedef.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \defgroup COMMON Common types and definitions * diff --git a/drivers/staging/nmf-cm/nmf/inc/channel_type.h b/drivers/staging/nmf-cm/nmf/inc/channel_type.h index 7d439ebf0cf..91a733dbbbf 100644 --- a/drivers/staging/nmf-cm/nmf/inc/channel_type.h +++ b/drivers/staging/nmf-cm/nmf/inc/channel_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Common Nomadik Multiprocessing Framework type definition * diff --git a/drivers/staging/nmf-cm/nmf/inc/component_type.h b/drivers/staging/nmf-cm/nmf/inc/component_type.h index 08b63b21225..26217554158 100644 --- a/drivers/staging/nmf-cm/nmf/inc/component_type.h +++ b/drivers/staging/nmf-cm/nmf/inc/component_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Common Nomadik Multiprocessing Framework type definition * diff --git a/drivers/staging/nmf-cm/nmf/inc/service_type.h b/drivers/staging/nmf-cm/nmf/inc/service_type.h index 3e5473338ee..06d5c72dce9 100644 --- a/drivers/staging/nmf-cm/nmf/inc/service_type.h +++ b/drivers/staging/nmf-cm/nmf/inc/service_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Service type and data used through service callback. * \defgroup NMF_SERVICE NMF Service Callback types and data definition diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index 94aa11fc91c..e79e35db106 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -353,7 +353,7 @@ void OSAL_PostDfc(t_nmf_mpc2host_handle upLayerTHIS, t_uint32 methodIndex, t_eve spin_unlock_bh(&skelwrapper->channelPriv->bh_lock); /* Wake up process' wait queue */ - wake_up_interruptible(&skelwrapper->channelPriv->waitq); + wake_up(&skelwrapper->channelPriv->waitq); } @@ -755,8 +755,8 @@ static int dspload_monitor(void *idx) /* init counter */ if (CM_GetMpcLoadCounter(mpc->coreId, &mpc->oldLoadCounter) != CM_OK) - pr_err("CM Driver: Failed to init load counter for %s\n", - mpc->name); + pr_warn("CM Driver: Failed to init load counter for %s\n", + mpc->name); while (!kthread_should_stop()) { t_cm_mpc_load_counter loadCounter; @@ -919,7 +919,7 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam /* Compute the relative end address of the range, relative to base address of BANK1 */ - secondParam = (firstParam+secondParam-(U8500_ESRAM_BASE+0x20000)-1); + secondParam = (firstParam+secondParam-U8500_ESRAM_BANK1-1); /* if end is below base address of BANK1, it means that full range of addresses is on Bank0 */ @@ -927,16 +927,16 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam break; /* Compute the index of the last bank accessed among esram 1+2 and esram 3+4 banks */ - secondParam /= 0x40000; + secondParam /= (2*U8500_ESRAM_BANK_SIZE); WARN_ON(secondParam > 1); /* Compute the index of the first bank accessed among esram 1+2 and esram 3+4 banks Do not manage Bank 0 (secured, must be always ON) */ - if (firstParam < (U8500_ESRAM_BASE+0x20000)) + if (firstParam < U8500_ESRAM_BANK1) firstParam = 0; else - firstParam = (firstParam-(U8500_ESRAM_BASE+0x20000))/0x40000; + firstParam = (firstParam-U8500_ESRAM_BANK1)/(2*U8500_ESRAM_BANK_SIZE); /* power off the banks 1+2 and 3+4 if accessed. */ for (i=firstParam; i<=secondParam; i++) { @@ -1032,7 +1032,7 @@ t_cm_error OSAL_EnablePwrRessource(t_nmf_power_resource resource, t_uint32 first /* Compute the relative end address of the range, relative to base address of BANK1 */ - secondParam = (firstParam+secondParam-(U8500_ESRAM_BASE+0x20000)-1); + secondParam = (firstParam+secondParam-U8500_ESRAM_BANK1-1); /* if end is below base address of BANK1, it means that full range of addresses is on Bank0 */ @@ -1040,16 +1040,16 @@ t_cm_error OSAL_EnablePwrRessource(t_nmf_power_resource resource, t_uint32 first break; /* Compute the index of the last bank accessed among esram 1+2 and esram 3+4 banks */ - secondParam /= 0x40000; + secondParam /= (2*U8500_ESRAM_BANK_SIZE); WARN_ON(secondParam > 1); /* Compute the index of the first bank accessed among esram 1+2 and esram 3+4 banks Do not manage Bank 0 (secured, must be always ON) */ - if (firstParam < (U8500_ESRAM_BASE+0x20000)) + if (firstParam < U8500_ESRAM_BANK1) firstParam = 0; else - firstParam = (firstParam-(U8500_ESRAM_BASE+0x20000))/0x40000; + firstParam = (firstParam-U8500_ESRAM_BANK1)/(2*U8500_ESRAM_BANK_SIZE); /* power on the banks 1+2 and 3+4 if accessed. */ for (i=firstParam; i<=secondParam; i++) { diff --git a/drivers/staging/nmf-cm/osal-kernel.h b/drivers/staging/nmf-cm/osal-kernel.h index 7a71bdd591d..29b82368d8d 100644 --- a/drivers/staging/nmf-cm/osal-kernel.h +++ b/drivers/staging/nmf-cm/osal-kernel.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include #ifdef CONFIG_HAS_WAKELOCK #include #endif @@ -24,7 +26,6 @@ */ #define _CM_ELF_H #include -#include #include "configuration.h" @@ -56,6 +57,9 @@ struct mpcConfig { #endif struct task_struct *monitor_tsk; /**< task to monitor the dsp load; */ t_cm_mpc_load_counter oldLoadCounter; /**< previous load counter of the DSP */ + atomic_t trace_read_count; /**< number of trace reader */ + spinlock_t trace_reader_lock; + struct task_struct *trace_reader;/**< current reader task */ #ifdef CONFIG_DEBUG_FS struct dentry *dir; /**< debugfs dir entry */ struct dentry *comp_dir; /**< debugfs component dir entry */ diff --git a/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h b/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h index 5ec08434492..71dfc534f97 100644 --- a/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h +++ b/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h @@ -12,5 +12,6 @@ #define MPC_SERVICE_NONE 0 #define MPC_SERVICE_BOOT 0xB001 #define MPC_SERVICE_PRINT 0x1234 +#define MPC_SERVICE_TRACE 0x789 #endif diff --git a/drivers/staging/nmf-cm/share/inc/macros.h b/drivers/staging/nmf-cm/share/inc/macros.h index c96fe031c25..7d2c2289cd3 100644 --- a/drivers/staging/nmf-cm/share/inc/macros.h +++ b/drivers/staging/nmf-cm/share/inc/macros.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief NMF Macro API. */ diff --git a/drivers/staging/nmf-cm/share/inc/nmf.h b/drivers/staging/nmf-cm/share/inc/nmf.h index 8be8b41e5e3..2f73311c2f3 100644 --- a/drivers/staging/nmf-cm/share/inc/nmf.h +++ b/drivers/staging/nmf-cm/share/inc/nmf.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Common Nomadik Multiprocessing Framework type definition * -- cgit v1.2.3