/* ib_umem_release - release memory pinned with ib_umem_get @umem: umem struct to release  */
void ib_umem_release(struct ib_umem *umem)
/* ib_umem_release - release memory pinned with ib_umem_get @umem: umem struct to release  */
void ib_umem_release(struct ib_umem *umem)
{
	struct ib_ucontext *context = umem->context;
	struct mm_struct *mm;
	unsigned long diff;
	__ib_umem_release(umem->context->device, umem, 1);
	mm = get_task_mm(current);
	if (!mm) {
		kfree(umem);
		return;
	}
	diff = PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT;
	if (context->closing) {
		if (!down_write_trylock(&mm->mmap_sem)) {
			INIT_WORK(&umem->work, ib_umem_account);
			umem->mm   = mm;
			umem->diff = diff;
			schedule_work(&umem->work);
			return;
		}
	} else
		down_write(&mm->mmap_sem);
	current->mm->locked_vm -= diff;
	up_write(&mm->mmap_sem);
	mmput(mm);
	kfree(umem);
}