static int mali_open(struct inode *inode, struct file *filp)
{
	struct mali_session_data * session_data;
    _mali_osk_errcode_t err;

	/* input validation */
	if (mali_miscdevice.minor != iminor(inode))
	{
		MALI_PRINT_ERROR(("mali_open() Minor does not match\n"));
		return -ENODEV;
	}

	/* allocated struct to track this session */
    err = _mali_ukk_open((void **)&session_data);
    if (_MALI_OSK_ERR_OK != err) return map_errcode(err);

	/* initialize file pointer */
	filp->f_pos = 0;

	/* link in our session data */
	filp->private_data = (void*)session_data;

	return 0;
}
Exemple #2
0
_mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core)
{
	/* Bus must be stopped before calling this function */
	const u32 reset_invalid_value = 0xC0FFE000;
	const u32 reset_check_value = 0xC01A0000;
	int i;

	MALI_DEBUG_ASSERT_POINTER(core);
	MALI_DEBUG_PRINT(2, ("Mali PP: Hard reset of core %s\n", core->hw_core.description));

	/* Set register to a bogus value. The register will be used to detect when reset is complete */
	mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_invalid_value);
	mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE);

	/* Force core to reset */
	mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET);

	/* Wait for reset to be complete */
	for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) {
		mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_check_value);
		if (reset_check_value == mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW)) {
			break;
		}
	}

	if (MALI_REG_POLL_COUNT_FAST == i) {
		MALI_PRINT_ERROR(("Mali PP: The hard reset loop didn't work, unable to recover\n"));
	}

	mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, 0x00000000); /* set it back to the default */
	/* Re-enable interrupts */
	mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL);
	mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);

	return _MALI_OSK_ERR_OK;
}
static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
#endif
{
	int err;
	struct mali_session_data *session_data;

#ifndef HAVE_UNLOCKED_IOCTL
	/* inode not used */
	(void)inode;
#endif

	MALI_DEBUG_PRINT(7, ("Ioctl received 0x%08X 0x%08lX\n", cmd, arg));

	session_data = (struct mali_session_data *)filp->private_data;
	if (NULL == session_data)
	{
		MALI_DEBUG_PRINT(7, ("filp->private_data was NULL\n"));
		return -ENOTTY;
	}

	if (NULL == (void *)arg)
	{
		MALI_DEBUG_PRINT(7, ("arg was NULL\n"));
		return -ENOTTY;
	}

	switch(cmd)
	{
		case MALI_IOC_WAIT_FOR_NOTIFICATION:
			err = wait_for_notification_wrapper(session_data, (_mali_uk_wait_for_notification_s __user *)arg);
			break;

		case MALI_IOC_GET_API_VERSION:
			err = get_api_version_wrapper(session_data, (_mali_uk_get_api_version_s __user *)arg);
			break;

		case MALI_IOC_POST_NOTIFICATION:
			err = post_notification_wrapper(session_data, (_mali_uk_post_notification_s __user *)arg);
			break;

		case MALI_IOC_GET_USER_SETTINGS:
			err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg);
			break;

#if MALI_TIMELINE_PROFILING_ENABLED
		case MALI_IOC_PROFILING_START:
			err = profiling_start_wrapper(session_data, (_mali_uk_profiling_start_s __user *)arg);
			break;

		case MALI_IOC_PROFILING_ADD_EVENT:
			err = profiling_add_event_wrapper(session_data, (_mali_uk_profiling_add_event_s __user *)arg);
			break;

		case MALI_IOC_PROFILING_STOP:
			err = profiling_stop_wrapper(session_data, (_mali_uk_profiling_stop_s __user *)arg);
			break;

		case MALI_IOC_PROFILING_GET_EVENT:
			err = profiling_get_event_wrapper(session_data, (_mali_uk_profiling_get_event_s __user *)arg);
			break;

		case MALI_IOC_PROFILING_CLEAR:
			err = profiling_clear_wrapper(session_data, (_mali_uk_profiling_clear_s __user *)arg);
			break;

		case MALI_IOC_PROFILING_GET_CONFIG:
			/* Deprecated: still compatible with get_user_settings */
			err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg);
			break;

		case MALI_IOC_PROFILING_REPORT_SW_COUNTERS:
			err = profiling_report_sw_counters_wrapper(session_data, (_mali_uk_sw_counters_report_s __user *)arg);
			break;

#else

		case MALI_IOC_PROFILING_START:              /* FALL-THROUGH */
		case MALI_IOC_PROFILING_ADD_EVENT:          /* FALL-THROUGH */
		case MALI_IOC_PROFILING_STOP:               /* FALL-THROUGH */
		case MALI_IOC_PROFILING_GET_EVENT:          /* FALL-THROUGH */
		case MALI_IOC_PROFILING_CLEAR:              /* FALL-THROUGH */
		case MALI_IOC_PROFILING_GET_CONFIG:         /* FALL-THROUGH */
		case MALI_IOC_PROFILING_REPORT_SW_COUNTERS: /* FALL-THROUGH */
			MALI_DEBUG_PRINT(2, ("Profiling not supported\n"));
			err = -ENOTTY;
			break;

#endif

		case MALI_IOC_MEM_INIT:
			err = mem_init_wrapper(session_data, (_mali_uk_init_mem_s __user *)arg);
			break;

		case MALI_IOC_MEM_TERM:
			err = mem_term_wrapper(session_data, (_mali_uk_term_mem_s __user *)arg);
			break;

		case MALI_IOC_MEM_MAP_EXT:
			err = mem_map_ext_wrapper(session_data, (_mali_uk_map_external_mem_s __user *)arg);
			break;

		case MALI_IOC_MEM_UNMAP_EXT:
			err = mem_unmap_ext_wrapper(session_data, (_mali_uk_unmap_external_mem_s __user *)arg);
			break;

		case MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE:
			err = mem_query_mmu_page_table_dump_size_wrapper(session_data, (_mali_uk_query_mmu_page_table_dump_size_s __user *)arg);
			break;

		case MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE:
			err = mem_dump_mmu_page_table_wrapper(session_data, (_mali_uk_dump_mmu_page_table_s __user *)arg);
			break;

#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0

		case MALI_IOC_MEM_ATTACH_UMP:
			err = mem_attach_ump_wrapper(session_data, (_mali_uk_attach_ump_mem_s __user *)arg);
			break;

		case MALI_IOC_MEM_RELEASE_UMP:
			err = mem_release_ump_wrapper(session_data, (_mali_uk_release_ump_mem_s __user *)arg);
			break;

#else

		case MALI_IOC_MEM_ATTACH_UMP:
		case MALI_IOC_MEM_RELEASE_UMP: /* FALL-THROUGH */
			MALI_DEBUG_PRINT(2, ("UMP not supported\n"));
			err = -ENOTTY;
			break;
#endif

#ifdef CONFIG_DMA_SHARED_BUFFER
		case MALI_IOC_MEM_ATTACH_DMA_BUF:
			err = mali_attach_dma_buf(session_data, (_mali_uk_attach_dma_buf_s __user *)arg);
			break;

		case MALI_IOC_MEM_RELEASE_DMA_BUF:
			err = mali_release_dma_buf(session_data, (_mali_uk_release_dma_buf_s __user *)arg);
			break;

		case MALI_IOC_MEM_DMA_BUF_GET_SIZE:
			err = mali_dma_buf_get_size(session_data, (_mali_uk_dma_buf_get_size_s __user *)arg);
			break;
#else

		case MALI_IOC_MEM_DMA_BUF_GET_SIZE: /* FALL-THROUGH */
			MALI_DEBUG_PRINT(2, ("DMA-BUF not supported\n"));
			err = -ENOTTY;
			break;
