예제 #1
0
/*  ======== dmm_create_tables ========
 *  Purpose:
 *      Create table to hold the information of physical address
 *      the buffer pages that is passed by the user, and the table
 *      to hold the information of the virtual memory that is reserved
 *      for DSP.
 */
int dmm_create_tables(struct dmm_object *dmm_mgr, u32 addr, u32 size)
{
	struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
	int status = 0;

	status = dmm_delete_tables(dmm_obj);
	if (!status) {
		dyn_mem_map_beg = addr;
		table_size = PG_ALIGN_HIGH(size, PG_SIZE4K) / PG_SIZE4K;
		/*  Create the free list */
		virtual_mapping_table = __vmalloc(table_size *
				sizeof(struct map_page), GFP_KERNEL |
				__GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
		if (virtual_mapping_table == NULL)
			status = -ENOMEM;
		else {
			/* On successful allocation,
			 * all entries are zero ('free') */
			free_region = 0;
			free_size = table_size * PG_SIZE4K;
			virtual_mapping_table[0].region_size = table_size;
		}
	}

	if (status)
		pr_err("%s: failure, status 0x%x\n", __func__, status);

	return status;
}
예제 #2
0
/*
 *  ======== DSPNode_Allocate ========
 *  Purpose:
 *      Allocate data structures for controlling and communicating
 *      with a node on a specific DSP processor..
 */
DBAPI DSPNode_Allocate(DSP_HPROCESSOR hProcessor,
		 IN CONST struct DSP_UUID *pNodeID,
		 IN CONST OPTIONAL struct DSP_CBDATA *pArgs,
		 IN OPTIONAL struct DSP_NODEATTRIN *pAttrIn,
		 OUT DSP_HNODE *phNode)
{
	DSP_STATUS status = DSP_SOK;
	Trapped_Args tempStruct;
	struct CMM_OBJECT *hCmm;		/* shared memory mngr handle */
	struct CMM_INFO pInfo;		/* Used for virtual space allocation */
	PVOID pVirtBase;
	struct DSP_BUFFERATTR bufAttr;
    DSP_NODETYPE nodeType;
    struct DSP_NDBPROPS    nodeProps;
    UINT            heapSize = 0;
    PVOID           pGPPVirtAddr = NULL;
    UINT            uProfileID;
	DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_Allocate:\r\n")));
	if (!hProcessor) {
		status = DSP_EHANDLE;
		DEBUGMSG(DSPAPI_ZONE_ERROR,
			(TEXT("NODE: DSPNode_Allocate: "
				"hProcessor is Invalid \r\n")));
		goto func_cont;
	}
	if (!(pNodeID) || !(phNode)) {
		status = DSP_EPOINTER;
		DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPNode_Allocate: "
			"Invalid pointer in the Input\r\n")));
		goto func_cont;
	}
	/* First get the NODE properties, allocate, reserve
				memory for Node heap */
	if (pAttrIn) {
		status = DSPNode_GetUUIDProps(hProcessor, pNodeID, &nodeProps);
		pAttrIn->pGPPVirtAddr = NULL;
		if (DSP_SUCCEEDED(status)) {
			uProfileID = pAttrIn->uProfileID;
			DEBUGMSG(DSPAPI_ZONE_FUNCTION,
					("DSPNodeAllocate: User requested"
						  "node heap profile \n"));
			if (uProfileID < nodeProps.uCountProfiles)
				heapSize =
				nodeProps.aProfiles[uProfileID].ulHeapSize;
			if (heapSize) {
				/* allocate heap memory */
				/* Make heap size multiple of page size * */
				heapSize = PG_ALIGN_HIGH(heapSize, PG_SIZE_4K);
				/* align memory on cache line boundary * */
				pGPPVirtAddr = memalign(GEM_CACHE_LINE_SIZE,
							heapSize);
				DEBUGMSG(DSPAPI_ZONE_FUNCTION,
					("DSPNodeAllocate: Node heap memory"
							  "addr, size \n"));
				if ((pGPPVirtAddr == NULL))
					status = DSP_EMEMORY;
				pAttrIn->uHeapSize = heapSize;
				pAttrIn->pGPPVirtAddr = pGPPVirtAddr;
			}
		} else {
			DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT(
				"NODE:DSPNode_Allocate: Failed to get Node "
				"UUID properties \r\n")));
		}
	}
	if (DSP_SUCCEEDED(status)) {
		/* Set up the structure  Call DSP Trap */
		tempStruct.ARGS_NODE_ALLOCATE.hProcessor = hProcessor;
		tempStruct.ARGS_NODE_ALLOCATE.pNodeID =
						(struct DSP_UUID *)pNodeID;
		tempStruct.ARGS_NODE_ALLOCATE.pArgs =
						(struct DSP_CBDATA *)pArgs;
		tempStruct.ARGS_NODE_ALLOCATE.pAttrIn =
					(struct DSP_NODEATTRIN *)pAttrIn;
		tempStruct.ARGS_NODE_ALLOCATE.phNode = phNode;
		status = DSPTRAP_Trap(&tempStruct, CMD_NODE_ALLOCATE_OFFSET);
	}
