static int gralloc_lock(gralloc_module_t const *module, buffer_handle_t handle, int usage, int l, int t, int w, int h, void **vaddr)
{
	if (private_handle_t::validate(handle) < 0)
	{
		AERR("Locking invalid buffer 0x%p, returning error", handle);
		return -EINVAL;
	}

	private_handle_t *hnd = (private_handle_t *)handle;

	if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP || hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION)
	{
		hnd->writeOwner = usage & GRALLOC_USAGE_SW_WRITE_MASK;
	}

	if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK))
	{
		*vaddr = (void *)hnd->base;
	}

	MALI_IGNORE(module);
	MALI_IGNORE(l);
	MALI_IGNORE(t);
	MALI_IGNORE(w);
	MALI_IGNORE(h);
	return 0;
}
void mali_mmu_pagedir_diag(struct mali_page_directory *pagedir, u32 fault_addr)
{
#if defined(DEBUG)
	u32 pde_index, pte_index;
	u32 pde, pte;

	pde_index = MALI_MMU_PDE_ENTRY(fault_addr);
	pte_index = MALI_MMU_PTE_ENTRY(fault_addr);


	pde = _mali_osk_mem_ioread32(pagedir->page_directory_mapped,
				     pde_index * sizeof(u32));


	if (pde & MALI_MMU_FLAGS_PRESENT) {
		u32 pte_addr = MALI_MMU_ENTRY_ADDRESS(pde);

		pte = _mali_osk_mem_ioread32(pagedir->page_entries_mapped[pde_index],
					     pte_index * sizeof(u32));

		MALI_DEBUG_PRINT(2, ("\tMMU: %08x: Page table present: %08x\n"
				     "\t\tPTE: %08x, page %08x is %s\n",
				     fault_addr, pte_addr, pte,
				     MALI_MMU_ENTRY_ADDRESS(pte),
				     pte & MALI_MMU_FLAGS_DEFAULT ? "rw" : "not present"));
	} else {
		MALI_DEBUG_PRINT(2, ("\tMMU: %08x: Page table not present: %08x\n",
				     fault_addr, pde));
	}
#else
	MALI_IGNORE(pagedir);
	MALI_IGNORE(fault_addr);
#endif
}
static int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle)
{
	MALI_IGNORE(module);
	if (private_handle_t::validate(handle) < 0)
	{
		AERR("Unlocking invalid buffer 0x%p, returning error", handle);
		return -EINVAL;
	}

	private_handle_t *hnd = (private_handle_t *)handle;
	int32_t current_value;
	int32_t new_value;
	int retry;

	if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP && hnd->writeOwner)
	{
#if GRALLOC_ARM_UMP_MODULE
		ump_cpu_msync_now((ump_handle)hnd->ump_mem_handle, UMP_MSYNC_CLEAN_AND_INVALIDATE, (void *)hnd->base, hnd->size);
#else
		AERR("Buffer 0x%p is UMP type but it is not supported", hnd);
#endif
	} else if ( hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION && hnd->writeOwner)
	{
#if GRALLOC_ARM_DMA_BUF_MODULE
		private_module_t *m = (private_module_t*)module;

		ion_sync_fd(m->ion_client, hnd->share_fd);
#endif
	}

	return 0;
}
_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args)
{
	_mali_uk_vsync_event event = (_mali_uk_vsync_event)args->event;
	MALI_IGNORE(event); /* event is not used for release code, and that is OK */

#if defined(CONFIG_MALI400_PROFILING)
	/*
	 * Manually generate user space events in kernel space.
	 * This saves user space from calling kernel space twice in this case.
	 * We just need to remember to add pid and tid manually.
	 */
	if ( event==_MALI_UK_VSYNC_EVENT_BEGIN_WAIT)
	{
		_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND |
		                              MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
		                              MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC,
		                              _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0);
	}

	if (event==_MALI_UK_VSYNC_EVENT_END_WAIT)
	{

		_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME |
		                              MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
		                              MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC,
		                              _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0);
	}
