Unverified Commit d8a92dea authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!2040 iommu/arm-smmu-v3: Fix ECMDQ initialization error and add arm_smmu_v3.disable_ecmdq

Merge Pull Request from: @ci-robot 
 
PR sync from: Zhen Lei <thunder.leizhen@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/46XBBYUFYKT4UMWEDCGZVSE5ZWORHTWB/ 
1. Make ECMDQs to be evenly allocated based on the number of cores
2. Allow disabling ECMDQs at boot time

Zhen Lei (2):
  iommu/arm-smmu-v3: Make ECMDQs to be evenly allocated based on the
    number of cores
  iommu/arm-smmu-v3: Allow disabling ECMDQs at boot time


-- 
2.34.1
 
https://gitee.com/openeuler/kernel/issues/I7YUNJ 
 
Link:https://gitee.com/openeuler/kernel/pulls/2040

 

Reviewed-by: default avatarWeilong Chen <chenweilong@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents 16d69905 0785deab
Loading
Loading
Loading
Loading
+17 −88
Original line number Diff line number Diff line
@@ -46,6 +46,10 @@ module_param(disable_msipolling, bool, 0444);
MODULE_PARM_DESC(disable_msipolling,
	"Disable MSI-based polling for CMD_SYNC completion.");

static bool disable_ecmdq;
module_param(disable_ecmdq, bool, 0444);
MODULE_PARM_DESC(disable_ecmdq,	"Disable the use of ECMDQs");

#ifdef CONFIG_SMMU_BYPASS_DEV
struct smmu_bypass_device {
	unsigned short vendor;
@@ -4733,104 +4737,29 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool resume)

static int arm_smmu_ecmdq_layout(struct arm_smmu_device *smmu)
{
	int cpu, node, nr_remain, nr_nodes = 0;
	int *nr_ecmdqs;
	struct arm_smmu_ecmdq *ecmdq, **ecmdqs;
	int cpu, host_cpu;
	struct arm_smmu_ecmdq *ecmdq;

	ecmdq = devm_alloc_percpu(smmu->dev, *ecmdq);
	if (!ecmdq)
		return -ENOMEM;
	smmu->ecmdq = ecmdq;

	if (num_possible_cpus() <= smmu->nr_ecmdq) {
		for_each_possible_cpu(cpu)
			*per_cpu_ptr(smmu->ecmdqs, cpu) = per_cpu_ptr(ecmdq, cpu);

	/* A core requires at most one ECMDQ */
	if (num_possible_cpus() < smmu->nr_ecmdq)
		smmu->nr_ecmdq = num_possible_cpus();

		return 0;
	}

	for_each_node(node)
		if (nr_cpus_node(node))
			nr_nodes++;

	if (nr_nodes >= smmu->nr_ecmdq) {
		dev_err(smmu->dev, "%d ECMDQs is less than %d nodes\n", smmu->nr_ecmdq, nr_nodes);
		return -ENOSPC;
	}

	nr_ecmdqs = kcalloc(MAX_NUMNODES, sizeof(int), GFP_KERNEL);
	if (!nr_ecmdqs)
		return -ENOMEM;

	ecmdqs = kcalloc(smmu->nr_ecmdq, sizeof(*ecmdqs), GFP_KERNEL);
	if (!ecmdqs) {
		kfree(nr_ecmdqs);
		return -ENOMEM;
	}

	/* [1] Ensure that each node has at least one ECMDQ */
	nr_remain = smmu->nr_ecmdq - nr_nodes;
	for_each_node(node) {
		/*
		 * Calculate the number of ECMDQs to be allocated to this node.
		 * NR_ECMDQS_PER_CPU = nr_remain / num_possible_cpus();
		 * When nr_cpus_node(node) is not zero, less than one ECMDQ
		 * may be left due to truncation rounding.
		 */
		nr_ecmdqs[node] = nr_cpus_node(node) * nr_remain / num_possible_cpus();
	}

	for_each_node(node) {
		if (!nr_cpus_node(node))
			continue;

		nr_remain -= nr_ecmdqs[node];

		/* An ECMDQ has been reserved for each node at above [1] */
		nr_ecmdqs[node]++;
	}

	/* Divide the remaining ECMDQs */
	while (nr_remain) {
		for_each_node(node) {
			if (!nr_remain)
				break;

			if (nr_ecmdqs[node] >= nr_cpus_node(node))
				continue;

			nr_ecmdqs[node]++;
			nr_remain--;
		}
	}

	for_each_node(node) {
		int i, round, shared;

		if (!nr_cpus_node(node))
			continue;

		shared = 0;
		if (nr_ecmdqs[node] < nr_cpus_node(node))
			shared = 1;

		i = 0;
		for_each_cpu(cpu, cpumask_of_node(node)) {
			round = i % nr_ecmdqs[node];
			if (i++ < nr_ecmdqs[node])
				ecmdqs[round] = per_cpu_ptr(ecmdq, cpu);
			else
				ecmdqs[round]->cmdq.shared = shared;
			*per_cpu_ptr(smmu->ecmdqs, cpu) = ecmdqs[round];
	for_each_possible_cpu(cpu) {
		if (cpu < smmu->nr_ecmdq) {
			*per_cpu_ptr(smmu->ecmdqs, cpu) = per_cpu_ptr(smmu->ecmdq, cpu);
		} else {
			host_cpu = cpu % smmu->nr_ecmdq;
			ecmdq = per_cpu_ptr(smmu->ecmdq, host_cpu);
			ecmdq->cmdq.shared = 1;
			*per_cpu_ptr(smmu->ecmdqs, cpu) = ecmdq;
		}
	}

	kfree(nr_ecmdqs);
	kfree(ecmdqs);

	return 0;
}

@@ -5204,7 +5133,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
	dev_info(smmu->dev, "ias %lu-bit, oas %lu-bit (features 0x%08x)\n",
		 smmu->ias, smmu->oas, smmu->features);

	if (smmu->features & ARM_SMMU_FEAT_ECMDQ) {
	if (smmu->features & ARM_SMMU_FEAT_ECMDQ && !disable_ecmdq) {
		int err;

		err = arm_smmu_ecmdq_probe(smmu);