From patchwork Mon Oct 10 16:05:50 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "dalias@libc.org" X-Patchwork-Id: 9369691 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C75F8607FD for ; Mon, 10 Oct 2016 16:06:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B8017288B3 for ; Mon, 10 Oct 2016 16:06:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AB20428E40; Mon, 10 Oct 2016 16:06:14 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EE580288B3 for ; Mon, 10 Oct 2016 16:06:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752877AbcJJQGN (ORCPT ); Mon, 10 Oct 2016 12:06:13 -0400 Received: from 216-12-86-13.cv.mvl.ntelos.net ([216.12.86.13]:55812 "EHLO brightrain.aerifal.cx" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752793AbcJJQGN (ORCPT ); Mon, 10 Oct 2016 12:06:13 -0400 Received: from dalias by brightrain.aerifal.cx with local (Exim 3.15 #2) id 1btd5K-0003X5-00; Mon, 10 Oct 2016 16:05:50 +0000 Message-Id: <03e26780321c28c7d6e72bdd72d8e7066f9b1779.1476115269.git.dalias@libc.org> From: Rich Felker Subject: [PATCH v2] irqchip/jcore: fix lost per-cpu interrupts To: linux-kernel@vger.kernel.org, linux-sh@vger.kernel.org Cc: Thomas Gleixner , Jason Cooper , Marc Zyngier Date: Mon, 10 Oct 2016 16:05:50 +0000 Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The J-Core AIC does not have separate interrupt numbers reserved for cpu-local vs global interrupts. Instead, the driver requesting the irq is expected to know whether its device uses per-cpu interrupts or not. Previously it was assumed that handle_simple_irq could work for both cases, but it intentionally drops interrupts for an irq number that already has a handler running. This resulted in the timer interrupt for one cpu being lost when multiple cpus' timers were set for approximately the same expiration time, leading to stalls. In theory the same could also happen with IPIs. One possible solution would be to use a wrapper handler function which determines at irq time whether the irq being handled was registered as percpu or not, and dispatches it to either handle_simple_irq or handle_percpu_irq. However handle_simple_irq is unnecessarily expensive for hardware that always delivers interrupts on a fixed cpu, and the runtime branch also has a small but nonzero cost. Instead, use handle_percpu_irq for all irqs. Signed-off-by: Rich Felker --- Updated based on discussions with Thomas Gleixner about the v1 patch, and confirmation from Jeff Dionne (J-Core project) that it's reasonable to treat the current interrupt behavior (delivery on a fixed cpu) as a guarantee of the jcore,aic1 and jcore,aic2 DT compatible tags. --- drivers/irqchip/irq-jcore-aic.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-jcore-aic.c b/drivers/irqchip/irq-jcore-aic.c index 5e5e3bb..055fb6f 100644 --- a/drivers/irqchip/irq-jcore-aic.c +++ b/drivers/irqchip/irq-jcore-aic.c @@ -30,7 +30,16 @@ static int jcore_aic_irqdomain_map(struct irq_domain *d, unsigned int irq, { struct irq_chip *aic = d->host_data; - irq_set_chip_and_handler(irq, aic, handle_simple_irq); + /* + * For the J-Core AIC1 and AIC2, all irqs behave as percpu. Some + * (timer and IPI) can be generated specifically for individual + * CPUs; the rest are directly connected to a particular CPU. None + * are dynamically routable. Use handle_percpu_irq for all cases, + * since it's necessary for the former and safe (and faster) for + * the latter, and there's no way to distinguish them with the + * information available at mapping time. + */ + irq_set_chip_and_handler(irq, aic, handle_percpu_irq); return 0; }