Received: by 2002:ac0:a594:0:0:0:0:0 with SMTP id m20-v6csp51040imm; Thu, 10 May 2018 15:17:03 -0700 (PDT) X-Google-Smtp-Source: AB8JxZqdqWnbh41yFqYsns0R0ezX0t5ibQOUOVkgG6G0BibAvxcd9tXGL3fu0wzPhRDtrSAXGWS/ X-Received: by 2002:a62:8d51:: with SMTP id z78-v6mr2962263pfd.69.1525990623834; Thu, 10 May 2018 15:17:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1525990623; cv=none; d=google.com; s=arc-20160816; b=Aq7ZCRHzTiPzFg++x1hfi4JCWINIL6oxGEKvdVmHoHgkTN+0HvJ5eLZ7d5JbauFKg9 y+tGuQSoYfos3PSLHts+l7ijyTScV7sQcpD8311tHiTceJ1jM+ymkT68y+hiXQrWN3nX QSm1+8ViNIvKlb5RXHv6d87JjLm1djaIWZMXOF/nycNE3UW/IYUULQhy/voM+oVs2T67 hnr67XTiGo8RswtDUSBBRmg47vazGQSo/EI/6FrqOFfe4JMaRF3/wlT93Pi1GlSSGIuE /ZiIJV1+xSYDGvlo3nzYqDLFU97/jHcHe6NDDlspOR6fvSbE/Ye26t0U0p7ovRmID/1K hCug== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dkim-signature:arc-authentication-results; bh=qnMT/zsz7NVeGG4mSNeFwpX8LZAy8Z5waV0oslf6br4=; b=c5mPQDM+GLLZ2uftOF3qntQOLjNuNRX6QxUiatzxz7dvuo0bIOfpLh41ErBVSYvppj Gys+TUxa8WqW0KA8/ac9Ta+0jK7OsSnQEcSpMqDujX4az1Q4jltUcQzvNbqrAUL9TxAt mtu4obhLaikgmPzbk1Ir6hYePm1zbLzYxrWU9+d4CW92hmJSNJ/fcVOIzth/tGRuT+7s HOfUpDF5lP2/jKkU8LGSWREyCu9WgK09V2ckuaXBZp8nnr3xMgWVLpaE3kGZw6b87pyO KQCK1cwhw70AdzYRWM/wiEj3Uh4gjLAO77jqgHHwsQf9mfm1JpOhNhPKL3jCkgX4Nprj V1XQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=M/3ON/nW; 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=chromium.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a69-v6si1754147pli.391.2018.05.10.15.16.42; Thu, 10 May 2018 15:17:03 -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=@chromium.org header.s=google header.b=M/3ON/nW; 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=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752675AbeEJWQc (ORCPT + 99 others); Thu, 10 May 2018 18:16:32 -0400 Received: from mail-pl0-f68.google.com ([209.85.160.68]:46032 "EHLO mail-pl0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752416AbeEJWQa (ORCPT ); Thu, 10 May 2018 18:16:30 -0400 Received: by mail-pl0-f68.google.com with SMTP id bi12-v6so2074677plb.12 for ; Thu, 10 May 2018 15:16:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=qnMT/zsz7NVeGG4mSNeFwpX8LZAy8Z5waV0oslf6br4=; b=M/3ON/nWxL6P7yqOkvAq0QNdxwLuNVWoEDqASrlHwTKgk2YpGqQ7fXQQZ80Txq1NQG eer6FqgduIeQNal422Z5eTYyqxXHFGiQ7DJjUaOZG5ZBcVQQnnKg7iObzf5oY98gLci2 l5LBfhzhhA39SfhR2JT2epUmB3Y1jwDlKXvvw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=qnMT/zsz7NVeGG4mSNeFwpX8LZAy8Z5waV0oslf6br4=; b=snQtAT87eFv0iXVuPLLdxi8lSKtXuFPyOrqMRXxqZUbMHClUFsHBaC5krmNyHKPcYN iSbz+WWvKwYy8iQEWXXMlp6WTfYc3y2InvybPxMKf7JAWcM0a4m0ctdbvVGIm7KZdnr+ saJaFZSsRkL0lm/sjXhqRyrdFyu74L64x5Epc35NErdWMqobiijj9wm4Ci4bT5IhdIbY uxMvb6Z3JAVuQeKmZfbqVKOFpBbGyXnwZqwItV3Kgt/spR9TZBecacHAaNTdouAaCK52 seOjNrHiLl7AE/8pPMzNa1EeppKOMogGXDmrmyiC9p303H6mBvT6rXffSD6HIbCMGr2Z yAFg== X-Gm-Message-State: ALKqPwfwPQGTDT+RBsMKhfEgnka94ceBpvdKJ+xI33SYkfrMyeKAAHpC KaL9701pL2kWMNC5/pgY/sjhPA== X-Received: by 2002:a17:902:b08f:: with SMTP id p15-v6mr216962plr.36.1525990590224; Thu, 10 May 2018 15:16:30 -0700 (PDT) Received: from rodete-desktop-imager.corp.google.com ([2620:0:1000:1501:bc2f:3082:9938:5d41]) by smtp.gmail.com with ESMTPSA id a11-v6sm3370845pgn.64.2018.05.10.15.16.29 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 10 May 2018 15:16:29 -0700 (PDT) Date: Thu, 10 May 2018 15:16:27 -0700 From: Brian Norris To: Doug Anderson Cc: JeffyChen , LKML , Heiko =?iso-8859-1?Q?St=FCbner?= , "open list:ARM/Rockchip SoC..." , Linus Walleij , linux-gpio@vger.kernel.org, Linux ARM , Marc Zyngier , Jason Cooper , Thomas Gleixner Subject: Re: [RESEND PATCH] pinctrl: rockchip: Disable interrupt when changing it's capability Message-ID: <20180510221626.GA258670@rodete-desktop-imager.corp.google.com> References: <20180503065553.7762-1-jeffy.chen@rock-chips.com> <20180507221511.GA6448@rodete-desktop-imager.corp.google.com> <5AF0FF18.1050905@rock-chips.com> <20180508015623.GA61455@rodete-desktop-imager.corp.google.com> <5AF25B2E.8080901@rock-chips.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.9.2 (2017-12-15) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org + irqchip maintainers [ irqchip is weird -- it's all over drivers/{pinctrl,gpio,irqchip}/ :D ] Hi Doug, On Tue, May 08, 2018 at 10:18:18PM -0700, Doug Anderson wrote: > On Tue, May 8, 2018 at 7:21 PM, JeffyChen wrote: > > On 05/09/2018 03:46 AM, Doug Anderson wrote: > >> One note is that in the case Brian points at (where we need to > >> simulate EDGE_BOTH by swapping edges) we purposely ignored the TRM and > >> we needed to do that to avoid losing interrupts. For details, see > >> commit 53b1bfc76df2 ("pinctrl: rockchip: Avoid losing interrupts when > >> supporting both edges"). We did this because: > >> > >> 1. We believed that the IP block in Rockchip SoCs has nearly the same > >> logic as "gpio-dwapb.c" and that's what "gpio-dwapb.c" did. > >> > > > > hmm, but i saw the gpio-dwapb.c actually toggle trigger after handle irq, > > which might avoid the race Brian mentioned: > > + generic_handle_irq(gpio_irq); > > + irq_status &= ~BIT(hwirq); > > + > > + if ((irq_get_trigger_type(gpio_irq) & IRQ_TYPE_SENSE_MASK) > > + == IRQ_TYPE_EDGE_BOTH) > > + dwapb_toggle_trigger(gpio, hwirq); > > The code you point at in dwapb_toggle_trigger() specifically is an > example of toggling the polarity _without_ disabling the interrupt in > between. We took this as "working" code and as proof that it was OK > to change polarity without disabling the interrupt in-between. There's a crucial ordering difference though: gpio-dwapb performs its polarity adjustments *after* calling generic_handle_irq(), which among other things calls ->irq_ack(). This means that it's re-ensuring that the polarity is correct *after* the point at which it last ack'ed the interrupt. So there's no chance of it clearing a second interrupt without appropriately reconfiguring the polarity. > > and i also saw ./qcom/pinctrl-msm.c do the > > toggle(msm_gpio_update_dual_edge_pos) at the end of msm_gpio_irq_set_type > > and msm_gpio_irq_ack, that seems can avoid the polarity races too. > > > >> 2. We were actually losing real interrupts and this was the only way > >> we could figure out how to fix it. > >> > >> When I tested that back in the day I was fairly convinced that we > >> weren't losing any interrupts in the EDGE_BOTH case after my fix, but > >> I certainly could have messed up. > >> > >> > >> For the EDGE_BOTH case it was important not to lose an interrupt > >> because, as you guys are talking about, we could end up configured the > >> wrong way. I think in your case where you're just picking one > >> polarity losing an interrupt shouldn't matter since it's undefined > >> exactly if an edge happens while you're in the middle of executing > >> rockchip_irq_set_type(). Is that right? > > > > > > right, so we now have 2 cases: rockchip_irq_demux/ rockchip_irq_set_type > > > > if i'm right about the spurious irq(only happen when set rising for a high > > gpio, or set falling for a low gpio), then: > > > > 1/ rockchip_irq_demux > > it's important to not losing irqs in this case, maybe we can > > > > a) ack irq > > b) update polarity for edge both irq > > > > we don't need to disable irq in b), since we would not hit the spurious irq > > cases here(always check gpio level to toggle it) > > Unless you have some sort of proof that rockchip_irq_demux(), I would > take it as an example of something that works. I remember stress > testing the heck out of it. Do you have some evidence that it's not > working? I think Brian was simply speculating that there might be a > race here, but I don't think anyone has shown it have they? Looking > back at my notes, the thing I really made sure to stress was that we > never got into a situation where we were losing an edge (AKA we were > never configured to look for a falling edge when the line was already > low). I'm not sure I confirmed that we never got an extra interrupt. I'll agree wholeheartedly that I'm only at the speculation stage right now :) I can try to poke at it sometime if I get some cycles. I'd definitely want to get better test results to prove this before changing this part. This is really just a side tangent anyway, because apparently the existing code is working well enough for rockchip_irq_demux(), and for $subject, we're really only working on improving set_type(). > I'm at home right now and I can't add prints and poke at things, but > as I understand it for edge interrupts the usual flow to make sure > interrupts aren't ever lost is: > > 1. See that the interrupt went off > 2. Ack it (clear it) > 3. Call the interrupt handler > > ...presumably in this case rockchip_irq_demux() is called after step > #2 (but I don't know if it's called before or after step #3). If the One thing to note here is that we're talking about a 2-level (chained) interrupt system. We've got the GIC, which does all of 1, 2, 3 at its level, and as part of #3 for the GIC, it runs the 2nd-level handler -- rockchip_irq_demux() -- which has to perform all of 1, 2, 3 at its level. 1 -> this is looping over GPIO_INT_STATUS in rockchip_irq_demux() 2 -> this happens when writing to GPIO_PORTS_EOI, which only is called by ->irq_ack() (irq_gc_ack_set_bit()) ... which happens from: rockchip_irq_demux() -> generic_handle_irq() -> handle_edge_irq() -> desc->irq_data.chip->irq_ack() = irq_gc_ack_set_bit() 3 -> same callpath as 2, except it's -> handle_edge_irq() -> handle_irq_event() Those all happen in the correct order. But the problem is that you left out the part about "change polarity for emulating EDGE_BOTH"; in your example (gpio-dwapb.c), polarity adjustment happens *after* 2; in Rockchip's driver, we have it before. I'm pretty sure dwapb is correct, and we are not. > line is toggling like crazy while the 3 steps are going on, it's OK if > the interrupt handler is called more than once. In general this could > be considered expected. That's why you Ack before handling--any extra > edges that come in any time after the interrupt handler starts (even > after the very first instruction) need to cause the interrupt handler > to get called again. > > This is different than Brian's understanding since he seemed to think > the Ack was happening later. If you're in front of something where > you can add printouts, maybe you can tell us. I tried to look through > the code and it was too twisted for me to be sure. I'm not sure your understanding of my understanding is accurate :) Hopefully the above clarifies what I'm thinking? > > 2/ rockchip_irq_set_type > > it's important to not having spurious irqs > > > > so we can disable irq during changing polarity only in these case: > > ((rising && gpio is heigh) || (falling && gpio is low)) > > > > i'm still confirming the spurious irq with IC guys. > > Hmmm, thinking about all this more, I'm curious how callers expect > this to work. Certainly things are undefined if you have the > following situation: > > Start: rising edge trigger, line is actually high > Request: change to falling edge trigger > Line falls during the request > > In that case it's OK to throw the interrupt away because it can be > argued that the line could have fallen before the request actually > took place. ...but it seems like there could be situations where the > user wouldn't expect interrupts to be thrown away by a call to > irq_set_type(). In other words: > > Start: rising edge trigger, line is actually high > Request: change to falling edge trigger > Line falls, rises, and falls during the request > > ...in that case you'd expect that some sort of interrupt would have > gone off and not be thrown away. No matter what instant in time the > request actually took place it should have caught an edge, right? > > > Said another way: As a client of irq_set_type() I'd expect it to not > throw away interrupts, but I'd expect that the change in type would be > atomic. That is: if the interrupt came in before the type change in > type applied then it should trigger with the old rules. If the > interrupt came in after the type change then it should trigger with > the new rules. I'm not sure it's totally possible to differentiate these, but that seems about right I think. > I would be tempted to confirm your testing and just clear the spurious > interrupts that you're aware of. AKA: if there's no interrupt pending > and you change the type to "IRQ_TYPE_EDGE_RISING" or > "IRQ_TYPE_EDGE_FALLING" then you should clear the interrupt. It's > still racy, but I guess it's the best you can do unless IC guys come > up with something better. Thanks! Yeah, clearing (rather than temporarily disabling) seems to make more sense. > Anyway, it's past my bedtime. Hopefully some of the above made sense. > I'm sure you'll tell me if it didn't or if I said something > stupid/wrong. :-P Brian