[PATCH v3 4/8] genirq: Drop redundant irq_init_effective_affinity

2022-07-01 Thread Samuel Holland
It does exactly the same thing as irq_data_update_effective_affinity.

Signed-off-by: Samuel Holland 
---

Changes in v3:
 - New patch to drop irq_init_effective_affinity

 kernel/irq/manage.c | 10 +-
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 8c396319d5ac..40fe7806cc8c 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -205,16 +205,8 @@ static void irq_validate_effective_affinity(struct 
irq_data *data)
pr_warn_once("irq_chip %s did not update eff. affinity mask of irq 
%u\n",
 chip->name, data->irq);
 }
-
-static inline void irq_init_effective_affinity(struct irq_data *data,
-  const struct cpumask *mask)
-{
-   cpumask_copy(irq_data_get_effective_affinity_mask(data), mask);
-}
 #else
 static inline void irq_validate_effective_affinity(struct irq_data *data) { }
-static inline void irq_init_effective_affinity(struct irq_data *data,
-  const struct cpumask *mask) { }
 #endif
 
 int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask,
@@ -347,7 +339,7 @@ static bool irq_set_affinity_deactivated(struct irq_data 
*data,
return false;
 
cpumask_copy(desc->irq_common_data.affinity, mask);
-   irq_init_effective_affinity(data, mask);
+   irq_data_update_effective_affinity(data, mask);
irqd_set(data, IRQD_AFFINITY_SET);
return true;
 }
-- 
2.35.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 6/8] genirq: Add and use an irq_data_update_affinity helper

2022-07-01 Thread Samuel Holland
Some architectures and irqchip drivers modify the cpumask returned by
irq_data_get_affinity_mask, usually by copying in to it. This is
problematic for uniprocessor configurations, where the affinity mask
should be constant, as it is known at compile time.

Add and use a setter for the affinity mask, following the pattern of
irq_data_update_effective_affinity. This allows the getter function to
return a const cpumask pointer.

Signed-off-by: Samuel Holland 
---

Changes in v3:
 - New patch to introduce irq_data_update_affinity

 arch/alpha/kernel/irq.c  | 2 +-
 arch/ia64/kernel/iosapic.c   | 2 +-
 arch/ia64/kernel/irq.c   | 4 ++--
 arch/ia64/kernel/msi_ia64.c  | 4 ++--
 arch/parisc/kernel/irq.c | 2 +-
 drivers/irqchip/irq-bcm6345-l1.c | 4 ++--
 drivers/parisc/iosapic.c | 2 +-
 drivers/sh/intc/chip.c   | 2 +-
 drivers/xen/events/events_base.c | 7 ---
 include/linux/irq.h  | 6 ++
 10 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index f6d2946edbd2..15f2effd6baf 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -60,7 +60,7 @@ int irq_select_affinity(unsigned int irq)
cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0);
last_cpu = cpu;
 
-   cpumask_copy(irq_data_get_affinity_mask(data), cpumask_of(cpu));
+   irq_data_update_affinity(data, cpumask_of(cpu));
chip->irq_set_affinity(data, cpumask_of(cpu), false);
return 0;
 }
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 35adcf89035a..99300850abc1 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -834,7 +834,7 @@ iosapic_unregister_intr (unsigned int gsi)
if (iosapic_intr_info[irq].count == 0) {
 #ifdef CONFIG_SMP
/* Clear affinity */
-   cpumask_setall(irq_get_affinity_mask(irq));
+   irq_data_update_affinity(irq_get_irq_data(irq), cpu_all_mask);
 #endif
/* Clear the interrupt information */
iosapic_intr_info[irq].dest = 0;
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index ecef17c7c35b..275b9ea58c64 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -57,8 +57,8 @@ static char irq_redir [NR_IRQS]; // = { [0 ... NR_IRQS-1] = 1 
};
 void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
 {
if (irq < NR_IRQS) {
-   cpumask_copy(irq_get_affinity_mask(irq),
-cpumask_of(cpu_logical_id(hwid)));
+   irq_data_update_affinity(irq_get_irq_data(irq),
+cpumask_of(cpu_logical_id(hwid)));
irq_redir[irq] = (char) (redir & 0xff);
}
 }
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c
index df5c28f252e3..025e5133c860 100644
--- a/arch/ia64/kernel/msi_ia64.c
+++ b/arch/ia64/kernel/msi_ia64.c
@@ -37,7 +37,7 @@ static int ia64_set_msi_irq_affinity(struct irq_data *idata,
msg.data = data;
 
pci_write_msi_msg(irq, );
-   cpumask_copy(irq_data_get_affinity_mask(idata), cpumask_of(cpu));
+   irq_data_update_affinity(idata, cpumask_of(cpu));
 
return 0;
 }
