···4949 select GENERIC_ARCH_TOPOLOGY if ARM_CPU_TOPOLOGY5050 select GENERIC_ATOMIC64 if CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI5151 select GENERIC_CLOCKEVENTS_BROADCAST if SMP5252+ select GENERIC_IRQ_IPI if SMP5253 select GENERIC_CPU_AUTOPROBE5354 select GENERIC_EARLY_IOREMAP5455 select GENERIC_IDLE_POLL_SETUP
-17
arch/arm/include/asm/hardirq.h
···66#include <linux/threads.h>77#include <asm/irq.h>8899-/* number of IPIS _not_ including IPI_CPU_BACKTRACE */1010-#define NR_IPI 71111-129typedef struct {1310 unsigned int __softirq_pending;1414-#ifdef CONFIG_SMP1515- unsigned int ipi_irqs[NR_IPI];1616-#endif1711} ____cacheline_aligned irq_cpustat_t;18121913#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */2020-2121-#define __inc_irq_stat(cpu, member) __IRQ_STAT(cpu, member)++2222-#define __get_irq_stat(cpu, member) __IRQ_STAT(cpu, member)2323-2424-#ifdef CONFIG_SMP2525-u64 smp_irq_stat_cpu(unsigned int cpu);2626-#else2727-#define smp_irq_stat_cpu(cpu) 02828-#endif2929-3030-#define arch_irq_stat_cpu smp_irq_stat_cpu31143215#define __ARCH_IRQ_EXIT_IRQS_DISABLED 13316
+2-3
arch/arm/include/asm/smp.h
···3939 */4040extern void smp_init_cpus(void);41414242-4342/*4444- * Provide a function to raise an IPI cross call on CPUs in callmap.4343+ * Register IPI interrupts with the arch SMP code4544 */4646-extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int));4545+extern void set_smp_ipi_range(int ipi_base, int nr_ipi);47464847/*4948 * Called from platform specific assembly code, this is the
-1
arch/arm/kernel/irq.c
···1818 * IRQ's are in fact implemented a bit like signal handlers for the kernel.1919 * Naturally it's not a 1:1 relation, but there are similarities.2020 */2121-#include <linux/kernel_stat.h>2221#include <linux/signal.h>2322#include <linux/ioport.h>2423#include <linux/interrupt.h>
+90-46
arch/arm/kernel/smp.c
···2626#include <linux/completion.h>2727#include <linux/cpufreq.h>2828#include <linux/irq_work.h>2929+#include <linux/kernel_stat.h>29303031#include <linux/atomic.h>3132#include <asm/bugs.h>···6665 IPI_CPU_STOP,6766 IPI_IRQ_WORK,6867 IPI_COMPLETION,6868+ NR_IPI,6969 /*7070 * CPU_BACKTRACE is special and not included in NR_IPI7171 * or tracable with trace_ipi_*7272 */7373- IPI_CPU_BACKTRACE,7373+ IPI_CPU_BACKTRACE = NR_IPI,7474 /*7575 * SGI8-15 can be reserved by secure firmware, and thus may7676 * not be usable by the kernel. Please keep the above limited7777 * to at most 8 entries.7878 */7979+ MAX_IPI7980};8181+8282+static int ipi_irq_base __read_mostly;8383+static int nr_ipi __read_mostly = NR_IPI;8484+static struct irq_desc *ipi_desc[MAX_IPI] __read_mostly;8585+8686+static void ipi_setup(int cpu);8787+static void ipi_teardown(int cpu);80888189static DECLARE_COMPLETION(cpu_running);8290···257247 * and we must not schedule until we're ready to give up the cpu.258248 */259249 set_cpu_online(cpu, false);250250+ ipi_teardown(cpu);260251261252 /*262253 * OK - migrate IRQs away from this CPU···433422434423 notify_cpu_starting(cpu);435424425425+ ipi_setup(cpu);426426+436427 calibrate_delay();437428438429 smp_store_cpu_info(cpu);···513500 }514501}515502516516-static void (*__smp_cross_call)(const struct cpumask *, unsigned int);517517-518518-void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int))519519-{520520- if (!__smp_cross_call)521521- __smp_cross_call = fn;522522-}523523-524503static const char *ipi_types[NR_IPI] __tracepoint_string = {525504#define S(x,s) [x] = s526505 S(IPI_WAKEUP, "CPU wakeup interrupts"),···524519 S(IPI_COMPLETION, "completion interrupts"),525520};526521527527-static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)528528-{529529- trace_ipi_raise_rcuidle(target, ipi_types[ipinr]);530530- __smp_cross_call(target, ipinr);531531-}522522+static void smp_cross_call(const struct cpumask *target, unsigned int ipinr);532523533524void show_ipi_list(struct seq_file *p, int prec)534525{535526 unsigned int cpu, i;536527537528 for (i = 0; i < NR_IPI; i++) {529529+ unsigned int irq = irq_desc_get_irq(ipi_desc[i]);538530 seq_printf(p, "%*s%u: ", prec - 1, "IPI", i);539531540532 for_each_online_cpu(cpu)541541- seq_printf(p, "%10u ",542542- __get_irq_stat(cpu, ipi_irqs[i]));533533+ seq_printf(p, "%10u ", kstat_irqs_cpu(irq, cpu));543534544535 seq_printf(p, " %s\n", ipi_types[i]);545536 }546546-}547547-548548-u64 smp_irq_stat_cpu(unsigned int cpu)549549-{550550- u64 sum = 0;551551- int i;552552-553553- for (i = 0; i < NR_IPI; i++)554554- sum += __get_irq_stat(cpu, ipi_irqs[i]);555555-556556- return sum;557537}558538559539void arch_send_call_function_ipi_mask(const struct cpumask *mask)···617627 handle_IPI(ipinr, regs);618628}619629620620-void handle_IPI(int ipinr, struct pt_regs *regs)630630+static void do_handle_IPI(int ipinr)621631{622632 unsigned int cpu = smp_processor_id();623623- struct pt_regs *old_regs = set_irq_regs(regs);624633625625- if ((unsigned)ipinr < NR_IPI) {634634+ if ((unsigned)ipinr < NR_IPI)626635 trace_ipi_entry_rcuidle(ipi_types[ipinr]);627627- __inc_irq_stat(cpu, ipi_irqs[ipinr]);628628- }629636630637 switch (ipinr) {631638 case IPI_WAKEUP:···630643631644#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST632645 case IPI_TIMER:633633- irq_enter();634646 tick_receive_broadcast();635635- irq_exit();636647 break;637648#endif638649···639654 break;640655641656 case IPI_CALL_FUNC:642642- irq_enter();643657 generic_smp_call_function_interrupt();644644- irq_exit();645658 break;646659647660 case IPI_CPU_STOP:648648- irq_enter();649661 ipi_cpu_stop(cpu);650650- irq_exit();651662 break;652663653664#ifdef CONFIG_IRQ_WORK654665 case IPI_IRQ_WORK:655655- irq_enter();656666 irq_work_run();657657- irq_exit();658667 break;659668#endif660669661670 case IPI_COMPLETION:662662- irq_enter();663671 ipi_complete(cpu);664664- irq_exit();665672 break;666673667674 case IPI_CPU_BACKTRACE:668675 printk_nmi_enter();669669- irq_enter();670670- nmi_cpu_backtrace(regs);671671- irq_exit();676676+ nmi_cpu_backtrace(get_irq_regs());672677 printk_nmi_exit();673678 break;674679···670695671696 if ((unsigned)ipinr < NR_IPI)672697 trace_ipi_exit_rcuidle(ipi_types[ipinr]);698698+}699699+700700+/* Legacy version, should go away once all irqchips have been converted */701701+void handle_IPI(int ipinr, struct pt_regs *regs)702702+{703703+ struct pt_regs *old_regs = set_irq_regs(regs);704704+705705+ irq_enter();706706+ do_handle_IPI(ipinr);707707+ irq_exit();708708+673709 set_irq_regs(old_regs);710710+}711711+712712+static irqreturn_t ipi_handler(int irq, void *data)713713+{714714+ do_handle_IPI(irq - ipi_irq_base);715715+ return IRQ_HANDLED;716716+}717717+718718+static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)719719+{720720+ trace_ipi_raise_rcuidle(target, ipi_types[ipinr]);721721+ __ipi_send_mask(ipi_desc[ipinr], target);722722+}723723+724724+static void ipi_setup(int cpu)725725+{726726+ int i;727727+728728+ if (WARN_ON_ONCE(!ipi_irq_base))729729+ return;730730+731731+ for (i = 0; i < nr_ipi; i++)732732+ enable_percpu_irq(ipi_irq_base + i, 0);733733+}734734+735735+static void ipi_teardown(int cpu)736736+{737737+ int i;738738+739739+ if (WARN_ON_ONCE(!ipi_irq_base))740740+ return;741741+742742+ for (i = 0; i < nr_ipi; i++)743743+ disable_percpu_irq(ipi_irq_base + i);744744+}745745+746746+void __init set_smp_ipi_range(int ipi_base, int n)747747+{748748+ int i;749749+750750+ WARN_ON(n < MAX_IPI);751751+ nr_ipi = min(n, MAX_IPI);752752+753753+ for (i = 0; i < nr_ipi; i++) {754754+ int err;755755+756756+ err = request_percpu_irq(ipi_base + i, ipi_handler,757757+ "IPI", &irq_stat);758758+ WARN_ON(err);759759+760760+ ipi_desc[i] = irq_to_desc(ipi_base + i);761761+ irq_set_status_flags(ipi_base + i, IRQ_HIDDEN);762762+ }763763+764764+ ipi_irq_base = ipi_base;765765+766766+ /* Setup the boot CPU immediately */767767+ ipi_setup(smp_processor_id());674768}675769676770void smp_send_reschedule(int cpu)···849805850806static void raise_nmi(cpumask_t *mask)851807{852852- __smp_cross_call(mask, IPI_CPU_BACKTRACE);808808+ __ipi_send_mask(ipi_desc[IPI_CPU_BACKTRACE], mask);853809}854810855811void arch_trigger_cpumask_backtrace(const cpumask_t *mask, bool exclude_self)
···5656struct seq_file;57575858/*5959- * generate IPI list text6060- */6161-extern void show_ipi_list(struct seq_file *p, int prec);6262-6363-/*6464- * Called from C code, this handles an IPI.6565- */6666-extern void handle_IPI(int ipinr, struct pt_regs *regs);6767-6868-/*6959 * Discover the set of possible CPUs and determine their7060 * SMP operations.7161 */7262extern void smp_init_cpus(void);73637464/*7575- * Provide a function to raise an IPI cross call on CPUs in callmap.6565+ * Register IPI interrupts with the arch SMP code7666 */7777-extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int));7878-7979-extern void (*__smp_cross_call)(const struct cpumask *, unsigned int);6767+extern void set_smp_ipi_range(int ipi_base, int nr_ipi);80688169/*8270 * Called from the secondary holding pen, this is the secondary CPU entry point.
+1-10
arch/arm64/kernel/irq.c
···1010 * Copyright (C) 2012 ARM Ltd.1111 */12121313-#include <linux/kernel_stat.h>1413#include <linux/irq.h>1514#include <linux/memory.h>1615#include <linux/smp.h>1616+#include <linux/hardirq.h>1717#include <linux/init.h>1818#include <linux/irqchip.h>1919#include <linux/kprobes.h>···2222#include <asm/daifflags.h>2323#include <asm/vmap_stack.h>24242525-unsigned long irq_err_count;2626-2725/* Only access this in an NMI enter/exit */2826DEFINE_PER_CPU(struct nmi_ctx, nmi_contexts);29273028DEFINE_PER_CPU(unsigned long *, irq_stack_ptr);3131-3232-int arch_show_interrupts(struct seq_file *p, int prec)3333-{3434- show_ipi_list(p, prec);3535- seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);3636- return 0;3737-}38293930#ifdef CONFIG_VMAP_STACK4031static void init_irq_stacks(void)
+83-44
arch/arm64/kernel/smp.c
···3030#include <linux/completion.h>3131#include <linux/of.h>3232#include <linux/irq_work.h>3333+#include <linux/kernel_stat.h>3334#include <linux/kexec.h>3435#include <linux/kvm_host.h>3536···7372 IPI_CPU_CRASH_STOP,7473 IPI_TIMER,7574 IPI_IRQ_WORK,7676- IPI_WAKEUP7575+ IPI_WAKEUP,7676+ NR_IPI7777};7878+7979+static int ipi_irq_base __read_mostly;8080+static int nr_ipi __read_mostly = NR_IPI;8181+static struct irq_desc *ipi_desc[NR_IPI] __read_mostly;8282+8383+static void ipi_setup(int cpu);8484+static void ipi_teardown(int cpu);78857986#ifdef CONFIG_HOTPLUG_CPU8087static int op_cpu_kill(unsigned int cpu);···246237 */247238 notify_cpu_starting(cpu);248239240240+ ipi_setup(cpu);241241+249242 store_cpu_topology(cpu);250243 numa_add_cpu(cpu);251244···313302 * and we must not schedule until we're ready to give up the cpu.314303 */315304 set_cpu_online(cpu, false);305305+ ipi_teardown(cpu);316306317307 /*318308 * OK - migrate IRQs away from this CPU···784772 }785773}786774787787-void (*__smp_cross_call)(const struct cpumask *, unsigned int);788788-789789-void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int))790790-{791791- __smp_cross_call = fn;792792-}793793-794775static const char *ipi_types[NR_IPI] __tracepoint_string = {795776#define S(x,s) [x] = s796777 S(IPI_RESCHEDULE, "Rescheduling interrupts"),···795790 S(IPI_WAKEUP, "CPU wake-up interrupts"),796791};797792798798-static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)799799-{800800- trace_ipi_raise(target, ipi_types[ipinr]);801801- __smp_cross_call(target, ipinr);802802-}793793+static void smp_cross_call(const struct cpumask *target, unsigned int ipinr);803794804804-void show_ipi_list(struct seq_file *p, int prec)795795+unsigned long irq_err_count;796796+797797+int arch_show_interrupts(struct seq_file *p, int prec)805798{806799 unsigned int cpu, i;807800808801 for (i = 0; i < NR_IPI; i++) {802802+ unsigned int irq = irq_desc_get_irq(ipi_desc[i]);809803 seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i,810804 prec >= 4 ? " " : "");811805 for_each_online_cpu(cpu)812812- seq_printf(p, "%10u ",813813- __get_irq_stat(cpu, ipi_irqs[i]));806806+ seq_printf(p, "%10u ", kstat_irqs_cpu(irq, cpu));814807 seq_printf(p, " %s\n", ipi_types[i]);815808 }816816-}817809818818-u64 smp_irq_stat_cpu(unsigned int cpu)819819-{820820- u64 sum = 0;821821- int i;822822-823823- for (i = 0; i < NR_IPI; i++)824824- sum += __get_irq_stat(cpu, ipi_irqs[i]);825825-826826- return sum;810810+ seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);811811+ return 0;827812}828813829814void arch_send_call_function_ipi_mask(const struct cpumask *mask)···836841#ifdef CONFIG_IRQ_WORK837842void arch_irq_work_raise(void)838843{839839- if (__smp_cross_call)840840- smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK);844844+ smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK);841845}842846#endif843847···884890/*885891 * Main handler for inter-processor interrupts886892 */887887-void handle_IPI(int ipinr, struct pt_regs *regs)893893+static void do_handle_IPI(int ipinr)888894{889895 unsigned int cpu = smp_processor_id();890890- struct pt_regs *old_regs = set_irq_regs(regs);891896892892- if ((unsigned)ipinr < NR_IPI) {897897+ if ((unsigned)ipinr < NR_IPI)893898 trace_ipi_entry_rcuidle(ipi_types[ipinr]);894894- __inc_irq_stat(cpu, ipi_irqs[ipinr]);895895- }896899897900 switch (ipinr) {898901 case IPI_RESCHEDULE:···897906 break;898907899908 case IPI_CALL_FUNC:900900- irq_enter();901909 generic_smp_call_function_interrupt();902902- irq_exit();903910 break;904911905912 case IPI_CPU_STOP:906906- irq_enter();907913 local_cpu_stop();908908- irq_exit();909914 break;910915911916 case IPI_CPU_CRASH_STOP:912917 if (IS_ENABLED(CONFIG_KEXEC_CORE)) {913913- irq_enter();914914- ipi_cpu_crash_stop(cpu, regs);918918+ ipi_cpu_crash_stop(cpu, get_irq_regs());915919916920 unreachable();917921 }···914928915929#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST916930 case IPI_TIMER:917917- irq_enter();918931 tick_receive_broadcast();919919- irq_exit();920932 break;921933#endif922934923935#ifdef CONFIG_IRQ_WORK924936 case IPI_IRQ_WORK:925925- irq_enter();926937 irq_work_run();927927- irq_exit();928938 break;929939#endif930940···939957940958 if ((unsigned)ipinr < NR_IPI)941959 trace_ipi_exit_rcuidle(ipi_types[ipinr]);942942- set_irq_regs(old_regs);960960+}961961+962962+static irqreturn_t ipi_handler(int irq, void *data)963963+{964964+ do_handle_IPI(irq - ipi_irq_base);965965+ return IRQ_HANDLED;966966+}967967+968968+static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)969969+{970970+ trace_ipi_raise(target, ipi_types[ipinr]);971971+ __ipi_send_mask(ipi_desc[ipinr], target);972972+}973973+974974+static void ipi_setup(int cpu)975975+{976976+ int i;977977+978978+ if (WARN_ON_ONCE(!ipi_irq_base))979979+ return;980980+981981+ for (i = 0; i < nr_ipi; i++)982982+ enable_percpu_irq(ipi_irq_base + i, 0);983983+}984984+985985+static void ipi_teardown(int cpu)986986+{987987+ int i;988988+989989+ if (WARN_ON_ONCE(!ipi_irq_base))990990+ return;991991+992992+ for (i = 0; i < nr_ipi; i++)993993+ disable_percpu_irq(ipi_irq_base + i);994994+}995995+996996+void __init set_smp_ipi_range(int ipi_base, int n)997997+{998998+ int i;999999+10001000+ WARN_ON(n < NR_IPI);10011001+ nr_ipi = min(n, NR_IPI);10021002+10031003+ for (i = 0; i < nr_ipi; i++) {10041004+ int err;10051005+10061006+ err = request_percpu_irq(ipi_base + i, ipi_handler,10071007+ "IPI", &cpu_number);10081008+ WARN_ON(err);10091009+10101010+ ipi_desc[i] = irq_to_desc(ipi_base + i);10111011+ irq_set_status_flags(ipi_base + i, IRQ_HIDDEN);10121012+ }10131013+10141014+ ipi_irq_base = ipi_base;10151015+10161016+ /* Setup the boot CPU immediately */10171017+ ipi_setup(smp_processor_id());9431018}94410199451020void smp_send_reschedule(int cpu)
+198-104
drivers/irqchip/irq-armada-370-xp.c
···310310}311311#endif312312313313+static void armada_xp_mpic_perf_init(void)314314+{315315+ unsigned long cpuid = cpu_logical_map(smp_processor_id());316316+317317+ /* Enable Performance Counter Overflow interrupts */318318+ writel(ARMADA_370_XP_INT_CAUSE_PERF(cpuid),319319+ per_cpu_int_base + ARMADA_370_XP_INT_FABRIC_MASK_OFFS);320320+}321321+313322#ifdef CONFIG_SMP323323+static struct irq_domain *ipi_domain;324324+325325+static void armada_370_xp_ipi_mask(struct irq_data *d)326326+{327327+ u32 reg;328328+ reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);329329+ reg &= ~BIT(d->hwirq);330330+ writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);331331+}332332+333333+static void armada_370_xp_ipi_unmask(struct irq_data *d)334334+{335335+ u32 reg;336336+ reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);337337+ reg |= BIT(d->hwirq);338338+ writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);339339+}340340+341341+static void armada_370_xp_ipi_send_mask(struct irq_data *d,342342+ const struct cpumask *mask)343343+{344344+ unsigned long map = 0;345345+ int cpu;346346+347347+ /* Convert our logical CPU mask into a physical one. */348348+ for_each_cpu(cpu, mask)349349+ map |= 1 << cpu_logical_map(cpu);350350+351351+ /*352352+ * Ensure that stores to Normal memory are visible to the353353+ * other CPUs before issuing the IPI.354354+ */355355+ dsb();356356+357357+ /* submit softirq */358358+ writel((map << 8) | d->hwirq, main_int_base +359359+ ARMADA_370_XP_SW_TRIG_INT_OFFS);360360+}361361+362362+static void armada_370_xp_ipi_eoi(struct irq_data *d)363363+{364364+ writel(~BIT(d->hwirq), per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);365365+}366366+367367+static struct irq_chip ipi_irqchip = {368368+ .name = "IPI",369369+ .irq_mask = armada_370_xp_ipi_mask,370370+ .irq_unmask = armada_370_xp_ipi_unmask,371371+ .irq_eoi = armada_370_xp_ipi_eoi,372372+ .ipi_send_mask = armada_370_xp_ipi_send_mask,373373+};374374+375375+static int armada_370_xp_ipi_alloc(struct irq_domain *d,376376+ unsigned int virq,377377+ unsigned int nr_irqs, void *args)378378+{379379+ int i;380380+381381+ for (i = 0; i < nr_irqs; i++) {382382+ irq_set_percpu_devid(virq + i);383383+ irq_domain_set_info(d, virq + i, i, &ipi_irqchip,384384+ d->host_data,385385+ handle_percpu_devid_fasteoi_ipi,386386+ NULL, NULL);387387+ }388388+389389+ return 0;390390+}391391+392392+static void armada_370_xp_ipi_free(struct irq_domain *d,393393+ unsigned int virq,394394+ unsigned int nr_irqs)395395+{396396+ /* Not freeing IPIs */397397+}398398+399399+static const struct irq_domain_ops ipi_domain_ops = {400400+ .alloc = armada_370_xp_ipi_alloc,401401+ .free = armada_370_xp_ipi_free,402402+};403403+404404+static void ipi_resume(void)405405+{406406+ int i;407407+408408+ for (i = 0; i < IPI_DOORBELL_END; i++) {409409+ int irq;410410+411411+ irq = irq_find_mapping(ipi_domain, i);412412+ if (irq <= 0)413413+ continue;414414+ if (irq_percpu_is_enabled(irq)) {415415+ struct irq_data *d;416416+ d = irq_domain_get_irq_data(ipi_domain, irq);417417+ armada_370_xp_ipi_unmask(d);418418+ }419419+ }420420+}421421+422422+static __init void armada_xp_ipi_init(struct device_node *node)423423+{424424+ int base_ipi;425425+426426+ ipi_domain = irq_domain_create_linear(of_node_to_fwnode(node),427427+ IPI_DOORBELL_END,428428+ &ipi_domain_ops, NULL);429429+ if (WARN_ON(!ipi_domain))430430+ return;431431+432432+ irq_domain_update_bus_token(ipi_domain, DOMAIN_BUS_IPI);433433+ base_ipi = __irq_domain_alloc_irqs(ipi_domain, -1, IPI_DOORBELL_END,434434+ NUMA_NO_NODE, NULL, false, NULL);435435+ if (WARN_ON(!base_ipi))436436+ return;437437+438438+ set_smp_ipi_range(base_ipi, IPI_DOORBELL_END);439439+}440440+314441static DEFINE_RAW_SPINLOCK(irq_controller_lock);315442316443static int armada_xp_set_affinity(struct irq_data *d,···461334462335 return IRQ_SET_MASK_OK;463336}337337+338338+static void armada_xp_mpic_smp_cpu_init(void)339339+{340340+ u32 control;341341+ int nr_irqs, i;342342+343343+ control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL);344344+ nr_irqs = (control >> 2) & 0x3ff;345345+346346+ for (i = 0; i < nr_irqs; i++)347347+ writel(i, per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK_OFFS);348348+349349+ /* Disable all IPIs */350350+ writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);351351+352352+ /* Clear pending IPIs */353353+ writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);354354+355355+ /* Unmask IPI interrupt */356356+ writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);357357+}358358+359359+static void armada_xp_mpic_reenable_percpu(void)360360+{361361+ unsigned int irq;362362+363363+ /* Re-enable per-CPU interrupts that were enabled before suspend */364364+ for (irq = 0; irq < ARMADA_370_XP_MAX_PER_CPU_IRQS; irq++) {365365+ struct irq_data *data;366366+ int virq;367367+368368+ virq = irq_linear_revmap(armada_370_xp_mpic_domain, irq);369369+ if (virq == 0)370370+ continue;371371+372372+ data = irq_get_irq_data(virq);373373+374374+ if (!irq_percpu_is_enabled(virq))375375+ continue;376376+377377+ armada_370_xp_irq_unmask(data);378378+ }379379+380380+ ipi_resume();381381+}382382+383383+static int armada_xp_mpic_starting_cpu(unsigned int cpu)384384+{385385+ armada_xp_mpic_perf_init();386386+ armada_xp_mpic_smp_cpu_init();387387+ armada_xp_mpic_reenable_percpu();388388+ return 0;389389+}390390+391391+static int mpic_cascaded_starting_cpu(unsigned int cpu)392392+{393393+ armada_xp_mpic_perf_init();394394+ armada_xp_mpic_reenable_percpu();395395+ enable_percpu_irq(parent_irq, IRQ_TYPE_NONE);396396+ return 0;397397+}398398+#else399399+static void armada_xp_mpic_smp_cpu_init(void) {}400400+static void ipi_resume(void) {}464401#endif465402466403static struct irq_chip armada_370_xp_irq_chip = {···562371563372 return 0;564373}565565-566566-static void armada_xp_mpic_smp_cpu_init(void)567567-{568568- u32 control;569569- int nr_irqs, i;570570-571571- control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL);572572- nr_irqs = (control >> 2) & 0x3ff;573573-574574- for (i = 0; i < nr_irqs; i++)575575- writel(i, per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK_OFFS);576576-577577- /* Clear pending IPIs */578578- writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);579579-580580- /* Enable first 8 IPIs */581581- writel(IPI_DOORBELL_MASK, per_cpu_int_base +582582- ARMADA_370_XP_IN_DRBEL_MSK_OFFS);583583-584584- /* Unmask IPI interrupt */585585- writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);586586-}587587-588588-static void armada_xp_mpic_perf_init(void)589589-{590590- unsigned long cpuid = cpu_logical_map(smp_processor_id());591591-592592- /* Enable Performance Counter Overflow interrupts */593593- writel(ARMADA_370_XP_INT_CAUSE_PERF(cpuid),594594- per_cpu_int_base + ARMADA_370_XP_INT_FABRIC_MASK_OFFS);595595-}596596-597597-#ifdef CONFIG_SMP598598-static void armada_mpic_send_doorbell(const struct cpumask *mask,599599- unsigned int irq)600600-{601601- int cpu;602602- unsigned long map = 0;603603-604604- /* Convert our logical CPU mask into a physical one. */605605- for_each_cpu(cpu, mask)606606- map |= 1 << cpu_logical_map(cpu);607607-608608- /*609609- * Ensure that stores to Normal memory are visible to the610610- * other CPUs before issuing the IPI.611611- */612612- dsb();613613-614614- /* submit softirq */615615- writel((map << 8) | irq, main_int_base +616616- ARMADA_370_XP_SW_TRIG_INT_OFFS);617617-}618618-619619-static void armada_xp_mpic_reenable_percpu(void)620620-{621621- unsigned int irq;622622-623623- /* Re-enable per-CPU interrupts that were enabled before suspend */624624- for (irq = 0; irq < ARMADA_370_XP_MAX_PER_CPU_IRQS; irq++) {625625- struct irq_data *data;626626- int virq;627627-628628- virq = irq_linear_revmap(armada_370_xp_mpic_domain, irq);629629- if (virq == 0)630630- continue;631631-632632- data = irq_get_irq_data(virq);633633-634634- if (!irq_percpu_is_enabled(virq))635635- continue;636636-637637- armada_370_xp_irq_unmask(data);638638- }639639-}640640-641641-static int armada_xp_mpic_starting_cpu(unsigned int cpu)642642-{643643- armada_xp_mpic_perf_init();644644- armada_xp_mpic_smp_cpu_init();645645- armada_xp_mpic_reenable_percpu();646646- return 0;647647-}648648-649649-static int mpic_cascaded_starting_cpu(unsigned int cpu)650650-{651651- armada_xp_mpic_perf_init();652652- armada_xp_mpic_reenable_percpu();653653- enable_percpu_irq(parent_irq, IRQ_TYPE_NONE);654654- return 0;655655-}656656-#endif657374658375static const struct irq_domain_ops armada_370_xp_mpic_irq_ops = {659376 .map = armada_370_xp_mpic_irq_map,···661562#ifdef CONFIG_SMP662563 /* IPI Handling */663564 if (irqnr == 0) {664664- u32 ipimask, ipinr;565565+ unsigned long ipimask;566566+ int ipi;665567666568 ipimask = readl_relaxed(per_cpu_int_base +667569 ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)668570 & IPI_DOORBELL_MASK;669571670670- writel(~ipimask, per_cpu_int_base +671671- ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);672672-673673- /* Handle all pending doorbells */674674- for (ipinr = IPI_DOORBELL_START;675675- ipinr < IPI_DOORBELL_END; ipinr++) {676676- if (ipimask & (0x1 << ipinr))677677- handle_IPI(ipinr, regs);678678- }679679- continue;572572+ for_each_set_bit(ipi, &ipimask, IPI_DOORBELL_END)573573+ handle_domain_irq(ipi_domain, ipi, regs);680574 }681575#endif682576···728636 writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);729637 if (doorbell_mask_reg & PCI_MSI_DOORBELL_MASK)730638 writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);639639+640640+ ipi_resume();731641}732642733643static struct syscore_ops armada_370_xp_mpic_syscore_ops = {···785691 irq_set_default_host(armada_370_xp_mpic_domain);786692 set_handle_irq(armada_370_xp_handle_irq);787693#ifdef CONFIG_SMP788788- set_smp_cross_call(armada_mpic_send_doorbell);694694+ armada_xp_ipi_init(node);789695 cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_ARMADA_XP_STARTING,790696 "irqchip/armada/ipi:starting",791697 armada_xp_mpic_starting_cpu, NULL);
+130-29
drivers/irqchip/irq-bcm2836.c
···1010#include <linux/of_irq.h>1111#include <linux/irqchip.h>1212#include <linux/irqdomain.h>1313+#include <linux/irqchip/chained_irq.h>1314#include <linux/irqchip/irq-bcm2836.h>14151516#include <asm/exception.h>···9089 .irq_unmask = bcm2836_arm_irqchip_unmask_gpu_irq,9190};92919292+static void bcm2836_arm_irqchip_dummy_op(struct irq_data *d)9393+{9494+}9595+9696+static struct irq_chip bcm2836_arm_irqchip_dummy = {9797+ .name = "bcm2836-dummy",9898+ .irq_eoi = bcm2836_arm_irqchip_dummy_op,9999+};100100+93101static int bcm2836_map(struct irq_domain *d, unsigned int irq,94102 irq_hw_number_t hw)95103{96104 struct irq_chip *chip;9710598106 switch (hw) {107107+ case LOCAL_IRQ_MAILBOX0:108108+ chip = &bcm2836_arm_irqchip_dummy;109109+ break;99110 case LOCAL_IRQ_CNTPSIRQ:100111 case LOCAL_IRQ_CNTPNSIRQ:101112 case LOCAL_IRQ_CNTHPIRQ:···140127 u32 stat;141128142129 stat = readl_relaxed(intc.base + LOCAL_IRQ_PENDING0 + 4 * cpu);143143- if (stat & BIT(LOCAL_IRQ_MAILBOX0)) {144144-#ifdef CONFIG_SMP145145- void __iomem *mailbox0 = (intc.base +146146- LOCAL_MAILBOX0_CLR0 + 16 * cpu);147147- u32 mbox_val = readl(mailbox0);148148- u32 ipi = ffs(mbox_val) - 1;149149-150150- writel(1 << ipi, mailbox0);151151- handle_IPI(ipi, regs);152152-#endif153153- } else if (stat) {130130+ if (stat) {154131 u32 hwirq = ffs(stat) - 1;155132156133 handle_domain_irq(intc.domain, hwirq, regs);···148145}149146150147#ifdef CONFIG_SMP151151-static void bcm2836_arm_irqchip_send_ipi(const struct cpumask *mask,152152- unsigned int ipi)148148+static struct irq_domain *ipi_domain;149149+150150+static void bcm2836_arm_irqchip_handle_ipi(struct irq_desc *desc)151151+{152152+ struct irq_chip *chip = irq_desc_get_chip(desc);153153+ int cpu = smp_processor_id();154154+ u32 mbox_val;155155+156156+ chained_irq_enter(chip, desc);157157+158158+ mbox_val = readl_relaxed(intc.base + LOCAL_MAILBOX0_CLR0 + 16 * cpu);159159+ if (mbox_val) {160160+ int hwirq = ffs(mbox_val) - 1;161161+ generic_handle_irq(irq_find_mapping(ipi_domain, hwirq));162162+ }163163+164164+ chained_irq_exit(chip, desc);165165+}166166+167167+static void bcm2836_arm_irqchip_ipi_eoi(struct irq_data *d)168168+{169169+ int cpu = smp_processor_id();170170+171171+ writel_relaxed(BIT(d->hwirq),172172+ intc.base + LOCAL_MAILBOX0_CLR0 + 16 * cpu);173173+}174174+175175+static void bcm2836_arm_irqchip_ipi_send_mask(struct irq_data *d,176176+ const struct cpumask *mask)153177{154178 int cpu;155179 void __iomem *mailbox0_base = intc.base + LOCAL_MAILBOX0_SET0;···187157 */188158 smp_wmb();189159190190- for_each_cpu(cpu, mask) {191191- writel(1 << ipi, mailbox0_base + 16 * cpu);192192- }160160+ for_each_cpu(cpu, mask)161161+ writel_relaxed(BIT(d->hwirq), mailbox0_base + 16 * cpu);193162}163163+164164+static struct irq_chip bcm2836_arm_irqchip_ipi = {165165+ .name = "IPI",166166+ .irq_mask = bcm2836_arm_irqchip_dummy_op,167167+ .irq_unmask = bcm2836_arm_irqchip_dummy_op,168168+ .irq_eoi = bcm2836_arm_irqchip_ipi_eoi,169169+ .ipi_send_mask = bcm2836_arm_irqchip_ipi_send_mask,170170+};171171+172172+static int bcm2836_arm_irqchip_ipi_alloc(struct irq_domain *d,173173+ unsigned int virq,174174+ unsigned int nr_irqs, void *args)175175+{176176+ int i;177177+178178+ for (i = 0; i < nr_irqs; i++) {179179+ irq_set_percpu_devid(virq + i);180180+ irq_domain_set_info(d, virq + i, i, &bcm2836_arm_irqchip_ipi,181181+ d->host_data,182182+ handle_percpu_devid_fasteoi_ipi,183183+ NULL, NULL);184184+ }185185+186186+ return 0;187187+}188188+189189+static void bcm2836_arm_irqchip_ipi_free(struct irq_domain *d,190190+ unsigned int virq,191191+ unsigned int nr_irqs)192192+{193193+ /* Not freeing IPIs */194194+}195195+196196+static const struct irq_domain_ops ipi_domain_ops = {197197+ .alloc = bcm2836_arm_irqchip_ipi_alloc,198198+ .free = bcm2836_arm_irqchip_ipi_free,199199+};194200195201static int bcm2836_cpu_starting(unsigned int cpu)196202{···241175 cpu);242176 return 0;243177}178178+179179+#define BITS_PER_MBOX 32180180+181181+static void bcm2836_arm_irqchip_smp_init(void)182182+{183183+ struct irq_fwspec ipi_fwspec = {184184+ .fwnode = intc.domain->fwnode,185185+ .param_count = 1,186186+ .param = {187187+ [0] = LOCAL_IRQ_MAILBOX0,188188+ },189189+ };190190+ int base_ipi, mux_irq;191191+192192+ mux_irq = irq_create_fwspec_mapping(&ipi_fwspec);193193+ if (WARN_ON(mux_irq <= 0))194194+ return;195195+196196+ ipi_domain = irq_domain_create_linear(intc.domain->fwnode,197197+ BITS_PER_MBOX, &ipi_domain_ops,198198+ NULL);199199+ if (WARN_ON(!ipi_domain))200200+ return;201201+202202+ ipi_domain->flags |= IRQ_DOMAIN_FLAG_IPI_SINGLE;203203+ irq_domain_update_bus_token(ipi_domain, DOMAIN_BUS_IPI);204204+205205+ base_ipi = __irq_domain_alloc_irqs(ipi_domain, -1, BITS_PER_MBOX,206206+ NUMA_NO_NODE, NULL,207207+ false, NULL);208208+209209+ if (WARN_ON(!base_ipi))210210+ return;211211+212212+ set_smp_ipi_range(base_ipi, BITS_PER_MBOX);213213+214214+ irq_set_chained_handler_and_data(mux_irq,215215+ bcm2836_arm_irqchip_handle_ipi, NULL);216216+217217+ /* Unmask IPIs to the boot CPU. */218218+ cpuhp_setup_state(CPUHP_AP_IRQ_BCM2836_STARTING,219219+ "irqchip/bcm2836:starting", bcm2836_cpu_starting,220220+ bcm2836_cpu_dying);221221+}222222+#else223223+#define bcm2836_arm_irqchip_smp_init() do { } while(0)244224#endif245225246226static const struct irq_domain_ops bcm2836_arm_irqchip_intc_ops = {247227 .xlate = irq_domain_xlate_onetwocell,248228 .map = bcm2836_map,249229};250250-251251-static void252252-bcm2836_arm_irqchip_smp_init(void)253253-{254254-#ifdef CONFIG_SMP255255- /* Unmask IPIs to the boot CPU. */256256- cpuhp_setup_state(CPUHP_AP_IRQ_BCM2836_STARTING,257257- "irqchip/bcm2836:starting", bcm2836_cpu_starting,258258- bcm2836_cpu_dying);259259-260260- set_smp_cross_call(bcm2836_arm_irqchip_send_ipi);261261-#endif262262-}263230264231/*265232 * The LOCAL_IRQ_CNT* timer firings are based off of the external···330231 NULL);331232 if (!intc.domain)332233 panic("%pOF: unable to create IRQ domain\n", node);234234+235235+ irq_domain_update_bus_token(intc.domain, DOMAIN_BUS_WIRED);333236334237 bcm2836_arm_irqchip_smp_init();335238
-3
drivers/irqchip/irq-gic-common.c
···152152 writel_relaxed(GICD_INT_DEF_PRI_X4,153153 base + GIC_DIST_PRI + i * 4 / 4);154154155155- /* Ensure all SGI interrupts are now enabled */156156- writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET);157157-158155 if (sync_access)159156 sync_access();160157}
+66-46
drivers/irqchip/irq-gic-v3.c
···3636#define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0)3737#define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1)38383939+#define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1)4040+3941struct redist_region {4042 void __iomem *redist_base;4143 phys_addr_t phys_base;···115113#define DEFAULT_PMR_VALUE 0xf0116114117115enum gic_intid_range {116116+ SGI_RANGE,118117 PPI_RANGE,119118 SPI_RANGE,120119 EPPI_RANGE,···127124static enum gic_intid_range __get_intid_range(irq_hw_number_t hwirq)128125{129126 switch (hwirq) {127127+ case 0 ... 15:128128+ return SGI_RANGE;130129 case 16 ... 31:131130 return PPI_RANGE;132131 case 32 ... 1019:···154149 return d->hwirq;155150}156151157157-static inline int gic_irq_in_rdist(struct irq_data *d)152152+static inline bool gic_irq_in_rdist(struct irq_data *d)158153{159159- enum gic_intid_range range = get_intid_range(d);160160- return range == PPI_RANGE || range == EPPI_RANGE;154154+ switch (get_intid_range(d)) {155155+ case SGI_RANGE:156156+ case PPI_RANGE:157157+ case EPPI_RANGE:158158+ return true;159159+ default:160160+ return false;161161+ }161162}162163163164static inline void __iomem *gic_dist_base(struct irq_data *d)164165{165166 switch (get_intid_range(d)) {167167+ case SGI_RANGE:166168 case PPI_RANGE:167169 case EPPI_RANGE:168170 /* SGI+PPI -> SGI_base for this CPU */···266254static u32 convert_offset_index(struct irq_data *d, u32 offset, u32 *index)267255{268256 switch (get_intid_range(d)) {257257+ case SGI_RANGE:269258 case PPI_RANGE:270259 case SPI_RANGE:271260 *index = d->hwirq;···386373{387374 u32 reg;388375389389- if (d->hwirq >= 8192) /* PPI/SPI only */376376+ if (d->hwirq >= 8192) /* SGI/PPI/SPI only */390377 return -EINVAL;391378392379 switch (which) {···553540 u32 offset, index;554541 int ret;555542556556- /* Interrupt configuration for SGIs can't be changed */557557- if (irq < 16)558558- return -EINVAL;559559-560543 range = get_intid_range(d);544544+545545+ /* Interrupt configuration for SGIs can't be changed */546546+ if (range == SGI_RANGE)547547+ return type != IRQ_TYPE_EDGE_RISING ? -EINVAL : 0;561548562549 /* SPIs have restrictions on the supported types */563550 if ((range == SPI_RANGE || range == ESPI_RANGE) &&···586573587574static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)588575{576576+ if (get_intid_range(d) == SGI_RANGE)577577+ return -EINVAL;578578+589579 if (vcpu)590580 irqd_set_forwarded_to_vcpu(d);591581 else···663647 if ((irqnr >= 1020 && irqnr <= 1023))664648 return;665649666666- /* Treat anything but SGIs in a uniform way */667667- if (likely(irqnr > 15)) {668668- int err;669669-670670- if (static_branch_likely(&supports_deactivate_key))671671- gic_write_eoir(irqnr);672672- else673673- isb();674674-675675- err = handle_domain_irq(gic_data.domain, irqnr, regs);676676- if (err) {677677- WARN_ONCE(true, "Unexpected interrupt received!\n");678678- gic_deactivate_unhandled(irqnr);679679- }680680- return;681681- }682682- if (irqnr < 16) {650650+ if (static_branch_likely(&supports_deactivate_key))683651 gic_write_eoir(irqnr);684684- if (static_branch_likely(&supports_deactivate_key))685685- gic_write_dir(irqnr);686686-#ifdef CONFIG_SMP687687- /*688688- * Unlike GICv2, we don't need an smp_rmb() here.689689- * The control dependency from gic_read_iar to690690- * the ISB in gic_write_eoir is enough to ensure691691- * that any shared data read by handle_IPI will692692- * be read after the ACK.693693- */694694- handle_IPI(irqnr, regs);695695-#else696696- WARN_ONCE(true, "Unexpected SGI received!\n");697697-#endif652652+ else653653+ isb();654654+655655+ if (handle_domain_irq(gic_data.domain, irqnr, regs)) {656656+ WARN_ONCE(true, "Unexpected interrupt received!\n");657657+ gic_deactivate_unhandled(irqnr);698658 }699659}700660···11241132 gic_write_sgi1r(val);11251133}1126113411271127-static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)11351135+static void gic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask)11281136{11291137 int cpu;1130113811311131- if (WARN_ON(irq >= 16))11391139+ if (WARN_ON(d->hwirq >= 16))11321140 return;1133114111341142 /*···11421150 u16 tlist;1143115111441152 tlist = gic_compute_target_list(&cpu, mask, cluster_id);11451145- gic_send_sgi(cluster_id, tlist, irq);11531153+ gic_send_sgi(cluster_id, tlist, d->hwirq);11461154 }1147115511481156 /* Force the above writes to ICC_SGI1R_EL1 to be executed */···1151115911521160static void __init gic_smp_init(void)11531161{11541154- set_smp_cross_call(gic_raise_softirq);11621162+ struct irq_fwspec sgi_fwspec = {11631163+ .fwnode = gic_data.fwnode,11641164+ .param_count = 1,11651165+ };11661166+ int base_sgi;11671167+11551168 cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GIC_STARTING,11561169 "irqchip/arm/gicv3:starting",11571170 gic_starting_cpu, NULL);11711171+11721172+ /* Register all 8 non-secure SGIs */11731173+ base_sgi = __irq_domain_alloc_irqs(gic_data.domain, -1, 8,11741174+ NUMA_NO_NODE, &sgi_fwspec,11751175+ false, NULL);11761176+ if (WARN_ON(base_sgi <= 0))11771177+ return;11781178+11791179+ set_smp_ipi_range(base_sgi, 8);11581180}1159118111601182static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,···12171211}12181212#else12191213#define gic_set_affinity NULL12141214+#define gic_ipi_send_mask NULL12201215#define gic_smp_init() do { } while(0)12211216#endif12221217···12601253 .irq_set_irqchip_state = gic_irq_set_irqchip_state,12611254 .irq_nmi_setup = gic_irq_nmi_setup,12621255 .irq_nmi_teardown = gic_irq_nmi_teardown,12561256+ .ipi_send_mask = gic_ipi_send_mask,12631257 .flags = IRQCHIP_SET_TYPE_MASKED |12641258 IRQCHIP_SKIP_SET_WAKE |12651259 IRQCHIP_MASK_ON_SUSPEND,···12781270 .irq_set_vcpu_affinity = gic_irq_set_vcpu_affinity,12791271 .irq_nmi_setup = gic_irq_nmi_setup,12801272 .irq_nmi_teardown = gic_irq_nmi_teardown,12731273+ .ipi_send_mask = gic_ipi_send_mask,12811274 .flags = IRQCHIP_SET_TYPE_MASKED |12821275 IRQCHIP_SKIP_SET_WAKE |12831276 IRQCHIP_MASK_ON_SUSPEND,···12931284 chip = &gic_eoimode1_chip;1294128512951286 switch (__get_intid_range(hw)) {12871287+ case SGI_RANGE:12881288+ irq_set_percpu_devid(irq);12891289+ irq_domain_set_info(d, irq, hw, chip, d->host_data,12901290+ handle_percpu_devid_fasteoi_ipi,12911291+ NULL, NULL);12921292+ break;12931293+12961294 case PPI_RANGE:12971295 case EPPI_RANGE:12981296 irq_set_percpu_devid(irq);···13291313 return 0;13301314}1331131513321332-#define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1)13331333-13341316static int gic_irq_domain_translate(struct irq_domain *d,13351317 struct irq_fwspec *fwspec,13361318 unsigned long *hwirq,13371319 unsigned int *type)13381320{13211321+ if (fwspec->param_count == 1 && fwspec->param[0] < 16) {13221322+ *hwirq = fwspec->param[0];13231323+ *type = IRQ_TYPE_EDGE_RISING;13241324+ return 0;13251325+ }13261326+13391327 if (is_of_node(fwspec->fwnode)) {13401328 if (fwspec->param_count < 3)13411329 return -EINVAL;···1696167616971677 gic_update_rdist_properties();1698167816991699- gic_smp_init();17001679 gic_dist_init();17011680 gic_cpu_init();16811681+ gic_smp_init();17021682 gic_cpu_pm_init();1703168317041684 if (gic_dist_supports_lpis()) {
+139-106
drivers/irqchip/irq-gic.c
···8383#endif8484 struct irq_domain *domain;8585 unsigned int gic_irqs;8686-#ifdef CONFIG_GIC_NON_BANKED8787- void __iomem *(*get_base)(union gic_base *);8888-#endif8986};90879188#ifdef CONFIG_BL_SWITCHER···121124122125static struct gic_kvm_info gic_v2_kvm_info;123126127127+static DEFINE_PER_CPU(u32, sgi_intid);128128+124129#ifdef CONFIG_GIC_NON_BANKED125125-static void __iomem *gic_get_percpu_base(union gic_base *base)130130+static DEFINE_STATIC_KEY_FALSE(frankengic_key);131131+132132+static void enable_frankengic(void)126133{127127- return raw_cpu_read(*base->percpu_base);134134+ static_branch_enable(&frankengic_key);128135}129136130130-static void __iomem *gic_get_common_base(union gic_base *base)137137+static inline void __iomem *__get_base(union gic_base *base)131138{139139+ if (static_branch_unlikely(&frankengic_key))140140+ return raw_cpu_read(*base->percpu_base);141141+132142 return base->common_base;133143}134144135135-static inline void __iomem *gic_data_dist_base(struct gic_chip_data *data)136136-{137137- return data->get_base(&data->dist_base);138138-}139139-140140-static inline void __iomem *gic_data_cpu_base(struct gic_chip_data *data)141141-{142142- return data->get_base(&data->cpu_base);143143-}144144-145145-static inline void gic_set_base_accessor(struct gic_chip_data *data,146146- void __iomem *(*f)(union gic_base *))147147-{148148- data->get_base = f;149149-}145145+#define gic_data_dist_base(d) __get_base(&(d)->dist_base)146146+#define gic_data_cpu_base(d) __get_base(&(d)->cpu_base)150147#else151148#define gic_data_dist_base(d) ((d)->dist_base.common_base)152149#define gic_data_cpu_base(d) ((d)->cpu_base.common_base)153153-#define gic_set_base_accessor(d, f)150150+#define enable_frankengic() do { } while(0)154151#endif155152156153static inline void __iomem *gic_dist_base(struct irq_data *d)···217226218227static void gic_eoi_irq(struct irq_data *d)219228{220220- writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);229229+ u32 hwirq = gic_irq(d);230230+231231+ if (hwirq < 16)232232+ hwirq = this_cpu_read(sgi_intid);233233+234234+ writel_relaxed(hwirq, gic_cpu_base(d) + GIC_CPU_EOI);221235}222236223237static void gic_eoimode1_eoi_irq(struct irq_data *d)224238{239239+ u32 hwirq = gic_irq(d);240240+225241 /* Do not deactivate an IRQ forwarded to a vcpu. */226242 if (irqd_is_forwarded_to_vcpu(d))227243 return;228244229229- writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_DEACTIVATE);245245+ if (hwirq < 16)246246+ hwirq = this_cpu_read(sgi_intid);247247+248248+ writel_relaxed(hwirq, gic_cpu_base(d) + GIC_CPU_DEACTIVATE);230249}231250232251static int gic_irq_set_irqchip_state(struct irq_data *d,···296295297296 /* Interrupt configuration for SGIs can't be changed */298297 if (gicirq < 16)299299- return -EINVAL;298298+ return type != IRQ_TYPE_EDGE_RISING ? -EINVAL : 0;300299301300 /* SPIs have restrictions on the supported types */302301 if (gicirq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&···316315static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)317316{318317 /* Only interrupts on the primary GIC can be forwarded to a vcpu. */319319- if (cascading_gic_irq(d))318318+ if (cascading_gic_irq(d) || gic_irq(d) < 16)320319 return -EINVAL;321320322321 if (vcpu)···325324 irqd_clr_forwarded_to_vcpu(d);326325 return 0;327326}328328-329329-#ifdef CONFIG_SMP330330-static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,331331- bool force)332332-{333333- void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + gic_irq(d);334334- unsigned int cpu;335335-336336- if (!force)337337- cpu = cpumask_any_and(mask_val, cpu_online_mask);338338- else339339- cpu = cpumask_first(mask_val);340340-341341- if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)342342- return -EINVAL;343343-344344- writeb_relaxed(gic_cpu_map[cpu], reg);345345- irq_data_update_effective_affinity(d, cpumask_of(cpu));346346-347347- return IRQ_SET_MASK_OK_DONE;348348-}349349-#endif350327351328static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)352329{···336357 irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);337358 irqnr = irqstat & GICC_IAR_INT_ID_MASK;338359339339- if (likely(irqnr > 15 && irqnr < 1020)) {340340- if (static_branch_likely(&supports_deactivate_key))341341- writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);342342- isb();343343- handle_domain_irq(gic->domain, irqnr, regs);344344- continue;345345- }346346- if (irqnr < 16) {360360+ if (unlikely(irqnr >= 1020))361361+ break;362362+363363+ if (static_branch_likely(&supports_deactivate_key))347364 writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);348348- if (static_branch_likely(&supports_deactivate_key))349349- writel_relaxed(irqstat, cpu_base + GIC_CPU_DEACTIVATE);350350-#ifdef CONFIG_SMP351351- /*352352- * Ensure any shared data written by the CPU sending353353- * the IPI is read after we've read the ACK register354354- * on the GIC.355355- *356356- * Pairs with the write barrier in gic_raise_softirq357357- */365365+ isb();366366+367367+ /*368368+ * Ensure any shared data written by the CPU sending the IPI369369+ * is read after we've read the ACK register on the GIC.370370+ *371371+ * Pairs with the write barrier in gic_ipi_send_mask372372+ */373373+ if (irqnr <= 15) {358374 smp_rmb();359359- handle_IPI(irqnr, regs);360360-#endif361361- continue;375375+376376+ /*377377+ * The GIC encodes the source CPU in GICC_IAR,378378+ * leading to the deactivation to fail if not379379+ * written back as is to GICC_EOI. Stash the INTID380380+ * away for gic_eoi_irq() to write back. This only381381+ * works because we don't nest SGIs...382382+ */383383+ this_cpu_write(sgi_intid, irqstat);362384 }363363- break;385385+386386+ handle_domain_irq(gic->domain, irqnr, regs);364387 } while (1);365388}366389···709728 int i;710729711730 for (i = 0; i < CONFIG_ARM_GIC_MAX_NR; i++) {712712-#ifdef CONFIG_GIC_NON_BANKED713713- /* Skip over unused GICs */714714- if (!gic_data[i].get_base)715715- continue;716716-#endif717731 switch (cmd) {718732 case CPU_PM_ENTER:719733 gic_cpu_save(&gic_data[i]);···771795#endif772796773797#ifdef CONFIG_SMP774774-static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)798798+static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,799799+ bool force)800800+{801801+ void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + gic_irq(d);802802+ unsigned int cpu;803803+804804+ if (!force)805805+ cpu = cpumask_any_and(mask_val, cpu_online_mask);806806+ else807807+ cpu = cpumask_first(mask_val);808808+809809+ if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)810810+ return -EINVAL;811811+812812+ writeb_relaxed(gic_cpu_map[cpu], reg);813813+ irq_data_update_effective_affinity(d, cpumask_of(cpu));814814+815815+ return IRQ_SET_MASK_OK_DONE;816816+}817817+818818+static void gic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask)775819{776820 int cpu;777821 unsigned long flags, map = 0;778822779823 if (unlikely(nr_cpu_ids == 1)) {780824 /* Only one CPU? let's do a self-IPI... */781781- writel_relaxed(2 << 24 | irq,825825+ writel_relaxed(2 << 24 | d->hwirq,782826 gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);783827 return;784828 }···816820 dmb(ishst);817821818822 /* this always happens on GIC0 */819819- writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);823823+ writel_relaxed(map << 16 | d->hwirq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);820824821825 gic_unlock_irqrestore(flags);822826}827827+828828+static int gic_starting_cpu(unsigned int cpu)829829+{830830+ gic_cpu_init(&gic_data[0]);831831+ return 0;832832+}833833+834834+static __init void gic_smp_init(void)835835+{836836+ struct irq_fwspec sgi_fwspec = {837837+ .fwnode = gic_data[0].domain->fwnode,838838+ .param_count = 1,839839+ };840840+ int base_sgi;841841+842842+ cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GIC_STARTING,843843+ "irqchip/arm/gic:starting",844844+ gic_starting_cpu, NULL);845845+846846+ base_sgi = __irq_domain_alloc_irqs(gic_data[0].domain, -1, 8,847847+ NUMA_NO_NODE, &sgi_fwspec,848848+ false, NULL);849849+ if (WARN_ON(base_sgi <= 0))850850+ return;851851+852852+ set_smp_ipi_range(base_sgi, 8);853853+}854854+#else855855+#define gic_smp_init() do { } while(0)856856+#define gic_set_affinity NULL857857+#define gic_ipi_send_mask NULL823858#endif824859825860#ifdef CONFIG_BL_SWITCHER···997970{998971 struct gic_chip_data *gic = d->host_data;99997210001000- if (hw < 32) {973973+ switch (hw) {974974+ case 0 ... 15:975975+ irq_set_percpu_devid(irq);976976+ irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,977977+ handle_percpu_devid_fasteoi_ipi,978978+ NULL, NULL);979979+ break;980980+ case 16 ... 31:1001981 irq_set_percpu_devid(irq);1002982 irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,1003983 handle_percpu_devid_irq, NULL, NULL);10041004- } else {984984+ break;985985+ default:1005986 irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,1006987 handle_fasteoi_irq, NULL, NULL);1007988 irq_set_probe(irq);1008989 irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));990990+ break;1009991 }1010992 return 0;1011993}···1028992 unsigned long *hwirq,1029993 unsigned int *type)1030994{995995+ if (fwspec->param_count == 1 && fwspec->param[0] < 16) {996996+ *hwirq = fwspec->param[0];997997+ *type = IRQ_TYPE_EDGE_RISING;998998+ return 0;999999+ }10001000+10311001 if (is_of_node(fwspec->fwnode)) {10321002 if (fwspec->param_count < 3)10331003 return -EINVAL;1034100410351035- /* Get the interrupt number and add 16 to skip over SGIs */10361036- *hwirq = fwspec->param[1] + 16;10371037-10381038- /*10391039- * For SPIs, we need to add 16 more to get the GIC irq10401040- * ID number10411041- */10421042- if (!fwspec->param[0])10431043- *hwirq += 16;10051005+ switch (fwspec->param[0]) {10061006+ case 0: /* SPI */10071007+ *hwirq = fwspec->param[1] + 32;10081008+ break;10091009+ case 1: /* PPI */10101010+ *hwirq = fwspec->param[1] + 16;10111011+ break;10121012+ default:10131013+ return -EINVAL;10141014+ }1044101510451016 *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;10461017···10681025 }1069102610701027 return -EINVAL;10711071-}10721072-10731073-static int gic_starting_cpu(unsigned int cpu)10741074-{10751075- gic_cpu_init(&gic_data[0]);10761076- return 0;10771028}1078102910791030static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,···11161079 gic->chip.irq_set_vcpu_affinity = gic_irq_set_vcpu_affinity;11171080 }1118108111191119-#ifdef CONFIG_SMP11201120- if (gic == &gic_data[0])10821082+ if (gic == &gic_data[0]) {11211083 gic->chip.irq_set_affinity = gic_set_affinity;11221122-#endif10841084+ gic->chip.ipi_send_mask = gic_ipi_send_mask;10851085+ }11231086}1124108711251088static int gic_init_bases(struct gic_chip_data *gic,···11491112 gic->raw_cpu_base + offset;11501113 }1151111411521152- gic_set_base_accessor(gic, gic_get_percpu_base);11151115+ enable_frankengic();11531116 } else {11541117 /* Normal, sane GIC... */11551118 WARN(gic->percpu_offset,···11571120 gic->percpu_offset);11581121 gic->dist_base.common_base = gic->raw_dist_base;11591122 gic->cpu_base.common_base = gic->raw_cpu_base;11601160- gic_set_base_accessor(gic, gic_get_common_base);11611123 }1162112411631125 /*···12351199 */12361200 for (i = 0; i < NR_GIC_CPU_IF; i++)12371201 gic_cpu_map[i] = 0xff;12381238-#ifdef CONFIG_SMP12391239- set_smp_cross_call(gic_raise_softirq);12401240-#endif12411241- cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GIC_STARTING,12421242- "irqchip/arm/gic:starting",12431243- gic_starting_cpu, NULL);12021202+12441203 set_handle_irq(gic_handle_irq);12451204 if (static_branch_likely(&supports_deactivate_key))12461205 pr_info("GIC: Using split EOI/Deactivate mode\n");···12521221 ret = gic_init_bases(gic, handle);12531222 if (ret)12541223 kfree(name);12241224+ else if (gic == &gic_data[0])12251225+ gic_smp_init();1255122612561227 return ret;12571228}
+40-49
drivers/irqchip/irq-hip04.c
···171171172172 return IRQ_SET_MASK_OK;173173}174174+175175+static void hip04_ipi_send_mask(struct irq_data *d, const struct cpumask *mask)176176+{177177+ int cpu;178178+ unsigned long flags, map = 0;179179+180180+ raw_spin_lock_irqsave(&irq_controller_lock, flags);181181+182182+ /* Convert our logical CPU mask into a physical one. */183183+ for_each_cpu(cpu, mask)184184+ map |= hip04_cpu_map[cpu];185185+186186+ /*187187+ * Ensure that stores to Normal memory are visible to the188188+ * other CPUs before they observe us issuing the IPI.189189+ */190190+ dmb(ishst);191191+192192+ /* this always happens on GIC0 */193193+ writel_relaxed(map << 8 | d->hwirq, hip04_data.dist_base + GIC_DIST_SOFTINT);194194+195195+ raw_spin_unlock_irqrestore(&irq_controller_lock, flags);196196+}174197#endif175198176199static void __exception_irq_entry hip04_handle_irq(struct pt_regs *regs)···205182 irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);206183 irqnr = irqstat & GICC_IAR_INT_ID_MASK;207184208208- if (likely(irqnr > 15 && irqnr <= HIP04_MAX_IRQS)) {185185+ if (irqnr <= HIP04_MAX_IRQS)209186 handle_domain_irq(hip04_data.domain, irqnr, regs);210210- continue;211211- }212212- if (irqnr < 16) {213213- writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);214214-#ifdef CONFIG_SMP215215- handle_IPI(irqnr, regs);216216-#endif217217- continue;218218- }219219- break;220220- } while (1);187187+ } while (irqnr > HIP04_MAX_IRQS);221188}222189223190static struct irq_chip hip04_irq_chip = {···218205 .irq_set_type = hip04_irq_set_type,219206#ifdef CONFIG_SMP220207 .irq_set_affinity = hip04_irq_set_affinity,208208+ .ipi_send_mask = hip04_ipi_send_mask,221209#endif222210 .flags = IRQCHIP_SET_TYPE_MASKED |223211 IRQCHIP_SKIP_SET_WAKE |···293279 writel_relaxed(1, base + GIC_CPU_CTRL);294280}295281296296-#ifdef CONFIG_SMP297297-static void hip04_raise_softirq(const struct cpumask *mask, unsigned int irq)298298-{299299- int cpu;300300- unsigned long flags, map = 0;301301-302302- raw_spin_lock_irqsave(&irq_controller_lock, flags);303303-304304- /* Convert our logical CPU mask into a physical one. */305305- for_each_cpu(cpu, mask)306306- map |= hip04_cpu_map[cpu];307307-308308- /*309309- * Ensure that stores to Normal memory are visible to the310310- * other CPUs before they observe us issuing the IPI.311311- */312312- dmb(ishst);313313-314314- /* this always happens on GIC0 */315315- writel_relaxed(map << 8 | irq, hip04_data.dist_base + GIC_DIST_SOFTINT);316316-317317- raw_spin_unlock_irqrestore(&irq_controller_lock, flags);318318-}319319-#endif320320-321282static int hip04_irq_domain_map(struct irq_domain *d, unsigned int irq,322283 irq_hw_number_t hw)323284{324324- if (hw < 32) {285285+ if (hw < 16) {286286+ irq_set_percpu_devid(irq);287287+ irq_set_chip_and_handler(irq, &hip04_irq_chip,288288+ handle_percpu_devid_fasteoi_ipi);289289+ } else if (hw < 32) {325290 irq_set_percpu_devid(irq);326291 irq_set_chip_and_handler(irq, &hip04_irq_chip,327292 handle_percpu_devid_irq);328328- irq_set_status_flags(irq, IRQ_NOAUTOEN);329293 } else {330294 irq_set_chip_and_handler(irq, &hip04_irq_chip,331295 handle_fasteoi_irq);···320328 unsigned long *out_hwirq,321329 unsigned int *out_type)322330{323323- unsigned long ret = 0;324324-325331 if (irq_domain_get_of_node(d) != controller)326332 return -EINVAL;333333+ if (intsize == 1 && intspec[0] < 16) {334334+ *out_hwirq = intspec[0];335335+ *out_type = IRQ_TYPE_EDGE_RISING;336336+ return 0;337337+ }327338 if (intsize < 3)328339 return -EINVAL;329340···339344340345 *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;341346342342- return ret;347347+ return 0;343348}344349345350static int hip04_irq_starting_cpu(unsigned int cpu)···356361static int __init357362hip04_of_init(struct device_node *node, struct device_node *parent)358363{359359- irq_hw_number_t hwirq_base = 16;360364 int nr_irqs, irq_base, i;361365362366 if (WARN_ON(!node))···384390 nr_irqs = HIP04_MAX_IRQS;385391 hip04_data.nr_irqs = nr_irqs;386392387387- nr_irqs -= hwirq_base; /* calculate # of irqs to allocate */388388-389389- irq_base = irq_alloc_descs(-1, hwirq_base, nr_irqs, numa_node_id());393393+ irq_base = irq_alloc_descs(-1, 0, nr_irqs, numa_node_id());390394 if (irq_base < 0) {391395 pr_err("failed to allocate IRQ numbers\n");392396 return -EINVAL;393397 }394398395399 hip04_data.domain = irq_domain_add_legacy(node, nr_irqs, irq_base,396396- hwirq_base,400400+ 0,397401 &hip04_irq_domain_ops,398402 &hip04_data);399399-400403 if (WARN_ON(!hip04_data.domain))401404 return -EINVAL;402405403406#ifdef CONFIG_SMP404404- set_smp_cross_call(hip04_raise_softirq);407407+ set_smp_ipi_range(irq_base, 16);405408#endif406409 set_handle_irq(hip04_handle_irq);407410
···945945}946946947947/**948948+ * handle_percpu_devid_fasteoi_ipi - Per CPU local IPI handler with per cpu949949+ * dev ids950950+ * @desc: the interrupt description structure for this irq951951+ *952952+ * The biggest difference with the IRQ version is that the interrupt is953953+ * EOIed early, as the IPI could result in a context switch, and we need to954954+ * make sure the IPI can fire again. We also assume that the arch code has955955+ * registered an action. If not, we are positively doomed.956956+ */957957+void handle_percpu_devid_fasteoi_ipi(struct irq_desc *desc)958958+{959959+ struct irq_chip *chip = irq_desc_get_chip(desc);960960+ struct irqaction *action = desc->action;961961+ unsigned int irq = irq_desc_get_irq(desc);962962+ irqreturn_t res;963963+964964+ __kstat_incr_irqs_this_cpu(desc);965965+966966+ if (chip->irq_eoi)967967+ chip->irq_eoi(&desc->irq_data);968968+969969+ trace_irq_handler_entry(irq, action);970970+ res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id));971971+ trace_irq_handler_exit(irq, action, res);972972+}973973+974974+/**948975 * handle_percpu_devid_fasteoi_nmi - Per CPU local NMI handler with per cpu949976 * dev ids950977 * @desc: the interrupt description structure for this irq
···485485486486 rcu_read_lock();487487 desc = irq_to_desc(i);488488- if (!desc)488488+ if (!desc || irq_settings_is_hidden(desc))489489 goto outsparse;490490491491 if (desc->kstat_irqs)