#endif

		case MALI_IOC_PP_START_JOB:
			err = pp_start_job_wrapper(session_data, (_mali_uk_pp_start_job_s __user *)arg);
			break;

		case MALI_IOC_PP_NUMBER_OF_CORES_GET:
			err = pp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_pp_number_of_cores_s __user *)arg);
			break;

		case MALI_IOC_PP_CORE_VERSION_GET:
			err = pp_get_core_version_wrapper(session_data, (_mali_uk_get_pp_core_version_s __user *)arg);
			break;

		case MALI_IOC_PP_DISABLE_WB:
			err = pp_disable_wb_wrapper(session_data, (_mali_uk_pp_disable_wb_s __user *)arg);
			break;

		case MALI_IOC_GP2_START_JOB:
			err = gp_start_job_wrapper(session_data, (_mali_uk_gp_start_job_s __user *)arg);
			break;

		case MALI_IOC_GP2_NUMBER_OF_CORES_GET:
			err = gp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_gp_number_of_cores_s __user *)arg);
			break;

		case MALI_IOC_GP2_CORE_VERSION_GET:
			err = gp_get_core_version_wrapper(session_data, (_mali_uk_get_gp_core_version_s __user *)arg);
			break;

		case MALI_IOC_GP2_SUSPEND_RESPONSE:
			err = gp_suspend_response_wrapper(session_data, (_mali_uk_gp_suspend_response_s __user *)arg);
			break;

		case MALI_IOC_VSYNC_EVENT_REPORT:
			err = vsync_event_report_wrapper(session_data, (_mali_uk_vsync_event_report_s __user *)arg);
			break;

		case MALI_IOC_MEM_GET_BIG_BLOCK: /* Fallthrough */
		case MALI_IOC_MEM_FREE_BIG_BLOCK:
			MALI_PRINT_ERROR(("Non-MMU mode is no longer supported.\n"));
			err = -ENOTTY;
			break;

		default:
			MALI_DEBUG_PRINT(2, ("No handler for ioctl 0x%08X 0x%08lX\n", cmd, arg));
			err = -ENOTTY;
	};

	return err;
}
Exemple #4
0
struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t *resource)
{
	struct mali_l2_cache_core *cache = NULL;
	_mali_osk_lock_flags_t lock_flags;

#if defined(MALI_UPPER_HALF_SCHEDULING)
	lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE;
#else
	lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE;
#endif

	MALI_DEBUG_PRINT(2, ("Mali L2 cache: Creating Mali L2 cache: %s\n", resource->description));

	if (mali_global_num_l2_cache_cores >= MALI_MAX_NUMBER_OF_L2_CACHE_CORES)
	{
		MALI_PRINT_ERROR(("Mali L2 cache: Too many L2 cache core objects created\n"));
		return NULL;
	}

	cache = _mali_osk_malloc(sizeof(struct mali_l2_cache_core));
	if (NULL != cache)
	{
		cache->core_id =  mali_global_num_l2_cache_cores;
		cache->counter_src0 = MALI_HW_CORE_NO_COUNTER;
		cache->counter_src1 = MALI_HW_CORE_NO_COUNTER;
		cache->pm_domain = NULL;
		cache->mali_l2_status = MALI_L2_NORMAL;
		if (_MALI_OSK_ERR_OK == mali_hw_core_create(&cache->hw_core, resource, MALI400_L2_CACHE_REGISTERS_SIZE))
		{
			cache->command_lock = _mali_osk_lock_init(lock_flags, 0, _MALI_OSK_LOCK_ORDER_L2_COMMAND);
			if (NULL != cache->command_lock)
			{
				cache->counter_lock = _mali_osk_lock_init(lock_flags, 0, _MALI_OSK_LOCK_ORDER_L2_COUNTER);
				if (NULL != cache->counter_lock)
				{
					mali_l2_cache_reset(cache);

					cache->last_invalidated_id = 0;

					mali_global_l2_cache_cores[mali_global_num_l2_cache_cores] = cache;
					mali_global_num_l2_cache_cores++;

					return cache;
				}
				else
				{
					MALI_PRINT_ERROR(("Mali L2 cache: Failed to create counter lock for L2 cache core %s\n", cache->hw_core.description));
				}

				_mali_osk_lock_term(cache->command_lock);
			}
			else
			{
				MALI_PRINT_ERROR(("Mali L2 cache: Failed to create command lock for L2 cache core %s\n", cache->hw_core.description));
			}

			mali_hw_core_delete(&cache->hw_core);
		}

		_mali_osk_free(cache);
	}
	else
	{
		MALI_PRINT_ERROR(("Mali L2 cache: Failed to allocate memory for L2 cache core\n"));
	}

	return NULL;
}
/** @note munmap handler is done by vma close handler */
int mali_mmap(struct file *filp, struct vm_area_struct *vma)
{
	struct mali_session_data *session;
	mali_mem_allocation *descriptor;
	u32 size = vma->vm_end - vma->vm_start;
	u32 mali_addr = vma->vm_pgoff << PAGE_SHIFT;

	session = (struct mali_session_data *)filp->private_data;
	if (NULL == session) {
		MALI_PRINT_ERROR(("mmap called without any session data available\n"));
		return -EFAULT;
	}

	MALI_DEBUG_PRINT(4, ("MMap() handler: start=0x%08X, phys=0x%08X, size=0x%08X vma->flags 0x%08x\n",
			     (unsigned int)vma->vm_start, (unsigned int)(vma->vm_pgoff << PAGE_SHIFT),
			     (unsigned int)(vma->vm_end - vma->vm_start), vma->vm_flags));

	/* Set some bits which indicate that, the memory is IO memory, meaning
	 * that no paging is to be performed and the memory should not be
	 * included in crash dumps. And that the memory is reserved, meaning
	 * that it's present and can never be paged out (see also previous
	 * entry)
	 */
	vma->vm_flags |= VM_IO;
	vma->vm_flags |= VM_DONTCOPY;
	vma->vm_flags |= VM_PFNMAP;
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
	vma->vm_flags |= VM_RESERVED;
#else
	vma->vm_flags |= VM_DONTDUMP;
	vma->vm_flags |= VM_DONTEXPAND;
#endif

	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
	vma->vm_ops = &mali_kernel_vm_ops; /* Operations used on any memory system */

	descriptor = mali_mem_block_alloc(mali_addr, size, vma, session);
	if (NULL == descriptor) {
		descriptor = mali_mem_os_alloc(mali_addr, size, vma, session);
		if (NULL == descriptor) {
			MALI_DEBUG_PRINT(3, ("MMAP failed\n"));
			return -ENOMEM;
		}
	}

	MALI_DEBUG_ASSERT(MALI_MEM_ALLOCATION_VALID_MAGIC == descriptor->magic);

	vma->vm_private_data = (void *)descriptor;

	/* Put on descriptor map */
	if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session->descriptor_mapping, descriptor, &descriptor->id)) {
		_mali_osk_mutex_wait(session->memory_lock);
		if (MALI_MEM_OS == descriptor->type) {
			mali_mem_os_release(descriptor);
		} else if (MALI_MEM_BLOCK == descriptor->type) {
			mali_mem_block_release(descriptor);
		}
		_mali_osk_mutex_signal(session->memory_lock);
		return -EFAULT;
	}

	return 0;
}
Exemple #6
0
_mali_osk_errcode_t malipmm_create(_mali_osk_resource_t *resource)
{
	/* Create PMM state memory */
	MALI_DEBUG_ASSERT( pmm_state == NULL );
	pmm_state = (_mali_pmm_internal_state_t *) _mali_osk_malloc(sizeof(*pmm_state));
	MALI_CHECK_NON_NULL( pmm_state, _MALI_OSK_ERR_NOMEM );	

	/* All values get 0 as default */
	_mali_osk_memset(pmm_state, 0, sizeof(*pmm_state));

	/* Set up the initial PMM state */
	pmm_state->waiting = 0;
	pmm_state->status = MALI_PMM_STATUS_IDLE;
	pmm_state->state = MALI_PMM_STATE_UNAVAILABLE; /* Until a core registers */

	/* Set up policy via compile time option for the moment */
#if MALI_PMM_ALWAYS_ON
	pmm_state->policy = MALI_PMM_POLICY_ALWAYS_ON;
#else 
	pmm_state->policy = MALI_PMM_POLICY_JOB_CONTROL;
#endif
	
#if MALI_PMM_TRACE
	_mali_pmm_trace_policy_change( MALI_PMM_POLICY_NONE, pmm_state->policy );
#endif

	/* Set up assumes all values are initialized to NULL or MALI_FALSE, so
	 * we can exit halfway through set up and perform clean up
	 */
#if !MALI_PMM_NO_PMU
	if( mali_platform_init(resource) != _MALI_OSK_ERR_OK ) goto pmm_fail_cleanup;
	pmm_state->pmu_initialized = MALI_TRUE;
#endif

	pmm_state->queue = _mali_osk_notification_queue_init();
	if( !pmm_state->queue ) goto pmm_fail_cleanup;

	pmm_state->iqueue = _mali_osk_notification_queue_init();
	if( !pmm_state->iqueue ) goto pmm_fail_cleanup;

	/* We are creating an IRQ handler just for the worker thread it gives us */
	pmm_state->irq = _mali_osk_irq_init( _MALI_OSK_IRQ_NUMBER_PMM,
		malipmm_irq_uhandler,
		malipmm_irq_bhandler,
		NULL,
		NULL,
		(void *)pmm_state,            /* PMM state is passed to IRQ */
		"PMM handler" );

	if( !pmm_state->irq ) goto pmm_fail_cleanup;
#ifdef CONFIG_SMP
	mali_pmm_lock  = _mali_osk_lock_init((_mali_osk_lock_flags_t)( _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED), 0, 0);
	if( !mali_pmm_lock ) goto pmm_fail_cleanup;
#endif /* CONFIG_SMP */

	pmm_state->lock = _mali_osk_lock_init((_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED), 0, 75);
	if( !pmm_state->lock ) goto pmm_fail_cleanup;

	if( _mali_osk_atomic_init( &(pmm_state->messages_queued), 0 ) != _MALI_OSK_ERR_OK )
	{
		goto pmm_fail_cleanup;
	}

	MALIPMM_DEBUG_PRINT( ("PMM: subsystem created, policy=%d\n", pmm_state->policy) );

	MALI_SUCCESS;

pmm_fail_cleanup:
	MALI_PRINT_ERROR( ("PMM: subsystem failed to be created\n") );
	if( pmm_state )
	{
		_mali_osk_resource_type_t t = PMU;
		if( pmm_state->lock ) _mali_osk_lock_term( pmm_state->lock );
		if( pmm_state->irq ) _mali_osk_irq_term( pmm_state->irq );
		if( pmm_state->queue ) _mali_osk_notification_queue_term( pmm_state->queue );
		if( pmm_state->iqueue ) _mali_osk_notification_queue_term( pmm_state->iqueue );		
		if( pmm_state->pmu_initialized ) ( mali_platform_deinit(&t) );
		_mali_osk_free(pmm_state);
		pmm_state = NULL; 
	}
	MALI_ERROR( _MALI_OSK_ERR_FAULT );
}
Exemple #7
0
struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t *resource, struct mali_group *group)
{
	struct mali_pp_core* core = NULL;

	MALI_DEBUG_PRINT(2, ("Mali PP: Creating Mali PP core: %s\n", resource->description));
	MALI_DEBUG_PRINT(2, ("Mali PP: Base address of PP core: 0x%x\n", resource->base));

	if (mali_global_num_pp_cores >= MALI_MAX_NUMBER_OF_PP_CORES)
	{
		MALI_PRINT_ERROR(("Mali PP: Too many PP core objects created\n"));
		return NULL;
	}

	core = _mali_osk_malloc(sizeof(struct mali_pp_core));
	if (NULL != core)
	{
		core->group = group;
		core->core_id = mali_global_num_pp_cores;
		core->running_job = NULL;
		core->counter_src0 = MALI_HW_CORE_NO_COUNTER;
		core->counter_src1 = MALI_HW_CORE_NO_COUNTER;
		core->counter_src0_used = MALI_HW_CORE_NO_COUNTER;
		core->counter_src1_used = MALI_HW_CORE_NO_COUNTER;
		if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI200_REG_SIZEOF_REGISTER_BANK))
		{
			_mali_osk_errcode_t ret;

			mali_group_lock(group);
			ret = mali_pp_reset(core);
			mali_group_unlock(group);

			if (_MALI_OSK_ERR_OK == ret)
			{
				/* Setup IRQ handlers (which will do IRQ probing if needed) */
				core->irq = _mali_osk_irq_init(resource->irq,
				                               mali_pp_upper_half,
				                               mali_pp_bottom_half,
				                               mali_pp_irq_probe_trigger,
				                               mali_pp_irq_probe_ack,
				                               core,
				                               "mali_pp_irq_handlers");
				if (NULL != core->irq)
				{
					/* Initialise the timeout timer */
					core->timeout_timer = _mali_osk_timer_init();
					if(NULL != core->timeout_timer)
					{
						_mali_osk_timer_setcallback(core->timeout_timer, mali_pp_timeout, (void *)core);

						mali_global_pp_cores[mali_global_num_pp_cores] = core;
						mali_global_num_pp_cores++;

						return core;
					}
					else
					{
						MALI_PRINT_ERROR(("Failed to setup timeout timer for PP core %s\n", core->hw_core.description));
						/* Release IRQ handlers */
						_mali_osk_irq_term(core->irq);
					}
				}
				else
				{
					MALI_PRINT_ERROR(("Mali PP: Failed to setup interrupt handlers for PP core %s\n", core->hw_core.description));
				}
			}
			mali_hw_core_delete(&core->hw_core);
		}

		_mali_osk_free(core);
	}
	else
	{
		MALI_PRINT_ERROR(("Mali PP: Failed to allocate memory for PP core\n"));
	}

	return NULL;
}
Exemple #8
0
_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core)
{
	int i;
	const int request_loop_count = 20;

	MALI_DEBUG_ASSERT_POINTER(core);
	MALI_DEBUG_PRINT(4, ("Mali PP: Reset of core %s\n", core->hw_core.description));
	MALI_ASSERT_GROUP_LOCKED(core->group);

	mali_pp_post_process_job(core); /* @@@@?is there some cases where it is unsafe to post process the job here? */

	mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */


#if defined(USING_MALI200)

	/* On Mali-200, stop the  bus, then do a hard reset of the core */

	mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS);

	for (i = 0; i < request_loop_count; i++)
	{
		if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED)
		{
			break;
		}
		_mali_osk_time_ubusydelay(10);
	}

	if (request_loop_count == i)
	{
		MALI_PRINT_ERROR(("Mali PP: Failed to stop bus for core %s, unable to recover\n", core->hw_core.description));
		return _MALI_OSK_ERR_FAULT ;
	}

	/* the bus was stopped OK, do the hard reset */
	mali_pp_hard_reset(core);

#elif defined(USING_MALI400)

	/* Mali-300 and Mali-400 have a safe reset command which we use */

	mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI400PP_REG_VAL_IRQ_RESET_COMPLETED);
	mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET);

	for (i = 0; i < request_loop_count; i++)
	{
		if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI400PP_REG_VAL_IRQ_RESET_COMPLETED)
		{
			break;
		}
		_mali_osk_time_ubusydelay(10);
	}

	if (request_loop_count == i)
	{
		MALI_DEBUG_PRINT(2, ("Mali PP: Failed to reset core %s, Status: 0x%08x\n", core->hw_core.description, mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS)));
		return _MALI_OSK_ERR_FAULT;
	}
