_mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, u32 mali_address, u32 size) { const int first_pde = MALI_MMU_PDE_ENTRY(mali_address); const int last_pde = MALI_MMU_PDE_ENTRY(mali_address + size - 1); u32 left = size; int i; #ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 mali_bool pd_changed = MALI_FALSE; u32 pages_to_invalidate[3]; /* hard-coded to 3: max two pages from the PT level plus max one page from PD level */ u32 num_pages_inv = 0; #endif /* For all page directory entries in range. */ for (i = first_pde; i <= last_pde; i++) { u32 size_in_pde, offset; MALI_DEBUG_ASSERT_POINTER(pagedir->page_entries_mapped[i]); MALI_DEBUG_ASSERT(0 != pagedir->page_entries_usage_count[i]); /* Offset into page table, 0 if mali_address is 4MiB aligned */ offset = (mali_address & (MALI_MMU_VIRTUAL_PAGE_SIZE - 1)); if (left < MALI_MMU_VIRTUAL_PAGE_SIZE - offset) { size_in_pde = left; } else { size_in_pde = MALI_MMU_VIRTUAL_PAGE_SIZE - offset; } pagedir->page_entries_usage_count[i]--; /* If entire page table is unused, free it */ if (0 == pagedir->page_entries_usage_count[i]) { u32 page_address; MALI_DEBUG_PRINT(4, ("Releasing page table as this is the last reference\n")); /* last reference removed, no need to zero out each PTE */ page_address = MALI_MMU_ENTRY_ADDRESS(_mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32))); pagedir->page_entries_mapped[i] = NULL; _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i*sizeof(u32), 0); mali_mmu_release_table_page(page_address); #ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 pd_changed = MALI_TRUE; #endif } else { #ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 pages_to_invalidate[num_pages_inv] = mali_page_directory_get_phys_address(pagedir, i); num_pages_inv++; MALI_DEBUG_ASSERT(num_pages_inv<3); #endif /* If part of the page table is still in use, zero the relevant PTEs */ mali_mmu_zero_pte(pagedir->page_entries_mapped[i], mali_address, size_in_pde); } left -= size_in_pde; mali_address += size_in_pde; } _mali_osk_write_mem_barrier(); #ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2 /* L2 pages invalidation */ if (MALI_TRUE == pd_changed) { pages_to_invalidate[num_pages_inv] = pagedir->page_directory; num_pages_inv++; MALI_DEBUG_ASSERT(num_pages_inv<3); } if (_MALI_PRODUCT_ID_MALI200 != mali_kernel_core_get_product_id()) { mali_cluster_invalidate_pages(pages_to_invalidate, num_pages_inv); } #endif MALI_SUCCESS; }
void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job, mali_bool restart_virtual) { u32 num_frame_registers; u32 relative_address; u32 start_index; u32 nr_of_regs; u32 *frame_registers = mali_pp_job_get_frame_registers(job); u32 *wb0_registers = mali_pp_job_get_wb0_registers(job); u32 *wb1_registers = mali_pp_job_get_wb1_registers(job); u32 *wb2_registers = mali_pp_job_get_wb2_registers(job); core->counter_src0_used = mali_pp_job_get_perf_counter_src0(job); core->counter_src1_used = mali_pp_job_get_perf_counter_src1(job); MALI_DEBUG_ASSERT_POINTER(core); /* Write frame registers */ num_frame_registers = (_MALI_PRODUCT_ID_MALI200 == mali_kernel_core_get_product_id()) ? MALI_PP_MALI200_NUM_FRAME_REGISTERS : MALI_PP_MALI400_NUM_FRAME_REGISTERS; /* * There are two frame registers which are different for each sub job: * 1. The Renderer List Address Register (MALI200_REG_ADDR_FRAME) * 2. The FS Stack Address Register (MALI200_REG_ADDR_STACK) */ mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_FRAME / sizeof(u32)]); /* For virtual jobs, the stack address shouldn't be broadcast but written individually */ if (!mali_pp_job_is_virtual(job) || restart_virtual) { mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_STACK / sizeof(u32)]); } /* Write registers between MALI200_REG_ADDR_FRAME and MALI200_REG_ADDR_STACK */ relative_address = MALI200_REG_ADDR_RSW; start_index = MALI200_REG_ADDR_RSW / sizeof(u32); nr_of_regs = (MALI200_REG_ADDR_STACK - MALI200_REG_ADDR_RSW) / sizeof(u32); mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, relative_address, &frame_registers[start_index], nr_of_regs, &mali_frame_registers_reset_values[start_index]); /* MALI200_REG_ADDR_STACK_SIZE */ relative_address = MALI200_REG_ADDR_STACK_SIZE; start_index = MALI200_REG_ADDR_STACK_SIZE / sizeof(u32); mali_hw_core_register_write_relaxed_conditional(&core->hw_core, relative_address, frame_registers[start_index], mali_frame_registers_reset_values[start_index]); /* Skip 2 reserved registers */ /* Write remaining registers */ relative_address = MALI200_REG_ADDR_ORIGIN_OFFSET_X; start_index = MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32); nr_of_regs = num_frame_registers - MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32); mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, relative_address, &frame_registers[start_index], nr_of_regs, &mali_frame_registers_reset_values[start_index]); /* Write WBx registers */ if (wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */ { mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values); } if (wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */ { mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values); } if (wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */ { mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values); } if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) { mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); } if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) { mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); } MALI_DEBUG_PRINT(3, ("Mali PP: Starting job 0x%08X part %u/%u on PP core %s\n", job, sub_job + 1, mali_pp_job_get_sub_job_count(job), core->hw_core.description)); /* Adding barrier to make sure all rester writes are finished */ _mali_osk_write_mem_barrier(); /* This is the command that starts the core. */ mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_START_RENDERING); /* Adding barrier to make sure previous rester writes is finished */ _mali_osk_write_mem_barrier(); }