Skip to content

Commit e38432c

Browse files
committed
Merge tag 'arm-smmu-updates' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into arm/smmu
Arm SMMU updates for 5.18 - Fix SMMUv3 soft lockup during continuous stream of events - Fix error path for Qualcomm SMMU probe() - Rework SMMU IRQ setup to prepare the ground for PMU support - Minor cleanups and refactoring
2 parents 754e0b0 + 97dfad1 commit e38432c

5 files changed

Lines changed: 64 additions & 75 deletions

File tree

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,6 +1558,7 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
15581558
dev_info(smmu->dev, "\t0x%016llx\n",
15591559
(unsigned long long)evt[i]);
15601560

1561+
cond_resched();
15611562
}
15621563

15631564
/*
@@ -2911,32 +2912,20 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
29112912
return 0;
29122913
}
29132914

2914-
static void arm_smmu_cmdq_free_bitmap(void *data)
2915-
{
2916-
unsigned long *bitmap = data;
2917-
bitmap_free(bitmap);
2918-
}
2919-
29202915
static int arm_smmu_cmdq_init(struct arm_smmu_device *smmu)
29212916
{
2922-
int ret = 0;
29232917
struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
29242918
unsigned int nents = 1 << cmdq->q.llq.max_n_shift;
2925-
atomic_long_t *bitmap;
29262919

29272920
atomic_set(&cmdq->owner_prod, 0);
29282921
atomic_set(&cmdq->lock, 0);
29292922

2930-
bitmap = (atomic_long_t *)bitmap_zalloc(nents, GFP_KERNEL);
2931-
if (!bitmap) {
2932-
dev_err(smmu->dev, "failed to allocate cmdq bitmap\n");
2933-
ret = -ENOMEM;
2934-
} else {
2935-
cmdq->valid_map = bitmap;
2936-
devm_add_action(smmu->dev, arm_smmu_cmdq_free_bitmap, bitmap);
2937-
}
2923+
cmdq->valid_map = (atomic_long_t *)devm_bitmap_zalloc(smmu->dev, nents,
2924+
GFP_KERNEL);
2925+
if (!cmdq->valid_map)
2926+
return -ENOMEM;
29382927

2939-
return ret;
2928+
return 0;
29402929
}
29412930

29422931
static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
@@ -2981,10 +2970,10 @@ static int arm_smmu_init_l1_strtab(struct arm_smmu_device *smmu)
29812970
{
29822971
unsigned int i;
29832972
struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
2984-
size_t size = sizeof(*cfg->l1_desc) * cfg->num_l1_ents;
29852973
void *strtab = smmu->strtab_cfg.strtab;
29862974

2987-
cfg->l1_desc = devm_kzalloc(smmu->dev, size, GFP_KERNEL);
2975+
cfg->l1_desc = devm_kcalloc(smmu->dev, cfg->num_l1_ents,
2976+
sizeof(*cfg->l1_desc), GFP_KERNEL);
29882977
if (!cfg->l1_desc)
29892978
return -ENOMEM;
29902979

drivers/iommu/arm/arm-smmu/arm-smmu.c

Lines changed: 44 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
807807
* Request context fault interrupt. Do this last to avoid the
808808
* handler seeing a half-initialised domain state.
809809
*/
810-
irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
810+
irq = smmu->irqs[cfg->irptndx];
811811

812812
if (smmu->impl && smmu->impl->context_fault)
813813
context_fault = smmu->impl->context_fault;
@@ -858,7 +858,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
858858
arm_smmu_write_context_bank(smmu, cfg->cbndx);
859859

860860
if (cfg->irptndx != ARM_SMMU_INVALID_IRPTNDX) {
861-
irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
861+
irq = smmu->irqs[cfg->irptndx];
862862
devm_free_irq(smmu->dev, irq, domain);
863863
}
864864

@@ -1951,8 +1951,8 @@ static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu)
19511951
return ret;
19521952
}
19531953