func_cont:
	 /* If 1st SM segment is configured then allocate and map it to
		this process.*/
	if (!DSP_SUCCEEDED(status)) {
		if (pGPPVirtAddr)
			free(pGPPVirtAddr);
		return status;
	}
	tempStruct.ARGS_CMM_GETHANDLE.hProcessor = hProcessor;
	tempStruct.ARGS_CMM_GETHANDLE.phCmmMgr = &hCmm;
	status = DSPTRAP_Trap(&tempStruct, CMD_CMM_GETHANDLE_OFFSET);
	if (DSP_SUCCEEDED(status)) {
		/* Get SM segment info from CMM */
		tempStruct.ARGS_CMM_GETINFO.hCmmMgr = hCmm;
		tempStruct.ARGS_CMM_GETINFO.pCmmInfo = &pInfo;
		status = DSPTRAP_Trap(&tempStruct, CMD_CMM_GETINFO_OFFSET);
		if (DSP_FAILED(status)) {
			status = DSP_EFAIL;
			DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT(
			"NODE: DSPNode_Allocate: "
			"Failed to get SM segment\r\n")));
		} else
			status = DSP_SOK;

	} else {
		status = DSP_EFAIL;
		DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT(
			"NODE: DSPNode_Allocate:Failed to CMM handle\r\n")));
	}
	if (!DSP_SUCCEEDED(status)) {
		free(pGPPVirtAddr);
		return status;
	}

	GetNodeType(*phNode, &nodeType);
	if ((nodeType != NODE_DEVICE) && (pInfo.ulNumGPPSMSegs > 0)) {
		/* Messaging uses 1st segment */
		if ((pInfo.segInfo[0].dwSegBasePa != 0) &&
		    (pInfo.segInfo[0].ulTotalSegSize) > 0) {
			pVirtBase = mmap(NULL, pInfo.segInfo[0].ulTotalSegSize,
				 PROT_READ | PROT_WRITE, MAP_SHARED |
				 MAP_LOCKED, hMediaFile,
				 pInfo.segInfo[0].dwSegBasePa);
			if (!pVirtBase) {
				DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: "
				"DSPNode_Allocate:Virt alloc failed\r\n")));
				status = DSP_EMEMORY;
				/* Clean up */
				tempStruct.ARGS_NODE_DELETE.hNode = *phNode;
				DSPTRAP_Trap(&tempStruct,
					CMD_NODE_DELETE_OFFSET);
				return status;
			}
			/* set node translator's virt addr range for seg */
			bufAttr.uAlignment = 0;
			bufAttr.uSegment = 1 | MEMRY_SETVIRTUALSEGID;
			bufAttr.cbStruct = 0;
			status = DSPNode_AllocMsgBuf(*phNode,
					pInfo.segInfo[0].ulTotalSegSize,
					&bufAttr, (BYTE **)&pVirtBase);
			if (DSP_FAILED(status)) {
				/* If failed to set segment, unmap */
				munmap(pVirtBase,
					pInfo.segInfo[0].ulTotalSegSize);
				/* Clean up */
				tempStruct.ARGS_NODE_DELETE.hNode = *phNode;
				DSPTRAP_Trap(&tempStruct,
					CMD_NODE_DELETE_OFFSET);
			}
		}
	}
    return status;
}
예제 #3
0
/*
 *  ======== read_ext_dsp_data ========
 *      Copies DSP external memory buffers to the host side buffers.
 */
