Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp5567988imm; Wed, 12 Sep 2018 07:54:45 -0700 (PDT) X-Google-Smtp-Source: ANB0VdZWo3s+1YIWSWLkvDlOmvcHrP3XSOWJTsxI0bNxGfzMco0BYpfbwziAUyZ80bxOF9lWEkS+ X-Received: by 2002:a63:d150:: with SMTP id c16-v6mr2792641pgj.188.1536764085098; Wed, 12 Sep 2018 07:54:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536764085; cv=none; d=google.com; s=arc-20160816; b=uID0x9D6ou/X5WmUPtbllf1AruXoqBYg2Chtdn3x7726yS/4ulA+7HwjJIXGDiH54k ClGk9ltYnPnxIzdmx11JIqkzW+RRPfl5cbUhRsPqH1rWc38DaVrr2kL/prxGy/ZyM67K BSoDGPny3LCy261FQuV3paE2KzXG8pldZt76Kod9EP+6kSblmI3ikndzrkKWOVT3Ik54 QYn5b6q3xxBcUkati5kh7X9RV6T21qL4DQWu8xxypDXD03D1ys8Ci41XBtj7NwG0d3ta p4WZyky0sVgmPpFyTfUixzdypTPrBDAgsUBvmMN4VD9L01u6vhZQMWqiiRaroZInCon6 lDHw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:dkim-signature; bh=o2kPz3lPGRMkYJdn0FQhaBlh9DR6avWRi6RO9EydLSo=; b=kHwUC/yAMgQlT6CGxJTzcWN8aQqQZyxpyebFY/Z+09+4c6pP0mVtovDTJZP4wks5uC Qbe0/C+VQ55HCQ1EvihI+kxgey/C/ha5GJd6eNNN4gYns5GOLWeJAvDvoQeqaicQRGnN ZtQO2Z1ziL56X6B6bVb/bCSo3113yaQ9qxBHRnq5/qnomjef6Fhe8P9f+RRikuP0ScRJ Vmkf+oWj/usQTyrr4R7Z9WDhG6dJwXiIQeT6g/GI+5zjzSnKfzGGbibW6YbGXnAd2zS2 dRUDFoxGnz7q3bvWAOi0TY8fQ/QrOAAisvb1LhLa6ebEuDMNCSjF+Z7p21YaJ6sWIngC m1Zg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@raspberrypi.org header.s=pp header.b=nm7mIkTB; dkim=pass header.i=@raspberrypi.org header.s=google header.b=hf+xoj8q; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=raspberrypi.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o6-v6si1153911plk.31.2018.09.12.07.54.24; Wed, 12 Sep 2018 07:54:45 -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; dkim=pass header.i=@raspberrypi.org header.s=pp header.b=nm7mIkTB; dkim=pass header.i=@raspberrypi.org header.s=google header.b=hf+xoj8q; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=raspberrypi.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728411AbeILT6i (ORCPT + 99 others); Wed, 12 Sep 2018 15:58:38 -0400 Received: from mx07-00252a01.pphosted.com ([62.209.51.214]:9521 "EHLO mx07-00252a01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728410AbeILT6h (ORCPT ); Wed, 12 Sep 2018 15:58:37 -0400 Received: from pps.filterd (m0102628.ppops.net [127.0.0.1]) by mx07-00252a01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w8CETEHT026401 for ; Wed, 12 Sep 2018 15:32:15 +0100 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.org; h=from : to : cc : subject : date : message-id : in-reply-to : references; s=pp; bh=o2kPz3lPGRMkYJdn0FQhaBlh9DR6avWRi6RO9EydLSo=; b=nm7mIkTBRUGmceCrX+A7HjGfyVjXSvcD/MkASY8J2xIpN6HbXkMEG1c25VH4vvHqKN1s GFmrSA/3d9BGW72q2nvqUC0nmBgNlkOlFwqgNYT5TEug4fAXjRZ/oFD9FsC9sA0ZN4WD L6t+8/X8qlQwC61G2h/nRvRWYTFXeQTvOd/dVbBoLAC0lttF/P2r0d1oLNjFe2X53Fr7 c6o4jAkrLCVfmnPuocgO2kbtl0DY4mUBcm3VO+/u+PUf44S/MGkUKmku/4YfwYPh1jBc 8pA8EGGPdOuUB4wp+czyZ3V1//VEOfAajq1Rrbniz9iZvBE5Tgsha1x9WY3C1+zXbqM7 BA== Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by mx07-00252a01.pphosted.com with ESMTP id 2mc3u0j171-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=OK) for ; Wed, 12 Sep 2018 15:32:15 +0100 Received: by mail-wr1-f69.google.com with SMTP id 40-v6so1998385wrb.23 for ; Wed, 12 Sep 2018 07:32:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=o2kPz3lPGRMkYJdn0FQhaBlh9DR6avWRi6RO9EydLSo=; b=hf+xoj8qka6U4bCf67FzlE/3ay7etMYPEiznDzDVqQJEiu5ZW1l7srX9Ny0stvNNvm NkBFrprvrt13orRGXQDmzxJGaAxRwJcV3EKZm5kwX936KY/6OTg8vdeyygdODRSC4xGU O3QCvpBOvxX2DwQncIdi5Xfvo4InYZVO/dwY2nRsdWH3qlw+Oo5gS+oyLOJm6oWTVWNb Gu3Ulh91bdvTUcshjKFuXmKdFbJ0u30KveqCrPjrz5jjZ0FfcNdBb5EVNvyrWPk/WDSM 8mFVgUvhQTHs3OHAW+AQ7rpc1KQ5X7V9swwPcREfHi96qChr3UIv+AIJsUAwR+mF0s8f KdcA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=o2kPz3lPGRMkYJdn0FQhaBlh9DR6avWRi6RO9EydLSo=; b=Besvnw36lMb+ri9J6kH2fHqxy5v9BFrgEQVLj636mLgqtRuUN49NbdhDQrVW8F8nFd J3HilgQw9KdqaGELs5q8wV5/S52HSKaVzmfBI1mDuM2d38gIjaYXsyyWDtoNIglIvUpW p3gcpuQCh1p3pZruCMKVZbfPv/Yfn4A29Zr9/rIYSduq7okLpQNB/mZObpG+iYUHGk5z qOqpw5i3r/lAqBz/m0HUOsQFvqFWirKuQZx3x02DCzH4h9OXJTAU41GWfosHtjHXmvXp J7Kd9xUrHN+aN/lEewvKXspE4Us6EDbtV8USyedvwa3A6uqRel+qYJ84ZllLwpTIgw1/ 5JSg== X-Gm-Message-State: APzg51BtFNEW/btKYwVNY1tQYblkwxxk88nzRu5nM8YUoGx3RcmmG9Fi wmfTQzuaLYS8mkahSOTgrgdoNN6DlLRTzD+IuFwfHmWuzF/sz5sDIg/HvpfmbtQwZTPhgiLq56y H/TJB4nyq0mTrxWB887wOD2UL X-Received: by 2002:a1c:7dc7:: with SMTP id y190-v6mr1782866wmc.62.1536762734469; Wed, 12 Sep 2018 07:32:14 -0700 (PDT) X-Received: by 2002:a1c:7dc7:: with SMTP id y190-v6mr1782846wmc.62.1536762734099; Wed, 12 Sep 2018 07:32:14 -0700 (PDT) Received: from buildbot.pitowers.org ([2a00:2381:fdf7:14:e45c:95a2:cfa0:31e0]) by smtp.gmail.com with ESMTPSA id h82-v6sm948217wme.11.2018.09.12.07.32.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 12 Sep 2018 07:32:12 -0700 (PDT) From: Phil Elwell To: Greg Kroah-Hartman , Jiri Slaby , linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, Alexander Graf , Stefan Wahren Cc: Phil Elwell Subject: [PATCH 1/2] sc16is7xx: Fix for multi-channel stall Date: Wed, 12 Sep 2018 15:31:55 +0100 Message-Id: <1536762716-30673-2-git-send-email-phil@raspberrypi.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1536762716-30673-1-git-send-email-phil@raspberrypi.org> References: <1536762716-30673-1-git-send-email-phil@raspberrypi.org> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-09-12_08:,, signatures=0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The SC16IS752 is a dual-channel device. The two channels are largely independent, but the IRQ signals are wired together as an open-drain, active low signal which will be driven low while either of the channels requires attention, which can be for significant periods of time until operations complete and the interrupt can be acknowledged. In that respect it is should be treated as a true level-sensitive IRQ. The kernel, however, needs to be able to exit interrupt context in order to use I2C or SPI to access the device registers (which may involve sleeping). Therefore the interrupt needs to be masked out or paused in some way. The usual way to manage sleeping from within an interrupt handler is to use a threaded interrupt handler - a regular interrupt routine does the minimum amount of work needed to triage the interrupt before waking the interrupt service thread. If the threaded IRQ is marked as IRQF_ONESHOT the kernel will automatically mask out the interrupt until the thread runs to completion. The sc16is7xx driver used to use a threaded IRQ, but a patch switched to using a kthread_worker in order to set realtime priorities on the handler thread and for other optimisations. The end result is non-threaded IRQ that schedules some work then returns IRQ_HANDLED, making the kernel think that all IRQ processing has completed. The work-around to prevent a constant stream of interrupts is to mark the interrupt as edge-sensitive rather than level-sensitive, but interpreting an active-low source as a falling-edge source requires care to prevent a total cessation of interrupts. Whereas an edge-triggering source will generate a new edge for every interrupt condition a level-triggering source will keep the signal at the interrupting level until it no longer requires attention; in other words, the host won't see another edge until all interrupt conditions are cleared. It is therefore vital that the interrupt handler does not exit with an outstanding interrupt condition, otherwise the kernel will not receive another interrupt unless some other operation causes the interrupt state on the device to be cleared. The existing sc16is7xx driver has a very simple interrupt "thread" (kthread_work job) that processes interrupts on each channel in turn until there are no more. If both channels are active and the first channel starts interrupting while the handler for the second channel is running then it will not be detected and an IRQ stall ensues. This could be handled easily if there was a shared IRQ status register, or a convenient way to determine if the IRQ had been deasserted for any length of time, but both appear to be lacking. Avoid this problem (or at least make it much less likely to happen) by reducing the granularity of per-channel interrupt processing to one condition per iteration, only exiting the overall loop when both channels are no longer interrupting. Signed-off-by: Phil Elwell --- drivers/tty/serial/sc16is7xx.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 243c960..47b4115 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -657,7 +657,7 @@ static void sc16is7xx_handle_tx(struct uart_port *port) uart_write_wakeup(port); } -static void sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno) +static bool sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno) { struct uart_port *port = &s->p[portno].port; @@ -666,7 +666,7 @@ static void sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno) iir = sc16is7xx_port_read(port, SC16IS7XX_IIR_REG); if (iir & SC16IS7XX_IIR_NO_INT_BIT) - break; + return false; iir &= SC16IS7XX_IIR_ID_MASK; @@ -688,16 +688,23 @@ static void sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno) port->line, iir); break; } - } while (1); + } while (0); + return true; } static void sc16is7xx_ist(struct kthread_work *ws) { struct sc16is7xx_port *s = to_sc16is7xx_port(ws, irq_work); - int i; - for (i = 0; i < s->devtype->nr_uart; ++i) - sc16is7xx_port_irq(s, i); + while (1) { + bool keep_polling = false; + int i; + + for (i = 0; i < s->devtype->nr_uart; ++i) + keep_polling |= sc16is7xx_port_irq(s, i); + if (!keep_polling) + break; + } } static irqreturn_t sc16is7xx_irq(int irq, void *dev_id) -- 2.7.4