Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp32941ybi; Tue, 18 Jun 2019 16:47:23 -0700 (PDT) X-Google-Smtp-Source: APXvYqy3e8A/upNbP6AzWz0MwVBqEjkEaKOYBvCeFQ9DN2F0xhcfn+f9NxWTClcxj07Yjv3HQU4h X-Received: by 2002:a63:4d05:: with SMTP id a5mr4648942pgb.19.1560901643263; Tue, 18 Jun 2019 16:47:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1560901643; cv=none; d=google.com; s=arc-20160816; b=SD5iu6q30rQG612B9ol6qpo6NwLJ7oxTt6BHo98nnoQ54k5Ozpn75Nq9Bvh6zuOKhm tceIcnIG++jzAf2iywpDXyuyGyFFqVTPLbYmz/AZ7dBbXnUxCpnHVBJIwNI6pD4ha2dz IwK8buE8YcNuxFnXL4b9We6XYwppBYLf6Vgu2fmV7+pKqIJIfbZYqBqDFBrR+LtsohCM Pd9kfOszLhFAGssu0t/XY5PddNVzMcTYxxTXUy98wMo8BCYEE0AFZsgL3xzDYwC9HvjJ +FxNa/NgTflIkQdXhbKUBUTZZpYz6yU4oBNjBRtuWAUkazlsEaCmswsknsIT4q3tI8Vn vOlQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=XKEwL46yWPL513Bk6jjrSqur9SqEusEP9oaTL7362No=; b=RTEom6N0HKJOe1BEOQ/lhVdjGu0ma9hh0jUeb4sStXsYMx8bpAYXXz1j+Na8GZtCbq 2iSMKeyUNUDXUeBw98vJ2mtROTbG3TgkLfBoDjZYn/Fcu7vu9mJ9z9BrXWtL+/cVualS G+/SpySZZHIjVxLYcsX05gN6OgHPk/Dsu0jy2xFW66VShoa5Ym6MuENVfxru8FRGB5v1 3pa6z6bLZ8UF0KfmZUb2AVxYb5dFlsq8jH47XSlyteCZTrSkXlWLw/Mr3N8Lj+6RlHDQ TZPaNi+3uY1oPn2Ucbfp0tmxXWq+Ej1X4KjLWRb94PKrX3vPl6QgU28Dfj5QXU5zTZzP jQZQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=f4vvo+qD; 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 d132si14831555pfd.102.2019.06.18.16.47.07; Tue, 18 Jun 2019 16:47:23 -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=f4vvo+qD; 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 S1729285AbfFRXqT (ORCPT + 99 others); Tue, 18 Jun 2019 19:46:19 -0400 Received: from mail-io1-f66.google.com ([209.85.166.66]:39646 "EHLO mail-io1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725913AbfFRXqS (ORCPT ); Tue, 18 Jun 2019 19:46:18 -0400 Received: by mail-io1-f66.google.com with SMTP id r185so27971575iod.6 for ; Tue, 18 Jun 2019 16:46:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=XKEwL46yWPL513Bk6jjrSqur9SqEusEP9oaTL7362No=; b=f4vvo+qD8x2fS17YJXotuuQ0yNTjhcMiOueIOJlRYlw9HiFm8vCalF8qWjIgF2lNUG UhESAqKI6Pj6stOt+JtZBAH96G1I5lNF5SUl031KNK4CEoJWb0Z5MUWMnNSQQGMES91v z7IRyyr4MVfZJAOoyKDFyHlp/E5VNmZ5on+zk= 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:mime-version:content-transfer-encoding; bh=XKEwL46yWPL513Bk6jjrSqur9SqEusEP9oaTL7362No=; b=XN2VrBG/IUOjSaXfKrFUkGNJXNBiOAO/n7frBAPAbEbx8sUic5iYQIFl1QWhdKWJC/ 6oYfNorrr+RSXnJphaX6/k3lRvNoPfUcFDMwoE3s24U+hawwUkVLfEGSIg12mKalwhMf pRCQdzxMc39EdeLnYbMRZQvbAyBXk4VT/L27VPs1YpfWoXfX2+klxAD/hk36pnhu5wLt FLONkCrRWoBrrlBWtK2Gj4CJxKy9YT6vcJpaQdX6fk1HcuSmNiAv55s3iyUECHU5qTOV zVYcQIQRUFInTt6AEkP60iulBP2k7uAjehj4uc9d7XDc7LdFOXBlgU6fJ59IqJPFF/Sb 9rfA== X-Gm-Message-State: APjAAAVzTvm8H9NLsN0TnmQt7IBedguVXNOmmhsjUvvDX4aZqTmo47Dc /aHfYtKFS+TO/x73KQSuIlwLS4aITeDs6A== X-Received: by 2002:a02:16c5:: with SMTP id a188mr93076208jaa.86.1560901577294; Tue, 18 Jun 2019 16:46:17 -0700 (PDT) Received: from localhost ([2620:15c:183:200:33ce:f5cf:f863:d3a6]) by smtp.gmail.com with ESMTPSA id p63sm19696117iof.45.2019.06.18.16.46.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 18 Jun 2019 16:46:16 -0700 (PDT) From: Fletcher Woodruff To: linux-kernel@vger.kernel.org Cc: Ben Zhang , Fletcher Woodruff , Jaroslav Kysela , Liam Girdwood , Mark Brown , Oder Chiou , Takashi Iwai , Curtis Malainey , Ross Zwisler , alsa-devel@alsa-project.org Subject: [PATCH v8 2/2] ASoC: rt5677: handle concurrent interrupts Date: Tue, 18 Jun 2019 17:45:55 -0600 Message-Id: <20190618234555.188955-3-fletcherw@chromium.org> X-Mailer: git-send-email 2.22.0.410.gd8fdbe21b5-goog In-Reply-To: <20190618234555.188955-1-fletcherw@chromium.org> References: <20190618234555.188955-1-fletcherw@chromium.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ben Zhang The rt5677 driver writes to the IRQ control register within the IRQ handler in order to flip the polarity of the interrupts that have been signalled. If an interrupt fires in the interval between the regmap_read and the regmap_write, it will not trigger a new call to rt5677_irq. Add a bounded loop to rt5677_irq that keeps checking interrupts until none are seen, so that any interrupts that are signalled in that interval are correctly handled. Signed-off-by: Ben Zhang Signed-off-by: Fletcher Woodruff --- sound/soc/codecs/rt5677.c | 71 +++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index b5ae61ff87af13..202af7135f07a4 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -5072,38 +5072,57 @@ static const struct rt5677_irq_desc rt5677_irq_descs[] = { static irqreturn_t rt5677_irq(int unused, void *data) { struct rt5677_priv *rt5677 = data; - int ret = 0, i, reg_irq, virq; + int ret = 0, loop, i, reg_irq, virq; bool irq_fired = false; mutex_lock(&rt5677->irq_lock); - /* Read interrupt status */ - ret = regmap_read(rt5677->regmap, RT5677_IRQ_CTRL1, ®_irq); - if (ret) { - dev_err(rt5677->dev, "failed reading IRQ status: %d\n", ret); - goto exit; - } - for (i = 0; i < RT5677_IRQ_NUM; i++) { - if (reg_irq & rt5677_irq_descs[i].status_mask) { - irq_fired = true; - virq = irq_find_mapping(rt5677->domain, i); - if (virq) - handle_nested_irq(virq); - - /* Clear the interrupt by flipping the polarity of the - * interrupt source line that fired - */ - reg_irq ^= rt5677_irq_descs[i].polarity_mask; + /* + * Loop to handle interrupts until the last i2c read shows no pending + * irqs. The interrupt line is shared by multiple interrupt sources. + * After the regmap_read() below, a new interrupt source line may + * become high before the regmap_write() finishes, so there isn't a + * rising edge on the shared interrupt line for the new interrupt. Thus, + * the loop is needed to avoid missing irqs. + * + * A safeguard of 20 loops is used to avoid hanging in the irq handler + * if there is something wrong with the interrupt status update. The + * interrupt sources here are audio jack plug/unplug events which + * shouldn't happen at a high frequency for a long period of time. + * Empirically, more than 3 loops have never been seen. + */ + for (loop = 0; loop < 20; loop++) { + /* Read interrupt status */ + ret = regmap_read(rt5677->regmap, RT5677_IRQ_CTRL1, ®_irq); + if (ret) { + dev_err(rt5677->dev, "failed reading IRQ status: %d\n", + ret); + goto exit; } - } - if (!irq_fired) - goto exit; - - ret = regmap_write(rt5677->regmap, RT5677_IRQ_CTRL1, reg_irq); - if (ret) { - dev_err(rt5677->dev, "failed updating IRQ status: %d\n", ret); - goto exit; + irq_fired = false; + for (i = 0; i < RT5677_IRQ_NUM; i++) { + if (reg_irq & rt5677_irq_descs[i].status_mask) { + irq_fired = true; + virq = irq_find_mapping(rt5677->domain, i); + if (virq) + handle_nested_irq(virq); + + /* Clear the interrupt by flipping the polarity + * of the interrupt source line that fired + */ + reg_irq ^= rt5677_irq_descs[i].polarity_mask; + } + } + if (!irq_fired) + goto exit; + + ret = regmap_write(rt5677->regmap, RT5677_IRQ_CTRL1, reg_irq); + if (ret) { + dev_err(rt5677->dev, "failed updating IRQ status: %d\n", + ret); + goto exit; + } } exit: mutex_unlock(&rt5677->irq_lock); -- 2.22.0.410.gd8fdbe21b5-goog