mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
IOMMU Fixes for Linux v6.3-rc4
Including: - 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 -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEr9jSbILcajRFYWYyK/BELZcBGuMFAmQoKpwACgkQK/BELZcB GuM4Aw//cxczRQcuEGF43yot+KRV9C3907yM3lZe8Yii/Ow6v3i/uAhic0vGLXDL uCGpcuBEWZdJ4C4/I7MOwuggcPql+kKYDutJ7t8c5cy/iQY9EkTC8XwG8NdePxp2 T46dTAjlP6fyB/1hvXhjb4s8VpaHhlTfP5SnSfnH0odxGj0ZHTWTcGrrZ/szuWha YuIR5DSKIA2eRR/gu8kXUKaEhPZ3DUKB5kU1qQxZqZhz7tiqJOOIqT0H1kFpngNd pgfqGFzTLPcReSViGW7lXmKax7mUJY9NBzCrPWdvT6tZoKIgxuPc2HO+9giy70Up o2hgyKJXxN7988OseWMm6Xexz/jvfuTHOOfh7m+Zgxu35zcQRo2RbYy6bbuwEmw+ 3kFe9wwmJ8qULI0QdRN0k2FSAuBg2WsHRDZQgvBMXu9Q3pbBNl3Fvl7BiFOQxlqq Se6kwmcDUwgdWTp1FqAp/T5ireGsIEfYYDUBTA1ZZV4kXOrNEkUmvc97zqNg9Hln MLrLRUY3PmfhrIUSx7ywhSB248mDbDppnTAyf7sUFEArHCfI6MdvOHtKSG5/H9gQ 1qHEW+iDv0dP8PtImCfKD+Dt7RmpkAFkBhCbZI3WI6AAQI/PD3uABmb0q5NwJxvh K7d84q9bi9O4l86mVl6BaCDtEOBRun0kEZ7r2653/s3B1MW+HU4= =ndWV -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
92367fdf3b
@ -18288,8 +18288,9 @@ F: drivers/s390/block/dasd*
|
||||
F: include/linux/dasd_mod.h
|
||||
|
||||
S390 IOMMU (PCI)
|
||||
M: Niklas Schnelle <schnelle@linux.ibm.com>
|
||||
M: Matthew Rosato <mjrosato@linux.ibm.com>
|
||||
M: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
|
||||
R: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
|
||||
L: linux-s390@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/iommu/s390-iommu.c
|
||||
|
@ -1415,23 +1415,26 @@ static struct iommu_device *exynos_iommu_probe_device(struct device *dev)
|
||||
return &data->iommu;
|
||||
}
|
||||
|
||||
static void exynos_iommu_release_device(struct device *dev)
|
||||
static void exynos_iommu_set_platform_dma(struct device *dev)
|
||||
{
|
||||
struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev);
|
||||
struct sysmmu_drvdata *data;
|
||||
|
||||
if (owner->domain) {
|
||||
struct iommu_group *group = iommu_group_get(dev);
|
||||
|
||||
if (group) {
|
||||
#ifndef CONFIG_ARM
|
||||
WARN_ON(owner->domain !=
|
||||
iommu_group_default_domain(group));
|
||||
#endif
|
||||
exynos_iommu_detach_device(owner->domain, dev);
|
||||
iommu_group_put(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void exynos_iommu_release_device(struct device *dev)
|
||||
{
|
||||
struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev);
|
||||
struct sysmmu_drvdata *data;
|
||||
|
||||
exynos_iommu_set_platform_dma(dev);
|
||||
|
||||
list_for_each_entry(data, &owner->controllers, owner_node)
|
||||
device_link_del(data->link);
|
||||
@ -1479,7 +1482,7 @@ static const struct iommu_ops exynos_iommu_ops = {
|
||||
.domain_alloc = exynos_iommu_domain_alloc,
|
||||
.device_group = generic_device_group,
|
||||
#ifdef CONFIG_ARM
|
||||
.set_platform_dma_ops = exynos_iommu_release_device,
|
||||
.set_platform_dma_ops = exynos_iommu_set_platform_dma,
|
||||
#endif
|
||||
.probe_device = exynos_iommu_probe_device,
|
||||
.release_device = exynos_iommu_release_device,
|
||||
|
@ -1071,7 +1071,8 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
|
||||
}
|
||||
|
||||
err = -EINVAL;
|
||||
if (cap_sagaw(iommu->cap) == 0) {
|
||||
if (!cap_sagaw(iommu->cap) &&
|
||||
(!ecap_smts(iommu->ecap) || ecap_slts(iommu->ecap))) {
|
||||
pr_info("%s: No supported address widths. Not attempting DMA translation.\n",
|
||||
iommu->name);
|
||||
drhd->ignored = 1;
|
||||
|
@ -641,6 +641,8 @@ struct iommu_pmu {
|
||||
DECLARE_BITMAP(used_mask, IOMMU_PMU_IDX_MAX);
|
||||
struct perf_event *event_list[IOMMU_PMU_IDX_MAX];
|
||||
unsigned char irq_name[16];
|
||||
struct hlist_node cpuhp_node;
|
||||
int cpu;
|
||||
};
|
||||
|
||||
#define IOMMU_IRQ_ID_OFFSET_PRQ (DMAR_UNITS_SUPPORTED)
|
||||
|
@ -311,14 +311,12 @@ static int set_ioapic_sid(struct irte *irte, int apic)
|
||||
if (!irte)
|
||||
return -1;
|
||||
|
||||
down_read(&dmar_global_lock);
|
||||
for (i = 0; i < MAX_IO_APICS; i++) {
|
||||
if (ir_ioapic[i].iommu && ir_ioapic[i].id == apic) {
|
||||
sid = (ir_ioapic[i].bus << 8) | ir_ioapic[i].devfn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
up_read(&dmar_global_lock);
|
||||
|
||||
if (sid == 0) {
|
||||
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)
|
||||
if (!irte)
|
||||
return -1;
|
||||
|
||||
down_read(&dmar_global_lock);
|
||||
for (i = 0; i < MAX_HPET_TBS; i++) {
|
||||
if (ir_hpet[i].iommu && ir_hpet[i].id == id) {
|
||||
sid = (ir_hpet[i].bus << 8) | ir_hpet[i].devfn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
up_read(&dmar_global_lock);
|
||||
|
||||
if (sid == 0) {
|
||||
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,
|
||||
if (!data)
|
||||
goto out_free_parent;
|
||||
|
||||
down_read(&dmar_global_lock);
|
||||
index = alloc_irte(iommu, &data->irq_2_iommu, nr_irqs);
|
||||
up_read(&dmar_global_lock);
|
||||
if (index < 0) {
|
||||
pr_warn("Failed to allocate IRTE\n");
|
||||
kfree(data);
|
||||
|
@ -773,19 +773,34 @@ static void iommu_pmu_unset_interrupt(struct intel_iommu *iommu)
|
||||
iommu->perf_irq = 0;
|
||||
}
|
||||
|
||||
static int iommu_pmu_cpu_online(unsigned int cpu)
|
||||
static int iommu_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
|
||||
{
|
||||
struct iommu_pmu *iommu_pmu = hlist_entry_safe(node, typeof(*iommu_pmu), cpuhp_node);
|
||||
|
||||
if (cpumask_empty(&iommu_pmu_cpu_mask))
|
||||
cpumask_set_cpu(cpu, &iommu_pmu_cpu_mask);
|
||||
|
||||
if (cpumask_test_cpu(cpu, &iommu_pmu_cpu_mask))
|
||||
iommu_pmu->cpu = cpu;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iommu_pmu_cpu_offline(unsigned int cpu)
|
||||
static int iommu_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
|
||||
{
|
||||
struct dmar_drhd_unit *drhd;
|
||||
struct intel_iommu *iommu;
|
||||
int target;
|
||||
struct iommu_pmu *iommu_pmu = hlist_entry_safe(node, typeof(*iommu_pmu), cpuhp_node);
|
||||
int target = cpumask_first(&iommu_pmu_cpu_mask);
|
||||
|
||||
/*
|
||||
* The iommu_pmu_cpu_mask has been updated when offline the CPU
|
||||
* for the first iommu_pmu. Migrate the other iommu_pmu to the
|
||||
* new target.
|
||||
*/
|
||||
if (target < nr_cpu_ids && target != iommu_pmu->cpu) {
|
||||
perf_pmu_migrate_context(&iommu_pmu->pmu, cpu, target);
|
||||
iommu_pmu->cpu = target;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!cpumask_test_and_clear_cpu(cpu, &iommu_pmu_cpu_mask))
|
||||
return 0;
|
||||
@ -795,45 +810,50 @@ static int iommu_pmu_cpu_offline(unsigned int cpu)
|
||||
if (target < nr_cpu_ids)
|
||||
cpumask_set_cpu(target, &iommu_pmu_cpu_mask);
|
||||
else
|
||||
target = -1;
|
||||
return 0;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
for_each_iommu(iommu, drhd) {
|
||||
if (!iommu->pmu)
|
||||
continue;
|
||||
perf_pmu_migrate_context(&iommu->pmu->pmu, cpu, target);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
perf_pmu_migrate_context(&iommu_pmu->pmu, cpu, target);
|
||||
iommu_pmu->cpu = target;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nr_iommu_pmu;
|
||||
static enum cpuhp_state iommu_cpuhp_slot;
|
||||
|
||||
static int iommu_pmu_cpuhp_setup(struct iommu_pmu *iommu_pmu)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (nr_iommu_pmu++)
|
||||
return 0;
|
||||
if (!nr_iommu_pmu) {
|
||||
ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
|
||||
"driver/iommu/intel/perfmon:online",
|
||||
iommu_pmu_cpu_online,
|
||||
iommu_pmu_cpu_offline);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
iommu_cpuhp_slot = ret;
|
||||
}
|
||||
|
||||
ret = cpuhp_setup_state(CPUHP_AP_PERF_X86_IOMMU_PERF_ONLINE,
|
||||
"driver/iommu/intel/perfmon:online",
|
||||
iommu_pmu_cpu_online,
|
||||
iommu_pmu_cpu_offline);
|
||||
if (ret)
|
||||
nr_iommu_pmu = 0;
|
||||
ret = cpuhp_state_add_instance(iommu_cpuhp_slot, &iommu_pmu->cpuhp_node);
|
||||
if (ret) {
|
||||
if (!nr_iommu_pmu)
|
||||
cpuhp_remove_multi_state(iommu_cpuhp_slot);
|
||||
return ret;
|
||||
}
|
||||
nr_iommu_pmu++;
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iommu_pmu_cpuhp_free(struct iommu_pmu *iommu_pmu)
|
||||
{
|
||||
cpuhp_state_remove_instance(iommu_cpuhp_slot, &iommu_pmu->cpuhp_node);
|
||||
|
||||
if (--nr_iommu_pmu)
|
||||
return;
|
||||
|
||||
cpuhp_remove_state(CPUHP_AP_PERF_X86_IOMMU_PERF_ONLINE);
|
||||
cpuhp_remove_multi_state(iommu_cpuhp_slot);
|
||||
}
|
||||
|
||||
void iommu_pmu_register(struct intel_iommu *iommu)
|
||||
|
@ -218,7 +218,6 @@ enum cpuhp_state {
|
||||
CPUHP_AP_PERF_X86_CQM_ONLINE,
|
||||
CPUHP_AP_PERF_X86_CSTATE_ONLINE,
|
||||
CPUHP_AP_PERF_X86_IDXD_ONLINE,
|
||||
CPUHP_AP_PERF_X86_IOMMU_PERF_ONLINE,
|
||||
CPUHP_AP_PERF_S390_CF_ONLINE,
|
||||
CPUHP_AP_PERF_S390_SF_ONLINE,
|
||||
CPUHP_AP_PERF_ARM_CCI_ONLINE,
|
||||
|
Loading…
Reference in New Issue
Block a user