2017-08-15 11:35:08

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 00/12] genirq/irqchip: Effective affinity fixups

4.13 contains a number of updates to the core IRQ code to deal with
things like the effective affinity. This series attempts to fix a
number of small things that are now breaking:

1) The core code assumes that CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
being defined implies that *all* interrupts have an effective
affinity, while it may not be the case (I may have compiled in an
irqchip driver that has this property, yet none of my interrupts are
routed through it).

2) A large number of our irqchips are effectively single target (they
will pick one CPU in the affinity list), and yet do not update the
effective affinity cpumask.

(1) is solved by checking that the interrupt has been configured as
"single target" when reporting the effective affinity mask.

(2) is just a matter of updating the effective affinity when required,
and to mark the interrupts as "single target". I've kept them separate
so that people can directly pick the irqchip they are interested in,
but these 10 patches could as well be squashed into a single one.

I've lightly tested the ARM GIC stuff, and that's it. I'd appreciate
some feedback from the platform maintainers, specially for the more
exotic architectures such as metag and xtensa.

Thanks,

M.

Marc Zyngier (12):
genirq: Restrict effective affinity to single-target interrupts
genirq/proc: Use the the accessor to report the effective affinity
irqchip/gic: Report that effective affinity is a single target
irqchip/gic-v3: Report that effective affinity is a single target
irqchip/gic-v3-its: Report that effective affinity is a single target
irqchip/armada-370-xp: Report that effective affinity is a single
target
irqchip/bcm-6345-l1: Report that effective affinity is a single target
irqchip/bcm-7038-l1: Report that effective affinity is a single target
irqchip/metag-ext: Report that effective affinity is a single target
irqchip/hip04: Report that effective affinity is a single target
irqchip/mips-gic: Report that effective affinity is a single target
irqchip/xtensa-mx: Report that effective affinity is a single target

arch/arm/mach-hisi/Kconfig | 1 +
arch/metag/Kconfig | 1 +
drivers/irqchip/Kconfig | 7 +++++++
drivers/irqchip/irq-armada-370-xp.c | 3 +++
drivers/irqchip/irq-bcm6345-l1.c | 3 +++
drivers/irqchip/irq-bcm7038-l1.c | 3 +++
drivers/irqchip/irq-gic-v3-its.c | 7 ++++++-
drivers/irqchip/irq-gic-v3.c | 3 +++
drivers/irqchip/irq-gic.c | 3 +++
drivers/irqchip/irq-hip04.c | 3 +++
drivers/irqchip/irq-metag-ext.c | 4 ++++
drivers/irqchip/irq-mips-gic.c | 2 ++
drivers/irqchip/irq-xtensa-mx.c | 6 +++++-
include/linux/irq.h | 5 ++++-
kernel/irq/proc.c | 2 +-
15 files changed, 49 insertions(+), 4 deletions(-)

--
2.11.0


2017-08-15 11:35:16

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 02/12] genirq/proc: Use the the accessor to report the effective affinity

If CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK is defined, but that the
interrupt is not single target, the effective affinity reported in
/proc/irq/x/effective_affinity will be empty, which is not the truth.

Instead, use the accessor to report the affinity, which will pick
the right mask.

Signed-off-by: Marc Zyngier <[email protected]>
---
kernel/irq/proc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 7f9642a1e267..0534781724d0 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -61,7 +61,7 @@ static int show_irq_affinity(int type, struct seq_file *m)
case EFFECTIVE:
case EFFECTIVE_LIST:
#ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
- mask = desc->irq_common_data.effective_affinity;
+ mask = irq_data_get_effective_affinity_mask(&desc->irq_data);
break;
#else
return -EINVAL;
--
2.11.0

2017-08-15 11:35:21

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 05/12] irqchip/gic-v3-its: Report that effective affinity is a single target

The GICv3 ITS driver only targets a single CPU at a time, even if
the notional affinity is wider. Let's inform the core code
about this.

Signed-off-by: Marc Zyngier <[email protected]>
---
drivers/irqchip/irq-gic-v3-its.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 68932873eebc..22e228500357 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -649,6 +649,7 @@ static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
target_col = &its_dev->its->collections[cpu];
its_send_movi(its_dev, target_col, id);
its_dev->event_map.col_map[id] = cpu;
+ irq_data_update_effective_affinity(d, cpumask_of(cpu));
}

return IRQ_SET_MASK_OK_DONE;
@@ -1481,6 +1482,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,

irq_domain_set_hwirq_and_chip(domain, virq + i,
hwirq, &its_irq_chip, its_dev);
+ irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq + i)));
pr_debug("ID:%d pID:%d vID:%d\n",
(int)(hwirq - its_dev->event_map.lpi_base),
(int) hwirq, virq + i);
@@ -1495,13 +1497,16 @@ static void its_irq_domain_activate(struct irq_domain *domain,
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
u32 event = its_get_event_id(d);
const struct cpumask *cpu_mask = cpu_online_mask;
+ int cpu;

/* get the cpu_mask of local node */
if (its_dev->its->numa_node >= 0)
cpu_mask = cpumask_of_node(its_dev->its->numa_node);

/* Bind the LPI to the first possible CPU */
- its_dev->event_map.col_map[event] = cpumask_first(cpu_mask);
+ cpu = cpumask_first(cpu_mask);
+ its_dev->event_map.col_map[event] = cpu;
+ irq_data_update_effective_affinity(d, cpumask_of(cpu));

/* Map the GIC IRQ and event to the device */
its_send_mapti(its_dev, d->hwirq, event);
--
2.11.0

2017-08-15 11:35:28

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 08/12] irqchip/bcm-7038-l1: Report that effective affinity is a single target

The BCM 7038-L1 driver only targets a single CPU at a time, even if
the notional affinity is wider. Let's inform the core code
about this.

Signed-off-by: Marc Zyngier <[email protected]>
---
drivers/irqchip/Kconfig | 1 +
drivers/irqchip/irq-bcm7038-l1.c | 3 +++
2 files changed, 4 insertions(+)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index b36a55d6833e..39bfa5b25b54 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -102,6 +102,7 @@ config BCM7038_L1_IRQ
bool
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
+ select GENERIC_IRQ_EFFECTIVE_AFF_MASK

config BCM7120_L2_IRQ
bool
diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c
index c2662a1bfdd3..55cfb986225b 100644
--- a/drivers/irqchip/irq-bcm7038-l1.c
+++ b/drivers/irqchip/irq-bcm7038-l1.c
@@ -212,6 +212,8 @@ static int bcm7038_l1_set_affinity(struct irq_data *d,
__bcm7038_l1_unmask(d, first_cpu);

raw_spin_unlock_irqrestore(&intc->lock, flags);
+ irq_data_update_effective_affinity(d, cpumask_of(first_cpu));
+
return 0;
}

@@ -299,6 +301,7 @@ static int bcm7038_l1_map(struct irq_domain *d, unsigned int virq,
{
irq_set_chip_and_handler(virq, &bcm7038_l1_irq_chip, handle_level_irq);
irq_set_chip_data(virq, d->host_data);
+ irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq)));
return 0;
}

--
2.11.0

2017-08-15 11:35:30

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 09/12] irqchip/metag-ext: Report that effective affinity is a single target

The metag-ext driver only targets a single CPU at a time, even if
the notional affinity is wider. Let's inform the core code
about this.

Signed-off-by: Marc Zyngier <[email protected]>
---
arch/metag/Kconfig | 1 +
drivers/irqchip/irq-metag-ext.c | 4 ++++
2 files changed, 5 insertions(+)

diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig
index 5b7a45d99cfb..7d8b322e5101 100644
--- a/arch/metag/Kconfig
+++ b/arch/metag/Kconfig
@@ -26,6 +26,7 @@ config METAG
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_UNDERSCORE_SYMBOL_PREFIX
select IRQ_DOMAIN
+ select GENERIC_IRQ_EFFECTIVE_AFF_MASK
select MODULES_USE_ELF_RELA
select OF
select OF_EARLY_FLATTREE
diff --git a/drivers/irqchip/irq-metag-ext.c b/drivers/irqchip/irq-metag-ext.c
index 0cdd923d1535..be7216bfb8dd 100644
--- a/drivers/irqchip/irq-metag-ext.c
+++ b/drivers/irqchip/irq-metag-ext.c
@@ -518,6 +518,8 @@ static int meta_intc_set_affinity(struct irq_data *data,

metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR2(thread)), vec_addr);

+ irq_data_update_effective_affinity(data, cpumask_of(cpu));
+
return 0;
}
#else
@@ -578,6 +580,8 @@ static int meta_intc_map(struct irq_domain *d, unsigned int irq,
else
irq_set_chip_and_handler(irq, &meta_intc_edge_chip,
handle_edge_irq);
+
+ irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
return 0;
}

--
2.11.0

2017-08-15 11:35:38

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 12/12] irqchip/xtensa-mx: Report that effective affinity is a single target

The xtensa-mx driver only targets a single CPU at a time, even if
the notional affinity is wider. Let's inform the core code
about this.

Signed-off-by: Marc Zyngier <[email protected]>
---
drivers/irqchip/Kconfig | 1 +
drivers/irqchip/irq-xtensa-mx.c | 6 +++++-
2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index bca9a88012f0..1139de9da21a 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -223,6 +223,7 @@ config VERSATILE_FPGA_IRQ_NR
config XTENSA_MX
bool
select IRQ_DOMAIN
+ select GENERIC_IRQ_EFFECTIVE_AFF_MASK

config XILINX_INTC
bool
diff --git a/drivers/irqchip/irq-xtensa-mx.c b/drivers/irqchip/irq-xtensa-mx.c
index 72a391e01011..a15a9510c904 100644
--- a/drivers/irqchip/irq-xtensa-mx.c
+++ b/drivers/irqchip/irq-xtensa-mx.c
@@ -32,6 +32,7 @@ static int xtensa_mx_irq_map(struct irq_domain *d, unsigned int irq,
irq_set_status_flags(irq, IRQ_LEVEL);
return 0;
}
+ irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
return xtensa_irq_map(d, irq, hw);
}

@@ -121,9 +122,12 @@ static int xtensa_mx_irq_retrigger(struct irq_data *d)
static int xtensa_mx_irq_set_affinity(struct irq_data *d,
const struct cpumask *dest, bool force)
{
- unsigned mask = 1u << cpumask_any_and(dest, cpu_online_mask);
+ int cpu = cpumask_any_and(dest, cpu_online_mask);
+ unsigned mask = 1u << cpu;

set_er(mask, MIROUT(d->hwirq - HW_IRQ_MX_BASE));
+ irq_data_update_effective_affinity(d, cpumask_of(cpu));
+
return 0;

}
--
2.11.0

2017-08-15 11:35:36

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 11/12] irqchip/mips-gic: Report that effective affinity is a single target

The MIPS GIC driver only targets a single CPU at a time, even if
the notional affinity is wider. Let's inform the core code
about this.

Signed-off-by: Marc Zyngier <[email protected]>
---
drivers/irqchip/Kconfig | 1 +
drivers/irqchip/irq-mips-gic.c | 2 ++
2 files changed, 3 insertions(+)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 39bfa5b25b54..bca9a88012f0 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -141,6 +141,7 @@ config IRQ_MIPS_CPU
select GENERIC_IRQ_IPI if SYS_SUPPORTS_MULTITHREADING
select IRQ_DOMAIN
select IRQ_DOMAIN_HIERARCHY if GENERIC_IRQ_IPI
+ select GENERIC_IRQ_EFFECTIVE_AFF_MASK

config CLPS711X_IRQCHIP
bool
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 6ab1d3afec02..e075cb25fad6 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -463,6 +463,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
set_bit(irq, pcpu_masks[cpumask_first(&tmp)].pcpu_mask);

cpumask_copy(irq_data_get_affinity_mask(d), cpumask);
+ irq_data_update_effective_affinity(d, cpumask);
spin_unlock_irqrestore(&gic_lock, flags);

return IRQ_SET_MASK_OK_NOCOPY;
@@ -716,6 +717,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
if (err)
return err;

+ irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq)));
return gic_shared_irq_domain_map(d, virq, hwirq, 0);
}

--
2.11.0

2017-08-15 11:35:33

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 10/12] irqchip/hip04: Report that effective affinity is a single target

The HIP04 driver only targets a single CPU at a time, even if
the notional affinity is wider. Let's inform the core code
about this.

Signed-off-by: Marc Zyngier <[email protected]>
---
arch/arm/mach-hisi/Kconfig | 1 +
drivers/irqchip/irq-hip04.c | 3 +++
2 files changed, 4 insertions(+)

diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig
index a3b091a4d344..65a048fa08ec 100644
--- a/arch/arm/mach-hisi/Kconfig
+++ b/arch/arm/mach-hisi/Kconfig
@@ -39,6 +39,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
help
Support for Hisilicon HiP04 SoC family

diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c
index c1b4ee955dbe..5b4fd2f4e5f8 100644
--- a/drivers/irqchip/irq-hip04.c
+++ b/drivers/irqchip/irq-hip04.c
@@ -165,6 +165,8 @@ static int hip04_irq_set_affinity(struct irq_data *d,
writel_relaxed(val | bit, reg);
raw_spin_unlock(&irq_controller_lock);

+ irq_data_update_effective_affinity(d, cpumask_of(cpu));
+
return IRQ_SET_MASK_OK;
}
#endif
@@ -312,6 +314,7 @@ static int hip04_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_set_chip_and_handler(irq, &hip04_irq_chip,
handle_fasteoi_irq);
irq_set_probe(irq);
+ irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
}
irq_set_chip_data(irq, d->host_data);
return 0;
--
2.11.0

2017-08-15 11:35:26

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 07/12] irqchip/bcm-6345-l1: Report that effective affinity is a single target

The BCM 6345-L1 driver only targets a single CPU at a time, even if
the notional affinity is wider. Let's inform the core code
about this.

Signed-off-by: Marc Zyngier <[email protected]>
---
drivers/irqchip/Kconfig | 1 +
drivers/irqchip/irq-bcm6345-l1.c | 3 +++
2 files changed, 4 insertions(+)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index cd688777553c..b36a55d6833e 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -96,6 +96,7 @@ config BCM6345_L1_IRQ
bool
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
+ select GENERIC_IRQ_EFFECTIVE_AFF_MASK

config BCM7038_L1_IRQ
bool
diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c
index daa4ae89e466..43f8abe40878 100644
--- a/drivers/irqchip/irq-bcm6345-l1.c
+++ b/drivers/irqchip/irq-bcm6345-l1.c
@@ -231,6 +231,8 @@ static int bcm6345_l1_set_affinity(struct irq_data *d,
}
raw_spin_unlock_irqrestore(&intc->lock, flags);

+ irq_data_update_effective_affinity(d, cpumask_of(new_cpu));
+
return IRQ_SET_MASK_OK_NOCOPY;
}

@@ -291,6 +293,7 @@ static int bcm6345_l1_map(struct irq_domain *d, unsigned int virq,
irq_set_chip_and_handler(virq,
&bcm6345_l1_irq_chip, handle_percpu_irq);
irq_set_chip_data(virq, d->host_data);
+ irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq)));
return 0;
}

--
2.11.0

2017-08-15 11:37:27

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 06/12] irqchip/armada-370-xp: Report that effective affinity is a single target

The Armada 370 XP driver only targets a single CPU at a time, even if
the notional affinity is wider. Let's inform the core code
about this.

Signed-off-by: Marc Zyngier <[email protected]>
---
drivers/irqchip/Kconfig | 1 +
drivers/irqchip/irq-armada-370-xp.c | 3 +++
2 files changed, 4 insertions(+)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index ce99c1ee6c7d..cd688777553c 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -66,6 +66,7 @@ config ARMADA_370_XP_IRQ
bool
select GENERIC_IRQ_CHIP
select PCI_MSI if PCI
+ select GENERIC_IRQ_EFFECTIVE_AFF_MASK

config ALPINE_MSI
bool
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index b207b2c3aa55..eb815676c088 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -330,6 +330,8 @@ static int armada_xp_set_affinity(struct irq_data *d,
writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));
raw_spin_unlock(&irq_controller_lock);

+ irq_data_update_effective_affinity(d, cpumask_of(cpu));
+
return IRQ_SET_MASK_OK;
}
#endif
@@ -363,6 +365,7 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
} else {
irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
handle_level_irq);
+ irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq)));
}
irq_set_probe(virq);

--
2.11.0

2017-08-15 11:37:45

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 04/12] irqchip/gic-v3: Report that effective affinity is a single target

