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

Commit 019bcfdf authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Fix pagetable member of struct kgsl_memdesc"

parents 5bd1cfab f4c9ffd6
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -250,7 +250,7 @@ static int a5xx_critical_packet_construct(struct adreno_device *adreno_dev)
		return ret;

	ret = kgsl_allocate_user(&adreno_dev->dev, &crit_pkts_refbuf0,
					NULL, PAGE_SIZE, KGSL_MEMFLAGS_SECURE);
		PAGE_SIZE, KGSL_MEMFLAGS_SECURE);
	if (ret)
		return ret;

+7 −26
Original line number Diff line number Diff line
/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -370,24 +370,6 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process,
	return kgsl_mmu_get_gpuaddr(pagetable, &entry->memdesc);
}

/**
 * kgsl_mem_entry_untrack_gpuaddr() - Untrack memory that is previously tracked
 * process - Pointer to process private to which memory belongs
 * entry - Memory entry to untrack
 *
 * Function just does the opposite of kgsl_mem_entry_track_gpuaddr. Needs to be
 * called with processes spin lock held
 */
static void
kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process,
				struct kgsl_mem_entry *entry)
{
	struct kgsl_pagetable *pagetable = entry->memdesc.pagetable;

	if (entry->memdesc.gpuaddr)
		kgsl_mmu_put_gpuaddr(pagetable, &entry->memdesc);
}