int read_ext_dsp_data(struct bridge_dev_context *dev_ctxt,
			     u8 *host_buff, u32 dsp_addr,
			     u32 ul_num_bytes, u32 mem_type)
{
	int status = 0;
	struct bridge_dev_context *dev_context = dev_ctxt;
	u32 offset;
	u32 ul_tlb_base_virt = 0;
	u32 ul_shm_offset_virt = 0;
	u32 dw_ext_prog_virt_mem;
	u32 dw_base_addr = dev_context->dsp_ext_base_addr;
	bool trace_read = false;

	if (!ul_shm_base_virt) {
		status = dev_get_symbol(dev_context->dev_obj,
					SHMBASENAME, &ul_shm_base_virt);
	}

	/* Check if it is a read of Trace section */
	if (!status && !ul_trace_sec_beg) {
		status = dev_get_symbol(dev_context->dev_obj,
					DSP_TRACESEC_BEG, &ul_trace_sec_beg);
	}

	if (!status && !ul_trace_sec_end) {
		status = dev_get_symbol(dev_context->dev_obj,
					DSP_TRACESEC_END, &ul_trace_sec_end);
	}

	if (!status) {
		if ((dsp_addr <= ul_trace_sec_end) &&
		    (dsp_addr >= ul_trace_sec_beg))
			trace_read = true;
	}

	/* If reading from TRACE, force remap/unmap */
	if (trace_read && dw_base_addr) {
		dw_base_addr = 0;
		dev_context->dsp_ext_base_addr = 0;
	}

	if (!dw_base_addr) {
		/* Initialize ul_ext_base and ul_ext_end */
		ul_ext_base = 0;
		ul_ext_end = 0;

		/* Get DYNEXT_BEG, EXT_BEG and EXT_END. */
		if (!status && !ul_dyn_ext_base) {
			status = dev_get_symbol(dev_context->dev_obj,
						DYNEXTBASE, &ul_dyn_ext_base);
		}

		if (!status) {
			status = dev_get_symbol(dev_context->dev_obj,
						EXTBASE, &ul_ext_base);
		}

		if (!status) {
			status = dev_get_symbol(dev_context->dev_obj,
						EXTEND, &ul_ext_end);
		}

		/* Trace buffer is right after the shm SEG0,
		 *  so set the base address to SHMBASE */
		if (trace_read) {
			ul_ext_base = ul_shm_base_virt;
			ul_ext_end = ul_trace_sec_end;
		}


		if (ul_ext_end < ul_ext_base)
			status = -EPERM;

		if (!status) {
			ul_tlb_base_virt =
			    dev_context->atlb_entry[0].dsp_va * DSPWORDSIZE;
			dw_ext_prog_virt_mem =
			    dev_context->atlb_entry[0].gpp_va;

			if (!trace_read) {
				ul_shm_offset_virt =
				    ul_shm_base_virt - ul_tlb_base_virt;
				ul_shm_offset_virt +=
				    PG_ALIGN_HIGH(ul_ext_end - ul_dyn_ext_base +
						  1, HW_PAGE_SIZE64KB);
				dw_ext_prog_virt_mem -= ul_shm_offset_virt;
				dw_ext_prog_virt_mem +=
				    (ul_ext_base - ul_dyn_ext_base);
				dev_context->dsp_ext_base_addr =
				    dw_ext_prog_virt_mem;

				/*
				 * This dsp_ext_base_addr will get cleared
				 * only when the board is stopped.
				*/
				if (!dev_context->dsp_ext_base_addr)
					status = -EPERM;
			}

			dw_base_addr = dw_ext_prog_virt_mem;
		}
	}

	if (!dw_base_addr || !ul_ext_base || !ul_ext_end)
		status = -EPERM;

	offset = dsp_addr - ul_ext_base;

	if (!status)
		memcpy(host_buff, (u8 *) dw_base_addr + offset, ul_num_bytes);

	return status;
}
예제 #4
0
/*
 *  ======== ReadExtDspData ========
 *      Copies DSP external memory buffers to the host side buffers.
 */
