static int trans_mmap(struct file *f, struct vm_area_struct *vma) { struct trans_channel *c = f->private_data; struct page *pg = NULL; unsigned long addr, sz, pages; int i; BUG_ON(!c); printl("trans_mmap, sz %d\n", vma->vm_end - vma->vm_start); sz = vma->vm_end - vma->vm_start; pages = sz/PAGE_SIZE; if (sz > TRANS_MAX_MAPPING) return -EINVAL; for (addr = vma->vm_start, i = 0 ; addr < vma->vm_end ; addr += PAGE_SIZE, i++) { pg = virt_to_page(&c->mem[PAGE_SIZE*i]); BUG_ON(!pg); if (vm_insert_page(vma, addr, pg)) { zap_vma_ptes(vma, vma->vm_start, addr - vma->vm_start); goto err; } //BUG_ON(pg != follow_page(vma, addr, 0)); } vma->vm_flags |= (VM_RESERVED | VM_INSERTPAGE); vma->vm_ops = &trans_vmops; BUG_ON(vma->vm_private_data); vma->vm_private_data = c; c->size = sz; return 0; err: return -EAGAIN; }
static _mali_osk_errcode_t mali_mem_resize(struct mali_session_data *session, mali_mem_backend *mem_backend, u32 physical_size) { _mali_osk_errcode_t ret = _MALI_OSK_ERR_FAULT; int retval = 0; mali_mem_allocation *mali_allocation = NULL; mali_mem_os_mem tmp_os_mem; s32 change_page_count; MALI_DEBUG_ASSERT_POINTER(session); MALI_DEBUG_ASSERT_POINTER(mem_backend); MALI_DEBUG_PRINT(4, (" mali_mem_resize_memory called! \n")); MALI_DEBUG_ASSERT(0 == physical_size % MALI_MMU_PAGE_SIZE); mali_allocation = mem_backend->mali_allocation; MALI_DEBUG_ASSERT_POINTER(mali_allocation); MALI_DEBUG_ASSERT(MALI_MEM_FLAG_CAN_RESIZE & mali_allocation->flags); MALI_DEBUG_ASSERT(MALI_MEM_OS == mali_allocation->type); mutex_lock(&mem_backend->mutex); /* Do resize*/ if (physical_size > mem_backend->size) { u32 add_size = physical_size - mem_backend->size; MALI_DEBUG_ASSERT(0 == add_size % MALI_MMU_PAGE_SIZE); /* Allocate new pages from os mem */ retval = mali_mem_os_alloc_pages(&tmp_os_mem, add_size); if (retval) { if (-ENOMEM == retval) { ret = _MALI_OSK_ERR_NOMEM; } else { ret = _MALI_OSK_ERR_FAULT; } MALI_DEBUG_PRINT(2, ("_mali_ukk_mem_resize: memory allocation failed !\n")); goto failed_alloc_memory; } MALI_DEBUG_ASSERT(tmp_os_mem.count == add_size / MALI_MMU_PAGE_SIZE); /* Resize the memory of the backend */ ret = mali_mem_os_resize_pages(&tmp_os_mem, &mem_backend->os_mem, 0, tmp_os_mem.count); if (ret) { MALI_DEBUG_PRINT(2, ("_mali_ukk_mem_resize: memory resizing failed !\n")); goto failed_resize_pages; } /*Resize cpu mapping */ if (NULL != mali_allocation->cpu_mapping.vma) { ret = mali_mem_os_resize_cpu_map_locked(mem_backend, mali_allocation->cpu_mapping.vma, mali_allocation->cpu_mapping.vma->vm_start + mem_backend->size, add_size); if (unlikely(ret != _MALI_OSK_ERR_OK)) { MALI_DEBUG_PRINT(2, ("_mali_ukk_mem_resize: cpu mapping failed !\n")); goto failed_cpu_map; } } /* Resize mali mapping */ _mali_osk_mutex_wait(session->memory_lock); ret = mali_mem_mali_map_resize(mali_allocation, physical_size); if (ret) { MALI_DEBUG_PRINT(1, ("_mali_ukk_mem_resize: mali map resize fail !\n")); goto failed_gpu_map; } ret = mali_mem_os_mali_map(&mem_backend->os_mem, session, mali_allocation->mali_vma_node.vm_node.start, mali_allocation->psize / MALI_MMU_PAGE_SIZE, add_size / MALI_MMU_PAGE_SIZE, mali_allocation->mali_mapping.properties); if (ret) { MALI_DEBUG_PRINT(2, ("_mali_ukk_mem_resize: mali mapping failed !\n")); goto failed_gpu_map; } _mali_osk_mutex_signal(session->memory_lock); } else { u32 dec_size, page_count; u32 vaddr = 0; INIT_LIST_HEAD(&tmp_os_mem.pages); tmp_os_mem.count = 0; dec_size = mem_backend->size - physical_size; MALI_DEBUG_ASSERT(0 == dec_size % MALI_MMU_PAGE_SIZE); page_count = dec_size / MALI_MMU_PAGE_SIZE; vaddr = mali_allocation->mali_vma_node.vm_node.start + physical_size; /* Resize the memory of the backend */ ret = mali_mem_os_resize_pages(&mem_backend->os_mem, &tmp_os_mem, physical_size / MALI_MMU_PAGE_SIZE, page_count); if (ret) { MALI_DEBUG_PRINT(4, ("_mali_ukk_mem_resize: mali map resize failed!\n")); goto failed_resize_pages; } /* Resize mali map */ _mali_osk_mutex_wait(session->memory_lock); mali_mem_mali_map_free(session, dec_size, vaddr, mali_allocation->flags); _mali_osk_mutex_signal(session->memory_lock); /* Zap cpu mapping */ if (0 != mali_allocation->cpu_mapping.addr) { MALI_DEBUG_ASSERT(NULL != mali_allocation->cpu_mapping.vma); zap_vma_ptes(mali_allocation->cpu_mapping.vma, mali_allocation->cpu_mapping.vma->vm_start + physical_size, dec_size); } /* Free those extra pages */ mali_mem_os_free(&tmp_os_mem.pages, tmp_os_mem.count, MALI_FALSE); } /* Resize memory allocation and memory backend */ change_page_count = (s32)(physical_size - mem_backend->size) / MALI_MMU_PAGE_SIZE; mali_allocation->psize = physical_size; mem_backend->size = physical_size; mutex_unlock(&mem_backend->mutex); if (change_page_count > 0) { atomic_add(change_page_count, &session->mali_mem_allocated_pages); if (atomic_read(&session->mali_mem_allocated_pages) * MALI_MMU_PAGE_SIZE > session->max_mali_mem_allocated_size) { session->max_mali_mem_allocated_size = atomic_read(&session->mali_mem_allocated_pages) * MALI_MMU_PAGE_SIZE; } } else { atomic_sub((s32)(-change_page_count), &session->mali_mem_allocated_pages); } return _MALI_OSK_ERR_OK; failed_gpu_map: _mali_osk_mutex_signal(session->memory_lock); failed_cpu_map: if (physical_size > mem_backend->size) { mali_mem_os_resize_pages(&mem_backend->os_mem, &tmp_os_mem, mem_backend->size / MALI_MMU_PAGE_SIZE, (physical_size - mem_backend->size) / MALI_MMU_PAGE_SIZE); } else { mali_mem_os_resize_pages(&tmp_os_mem, &mem_backend->os_mem, 0, tmp_os_mem.count); } failed_resize_pages: if (0 != tmp_os_mem.count) mali_mem_os_free(&tmp_os_mem.pages, tmp_os_mem.count, MALI_FALSE); failed_alloc_memory: mutex_unlock(&mem_backend->mutex); return ret; }