Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fa5e623a authored by Harshdeep Dhatt's avatar Harshdeep Dhatt
Browse files

msm: kgsl: Add array of page pointers to memdesc



This is done to improve the kgsl vmfault routine. Currently,
it traverses the sglist to find the faulted page, which takes
linear time. By having an array of all the page pointers,
this operation will be completed in constant time.
Also, allocate sgt only for mapping this memory to the GPU.

Since this optimization is not needed for secure/global or
imported memory, we will not keep this array but keep
the sgt instead.

CRs-Fixed: 1006012
Change-Id: I221fce9082da0bdd59842455221b896a33a6ce42
Signed-off-by: default avatarHarshdeep Dhatt <hdhatt@codeaurora.org>
parent 0130e341
Loading
Loading
Loading
Loading
+3 −8
Original line number Diff line number Diff line
@@ -3643,21 +3643,16 @@ static int kgsl_mmap(struct file *file, struct vm_area_struct *vma)

	if (cache == KGSL_CACHEMODE_WRITEBACK
		|| cache == KGSL_CACHEMODE_WRITETHROUGH) {
		struct scatterlist *s;
		int i;
		unsigned long addr = vma->vm_start;
		struct kgsl_memdesc *m = &entry->memdesc;

		for_each_sg(entry->memdesc.sgt->sgl, s,
				entry->memdesc.sgt->nents, i) {
			int j;
			for (j = 0; j < (s->length >> PAGE_SHIFT); j++) {
				struct page *page = sg_page(s);
				page = nth_page(page, j);
		for (i = 0; i < m->page_count; i++) {
				struct page *page = m->pages[i];
				vm_insert_page(vma, addr, page);
				addr += PAGE_SIZE;
		}
	}
	}

	vma->vm_file = file;

+5 −2
Original line number Diff line number Diff line
@@ -153,8 +153,9 @@ struct kgsl_memdesc_ops {
 * @ops: Function hooks for the memdesc memory type
 * @flags: Flags set from userspace
 * @dev: Pointer to the struct device that owns this memory
 * @memmap: bitmap of pages for mmapsize
 * @memmap_len: Number of bits for memmap
 * @attrs: dma attributes for this memory
 * @pages: An array of pointers to allocated pages
 * @page_count: Total number of pages allocated
 */
struct kgsl_memdesc {
	struct kgsl_pagetable *pagetable;
@@ -171,6 +172,8 @@ struct kgsl_memdesc {
	uint64_t flags;
	struct device *dev;
	struct dma_attrs attrs;
	struct page **pages;
	unsigned int page_count;
};

/*
+1 −1
Original line number Diff line number Diff line
@@ -150,7 +150,7 @@ static int print_mem_entry(int id, void *ptr, void *data)
			(unsigned long *) m->useraddr,
			m->size, entry->id, flags,
			memtype_str(kgsl_memdesc_usermem_type(m)),
			usage, m->sgt->nents, m->mapsize);
			usage, (m->sgt ? m->sgt->nents : 0), m->mapsize);

	if (entry->metadata[0] != 0)
		seq_printf(s, " %s", entry->metadata);
+44 −6
Original line number Diff line number Diff line
@@ -1582,16 +1582,34 @@ kgsl_iommu_map(struct kgsl_pagetable *pt,
	uint64_t addr = memdesc->gpuaddr;
	uint64_t size = memdesc->size;
	unsigned int flags = _get_protection_flags(memdesc);
	struct sg_table *sgt = NULL;

	ret = _iommu_map_sg_sync_pc(pt, addr, memdesc, memdesc->sgt->sgl,
			memdesc->sgt->nents, flags);
	/*
	 * For paged memory allocated through kgsl, memdesc->pages is not NULL.
	 * Allocate sgt here just for its map operation. Contiguous memory
	 * already has its sgt, so no need to allocate it here.
	 */
	if (memdesc->pages != NULL)
		sgt = kgsl_alloc_sgt_from_pages(memdesc);
	else
		sgt = memdesc->sgt;

	if (IS_ERR(sgt))
		return PTR_ERR(sgt);

	ret = _iommu_map_sg_sync_pc(pt, addr, memdesc, sgt->sgl,
				sgt->nents, flags);
	if (ret)
		return ret;
		goto done;

	ret = _iommu_map_guard_page(pt, memdesc, addr + size, flags);
	if (ret)
		_iommu_unmap_sync_pc(pt, memdesc, addr, size);

done:
	if (memdesc->pages != NULL)
		kgsl_free_sgt(sgt);

	return ret;
}

@@ -1602,6 +1620,8 @@ static int kgsl_iommu_map_offset(struct kgsl_pagetable *pt,
{
	int pg_sz;
	unsigned int protflags = _get_protection_flags(memdesc);
	int ret;
	struct sg_table *sgt = NULL;

	pg_sz = (1 << kgsl_memdesc_get_align(memdesc));
	if (!IS_ALIGNED(virtaddr | virtoffset | physoffset | size, pg_sz))
@@ -1610,9 +1630,27 @@ static int kgsl_iommu_map_offset(struct kgsl_pagetable *pt,
	if (size == 0)
		return -EINVAL;

	return _iommu_map_sg_offset_sync_pc(pt, virtaddr + virtoffset,
			memdesc, memdesc->sgt->sgl, memdesc->sgt->nents,
	/*
	 * For paged memory allocated through kgsl, memdesc->pages is not NULL.
	 * Allocate sgt here just for its map operation. Contiguous memory
	 * already has its sgt, so no need to allocate it here.
	 */
	if (memdesc->pages != NULL)
		sgt = kgsl_alloc_sgt_from_pages(memdesc);
	else
		sgt = memdesc->sgt;

	if (IS_ERR(sgt))
		return PTR_ERR(sgt);

	ret = _iommu_map_sg_offset_sync_pc(pt, virtaddr + virtoffset,
		memdesc, sgt->sgl, sgt->nents,
		physoffset, size, protflags);

	if (memdesc->pages != NULL)
		kgsl_free_sgt(sgt);

	return ret;
}

/* This function must be called with context bank attached */
+25 −0
Original line number Diff line number Diff line
@@ -263,6 +263,31 @@ void kgsl_pool_free_sgt(struct sg_table *sgt)
	}
}

/**
 * kgsl_pool_free_pages() - Free pages in the pages array
 * @pages: pointer of the pages array
 *
 * Free the pages by collapsing any physical adjacent pages.
 * Pages are added back to the pool, if pool has sufficient space
 * otherwise they are given back to system.
 */
void kgsl_pool_free_pages(struct page **pages, unsigned int pcount)
{
	int i;

	if (pages == NULL || pcount == 0)
		return;

	for (i = 0; i < pcount;) {
		/*
		 * Free each page or compound page group individually.
		 */
		struct page *p = pages[i];

		i += 1 << compound_order(p);
		kgsl_pool_free_page(p);
	}
}
static int kgsl_pool_idx_lookup(unsigned int order)
{
	int i;
Loading