#else
#error "no supported mali core defined"
#endif

	/* Re-enable interrupts */
	mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL);
	mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);

	return _MALI_OSK_ERR_OK;
}
Exemple #9
0
_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core)
{
    int i;
    const int request_loop_count = 20;

    MALI_DEBUG_ASSERT_POINTER(core);
    MALI_DEBUG_PRINT(4, ("Mali GP: Reset of core %s\n", core->hw_core.description));
    MALI_ASSERT_GROUP_LOCKED(core->group);

    mali_gp_post_process_job(core, MALI_FALSE);

    mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, 0);

#if defined(USING_MALI200)



    mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS);

    for (i = 0; i < request_loop_count; i++)
    {
        if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED)
        {
            break;
        }
        _mali_osk_time_ubusydelay(10);
    }

    if (request_loop_count == i)
    {
        MALI_PRINT_ERROR(("Mali GP: Failed to stop bus for core %s, unable to recover\n", core->hw_core.description));
        return _MALI_OSK_ERR_FAULT;
    }


    mali_gp_hard_reset(core);

#elif defined(USING_MALI400)



    mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALI400GP_REG_VAL_IRQ_RESET_COMPLETED);
    mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALI400GP_REG_VAL_CMD_SOFT_RESET);

    for (i = 0; i < request_loop_count; i++)
    {
        if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALI400GP_REG_VAL_IRQ_RESET_COMPLETED)
        {
            break;
        }
        _mali_osk_time_ubusydelay(10);
    }

    if (request_loop_count == i)
    {
        MALI_PRINT_ERROR(("Mali GP: Failed to reset core %s, unable to recover\n", core->hw_core.description));
        return _MALI_OSK_ERR_FAULT;
    }
#else
#error "no supported mali core defined"
#endif


    mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL);
    mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED);

    return _MALI_OSK_ERR_OK;
}
static void mali_user_settings_notify(_mali_uk_user_setting_t setting, u32 value)
{
	mali_bool done = MALI_FALSE;

	/*
	 * This function gets a bit complicated because we can't hold the session lock while
	 * allocating notification objects.
	 */

	while (!done) {
		u32 i;
		u32 num_sessions_alloc;
		u32 num_sessions_with_lock;
		u32 used_notification_objects = 0;
		_mali_osk_notification_t **notobjs;

		/* Pre allocate the number of notifications objects we need right now (might change after lock has been taken) */
		num_sessions_alloc = mali_session_get_count();
		if (0 == num_sessions_alloc) {
			/* No sessions to report to */
			return;
		}

		notobjs = (_mali_osk_notification_t **)_mali_osk_malloc(sizeof(_mali_osk_notification_t *) * num_sessions_alloc);
		if (NULL == notobjs) {
			MALI_PRINT_ERROR(("Failed to notify user space session about num PP core change (alloc failure)\n"));
			return;
		}

		for (i = 0; i < num_sessions_alloc; i++) {
			notobjs[i] = _mali_osk_notification_create(_MALI_NOTIFICATION_SETTINGS_CHANGED,
			             sizeof(_mali_uk_settings_changed_s));
			if (NULL != notobjs[i]) {
				_mali_uk_settings_changed_s *data;
				data = notobjs[i]->result_buffer;

				data->setting = setting;
				data->value = value;
			} else {
				MALI_PRINT_ERROR(("Failed to notify user space session about setting change (alloc failure %u)\n", i));
			}
		}

		mali_session_lock();

		/* number of sessions will not change while we hold the lock */
		num_sessions_with_lock = mali_session_get_count();

		if (num_sessions_alloc >= num_sessions_with_lock) {
			/* We have allocated enough notification objects for all the sessions atm */
			struct mali_session_data *session, *tmp;
			MALI_SESSION_FOREACH(session, tmp, link) {
				MALI_DEBUG_ASSERT(used_notification_objects < num_sessions_alloc);
				if (NULL != notobjs[used_notification_objects]) {
					mali_session_send_notification(session, notobjs[used_notification_objects]);
					notobjs[used_notification_objects] = NULL; /* Don't track this notification object any more */
				}
				used_notification_objects++;
			}
			done = MALI_TRUE;
		}

		mali_session_unlock();

		/* Delete any remaining/unused notification objects */
		for (; used_notification_objects < num_sessions_alloc; used_notification_objects++) {
			if (NULL != notobjs[used_notification_objects]) {
				_mali_osk_notification_delete(notobjs[used_notification_objects]);
			}
		}

		_mali_osk_free(notobjs);
	}
static void mali_gp_bottom_half(void *data)
{
	struct mali_gp_core *core = (struct mali_gp_core *)data;
	u32 irq_readout;
	u32 irq_errors;

#if MALI_TIMELINE_PROFILING_ENABLED
	_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), MALI_PROFILING_MAKE_EVENT_DATA_CORE_GP(0), 0, 0);
#endif

	mali_group_lock(core->group); /* Group lock grabbed in core handlers, but released in common group handler */

	if ( MALI_FALSE == mali_group_power_is_on(core->group) )
	{
		MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", core->hw_core.description));
		mali_group_unlock(core->group);
#if MALI_TIMELINE_PROFILING_ENABLED
		_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
#endif
		return;
	}

	irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALIGP2_REG_VAL_IRQ_MASK_USED;
	MALI_DEBUG_PRINT(4, ("Mali GP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, core->hw_core.description));

	if (irq_readout & (MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST))
	{
		u32 core_status = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS);
		if (0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE))
		{
			mali_gp_post_process_job(core, MALI_FALSE);
			MALI_DEBUG_PRINT(4, ("Mali GP: Job completed, calling group handler\n"));
			mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_COMPLETED); /* Will release group lock */
#if MALI_TIMELINE_PROFILING_ENABLED
		_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
#endif
			return;
		}
	}

	/*
	 * Now lets look at the possible error cases (IRQ indicating error or timeout)
	 * END_CMD_LST, HANG and PLBU_OOM interrupts are not considered error.
	 */
	irq_errors = irq_readout & ~(MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_HANG|MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM);
	if (0 != irq_errors)
	{
		mali_gp_post_process_job(core, MALI_FALSE);
		MALI_PRINT_ERROR(("Mali GP: Unknown interrupt 0x%08X from core %s, aborting job\n", irq_readout, core->hw_core.description));
		mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_FAILED); /* Will release group lock */
#if MALI_TIMELINE_PROFILING_ENABLED
		_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
#endif
		return;
	}
	else if (MALI_TRUE == core->core_timed_out) /* SW timeout */
	{
		if (core->timeout_job_id == mali_gp_job_get_id(core->running_job))
		{
			mali_gp_post_process_job(core, MALI_FALSE);
			MALI_DEBUG_PRINT(2, ("Mali GP: Job %d timed out\n", mali_gp_job_get_id(core->running_job)));
			mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_TIMED_OUT);
		}
		core->core_timed_out = MALI_FALSE;
#if MALI_TIMELINE_PROFILING_ENABLED
		_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
#endif
		return;
	}
	else if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM)
	{
		/* GP wants more memory in order to continue.
		 *
		 * This must be handled prior to HANG because this actually can
		 * generate a HANG while waiting for more memory.
		 * And it must be handled before the completion interrupts,
		 * since the PLBU can run out of memory after VS is complete;
		 * in which case the OOM must be handled before to complete the
		 * PLBU work.
		 */
		mali_gp_post_process_job(core, MALI_TRUE);
		MALI_DEBUG_PRINT(3, ("Mali GP: PLBU needs more heap memory\n"));
		mali_group_bottom_half(core->group, GROUP_EVENT_GP_OOM); /* Will release group lock */
#if MALI_TIMELINE_PROFILING_ENABLED
		_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
#endif
		return;
	}
	else if (irq_readout & MALIGP2_REG_VAL_IRQ_HANG)
	{
		/* we mask hang interrupts, so this should never happen... */
		MALI_DEBUG_ASSERT( 0 );
	}

	/* The only way to get here is if we only got one of two needed END_CMD_LST
	 * interrupts. Disable the interrupt that has been received and continue to
	 * run. */
	mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK,
			MALIGP2_REG_VAL_IRQ_MASK_USED &
			((irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST)
			? ~MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST
			: ~MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST
			));
	mali_group_unlock(core->group);

#if MALI_TIMELINE_PROFILING_ENABLED
	_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
#endif
}
_mali_osk_errcode_t mali_pmm_pmu_init(_mali_osk_resource_t *resource)
{

	if( resource->type == PMU )
	{
		if( (resource->base == 0) ||
			(resource->description == NULL) )
		{
			/* NOTE: We currently don't care about any other resource settings */
			MALI_PRINT_ERROR(("PLATFORM mali400-pmu: Missing PMU set up information\n"));
			MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
		}
		pmu_info = (platform_pmu_t *)_mali_osk_malloc(sizeof(*pmu_info));
		MALI_CHECK_NON_NULL( pmu_info, _MALI_OSK_ERR_NOMEM );	

		/* All values get 0 as default */
		_mali_osk_memset(pmu_info, 0, sizeof(*pmu_info));
		
		pmu_info->reg_base_addr = resource->base;
		pmu_info->reg_size = (u32)PMU_REGISTER_ADDRESS_SPACE_SIZE;
		pmu_info->name = resource->description; 
		pmu_info->irq_num = resource->irq;

		if( _MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(pmu_info->reg_base_addr, pmu_info->reg_size, pmu_info->name) )
		{
			MALI_PRINT_ERROR(("PLATFORM mali400-pmu: Could not request register region (0x%08X - 0x%08X) for %s\n",
					 pmu_info->reg_base_addr, pmu_info->reg_base_addr + pmu_info->reg_size - 1, pmu_info->name));
			goto cleanup;
		}
		else
		{
			MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Success: request_mem_region: (0x%08X - 0x%08X) for %s\n",
					 pmu_info->reg_base_addr, pmu_info->reg_base_addr + pmu_info->reg_size - 1, pmu_info->name));
		}

		pmu_info->reg_mapped = _mali_osk_mem_mapioregion( pmu_info->reg_base_addr, pmu_info->reg_size, pmu_info->name );

		if( 0 == pmu_info->reg_mapped )
		{
			MALI_PRINT_ERROR(("PLATFORM mali400-pmu: Could not ioremap registers for %s .\n", pmu_info->name));
			_mali_osk_mem_unreqregion( pmu_info->reg_base_addr, pmu_info->reg_size );
			goto cleanup;
		}
		else
		{
			MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Success: ioremap_nocache: Internal ptr: (0x%08X - 0x%08X) for %s\n",
					(u32) pmu_info->reg_mapped,
					((u32)pmu_info->reg_mapped)+ pmu_info->reg_size - 1,
					pmu_info->name));
		}

		MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Success: Mapping registers to %s\n", pmu_info->name));

#if PMU_TEST
		pmu_test(pmu_info, (MALI_PMM_CORE_GP));
		pmu_test(pmu_info, (MALI_PMM_CORE_GP|MALI_PMM_CORE_L2|MALI_PMM_CORE_PP0));
#endif

		MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Initialized - %s\n", pmu_info->name) );		
	}
	else
	{
		/* Didn't expect a different resource */
		MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
	}	

	MALI_SUCCESS;
	
