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:
Linus Torvalds 2023-04-01 09:17:33 -07:00
commit 92367fdf3b
7 changed files with 60 additions and 40 deletions

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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,