The GICv3 driver only targets a single CPU at a time, even if
the notional affinity is wider. Let's inform the core code
about this.

Signed-off-by: Marc Zyngier <[email protected]>
---
drivers/irqchip/Kconfig | 1 +
drivers/irqchip/irq-gic-v3.c | 3 +++
2 files changed, 4 insertions(+)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 586929d072ca..ce99c1ee6c7d 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -35,6 +35,7 @@ config ARM_GIC_V3
select MULTI_IRQ_HANDLER
select IRQ_DOMAIN_HIERARCHY
select PARTITION_PERCPU
+ select GENERIC_IRQ_EFFECTIVE_AFF_MASK

config ARM_GIC_V3_ITS
bool
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index dbffb7ab6203..511c290c4a26 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -670,6 +670,8 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
else
gic_dist_wait_for_rwp();

+ irq_data_update_effective_affinity(d, cpumask_of(cpu));
+
return IRQ_SET_MASK_OK_DONE;
}
#else
@@ -768,6 +770,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_domain_set_info(d, irq, hw, chip, d->host_data,
handle_fasteoi_irq, NULL, NULL);
irq_set_probe(irq);
+ irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
}
/* LPIs */
if (hw >= 8192 && hw < GIC_ID_NR) {
--
2.11.0

2017-08-15 11:35:14

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 03/12] irqchip/gic: Report that effective affinity is a single target

The GIC driver only targets a single CPU at a time, even if
the notional affinity is wider. Let's inform the core code
about this.

Signed-off-by: Marc Zyngier <[email protected]>
---
drivers/irqchip/Kconfig | 1 +
drivers/irqchip/irq-gic.c | 3 +++
2 files changed, 4 insertions(+)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index f1fd5f44d1d4..586929d072ca 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -7,6 +7,7 @@ config ARM_GIC
select IRQ_DOMAIN
select IRQ_DOMAIN_HIERARCHY
select MULTI_IRQ_HANDLER
+ select GENERIC_IRQ_EFFECTIVE_AFF_MASK

config ARM_GIC_PM
bool
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 1b1df4f770bd..20dd2ba3d603 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -344,6 +344,8 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
writel_relaxed(val | bit, reg);
gic_unlock_irqrestore(flags);

+ irq_data_update_effective_affinity(d, cpumask_of(cpu));
+
return IRQ_SET_MASK_OK_DONE;
}
#endif
@@ -966,6 +968,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,
handle_fasteoi_irq, NULL, NULL);
irq_set_probe(irq);
+ irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
}
return 0;
}
--
2.11.0

2017-08-15 11:38:17

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 01/12] genirq: Restrict effective affinity to single-target interrupts

Just because CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK is selected
doesn't mean that all the interrupts are using the effective
affinity mask. For a number of them, this mask is likely to
be empty.

In order to deal with this, let's restrict the use of the
effective affinity mask to these interrupts that have been
configured as "single target".

Signed-off-by: Marc Zyngier <[email protected]>
---
include/linux/irq.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index d2d543794093..af1510642b8a 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -781,7 +781,10 @@ static inline struct cpumask *irq_data_get_affinity_mask(struct irq_data *d)
static inline
struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d)
{
- return d->common->effective_affinity;
+ if (irqd_is_single_target(d))
+ return d->common->effective_affinity;
+ else
+ return d->common->affinity;
}
static inline void irq_data_update_effective_affinity(struct irq_data *d,
const struct cpumask *m)
--
2.11.0

2017-08-15 12:02:03

by Thomas Gleixner

[permalink] [raw]
Subject: Re: [PATCH 01/12] genirq: Restrict effective affinity to single-target interrupts

On Tue, 15 Aug 2017, Marc Zyngier wrote:

> Just because CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK is selected
> doesn't mean that all the interrupts are using the effective
> affinity mask. For a number of them, this mask is likely to
> be empty.
>
> In order to deal with this, let's restrict the use of the
> effective affinity mask to these interrupts that have been
> configured as "single target".

That's actually wrong. On X86 we have other restrictions, i.e. groups of
CPUs which are a subset of the affinity mask.

The point of the effective mask is to see to which CPU(s) a particular
interrupt is effectively routed. This is always a subset of the affinity
mask which is either the boot default or set by the admin.

