Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UNTESTED AIC driver cleanup/reorg #2

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
cc475e5
duplicate AIC driver as irq-apple-fiq.c
pipcet Aug 10, 2021
99e3e01
delete IRQ stuff from FIQ driver
pipcet Aug 10, 2021
5d69304
delete FIQ stuff from IRQ driver
pipcet Aug 10, 2021
5e3e99a
remove more IRQ stuff from FIQ driver
pipcet Aug 10, 2021
77896b2
remove more IRQ stuff from FIQ driver
pipcet Aug 10, 2021
911a0b3
remove more IRQ stuff from FIQ driver
pipcet Aug 10, 2021
4be2189
FIQ cleanup
pipcet Aug 10, 2021
8b437d3
TEMPORARY hack to build FIQ driver
pipcet Aug 10, 2021
e76788d
compilation fixes
pipcet Aug 10, 2021
ae64c3e
TEMPORARY DT entries
pipcet Aug 10, 2021
566b0ba
minor things
pipcet Aug 10, 2021
58d1214
TEMPORARY hack since FIQs aren't masked properly yet.
pipcet Aug 10, 2021
de52b6b
initialize CPUs properly
pipcet Aug 10, 2021
1dabd80
undo temporary hack
pipcet Aug 10, 2021
1df1de8
rm inappropriate message
pipcet Aug 10, 2021
8332d9f
fix the bug @svenpeter42 found.
pipcet Aug 10, 2021
c47660c
duplicate code
pipcet Aug 10, 2021
4820a22
prepare the funneling driver
pipcet Aug 10, 2021
db0fca9
still hoping for a negative diffstat
pipcet Aug 10, 2021
c7a8013
remove the vIPI implementation
pipcet Aug 10, 2021
051e9f7
minor
pipcet Aug 11, 2021
605c9f7
comments
pipcet Aug 11, 2021
7235b1b
comments
pipcet Aug 11, 2021
88c6ef9
whitespace
pipcet Aug 11, 2021
7ccd8ec
rename ipi-funnel to vipi
pipcet Aug 11, 2021
8f33c22
rename ipi-funnel to vipi
pipcet Aug 11, 2021
6ada2b7
more renaming
pipcet Aug 11, 2021
be45284
cleanup
pipcet Aug 11, 2021
93edc61
allow multi-CPU affinities
pipcet Aug 11, 2021
7a7bfa9
handle only a single IRQ event at a time
pipcet Aug 11, 2021
1bda904
delete file
pipcet Aug 11, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions arch/arm64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,9 @@ config ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE
config SMP
def_bool y

config IPI_FUNNELING
def_bool y

config KERNEL_MODE_NEON
def_bool y

Expand Down
8 changes: 7 additions & 1 deletion arch/arm64/boot/dts/apple/t8103.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,15 @@
};
};

fiq: interrupt-controller {
compatible = "apple,fiq";
#interrupt-cells = <3>;
interrupt-controller;
};

timer {
compatible = "arm,armv8-timer";
interrupt-parent = <&aic>;
interrupt-parent = <&fiq>;
interrupt-names = "phys", "virt", "hyp-phys", "hyp-virt";
interrupts = <AIC_FIQ AIC_TMR_GUEST_PHYS IRQ_TYPE_LEVEL_HIGH>,
<AIC_FIQ AIC_TMR_GUEST_VIRT IRQ_TYPE_LEVEL_HIGH>,
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
obj-$(CONFIG_ARM64_MTE) += mte.o
obj-y += vdso-wrap.o
obj-$(CONFIG_COMPAT_VDSO) += vdso32-wrap.o
obj-$(CONFIG_IPI_FUNNELING) += vipi.o

obj-y += probes/
head-y := head.o
Expand Down
16 changes: 16 additions & 0 deletions arch/arm64/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -979,10 +979,26 @@ static void ipi_teardown(int cpu)
}
#endif

#ifdef CONFIG_IPI_FUNNELING
extern int __init vipi_init(struct irq_data *hwirq);
#else
static inline int vipi_init(irqdata)
{
return -EINVAL;
}
#endif