DSP_STATUS ReadExtDspData(struct WMD_DEV_CONTEXT *hDevContext,
			 OUT u8 *pbHostBuf, u32 dwDSPAddr,
			 u32 ulNumBytes, u32 ulMemType)
{
	DSP_STATUS	status = DSP_SOK;
	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
	u32	offset;
	u32	ulTLBBaseVirt = 0;
	u32	ulShmOffsetVirt = 0;
	u32	dwExtProgVirtMem;
	u32	dwBaseAddr = pDevContext->dwDspExtBaseAddr;
	bool	bTraceRead = false;

	if (!ulShmBaseVirt) {
		status = DEV_GetSymbol(pDevContext->hDevObject,
		SHMBASENAME, &ulShmBaseVirt);
	}
	DBC_Assert(ulShmBaseVirt != 0);

	/* Check if it is a read of Trace section */
	if (DSP_SUCCEEDED(status) && !ulTraceSecBeg) {
		status = DEV_GetSymbol(pDevContext->hDevObject,
		DSP_TRACESEC_BEG, &ulTraceSecBeg);
	}
	DBC_Assert(ulTraceSecBeg != 0);

	if (DSP_SUCCEEDED(status) && !ulTraceSecEnd) {
		status = DEV_GetSymbol(pDevContext->hDevObject,
		DSP_TRACESEC_END, &ulTraceSecEnd);
	}
	DBC_Assert(ulTraceSecEnd != 0);

	if (DSP_SUCCEEDED(status)) {
		if ((dwDSPAddr <= ulTraceSecEnd) &&
			(dwDSPAddr >= ulTraceSecBeg))
			bTraceRead = true;
	}

	/* If reading from TRACE, force remap/unmap */
	if (bTraceRead && dwBaseAddr) {
		dwBaseAddr = 0;
		pDevContext->dwDspExtBaseAddr = 0;
	}

	if (!dwBaseAddr) {
		/* Initialize ulExtBase and ulExtEnd */
		ulExtBase = 0;
		ulExtEnd = 0;

		/* Get DYNEXT_BEG, EXT_BEG and EXT_END.*/
		if (DSP_SUCCEEDED(status) && !ulDynExtBase) {
			status = DEV_GetSymbol(pDevContext->hDevObject,
					DYNEXTBASE, &ulDynExtBase);
		}
		DBC_Assert(ulDynExtBase != 0);

		if (DSP_SUCCEEDED(status)) {
			status = DEV_GetSymbol(pDevContext->hDevObject,
				 EXTBASE, &ulExtBase);
		}
		DBC_Assert(ulExtBase != 0);

		if (DSP_SUCCEEDED(status)) {
			status = DEV_GetSymbol(pDevContext->hDevObject,
					EXTEND,	&ulExtEnd);
		}
		DBC_Assert(ulExtEnd != 0);

	/* Trace buffer is right after the SHM SEG0,
	*  so set the base address to SHMBASE */
		if (bTraceRead) {
			ulExtBase = ulShmBaseVirt;
			ulExtEnd = ulTraceSecEnd;
		}

		DBC_Assert(ulExtEnd != 0);
		DBC_Assert(ulExtEnd > ulExtBase);

		if (ulExtEnd < ulExtBase)
			status = DSP_EFAIL;

		if (DSP_SUCCEEDED(status)) {
			ulTLBBaseVirt =
			pDevContext->aTLBEntry[0].ulDspVa * DSPWORDSIZE;
			DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
			dwExtProgVirtMem = pDevContext->aTLBEntry[0].ulGppVa;

			if (!bTraceRead) {
				ulShmOffsetVirt = ulShmBaseVirt - ulTLBBaseVirt;
				ulShmOffsetVirt += PG_ALIGN_HIGH(ulExtEnd -
						ulDynExtBase + 1,
						HW_PAGE_SIZE_64KB);
				dwExtProgVirtMem -= ulShmOffsetVirt;
				dwExtProgVirtMem += (ulExtBase - ulDynExtBase);
				pDevContext->dwDspExtBaseAddr =
						dwExtProgVirtMem;

	/* This dwDspExtBaseAddr will get cleared only when the board is
	* stopped. */
				if (!pDevContext->dwDspExtBaseAddr)
					status = DSP_EFAIL;
			}

			dwBaseAddr = dwExtProgVirtMem;
		}
	}

	if (!dwBaseAddr || !ulExtBase || !ulExtEnd)
		status = DSP_EFAIL;

	offset = dwDSPAddr - ulExtBase;

	if (DSP_SUCCEEDED(status))
		memcpy(pbHostBuf, (u8 *)dwBaseAddr+offset, ulNumBytes);

	return status;
}
int read_ext_dsp_data(struct bridge_dev_context *dev_ctxt,
			     u8 *host_buff, u32 dsp_addr,
			     u32 ul_num_bytes, u32 mem_type)
{
	int status = 0;
	struct bridge_dev_context *dev_context = dev_ctxt;
	u32 offset;
	u32 ul_tlb_base_virt = 0;
	u32 ul_shm_offset_virt = 0;
	u32 dw_ext_prog_virt_mem;
	u32 dw_base_addr = dev_context->dsp_ext_base_addr;
	bool trace_read = false;

	if (!ul_shm_base_virt) {
		status = dev_get_symbol(dev_context->dev_obj,
					SHMBASENAME, &ul_shm_base_virt);
	}

	
	if (!status && !ul_trace_sec_beg) {
		status = dev_get_symbol(dev_context->dev_obj,
					DSP_TRACESEC_BEG, &ul_trace_sec_beg);
	}

	if (!status && !ul_trace_sec_end) {
		status = dev_get_symbol(dev_context->dev_obj,
					DSP_TRACESEC_END, &ul_trace_sec_end);
	}

	if (!status) {
		if ((dsp_addr <= ul_trace_sec_end) &&
		    (dsp_addr >= ul_trace_sec_beg))
			trace_read = true;
	}

	
	if (trace_read && dw_base_addr) {
		dw_base_addr = 0;
		dev_context->dsp_ext_base_addr = 0;
	}

	if (!dw_base_addr) {
		
		ul_ext_base = 0;
		ul_ext_end = 0;

		
		if (!status && !ul_dyn_ext_base) {
			status = dev_get_symbol(dev_context->dev_obj,
						DYNEXTBASE, &ul_dyn_ext_base);
		}

		if (!status) {
			status = dev_get_symbol(dev_context->dev_obj,
						EXTBASE, &ul_ext_base);
		}

		if (!status) {
			status = dev_get_symbol(dev_context->dev_obj,
						EXTEND, &ul_ext_end);
		}

		if (trace_read) {
			ul_ext_base = ul_shm_base_virt;
			ul_ext_end = ul_trace_sec_end;
		}


		if (ul_ext_end < ul_ext_base)
			status = -EPERM;

		if (!status) {
			ul_tlb_base_virt =
			    dev_context->atlb_entry[0].dsp_va * DSPWORDSIZE;
			dw_ext_prog_virt_mem =
			    dev_context->atlb_entry[0].gpp_va;

			if (!trace_read) {
				ul_shm_offset_virt =
				    ul_shm_base_virt - ul_tlb_base_virt;
				ul_shm_offset_virt +=
				    PG_ALIGN_HIGH(ul_ext_end - ul_dyn_ext_base +
						  1, HW_PAGE_SIZE64KB);
				dw_ext_prog_virt_mem -= ul_shm_offset_virt;
				dw_ext_prog_virt_mem +=
				    (ul_ext_base - ul_dyn_ext_base);
				dev_context->dsp_ext_base_addr =
				    dw_ext_prog_virt_mem;

				if (!dev_context->dsp_ext_base_addr)
					status = -EPERM;
			}

			dw_base_addr = dw_ext_prog_virt_mem;
		}
	}

	if (!dw_base_addr || !ul_ext_base || !ul_ext_end)
		status = -EPERM;

	offset = dsp_addr - ul_ext_base;

	if (!status)
		memcpy(host_buff, (u8 *) dw_base_addr + offset, ul_num_bytes);

	return status;
}