Received: by 2002:ac0:a582:0:0:0:0:0 with SMTP id m2-v6csp1916392imm; Thu, 18 Oct 2018 06:24:48 -0700 (PDT) X-Google-Smtp-Source: ACcGV60v6QbBpm66Ift5u+TsTAQ7RRhfIMVmtzD48+0/FLlW29Xfy6nwa5XfSRi7Vo4YYw4rDIhg X-Received: by 2002:a62:425b:: with SMTP id p88-v6mr30536544pfa.96.1539869088430; Thu, 18 Oct 2018 06:24:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1539869088; cv=none; d=google.com; s=arc-20160816; b=PM50Vg5xFHoHebGpcj9wT8/u5hkEfAEE6X464wtgJfNvgH/PE69fZft7J+yf5r9bhf 1TOOdNlj0RMmZ1W4SpIwKW/TSuoVNDJ6besnQIe9F0e9cXrTszqGLSu6IfZwBahJfE+/ 7oVgZWyvPta5k7fD2NdrigMktCqg8Ix36Es8SrGaHNEMG3wV0S6TBsd84qSoBZPgISzB 9/ehQDVfuJxdKfHdOKTaTi0ogU/jxgsmaV1wnFWSb7to1Can4nBEzouh5fICZcf3wMjU nP3szF/mPvGxZpp9OeRMS3NUBL6DCiXGyHT/0VQvn/BBHkhXX9dvXrmiFlJKYwkPVp7M nXog== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:date:from:message-id; bh=3HS1uF/eIG34SZlxA+YrPRA9g0UFD0k/tbMvGrORCA4=; b=iGR/5+1cYWKGWpFcBjRZk+M8HPuEGuRzCGqJo7UV6AdcQIkhsLGAg1ZjcvXrqN6grR N/WGQir8dQJcf2rbgiCUNtAgtf6glk2uV7eLhLbe41YueSVrkuS0kmw7Glvtwyex5Ojn peulkQLso5x89FwDBNqBvVRWd8OuaDHq9mtbyycMF0lNl0daYbtmo45d9W6oq550bEc/ gqDioHbhC75HSe6tN59dmzMhDMFeif9stx9LY3Gwbvn3DNqUA5yay3mMr+UF7Hn8bUl7 J1dow4Ymh3rF+CNRGWRXh57Nk1+wxyUQt8eLMlNVwjmzaRNlQ9NwaQl1sRNvYq6XNGL7 dU7Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 35-v6si10883503pla.290.2018.10.18.06.24.32; Thu, 18 Oct 2018 06:24:48 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728172AbeJRVX6 (ORCPT + 99 others); Thu, 18 Oct 2018 17:23:58 -0400 Received: from mailout2.hostsharing.net ([83.223.90.233]:49321 "EHLO mailout2.hostsharing.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727199AbeJRVX6 (ORCPT ); Thu, 18 Oct 2018 17:23:58 -0400 X-Greylist: delayed 438 seconds by postgrey-1.27 at vger.kernel.org; Thu, 18 Oct 2018 17:23:56 EDT Received: from h08.hostsharing.net (h08.hostsharing.net [83.223.95.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "*.hostsharing.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (not verified)) by mailout2.hostsharing.net (Postfix) with ESMTPS id F07DF10189CB7; Thu, 18 Oct 2018 15:15:37 +0200 (CEST) Received: from localhost (p57BD76CD.dip0.t-ipconnect.de [87.189.118.205]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by h08.hostsharing.net (Postfix) with ESMTPSA id 9445A6106F5B; Thu, 18 Oct 2018 15:15:37 +0200 (CEST) X-Mailbox-Line: From 1dfd8bbd16163940648045495e3e9698e63b50ad Mon Sep 17 00:00:00 2001 Message-Id: <1dfd8bbd16163940648045495e3e9698e63b50ad.1539867047.git.lukas@wunner.de> From: Lukas Wunner Date: Thu, 18 Oct 2018 15:15:05 +0200 Subject: [PATCH] genirq: Fix race on spurious interrupt detection To: Thomas Gleixner Cc: linux-kernel@vger.kernel.org, Mathias Duckeck , Akshay Bhat , Casey Fitzpatrick Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit 1e77d0a1ed74 ("genirq: Sanitize spurious interrupt detection of threaded irqs") made detection of spurious interrupts work for threaded handlers by: a) incrementing a counter every time the thread returns IRQ_HANDLED, and b) checking whether that counter has increased every time the thread is woken. However for oneshot interrupts, the commit unmasks the interrupt before incrementing the counter. If another interrupt occurs right after unmasking but before the counter is incremented, that interrupt is incorrectly considered spurious: time | irq_thread() | irq_thread_fn() | action->thread_fn() | irq_finalize_oneshot() | unmask_threaded_irq() /* interrupt is unmasked */ | | /* interrupt fires, incorrectly deemed spurious */ | | atomic_inc(&desc->threads_handled); /* counter is incremented */ v I am seeing this with a hi3110 CAN controller receiving data at high volume (from a separate machine sending with "cangen -g 0 -i -x"): The controller signals a huge number of interrupts (hundreds of millions per day) and every second there are about a dozen which are deemed spurious. The issue is benign in this case, mostly just an irritation, but I'm worrying that at high CPU load and in the presence of higher priority tasks, the number of incorrectly detected spurious interrupts might increase beyond the 99,900 threshold and cause disablement of the IRQ. Fix by moving the incrementation of the counter from irq_thread() to irq_thread_fn() and irq_forced_thread_fn(), before the invocation of irq_finalize_oneshot(). Fixes: 1e77d0a1ed74 ("genirq: Sanitize spurious interrupt detection of threaded irqs") Signed-off-by: Lukas Wunner Cc: stable@vger.kernel.org # v3.16+ --- kernel/irq/manage.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index fb86146037a7..9dbdccab3b6a 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -927,6 +927,9 @@ irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action) local_bh_disable(); ret = action->thread_fn(action->irq, action->dev_id); + if (ret == IRQ_HANDLED) + atomic_inc(&desc->threads_handled); + irq_finalize_oneshot(desc, action); local_bh_enable(); return ret; @@ -943,6 +946,9 @@ static irqreturn_t irq_thread_fn(struct irq_desc *desc, irqreturn_t ret; ret = action->thread_fn(action->irq, action->dev_id); + if (ret == IRQ_HANDLED) + atomic_inc(&desc->threads_handled); + irq_finalize_oneshot(desc, action); return ret; } @@ -1020,8 +1026,6 @@ static int irq_thread(void *data) irq_thread_check_affinity(desc, action); action_ret = handler_fn(desc, action); - if (action_ret == IRQ_HANDLED) - atomic_inc(&desc->threads_handled); if (action_ret == IRQ_WAKE_THREAD) irq_wake_secondary(desc, action); -- 2.19.1