void __init set_smp_ipi_range(int ipi_base, int n)
{
int i;

if (n < NR_IPI) {
int ret;
BUG_ON(n < 1);
ret = vipi_init(irq_get_irq_data(ipi_base));
if (ret >= 0)
return;
}
WARN_ON(n < NR_IPI);
nr_ipi = min(n, NR_IPI);

Expand Down
231 changes: 231 additions & 0 deletions arch/arm64/kernel/vipi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright The Asahi Linux Contributors
*
* Based on irq-lpc32xx:
* Copyright 2015-2016 Vladimir Zapolskiy <vz@mleia.com>
* Based on irq-bcm2836:
* Copyright 2015 Broadcom
*/

#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/cpuhotplug.h>
#include <linux/io.h>
#include <linux/irqchip.h>
#include <linux/irqdomain.h>
#include <linux/limits.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <asm/exception.h>
#include <asm/sysreg.h>
#include <asm/virt.h>

struct vipi_irq_chip {
struct irq_domain *domain;
struct irq_data *hwirq;
};

#define NR_SWIPI 32

static DEFINE_PER_CPU(atomic_t, vipi_flag);
static DEFINE_PER_CPU(atomic_t, vipi_enable);

static struct vipi_irq_chip *vipi_irqc;

static void handle_ipi(struct irq_desc *d);
/*
* IPI irqchip
*/

static void vipi_mask(struct irq_data *d)
{
u32 irq_bit = BIT(irqd_to_hwirq(d));

/* No specific ordering requirements needed here. */
atomic_andnot(irq_bit, this_cpu_ptr(&vipi_enable));
}

static void vipi_unmask(struct irq_data *d)
{
struct vipi_irq_chip *ic = irq_data_get_irq_chip_data(d);
u32 irq_bit = BIT(irqd_to_hwirq(d));

atomic_or(irq_bit, this_cpu_ptr(&vipi_enable));

/*
* The atomic_or() above must complete before the atomic_read()
* below to avoid racing aic_ipi_send_mask().
*/
smp_mb__after_atomic();

/*
* If a pending vIPI was unmasked, raise a HW IPI to ourselves.
* No barriers needed here since this is a self-IPI.
*/
if (atomic_read(this_cpu_ptr(&vipi_flag)) & irq_bit) {
struct cpumask self_mask = { 0, };
cpumask_set_cpu(smp_processor_id(), &self_mask);
ipi_send_mask(ic->hwirq->irq, &self_mask);
}
}


static void vipi_send_mask(struct irq_data *d, const struct cpumask *mask)
{
struct vipi_irq_chip *ic = irq_data_get_irq_chip_data(d);
u32 irq_bit = BIT(irqd_to_hwirq(d));
int cpu;
bool send;
unsigned long pending;
struct cpumask sendmask = *mask;

for_each_cpu(cpu, mask) {
/*
* This sequence is the mirror of the one in vipi_unmask();
* see the comment there. Additionally, release semantics
* ensure that the vIPI flag set is ordered after any shared
* memory accesses that precede it. This therefore also pairs
* with the atomic_fetch_andnot in handle_ipi().
*/
pending = atomic_fetch_or_release(irq_bit, per_cpu_ptr(&vipi_flag, cpu));

/*
* The atomic_fetch_or_release() above must complete before the
* atomic_read() below to avoid racing vipi_unmask().
*/
smp_mb__after_atomic();

if (!(pending & irq_bit) &&
(atomic_read(per_cpu_ptr(&vipi_enable, cpu)) & irq_bit)) {
cpumask_set_cpu(cpu, &sendmask);
send = true;
}
}

/*
* The flag writes must complete before the physical IPI is issued
* to another CPU. This is implied by the control dependency on
* the result of atomic_read_acquire() above, which is itself
* already ordered after the vIPI flag write.
*/
if (send)
ipi_send_mask(ic->hwirq->irq, &sendmask);
}

static struct irq_chip vipi_chip = {
.name = "VIPI",
.irq_mask = vipi_mask,
.irq_unmask = vipi_unmask,
.ipi_send_mask = vipi_send_mask,
};

/*
* IPI IRQ domain
*/

static void handle_ipi(struct irq_desc *d)
{
int i;
unsigned long enabled, firing;

/*
* The mask read does not need to be ordered. Only we can change
* our own mask anyway, so no races are possible here, as long as
* we are properly in the interrupt handler (XXX is this satisfied?).
*/
enabled = atomic_read(this_cpu_ptr(&vipi_enable));

/*
* Clear the IPIs we are about to handle. This pairs with the
* atomic_fetch_or_release() in vipi_send_mask(), and needs to be
* ordered after the ic_write() above (to avoid dropping vIPIs) and
* before IPI handling code (to avoid races handling vIPIs before they
* are signaled). The former is taken care of by the release semantics
* of the write portion, while the latter is taken care of by the
* acquire semantics of the read portion.
*/
firing = atomic_fetch_andnot(enabled, this_cpu_ptr(&vipi_flag)) & enabled;

for_each_set_bit(i, &firing, NR_SWIPI) {
struct irq_desc *nd =
irq_resolve_mapping(vipi_irqc->domain, i);

handle_irq_desc(nd);
}
}

static int vipi_alloc(struct irq_domain *d, unsigned int virq,
unsigned int nr_irqs, void *args)
{
int i;

for (i = 0; i < nr_irqs; i++) {
irq_set_percpu_devid(virq + i);
irq_domain_set_info(d, virq + i, i, &vipi_chip, d->host_data,
handle_percpu_devid_irq, NULL, NULL);
}

return 0;
}

static void vipi_free(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs)
{
/* Not freeing IPIs */
WARN_ON(1);
}

static const struct irq_domain_ops vipi_domain_ops = {
.alloc = vipi_alloc,
.free = vipi_free,
};

static int vipi_init_smp(struct vipi_irq_chip *irqc)
{
struct irq_domain *vipi_domain;
int base_ipi;

vipi_domain = irq_domain_create_linear(NULL, NR_SWIPI,
&vipi_domain_ops, irqc);
if (WARN_ON(!vipi_domain))
return -ENOMEM;

vipi_domain->flags |= IRQ_DOMAIN_FLAG_IPI_SINGLE;
irq_domain_update_bus_token(vipi_domain, DOMAIN_BUS_IPI);

base_ipi = __irq_domain_alloc_irqs(vipi_domain, -1, NR_SWIPI,
NUMA_NO_NODE, NULL, false, NULL);

if (WARN_ON(!base_ipi)) {
irq_domain_remove(vipi_domain);
return -ENOMEM;
}

set_smp_ipi_range(base_ipi, NR_SWIPI);

irqc->domain = vipi_domain;

return 0;
}

int __init vipi_init(struct irq_data *hwirq)
{
struct vipi_irq_chip *irqc;

irqc = kzalloc(sizeof(*irqc), GFP_KERNEL);
if (!irqc)
return -ENOMEM;

irqc->hwirq = hwirq;

if (vipi_init_smp(irqc))
return -ENOMEM;

vipi_irqc = irqc;

irq_set_handler_locked(hwirq, handle_ipi);

pr_info("Initialized with %d vIPIs\n", NR_SWIPI);

return 0;
}
2 changes: 1 addition & 1 deletion drivers/irqchip/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,4 @@ obj-$(CONFIG_SL28CPLD_INTC) += irq-sl28cpld.o
obj-$(CONFIG_MACH_REALTEK_RTL) += irq-realtek-rtl.o
obj-$(CONFIG_WPCM450_AIC) += irq-wpcm450-aic.o
obj-$(CONFIG_IRQ_IDT3243X) += irq-idt3243x.o
obj-$(CONFIG_APPLE_AIC) += irq-apple-aic.o
obj-$(CONFIG_APPLE_AIC) += irq-apple-aic.o irq-apple-fiq.o
Loading