1954-
static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
1955-
struct arm_smmu_device *smmu)
1954+
static int arm_smmu_device_acpi_probe(struct arm_smmu_device *smmu,
1955+
u32 *global_irqs, u32 *pmu_irqs)
19561956
{
19571957
struct device *dev = smmu->dev;
19581958
struct acpi_iort_node *node =
@@ -1968,33 +1968,33 @@ static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
19681968
return ret;
19691969

19701970
/* Ignore the configuration access interrupt */
1971-
smmu->num_global_irqs = 1;
1971+
*global_irqs = 1;
1972+
*pmu_irqs = 0;
19721973

19731974
if (iort_smmu->flags & ACPI_IORT_SMMU_COHERENT_WALK)
19741975
smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
19751976

19761977
return 0;
19771978
}
19781979
#else
1979-
static inline int arm_smmu_device_acpi_probe(struct platform_device *pdev,
1980-
struct arm_smmu_device *smmu)
1980+
static inline int arm_smmu_device_acpi_probe(struct arm_smmu_device *smmu,
1981+
u32 *global_irqs, u32 *pmu_irqs)
19811982
{
19821983
return -ENODEV;
19831984
}
19841985
#endif
19851986

1986-
static int arm_smmu_device_dt_probe(struct platform_device *pdev,
1987-
struct arm_smmu_device *smmu)
1987+
static int arm_smmu_device_dt_probe(struct arm_smmu_device *smmu,
1988+
u32 *global_irqs, u32 *pmu_irqs)
19881989
{
19891990
const struct arm_smmu_match_data *data;
1990-
struct device *dev = &pdev->dev;
1991+
struct device *dev = smmu->dev;
19911992
bool legacy_binding;
19921993

1993-
if (of_property_read_u32(dev->of_node, "#global-interrupts",
1994-
&smmu->num_global_irqs)) {
1995-
dev_err(dev, "missing #global-interrupts property\n");
1996-
return -ENODEV;
1997-
}
1994+
if (of_property_read_u32(dev->of_node, "#global-interrupts", global_irqs))
1995+
return dev_err_probe(dev, -ENODEV,
1996+
"missing #global-interrupts property\n");
1997+
*pmu_irqs = 0;
19981998

19991999
data = of_device_get_match_data(dev);
20002000
smmu->version = data->version;
@@ -2073,6 +2073,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
20732073
struct arm_smmu_device *smmu;
20742074
struct device *dev = &pdev->dev;
20752075
int num_irqs, i, err;
2076+
u32 global_irqs, pmu_irqs;
20762077
irqreturn_t (*global_fault)(int irq, void *dev);
20772078

20782079
smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
@@ -2083,10 +2084,9 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
20832084
smmu->dev = dev;
20842085

20852086
if (dev->of_node)
2086-
err = arm_smmu_device_dt_probe(pdev, smmu);
2087+
err = arm_smmu_device_dt_probe(smmu, &global_irqs, &pmu_irqs);
20872088
else
2088-
err = arm_smmu_device_acpi_probe(pdev, smmu);
2089-
2089+
err = arm_smmu_device_acpi_probe(smmu, &global_irqs, &pmu_irqs);
20902090
if (err)
20912091
return err;
20922092

@@ -2105,31 +2105,25 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
21052105
if (IS_ERR(smmu))
21062106
return PTR_ERR(smmu);
21072107

2108-
num_irqs = 0;
2109-
while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, num_irqs))) {
2110-
num_irqs++;
2111-
if (num_irqs > smmu->num_global_irqs)
2112-
smmu->num_context_irqs++;
2113-
}
2108+
num_irqs = platform_irq_count(pdev);
21142109

2115-
if (!smmu->num_context_irqs) {
2116-
dev_err(dev, "found %d interrupts but expected at least %d\n",
2117-
num_irqs, smmu->num_global_irqs + 1);
2118-
return -ENODEV;
2119-
}
2110+
smmu->num_context_irqs = num_irqs - global_irqs - pmu_irqs;
2111+
if (smmu->num_context_irqs <= 0)
2112+
return dev_err_probe(dev, -ENODEV,
2113+
"found %d interrupts but expected at least %d\n",
2114+
num_irqs, global_irqs + pmu_irqs + 1);
21202115

2121-
smmu->irqs = devm_kcalloc(dev, num_irqs, sizeof(*smmu->irqs),
2122-
GFP_KERNEL);
2123-
if (!smmu->irqs) {
2124-
dev_err(dev, "failed to allocate %d irqs\n", num_irqs);
2125-
return -ENOMEM;
2126-
}
2116+
smmu->irqs = devm_kcalloc(dev, smmu->num_context_irqs,
2117+
sizeof(*smmu->irqs), GFP_KERNEL);
2118+
if (!smmu->irqs)
2119+
return dev_err_probe(dev, -ENOMEM, "failed to allocate %d irqs\n",
2120+
smmu->num_context_irqs);
21272121

2128-
for (i = 0; i < num_irqs; ++i) {
2129-
int irq = platform_get_irq(pdev, i);
2122+
for (i = 0; i < smmu->num_context_irqs; i++) {
2123+
int irq = platform_get_irq(pdev, global_irqs + pmu_irqs + i);
21302124

21312125
if (irq < 0)
2132-
return -ENODEV;
2126+
return irq;
21332127
smmu->irqs[i] = irq;
21342128
}
21352129

@@ -2165,17 +2159,18 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
21652159
else
21662160
global_fault = arm_smmu_global_fault;
21672161

2168-
for (i = 0; i < smmu->num_global_irqs; ++i) {
2169-
err = devm_request_irq(smmu->dev, smmu->irqs[i],
2170-
global_fault,
2171-
IRQF_SHARED,
2172-
"arm-smmu global fault",
2173-
smmu);
2174-
if (err) {
2175-
dev_err(dev, "failed to request global IRQ %d (%u)\n",
2176-
i, smmu->irqs[i]);
2177-
return err;
2178-
}
2162+
for (i = 0; i < global_irqs; i++) {
2163+
int irq = platform_get_irq(pdev, i);
2164+
2165+
if (irq < 0)
2166+
return irq;
2167+
2168+
err = devm_request_irq(dev, irq, global_fault, IRQF_SHARED,
2169+
"arm-smmu global fault", smmu);
2170+
if (err)
2171+
return dev_err_probe(dev, err,
2172+
"failed to request global IRQ %d (%u)\n",
2173+
i, irq);
21792174
}
21802175

21812176
err = iommu_device_sysfs_add(&smmu->iommu, smmu->dev, NULL,

drivers/iommu/arm/arm-smmu/arm-smmu.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,11 +318,10 @@ struct arm_smmu_device {
318318
unsigned long pa_size;
319319
unsigned long pgsize_bitmap;
320320

321-
u32 num_global_irqs;
322-
u32 num_context_irqs;
321+
int num_context_irqs;
322+
int num_clks;
323323
unsigned int *irqs;
324324
struct clk_bulk_data *clks;
325-
int num_clks;
326325

327326
spinlock_t global_sync_lock;
328327

drivers/iommu/arm/arm-smmu/qcom_iommu.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -827,20 +827,20 @@ static int qcom_iommu_device_probe(struct platform_device *pdev)
827827
ret = devm_of_platform_populate(dev);
828828
if (ret) {
829829
dev_err(dev, "Failed to populate iommu contexts\n");
830-
return ret;
830+
goto err_pm_disable;
831831
}
832832

833833
ret = iommu_device_sysfs_add(&qcom_iommu->iommu, dev, NULL,
834834
dev_name(dev));
835835
if (ret) {
836836
dev_err(dev, "Failed to register iommu in sysfs\n");
837-
return ret;
837+
goto err_pm_disable;
838838
}
839839

840840
ret = iommu_device_register(&qcom_iommu->iommu, &qcom_iommu_ops, dev);
841841
if (ret) {
842842
dev_err(dev, "Failed to register iommu\n");
843-
return ret;
843+
goto err_pm_disable;
844844
}
845845

846846
bus_set_iommu(&platform_bus_type, &qcom_iommu_ops);
@@ -852,6 +852,10 @@ static int qcom_iommu_device_probe(struct platform_device *pdev)
852852
}
853853

854854
return 0;
855+
856+
err_pm_disable:
857+
pm_runtime_disable(dev);
858+
return ret;
855859
}
856860

857861
static int qcom_iommu_device_remove(struct platform_device *pdev)

drivers/perf/arm_smmuv3_pmu.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,7 @@ static int smmu_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
654654
static irqreturn_t smmu_pmu_handle_irq(int irq_num, void *data)
655655
{
656656
struct smmu_pmu *smmu_pmu = data;
657+
DECLARE_BITMAP(ovs, BITS_PER_TYPE(u64));
657658
u64 ovsr;
658659
unsigned int idx;
659660

@@ -663,7 +664,8 @@ static irqreturn_t smmu_pmu_handle_irq(int irq_num, void *data)
663664

664665
writeq(ovsr, smmu_pmu->reloc_base + SMMU_PMCG_OVSCLR0);
665666

666-
for_each_set_bit(idx, (unsigned long *)&ovsr, smmu_pmu->num_counters) {
667+
bitmap_from_u64(ovs, ovsr);
668+
for_each_set_bit(idx, ovs, smmu_pmu->num_counters) {
667669
struct perf_event *event = smmu_pmu->events[idx];
668670
struct hw_perf_event *hwc;
669671

0 commit comments

Comments
 (0)