@@ -132,7 +132,7 @@ static int dmar_msi_set_affinity(struct irq_data *data,
msg.address_lo |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu));
 
dmar_msi_write(irq, );
-   cpumask_copy(irq_data_get_affinity_mask(data), mask);
+   irq_data_update_affinity(data, mask);
 
return 0;
 }
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index 0fe2d79fb123..5ebb1771b4ab 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -315,7 +315,7 @@ unsigned long txn_affinity_addr(unsigned int irq, int cpu)
 {
 #ifdef CONFIG_SMP
struct irq_data *d = irq_get_irq_data(irq);
-   cpumask_copy(irq_data_get_affinity_mask(d), cpumask_of(cpu));
+   irq_data_update_affinity(d, cpumask_of(cpu));
 #endif
 
return per_cpu(cpu_data, cpu).txn_addr;
diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c
index 142a7431745f..6899e37810a8 100644
--- a/drivers/irqchip/irq-bcm6345-l1.c
+++ b/drivers/irqchip/irq-bcm6345-l1.c
@@ -216,11 +216,11 @@ static int bcm6345_l1_set_affinity(struct irq_data *d,
enabled = intc->cpus[old_cpu]->enable_cache[word] & mask;
if (enabled)
__bcm6345_l1_mask(d);
-   cpumask_copy(irq_data_get_affinity_mask(d), dest);
+   irq_data_update_affinity(d, dest);
if (enabled)
__bcm6345_l1_unmask(d);
} else {
-   cpumask_copy(irq_data_get_affinity_mask(d), dest);
+   irq_data_update_affinity(d, dest);
}
raw_spin_unlock_irqrestore(>lock, flags);
 
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 

[PATCH v3 7/8] genirq: Return a const cpumask from irq_data_get_affinity_mask

2022-07-01 Thread Samuel Holland
Now that the irq_data_update_affinity helper exists, enforce its use
by returning a a const cpumask from irq_data_get_affinity_mask.

Since the previous commit already updated places that needed to call
irq_data_update_affinity, this commit updates the remaining code that
either did not modify the cpumask or immediately passed the modified
mask to irq_set_affinity.

Signed-off-by: Samuel Holland 
---

Changes in v3:
 - New patch to make the returned cpumasks const

 arch/mips/cavium-octeon/octeon-irq.c |  4 ++--
 arch/sh/kernel/irq.c |  7 ---
 arch/x86/hyperv/irqdomain.c  |  2 +-
 arch/xtensa/kernel/irq.c |  7 ---
 drivers/iommu/hyperv-iommu.c |  2 +-
 drivers/pci/controller/pci-hyperv.c  | 10 +-
 include/linux/irq.h  | 12 +++-
 kernel/irq/chip.c|  8 +---
 kernel/irq/debugfs.c |  2 +-
 kernel/irq/ipi.c | 16 +---
 10 files changed, 39 insertions(+), 31 deletions(-)

diff --git a/arch/mips/cavium-octeon/octeon-irq.c 
b/arch/mips/cavium-octeon/octeon-irq.c
index 6cdcbf4de763..9cb9ed44bcaf 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -263,7 +263,7 @@ static int next_cpu_for_irq(struct irq_data *data)
 
 #ifdef CONFIG_SMP
int cpu;
-   struct cpumask *mask = irq_data_get_affinity_mask(data);
+   const struct cpumask *mask = irq_data_get_affinity_mask(data);
int weight = cpumask_weight(mask);
struct octeon_ciu_chip_data *cd = irq_data_get_irq_chip_data(data);
 
@@ -758,7 +758,7 @@ static void octeon_irq_cpu_offline_ciu(struct irq_data 
*data)
 {
int cpu = smp_processor_id();
cpumask_t new_affinity;
-   struct cpumask *mask = irq_data_get_affinity_mask(data);
+   const struct cpumask *mask = irq_data_get_affinity_mask(data);
 
if (!cpumask_test_cpu(cpu, mask))
return;
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index ef0f0827cf57..56269c2c3414 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -230,16 +230,17 @@ void migrate_irqs(void)
struct irq_data *data = irq_get_irq_data(irq);
 
if (irq_data_get_node(data) == cpu) {
-   struct cpumask *mask = irq_data_get_affinity_mask(data);
+   const struct cpumask *mask = 
irq_data_get_affinity_mask(data);
unsigned int newcpu = cpumask_any_and(mask,
  cpu_online_mask);
if (newcpu >= nr_cpu_ids) {
pr_info_ratelimited("IRQ%u no longer affine to 
CPU%u\n",
irq, cpu);
 
-   cpumask_setall(mask);
+   irq_set_affinity(irq, cpu_all_mask);
+   } else {
+   irq_set_affinity(irq, mask);
}
-   irq_set_affinity(irq, mask);
}
}
 }