cleanup:
	_mali_osk_free(pmu_info);
	pmu_info = NULL;
	MALI_ERROR(_MALI_OSK_ERR_NOMEM);
}
void mali_clk_set_rate(unsigned int clk, unsigned int mhz)
{
	int err;
	unsigned long rate = (unsigned long)clk * (unsigned long)mhz;
	unsigned int read_val;

	_mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
	MALI_DEBUG_PRINT(3, ("Mali platform: Setting frequency to %d mhz\n", clk));

	if (mali_clk_get() == MALI_FALSE) {
		_mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
		return;
	}

	clk_set_parent(mali_parent_clock, mout_epll_clock);

	do {
		cpu_relax();
		read_val = __raw_readl(EXYNOS4_CLKMUX_STAT_G3D0);
	} while (((read_val >> 4) & 0x7) != 0x1);
	MALI_DEBUG_PRINT(3, ("Mali platform: set to EPLL EXYNOS4270_CLKMUX_STAT_G3D0 : 0x%08x\n", __raw_readl(EXYNOS4270_CLKMUX_STAT_G3D0)));

	err = clk_set_parent(sclk_vpll_clock, ext_xtal_clock);

	if (err)
		MALI_PRINT_ERROR(("sclk_vpll set parent to ext_xtal failed\n"));

	MALI_DEBUG_PRINT(3, ("Mali platform: set_parent_vpll : %8.x \n", (__raw_readl(EXYNOS4_CLKSRC_TOP0) >> 8) & 0x1));

	clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ);
	clk_set_parent(vpll_src_clock, ext_xtal_clock);

	err = clk_set_parent(sclk_vpll_clock, fout_vpll_clock);

	if (err)
		MALI_PRINT_ERROR(("sclk_vpll set parent to fout_vpll failed\n"));

	MALI_DEBUG_PRINT(3, ("Mali platform: set_parent_vpll : %8.x \n", (__raw_readl(EXYNOS4_CLKSRC_TOP0) >> 8) & 0x1));

	clk_set_parent(mali_parent_clock, sclk_vpll_clock);

	do {
		cpu_relax();
		read_val = __raw_readl(EXYNOS4_CLKMUX_STAT_G3D0);
	} while (((read_val >> 4) & 0x7) != 0x2);

	MALI_DEBUG_PRINT(3, ("SET to VPLL EXYNOS4270_CLKMUX_STAT_G3D0 : 0x%08x\n", __raw_readl(EXYNOS4270_CLKMUX_STAT_G3D0)));

	clk_set_parent(mali_clock, mali_parent_clock);

	if (!atomic_read(&clk_active)) {
		if (clk_enable(mali_clock) < 0) {
			_mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
			return;
		}
		atomic_set(&clk_active, 1);
	}

	err = clk_set_rate(mali_clock, rate);

	if (err)
		MALI_PRINT_ERROR(("Failed to set Mali clock: %d\n", err));

	rate = clk_get_rate(mali_clock);

	MALI_DEBUG_PRINT(1, ("Mali frequency %d\n", rate / mhz));
	GPU_MHZ = mhz;

	mali_gpu_clk = clk;
	mali_clk_put(MALI_FALSE);

	_mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
}
_mali_osk_errcode_t malipmm_core_register( mali_pmm_core_id core )
{
	_mali_osk_errcode_t err;
	_mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;

	if( pmm == NULL )
	{
		/* PMM state has not been created, this is because the PMU resource has not been 
		 * created yet.
		 * This probably means that the PMU resource has not been specfied as the first 
		 * resource in the config file
		 */
		MALI_PRINT_ERROR( ("PMM: Cannot register core %s because the PMU resource has not been\n initialized. Please make sure the PMU resource is the first resource in the\n resource configuration.\n", 
							pmm_trace_get_core_name(core)) );
		MALI_ERROR(_MALI_OSK_ERR_FAULT);
	}

	MALI_PMM_LOCK(pmm);

#if MALI_STATE_TRACKING
	pmm->mali_pmm_lock_acquired = 1;
#endif /* MALI_STATE_TRACKING */


	/* Check if the core is registered more than once in PMM */
	MALI_DEBUG_ASSERT( (pmm->cores_registered & core) == 0 );

	MALIPMM_DEBUG_PRINT( ("PMM: core registered: (0x%x) %s\n", core, pmm_trace_get_core_name(core)) );

#if !MALI_PMM_NO_PMU
	/* Make sure the core is powered up */
	err = malipmm_powerup( core );
#else
	err = _MALI_OSK_ERR_OK;
#endif
	if( _MALI_OSK_ERR_OK == err )
	{
#if MALI_PMM_TRACE
		mali_pmm_core_mask old_power = pmm->cores_powered;
#endif
		/* Assume a registered core is now powered up and idle */
		pmm->cores_registered |= core;
		pmm->cores_idle |= core;
		pmm->cores_powered |= core;
		pmm_update_system_state( pmm );

#if MALI_PMM_TRACE
		_mali_pmm_trace_hardware_change( old_power, pmm->cores_powered );
#endif		
	}
	else
	{
		MALI_PRINT_ERROR( ("PMM: Error(%d) powering up registered core: (0x%x) %s\n", 
								err, core, pmm_trace_get_core_name(core)) );
	}

#if MALI_STATE_TRACKING
	pmm->mali_pmm_lock_acquired = 0;
#endif /* MALI_STATE_TRACKING */

	MALI_PMM_UNLOCK(pmm);
	
	return err;
}
_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler,	_mali_osk_irq_bhandler_t bhandler, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *data, const char *description )
{
	mali_osk_irq_object_t *irq_object;

	irq_object = kmalloc(sizeof(mali_osk_irq_object_t), GFP_KERNEL);
	if (NULL == irq_object) return NULL;

#if MALI_LICENSE_IS_GPL
	if (NULL == mali_wq)
	{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
		mali_wq = alloc_workqueue("mali", WQ_UNBOUND, 0);
#else
		mali_wq = create_workqueue("mali");
#endif
		if(NULL == mali_wq)
		{
			MALI_PRINT_ERROR(("Unable to create Mali workqueue\n"));
			kfree(irq_object);
			return NULL;
		}
	}
#endif

	/* workqueue API changed in 2.6.20, support both versions: */
#if defined(INIT_DELAYED_WORK)
	/* New syntax: INIT_WORK( struct work_struct *work, void (*function)(struct work_struct *)) */
	INIT_WORK( &irq_object->work_queue_irq_handle, irq_handler_bottom_half);
#else
	/* Old syntax: INIT_WORK( struct work_struct *work, void (*function)(void *), void *data) */
	INIT_WORK( &irq_object->work_queue_irq_handle, irq_handler_bottom_half, irq_object);
#endif /* defined(INIT_DELAYED_WORK) */

	if (-1 == irqnum)
	{
		/* Probe for IRQ */
		if ( (NULL != trigger_func) && (NULL != ack_func) )
		{
			unsigned long probe_count = 3;
			_mali_osk_errcode_t err;
			int irq;

			MALI_DEBUG_PRINT(2, ("Probing for irq\n"));

			do
			{
				unsigned long mask;

				mask = probe_irq_on();
				trigger_func(data);

				_mali_osk_time_ubusydelay(5);

				irq = probe_irq_off(mask);
				err = ack_func(data);
			}
			while (irq < 0 && (err == _MALI_OSK_ERR_OK) && probe_count--);

			if (irq < 0 || (_MALI_OSK_ERR_OK != err)) irqnum = -1;
			else irqnum = irq;
		}
		else irqnum = -1; /* no probe functions, fault */

		if (-1 != irqnum)
		{
			/* found an irq */
			MALI_DEBUG_PRINT(2, ("Found irq %d\n", irqnum));
		}
		else
		{
			MALI_DEBUG_PRINT(2, ("Probe for irq failed\n"));
		}
	}

	irq_object->irqnum = irqnum;
	irq_object->uhandler = uhandler;
	irq_object->bhandler = bhandler;
	irq_object->data = data;

	/* Is this a real IRQ handler we need? */
	if (irqnum != _MALI_OSK_IRQ_NUMBER_FAKE && irqnum != _MALI_OSK_IRQ_NUMBER_PMM)
	{
		if (-1 == irqnum)
		{
			MALI_DEBUG_PRINT(2, ("No IRQ for core '%s' found during probe\n", description));
			kfree(irq_object);
			return NULL;
		}

		if (0 != request_irq(irqnum, irq_handler_upper_half, IRQF_SHARED, description, irq_object))
		{
			MALI_DEBUG_PRINT(2, ("Unable to install IRQ handler for core '%s'\n", description));
			kfree(irq_object);
			return NULL;
		}
	}

#if MALI_LICENSE_IS_GPL
	if ( _MALI_OSK_IRQ_NUMBER_PMM == irqnum )
	{
		pmm_wq = create_singlethread_workqueue("mali-pmm-wq");
	}
#endif

	return irq_object;
}
static _mali_osk_errcode_t mali200_renderunit_create(_mali_osk_resource_t * resource)
{
	mali_core_renderunit *core;
	_mali_osk_errcode_t err;

	MALI_DEBUG_PRINT(3, ("Mali PP: mali200_renderunit_create\n") ) ;
	/* Checking that the resource settings are correct */
#if defined(USING_MALI200)
	if(MALI200 != resource->type)
	{
		MALI_PRINT_ERROR(("Can not register this resource as a " MALI_PP_SUBSYSTEM_NAME " core."));
		MALI_ERROR(_MALI_OSK_ERR_FAULT);
	}
#elif defined(USING_MALI400)
	if(MALI400PP != resource->type)
	{
		MALI_PRINT_ERROR(("Can not register this resource as a " MALI_PP_SUBSYSTEM_NAME " core."));
		MALI_ERROR(_MALI_OSK_ERR_FAULT);
	}
#endif
	if ( 0 != resource->size )
	{
		MALI_PRINT_ERROR(("Memory size set to " MALI_PP_SUBSYSTEM_NAME " core should be zero."));
		MALI_ERROR(_MALI_OSK_ERR_FAULT);
	}

	if ( NULL == resource->description )
	{
		MALI_PRINT_ERROR(("A " MALI_PP_SUBSYSTEM_NAME " core needs a unique description field"));
		MALI_ERROR(_MALI_OSK_ERR_FAULT);
	}

	/* Create a new core object */
	core = (mali_core_renderunit*) _mali_osk_malloc(sizeof(*core));
	if ( NULL == core )
	{
		MALI_ERROR(_MALI_OSK_ERR_NOMEM);
	}

	/* Variables set to be able to open and register the core */
	core->subsystem = &subsystem_mali200 ;
	core->registers_base_addr 	= resource->base ;
	core->size 					= MALI200_REG_SIZEOF_REGISTER_BANK ;
	core->irq_nr 				= resource->irq ;
	core->description 			= resource->description;
#if USING_MMU
	core->mmu_id                = resource->mmu_id;
	core->mmu                   = NULL;
#endif
#if USING_MALI_PMM
	/* Set up core's PMM id */
	switch( subsystem_mali200.number_of_cores )
	{
	case 0:
		core->pmm_id = MALI_PMM_CORE_PP0;
		break;
	case 1:
		core->pmm_id = MALI_PMM_CORE_PP1;
		break;
	case 2:
		core->pmm_id = MALI_PMM_CORE_PP2;
		break;
	case 3:
		core->pmm_id = MALI_PMM_CORE_PP3;
		break;
	default:
		MALI_DEBUG_PRINT(1, ("Unknown supported core for PMM\n"));
		err = _MALI_OSK_ERR_FAULT;
		goto exit_on_error0;
	}
#endif

	err = mali_core_renderunit_init( core );
    if (_MALI_OSK_ERR_OK != err)
    {
		MALI_DEBUG_PRINT(1, ("Failed to initialize renderunit\n"));
		goto exit_on_error0;
    }

	/* Map the new core object, setting: core->registers_mapped  */
	err = mali_core_renderunit_map_registers(core);
	if (_MALI_OSK_ERR_OK != err)
	{
		MALI_DEBUG_PRINT(1, ("Failed to map register\n"));
		goto exit_on_error1;
	}

	/* Check that the register mapping of the core works.
	Return 0 if Mali PP core is present and accessible. */
	if (mali_benchmark) {
#if defined(USING_MALI200)
		core->core_version = (((u32)MALI_PP_PRODUCT_ID) << 16) | 5 /* Fake Mali200-r0p5 */;
#elif defined(USING_MALI400)
		core->core_version = (((u32)MALI_PP_PRODUCT_ID) << 16) | 0x0101 /* Fake Mali400-r1p1 */;
#else
#error "No supported mali core defined"
#endif
	} else {
		core->core_version = mali_core_renderunit_register_read(
		                     core,
		                     MALI200_REG_ADDR_MGMT_VERSION);
	}

	err = mali200_core_version_legal(core);
	if (_MALI_OSK_ERR_OK != err)
	{
		MALI_DEBUG_PRINT(1, ("Invalid core\n"));
		goto exit_on_error2;
	}

	/* Reset the core. Put the core into a state where it can start to render. */
	mali200_reset(core);

	/* Registering IRQ, init the work_queue_irq_handle */
	/* Adding this core as an available renderunit in the subsystem. */
	err = mali_core_subsystem_register_renderunit(&subsystem_mali200, core);
	if (_MALI_OSK_ERR_OK != err)
	{
		MALI_DEBUG_PRINT(1, ("Failed to register with core\n"));
		goto exit_on_error2;
	}
	MALI_DEBUG_PRINT(6, ("Mali PP: mali200_renderunit_create\n") ) ;

	MALI_SUCCESS;

exit_on_error2:
	mali_core_renderunit_unmap_registers(core);
exit_on_error1:
    mali_core_renderunit_term(core);
exit_on_error0:
	_mali_osk_free( core ) ;
	MALI_PRINT_ERROR(("Renderunit NOT created."));
    MALI_ERROR(err);
}
static int subsystem_mali200_irq_handler_bottom_half(struct mali_core_renderunit* core)
{
	u32 irq_readout;
	u32 current_tile_addr;
	u32 core_status;
	mali_core_job * job;
	mali200_job * job200;

	job = core->current_job;
	job200 = GET_JOB200_PTR(job);


	if (mali_benchmark) {
		irq_readout = MALI200_REG_VAL_IRQ_END_OF_FRAME;
		current_tile_addr = 0;
		core_status = 0;
	} else {
		irq_readout = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI200_REG_VAL_IRQ_MASK_USED;
		current_tile_addr = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR);
		core_status = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_STATUS);
	}

	if (NULL == job)
	{
		MALI_DEBUG_ASSERT(CORE_IDLE==core->state);
		if ( 0 != irq_readout )
		{
			MALI_PRINT_ERROR(("Interrupt from a core not running a job. IRQ: 0x%04x Status: 0x%04x", irq_readout, core_status));
		}
		return JOB_STATUS_END_UNKNOWN_ERR;
	}
	MALI_DEBUG_ASSERT(CORE_IDLE!=core->state);

	job200->irq_status |= irq_readout;

	MALI_DEBUG_PRINT_IF( 3, ( 0 != irq_readout ),
	            ("Mali PP: Job: 0x%08x  IRQ RECEIVED  Rawstat: 0x%x Tile_addr: 0x%x Status: 0x%x\n",
	            (u32)job200->user_input.user_job_ptr, irq_readout ,current_tile_addr ,core_status));

	if ( MALI200_REG_VAL_IRQ_END_OF_FRAME & irq_readout)
	{
#if defined(USING_MALI200)
		mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_FLUSH_CACHES);
