Exemple #1
0
/* Allocate a buffer which can be used directly by hardware, 4kb aligned */
static ump_handle ump_ref_drv_allocate_internal(unsigned long size, ump_alloc_constraints constraints, ump_cache_enabled cache)
{
	ump_secure_id secure_id;
	unsigned long allocated_size = size;

	UMP_DEBUG_PRINT(4, ("Allocating UMP memory of size %lu", size));

	secure_id = ump_arch_allocate(&allocated_size, constraints);
	if (secure_id != UMP_INVALID_SECURE_ID)
	{
		unsigned long cookie;
		void * mapping;

		mapping = ump_arch_map(secure_id, allocated_size, cache, &cookie);
		if (NULL != mapping)
		{
			/*
			 * PS: By now we have actually increased the ref count in the device driver by 2,
			 * one for the allocation iteself, and one for the mapping.
			 */
			ump_mem * mem;
			mem = _ump_osu_calloc(1, sizeof(*mem));
			if (NULL != mem)
			{
				mem->secure_id = secure_id;
				mem->mapped_mem = mapping;
				mem->size = allocated_size;
				mem->cookie = cookie;
				mem->is_cached = 1; /* Default to ON, is disabled later if not */

				_ump_osu_lock_auto_init(&mem->ref_lock, 0, 0, 0);
				UMP_DEBUG_ASSERT(NULL != mem->ref_lock, ("Failed to initialize lock\n"));
				mem->ref_count = 1;

				/*
				 * ump_arch_allocate() gave us a kernel space reference, and the same did ump_arch_map()
				 * We release the one from ump_arch_allocate(), and rely solely on the one from the ump_arch_map()
				 * That is, ump_arch_unmap() should now do the final release towards the UMP kernel space driver.
				 */
				ump_arch_reference_release(secure_id);

				/* This is called only to set the cache settings in this handle */
				ump_cpu_msync_now((ump_handle)mem, UMP_MSYNC_READOUT_CACHE_ENABLED, NULL, 0);

				UMP_DEBUG_PRINT(4, ("UMP handle created for ID %u of size %lu, mapped into address 0x%08lx", mem->secure_id, mem->size, (unsigned long)mem->mapped_mem));

				return (ump_handle)mem;
			}

			ump_arch_unmap(mapping, allocated_size, cookie); /* Unmap the memory */
			ump_arch_reference_release(secure_id); /* Release reference added when we allocated the UMP memory */
		}

		ump_arch_reference_release(secure_id); /* Release reference added when we allocated the UMP memory */
	}

	UMP_DEBUG_PRINT(4, ("Allocation of UMP memory failed"));
	return UMP_INVALID_MEMORY_HANDLE;
}
UMP_API_EXPORT ump_handle ump_handle_create_from_secure_id(ump_secure_id secure_id)
{
	unsigned long size;

	UMP_DEBUG_ASSERT(UMP_INVALID_SECURE_ID != secure_id, ("Secure ID is invalid"));

	size = ump_arch_size_get(secure_id);

	if (0 != size)
	{
		unsigned long cookie;
		/*
		 * The UMP memory which the secure_id referes to could now be deleted and re-created
		 * since we don't have any references to it yet. The mapping below will however fail if
		 * we have supplied incorrect size, so we are safe.
		 */
		void *mapping = ump_arch_map(secure_id, size, UMP_CACHE_DISABLE, &cookie);

		if (NULL != mapping)
		{
			ump_mem *mem = _ump_osu_calloc(1, sizeof(*mem));

			if (NULL != mem)
			{
				mem->secure_id = secure_id;
				mem->mapped_mem = mapping;
				mem->size = size;
				mem->cookie = cookie;
				mem->is_cached = UMP_CACHE_ENABLE; /* Is set to actually check in the ump_cpu_msync_now() function */

				_ump_osu_lock_auto_init(&mem->ref_lock, _UMP_OSU_LOCKFLAG_DEFAULT, 0, 0);
				UMP_DEBUG_ASSERT(NULL != mem->ref_lock, ("Failed to initialize lock\n"));
				mem->ref_count = 1;

				/* This is called only to set the cache settings in this handle */
				ump_cpu_msync_now((ump_handle)mem, UMP_MSYNC_READOUT_CACHE_ENABLED, NULL, 0);

				UMP_DEBUG_PRINT(4, ("UMP handle created for ID %u of size %lu, mapped into address 0x%08lx", mem->secure_id, mem->size, (unsigned long)mem->mapped_mem));

				return (ump_handle)mem;
			}

			ump_arch_unmap(mapping, size, cookie);
		}
	}

	UMP_DEBUG_PRINT(2, ("UMP handle creation failed for ID %u", secure_id));

	return UMP_INVALID_MEMORY_HANDLE;
}
void ump_arch_close(void)
{
	_ump_osu_lock_auto_init(&ump_lock_arch, _UMP_OSU_LOCKFLAG_DEFAULT, 0, 0);

	/* Check that the lock was initialized */
	if (NULL == ump_lock_arch)
	{
		UMP_DEBUG_PRINT(1, ("UMP: ump_arch_close() failed to init lock\n"));
		return;
	}

	/* Attempt to obtain a lock */
	if (_UMP_OSU_ERR_OK !=  _ump_osu_lock_wait(ump_lock_arch, _UMP_OSU_LOCKMODE_RW))
	{
		UMP_DEBUG_PRINT(1, ("UMP: ump_arch_close() failed to acquire lock\n"));
		return;
	}

	UMP_DEBUG_ASSERT(0 < ump_ref_count, ("UMP: ump_arch_close() called while no references exist"));

	if (ump_ref_count > 0)
	{
		ump_ref_count--;

		if (0 == ump_ref_count)
		{
			_ump_osu_errcode_t retval = _ump_uku_close(&ump_uk_ctx);
			UMP_DEBUG_ASSERT(retval == _UMP_OSU_ERR_OK, ("UMP: Failed to close UMP interface"));
			UMP_IGNORE(retval);
			ump_uk_ctx = NULL;
			_ump_osu_lock_signal(ump_lock_arch, _UMP_OSU_LOCKMODE_RW);
			_ump_osu_lock_term(ump_lock_arch);   /* Not 100% thread safe, since another thread can already be waiting for this lock in ump_arch_open() */
			ump_lock_arch = NULL;
			return;
		}
	}

	/* Signal the lock so someone else can use it */
	_ump_osu_lock_signal(ump_lock_arch, _UMP_OSU_LOCKMODE_RW);
}