diff --git a/arch/x86/hyperv/irqdomain.c b/arch/x86/hyperv/irqdomain.c
index 7e0f6bedc248..42c70d28ef27 100644
--- a/arch/x86/hyperv/irqdomain.c
+++ b/arch/x86/hyperv/irqdomain.c
@@ -192,7 +192,7 @@ static void hv_irq_compose_msi_msg(struct irq_data *data, 
struct msi_msg *msg)
struct pci_dev *dev;
struct hv_interrupt_entry out_entry, *stored_entry;
struct irq_cfg *cfg = irqd_cfg(data);
-   cpumask_t *affinity;
+   const cpumask_t *affinity;
int cpu;
u64 status;
 
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c
index 529fe9245821..42f106004400 100644
--- a/arch/xtensa/kernel/irq.c
+++ b/arch/xtensa/kernel/irq.c
@@ -169,7 +169,7 @@ void migrate_irqs(void)
 
for_each_active_irq(i) {
struct irq_data *data = irq_get_irq_data(i);
-   struct cpumask *mask;
+   const struct cpumask *mask;
unsigned int newcpu;
 
if (irqd_is_per_cpu(data))
@@ -185,9 +185,10 @@ void migrate_irqs(void)
pr_info_ratelimited("IRQ%u no longer affine to CPU%u\n",
i, cpu);
 
-   cpumask_setall(mask);
+   irq_set_affinity(i, cpu_all_mask);
+   } else {
+   irq_set_affinity(i, mask);
}
-   irq_set_affinity(i, mask);
}
 }
 #endif /* CONFIG_HOTPLUG_CPU */
diff --git a/drivers/iommu/hyperv-iommu.c b/drivers/iommu/hyperv-iommu.c
index e285a220c913..51bd66a45a11 100644
--- a/drivers/iommu/hyperv-iommu.c
+++ b/drivers/iommu/hyperv-iommu.c
@@ -194,7 +194,7 @@ hyperv_root_ir_compose_msi_msg(struct irq_data *irq_data, 
struct msi_msg *msg)
u32 vector;
struct irq_cfg *cfg;
int ioapic_id;
-   s

[PATCH v3 5/8] genirq: Refactor accessors to use irq_data_get_affinity_mask

2022-07-01 Thread Samuel Holland
A couple of functions directly reference the affinity mask. Route them
through irq_data_get_affinity_mask so they will pick up any refactoring
done there.

Signed-off-by: Samuel Holland 
---

(no changes since v1)

 include/linux/irq.h | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 505308253d23..69ee4e2f36ce 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -879,16 +879,16 @@ static inline int irq_data_get_node(struct irq_data *d)
return irq_common_data_get_node(d->common);
 }
 
-static inline struct cpumask *irq_get_affinity_mask(int irq)
+static inline struct cpumask *irq_data_get_affinity_mask(struct irq_data *d)
 {
-   struct irq_data *d = irq_get_irq_data(irq);
-
-   return d ? d->common->affinity : NULL;
+   return d->common->affinity;
 }
 
-static inline struct cpumask *irq_data_get_affinity_mask(struct irq_data *d)
+static inline struct cpumask *irq_get_affinity_mask(int irq)
 {
-   return d->common->affinity;
+   struct irq_data *d = irq_get_irq_data(irq);
+
+   return d ? irq_data_get_affinity_mask(d) : NULL;
 }
 
 #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
@@ -910,7 +910,7 @@ static inline void 
irq_data_update_effective_affinity(struct irq_data *d,
 static inline
 struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d)
 {
-   return d->common->affinity;
+   return irq_data_get_affinity_mask(d);
 }
 #endif
 
-- 
2.35.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 1/8] irqchip/mips-gic: Only register IPI domain when SMP is enabled

2022-07-01 Thread Samuel Holland
The MIPS GIC irqchip driver may be selected in a uniprocessor
configuration, but it unconditionally registers an IPI domain.

Limit the part of the driver dealing with IPIs to only be compiled when
GENERIC_IRQ_IPI is enabled, which corresponds to an SMP configuration.

Reported-by: kernel test robot 
Signed-off-by: Samuel Holland 
---

Changes in v3:
 - New patch to fix build errors in uniprocessor MIPS configs

 drivers/irqchip/Kconfig|  3 +-
 drivers/irqchip/irq-mips-gic.c | 80 +++---
 2 files changed, 56 insertions(+), 27 deletions(-)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 1f23a6be7d88..d26a4ff7c99f 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -322,7 +322,8 @@ config KEYSTONE_IRQ
 
 config MIPS_GIC
