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; }
_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; }
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; }
_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 ); }
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; }
_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; }
_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 */ }
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; }
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 }
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; }
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; }
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; }
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; }
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; }
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; }