/* Commit the entry to the process so it can be accessed by other operations */
static void kgsl_mem_entry_commit_process(struct kgsl_mem_entry *entry)
{
@@ -436,7 +418,7 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry,

	if (id < 0) {
		ret = id;
		kgsl_mem_entry_untrack_gpuaddr(process, entry);
		kgsl_mmu_put_gpuaddr(&entry->memdesc);
		goto err_put_proc_priv;
	}

@@ -472,6 +454,7 @@ err_put_proc_priv:
static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
{
	unsigned int type;

	if (entry == NULL)
		return;

@@ -488,9 +471,7 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
	entry->priv->stats[type].cur -= entry->memdesc.size;
	spin_unlock(&entry->priv->mem_lock);

	kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc);

	kgsl_mem_entry_untrack_gpuaddr(entry->priv, entry);
	kgsl_mmu_put_gpuaddr(&entry->memdesc);

	kgsl_process_private_put(entry->priv);

@@ -3021,7 +3002,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry(
		entry->memdesc.priv |= KGSL_MEMDESC_SECURE;

	ret = kgsl_allocate_user(dev_priv->device, &entry->memdesc,
				private->pagetable, size, flags);
		size, flags);
	if (ret != 0)
		goto err;

@@ -3442,11 +3423,11 @@ static unsigned long _gpu_set_svm_region(struct kgsl_process_private *private,
		return ret;

	entry->memdesc.gpuaddr = (uint64_t) addr;
	entry->memdesc.pagetable = private->pagetable;

	ret = kgsl_mmu_map(private->pagetable, &entry->memdesc);
	if (ret) {
		kgsl_mmu_put_gpuaddr(private->pagetable,
				&entry->memdesc);
		kgsl_mmu_put_gpuaddr(&entry->memdesc);
		return ret;
	}

+19 −16
Original line number Diff line number Diff line
/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -1402,17 +1402,16 @@ static int _setstate_alloc(struct kgsl_device *device,
{
	int ret;

	ret = kgsl_sharedmem_alloc_contig(device, &iommu->setstate, NULL,
		PAGE_SIZE);
	if (ret)
		return ret;
	ret = kgsl_sharedmem_alloc_contig(device, &iommu->setstate, PAGE_SIZE);

	if (!ret) {
		/* Mark the setstate memory as read only */
		iommu->setstate.flags |= KGSL_MEMFLAGS_GPUREADONLY;

		kgsl_sharedmem_set(device, &iommu->setstate, 0, 0, PAGE_SIZE);
	}

	return 0;
	return ret;
}

static int kgsl_iommu_init(struct kgsl_mmu *mmu)
@@ -1663,7 +1662,7 @@ static int _iommu_map_guard_page(struct kgsl_pagetable *pt,

		if (!kgsl_secure_guard_page_memdesc.sgt) {
			if (kgsl_allocate_user(KGSL_MMU_DEVICE(pt->mmu),
					&kgsl_secure_guard_page_memdesc, pt,
					&kgsl_secure_guard_page_memdesc,
					sgp_size, KGSL_MEMFLAGS_SECURE)) {
				KGSL_CORE_ERR(
					"Secure guard page alloc failed\n");
@@ -2264,23 +2263,27 @@ static int kgsl_iommu_get_gpuaddr(struct kgsl_pagetable *pagetable,
	}

	ret = _insert_gpuaddr(pagetable, addr, size);
	if (ret == 0)
	if (ret == 0) {
		memdesc->gpuaddr = addr;
		memdesc->pagetable = pagetable;
	}

out:
	spin_unlock(&pagetable->lock);
	return ret;
}

static void kgsl_iommu_put_gpuaddr(struct kgsl_pagetable *pagetable,
		struct kgsl_memdesc *memdesc)
static void kgsl_iommu_put_gpuaddr(struct kgsl_memdesc *memdesc)
{
	spin_lock(&pagetable->lock);
	if (memdesc->pagetable == NULL)
		return;

	spin_lock(&memdesc->pagetable->lock);

	if (_remove_gpuaddr(pagetable, memdesc->gpuaddr))
	if (_remove_gpuaddr(memdesc->pagetable, memdesc->gpuaddr))
		BUG();

	spin_unlock(&pagetable->lock);
	spin_unlock(&memdesc->pagetable->lock);
}

static int kgsl_iommu_svm_range(struct kgsl_pagetable *pagetable,
+23 −6
Original line number Diff line number Diff line
/* Copyright (c) 2002,2007-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2002,2007-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -419,17 +419,29 @@ EXPORT_SYMBOL(kgsl_mmu_map);
 * @pagetable: Pagetable to release the memory from
 * @memdesc: Memory descriptor containing the GPU address to free
 */
void kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable,
		struct kgsl_memdesc *memdesc)
void kgsl_mmu_put_gpuaddr(struct kgsl_memdesc *memdesc)
{
	struct kgsl_pagetable *pagetable = memdesc->pagetable;
	int unmap_fail = 0;

	if (memdesc->size == 0 || memdesc->gpuaddr == 0)
		return;

	if (PT_OP_VALID(pagetable, put_gpuaddr))
		pagetable->pt_ops->put_gpuaddr(pagetable, memdesc);
	if (!kgsl_memdesc_is_global(memdesc))
		unmap_fail = kgsl_mmu_unmap(pagetable, memdesc);

	/*
	 * Do not free the gpuaddr/size if unmap fails. Because if we
	 * try to map this range in future, the iommu driver will throw
	 * a BUG_ON() because it feels we are overwriting a mapping.
	*/
	if (PT_OP_VALID(pagetable, put_gpuaddr) && (unmap_fail == 0))
		pagetable->pt_ops->put_gpuaddr(memdesc);

	if (!kgsl_memdesc_is_global(memdesc))
		memdesc->gpuaddr = 0;

	memdesc->pagetable = NULL;
}
EXPORT_SYMBOL(kgsl_mmu_put_gpuaddr);

@@ -580,7 +592,12 @@ static int nommu_get_gpuaddr(struct kgsl_pagetable *pagetable,

	memdesc->gpuaddr = (uint64_t) sg_phys(memdesc->sgt->sgl);

	return memdesc->gpuaddr != 0 ? 0 : -ENOMEM;
	if (memdesc->gpuaddr) {
		memdesc->pagetable = pagetable;
		return 0;
	}

	return -ENOMEM;
}

static struct kgsl_mmu_pt_ops nommu_pt_ops = {
+3 −4
Original line number Diff line number Diff line
/* Copyright (c) 2002,2007-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2002,2007-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -92,7 +92,7 @@ struct kgsl_mmu_pt_ops {
	u64 (*get_ttbr0)(struct kgsl_pagetable *);
	u32 (*get_contextidr)(struct kgsl_pagetable *);
	int (*get_gpuaddr)(struct kgsl_pagetable *, struct kgsl_memdesc *);
	void (*put_gpuaddr)(struct kgsl_pagetable *, struct kgsl_memdesc *);
	void (*put_gpuaddr)(struct kgsl_memdesc *);
	uint64_t (*find_svm_region)(struct kgsl_pagetable *, uint64_t, uint64_t,
		uint64_t, uint64_t);
	int (*set_svm_region)(struct kgsl_pagetable *, uint64_t, uint64_t);
@@ -180,8 +180,7 @@ int kgsl_mmu_map(struct kgsl_pagetable *pagetable,
		 struct kgsl_memdesc *memdesc);
int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
		    struct kgsl_memdesc *memdesc);
void kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable,
		 struct kgsl_memdesc *memdesc);
void kgsl_mmu_put_gpuaddr(struct kgsl_memdesc *memdesc);
unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
unsigned int kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu,
		u64 ttbr0, uint64_t addr);
Loading