bool
-   select GENERIC_IRQ_IPI
+   select GENERIC_IRQ_IPI if SMP
+   select IRQ_DOMAIN_HIERARCHY
select MIPS_CM
 
 config INGENIC_IRQ
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index ff89b36267dd..8a9efb6ae587 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -52,13 +52,15 @@ static DEFINE_PER_CPU_READ_MOSTLY(unsigned 
long[GIC_MAX_LONGS], pcpu_masks);
 
 static DEFINE_SPINLOCK(gic_lock);
 static struct irq_domain *gic_irq_domain;
-static struct irq_domain *gic_ipi_domain;
 static int gic_shared_intrs;
 static unsigned int gic_cpu_pin;
 static unsigned int timer_cpu_pin;
 static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller;
+
+#ifdef CONFIG_GENERIC_IRQ_IPI
 static DECLARE_BITMAP(ipi_resrv, GIC_MAX_INTRS);
 static DECLARE_BITMAP(ipi_available, GIC_MAX_INTRS);
+#endif /* CONFIG_GENERIC_IRQ_IPI */
 
 static struct gic_all_vpes_chip_data {
u32 map;
@@ -472,9 +474,11 @@ static int gic_irq_domain_map(struct irq_domain *d, 
unsigned int virq,
u32 map;
 
if (hwirq >= GIC_SHARED_HWIRQ_BASE) {
+#ifdef CONFIG_GENERIC_IRQ_IPI
/* verify that shared irqs don't conflict with an IPI irq */
if (test_bit(GIC_HWIRQ_TO_SHARED(hwirq), ipi_resrv))
return -EBUSY;
+#endif /* CONFIG_GENERIC_IRQ_IPI */
 
err = irq_domain_set_hwirq_and_chip(d, virq, hwirq,
_level_irq_controller,
@@ -567,6 +571,8 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
.map = gic_irq_domain_map,
 };
 
+#ifdef CONFIG_GENERIC_IRQ_IPI
+
 static int gic_ipi_domain_xlate(struct irq_domain *d, struct device_node 
*ctrlr,
const u32 *intspec, unsigned int intsize,
irq_hw_number_t *out_hwirq,
@@ -670,6 +676,48 @@ static const struct irq_domain_ops gic_ipi_domain_ops = {
.match = gic_ipi_domain_match,
 };
 
+static int gic_register_ipi_domain(struct device_node *node)
+{
+   struct irq_domain *gic_ipi_domain;
+   unsigned int v[2], num_ipis;
+
+   gic_ipi_domain = irq_domain_add_hierarchy(gic_irq_domain,
+ IRQ_DOMAIN_FLAG_IPI_PER_CPU,
+ GIC_NUM_LOCAL_INTRS + 
gic_shared_intrs,
+ node, _ipi_domain_ops, 
NULL);
+   if (!gic_ipi_domain) {
+   pr_err("Failed to add IPI domain");
+   return -ENXIO;
+   }
+
+   irq_domain_update_bus_token(gic_ipi_domain, DOMAIN_BUS_IPI);
+
+   if (node &&
+   !of_property_read_u32_array(node, "mti,reserved-ipi-vectors", v, 
2)) {
+   bitmap_set(ipi_resrv, v[0], v[1]);
+   } else {
+   /*
+* Reserve 2 interrupts per possible CPU/VP for use as IPIs,
+* meeting the requirements of arch/mips SMP.
+*/
+   num_ipis = 2 * num_possible_cpus();
+   bitmap_set(ipi_resrv, gic_shared_intrs - num_ipis, num_ipis);
+   }
+
+   bitmap_copy(ipi_available, ipi_resrv, GIC_MAX_INTRS);
+
+   return 0;
+}
+
+#else /* !CONFIG_GENERIC_IRQ_IPI */
+
+static inline int gic_register_ipi_domain(struct device_node *node)
+{
+   return 0;
+}
+
+#endif /* !CONFIG_GENERIC_IRQ_IPI */
+
 static int gic_cpu_startup(unsigned int cpu)
 {
/* Enable or disable EIC */
@@ -688,11 +736,12 @@ static int gic_cpu_startup(unsigned int cpu)
 static int __init gic_of_init(struct device_node *node,
  struct device_node *parent)
 {
-   unsigned int cpu_vec, i, gicconfig, v[2], num_ipis;
+   unsigned int cpu_vec, i, gicconfig;
unsigned long reserved;
phys_addr_t gic_base;
struct resource res;
size_t gic_len;
+   int ret;
 
/* Find the first available CPU vector. */
i = 0;
@@ -780,30 +829,9 @@ static int __init gic_of_init(struct device_node *node,
return -ENXIO;
}
 
-   gic_ipi_do

[PATCH v3 2/8] genirq: GENERIC_IRQ_IPI depends on SMP

2022-07-01 Thread Samuel Holland
The generic IPI code depends on the IRQ affinity mask being allocated
and initialized. This will not be the case if SMP is disabled. Fix up
the remaining driver that selected GENERIC_IRQ_IPI in a non-SMP config.

Reported-by: kernel test robot 
Signed-off-by: Samuel Holland 
---

(no changes since v2)

Changes in v2:
 - New patch to prevent GENERIC_IRQ_IPI from being selected on !SMP

 drivers/irqchip/Kconfig | 2 +-
 kernel/irq/Kconfig  | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index d26a4ff7c99f..5dd98a81efc8 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -177,7 +177,7 @@ config MADERA_IRQ
 config IRQ_MIPS_CPU
bool
select GENERIC_IRQ_CHIP
-   select GENERIC_IRQ_IPI if SYS_SUPPORTS_MULTITHREADING
+   select GENERIC_IRQ_IPI if SMP && SYS_SUPPORTS_MULTITHREADING
select IRQ_DOMAIN
select GENERIC_IRQ_EFFECTIVE_AFF_MASK
 
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index 10929eda9825..fc760d064a65 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -82,6 +82,7 @@ config IRQ_FASTEOI_HIERARCHY_HANDLERS
 # Generic IRQ IPI support
 config GENERIC_IRQ_IPI
bool
+   depends on SMP
select IRQ_DOMAIN_HIERARCHY
 
 # Generic MSI interrupt support
-- 
2.35.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 3/8] genirq: GENERIC_IRQ_EFFECTIVE_AFF_MASK depends on SMP

2022-07-01 Thread Samuel Holland
An IRQ's effective affinity can only be different from its configured
affinity if there are multiple CPUs. Make it clear that this option is
only meaningful when SMP is enabled. Most of the relevant code in
irqdesc.c is already hidden behind CONFIG_SMP anyway.

Signed-off-by: Samuel Holland 
---

(no changes since v1)

 arch/arm/mach-hisi/Kconfig |  2 +-
 drivers/irqchip/Kconfig| 14 +++---
 kernel/irq/Kconfig |  1 +
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig
index 75cccbd3f05f..7b3440687176 100644
--- a/arch/arm/mach-hisi/Kconfig
+++ b/arch/arm/mach-hisi/Kconfig
@@ -40,7 +40,7 @@ config ARCH_HIP04
select HAVE_ARM_ARCH_TIMER
select MCPM if SMP
select MCPM_QUAD_CLUSTER if SMP
-   select GENERIC_IRQ_EFFECTIVE_AFF_MASK
+   select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
help
  Support for Hisilicon HiP04 SoC family
 
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 5dd98a81efc8..462adac905a6 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -8,7 +8,7 @@ config IRQCHIP
 config ARM_GIC
bool
select IRQ_DOMAIN_HIERARCHY
-   select GENERIC_IRQ_EFFECTIVE_AFF_MASK
+   select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
 
 config ARM_GIC_PM
bool
@@ -34,7 +34,7 @@ config ARM_GIC_V3
bool
select IRQ_DOMAIN_HIERARCHY
select PARTITION_PERCPU
-   select GENERIC_IRQ_EFFECTIVE_AFF_MASK
+   select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
 
 config ARM_GIC_V3_ITS
bool
@@ -76,7 +76,7 @@ config ARMADA_370_XP_IRQ
bool
select GENERIC_IRQ_CHIP
select PCI_MSI if PCI
-   select GENERIC_IRQ_EFFECTIVE_AFF_MASK
+   select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
 
 config ALPINE_MSI
bool
@@ -112,7 +112,7 @@ config BCM6345_L1_IRQ
bool
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
-   select GENERIC_IRQ_EFFECTIVE_AFF_MASK
+   select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
 
 config BCM7038_L1_IRQ
tristate "Broadcom STB 7038-style L1/L2 interrupt controller driver"
@@ -120,7 +120,7 @@ config BCM7038_L1_IRQ
default ARCH_BRCMSTB || BMIPS_GENERIC
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
-   select GENERIC_IRQ_EFFECTIVE_AFF_MASK
+   select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
 
 config BCM7120_L2_IRQ
tristate "Broadcom STB 7120-style L2 interrupt controller driver"
@@ -179,7 +179,7 @@ config IRQ_MIPS_CPU
select GENERIC_IRQ_CHIP
select GENERIC_IRQ_IPI if SMP && SYS_SUPPORTS_MULTITHREADING
select IRQ_DOMAIN
-   select GENERIC_IRQ_EFFECTIVE_AFF_MASK
+   select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
 
 config CLPS711X_IRQCHIP
bool
@@ -294,7 +294,7 @@ config VERSATILE_FPGA_IRQ_NR
 config XTENSA_MX
bool
select IRQ_DOMAIN
-   select GENERIC_IRQ_EFFECTIVE_AFF_MASK
+   select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
 
 config XILINX_INTC
bool "Xilinx Interrupt Controller IP"
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index fc760d064a65..db3d174c53d4 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -24,6 +24,7 @@ config GENERIC_IRQ_SHOW_LEVEL
 
 # Supports effective affinity mask
 config GENERIC_IRQ_EFFECTIVE_AFF_MASK
+   depends on SMP
bool
 
 # Support for delayed migration from interrupt context
-- 
2.35.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 0/8] genirq: Provide real IRQ affinity masks in non-SMP configs

2022-07-01 Thread Samuel Holland
This series solves some inconsistency with how IRQ affinity masks are
handled between SMP and non-SMP configurations.

In non-SMP configs, an IRQ's true affinity is always cpumask_of(0), so
irq_{,data_}get_affinity_mask now return that, instead of returning an
uninitialized per-IRQ cpumask. This change makes iterating over the
affinity mask do the right thing in both SMP and non-SMP configurations.

To accomplish that:
 - patches 1-3 disable some library code that was broken anyway on !SMP
 - patches 4-7 refactor the code so that irq_{,data_}get_affinity_mask
   can return a const cpumask, since that is what cpumask_of provides
 - patch 8 drops the per-IRQ cpumask and replaces it with cpumask_of(0)

This series was split from the v2 series here, which uses the new
behavior in the RISC-V PLIC irqchip driver:

https://lore.kernel.org/lkml/20220616064028.57933-1-sam...@sholland.org/

Changes in v3:
 - New patch to fix build errors in uniprocessor MIPS configs
 - New patch to drop irq_init_effective_affinity
 - New patch to introduce irq_data_update_affinity
 - New patch to make the returned cpumasks const
 - Use cpumask_of(0) instead of cpu_possible_mask

Changes in v2:
 - New patch to prevent GENERIC_IRQ_IPI from being selected on !SMP

Samuel Holland (8):
  irqchip/mips-gic: Only register IPI domain when SMP is enabled
  genirq: GENERIC_IRQ_IPI depends on SMP
  genirq: GENERIC_IRQ_EFFECTIVE_AFF_MASK depends on SMP
  genirq: Drop redundant irq_init_effective_affinity
  genirq: Refactor accessors to use irq_data_get_affinity_mask
  genirq: Add and use an irq_data_update_affinity helper
  genirq: Return a const cpumask from irq_data_get_affinity_mask
  genirq: Provide an IRQ affinity mask in non-SMP configs

 arch/alpha/kernel/irq.c  |  2 +-
 arch/arm/mach-hisi/Kconfig   |  2 +-
 arch/ia64/kernel/iosapic.c   |  2 +-
 arch/ia64/kernel/irq.c   |  4 +-
 arch/ia64/kernel/msi_ia64.c  |  4 +-
 arch/mips/cavium-octeon/octeon-irq.c |  4 +-
 arch/parisc/kernel/irq.c |  2 +-
 arch/sh/kernel/irq.c |  7 +--
 arch/x86/hyperv/irqdomain.c  |  2 +-
 arch/xtensa/kernel/irq.c |  7 +--
 drivers/iommu/hyperv-iommu.c |  2 +-
 drivers/irqchip/Kconfig  | 19 +++
 drivers/irqchip/irq-bcm6345-l1.c |  4 +-
 drivers/irqchip/irq-mips-gic.c   | 80 +++-
 drivers/parisc/iosapic.c |  2 +-
 drivers/pci/controller/pci-hyperv.c  | 10 ++--
 drivers/sh/intc/chip.c   |  2 +-
 drivers/xen/events/events_base.c |  7 +--
 include/linux/irq.h  | 34 
 kernel/irq/Kconfig   |  2 +
 kernel/irq/chip.c|  8 +--
 kernel/irq/debugfs.c |  2 +-
 kernel/irq/ipi.c | 16 +++---
 kernel/irq/manage.c  | 10 +---
 24 files changed, 140 insertions(+), 94 deletions(-)

-- 
2.35.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 8/8] genirq: Provide an IRQ affinity mask in non-SMP configs

2022-07-01 Thread Samuel Holland
IRQ affinity masks are not allocated in uniprocessor configurations.
This requires special case non-SMP code in drivers for irqchips which
have per-CPU enable or mask registers.

Since IRQ affinity is always the same in a uniprocessor configuration,
we can provide a correct affinity mask without allocating one per IRQ.

By returning a real cpumask from irq_data_get_affinity_mask even when
SMP is disabled, irqchip drivers which iterate over that mask will
automatically do the right thing.

Signed-off-by: Samuel Holland 
---

Changes in v3:
 - Use cpumask_of(0) instead of cpu_possible_mask

 include/linux/irq.h | 8 
 1 file changed, 8 insertions(+)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 02073f7a156e..996e22744edd 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -151,7 +151,9 @@ struct irq_common_data {
 #endif
void*handler_data;
struct msi_desc *msi_desc;
+#ifdef CONFIG_SMP
cpumask_var_t   affinity;
+#endif
 #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
cpumask_var_t   effective_affinity;
 #endif
@@ -882,13 +884,19 @@ static inline int irq_data_get_node(struct irq_data *d)
 static inline
 const struct cpumask *irq_data_get_affinity_mask(struct irq_data *d)
 {
+#ifdef CONFIG_SMP
return d->common->affinity;
+#else
+   return cpumask_of(0);
+#endif
 }
 
 static inline void irq_data_update_affinity(struct irq_data *d,
const struct cpumask *m)
 {
+#ifdef CONFIG_SMP
cpumask_copy(d->common->affinity, m);
+#endif
 }
 
 static inline const struct cpumask *irq_get_affinity_mask(int irq)
-- 
2.35.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 4/5] iommu/sun50i: Add support for the D1 variant

2022-04-27 Thread Samuel Holland
D1 contains an IOMMU similar to the one in the H6 SoC, but the D1
variant has no external reset signal. It also has some register
definition changes, but none that affect the current driver.

Signed-off-by: Samuel Holland 
---

 drivers/iommu/sun50i-iommu.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
index b9e644b93637..1fb707e37fb3 100644
--- a/drivers/iommu/sun50i-iommu.c
+++ b/drivers/iommu/sun50i-iommu.c
@@ -999,11 +999,15 @@ static int sun50i_iommu_probe(struct platform_device 
*pdev)
return ret;
 }
 
+static const struct sun50i_iommu_variant sun20i_d1_iommu = {
+};
+
 static const struct sun50i_iommu_variant sun50i_h6_iommu = {
.has_reset = true,
 };
 
 static const struct of_device_id sun50i_iommu_dt[] = {
+   { .compatible = "allwinner,sun20i-d1-iommu", .data = _d1_iommu },
{ .compatible = "allwinner,sun50i-h6-iommu", .data = _h6_iommu },
{ /* sentinel */ },
 };
-- 
2.35.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 0/5] iommu/sun50i: Allwinner D1 support

2022-04-27 Thread Samuel Holland
D1 is a RISC-V SoC from Allwinner's sunxi family. This series adds IOMMU
binding and driver support.

One piece is still missing to use the IOMMU for DMA allocations: a call
to iommu_setup_dma_ops(). On ARM64 this is handled by the architecture's
code. RISC-V does not currently select ARCH_HAS_SETUP_DMA_OPS, but it
will once Zicbom support[1] is merged.

[1]: https://lore.kernel.org/lkml/20220307224620.1933061-2-he...@sntech.de/

So I cannot follow virtio-iommu.c and call iommu_setup_dma_ops() when
ARCH_HAS_SETUP_DMA_OPS=n. However, if I apply the following patch on top
of Heiko's non-coherent DMA series, the display engine successfully uses
the IOMMU to allocate its framebuffer:

--- a/arch/riscv/mm/dma-noncoherent.c
+++ b/arch/riscv/mm/dma-noncoherent.c
@@ -6,6 +6,7 @@
  */

 #include 
+#include 
 #include 
 #include 

@@ -53,4 +54,7 @@
 {
/* If a specific device is dma-coherent, set it here */
dev->dma_coherent = coherent;
+
+   if (iommu)
+   iommu_setup_dma_ops(dev, dma_base, dma_base + size - 1);
 }


Samuel Holland (5):
  dt-bindings: iommu: sun50i: Add compatible for Allwinner D1
  iommu/sun50i: Support variants without an external reset
  iommu/sun50i: Ensure bypass is disabled
  iommu/sun50i: Add support for the D1 variant
  iommu/sun50i: Ensure the IOMMU can be used for DMA

 .../iommu/allwinner,sun50i-h6-iommu.yaml  | 16 +++--
 drivers/iommu/Kconfig |  1 +
 drivers/iommu/sun50i-iommu.c  | 24 +--
 3 files changed, 37 insertions(+), 4 deletions(-)

-- 
2.35.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 3/5] iommu/sun50i: Ensure bypass is disabled

2022-04-27 Thread Samuel Holland
The H6 variant of the hardware disables bypass by default. The D1
variant of the hardware enables bypass for all masters by default.

Since the driver expects bypass to be disabled, ensure that is the case.

Signed-off-by: Samuel Holland 
---

 drivers/iommu/sun50i-iommu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
index ec07b60016d3..b9e644b93637 100644
--- a/drivers/iommu/sun50i-iommu.c
+++ b/drivers/iommu/sun50i-iommu.c
@@ -374,6 +374,8 @@ static int sun50i_iommu_enable(struct sun50i_iommu *iommu)
 
spin_lock_irqsave(>iommu_lock, flags);
 
+   iommu_write(iommu, IOMMU_BYPASS_REG, 0);
+
iommu_write(iommu, IOMMU_TTB_REG, sun50i_domain->dt_dma);
iommu_write(iommu, IOMMU_TLB_PREFETCH_REG,
IOMMU_TLB_PREFETCH_MASTER_ENABLE(0) |
-- 
2.35.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 1/5] dt-bindings: iommu: sun50i: Add compatible for Allwinner D1

2022-04-27 Thread Samuel Holland
D1 contains an IOMMU similar to the one in the H6 SoC, but the D1
variant has no external reset signal.

Signed-off-by: Samuel Holland 
---

 .../iommu/allwinner,sun50i-h6-iommu.yaml | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml 