So what you really want is to check whether the effective mask is
empty. That's an indicator that the underlying irq chip does not update the
effective mask.

The single target bit is an optimization for the hotplug case. If its set,
then we can avoid to reconfigure the affinity for that interrupt because it
either would not change or pointlessly be redirected to another single CPU
in the valid set.

Thanks,

tglx

2017-08-15 12:18:55

by Marc Zyngier

[permalink] [raw]
Subject: Re: [PATCH 01/12] genirq: Restrict effective affinity to single-target interrupts

On 15/08/17 13:01, Thomas Gleixner wrote:
> On Tue, 15 Aug 2017, Marc Zyngier wrote:
>
>> Just because CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK is selected
>> doesn't mean that all the interrupts are using the effective
>> affinity mask. For a number of them, this mask is likely to
>> be empty.
>>
>> In order to deal with this, let's restrict the use of the
>> effective affinity mask to these interrupts that have been
>> configured as "single target".
>
> That's actually wrong. On X86 we have other restrictions, i.e. groups of
> CPUs which are a subset of the affinity mask.

Ah, I completely missed that particular restriction.

> The point of the effective mask is to see to which CPU(s) a particular
> interrupt is effectively routed. This is always a subset of the affinity
> mask which is either the boot default or set by the admin.
>
> So what you really want is to check whether the effective mask is
> empty. That's an indicator that the underlying irq chip does not update the
> effective mask.

Yes, that should do the trick. I'll update that patch.

Thanks,

M.
--
Jazz is not dead. It just smells funny...

2017-08-15 16:23:46

by Paul Burton

[permalink] [raw]
Subject: Re: [PATCH 11/12] irqchip/mips-gic: Report that effective affinity is a single target

Hi Marc,

On Tuesday, 15 August 2017 04:34:46 PDT Marc Zyngier wrote:
> The MIPS GIC driver only targets a single CPU at a time, even if
> the notional affinity is wider. Let's inform the core code
> about this.
>
> Signed-off-by: Marc Zyngier <[email protected]>
> ---
> drivers/irqchip/Kconfig | 1 +
> drivers/irqchip/irq-mips-gic.c | 2 ++
> 2 files changed, 3 insertions(+)
>
> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> index 39bfa5b25b54..bca9a88012f0 100644
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -141,6 +141,7 @@ config IRQ_MIPS_CPU
> select GENERIC_IRQ_IPI if SYS_SUPPORTS_MULTITHREADING
> select IRQ_DOMAIN
> select IRQ_DOMAIN_HIERARCHY if GENERIC_IRQ_IPI
> + select GENERIC_IRQ_EFFECTIVE_AFF_MASK
>
> config CLPS711X_IRQCHIP
> bool
> diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
> index 6ab1d3afec02..e075cb25fad6 100644
> --- a/drivers/irqchip/irq-mips-gic.c
> +++ b/drivers/irqchip/irq-mips-gic.c
> @@ -463,6 +463,7 @@ static int gic_set_affinity(struct irq_data *d, const
> struct cpumask *cpumask, set_bit(irq,
> pcpu_masks[cpumask_first(&tmp)].pcpu_mask);
>
> cpumask_copy(irq_data_get_affinity_mask(d), cpumask);
> + irq_data_update_effective_affinity(d, cpumask);

This doesn't seem right - it's just setting the effective affinity to the same
as affinity, not taking into account CPU restrictions at all. I think this
should be:

irq_data_update_effective_affinity(d, cpumask_of(cpumask_first(&tmp)));

(or something cleaner but to that effect)

Thanks,
Paul

> spin_unlock_irqrestore(&gic_lock, flags);
>
> return IRQ_SET_MASK_OK_NOCOPY;
> @@ -716,6 +717,7 @@ static int gic_irq_domain_map(struct irq_domain *d,
> unsigned int virq, if (err)
> return err;
>
> + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq)));
> return gic_shared_irq_domain_map(d, virq, hwirq, 0);
> }


Attachments:
signature.asc (833.00 B)
This is a digitally signed message part.

2017-08-15 16:44:29

by Marc Zyngier

[permalink] [raw]
Subject: Re: [PATCH 11/12] irqchip/mips-gic: Report that effective affinity is a single target