#endif

	MALI_DEBUG_PRINT(4, ("Received VSYNC event: %d\n", event));
	MALI_SUCCESS;
}
/** see comment below inside _flush() **/
MALI_STATIC void projob_cb_wrapper(mali_base_ctx_handle ctx, void * cb_param)
{
	struct mali_projob* projob = cb_param;
	MALI_DEBUG_ASSERT_POINTER(projob);
	MALI_IGNORE(ctx);
	projob->cb_func(projob->cb_param); /* call the real callback */
}
Example #6
0
_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args)
{
	_mali_uk_vsync_event event = (_mali_uk_vsync_event)args->event;
	MALI_IGNORE(event); /* event is not used for release code, and that is OK */
/*	u64 ts = _mali_timestamp_get();
 */

#if MALI_TIMELINE_PROFILING_ENABLED
	if ( event==_MALI_UK_VSYNC_EVENT_BEGIN_WAIT)
	{
		_mali_profiling_add_event(  MALI_PROFILING_EVENT_TYPE_SUSPEND |
		                            MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
		                            MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC,
		                            0, 0, 0, 0, 0);
	}

	if ( event==_MALI_UK_VSYNC_EVENT_END_WAIT)
	{

		_mali_profiling_add_event(  MALI_PROFILING_EVENT_TYPE_RESUME |
		                            MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
		                            MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC,
		                            0, 0, 0, 0, 0);
	}
#endif

	MALI_DEBUG_PRINT(4, ("Received VSYNC event: %d\n", event));
	MALI_SUCCESS;
}
_mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu)
{
	_mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
	mali_bool stall_success;
	MALI_DEBUG_ASSERT_POINTER(mmu);

	stall_success = mali_mmu_enable_stall(mmu);

	/* The stall can not fail in current hw-state */
	MALI_DEBUG_ASSERT(stall_success);
	MALI_IGNORE(stall_success);

	MALI_DEBUG_PRINT(3, ("Mali MMU: mali_kernel_mmu_reset: %s\n", mmu->hw_core.description));

	if (_MALI_OSK_ERR_OK == mali_mmu_raw_reset(mmu))
	{
		mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
		/* no session is active, so just activate the empty page directory */
		mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory);
		mali_mmu_enable_paging(mmu);
		err = _MALI_OSK_ERR_OK;
	}
	mali_mmu_disable_stall(mmu);

	return err;
}
_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args)
{
	_mali_uk_vsync_event event = (_mali_uk_vsync_event)args->event;
	MALI_IGNORE(event); /* event is not used for release code, and that is OK */
/*	u64 ts = _mali_timestamp_get();
 */

	MALI_DEBUG_PRINT(4, ("Received VSYNC event: %d\n", event));

	MALI_SUCCESS;
}
void mali_mmu_activate_page_directory(struct mali_mmu_core *mmu, struct mali_page_directory *pagedir)
{
	mali_bool stall_success;
	MALI_DEBUG_ASSERT_POINTER(mmu);

	MALI_DEBUG_PRINT(5, ("Asked to activate page directory 0x%x on MMU %s\n", pagedir, mmu->hw_core.description));

	stall_success = mali_mmu_enable_stall(mmu);
	MALI_DEBUG_ASSERT(stall_success);
	MALI_IGNORE(stall_success);
	mali_mmu_activate_address_space(mmu, pagedir->page_directory);
	mali_mmu_disable_stall(mmu);
}
Example #10
0
int mali_platform_device_deinit(struct platform_device *device)
{
	MALI_IGNORE(device);

	MALI_DEBUG_PRINT(4, ("mali_platform_device_deinit() called\n"));

	mali_core_scaling_term();

#if defined(CONFIG_ARCH_REALVIEW)
	mali_write_phys(0xC0010020, 0x9); /* Restore default (legacy) memory mapping */
#endif

	return 0;
}
static int mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf)
{
	void __user *address;
	mali_mem_allocation *descriptor;

	address = vmf->virtual_address;
	descriptor = (mali_mem_allocation *)vma->vm_private_data;

	MALI_DEBUG_ASSERT(MALI_MEM_ALLOCATION_VALID_MAGIC == descriptor->magic);

	/*
	 * We always fail the call since all memory is pre-faulted when assigned to the process.
	 * Only the Mali cores can use page faults to extend buffers.
	*/

	MALI_DEBUG_PRINT(1, ("Page-fault in Mali memory region caused by the CPU.\n"));
	MALI_DEBUG_PRINT(1, ("Tried to access %p (process local virtual address) which is not currently mapped to any Mali memory.\n", (void *)address));

	MALI_IGNORE(address);
	MALI_IGNORE(descriptor);

	return VM_FAULT_SIGBUS;
}
void mali_mmu_activate_empty_page_directory(struct mali_mmu_core *mmu)
{
	mali_bool stall_success;

	MALI_DEBUG_ASSERT_POINTER(mmu);
	MALI_DEBUG_PRINT(3, ("Activating the empty page directory on MMU %s\n", mmu->hw_core.description));

	stall_success = mali_mmu_enable_stall(mmu);

	/* This function can only be called when the core is idle, so it could not fail. */
	MALI_DEBUG_ASSERT(stall_success);
	MALI_IGNORE(stall_success);

	mali_mmu_activate_address_space(mmu, mali_empty_page_directory_phys);
	mali_mmu_disable_stall(mmu);
}
static int gralloc_unlock(gralloc_module_t const *module, buffer_handle_t handle)
{
	MALI_IGNORE(module);

	if (private_handle_t::validate(handle) < 0)
	{
		AERR("Unlocking invalid buffer 0x%p, returning error", handle);
		return -EINVAL;
	}

	private_handle_t *hnd = (private_handle_t *)handle;
	int32_t current_value;
	int32_t new_value;
	int retry;

	if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP && hnd->writeOwner)
	{
#if GRALLOC_ARM_UMP_MODULE
		ump_cpu_msync_now((ump_handle)hnd->ump_mem_handle, UMP_MSYNC_CLEAN_AND_INVALIDATE, (void *)hnd->base, hnd->size);
#else
		AERR("Buffer 0x%p is UMP type but it is not supported", hnd);
#endif
	}
	else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION && hnd->writeOwner)
	{
#if GRALLOC_ARM_DMA_BUF_MODULE
		hw_module_t *pmodule = NULL;
		private_module_t *m = NULL;

		if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&pmodule) == 0)
		{
			m = reinterpret_cast<private_module_t *>(pmodule);
			//ion_sync_fd(m->ion_client, hnd->share_fd);
		}
		else
		{
			AERR("Couldnot get gralloc module for handle 0x%p\n", handle);
		}

