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

Commit 7e38aa10 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: Implement mutex between SMMU operations and GPU power collapse"

parents 4d4ccd5c b3e31a5d
Loading
Loading
Loading
Loading
+6 −14
Original line number Diff line number Diff line
@@ -1345,9 +1345,8 @@ static int _adreno_start(struct adreno_device *adreno_dev)
{
	struct kgsl_device *device = &adreno_dev->dev;
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	int i, status = -EINVAL;
	int status = -EINVAL;
	unsigned int state = device->state;
	unsigned int regulator_left_on = 0;
	unsigned int pmqos_wakeup_vote = device->pwrctrl.pm_qos_wakeup_latency;
	unsigned int pmqos_active_vote = device->pwrctrl.pm_qos_active_latency;

@@ -1359,27 +1358,20 @@ static int _adreno_start(struct adreno_device *adreno_dev)

	kgsl_cffdump_open(device);

	for (i = 0; i < KGSL_MAX_REGULATORS; i++) {
		if (device->pwrctrl.gpu_reg[i] &&
			regulator_is_enabled(device->pwrctrl.gpu_reg[i])) {
			regulator_left_on = 1;
			break;
		}
	}

	/* Clear any GPU faults that might have been left over */
	adreno_clear_gpu_fault(adreno_dev);

	/* Put the GPU in a responsive state */
	device->regulator_left_on = false;
	status = kgsl_pwrctrl_change_state(device, KGSL_STATE_AWARE);
	if (status)
		goto error_pwr_off;

	/* Clear any GPU faults that might have been left over */
	adreno_clear_gpu_fault(adreno_dev);

	/* Set the bit to indicate that we've just powered on */
	set_bit(ADRENO_DEVICE_PWRON, &adreno_dev->priv);

	/* Soft reset the GPU if a regulator is stuck on*/
	if (regulator_left_on)
	if (device->regulator_left_on)
		_soft_reset(adreno_dev);

	status = kgsl_mmu_start(device);
+3 −0
Original line number Diff line number Diff line
@@ -250,6 +250,7 @@ struct kgsl_device {
	int open_count;

	struct mutex mutex;
	struct mutex mutex_pc_smmu;
	uint32_t state;
	uint32_t requested_state;

@@ -289,6 +290,7 @@ struct kgsl_device {
	struct workqueue_struct *events_wq;

	struct device *busmondev; /* pseudo dev for GPU BW voting governor */
	bool regulator_left_on;
};


@@ -303,6 +305,7 @@ struct kgsl_device {
	.wait_queue = __WAIT_QUEUE_HEAD_INITIALIZER((_dev).wait_queue),\
	.active_cnt_wq = __WAIT_QUEUE_HEAD_INITIALIZER((_dev).active_cnt_wq),\
	.mutex = __MUTEX_INITIALIZER((_dev).mutex),\
	.mutex_pc_smmu = __MUTEX_INITIALIZER((_dev).mutex_pc_smmu),\
	.state = KGSL_STATE_NONE,\
	.ver_major = DRIVER_VERSION_MAJOR,\
	.ver_minor = DRIVER_VERSION_MINOR
+20 −3
Original line number Diff line number Diff line
@@ -1022,6 +1022,7 @@ static int kgsl_iommu_start(struct kgsl_mmu *mmu)
	kgsl_map_global_pt_entries(mmu->defaultpagetable);

	kgsl_iommu_enable_clk(mmu);
	KGSL_IOMMU_SET_CTX_REG(iommu, 0, TLBIALL, 1);

	/* Get the lsb value of pagetables set in the IOMMU ttbr0 register as
	 * that value should not change when we change pagetables, so while
@@ -1130,13 +1131,18 @@ kgsl_iommu_unmap(struct kgsl_pagetable *pt,
		mutex_lock(&device->mutex);
		ret = kgsl_active_count_get(device);
		if (!ret) {
			mutex_lock(&device->mutex_pc_smmu);
			unmapped = iommu_unmap(iommu_pt->domain, gpuaddr,
					range);
			mutex_unlock(&device->mutex_pc_smmu);
			kgsl_active_count_put(device);
		}
		mutex_unlock(&device->mutex);
	} else
	} else {
		mutex_lock(&device->mutex_pc_smmu);
		unmapped = iommu_unmap(iommu_pt->domain, gpuaddr, range);
		mutex_unlock(&device->mutex_pc_smmu);
	}
	if (unmapped != range) {
		KGSL_CORE_ERR(
			"iommu_unmap(%p, %llx, %lld) failed with unmapped size: %zd\n",
@@ -1197,9 +1203,11 @@ int _iommu_add_guard_page(struct kgsl_pagetable *pt,
			physaddr = kgsl_secure_guard_page_memdesc.physaddr;
		}

		mutex_lock(&pt->mmu->device->mutex_pc_smmu);
		ret = iommu_map(iommu_pt->domain, gpuaddr, physaddr,
				kgsl_memdesc_guard_page_size(memdesc),
				protflags & ~IOMMU_WRITE);
		mutex_unlock(&pt->mmu->device->mutex_pc_smmu);
		if (ret) {
			KGSL_CORE_ERR(
			"iommu_map(%p, addr %016llX, flags %x) err: %d\n",
@@ -1247,15 +1255,21 @@ kgsl_iommu_map(struct kgsl_pagetable *pt,
		mutex_lock(&device->mutex);
		ret = kgsl_active_count_get(device);
		if (!ret) {
			mutex_lock(&device->mutex_pc_smmu);
			mapped = iommu_map_sg(iommu_pt->domain, addr,
					memdesc->sgt->sgl, memdesc->sgt->nents,
					flags);
			mutex_unlock(&device->mutex_pc_smmu);
			kgsl_active_count_put(device);
		}
		mutex_unlock(&device->mutex);
	} else
	} else {
		mutex_lock(&device->mutex_pc_smmu);
		mapped = iommu_map_sg(iommu_pt->domain, addr,
				memdesc->sgt->sgl, memdesc->sgt->nents, flags);
		mutex_unlock(&device->mutex_pc_smmu);
	}


	if (mapped != size) {
		KGSL_CORE_ERR("iommu_map_sg(%p, %016llX, %lld, %x) err: %zd\n",
@@ -1265,9 +1279,12 @@ kgsl_iommu_map(struct kgsl_pagetable *pt,
	}

	ret = _iommu_add_guard_page(pt, memdesc, addr + size, flags);
	if (ret)
	if (ret) {
		/* cleanup the partial mapping */
		mutex_lock(&device->mutex_pc_smmu);
		iommu_unmap(iommu_pt->domain, addr, size);
		mutex_unlock(&device->mutex_pc_smmu);
	}

	/*
	 *  IOMMU V1 BFBs pre-fetch data beyond what is being used by the core.
+9 −0
Original line number Diff line number Diff line
@@ -1286,15 +1286,21 @@ static int kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state)
		if (test_and_clear_bit(KGSL_PWRFLAGS_POWER_ON,
			&pwr->power_flags)) {
			trace_kgsl_rail(device, state);
			mutex_lock(&device->mutex_pc_smmu);
			for (i = KGSL_MAX_REGULATORS - 1; i >= 0; i--) {
				if (pwr->gpu_reg[i])
					regulator_disable(pwr->gpu_reg[i]);
			}
			mutex_unlock(&device->mutex_pc_smmu);
		}
	} else if (state == KGSL_PWRFLAGS_ON) {
		if (!test_and_set_bit(KGSL_PWRFLAGS_POWER_ON,
			&pwr->power_flags)) {
			mutex_lock(&device->mutex_pc_smmu);
			for (i = 0; i < KGSL_MAX_REGULATORS; i++) {
				if (regulator_is_enabled(
				    device->pwrctrl.gpu_reg[i]))
					device->regulator_left_on = true;
				if (pwr->gpu_reg[i])
					status = regulator_enable(
							pwr->gpu_reg[i]);
@@ -1306,13 +1312,16 @@ static int kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state)
					break;
				}
			}
			mutex_unlock(&device->mutex_pc_smmu);

			if (status) {
				mutex_lock(&device->mutex_pc_smmu);
				for (j = i - 1; j >= 0; j--) {
					if (pwr->gpu_reg[j])
						regulator_disable(
							pwr->gpu_reg[j]);
				}
				mutex_unlock(&device->mutex_pc_smmu);
				clear_bit(KGSL_PWRFLAGS_POWER_ON,
					&pwr->power_flags);
			} else