#endif

		if (0 != job200->user_input.perf_counter_flag )
		{
			if (job200->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) )
			{
				job200->perf_counter0 = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
				job200->perf_counter1 = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
			}

#if defined(USING_MALI400_L2_CACHE)
			if (job200->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE) )
			{
				u32 src0;
				u32 val0;
				u32 src1;
				u32 val1;
				mali_kernel_l2_cache_get_perf_counters(&src0, &val0, &src1, &val1);

				if (job200->perf_counter_l2_src0 == src0)
				{
					job200->perf_counter_l2_val0_raw = val0;
					job200->perf_counter_l2_val0 = val0 - job200->perf_counter_l2_val0;
				}
				else
				{
					job200->perf_counter_l2_val0_raw = 0;
					job200->perf_counter_l2_val0 = 0;
				}

				if (job200->perf_counter_l2_src1 == src1)
				{
					job200->perf_counter_l2_val1_raw = val1;
					job200->perf_counter_l2_val1 = val1 - job200->perf_counter_l2_val1;
				}
				else
				{
					job200->perf_counter_l2_val1_raw = 0;
					job200->perf_counter_l2_val1 = 0;
				}
			}
#endif

		}

#if MALI_TIMELINE_PROFILING_ENABLED
		_mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number),
				job200->perf_counter0, job200->perf_counter1,
				job200->user_input.perf_counter_src0 | (job200->user_input.perf_counter_src1 << 8)
#if defined(USING_MALI400_L2_CACHE)
				| (job200->user_input.perf_counter_l2_src0 << 16) | (job200->user_input.perf_counter_l2_src1 << 24),
				job200->perf_counter_l2_val0_raw, job200->perf_counter_l2_val1_raw
#else
				, 0, 0
#endif
				);
#endif


#if MALI_STATE_TRACKING
		_mali_osk_atomic_inc(&job->session->jobs_ended);
#endif
		return JOB_STATUS_END_SUCCESS; /* reschedule */
	}
	/* Overall SW watchdog timeout or (time to do hang checking and progress detected)? */
	else if (
	         (CORE_WATCHDOG_TIMEOUT == core->state) ||
	         ((CORE_HANG_CHECK_TIMEOUT == core->state) && (current_tile_addr == job200->last_tile_list_addr))
	        )
	{
#if MALI_TIMELINE_PROFILING_ENABLED
		_mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status */
#endif
		/* no progress detected, killed by the watchdog */
		MALI_DEBUG_PRINT(2, ("M200: SW-Timeout Rawstat: 0x%x Tile_addr: 0x%x Status: 0x%x.\n", irq_readout ,current_tile_addr ,core_status) );
		/* In this case will the system outside cleanup and reset the core */

#if MALI_STATE_TRACKING
		_mali_osk_atomic_inc(&job->session->jobs_ended);
#endif

		return JOB_STATUS_END_HANG;
   	}
	/* HW watchdog triggered or an existing hang check passed? */
	else if	((CORE_HANG_CHECK_TIMEOUT == core->state) || (irq_readout & job200->active_mask & MALI200_REG_VAL_IRQ_HANG))
	{
		/* check interval in ms */
		u32 timeout = mali_core_hang_check_timeout_get();
		MALI_DEBUG_PRINT(3, ("M200: HW/SW Watchdog triggered, checking for progress in %d ms\n", timeout));
		job200->last_tile_list_addr = current_tile_addr;
		/* hw watchdog triggered, set up a progress checker every HANGCHECK ms */
		_mali_osk_timer_add(core->timer_hang_detection, _mali_osk_time_mstoticks(timeout));
		job200->active_mask &= ~MALI200_REG_VAL_IRQ_HANG; /* ignore the hw watchdoig from now on */
		mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, irq_readout & ~MALI200_REG_VAL_IRQ_HANG);
		mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, job200->active_mask);
		return JOB_STATUS_CONTINUE_RUN; /* not finished */
	}
	/* No irq pending, core still busy */
	else if ((0 == (irq_readout & MALI200_REG_VAL_IRQ_MASK_USED)) && ( 0 != (core_status & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE)))
	{
		mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, irq_readout);
		mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, job200->active_mask);
		return JOB_STATUS_CONTINUE_RUN; /* Not finished */
	}
	else
	{
#if MALI_TIMELINE_PROFILING_ENABLED
		_mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status */
#endif

		MALI_DEBUG_PRINT(1, ("Mali PP: Job: 0x%08x  CRASH?  Rawstat: 0x%x Tile_addr: 0x%x Status: 0x%x\n",
				(u32)job200->user_input.user_job_ptr, irq_readout ,current_tile_addr ,core_status) ) ;

		if (irq_readout & MALI200_REG_VAL_IRQ_BUS_ERROR)
		{
			u32 bus_error = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS);

			MALI_DEBUG_PRINT(1, ("Bus error status: 0x%08X\n", bus_error));
			MALI_DEBUG_PRINT_IF(1, (bus_error & 0x01), ("Bus write error from id 0x%02x\n", (bus_error>>2) & 0x0F));
			MALI_DEBUG_PRINT_IF(1, (bus_error & 0x02), ("Bus read error from id 0x%02x\n", (bus_error>>6) & 0x0F));
			MALI_DEBUG_PRINT_IF(1, (0 == (bus_error & 0x03)), ("Bus error but neither read or write was set as the error reason\n"));
			(void)bus_error;
		}

#if MALI_STATE_TRACKING
		_mali_osk_atomic_inc(&job->session->jobs_ended);
#endif
		return JOB_STATUS_END_UNKNOWN_ERR; /* reschedule */
	}
Exemple #18
0
struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group)
{
    struct mali_gp_core* core = NULL;

    MALI_DEBUG_ASSERT(NULL == mali_global_gp_core);
    MALI_DEBUG_PRINT(2, ("Mali GP: Creating Mali GP core: %s\n", resource->description));

    core = _mali_osk_malloc(sizeof(struct mali_gp_core));
    if (NULL != core)
    {
        core->group = group;
        core->running_job = NULL;
        core->counter_src0 = MALI_HW_CORE_NO_COUNTER;
        core->counter_src1 = MALI_HW_CORE_NO_COUNTER;
        core->counter_src0_used = MALI_HW_CORE_NO_COUNTER;
        core->counter_src1_used = MALI_HW_CORE_NO_COUNTER;
        if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALIGP2_REGISTER_ADDRESS_SPACE_SIZE))
        {
            _mali_osk_errcode_t ret;

            mali_group_lock(group);
            ret = mali_gp_reset(core);
            mali_group_unlock(group);

            if (_MALI_OSK_ERR_OK == ret)
            {

                core->irq = _mali_osk_irq_init(resource->irq,
                                               mali_gp_upper_half,
                                               mali_gp_bottom_half,
                                               mali_gp_irq_probe_trigger,
                                               mali_gp_irq_probe_ack,
                                               core,
                                               "mali_gp_irq_handlers");
                if (NULL != core->irq)
                {

                    core->timeout_timer = _mali_osk_timer_init();
                    if(NULL != core->timeout_timer)
                    {
                        _mali_osk_timer_setcallback(core->timeout_timer, mali_gp_timeout, (void *)core);
                        MALI_DEBUG_PRINT(4, ("Mali GP: set global gp core from 0x%08X to 0x%08X\n", mali_global_gp_core, core));
                        mali_global_gp_core = core;

                        return core;
                    }
                    else
                    {
                        MALI_PRINT_ERROR(("Failed to setup timeout timer for GP core %s\n", core->hw_core.description));

                        _mali_osk_irq_term(core->irq);
                    }
                }
                else
                {
                    MALI_PRINT_ERROR(("Failed to setup interrupt handlers for GP core %s\n", core->hw_core.description));
                }
            }
            mali_hw_core_delete(&core->hw_core);
        }

        _mali_osk_free(core);
    }
    else
    {
        MALI_PRINT_ERROR(("Failed to allocate memory for GP core\n"));
    }

    return NULL;
}
Exemple #19
0
static void mali_pp_bottom_half(void *data)
{
	struct mali_pp_core *core = (struct mali_pp_core *)data;
	u32 irq_readout;
	u32 irq_errors;

#if MALI_TIMELINE_PROFILING_ENABLED
#if 0  /* Bottom half TLP logging is currently not supported */
	_mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_START| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE ,  _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0);