b/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml
index 5e125cf2a88b..18d3451d4dd5 100644
--- a/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml
+++ b/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml
@@ -17,7 +17,9 @@ properties:
   The content of the cell is the master ID.
 
   compatible:
-const: allwinner,sun50i-h6-iommu
+enum:
+  - allwinner,sun20i-d1-iommu
+  - allwinner,sun50i-h6-iommu
 
   reg:
 maxItems: 1
@@ -37,7 +39,17 @@ required:
   - reg
   - interrupts
   - clocks
-  - resets
+
+if:
+  properties:
+compatible:
+  contains:
+enum:
+  - allwinner,sun50i-h6-iommu
+
+then:
+  required:
+- resets
 
 additionalProperties: false
 
-- 
2.35.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 2/5] iommu/sun50i: Support variants without an external reset

2022-04-27 Thread Samuel Holland
The IOMMU in the Allwinner D1 SoC does not have an external reset line.

Only attempt to get the reset on hardware variants which should have one
according to the binding. And switch from the deprecated function to the
explicit "exclusive" variant.

Signed-off-by: Samuel Holland 
---

 drivers/iommu/sun50i-iommu.c | 18 --
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
index c54ab477b8fd..ec07b60016d3 100644
--- a/drivers/iommu/sun50i-iommu.c
+++ b/drivers/iommu/sun50i-iommu.c
@@ -92,6 +92,10 @@
 #define NUM_PT_ENTRIES 256
 #define PT_SIZE(NUM_PT_ENTRIES * PT_ENTRY_SIZE)
 
