From patchwork Thu Sep 3 20:45:21 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Helge Deller X-Patchwork-Id: 7119311 X-Patchwork-Delegate: deller@gmx.de Return-Path: X-Original-To: patchwork-linux-parisc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 0EB6CBEEC1 for ; Thu, 3 Sep 2015 20:45:32 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1CAA12073D for ; Thu, 3 Sep 2015 20:45:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 03410205B1 for ; Thu, 3 Sep 2015 20:45:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753846AbbICUp3 (ORCPT ); Thu, 3 Sep 2015 16:45:29 -0400 Received: from mout.gmx.net ([212.227.17.22]:57253 "EHLO mout.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752810AbbICUp2 (ORCPT ); Thu, 3 Sep 2015 16:45:28 -0400 Received: from p100.box ([92.203.6.179]) by mail.gmx.com (mrgmx101) with ESMTPSA (Nemesis) id 0LjN0F-1Yy0S22DQV-00dWVo; Thu, 03 Sep 2015 22:45:25 +0200 Date: Thu, 3 Sep 2015 22:45:21 +0200 From: Helge Deller To: linux-parisc@vger.kernel.org, James Bottomley Subject: [PATCH] parisc: Filter out spurious interrupts in PA-RISC irq handler Message-ID: <20150903204521.GA26912@p100.box> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) X-Provags-ID: V03:K0:T2zk9DXQpgM9AZXb+Dee6uz9Gkc+idiPvzOmRu6HhCwkJV588V2 55YSDO8AONF+bZhT34uT8oqO3FY5HmyC62QQYMDMFxrRElQ1uUcuyU8zRWXw2PphBoV5SSa fsm1eAyqvcSIODaNF0gcSJxLGCDP5y8kUKW5wMwrTflexkJhHG8onqvZBnkg0TOMXlv2kD8 jph28EkGsIwjwGVj4gRUQ== X-UI-Out-Filterresults: notjunk:1; V01:K0:XBvhUIytaLI=:nd+wAXUb5A2KrOt2BL0dkD FJMvGqGEV28c9EVriUWPnX/sA21PiACobILIqhbYjy2Xl3wiu+/aJ+09AkmzQsryGR3EDDWW7 NrpC4//5vOEO38tKa9DLal+4sHdhRrvASLlIXcjrLkhMhIUWKN18iJvAtMThiz1e0nx/x/DVa t3m62Rmyd/TgI3dN2tnWy8Qacz+MR17QMQmFf6f1F4YbvgJ0RASLWhDrjWtzrsi+877+RNd6q qyFjfsNGijRH/JSdAFs09Dd0Dv/rrgVyAq4GQF2Crm0926QLAmeloiVPpe/jgHn6PdZId33UT eOHar3iop9+dU1R9TPcqqfJGXuP6uwaebY5j67zcE2fuJtuWSfh7dwxMf/7a7maD2UMdm+xKP xnlJgiFJjwuwAy6CLH5DUuA6igpq0EUIvIn/6jqCrNSknkaBOr/eXcQpldq8tUmiKuvS/qNwV 6a+gaIkoQlblYZgU8kszrBaXmGpI9IvJkpnEDz6n5EQl2B9CWX78I4D42OHiomC3DPOkjL1iT lEiNBAR3T3KhS83xQerLhetsdvoXokefbTW6S20T13SJ3R+zWB/zt4sx7lVdOVBXfv5hFVFoQ 4sMcKIKmL8lyltWbGQW/8iVFBuxX1J4XPXaqcqclBAl7w592ZLsXEFp+u8p2A3IPjJLgLsFB2 WaX7th7TjGv+xjKBrGdn74Swj+CNs+m0nzO4Cc1GzQiRcUPhQlnD3TsNU5Gv/xDgK2pW5c930 91ji6RwaUFMJklwS Sender: linux-parisc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-parisc@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_HI,T_RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When detecting a serial port on newer PA-RISC machines (with iosapic) we have a long way to go to find the right IRQ line, registering it, then registering the serial port and the irq handler for the serial port. During this phase spurious interrupts for the serial port may happen which then crashes the kernel because the action handler might not have been set up yet. So, basically it's a race condition between the serial port hardware and the CPU which sets up the necessary fields in the irq sructs. The main reason for this race is, that we unmask the serial port irqs too early without having set up everything properly before (which isn't easily possible because we need the IRQ number to register the serial ports). This patch is a work-around for this problem. It adds checks to the CPU irq handler to verify if the IRQ action field has been initialized already. If not, we just skip this interrupt (which isn't critical for a serial port at bootup). The real fix would probably involve rewriting all PA-RISC specific IRQ code (for CPU, IOSAPIC, GSC and EISA) to use IRQ domains with proper parenting of the irq chips and proper irq enabling along this line. This bug has been in the PA-RISC port since the beginning, but the crashes happened very rarely with currently used hardware. But on the latest machine which I bought (a C8000 workstation), which uses the fastest CPUs (4 x PA8900, 1GHz) and which has the largest possible L1 cache size (64MB each), the kernel crashed at every boot because of this race. So, without this patch the machine would currently be unuseable. For the record, here is the flow logic: 1. serial_init_chip() in 8250_gsc.c calls iosapic_serial_irq(). 2. iosapic_serial_irq() calls txn_alloc_irq() to find the irq. 3. iosapic_serial_irq() calls cpu_claim_irq() to register the CPU irq 4. cpu_claim_irq() unmasks the CPU irq (which it shouldn't!) 5. serial_init_chip() then registers the 8250 port. Problems: - In step 4 the CPU irq shouldn't have been registered yet, but after step 5 - If serial irq happens between 4 and 5 have finished, the kernel will crash Cc: Signed-off-by: Helge Deller --- To unsubscribe from this list: send the line "unsubscribe linux-parisc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index f3191db..c0eab24 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -507,8 +507,8 @@ void do_cpu_irq_mask(struct pt_regs *regs) struct pt_regs *old_regs; unsigned long eirr_val; int irq, cpu = smp_processor_id(); -#ifdef CONFIG_SMP struct irq_desc *desc; +#ifdef CONFIG_SMP cpumask_t dest; #endif @@ -521,8 +521,12 @@ void do_cpu_irq_mask(struct pt_regs *regs) goto set_out; irq = eirr_to_irq(eirr_val); -#ifdef CONFIG_SMP + /* Filter out spurious interrupts, mostly from serial port at bootup */ desc = irq_to_desc(irq); + if (unlikely(!desc->action)) + goto set_out; + +#ifdef CONFIG_SMP cpumask_copy(&dest, desc->irq_data.affinity); if (irqd_is_per_cpu(&desc->irq_data) && !cpumask_test_cpu(smp_processor_id(), &dest)) {