#endif
#endif

	mali_group_lock(core->group); /* Group lock grabbed in core handlers, but released in common group handler */

	if ( MALI_FALSE == mali_group_power_is_on(core->group) )
	{
		MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", core->hw_core.description));
		mali_group_unlock(core->group);
#if MALI_TIMELINE_PROFILING_ENABLED
#if 0
		_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
#endif
#endif
		return;
	}

	irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI200_REG_VAL_IRQ_MASK_USED;

	MALI_DEBUG_PRINT(4, ("Mali PP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, core->hw_core.description));

	if (irq_readout & MALI200_REG_VAL_IRQ_END_OF_FRAME)
	{
		mali_pp_post_process_job(core);
		MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler\n"));
		mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_COMPLETED); /* Will release group lock */
#if MALI_TIMELINE_PROFILING_ENABLED
#if 0
		_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
#endif
#endif
		return;
	}

	/*
	 * Now lets look at the possible error cases (IRQ indicating error or timeout)
	 * END_OF_FRAME and HANG interrupts are not considered error.
	 */
	irq_errors = irq_readout & ~(MALI200_REG_VAL_IRQ_END_OF_FRAME|MALI200_REG_VAL_IRQ_HANG);
	if (0 != irq_errors)
	{
		mali_pp_post_process_job(core);
		MALI_PRINT_ERROR(("Mali PP: Unknown interrupt 0x%08X from core %s, aborting job\n",
		                  irq_readout, core->hw_core.description));
		mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_FAILED); /* Will release group lock */
#if MALI_TIMELINE_PROFILING_ENABLED
#if 0
		_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
#endif
#endif
		return;
	}
	else if (MALI_TRUE == core->core_timed_out) /* SW timeout */
	{
		if (core->timeout_job_id == mali_pp_job_get_id(core->running_job))
		{
			mali_pp_post_process_job(core);
			MALI_DEBUG_PRINT(2, ("Mali PP: Job %d timed out on core %s\n",
			                 mali_pp_job_get_id(core->running_job), core->hw_core.description));
			mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_TIMED_OUT); /* Will release group lock */
		}
		else
		{
			mali_group_unlock(core->group);
		}
		core->core_timed_out = MALI_FALSE;
#if MALI_TIMELINE_PROFILING_ENABLED
#if 0
		_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
#endif
#endif
		return;
	}
	else if (irq_readout & MALI200_REG_VAL_IRQ_HANG)
	{
		/* Just ignore hang interrupts, the job timer will detect hanging jobs anyways */
		mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_HANG);
	}

	/*
	 * The only way to get here is if we got a HANG interrupt, which we ignore.
	 * Re-enable interrupts and let core continue to run
	 */
	mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
	mali_group_unlock(core->group);

#if MALI_TIMELINE_PROFILING_ENABLED
#if 0   /* Bottom half TLP logging is currently not supported */
	_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
#endif
#endif
}
Exemple #20
0
static void mali_gp_bottom_half(void *data)
{
    struct mali_gp_core *core = (struct mali_gp_core *)data;
    u32 irq_readout;
    u32 irq_errors;

#if MALI_TIMELINE_PROFILING_ENABLED
#if 0
    _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_START| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE ,  _mali_osk_get_pid(), _mali_osk_get_tid()+11000, 0, 0, 0);
#endif
#endif

    mali_group_lock(core->group);

    if ( MALI_FALSE == mali_group_power_is_on(core->group) )
    {
        MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", core->hw_core.description));
        mali_group_unlock(core->group);
        return;
    }

    irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALIGP2_REG_VAL_IRQ_MASK_USED;
    MALI_DEBUG_PRINT(4, ("Mali GP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, core->hw_core.description));

    if (irq_readout & (MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST))
    {
        u32 core_status = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS);
        if (0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE))
        {
            mali_gp_post_process_job(core, MALI_FALSE);
            MALI_DEBUG_PRINT(4, ("Mali GP: Job completed, calling group handler\n"));
            mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_COMPLETED);
            return;
        }
    }

    irq_errors = irq_readout & ~(MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_HANG|MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM);
    if (0 != irq_errors)
    {
        mali_gp_post_process_job(core, MALI_FALSE);
        MALI_PRINT_ERROR(("Mali GP: Unknown interrupt 0x%08X from core %s, aborting job\n", irq_readout, core->hw_core.description));
        mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_FAILED);
        return;
    }
    else if (MALI_TRUE == core->core_timed_out)
    {
        if (core->timeout_job_id == mali_gp_job_get_id(core->running_job))
        {
            mali_gp_post_process_job(core, MALI_FALSE);
            MALI_DEBUG_PRINT(2, ("Mali GP: Job %d timed out\n", mali_gp_job_get_id(core->running_job)));
            mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_TIMED_OUT);
        }
        else
        {
            MALI_DEBUG_PRINT(2, ("Mali GP: Job %d timed out but current job is %d\n", core->timeout_job_id, mali_gp_job_get_id(core->running_job)));
            mali_group_unlock(core->group);
        }
        core->core_timed_out = MALI_FALSE;
        return;
    }
    else if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM)
    {
        mali_gp_post_process_job(core, MALI_TRUE);
        MALI_DEBUG_PRINT(3, ("Mali GP: PLBU needs more heap memory\n"));
        mali_group_bottom_half(core->group, GROUP_EVENT_GP_OOM);
        return;
    }
    else if (irq_readout & MALIGP2_REG_VAL_IRQ_HANG)
    {

        mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_HANG);
    }

    mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED);
    mali_group_unlock(core->group);

#if MALI_TIMELINE_PROFILING_ENABLED
#if 0
    _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_STOP| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE ,  _mali_osk_get_pid(), _mali_osk_get_tid()+11000, 0, 0, 0);
#endif
#endif
}
struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *uargs, u32 id)
{
	struct mali_pp_job *job;
	u32 perf_counter_flag;

	job = _mali_osk_calloc(1, sizeof(struct mali_pp_job));
	if (NULL != job)
	{
		if (0 != _mali_osk_copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_pp_start_job_s)))
		{
			goto fail;
		}

		if (job->uargs.num_cores > _MALI_PP_MAX_SUB_JOBS)
		{
			MALI_PRINT_ERROR(("Mali PP job: Too many sub jobs specified in job object\n"));
			goto fail;
		}

		if (!mali_pp_job_use_no_notification(job))
		{
			job->finished_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_FINISHED, sizeof(_mali_uk_pp_job_finished_s));
			if (NULL == job->finished_notification) goto fail;
		}

		perf_counter_flag = mali_pp_job_get_perf_counter_flag(job);

		/* case when no counters came from user space
		 * so pass the debugfs / DS-5 provided global ones to the job object */
		if (!((perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) ||
				(perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE)))
		{
			mali_pp_job_set_perf_counter_src0(job, mali_pp_job_get_pp_counter_src0());
			mali_pp_job_set_perf_counter_src1(job, mali_pp_job_get_pp_counter_src1());
		}

		_mali_osk_list_init(&job->list);
		job->session = session;
		_mali_osk_list_init(&job->session_list);
		job->id = id;

		job->sub_jobs_num = job->uargs.num_cores ? job->uargs.num_cores : 1;
		job->pid = _mali_osk_get_pid();
		job->tid = _mali_osk_get_tid();

		job->num_memory_cookies = job->uargs.num_memory_cookies;
		if (job->num_memory_cookies > 0)
		{
			u32 size;

			if (job->uargs.num_memory_cookies > session->descriptor_mapping->current_nr_mappings)
			{
				MALI_PRINT_ERROR(("Mali PP job: Too many memory cookies specified in job object\n"));
				goto fail;
			}

			size = sizeof(*job->uargs.memory_cookies) * job->num_memory_cookies;

			job->memory_cookies = _mali_osk_malloc(size);
			if (NULL == job->memory_cookies)
			{
				MALI_PRINT_ERROR(("Mali PP job: Failed to allocate %d bytes of memory cookies!\n", size));
				goto fail;
			}

			if (0 != _mali_osk_copy_from_user(job->memory_cookies, job->uargs.memory_cookies, size))
			{
				MALI_PRINT_ERROR(("Mali PP job: Failed to copy %d bytes of memory cookies from user!\n", size));
				goto fail;
			}

#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
			job->num_dma_bufs = job->num_memory_cookies;
			job->dma_bufs = _mali_osk_calloc(job->num_dma_bufs, sizeof(struct mali_dma_buf_attachment *));
			if (NULL == job->dma_bufs)
			{
				MALI_PRINT_ERROR(("Mali PP job: Failed to allocate dma_bufs array!\n"));
				goto fail;
			}
#endif
		}
		else
		{
			job->memory_cookies = NULL;
		}

		return job;
	}

