From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.9 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3FE7BC433DB for ; Wed, 20 Jan 2021 13:32:17 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9CB922245C for ; Wed, 20 Jan 2021 13:32:16 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9CB922245C Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=caramail.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=DAhlFqfIHj4s/tcbazRzaZe+X0mQl4IabhHNLnz5pPc=; b=zgm2+IBtaeEueg1L44aQamsUi 22xPrK6y40bMthoKqJXMg1rNIt7brbaFcFxOKuETC+k59EcHQ3PUW2JhOtvOjod7FbaN2UnNMpgSw ApOQ3dKppWcCKH+pLeuP6NhAw1j2RQxF/rSzlUuC7XfMK5XMWkPcWBiGkM3hb63gr3IfTcLplGwZJ WY6va96UbPaWmoGk729Gh+WmORefOjVg/Jjc0+i+QPG8++IiZIjgYXIHm4qmmlvqGWDJmT0sIm4zS i5LV6pU807SmvLZIRIJ0GQSxANb2qnZELqXEhoHzBa9CUr+cyQAebAa9OV+t6ddpRz9kFmX1lfGxy ULleu7OGQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1l2DYT-0005N1-2n; Wed, 20 Jan 2021 13:29:49 +0000 Received: from mout.gmx.net ([212.227.15.15]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1l2DWW-0004fa-RE for linux-arm-kernel@lists.infradead.org; Wed, 20 Jan 2021 13:28:00 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1611149257; bh=SHyn+p6d9tSU0bcfld9T3QsMG6Kshj0bouj+YRflQxg=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:In-Reply-To:References; b=P331zmNtpup6C0kXjNW5FmI+oBCXedb91RdEpZqfhdBzOoUYF03n0snxnScZ6JMY/ 2MQY7me5Oq27GpOtqvyY+/sYQzH7V5i14H+UqdJHRtc5OfCVwcJFWSj90ADaQMMtWJ yl/Ty4eH7hrz8y7+EU3FyUr08FReijV+1qlJYgN8= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from localhost.localdomain ([83.204.192.78]) by mail.gmx.net (mrgmx004 [212.227.17.184]) with ESMTPSA (Nemesis) id 1MAwbz-1l931F3S7V-00BIC6; Wed, 20 Jan 2021 14:27:37 +0100 From: Mohamed Mediouni To: linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH 7/7] irqchip/apple-aic: add SMP support to the Apple AIC driver. Date: Wed, 20 Jan 2021 14:27:17 +0100 Message-Id: <20210120132717.395873-8-mohamed.mediouni@caramail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210120132717.395873-1-mohamed.mediouni@caramail.com> References: <20210120132717.395873-1-mohamed.mediouni@caramail.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:UzbF93QD7ewtU45SWccubUGzjxleBAEd8cENkEmwy10LMjhlCnd DQGo+V/owwH1jTprv0HzwwC3JeJOHcSnQBIxmfgUQ39kzXLLPeruGif+m1AEZfvdNb2zEIh nxuipyANKmNwsP4C+wyEBfjE+aJbBpaULJXKnuNjRJLcb2Y7feUNZiojJboECOxdIMtMDqD g4Cp71tGcP6AZdOnkKZyQ== X-UI-Out-Filterresults: notjunk:1;V03:K0:GiAGZBgh9e8=:ApCMlQctfbLVb/ERxyRHEW pTnRSo/156O+OQdCC5H2l6dRseBIppf4vBBHFrbSUKkr7CC6VCW4tjhoWKoDKD3kfoqQsJ8iV WvTcxv7R/x7RXFTMqtp3dgQ75lC1XLXGdC0ryLFww9u1AwEJjpFPL0PANlPVkynqlzeMIBzJ1 paOIcMU4c54fOq12uMm7k/CKxTGtYz3Lq+58hFyOgQd4dKZzFgJQOlsZ+V626DG+wpp0VTpIh b3gW0xxqAD6stxlOPj6sbTrpmLX6Fl7lm7Z2eTvGQB+0fDemuyRai58Kn1i42fHfrTOsWrA2W TzHeaZ/medH9kpubdFUK8UsqU8d84FYj9FvMIAkmneGcMVqA+9l8V4I2qe32Db0bQRgk75z+5 Q3oiUlaTdjkYXUWNiJzLqtMRHMJYjDwSE8bSppolE7XSjUm6UUsR41FQi7gvOrSuI96/zN1J8 MM/ZFoBTv0Rmeh6aW6iqda9YCPoes3IjTM+Q8E5OgmpVYR5Ih8Tddb1mOJ2Vcnp8/KD7x3o6q RcYa48ddJMuGbtt7Fu8WC5uAHq5suBKilza/h4AB08jdRm28ERY9LniFRz7ZSFnaT3SeHv6th ZtCx/d7huArqF0NxsosjM5bDu0VPr38nmLivYRmquZRkQrGSKH4hMJUbyu4kPiS8o69DpBUEq kf2+8nNkzgBGGvOXh9eX2KDeMgnx9xJ+SragVDQr5TBHYjIbi5PvcOPxgDi9QuvNivIdo/5Hm CLedIj8ZdhYMzwQRwrUEvELgiE/7ogy9MaCdA2k/zCx7TXAMg6YhcDMG4SPkzafF8kRkWiG3Z VxYO9l0WwsGnzRu+CcGyv++lOSn7h842+UhVOUAe3ra0f74uFtHGdrdJSutLNSpYYG0Tnnj0V H0iLmlghyYmeNM7XUD1FKGGWlUjX/IWuKqNcY7X2Q= X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210120_082749_246747_53547F7E X-CRM114-Status: GOOD ( 22.21 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Catalin Marinas , Hector Martin , linux-kernel@vger.kernel.org, Marc Zyngier , Mohamed Mediouni , Will Deacon , Stan Skowronek Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Stan Skowronek This includes IPI support and a workaround for non-working WFI on Apple processors. Signed-off-by: Stan Skowronek Signed-off-by: Mohamed Mediouni --- drivers/irqchip/irq-apple-aic.c | 177 +++++++++++++++++++++++++++++--- 1 file changed, 165 insertions(+), 12 deletions(-) diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c index c601bc4b501a..ce4e39d56fcf 100644 --- a/drivers/irqchip/irq-apple-aic.c +++ b/drivers/irqchip/irq-apple-aic.c @@ -17,6 +17,7 @@ #include #include +#include #define REG_ID_REVISION 0x0000 #define REG_ID_CONFIG 0x0004 @@ -53,12 +54,17 @@ #define REG_PERCPU(r, c) \ ((r) + REG_CPU_REGION - REG_CPU_LOCAL + ((c) << REG_CPU_SHIFT)) +#define NUM_IPI 8 + static struct aic_chip_data { void __iomem *base; struct irq_domain *domain; unsigned int num_irqs; + bool fast_ipi; } aic; +static DEFINE_PER_CPU(atomic_t, aic_ipi_mask); + static void apple_aic_irq_mask(struct irq_data *d) { writel(REG_IRQ_xABLE_MASK(d->hwirq), @@ -78,18 +84,71 @@ static struct irq_chip apple_aic_irq_chip = { .irq_unmask = apple_aic_irq_unmask, }; -static void apple_aic_fiq_mask(struct irq_data *d) +static void apple_aic_fiq_ipi_mask(struct irq_data *d) { } -static void apple_aic_fiq_unmask(struct irq_data *d) +static void apple_aic_fiq_ipi_unmask(struct irq_data *d) { } static struct irq_chip apple_aic_irq_chip_fiq = { .name = "apple_aic_fiq", - .irq_mask = apple_aic_fiq_mask, - .irq_unmask = apple_aic_fiq_unmask, + .irq_mask = apple_aic_fiq_ipi_mask, + .irq_unmask = apple_aic_fiq_ipi_unmask, +}; + +#define SR_APPLE_IPI_LOCAL s3_5_c15_c0_0 +#define SR_APPLE_IPI_REMOTE s3_5_c15_c0_1 +#define SR_APPLE_IPI_STAT s3_5_c15_c1_1 + +#ifdef CONFIG_SMP +static void apple_aic_ipi_send_mask(struct irq_data *d, + const struct cpumask *mask) +{ + int cpu, lcpu; + int irqnr = d->hwirq - (aic.num_irqs + 2); + + if (WARN_ON(irqnr < 0 || irqnr >= NUM_IPI)) + return; + + /* + * Ensure that stores to Normal memory are visible to the + * other CPUs before issuing the IPI. + */ + wmb(); + + for_each_cpu (cpu, mask) { + smp_mb__before_atomic(); + atomic_or(1u << irqnr, per_cpu_ptr(&aic_ipi_mask, cpu)); + smp_mb__after_atomic(); + lcpu = get_cpu(); + if (aic.fast_ipi) { + if ((lcpu >> 2) == (cpu >> 2)) + write_sysreg(cpu & 3, SR_APPLE_IPI_LOCAL); + else + write_sysreg((cpu & 3) | ((cpu >> 2) << 16), + SR_APPLE_IPI_REMOTE); + } else + writel(lcpu == cpu ? REG_IPI_FLAG_SELF : + (REG_IPI_FLAG_OTHER << cpu), + aic.base + REG_IPI_SET); + put_cpu(); + } + + /* Force the above writes to be executed */ + if (aic.fast_ipi) + isb(); +} +#else +#define apple_aic_ipi_send_mask NULL +#endif + +static struct irq_chip apple_aic_irq_chip_ipi = { + .name = "apple_aic_ipi", + .irq_mask = apple_aic_fiq_ipi_mask, + .irq_unmask = apple_aic_fiq_ipi_unmask, + .ipi_send_mask = apple_aic_ipi_send_mask, }; static int apple_aic_irq_domain_xlate(struct irq_domain *d, @@ -98,16 +157,27 @@ static int apple_aic_irq_domain_xlate(struct irq_domain *d, unsigned long *out_hwirq, unsigned int *out_type) { - if (intspec[0]) { /* FIQ */ + switch (intspec[0]) { + case 0: /* IRQ */ + if (intspec[1] >= aic.num_irqs) + return -EINVAL; + if (out_hwirq) + *out_hwirq = intspec[1]; + break; + case 1: /* FIQ */ if (intspec[1] >= 2) return -EINVAL; if (out_hwirq) *out_hwirq = aic.num_irqs + intspec[1]; - } else { - if (intspec[1] >= aic.num_irqs) + break; + case 2: /* IPI */ + if (intspec[1] >= NUM_IPI) return -EINVAL; if (out_hwirq) - *out_hwirq = intspec[1]; + *out_hwirq = aic.num_irqs + 2 + intspec[1]; + break; + default: + return -EINVAL; } if (out_type) @@ -118,7 +188,13 @@ static int apple_aic_irq_domain_xlate(struct irq_domain *d, static int apple_aic_irq_domain_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw) { - if (hw >= aic.num_irqs) { + if (hw >= aic.num_irqs + 2) { + irq_set_percpu_devid(virq); + irq_domain_set_info(d, virq, hw, &apple_aic_irq_chip_ipi, + d->host_data, handle_percpu_devid_irq, NULL, + NULL); + irq_set_status_flags(virq, IRQ_NOAUTOEN); + } else if (hw >= aic.num_irqs) { irq_set_percpu_devid(virq); irq_domain_set_info(d, virq, hw, &apple_aic_irq_chip_fiq, d->host_data, handle_percpu_devid_irq, NULL, @@ -141,8 +217,10 @@ static const struct irq_domain_ops apple_aic_irq_domain_ops = { static void __exception_irq_entry apple_aic_handle_irq(struct pt_regs *regs) { + atomic_t *maskptr; uint32_t ack; - unsigned done = 0; + unsigned done = 0, irqnr; + unsigned long mask; while (1) { ack = readl(aic.base + REG_IRQ_ACK); @@ -154,6 +232,36 @@ static void __exception_irq_entry apple_aic_handle_irq(struct pt_regs *regs) handle_domain_irq(aic.domain, ack & REG_IRQ_ACK_NUM_MASK, regs); break; + case REG_IRQ_ACK_TYPE_IPI: +#ifdef CONFIG_SMP + if (ack == REG_IRQ_ACK_IPI_SELF) + writel(REG_IPI_FLAG_SELF, + aic.base + REG_IPI_CLEAR); + else + writel(REG_IPI_FLAG_OTHER, + aic.base + REG_IPI_CLEAR); + maskptr = get_cpu_ptr(&aic_ipi_mask); + smp_mb__before_atomic(); + mask = atomic_xchg(maskptr, 0); + smp_mb__after_atomic(); + put_cpu_ptr(&aic_ipi_mask); + for_each_set_bit (irqnr, &mask, NUM_IPI) { + handle_domain_irq(aic.domain, + aic.num_irqs + 2 + irqnr, + regs); + } + if (ack == REG_IRQ_ACK_IPI_SELF) + writel(REG_IPI_FLAG_SELF, + aic.base + + REG_PERCPU(REG_IPI_ENABLE, + __smp_processor_id())); + else + writel(REG_IPI_FLAG_OTHER, + aic.base + + REG_PERCPU(REG_IPI_ENABLE, + __smp_processor_id())); +#endif + break; } if (done) break; @@ -162,6 +270,27 @@ static void __exception_irq_entry apple_aic_handle_irq(struct pt_regs *regs) static void __exception_irq_entry apple_aic_handle_fiq(struct pt_regs *regs) { +#ifdef CONFIG_SMP + atomic_t *maskptr; + unsigned long mask; + unsigned irqnr; + + if (aic.fast_ipi) { + if (read_sysreg(SR_APPLE_IPI_STAT)) { + write_sysreg(1, SR_APPLE_IPI_STAT); + + maskptr = get_cpu_ptr(&aic_ipi_mask); + smp_mb__before_atomic(); + mask = atomic_xchg(maskptr, 0); + smp_mb__after_atomic(); + put_cpu_ptr(&aic_ipi_mask); + for_each_set_bit (irqnr, &mask, NUM_IPI) + handle_domain_irq(aic.domain, + aic.num_irqs + 2 + irqnr, + regs); + } + } +#endif handle_domain_irq(aic.domain, aic.num_irqs, regs); } @@ -169,6 +298,13 @@ void apple_aic_cpu_prepare(unsigned int cpu) { unsigned i; + if (aic.fast_ipi) + writel(REG_IPI_FLAG_SELF | REG_IPI_FLAG_OTHER, + aic.base + REG_PERCPU(REG_IPI_DISABLE, cpu)); + else + writel(REG_IPI_FLAG_SELF | REG_IPI_FLAG_OTHER, + aic.base + REG_PERCPU(REG_IPI_ENABLE, cpu)); + for (i = 0; i < aic.num_irqs; i++) writel(readl(aic.base + REG_IRQ_AFFINITY(i)) | (1u << cpu), aic.base + REG_IRQ_AFFINITY(i)); @@ -178,6 +314,9 @@ static int __init apple_aic_init(struct device_node *node, struct device_node *interrupt_parent) { unsigned i; +#ifdef CONFIG_SMP + int base_ipi, ret; +#endif if (!node) return -ENODEV; @@ -186,8 +325,11 @@ static int __init apple_aic_init(struct device_node *node, if (WARN(!aic.base, "unable to map aic registers\n")) return -EINVAL; + aic.fast_ipi = of_property_read_bool(node, "fast-ipi"); + aic.num_irqs = readl(aic.base + REG_ID_CONFIG) & 0xFFFF; - pr_info("Apple AIC: %d IRQs + 1 FIQ + 1 dummy\n", aic.num_irqs); + pr_info("Apple AIC: %d IRQs + 1 FIQ + 1 dummy + %d IPIs%s\n", + aic.num_irqs, NUM_IPI, aic.fast_ipi ? " (fast)" : ""); for (i = 0; i < aic.num_irqs; i++) writel(1, aic.base + REG_IRQ_AFFINITY(i)); @@ -201,10 +343,21 @@ static int __init apple_aic_init(struct device_node *node, apple_aic_cpu_prepare(0); - aic.domain = irq_domain_add_linear(node, aic.num_irqs + 2, + aic.domain = irq_domain_add_linear(node, aic.num_irqs + 2 + NUM_IPI, &apple_aic_irq_domain_ops, &apple_aic_irq_chip); irq_set_default_host(aic.domain); + +#ifdef CONFIG_SMP + base_ipi = aic.num_irqs + 2; + ret = irq_create_strict_mappings(aic.domain, base_ipi, aic.num_irqs + 2, + NUM_IPI); + if (ret < 0) + pr_err("%s: irq_create_strict_mappings failed with %d\n", + __func__, ret); + set_smp_ipi_range(base_ipi, NUM_IPI); +#endif + return 0; } -- 2.29.2 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel