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

Commit 66c95a67 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: Take the pagetable reference count only when needed"

parents 083824ec fe1d2cbb
Loading
Loading
Loading
Loading
+23 −52
Original line number Original line Diff line number Diff line
@@ -230,41 +230,27 @@ int kgsl_add_global_pt_entry(struct kgsl_device *device,
}
}
EXPORT_SYMBOL(kgsl_add_global_pt_entry);
EXPORT_SYMBOL(kgsl_add_global_pt_entry);


static void _kgsl_destroy_pagetable(struct kgsl_pagetable *pagetable)
{
	pagetable_remove_sysfs_objects(pagetable);

	kgsl_unmap_global_pt_entries(pagetable);

	if (pagetable->pool)
		gen_pool_destroy(pagetable->pool);

	pagetable->pt_ops->mmu_destroy_pagetable(pagetable);

	kfree(pagetable);
}

static void kgsl_destroy_pagetable(struct kref *kref)
static void kgsl_destroy_pagetable(struct kref *kref)
{
{
	struct kgsl_pagetable *pagetable = container_of(kref,
	struct kgsl_pagetable *pagetable = container_of(kref,
		struct kgsl_pagetable, refcount);
		struct kgsl_pagetable, refcount);

	unsigned long flags;
	unsigned long flags;


	spin_lock_irqsave(&kgsl_driver.ptlock, flags);
	spin_lock_irqsave(&kgsl_driver.ptlock, flags);
	list_del(&pagetable->list);
	list_del(&pagetable->list);
	spin_unlock_irqrestore(&kgsl_driver.ptlock, flags);
	spin_unlock_irqrestore(&kgsl_driver.ptlock, flags);


	_kgsl_destroy_pagetable(pagetable);
	pagetable_remove_sysfs_objects(pagetable);
}


static void kgsl_destroy_pagetable_locked(struct kref *kref)
	kgsl_unmap_global_pt_entries(pagetable);
{
	struct kgsl_pagetable *pagetable = container_of(kref,
		struct kgsl_pagetable, refcount);


	list_del(&pagetable->list);
	if (pagetable->pool)
		gen_pool_destroy(pagetable->pool);

	pagetable->pt_ops->mmu_destroy_pagetable(pagetable);


	_kgsl_destroy_pagetable(pagetable);
	kfree(pagetable);
}
}


static inline void kgsl_put_pagetable(struct kgsl_pagetable *pagetable)
static inline void kgsl_put_pagetable(struct kgsl_pagetable *pagetable)
@@ -281,13 +267,10 @@ kgsl_get_pagetable(unsigned long name)


	spin_lock_irqsave(&kgsl_driver.ptlock, flags);
	spin_lock_irqsave(&kgsl_driver.ptlock, flags);
	list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) {
	list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) {
		if (kref_get_unless_zero(&pt->refcount)) {
		if (name == pt->name && kref_get_unless_zero(&pt->refcount)) {
			if (pt->name == name) {
			ret = pt;
			ret = pt;
			break;
			break;
		}
		}
			kref_put(&pt->refcount, kgsl_destroy_pagetable_locked);
		}
	}
	}


	spin_unlock_irqrestore(&kgsl_driver.ptlock, flags);
	spin_unlock_irqrestore(&kgsl_driver.ptlock, flags);
@@ -433,15 +416,10 @@ kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, phys_addr_t pt_base)
		return KGSL_MMU_GLOBAL_PT;
		return KGSL_MMU_GLOBAL_PT;
	spin_lock(&kgsl_driver.ptlock);
	spin_lock(&kgsl_driver.ptlock);
	list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) {
	list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) {
		if (kref_get_unless_zero(&pt->refcount)) {
		if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) {
		if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) {
			ptid = (int) pt->name;
			ptid = (int) pt->name;
				kref_put(&pt->refcount,
					kgsl_destroy_pagetable_locked);
			break;
			break;
		}
		}
			kref_put(&pt->refcount, kgsl_destroy_pagetable_locked);
		}
	}
	}
	spin_unlock(&kgsl_driver.ptlock);
	spin_unlock(&kgsl_driver.ptlock);


@@ -460,24 +438,17 @@ kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, phys_addr_t pt_base,
		return 0;
		return 0;
	spin_lock(&kgsl_driver.ptlock);
	spin_lock(&kgsl_driver.ptlock);
	list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) {
	list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) {
		if (kref_get_unless_zero(&pt->refcount)) {
		if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) {
		if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) {
			if ((addr & ~(PAGE_SIZE-1)) == pt->fault_addr) {
			if ((addr & ~(PAGE_SIZE-1)) == pt->fault_addr) {
				ret = 1;
				ret = 1;
					kref_put(&pt->refcount,
						kgsl_destroy_pagetable_locked);
				break;
				break;
			} else {
			} else {
				pt->fault_addr =
				pt->fault_addr =
					(addr & ~(PAGE_SIZE-1));
					(addr & ~(PAGE_SIZE-1));
				ret = 0;
				ret = 0;
					kref_put(&pt->refcount,
						kgsl_destroy_pagetable_locked);
				break;
				break;
			}
			}
		}
		}
			kref_put(&pt->refcount, kgsl_destroy_pagetable_locked);
		}
	}
	}
	spin_unlock(&kgsl_driver.ptlock);
	spin_unlock(&kgsl_driver.ptlock);