fail:
	if (NULL != job)
	{
		mali_pp_job_delete(job);
	}

	return NULL;
}
Exemple #22
0
struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group)
{
	struct mali_gp_core* core = NULL;

	MALI_DEBUG_ASSERT(NULL == mali_global_gp_core);
	MALI_DEBUG_PRINT(2, ("Mali GP: Creating Mali GP core: %s\n", resource->description));

	core = _mali_osk_malloc(sizeof(struct mali_gp_core));
	if (NULL != core)
	{
		core->counter_src0_used = MALI_HW_CORE_NO_COUNTER;
		core->counter_src1_used = MALI_HW_CORE_NO_COUNTER;
		if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALIGP2_REGISTER_ADDRESS_SPACE_SIZE))
		{
			_mali_osk_errcode_t ret;

			ret = mali_gp_reset(core);

			if (_MALI_OSK_ERR_OK == ret)
			{
				ret = mali_group_add_gp_core(group, core);
				if (_MALI_OSK_ERR_OK == ret)
				{
					/* Setup IRQ handlers (which will do IRQ probing if needed) */
					core->irq = _mali_osk_irq_init(resource->irq,
					                               mali_group_upper_half_gp,
					                               group,
					                               mali_gp_irq_probe_trigger,
					                               mali_gp_irq_probe_ack,
					                               core,
					                               "mali_gp_irq_handlers");
					if (NULL != core->irq)
					{
						MALI_DEBUG_PRINT(4, ("Mali GP: set global gp core from 0x%08X to 0x%08X\n", mali_global_gp_core, core));
						mali_global_gp_core = core;

						return core;
					}
					else
					{
						MALI_PRINT_ERROR(("Mali GP: Failed to setup interrupt handlers for GP core %s\n", core->hw_core.description));
					}
					mali_group_remove_gp_core(group);
				}
				else
				{
					MALI_PRINT_ERROR(("Mali GP: Failed to add core %s to group\n", core->hw_core.description));
				}
			}
			mali_hw_core_delete(&core->hw_core);
		}

		_mali_osk_free(core);
	}
	else
	{
		MALI_PRINT_ERROR(("Failed to allocate memory for GP core\n"));
	}

	return NULL;
}
Exemple #23
0
static void pmm_event_process( void )
{
	_mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
	_mali_osk_notification_t *msg = NULL;
	_mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
	mali_pmm_message_t *event;
	u32 process_messages;

	MALI_DEBUG_ASSERT_POINTER(pmm);


	/* Max number of messages to process before exiting - as we shouldn't stay
	 * processing the messages for a long time
	 */
	process_messages = _mali_osk_atomic_read( &(pmm->messages_queued) );

	while( process_messages > 0 )
	{
		/* Check internal message queue first */
		err = _mali_osk_notification_queue_dequeue( pmm->iqueue, &msg );

		if( err != _MALI_OSK_ERR_OK )
		{
			if( pmm->status == MALI_PMM_STATUS_IDLE || pmm->status == MALI_PMM_STATUS_OS_WAITING || pmm->status == MALI_PMM_STATUS_DVFS_PAUSE) 	
			{
				if( pmm->waiting > 0 ) pmm->waiting--;

				/* We aren't busy changing state, so look at real events */
				err = _mali_osk_notification_queue_dequeue( pmm->queue, &msg );

				if( err != _MALI_OSK_ERR_OK )
				{
					pmm->no_events++;
					MALIPMM_DEBUG_PRINT( ("PMM: event_process - No message to process\n") );
					/* Nothing to do - so return */
					return;
				}
				else
				{					
					#if MALI_PMM_TRACE
						pmm->messages_received++;
					#endif		
				}
			}
			else
			{
				/* Waiting for an internal message */
				pmm->waiting++;
				MALIPMM_DEBUG_PRINT( ("PMM: event_process - Waiting for internal message, messages queued=%d\n", pmm->waiting) );
				return;
			}
		}
		else
		{
			#if MALI_PMM_TRACE
				pmm->imessages_received++;
			#endif		
		}

		MALI_DEBUG_ASSERT_POINTER( msg );
		/* Check the message type matches */
		MALI_DEBUG_ASSERT( msg->notification_type == MALI_PMM_NOTIFICATION_TYPE );

		event = msg->result_buffer;

		_mali_osk_atomic_dec( &(pmm->messages_queued) );
		process_messages--;

		#if MALI_PMM_TRACE
			/* Trace before we process the event in case we have an error */
			_mali_pmm_trace_event_message( event, MALI_TRUE );
		#endif
		err = pmm_policy_process( pmm, event );

		
		if( err != _MALI_OSK_ERR_OK )
		{
			MALI_PRINT_ERROR( ("PMM: Error(%d) in policy %d when processing event message with id: %d", 
					err, pmm->policy, event->id) );
		}
		
		/* Delete notification */
		_mali_osk_notification_delete ( msg );

		if( pmm->fatal_power_err )
		{
			/* Nothing good has happened - exit */
			return;
		}

			
		#if MALI_PMM_TRACE
			MALI_PRINT( ("PMM Trace: Event processed, msgs (sent/read) = %d/%d, int msgs (sent/read) = %d/%d, no events = %d, waiting = %d\n", 
					pmm->messages_sent, pmm->messages_received, pmm->imessages_sent, pmm->imessages_received, pmm->no_events, pmm->waiting) );
		#endif
	}

	if( pmm->status == MALI_PMM_STATUS_IDLE && pmm->waiting > 0 )
	{
		/* For events we ignored whilst we were busy, add a new
		 * scheduled time to look at them */
		_mali_osk_irq_schedulework( pmm->irq );
	}
}
struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session,
				       _mali_uk_pp_start_job_s __user *uargs, u32 id)
{
	struct mali_pp_job *job;
	u32 perf_counter_flag;

	job = _mali_osk_calloc(1, sizeof(struct mali_pp_job));
	if (NULL != job) {
		if (0 != _mali_osk_copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_pp_start_job_s))) {
			goto fail;
		}

		if (job->uargs.num_cores > _MALI_PP_MAX_SUB_JOBS) {
			MALI_PRINT_ERROR(("Mali PP job: Too many sub jobs specified in job object\n"));
			goto fail;
		}

		if (!mali_pp_job_use_no_notification(job)) {
			job->finished_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_FINISHED, sizeof(_mali_uk_pp_job_finished_s));
			if (NULL == job->finished_notification) goto fail;
		}

		perf_counter_flag = mali_pp_job_get_perf_counter_flag(job);

		/* case when no counters came from user space
		 * so pass the debugfs / DS-5 provided global ones to the job object */
		if (!((perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) ||
		      (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE))) {
			u32 sub_job_count = _mali_osk_atomic_read(&pp_counter_per_sub_job_count);

			/* These counters apply for all virtual jobs, and where no per sub job counter is specified */
			job->uargs.perf_counter_src0 = pp_counter_src0;
			job->uargs.perf_counter_src1 = pp_counter_src1;

			/* We only copy the per sub job array if it is enabled with at least one counter */
			if (0 < sub_job_count) {
				job->perf_counter_per_sub_job_count = sub_job_count;
				_mali_osk_memcpy(job->perf_counter_per_sub_job_src0, pp_counter_per_sub_job_src0, sizeof(pp_counter_per_sub_job_src0));
				_mali_osk_memcpy(job->perf_counter_per_sub_job_src1, pp_counter_per_sub_job_src1, sizeof(pp_counter_per_sub_job_src1));
			}
		}

		_mali_osk_list_init(&job->list);
		job->session = session;
		_mali_osk_list_init(&job->session_list);
		job->id = id;

		job->sub_jobs_num = job->uargs.num_cores ? job->uargs.num_cores : 1;
		job->pid = _mali_osk_get_pid();
		job->tid = _mali_osk_get_tid();

		job->num_memory_cookies = job->uargs.num_memory_cookies;
		if (job->num_memory_cookies > 0) {
			u32 size;
			u32 __user *memory_cookies = (u32 __user *)(uintptr_t)job->uargs.memory_cookies;

			if (job->uargs.num_memory_cookies > session->descriptor_mapping->current_nr_mappings) {
				MALI_PRINT_ERROR(("Mali PP job: Too many memory cookies specified in job object\n"));
				goto fail;
			}

			size = sizeof(*memory_cookies) * job->num_memory_cookies;

			job->memory_cookies = _mali_osk_malloc(size);
			if (NULL == job->memory_cookies) {
				MALI_PRINT_ERROR(("Mali PP job: Failed to allocate %d bytes of memory cookies!\n", size));
				goto fail;
			}

			if (0 != _mali_osk_copy_from_user(job->memory_cookies, memory_cookies, size)) {
				MALI_PRINT_ERROR(("Mali PP job: Failed to copy %d bytes of memory cookies from user!\n", size));
				goto fail;
			}

#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
			job->num_dma_bufs = job->num_memory_cookies;
			job->dma_bufs = _mali_osk_calloc(job->num_dma_bufs, sizeof(struct mali_dma_buf_attachment *));
			if (NULL == job->dma_bufs) {
				MALI_PRINT_ERROR(("Mali PP job: Failed to allocate dma_bufs array!\n"));
				goto fail;
			}
#endif
		}

		/* Prepare DMA command buffer to start job, if it is virtual. */
		if (mali_pp_job_is_virtual_group_job(job)) {
			struct mali_pp_core *core;
			_mali_osk_errcode_t err =  mali_dma_get_cmd_buf(&job->dma_cmd_buf);

			if (_MALI_OSK_ERR_OK != err) {
				MALI_PRINT_ERROR(("Mali PP job: Failed to allocate DMA command buffer\n"));
				goto fail;
			}

			core = mali_pp_scheduler_get_virtual_pp();
			MALI_DEBUG_ASSERT_POINTER(core);

			mali_pp_job_dma_cmd_prepare(core, job, 0, &job->dma_cmd_buf);
		}

		if (_MALI_OSK_ERR_OK != mali_pp_job_check(job)) {
			/* Not a valid job. */
			goto fail;
		}

		mali_timeline_tracker_init(&job->tracker, MALI_TIMELINE_TRACKER_PP, NULL, job);
		mali_timeline_fence_copy_uk_fence(&(job->tracker.fence), &(job->uargs.fence));

		return job;
	}

fail:
	if (NULL != job) {
		mali_pp_job_delete(job);
	}

	return NULL;
}
/* ------------- interrupt handling below ------------------ */
static _mali_osk_errcode_t mali_mmu_upper_half(void * data)
{
	struct mali_mmu_core *mmu = (struct mali_mmu_core *)data;
	u32 int_stat;

	MALI_DEBUG_ASSERT_POINTER(mmu);
	/* Check if it was our device which caused the interrupt (we could be sharing the IRQ line) */
	//MALI_DEBUG_PRINT(5, ("Mali MMU: %d..\n",mmu->id));

#ifdef CONFIG_ARCH_MESON6
	if ( MALI_FALSE == mali_group_power_is_on_2(mmu->group) )
	{
		if (mmu->id == 2)
			malifix_set_mmu_int_process_state(0, MMU_INT_NONE);
		else if (mmu->id == 3)
			malifix_set_mmu_int_process_state(1, MMU_INT_NONE);
		MALI_DEBUG_PRINT(4, ("Mali MMU: invalid interrupt. <<-- \n"));
		MALI_SUCCESS;
	}
#endif

	int_stat = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS);
	if (0 != int_stat)
	{
		mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, 0);
		mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);

		if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT)
		{
#ifdef CONFIG_ARCH_MESON6 
			MALI_DEBUG_PRINT(3, ("Mali MMU: core0 page fault reply. <<-- \n"));
			if (mmu->id == 2)
				malifix_set_mmu_int_process_state(0, MMU_INT_TOP);
			else if (mmu->id == 3)
				malifix_set_mmu_int_process_state(1, MMU_INT_TOP);
#endif
			_mali_osk_irq_schedulework(mmu->irq);
		}

		if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR)
		{
			/* clear interrupt flag */
			mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR);
			/* reenable it */
			mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK,
			                            mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK) | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
			MALI_PRINT_ERROR(("Mali MMU: Read bus error\n"));
#ifdef CONFIG_ARCH_MESON6
			if (mmu->id == 2) {
				if (malifix_get_mmu_int_process_state(0) == MMU_INT_TOP)
					malifix_set_mmu_int_process_state(0, MMU_INT_NONE);
			}
			else if (mmu->id == 3) {
				if (malifix_get_mmu_int_process_state(1) == MMU_INT_TOP)
					malifix_set_mmu_int_process_state(1, MMU_INT_NONE);
			}
#endif
		}
		return _MALI_OSK_ERR_OK;
	} 
#ifdef CONFIG_ARCH_MESON6
	else { 

		if (mmu->id == 2)
			malifix_set_mmu_int_process_state(0, MMU_INT_NONE);
		else if (mmu->id == 3)
			malifix_set_mmu_int_process_state(1, MMU_INT_NONE);
	}
#endif	

	return _MALI_OSK_ERR_FAULT;
}
Exemple #26
0
mali_bool pmm_invoke_power_up( _mali_pmm_internal_state_t *pmm )
{
	_mali_osk_errcode_t err;

	MALI_DEBUG_ASSERT_POINTER(pmm);

	/* Check that cores are pending power up during power up invoke */
	MALI_DEBUG_ASSERT( pmm->cores_pend_up != 0 );
	/* Check that cores are not pending power down during power up invoke */
	MALI_DEBUG_ASSERT( pmm->cores_pend_down == 0 );

	if( pmm_power_up_okay( pmm ) )
	{
		/* Power up has completed - sort out subsystem core status */
		
		int n;
		/* Use volatile to access, so that it is updated if any cores are unregistered */
		volatile mali_pmm_core_mask *ppendup = &(pmm->cores_pend_up);
#if MALI_PMM_TRACE
		mali_pmm_core_mask old_power = pmm->cores_powered;
#endif
		/* Move cores into idle queues */
		for( n = 0; n < SIZEOF_CORES_LIST; n++ )
		{
			if( (cores_list[n] & (*ppendup)) != 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 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);
				err = mali_core_signal_power_up( cores_list[n], MALI_FALSE );
				MALI_PMM_LOCK(pmm);

				if( err != _MALI_OSK_ERR_OK )
				{
					MALI_DEBUG_ASSERT( (err == _MALI_OSK_ERR_FAULT &&
										(*ppendup & cores_list[n]) == 0) );
					/* We only expect this to fail when we are shutting down 
					 * and the core has been unregistered
					 */
				}
			}
		}
		/* Finished power up - add cores to idle and powered list */
		pmm->cores_powered |= (*ppendup);
		pmm->cores_idle |= (*ppendup);
		/* Reset pending/acknowledge status */
		pmm->cores_pend_up = 0;
		pmm->cores_ack_up = 0;

#if MALI_PMM_TRACE
		_mali_pmm_trace_hardware_change( old_power, pmm->cores_powered );
#endif
		return MALI_TRUE;
	}
	else
	{
#if !MALI_PMM_NO_PMU
		/* Power up must now be done */
		err = mali_platform_powerup( pmm->cores_pend_up );
#else
		err = _MALI_OSK_ERR_OK;
#endif
		if( err != _MALI_OSK_ERR_OK )
		{
			MALI_PRINT_ERROR( ("PMM: Failed to get PMU to power up cores - (0x%x) %s", 
					pmm->cores_pend_up, pmm_trace_get_core_name(pmm->cores_pend_up)) );
			pmm->fatal_power_err = MALI_TRUE;
		}
		else
		{
			/* TBD - Update core status immediately rather than use event message */
			_mali_uk_pmm_message_s event = {
				NULL,
				MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK,
				0 };
			/* All the cores that were pending power up, have now completed power up */
			event.data = pmm->cores_pend_up;
			_mali_ukk_pmm_event_message( &event );
			MALIPMM_DEBUG_PRINT( ("PMM: Sending ACK to power up") );
		}
	}

	/* Always return false, as we need an interrupt to acknowledge
	 * when power up is complete
	 */
	return MALI_FALSE;
}
int mali_driver_init(void)
{
	int ret = 0;

	MALI_DEBUG_PRINT(2, ("\n"));
	MALI_DEBUG_PRINT(2, ("Inserting Mali v%d device driver. \n",_MALI_API_VERSION));
	MALI_DEBUG_PRINT(2, ("Compiled: %s, time: %s.\n", __DATE__, __TIME__));
	MALI_DEBUG_PRINT(2, ("Driver revision: %s\n", SVN_REV_STRING));

	ret = _mali_dev_platform_register();
	if (0 != ret) goto platform_register_failed;
	ret = map_errcode(initialize_kernel_device());
	if (0 != ret) goto initialize_kernel_device_failed;

	ret = map_errcode(mali_platform_init());
	if (0 != ret) goto platform_init_failed;

	mali_osk_low_level_mem_init();

	ret = map_errcode(mali_initialize_subsystems());
	if (0 != ret) goto initialize_subsystems_failed;

#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
        ret = _mali_internal_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE);
        if (0 != ret)
        {
                /* No biggie if we wheren't able to initialize the profiling */
                MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n"));
        }