+struct sun50i_iommu_variant {
+   bool has_reset;
+};
+
 struct sun50i_iommu {
struct iommu_device iommu;
 
@@ -905,9 +909,14 @@ static irqreturn_t sun50i_iommu_irq(int irq, void *dev_id)
 
 static int sun50i_iommu_probe(struct platform_device *pdev)
 {
+   const struct sun50i_iommu_variant *variant;
struct sun50i_iommu *iommu;
int ret, irq;
 
+   variant = of_device_get_match_data(>dev);
+   if (!variant)
+   return -EINVAL;
+
iommu = devm_kzalloc(>dev, sizeof(*iommu), GFP_KERNEL);
if (!iommu)
return -ENOMEM;
@@ -947,7 +956,8 @@ static int sun50i_iommu_probe(struct platform_device *pdev)
goto err_free_group;
}
 
-   iommu->reset = devm_reset_control_get(>dev, NULL);
+   if (variant->has_reset)
+   iommu->reset = devm_reset_control_get_exclusive(>dev, 
NULL);
if (IS_ERR(iommu->reset)) {
dev_err(>dev, "Couldn't get our reset line.\n");
ret = PTR_ERR(iommu->reset);
@@ -987,8 +997,12 @@ static int sun50i_iommu_probe(struct platform_device *pdev)
return ret;
 }
 
+static const struct sun50i_iommu_variant sun50i_h6_iommu = {
+   .has_reset = true,
+};
+
 static const struct of_device_id sun50i_iommu_dt[] = {
-   { .compatible = "allwinner,sun50i-h6-iommu", },
+   { .compatible = "allwinner,sun50i-h6-iommu", .data = _h6_iommu },
{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, sun50i_iommu_dt);
-- 
2.35.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 5/5] iommu/sun50i: Ensure the IOMMU can be used for DMA

2022-04-27 Thread Samuel Holland
So far, the driver has relied on arch/arm64/Kconfig to select IOMMU_DMA.
Unsurprisingly, this does not work on RISC-V, so the driver must select
IOMMU_DMA itself.

Signed-off-by: Samuel Holland 
---

 drivers/iommu/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index c79a0df090c0..70a0bfa6d907 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -223,6 +223,7 @@ config SUN50I_IOMMU
depends on ARCH_SUNXI || COMPILE_TEST
select ARM_DMA_USE_IOMMU
select IOMMU_API
+   select IOMMU_DMA
help
  Support for the IOMMU introduced in the Allwinner H6 SoCs.
 
-- 
2.35.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu