Skip to content

Commit 92367fd

Browse files
committed
Merge tag 'iommu-fixes-6.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull iommu fixes from Joerg Roedel: - Maintainer update for S390 IOMMU driver - A fix for the set_platform_dma_ops() call-back in the Exynos IOMMU driver - Intel VT-d fixes from Lu Baolu: - Fix a lockdep splat - Fix a supplement of the specification - Fix a warning in perfmon code * tag 'iommu-fixes-6.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: iommu/vt-d: Fix an IOMMU perfmon warning when CPU hotplug iommu/vt-d: Allow zero SAGAW if second-stage not supported iommu/vt-d: Remove unnecessary locking in intel_irq_remapping_alloc() iommu/exynos: Fix set_platform_dma_ops() callback MAINTAINERS: Update s390-iommu driver maintainer information
2 parents 7b50567 + 16812c9 commit 92367fd

File tree

7 files changed

+60
-40
lines changed

7 files changed

+60
-40
lines changed

MAINTAINERS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18288,8 +18288,9 @@ F: drivers/s390/block/dasd*
1828818288
F: include/linux/dasd_mod.h
1828918289

1829018290
S390 IOMMU (PCI)
18291+
M: Niklas Schnelle <[email protected]>
1829118292
M: Matthew Rosato <[email protected]>
18292-
M: Gerald Schaefer <[email protected]>
18293+
R: Gerald Schaefer <[email protected]>
1829318294
1829418295
S: Supported
1829518296
F: drivers/iommu/s390-iommu.c

drivers/iommu/exynos-iommu.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,23 +1415,26 @@ static struct iommu_device *exynos_iommu_probe_device(struct device *dev)
14151415
return &data->iommu;
14161416
}
14171417

1418-
static void exynos_iommu_release_device(struct device *dev)
1418+
static void exynos_iommu_set_platform_dma(struct device *dev)
14191419
{
14201420
struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev);
1421-
struct sysmmu_drvdata *data;
14221421

14231422
if (owner->domain) {
14241423
struct iommu_group *group = iommu_group_get(dev);
14251424

14261425
if (group) {
1427-
#ifndef CONFIG_ARM
1428-
WARN_ON(owner->domain !=
1429-
iommu_group_default_domain(group));
1430-
#endif
14311426
exynos_iommu_detach_device(owner->domain, dev);
14321427
iommu_group_put(group);
14331428
}
14341429
}
1430+
}
1431+
1432+
static void exynos_iommu_release_device(struct device *dev)
1433+
{
1434+
struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev);
1435+
struct sysmmu_drvdata *data;
1436+
1437+
exynos_iommu_set_platform_dma(dev);
14351438

14361439
list_for_each_entry(data, &owner->controllers, owner_node)
14371440
device_link_del(data->link);
@@ -1479,7 +1482,7 @@ static const struct iommu_ops exynos_iommu_ops = {
14791482
.domain_alloc = exynos_iommu_domain_alloc,
14801483
.device_group = generic_device_group,
14811484
#ifdef CONFIG_ARM
1482-
.set_platform_dma_ops = exynos_iommu_release_device,
1485+
.set_platform_dma_ops = exynos_iommu_set_platform_dma,
14831486
#endif
14841487
.probe_device = exynos_iommu_probe_device,
14851488
.release_device = exynos_iommu_release_device,

drivers/iommu/intel/dmar.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1071,7 +1071,8 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
10711071
}
10721072

10731073
err = -EINVAL;
1074-
if (cap_sagaw(iommu->cap) == 0) {
1074+
if (!cap_sagaw(iommu->cap) &&
1075+
(!ecap_smts(iommu->ecap) || ecap_slts(iommu->ecap))) {
10751076
pr_info("%s: No supported address widths. Not attempting DMA translation.\n",
10761077
iommu->name);
10771078
drhd->ignored = 1;

drivers/iommu/intel/iommu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,8 @@ struct iommu_pmu {
641641
DECLARE_BITMAP(used_mask, IOMMU_PMU_IDX_MAX);
642642
struct perf_event *event_list[IOMMU_PMU_IDX_MAX];
643643
unsigned char irq_name[16];
644+
struct hlist_node cpuhp_node;
645+
int cpu;
644646
};
645647

646648
#define IOMMU_IRQ_ID_OFFSET_PRQ (DMAR_UNITS_SUPPORTED)

drivers/iommu/intel/irq_remapping.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -311,14 +311,12 @@ static int set_ioapic_sid(struct irte *irte, int apic)
311311
if (!irte)
312312
return -1;
313313

314-
down_read(&dmar_global_lock);
315314
for (i = 0; i < MAX_IO_APICS; i++) {
316315
if (ir_ioapic[i].iommu && ir_ioapic[i].id == apic) {
317316
sid = (ir_ioapic[i].bus << 8) | ir_ioapic[i].devfn;
318317
break;
319318
}
320319
}
321-
up_read(&dmar_global_lock);
322320

323321
if (sid == 0) {
324322
pr_warn("Failed to set source-id of IOAPIC (%d)\n", apic);
@@ -338,14 +336,12 @@ static int set_hpet_sid(struct irte *irte, u8 id)
338336
if (!irte)
339337
return -1;
340338

341-
down_read(&dmar_global_lock);
342339
for (i = 0; i < MAX_HPET_TBS; i++) {
343340
if (ir_hpet[i].iommu && ir_hpet[i].id == id) {
344341
sid = (ir_hpet[i].bus << 8) | ir_hpet[i].devfn;
345342
break;
346343
}
347344
}
348-
up_read(&dmar_global_lock);
349345

350346
if (sid == 0) {
351347
pr_warn("Failed to set source-id of HPET block (%d)\n", id);
@@ -1339,9 +1335,7 @@ static int intel_irq_remapping_alloc(struct irq_domain *domain,
13391335
if (!data)
13401336
goto out_free_parent;
13411337

1342-
down_read(&dmar_global_lock);
13431338
index = alloc_irte(iommu, &data->irq_2_iommu, nr_irqs);
1344-
up_read(&dmar_global_lock);
13451339
if (index < 0) {
13461340
pr_warn("Failed to allocate IRTE\n");
13471341
kfree(data);

drivers/iommu/intel/perfmon.c

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -773,19 +773,34 @@ static void iommu_pmu_unset_interrupt(struct intel_iommu *iommu)
773773
iommu->perf_irq = 0;
774774
}
775775

776-
static int iommu_pmu_cpu_online(unsigned int cpu)
776+
static int iommu_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
777777
{
778+
struct iommu_pmu *iommu_pmu = hlist_entry_safe(node, typeof(*iommu_pmu), cpuhp_node);
779+
778780
if (cpumask_empty(&iommu_pmu_cpu_mask))
779781
cpumask_set_cpu(cpu, &iommu_pmu_cpu_mask);
780782

783+
if (cpumask_test_cpu(cpu, &iommu_pmu_cpu_mask))
784+
iommu_pmu->cpu = cpu;
785+
781786
return 0;
782787
}
783788

784-
static int iommu_pmu_cpu_offline(unsigned int cpu)
789+
static int iommu_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
785790
{
786-
struct dmar_drhd_unit *drhd;
787-
struct intel_iommu *iommu;
788-
int target;
791+
struct iommu_pmu *iommu_pmu = hlist_entry_safe(node, typeof(*iommu_pmu), cpuhp_node);
792+
int target = cpumask_first(&iommu_pmu_cpu_mask);
793+
794+
/*
795+
* The iommu_pmu_cpu_mask has been updated when offline the CPU
796+
* for the first iommu_pmu. Migrate the other iommu_pmu to the
797+
* new target.
798+
*/
799+
if (target < nr_cpu_ids && target != iommu_pmu->cpu) {
800+
perf_pmu_migrate_context(&iommu_pmu->pmu, cpu, target);
801+
iommu_pmu->cpu = target;
802+
return 0;
803+
}
789804

790805
if (!cpumask_test_and_clear_cpu(cpu, &iommu_pmu_cpu_mask))
791806
return 0;
@@ -795,45 +810,50 @@ static int iommu_pmu_cpu_offline(unsigned int cpu)
795810
if (target < nr_cpu_ids)
796811
cpumask_set_cpu(target, &iommu_pmu_cpu_mask);
797812
else
798-
target = -1;
813+
return 0;
799814

800-
rcu_read_lock();
801-
802-
for_each_iommu(iommu, drhd) {
803-
if (!iommu->pmu)
804-
continue;
805-
perf_pmu_migrate_context(&iommu->pmu->pmu, cpu, target);
806-
}
807-
rcu_read_unlock();
815+
perf_pmu_migrate_context(&iommu_pmu->pmu, cpu, target);
816+
iommu_pmu->cpu = target;
808817

809818
return 0;
810819
}
811820

812821
static int nr_iommu_pmu;
822+
static enum cpuhp_state iommu_cpuhp_slot;
813823

814824
static int iommu_pmu_cpuhp_setup(struct iommu_pmu *iommu_pmu)
815825
{
816826
int ret;
817827

818-
if (nr_iommu_pmu++)
819-
return 0;
828+
if (!nr_iommu_pmu) {
829+
ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
830+
"driver/iommu/intel/perfmon:online",
831+
iommu_pmu_cpu_online,
832+
iommu_pmu_cpu_offline);
833+
if (ret < 0)
834+
return ret;
835+
iommu_cpuhp_slot = ret;
836+
}
820837

821-
ret = cpuhp_setup_state(CPUHP_AP_PERF_X86_IOMMU_PERF_ONLINE,
822-
"driver/iommu/intel/perfmon:online",
823-
iommu_pmu_cpu_online,
824-
iommu_pmu_cpu_offline);
825-
if (ret)
826-
nr_iommu_pmu = 0;
838+
ret = cpuhp_state_add_instance(iommu_cpuhp_slot, &iommu_pmu->cpuhp_node);
839+
if (ret) {
840+
if (!nr_iommu_pmu)
841+
cpuhp_remove_multi_state(iommu_cpuhp_slot);
842+
return ret;
843+
}
844+
nr_iommu_pmu++;
827845

828-
return ret;
846+
return 0;
829847
}
830848

831849
static void iommu_pmu_cpuhp_free(struct iommu_pmu *iommu_pmu)
832850
{
851+
cpuhp_state_remove_instance(iommu_cpuhp_slot, &iommu_pmu->cpuhp_node);
852+
833853
if (--nr_iommu_pmu)
834854
return;
835855

836-
cpuhp_remove_state(CPUHP_AP_PERF_X86_IOMMU_PERF_ONLINE);
856+
cpuhp_remove_multi_state(iommu_cpuhp_slot);
837857
}
838858

839859
void iommu_pmu_register(struct intel_iommu *iommu)

include/linux/cpuhotplug.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,6 @@ enum cpuhp_state {
218218
CPUHP_AP_PERF_X86_CQM_ONLINE,
219219
CPUHP_AP_PERF_X86_CSTATE_ONLINE,
220220
CPUHP_AP_PERF_X86_IDXD_ONLINE,
221-
CPUHP_AP_PERF_X86_IOMMU_PERF_ONLINE,
222221
CPUHP_AP_PERF_S390_CF_ONLINE,
223222
CPUHP_AP_PERF_S390_SF_ONLINE,
224223
CPUHP_AP_PERF_ARM_CCI_ONLINE,

0 commit comments

Comments
 (0)