#endif

	ret = initialize_sysfs();
	if (0 != ret) goto initialize_sysfs_failed;

#if MALI_LICENSE_IS_GPL && defined(CONFIG_MALI_UMP_R3P1_DEBUG_MEM_USAGE_FOR_OOM)
	ret = register_oom_notifier(&mali_oom_notifier);
	if (0 != ret) goto initialize_oom_nofifier_failed;
#endif

	MALI_PRINT(("Mali device driver loaded\n"));

	return 0; /* Success */

	/* Error handling */
#if MALI_LICENSE_IS_GPL && defined(CONFIG_MALI_UMP_R3P1_DEBUG_MEM_USAGE_FOR_OOM)
initialize_oom_nofifier_failed:
	/* No need to terminate sysfs, this will be done automatically
	 * along with device termination */
#endif
initialize_sysfs_failed:
#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
        _mali_internal_profiling_term();
#endif
	mali_terminate_subsystems();
initialize_subsystems_failed:
	mali_osk_low_level_mem_term();
	mali_platform_deinit();
platform_init_failed:
	terminate_kernel_device();
initialize_kernel_device_failed:
	_mali_dev_platform_unregister();
platform_register_failed:
	return ret;
}
Exemple #28
0
void pmm_fatal_reset( _mali_pmm_internal_state_t *pmm )
{
	_mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
	_mali_osk_notification_t *msg = NULL;
	mali_pmm_status status;
	MALI_DEBUG_ASSERT_POINTER(pmm);
	MALIPMM_DEBUG_PRINT( ("PMM: Fatal Reset called") ); 

	MALI_DEBUG_ASSERT( pmm->status != MALI_PMM_STATUS_OFF );

	/* Reset the common status */
	pmm->waiting = 0;
	pmm->missed = 0;
	pmm->fatal_power_err = MALI_FALSE;
	pmm->no_events = 0;
	pmm->check_policy = MALI_FALSE;
	pmm->cores_pend_down = 0;
	pmm->cores_pend_up = 0;
	pmm->cores_ack_down = 0;
	pmm->cores_ack_up = 0;
	pmm->is_dvfs_active = 0; 
#if MALI_PMM_TRACE
	pmm->messages_sent = 0;
	pmm->messages_received = 0;
	pmm->imessages_sent = 0;
	pmm->imessages_received = 0;
	MALI_PRINT( ("PMM Trace: *** Fatal reset occurred ***") );
#endif

	/* Set that we are unavailable whilst resetting */
	pmm->state = MALI_PMM_STATE_UNAVAILABLE;
	status = pmm->status;
	pmm->status = MALI_PMM_STATUS_OFF;

	/* We want all cores powered */
	pmm->cores_powered = pmm->cores_registered;
	/* The cores may not be idle, but this state will be rectified later */
	pmm->cores_idle = pmm->cores_registered;
	
	/* So power on any cores that are registered */
	if( pmm->cores_registered != 0 )
	{
		int n;
		volatile mali_pmm_core_mask *pregistered = &(pmm->cores_registered);
#if !MALI_PMM_NO_PMU
		err = mali_platform_powerup( pmm->cores_registered );
#endif
		if( err != _MALI_OSK_ERR_OK )
		{
			/* This is very bad as we can't even be certain the cores are now 
			 * powered up
			 */
			MALI_PRINT_ERROR( ("PMM: Failed to perform PMM reset!\n") );
			/* TBD driver exit? */
		}

		for( n = SIZEOF_CORES_LIST-1; n >= 0; n-- )
		{
			if( (cores_list[n] & (*pregistered)) != 0 )
			{
				MALI_PMM_UNLOCK(pmm);
				/* Core is now active - so try putting it in the idle queue */
				err = mali_core_signal_power_up( cores_list[n], MALI_FALSE );
				MALI_PMM_LOCK(pmm);
				/* We either succeeded, or we were not off anyway, or we have
				 * just be deregistered 
				 */
				MALI_DEBUG_ASSERT( (err == _MALI_OSK_ERR_OK) ||
									(err == _MALI_OSK_ERR_BUSY) ||
									(err == _MALI_OSK_ERR_FAULT && 
									(*pregistered & cores_list[n]) == 0) );
			}
		}
	}

	/* Unblock any pending OS event */
	if( status == MALI_PMM_STATUS_OS_POWER_UP )
	{
		/* Get the OS data and respond to the power up */
		_mali_osk_pmm_power_up_done( pmm_retrieve_os_event_data( pmm ) );
	}
	if( status == MALI_PMM_STATUS_OS_POWER_DOWN )
	{
		/* Get the OS data and respond to the power down 
		 * NOTE: We are not powered down at this point due to power problems,
		 * so we are lying to the system, but something bad has already 
		 * happened and we are trying unstick things
		 * TBD - Add busy loop to power down cores?
		 */
		_mali_osk_pmm_power_down_done( pmm_retrieve_os_event_data( pmm ) );
	}
		
	/* Purge the event queues */
	do
	{
		if( _mali_osk_notification_queue_dequeue( pmm->iqueue, &msg ) == _MALI_OSK_ERR_OK )
		{
			_mali_osk_notification_delete ( msg );
			break;
		}
	} while (MALI_TRUE);

	do
	{
		if( _mali_osk_notification_queue_dequeue( pmm->queue, &msg ) == _MALI_OSK_ERR_OK )
		{
			_mali_osk_notification_delete ( msg );
			break;
		}
	} while (MALI_TRUE);

	/* Return status/state to normal */
	pmm->status = MALI_PMM_STATUS_IDLE;
	pmm_update_system_state(pmm);
}
struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual, u32 bcast_id)
{
	struct mali_pp_core *core = NULL;

	MALI_DEBUG_PRINT(2, ("Mali PP: Creating Mali PP core: %s\n", resource->description));
	MALI_DEBUG_PRINT(2, ("Mali PP: Base address of PP core: 0x%x\n", resource->base));

	if (mali_global_num_pp_cores >= MALI_MAX_NUMBER_OF_PP_CORES) {
		MALI_PRINT_ERROR(("Mali PP: Too many PP core objects created\n"));
		return NULL;
	}

	core = _mali_osk_calloc(1, sizeof(struct mali_pp_core));
	if (NULL != core) {
		core->core_id = mali_global_num_pp_cores;
		core->bcast_id = bcast_id;

		if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI200_REG_SIZEOF_REGISTER_BANK)) {
			_mali_osk_errcode_t ret;

			if (!is_virtual) {
				ret = mali_pp_reset(core);
			} else {
				ret = _MALI_OSK_ERR_OK;
			}

			if (_MALI_OSK_ERR_OK == ret) {
				ret = mali_group_add_pp_core(group, core);
				if (_MALI_OSK_ERR_OK == ret) {
					/* Setup IRQ handlers (which will do IRQ probing if needed) */
					MALI_DEBUG_ASSERT(!is_virtual || -1 != resource->irq);

					core->irq = _mali_osk_irq_init(resource->irq,
								       mali_group_upper_half_pp,
								       group,
								       mali_pp_irq_probe_trigger,
								       mali_pp_irq_probe_ack,
								       core,
								       resource->description);
					if (NULL != core->irq) {
						mali_global_pp_cores[mali_global_num_pp_cores] = core;
						mali_global_num_pp_cores++;

						return core;
					} else {
						MALI_PRINT_ERROR(("Mali PP: Failed to setup interrupt handlers for PP core %s\n", core->hw_core.description));
					}
					mali_group_remove_pp_core(group);
				} else {
					MALI_PRINT_ERROR(("Mali PP: Failed to add core %s to group\n", core->hw_core.description));
				}
			}
			mali_hw_core_delete(&core->hw_core);
		}

		_mali_osk_free(core);
	} else {
		MALI_PRINT_ERROR(("Mali PP: Failed to allocate memory for PP core\n"));
	}

	return NULL;
}
Exemple #30
0
struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *uargs, u32 id)
{
	struct mali_pp_job *job;
	u32 perf_counter_flag;

	job = _mali_osk_malloc(sizeof(struct mali_pp_job));
	if (NULL != job)
	{
		u32 i;

		if (0 != _mali_osk_copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_pp_start_job_s)))
		{
			_mali_osk_free(job);
			return NULL;
		}

		if (job->uargs.num_cores > _MALI_PP_MAX_SUB_JOBS)
		{
			MALI_PRINT_ERROR(("Mali PP job: Too many sub jobs specified in job object\n"));
			_mali_osk_free(job);
			return NULL;
		}

		if (!mali_pp_job_use_no_notification(job))
		{
			job->finished_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_FINISHED, sizeof(_mali_uk_pp_job_finished_s));
			if (NULL == job->finished_notification)
			{
				_mali_osk_free(job);
				return NULL;
			}
		}
		else
		{
			job->finished_notification = NULL;
		}

		perf_counter_flag = mali_pp_job_get_perf_counter_flag(job);

		/* case when no counters came from user space
		 * so pass the debugfs / DS-5 provided global ones to the job object */
		if (!((perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) ||
				(perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE)))
		{
			mali_pp_job_set_perf_counter_src0(job, mali_pp_job_get_pp_counter_src0());
			mali_pp_job_set_perf_counter_src1(job, mali_pp_job_get_pp_counter_src1());
		}

		_mali_osk_list_init(&job->list);
		job->session = session;
		_mali_osk_list_init(&job->session_list);
		job->id = id;

		for (i = 0; i < job->uargs.num_cores; i++)
		{
			job->perf_counter_value0[i] = 0;
			job->perf_counter_value1[i] = 0;
		}
		job->sub_jobs_num = job->uargs.num_cores ? job->uargs.num_cores : 1;
		job->sub_jobs_started = 0;
		job->sub_jobs_completed = 0;
		job->sub_job_errors = 0;
		job->pid = _mali_osk_get_pid();
		job->tid = _mali_osk_get_tid();
#if defined(MTK_CONFIG_SYNC)
		job->sync_point = NULL;
		job->pre_fence = NULL;
		job->sync_work = NULL;
#endif

		return job;
	}

	return NULL;
}