On 15/08/17 17:23, Paul Burton wrote:
> Hi Marc,
>
> On Tuesday, 15 August 2017 04:34:46 PDT Marc Zyngier wrote:
>> The MIPS GIC driver only targets a single CPU at a time, even if
>> the notional affinity is wider. Let's inform the core code
>> about this.
>>
>> Signed-off-by: Marc Zyngier <[email protected]>
>> ---
>> drivers/irqchip/Kconfig | 1 +
>> drivers/irqchip/irq-mips-gic.c | 2 ++
>> 2 files changed, 3 insertions(+)
>>
>> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
>> index 39bfa5b25b54..bca9a88012f0 100644
>> --- a/drivers/irqchip/Kconfig
>> +++ b/drivers/irqchip/Kconfig
>> @@ -141,6 +141,7 @@ config IRQ_MIPS_CPU
>> select GENERIC_IRQ_IPI if SYS_SUPPORTS_MULTITHREADING
>> select IRQ_DOMAIN
>> select IRQ_DOMAIN_HIERARCHY if GENERIC_IRQ_IPI
>> + select GENERIC_IRQ_EFFECTIVE_AFF_MASK
>>
>> config CLPS711X_IRQCHIP
>> bool
>> diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
>> index 6ab1d3afec02..e075cb25fad6 100644
>> --- a/drivers/irqchip/irq-mips-gic.c
>> +++ b/drivers/irqchip/irq-mips-gic.c
>> @@ -463,6 +463,7 @@ static int gic_set_affinity(struct irq_data *d, const
>> struct cpumask *cpumask, set_bit(irq,
>> pcpu_masks[cpumask_first(&tmp)].pcpu_mask);
>>
>> cpumask_copy(irq_data_get_affinity_mask(d), cpumask);
>> + irq_data_update_effective_affinity(d, cpumask);
>
> This doesn't seem right - it's just setting the effective affinity to the same
> as affinity, not taking into account CPU restrictions at all. I think this
> should be:
>
> irq_data_update_effective_affinity(d, cpumask_of(cpumask_first(&tmp)));
>
> (or something cleaner but to that effect)

Gah, you're absolutely right (/me plugs brain back in). How about something like this:

diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index e075cb25fad6..6461380ff1a4 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -445,25 +445,27 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
unsigned int irq = GIC_HWIRQ_TO_SHARED(d->hwirq);
cpumask_t tmp = CPU_MASK_NONE;
unsigned long flags;
- int i;
+ int i, cpu;

cpumask_and(&tmp, cpumask, cpu_online_mask);
if (cpumask_empty(&tmp))
return -EINVAL;

+ cpu = cpumask_first(&tmp);
+
/* Assumption : cpumask refers to a single CPU */
spin_lock_irqsave(&gic_lock, flags);

/* Re-route this IRQ */
- gic_map_to_vpe(irq, mips_cm_vp_id(cpumask_first(&tmp)));
+ gic_map_to_vpe(irq, mips_cm_vp_id(cpu));

/* Update the pcpu_masks */
for (i = 0; i < min(gic_vpes, NR_CPUS); i++)
clear_bit(irq, pcpu_masks[i].pcpu_mask);
- set_bit(irq, pcpu_masks[cpumask_first(&tmp)].pcpu_mask);
+ set_bit(irq, pcpu_masks[cpu].pcpu_mask);

cpumask_copy(irq_data_get_affinity_mask(d), cpumask);
- irq_data_update_effective_affinity(d, cpumask);
+ irq_data_update_effective_affinity(d, cpumask_of(cpu));
spin_unlock_irqrestore(&gic_lock, flags);

return IRQ_SET_MASK_OK_NOCOPY;

Thanks,

M.
--
Jazz is not dead. It just smells funny...

2017-08-15 16:48:39

by Paul Burton

[permalink] [raw]
Subject: Re: [PATCH 11/12] irqchip/mips-gic: Report that effective affinity is a single target

Hi Marc,

On Tuesday, 15 August 2017 09:44:24 PDT Marc Zyngier wrote:
> On 15/08/17 17:23, Paul Burton wrote:
> > Hi Marc,
> >
> > On Tuesday, 15 August 2017 04:34:46 PDT Marc Zyngier wrote:
> >> The MIPS GIC driver only targets a single CPU at a time, even if
> >> the notional affinity is wider. Let's inform the core code
> >> about this.
> >>
> >> Signed-off-by: Marc Zyngier <[email protected]>
> >> ---
> >>
> >> drivers/irqchip/Kconfig | 1 +
> >> drivers/irqchip/irq-mips-gic.c | 2 ++
> >> 2 files changed, 3 insertions(+)
> >>
> >> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> >> index 39bfa5b25b54..bca9a88012f0 100644
> >> --- a/drivers/irqchip/Kconfig
> >> +++ b/drivers/irqchip/Kconfig
> >> @@ -141,6 +141,7 @@ config IRQ_MIPS_CPU
> >>
> >> select GENERIC_IRQ_IPI if SYS_SUPPORTS_MULTITHREADING
> >> select IRQ_DOMAIN
> >> select IRQ_DOMAIN_HIERARCHY if GENERIC_IRQ_IPI
> >>
> >> + select GENERIC_IRQ_EFFECTIVE_AFF_MASK
> >>
> >> config CLPS711X_IRQCHIP
> >>
> >> bool
> >>
> >> diff --git a/drivers/irqchip/irq-mips-gic.c
> >> b/drivers/irqchip/irq-mips-gic.c index 6ab1d3afec02..e075cb25fad6 100644
> >> --- a/drivers/irqchip/irq-mips-gic.c
> >> +++ b/drivers/irqchip/irq-mips-gic.c
> >> @@ -463,6 +463,7 @@ static int gic_set_affinity(struct irq_data *d, const
> >> struct cpumask *cpumask, set_bit(irq,
> >> pcpu_masks[cpumask_first(&tmp)].pcpu_mask);
> >>
> >> cpumask_copy(irq_data_get_affinity_mask(d), cpumask);
> >>
> >> + irq_data_update_effective_affinity(d, cpumask);
> >
> > This doesn't seem right - it's just setting the effective affinity to the
> > same as affinity, not taking into account CPU restrictions at all. I
> > think this>
> > should be:
> > irq_data_update_effective_affinity(d, cpumask_of(cpumask_first(&tmp)));
> >
> > (or something cleaner but to that effect)
>
> Gah, you're absolutely right (/me plugs brain back in). How about something
> like this:
>
> diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
> index e075cb25fad6..6461380ff1a4 100644
> --- a/drivers/irqchip/irq-mips-gic.c
> +++ b/drivers/irqchip/irq-mips-gic.c
> @@ -445,25 +445,27 @@ static int gic_set_affinity(struct irq_data *d, const
> struct cpumask *cpumask, unsigned int irq = GIC_HWIRQ_TO_SHARED(d->hwirq);
> cpumask_t tmp = CPU_MASK_NONE;
> unsigned long flags;
> - int i;
> + int i, cpu;
>
> cpumask_and(&tmp, cpumask, cpu_online_mask);
> if (cpumask_empty(&tmp))
> return -EINVAL;
>
> + cpu = cpumask_first(&tmp);
> +
> /* Assumption : cpumask refers to a single CPU */
> spin_lock_irqsave(&gic_lock, flags);
>
> /* Re-route this IRQ */
> - gic_map_to_vpe(irq, mips_cm_vp_id(cpumask_first(&tmp)));
> + gic_map_to_vpe(irq, mips_cm_vp_id(cpu));
>
> /* Update the pcpu_masks */
> for (i = 0; i < min(gic_vpes, NR_CPUS); i++)
> clear_bit(irq, pcpu_masks[i].pcpu_mask);
> - set_bit(irq, pcpu_masks[cpumask_first(&tmp)].pcpu_mask);
> + set_bit(irq, pcpu_masks[cpu].pcpu_mask);
>
> cpumask_copy(irq_data_get_affinity_mask(d), cpumask);
> - irq_data_update_effective_affinity(d, cpumask);
> + irq_data_update_effective_affinity(d, cpumask_of(cpu));
> spin_unlock_irqrestore(&gic_lock, flags);
>
> return IRQ_SET_MASK_OK_NOCOPY;
>
> Thanks,
>
> M.

That looks better (though patch 37 of my "irqchip: mips-gic: Cleanup &
optimisation" series would get you that cpu variable already ;) ).

Thanks,
Paul


Attachments:
signature.asc (833.00 B)
This is a digitally signed message part.