#endif
	}

	return 0;
}
static void do_scaling(struct work_struct *work)
{
	mali_dvfs_threshold_table * pdvfs = pmali_plat->dvfs_table;
	int err = mali_perf_set_num_pp_cores(num_cores_enabled);
	scalingdbg(1, "set pp cores to %d\n", num_cores_enabled);
	MALI_DEBUG_ASSERT(0 == err);
	MALI_IGNORE(err);
	scalingdbg(1, "pdvfs[%d].freq_index=%d, pdvfs[%d].freq_index=%d\n",
			currentStep, pdvfs[currentStep].freq_index,
			lastStep, pdvfs[lastStep].freq_index);
	mali_clk_exected();
#ifdef CONFIG_MALI400_PROFILING
	_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
			MALI_PROFILING_EVENT_CHANNEL_GPU |
			MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
			get_current_frequency(),
			0,	0,	0,	0);
#endif
}
Example #15
0
static void do_scaling(struct work_struct *work)
{
	mali_dvfs_threshold_table * pdvfs = pmali_plat->dvfs_table;
	int err = mali_perf_set_num_pp_cores(num_cores_enabled);
	MALI_DEBUG_ASSERT(0 == err);
	MALI_IGNORE(err);
	if (pdvfs[currentStep].freq_index != pdvfs[lastStep].freq_index) {
		mali_dev_pause();
		mali_clock_set(pdvfs[currentStep].freq_index);
		mali_dev_resume();
		lastStep = currentStep;
	}
#ifdef CONFIG_MALI400_PROFILING
	_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
					MALI_PROFILING_EVENT_CHANNEL_GPU |
					MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
					get_current_frequency(),
					0,	0,	0,	0);
#endif
}
static int gralloc_lock_ycbcr(struct gralloc_module_t const* module,
            buffer_handle_t handle, int usage,
            int l, int t, int w, int h,
            struct android_ycbcr *ycbcr)
{
	if (private_handle_t::validate(handle) < 0)
	{
		AERR("Locking invalid buffer 0x%p, returning error", handle );
		return -EINVAL;
	}
	private_handle_t* hnd = (private_handle_t*)handle;
	int ystride;
	int err=0;

	switch (hnd->format) {
		case HAL_PIXEL_FORMAT_YCrCb_420_SP:
			ystride = GRALLOC_ALIGN(hnd->width, 16);
			ycbcr->y  = (void*)hnd->base;
			ycbcr->cr = (void*)((uintptr_t)hnd->base + ystride * hnd->height);
			ycbcr->cb = (void*)((uintptr_t)hnd->base + ystride * hnd->height + 1);
			ycbcr->ystride = ystride;
			ycbcr->cstride = ystride;
			ycbcr->chroma_step = 2;
			memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
			break;
		case HAL_PIXEL_FORMAT_YCbCr_420_SP:
			ystride = GRALLOC_ALIGN(hnd->width, 16);
			ycbcr->y  = (void*)hnd->base;
			ycbcr->cb = (void*)((uintptr_t)hnd->base + ystride * hnd->height);
			ycbcr->cr = (void*)((uintptr_t)hnd->base + ystride * hnd->height + 1);
			ycbcr->ystride = ystride;
			ycbcr->cstride = ystride;
			ycbcr->chroma_step = 2;
			memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
			break;
		default:
			ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__,
			       hnd->format);
			err = -EINVAL;
	}

	MALI_IGNORE(module);
	MALI_IGNORE(usage);
	MALI_IGNORE(l);
	MALI_IGNORE(t);
	MALI_IGNORE(w);
	MALI_IGNORE(h);
	return err;
}
Example #17
0
void mali_pm_os_suspend(mali_bool os_suspend)
{
	int ret;

	MALI_DEBUG_PRINT(3, ("Mali PM: OS suspend\n"));

	/* Suspend execution of all jobs, and go to inactive state */
	mali_executor_suspend();

	if (os_suspend) {
		mali_control_timer_suspend(MALI_TRUE);
	}

	mali_pm_exec_lock();

	ret = mali_pm_common_suspend();

	MALI_DEBUG_ASSERT(MALI_TRUE == ret);
	MALI_IGNORE(ret);

	mali_pm_exec_unlock();
}
/**
 * Draw a quad onto a given master tile list. 
 *
 * This function is adds one drawcall to a pp tile list memory area. 
 *
 * This function will add 16 bytes of data to the pointer given pointer at the given offset. 
 * Sizes are passed in for safety reasons. The next 8 bytes are then listed as an "end list"
 * command. 
 *
 * @param master_tile_list_mem - A CPU memory pointer. 
 *                               Should probably point to some mapped GPU memory 
 * @param tile_list_mem_offset - The offset of the memory to place the commands onto. 
 *                               Inout parameter, will be increased by 16 bytes after calling. 
 * @param tile_list_mem_size   - The size of the master_tile_list_mem
 * @param mali_vertex_address  - The GPU address of the vertex buffer
 * @param mali_rsw_address     - The GPU address of the RSW 
 *
 * Note: There must be at least 16+8 available bytes in the master tile list mem block. 
 * An assert will trigger otherwise. 
 *
 */
MALI_STATIC void _mali200_draw_pp_job_quad( mali_tilelist_cmd*      master_tile_list_mem,
                                            u32*    /*inout*/       tile_list_mem_offset, 
                                            u32                     tile_list_mem_size,
                                            mali_addr               mali_vertex_address,
                                            mali_addr               mali_rsw_address)
{
	mali_tilelist_cmd* ptr = (mali_tilelist_cmd*) (((u8*)master_tile_list_mem) + *tile_list_mem_offset);

	MALI_DEBUG_ASSERT_POINTER(master_tile_list_mem);
	MALI_DEBUG_ASSERT(*tile_list_mem_offset + 3*sizeof(mali_tilelist_cmd) <= tile_list_mem_size, 
	                  ("Not enough room in master tile list: space=%i, need %i", tile_list_mem_size-(*tile_list_mem_offset), 3*sizeof(mali_tilelist_cmd))); 
	MALI_IGNORE(tile_list_mem_size); /* for release builds */
	MALI_PL_CMD_SET_BASE_VB_RSW(ptr[0], mali_vertex_address, mali_rsw_address);
	MALI_PL_PRIMITIVE(ptr[1], 
	                  MALI_PRIMITIVE_TYPE_PIXEL_RECT, 
					  0, /* rsw index, always equal to the base RSW at this point */
					  0, /* vertex0 index*/
					  1, /* vertex1 index*/ 
					  2  /* vertex2 index*/);
	MALI_PL_CMD_END_OF_LIST(ptr[2]);
	/* update the inout ptr */
	(*tile_list_mem_offset) += 2*sizeof(mali_tilelist_cmd);

}
static int gralloc_unregister_buffer(gralloc_module_t const *module, buffer_handle_t handle)
{
	MALI_IGNORE(module);

	if (private_handle_t::validate(handle) < 0)
	{
		AERR("unregistering invalid buffer 0x%p, returning error", handle);
		return -EINVAL;
	}

	private_handle_t *hnd = (private_handle_t *)handle;

	AERR_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, "[unregister] handle %p still locked (state=%08x)", hnd, hnd->lockState);

	if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)
	{
		AERR("Can't unregister buffer 0x%p as it is a framebuffer", handle);
	}
	else if (hnd->pid == getpid()) // never unmap buffers that were not registered in this process
	{
		pthread_mutex_lock(&s_map_lock);

		if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP)
		{
#if GRALLOC_ARM_UMP_MODULE
			ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle);
			ump_reference_release((ump_handle)hnd->ump_mem_handle);
			hnd->ump_mem_handle = (int)UMP_INVALID_MEMORY_HANDLE;
#else
			AERR("Can't unregister UMP buffer for handle 0x%p. Not supported", handle);
#endif
		}
		else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION)
		{
#if GRALLOC_ARM_DMA_BUF_MODULE
			void *base = (void *)hnd->base;
			size_t size = hnd->size;

			if (munmap(base, size) < 0)
			{
				AERR("Could not munmap base:0x%p size:%lu '%s'", base, (unsigned long)size, strerror(errno));
			}

#else
			AERR("Can't unregister DMA_BUF buffer for hnd %p. Not supported", hnd);
#endif

		}
		else
		{
			AERR("Unregistering unknown buffer is not supported. Flags = %d", hnd->flags);
		}

		hnd->base = 0;
		hnd->lockState  = 0;
		hnd->writeOwner = 0;

		pthread_mutex_unlock(&s_map_lock);
	}
	else
	{
		AERR("Trying to unregister buffer 0x%p from process %d that was not created in current process: %d", hnd, hnd->pid, getpid());
	}

	return 0;
}
Example #20
0
void pmm_power_down_cancel( _mali_pmm_internal_state_t *pmm )
{
	int n;
	mali_pmm_core_mask pd, ad;
	_mali_osk_errcode_t err;
	volatile mali_pmm_core_mask *pregistered;

	MALI_DEBUG_ASSERT_POINTER(pmm);

	MALIPMM_DEBUG_PRINT( ("PMM: Cancelling power down\n") );

	pd = pmm->cores_pend_down;
	ad = pmm->cores_ack_down;
	/* Clear the pending cores so that they don't move to the off
	 * queue if they haven't already
	 */
	pmm->cores_pend_down = 0;
	pmm->cores_ack_down = 0;
	pregistered = &(pmm->cores_registered);

	/* Power up all the pending power down cores - just so
	 * we make sure the system is in a known state, as a
	 * pending core might have sent an acknowledged message
	 * which hasn't been read yet.
	 */
	for( n = 0; n < SIZEOF_CORES_LIST; n++ )
	{
		if( (cores_list[n] & pd) != 0 )
		{
			/* Can't hold the power lock, when acessing subsystem mutex via
			 * the core power call.
			 * Due to terminatation of driver requiring a subsystem mutex
			 * and then power lock held to unregister a core.
			 * This does mean that the following power up function could fail
			 * as the core is unregistered before we tell it to power
			 * up, but it does not matter as we are terminating
			 */
			MALI_PMM_UNLOCK(pmm);
			/* As we are cancelling - only move the cores back to the queue - 
			 * no reset needed
			 */
			err = mali_core_signal_power_up( cores_list[n], MALI_TRUE );
			MALI_PMM_LOCK(pmm);

			/* Update pending list with the current registered cores */
			pd &= (*pregistered);

			if( err != _MALI_OSK_ERR_OK )
			{
				MALI_DEBUG_ASSERT( (err == _MALI_OSK_ERR_BUSY && 
										((cores_list[n] & ad) == 0))  ||
										(err == _MALI_OSK_ERR_FAULT &&
										(*pregistered & cores_list[n]) == 0) );
				/* If we didn't power up a core - it must be active and 
				 * hasn't actually tried to power down - this is expected
				 * for cores that haven't acknowledged
				 * Alternatively we are shutting down and the core has
				 * been unregistered
				 */
			}
		}
	}
	/* Only used in debug builds */
	MALI_IGNORE(ad);
}
static void mali_scheduler_wq_schedule_gp(void *arg)
{
	MALI_IGNORE(arg);

	mali_gp_scheduler_schedule();
}
static void set_num_cores(struct work_struct *work)
{
	int err = mali_perf_set_num_pp_cores(num_cores_enabled);
	MALI_DEBUG_ASSERT(0 == err);
	MALI_IGNORE(err);
}
static int gralloc_register_buffer(gralloc_module_t const *module, buffer_handle_t handle)
{
	MALI_IGNORE(module);

	if (private_handle_t::validate(handle) < 0)
	{
		AERR("Registering invalid buffer 0x%p, returning error", handle);
		return -EINVAL;
	}

	// if this handle was created in this process, then we keep it as is.
	private_handle_t *hnd = (private_handle_t *)handle;

	int retval = -EINVAL;

	pthread_mutex_lock(&s_map_lock);

#if GRALLOC_ARM_UMP_MODULE

	if (!s_ump_is_open)
	{
		ump_result res = ump_open(); // MJOLL-4012: UMP implementation needs a ump_close() for each ump_open

		if (res != UMP_OK)
		{
			pthread_mutex_unlock(&s_map_lock);
			AERR("Failed to open UMP library with res=%d", res);
			return retval;
		}

		s_ump_is_open = 1;
	}

#endif

	hnd->pid = getpid();

	if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)
	{
		AERR("Can't register buffer 0x%p as it is a framebuffer", handle);
	}
	else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP)
	{
#if GRALLOC_ARM_UMP_MODULE
		hnd->ump_mem_handle = (int)ump_handle_create_from_secure_id(hnd->ump_id);

		if (UMP_INVALID_MEMORY_HANDLE != (ump_handle)hnd->ump_mem_handle)
		{
			hnd->base = ump_mapped_pointer_get((ump_handle)hnd->ump_mem_handle);

			if (0 != hnd->base)
			{
				hnd->lockState = private_handle_t::LOCK_STATE_MAPPED;
				hnd->writeOwner = 0;
				hnd->lockState = 0;

				pthread_mutex_unlock(&s_map_lock);
				return 0;
			}
			else
			{
				AERR("Failed to map UMP handle 0x%x", hnd->ump_mem_handle);
			}

			ump_reference_release((ump_handle)hnd->ump_mem_handle);
		}
		else
		{
			AERR("Failed to create UMP handle 0x%x", hnd->ump_mem_handle);
		}

#else
		AERR("Gralloc does not support UMP. Unable to register UMP memory for handle 0x%p", hnd);
#endif
	}
	else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION)
	{
#if GRALLOC_ARM_DMA_BUF_MODULE
		int ret;
		unsigned char *mappedAddress;
		size_t size = hnd->size;
		hw_module_t *pmodule = NULL;
		private_module_t *m = NULL;

		if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&pmodule) == 0)
		{
			m = reinterpret_cast<private_module_t *>(pmodule);
		}
		else
		{
			AERR("Could not get gralloc module for handle: 0x%p", hnd);
			retval = -errno;
			goto cleanup;
		}

		/* the test condition is set to m->ion_client <= 0 here, because:
		 * 1) module structure are initialized to 0 if no initial value is applied
		 * 2) a second user process should get a ion fd greater than 0.
		 */
		if (m->ion_client <= 0)
		{
			/* a second user process must obtain a client handle first via ion_open before it can obtain the shared ion buffer*/
			m->ion_client = ion_open();

			if (m->ion_client < 0)
			{
				AERR("Could not open ion device for handle: 0x%p", hnd);
				retval = -errno;
				goto cleanup;
			}
		}

		mappedAddress = (unsigned char *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, hnd->share_fd, 0);

		if (MAP_FAILED == mappedAddress)
		{
			AERR("mmap( share_fd:%d ) failed with %s",  hnd->share_fd, strerror(errno));
			retval = -errno;
			goto cleanup;
		}

		hnd->base = mappedAddress + hnd->offset;
		pthread_mutex_unlock(&s_map_lock);
		return 0;
#endif
	}
	else
	{
		AERR("registering non-UMP buffer not supported. flags = %d", hnd->flags);
	}

cleanup:
	pthread_mutex_unlock(&s_map_lock);
	return retval;
}
MALI_STATIC mali_err_code allocate_and_setup_pp_job(struct mali_projob* projob, mali_mem_pool* pool, mali_frame_builder* frame_builder, mali_internal_frame* frame)
{
	void* outbuf;
	mali_tilelist_cmd* tilebuf;
	mali_addr out_addr;
	mali_addr tile_addr;
	void* new_jobarray;
	mali_pp_job_handle new_job;
	u32 num_tilebuf_commands;

	MALI_DEBUG_ASSERT_POINTER(projob);
	MALI_DEBUG_ASSERT_POINTER(pool);
	MALI_DEBUG_ASSERT_POINTER(frame_builder);

	/* grow PP job array size by one */
	new_jobarray = _mali_sys_realloc(projob->projob_pp_job_array,
	                  sizeof(mali_pp_job_handle) * (projob->projob_pp_job_array_size + 1));
	if(new_jobarray == NULL) return MALI_ERR_OUT_OF_MEMORY;
	/* use new array regardless of future errors, but don't grow the size until we use it*/
	projob->projob_pp_job_array = new_jobarray;

	/* allocate new empty job. Will mostly be set up on flush!
	 * We allocate this now to avoid memfail issues on flush! */
	new_job = _mali_pp_job_new(frame_builder->base_ctx, 1); /* split count 1 */ 
	if(new_job == NULL) return MALI_ERR_OUT_OF_MEMORY;
	
	/* we need to set up all registers for this job. The WBx registers and the 
	 * tilelist pointers in particular. Both memory blocks must be allocated right here */

	/* allocate a new output buffer. This is allocated on the fbuilder framepool. 
	 * Need space for PROJOB_DRAWCALL_LIMIT drawcalls * vec4 * fp16 bytes outputs.
	 * The space also need to be a full tile worth of outputs, so using MALI_ALIGN
	 * to expand the limit to the next MALI200_TILE_SIZE boundary. */
	outbuf = _mali_mem_pool_alloc(pool,
	             MALI_ALIGN(PROJOB_DRAWCALL_LIMIT, MALI200_TILE_SIZE*MALI200_TILE_SIZE)
				 * 4 * sizeof(u16), &out_addr);	
	if(outbuf == NULL) 
	{
		_mali_pp_job_free(new_job);
		return MALI_ERR_OUT_OF_MEMORY;
	}

	/* allocate new tilelist buffer. This is allocated on the fbuilder framepool. 
	 * Need space for PROJOB_DRAWCALL_LIMIT * 2 commands à 8 bytes each, plus initialization
	 * commands and an end command */
	num_tilebuf_commands = PROJOB_DRAWCALL_LIMIT*2 + 2; /*+2 for "begin tile" and "end list" */
	tilebuf = _mali_mem_pool_alloc(pool,
	             num_tilebuf_commands*sizeof(mali_tilelist_cmd), &tile_addr);	
	if(tilebuf == NULL) 
	{
		_mali_pp_job_free(new_job);
		return MALI_ERR_OUT_OF_MEMORY;
	}

	/* setup registers */
	_m200_frame_reg_write_common(new_job, M200_FRAME_REG_REND_LIST_ADDR, tile_addr);
	_m200_frame_reg_write_common(new_job, M200_FRAME_REG_REND_RSW_BASE, _mali_mem_mali_addr_get( frame_builder->dummy_rsw_mem, 0));
	_m200_frame_reg_write_common(new_job, M200_FRAME_REG_FEATURE_ENABLE, M200_FEATURE_FP_TILEBUF_ENABLE );
	/* Not set: Stack addr, offsets. Currently all projobs don't use stack, so it's not needed. */
	_m200_wb_reg_write( new_job, 0, M200_WBx_REG_SOURCE_SELECT, M200_WBx_SOURCE_ARGB );
	_m200_wb_reg_write( new_job, 0, M200_WBx_REG_TARGET_ADDR, out_addr );
	_m200_wb_reg_write( new_job, 0, M200_WBx_REG_TARGET_PIXEL_FORMAT, MALI_PIXEL_FORMAT_ARGB_FP16 );
	_m200_wb_reg_write( new_job, 0, M200_WBx_REG_TARGET_LAYOUT, MALI_PIXEL_LAYOUT_LINEAR);
	_m200_wb_reg_write( new_job, 0, M200_WBx_REG_TARGET_SCANLINE_LENGTH, MALI_ALIGN(PROJOB_DRAWCALL_WIDTH, MALI200_TILE_SIZE)*sizeof(u16)*4 / 8);
	_m200_wb_reg_write( new_job, 0, M200_WBx_REG_TARGET_FLAGS, M200_WBx_TARGET_FLAGS_SWAP_RED_BLUE_ENABLE);

#if MALI_TIMELINE_PROFILING_ENABLED
	_mali_pp_job_set_identity(new_job, frame_builder->identifier | MALI_FRAME_BUILDER_TYPE_PROJOB_BIT, frame->flush_id);
#else 
	MALI_IGNORE(frame);
#endif

	/* and set this new job as the current frame */
	projob->projob_pp_job_array[projob->projob_pp_job_array_size] = new_job;
	projob->projob_pp_job_array_size++;

	projob->mapped_pp_tilelist = tilebuf;
	projob->mapped_pp_tilelist_bytesize = num_tilebuf_commands*sizeof(mali_tilelist_cmd);
	projob->mapped_pp_tilelist_byteoffset = 1*sizeof(mali_tilelist_cmd); /* adding 1 command: "begin tile" */
    projob->pp_tilelist_addr = tile_addr;
    projob->output_mali_addr = out_addr;

	projob->num_pp_drawcalls_added_to_the_current_pp_job = 0;

	/* fill in begin tile / end list commands in the tile buffer */
	MALI_PL_CMD_BEGIN_NEW_TILE( tilebuf[0], 0, 0 );
	MALI_PL_CMD_END_OF_LIST(tilebuf[1]);

	/* and set up the new job to trigger the sync handle when done */
	_mali_pp_job_add_to_sync_handle(projob->sync_handle, new_job);

	return MALI_ERR_NO_ERROR;
}
void _mali_osk_atomic_term(_mali_osk_atomic_t *atom)
{
	MALI_IGNORE(atom);
}
/**
 * Check if fence has been signaled.
 *
 * @param system Timeline system.
 * @param fence Timeline fence.
 * @return MALI_TRUE if fence is signaled, MALI_FALSE if not.
 */
static mali_bool mali_timeline_fence_wait_check_status(struct mali_timeline_system *system, struct mali_timeline_fence *fence)
{
	int i;
	u32 tid = _mali_osk_get_tid();
	mali_bool ret = MALI_TRUE;
#if defined(CONFIG_SYNC)
	struct sync_fence *sync_fence = NULL;
#endif

	MALI_DEBUG_ASSERT_POINTER(system);
	MALI_DEBUG_ASSERT_POINTER(fence);

	mali_spinlock_reentrant_wait(system->spinlock, tid);

	for (i = 0; i < MALI_TIMELINE_MAX; ++i) {
		struct mali_timeline *timeline;
		mali_timeline_point   point;

		point = fence->points[i];

		if (likely(MALI_TIMELINE_NO_POINT == point)) {
			/* Fence contains no point on this timeline. */
			continue;
		}

		timeline = system->timelines[i];
		MALI_DEBUG_ASSERT_POINTER(timeline);

		if (unlikely(!mali_timeline_is_point_valid(timeline, point))) {
			MALI_PRINT_ERROR(("Mali Timeline: point %d is not valid (oldest=%d, next=%d)\n", point, timeline->point_oldest, timeline->point_next));
		}

		if (!mali_timeline_is_point_released(timeline, point)) {
			ret = MALI_FALSE;
			goto exit;
		}
	}

#if defined(CONFIG_SYNC)
	if (-1 != fence->sync_fd) {
		sync_fence = sync_fence_fdget(fence->sync_fd);
		if (likely(NULL != sync_fence)) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
			if (0 == sync_fence->status) {
#else
			if (0 == atomic_read(&sync_fence->status)) {
#endif
				ret = MALI_FALSE;
			}
		} else {
			MALI_PRINT_ERROR(("Mali Timeline: failed to get sync fence from fd %d\n", fence->sync_fd));
		}
	}
#endif /* defined(CONFIG_SYNC) */

exit:
	mali_spinlock_reentrant_signal(system->spinlock, tid);

#if defined(CONFIG_SYNC)
	if (NULL != sync_fence) {
		sync_fence_put(sync_fence);
	}
#endif /* defined(CONFIG_SYNC) */

	return ret;
}

mali_bool mali_timeline_fence_wait(struct mali_timeline_system *system, struct mali_timeline_fence *fence, u32 timeout)
{
	struct mali_timeline_fence_wait_tracker *wait;
	mali_timeline_point point;
	mali_bool ret;

	MALI_DEBUG_ASSERT_POINTER(system);
	MALI_DEBUG_ASSERT_POINTER(fence);

	MALI_DEBUG_PRINT(4, ("Mali Timeline: wait on fence\n"));

	if (MALI_TIMELINE_FENCE_WAIT_TIMEOUT_IMMEDIATELY == timeout) {
		return mali_timeline_fence_wait_check_status(system, fence);
	}

	wait = mali_timeline_fence_wait_tracker_alloc();
	if (unlikely(NULL == wait)) {
		MALI_PRINT_ERROR(("Mali Timeline: failed to allocate data for fence wait\n"));
		return MALI_FALSE;
	}

	wait->activated = MALI_FALSE;
	wait->system = system;

	/* Initialize refcount to two references.  The reference first will be released by this
	 * function after the wait is over.  The second reference will be released when the tracker
	 * is activated. */
	_mali_osk_atomic_init(&wait->refcount, 2);

	/* Add tracker to timeline system, but not to a timeline. */
	mali_timeline_tracker_init(&wait->tracker, MALI_TIMELINE_TRACKER_WAIT, fence, wait);
	point = mali_timeline_system_add_tracker(system, &wait->tracker, MALI_TIMELINE_NONE);
	MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT == point);
	MALI_IGNORE(point);

	/* Wait for the tracker to be activated or time out. */
	if (MALI_TIMELINE_FENCE_WAIT_TIMEOUT_NEVER == timeout) {
		_mali_osk_wait_queue_wait_event(system->wait_queue, mali_timeline_fence_wait_tracker_is_activated, (void *) wait);
	} else {
		_mali_osk_wait_queue_wait_event_timeout(system->wait_queue, mali_timeline_fence_wait_tracker_is_activated, (void *) wait, timeout);
	}

	ret = wait->activated;

	if (0 == _mali_osk_atomic_dec_return(&wait->refcount)) {
		mali_timeline_fence_wait_tracker_free(wait);
	}

	return ret;
}

void mali_timeline_fence_wait_activate(struct mali_timeline_fence_wait_tracker *wait)
{
	mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;

	MALI_DEBUG_ASSERT_POINTER(wait);
	MALI_DEBUG_ASSERT_POINTER(wait->system);

	MALI_DEBUG_PRINT(4, ("Mali Timeline: activation for fence wait tracker\n"));

	MALI_DEBUG_ASSERT(MALI_FALSE == wait->activated);
	wait->activated = MALI_TRUE;

	_mali_osk_wait_queue_wake_up(wait->system->wait_queue);

	/* Nothing can wait on this tracker, so nothing to schedule after release. */
	schedule_mask = mali_timeline_tracker_release(&wait->tracker);
	MALI_DEBUG_ASSERT(MALI_SCHEDULER_MASK_EMPTY == schedule_mask);
	MALI_IGNORE(schedule_mask);

	if (0 == _mali_osk_atomic_dec_return(&wait->refcount)) {
		mali_timeline_fence_wait_tracker_free(wait);
	}
}