From patchwork Sun Mar 6 15:27:52 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akinobu Mita X-Patchwork-Id: 592561 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail-yw0-x23a.google.com (mail-yw0-x23a.google.com [IPv6:2607:f8b0:4002:c05::23a]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id E4F931402D9 for ; Mon, 7 Mar 2016 02:28:28 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.b=whb2lsD8; dkim-atps=neutral Received: by mail-yw0-x23a.google.com with SMTP id g127sf20941136ywf.0 for ; Sun, 06 Mar 2016 07:28:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20120806; h=mime-version:from:to:cc:subject:date:message-id:in-reply-to :references:x-original-sender:x-original-authentication-results :reply-to:precedence:mailing-list:list-id:x-spam-checked-in-group :list-post:list-help:list-archive:sender:list-subscribe :list-unsubscribe; bh=puGXFWXkeYUhbTaar0TBypkb1J0vxih1k7ZDN0zwDeU=; b=whb2lsD8egt/ns5TkaymKp/traUNfPpreDjmIUhxNloYMG7fHKmlCmVZtK93BW78CT 7INu6REuHypdiEPsD8w58NrSlFeCGP99d8gdloHjWvRcSl90zCF5toYLQGJAUL+XVBSR RZrBtQBSOk6/FYEY49LChKcytlwRUJciK3ES0iJCRa/0qMgoI9fbvhINvaqOXH1ckLz0 7gxlYVXjAyRofftQq/WmRrnnd94WPFrWyfxR4UHLWVaLHu+nl9+G41vXx15YPQ7QStwt qNHpdr8at7VTIOCbcfZ6xUdYFWOBXrB8EAAnWPD8SnN+RxCzHCM+femI1ZgwmlxPtNe4 2X0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:to:cc:subject:date:message-id :in-reply-to:references:x-original-sender :x-original-authentication-results:reply-to:precedence:mailing-list :list-id:x-spam-checked-in-group:list-post:list-help:list-archive :sender:list-subscribe:list-unsubscribe; bh=puGXFWXkeYUhbTaar0TBypkb1J0vxih1k7ZDN0zwDeU=; b=b+wJYTeR4kNYeznsKtSWvtShwkVpmbeclqyYoZrdFHoWUmw7GJMFdsP4tMDX8/lzCC k3HoWKr8U0F3e0nAtorzeMW0ZgOmt5BSJCwu/5N1yh1fY8+7FXD7IF3EUuvSwljwAZ+d cb3p03uioIvJZDQEmb28QQ4CQGUFT00O4Z8UiHLTryrDKRHqyXP83BcaQfm8fRp/He6A ccflwRfZqjPm/kiri8EGM8volu9gG35FJj78edO9kR4Y8XO4Se16bevYj5oC+c3wKFPz q587MRtLAxnuxHKU6/KsGClzcHKV4gzwhl+nS0iVUFBPjkdOBHP2ONR9KK+lDNYyUhan r1SQ== X-Gm-Message-State: AD7BkJJVNsH2wgBKVt+YqFhQB58QpKI7/ePZfu42J7xMnRk9AcmJBqsGr3DIa/0agS5Rqg== X-Received: by 10.182.45.163 with SMTP id o3mr192827obm.6.1457278107130; Sun, 06 Mar 2016 07:28:27 -0800 (PST) MIME-Version: 1.0 X-BeenThere: rtc-linux@googlegroups.com Received: by 10.182.32.34 with SMTP id f2ls568041obi.25.gmail; Sun, 06 Mar 2016 07:28:26 -0800 (PST) X-Received: by 10.182.137.193 with SMTP id qk1mr12864275obb.50.1457278106744; Sun, 06 Mar 2016 07:28:26 -0800 (PST) Received: from mail-pa0-x244.google.com (mail-pa0-x244.google.com. [2607:f8b0:400e:c03::244]) by gmr-mx.google.com with ESMTPS id 12si2396052pfb.1.2016.03.06.07.28.26 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 06 Mar 2016 07:28:26 -0800 (PST) Received-SPF: pass (google.com: domain of akinobu.mita@gmail.com designates 2607:f8b0:400e:c03::244 as permitted sender) client-ip=2607:f8b0:400e:c03::244; Received: by mail-pa0-x244.google.com with SMTP id hj7so6180971pac.1 for ; Sun, 06 Mar 2016 07:28:26 -0800 (PST) X-Received: by 10.66.222.41 with SMTP id qj9mr27078766pac.136.1457278106550; Sun, 06 Mar 2016 07:28:26 -0800 (PST) Received: from localhost.localdomain (KD113159139091.ppp-bb.dion.ne.jp. [113.159.139.91]) by smtp.gmail.com with ESMTPSA id g74sm18432196pfj.1.2016.03.06.07.28.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 06 Mar 2016 07:28:25 -0800 (PST) From: Akinobu Mita To: rtc-linux@googlegroups.com Cc: Akinobu Mita , Alessandro Zummo , Alexandre Belloni , Dennis Aberilla Subject: [rtc-linux] [PATCH v4 6/7] rtc: ds3232: fix issue when irq is shared several devices Date: Mon, 7 Mar 2016 00:27:52 +0900 Message-Id: <1457278073-11627-6-git-send-email-akinobu.mita@gmail.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1457278073-11627-1-git-send-email-akinobu.mita@gmail.com> References: <1457278073-11627-1-git-send-email-akinobu.mita@gmail.com> X-Original-Sender: Akinobu.Mita@gmail.com X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com: domain of akinobu.mita@gmail.com designates 2607:f8b0:400e:c03::244 as permitted sender) smtp.mailfrom=akinobu.mita@gmail.com; dkim=pass header.i=@gmail.com; dmarc=pass (p=NONE dis=NONE) header.from=gmail.com Reply-To: rtc-linux@googlegroups.com Precedence: list Mailing-list: list rtc-linux@googlegroups.com; contact rtc-linux+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: rtc-linux@googlegroups.com X-Google-Group-Id: 712029733259 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , ds3232-core requests irq with IRQF_SHARED, so irq can be shared by several devices. But the irq handler for ds3232 unconditionally disables the irq at first and the irq is re-enabled only when the interrupt source was the ds3232's alarm. This behaviour breaks the devices sharing the same irq in the various scenarios. This converts to use threaded irq and remove outdated code in suspend/resume paths. Signed-off-by: Akinobu Mita Suggested-by: Alexandre Belloni Cc: Alessandro Zummo Cc: Alexandre Belloni Cc: Dennis Aberilla --- * v4 - use threaded irq and remove outdated code and comment in suspend/resume paths drivers/rtc/rtc-ds3232.c | 81 +++++++----------------------------------------- 1 file changed, 12 insertions(+), 69 deletions(-) diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index 6016681..dacced5 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -52,7 +51,6 @@ struct ds3232 { struct regmap *regmap; int irq; struct rtc_device *rtc; - struct work_struct work; /* The mutex protects alarm operations, and prevents a race * between the enable_irq() in the workqueue and the free_irq() @@ -60,7 +58,6 @@ struct ds3232 { */ struct mutex mutex; bool suspended; - int exiting; }; static int ds3232_check_rtc_status(struct device *dev) @@ -314,23 +311,6 @@ static irqreturn_t ds3232_irq(int irq, void *dev_id) { struct device *dev = dev_id; struct ds3232 *ds3232 = dev_get_drvdata(dev); - - disable_irq_nosync(irq); - - /* - * If rtc as a wakeup source, can't schedule the work - * at system resume flow, because at this time the i2c bus - * has not been resumed. - */ - if (!ds3232->suspended) - schedule_work(&ds3232->work); - - return IRQ_HANDLED; -} - -static void ds3232_work(struct work_struct *work) -{ - struct ds3232 *ds3232 = container_of(work, struct ds3232, work); int ret; int stat, control; @@ -343,8 +323,8 @@ static void ds3232_work(struct work_struct *work) if (stat & DS3232_REG_SR_A1F) { ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control); if (ret) { - pr_warn("Read Control Register error - Disable IRQ%d\n", - ds3232->irq); + dev_warn(ds3232->dev, + "Read Control Register error %d\n", ret); } else { /* disable alarm1 interrupt */ control &= ~(DS3232_REG_CR_A1IE); @@ -368,14 +348,13 @@ static void ds3232_work(struct work_struct *work) } rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF); - - if (!ds3232->exiting) - enable_irq(ds3232->irq); } } unlock: mutex_unlock(&ds3232->mutex); + + return IRQ_HANDLED; } static const struct rtc_class_ops ds3232_rtc_ops = { @@ -401,7 +380,6 @@ static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq, ds3232->dev = dev; dev_set_drvdata(dev, ds3232); - INIT_WORK(&ds3232->work, ds3232_work); mutex_init(&ds3232->mutex); ret = ds3232_check_rtc_status(dev); @@ -409,8 +387,10 @@ static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq, return ret; if (ds3232->irq > 0) { - ret = devm_request_irq(dev, ds3232->irq, ds3232_irq, - IRQF_SHARED, name, dev); + ret = devm_request_threaded_irq(dev, ds3232->irq, NULL, + ds3232_irq, + IRQF_SHARED | IRQF_ONESHOT, + name, dev); if (ret) { ds3232->irq = 0; dev_err(dev, "unable to request IRQ\n"); @@ -423,33 +403,14 @@ static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq, return PTR_ERR_OR_ZERO(ds3232->rtc); } -static int ds3232_remove(struct device *dev) -{ - struct ds3232 *ds3232 = dev_get_drvdata(dev); - - if (ds3232->irq > 0) { - mutex_lock(&ds3232->mutex); - ds3232->exiting = 1; - mutex_unlock(&ds3232->mutex); - - devm_free_irq(dev, ds3232->irq, dev); - cancel_work_sync(&ds3232->work); - } - - return 0; -} - #ifdef CONFIG_PM_SLEEP static int ds3232_suspend(struct device *dev) { struct ds3232 *ds3232 = dev_get_drvdata(dev); - if (device_can_wakeup(dev)) { - ds3232->suspended = true; - if (irq_set_irq_wake(ds3232->irq, 1)) { + if (device_may_wakeup(dev)) { + if (enable_irq_wake(ds3232->irq)) dev_warn_once(dev, "Cannot set wakeup source\n"); - ds3232->suspended = false; - } } return 0; @@ -459,14 +420,8 @@ static int ds3232_resume(struct device *dev) { struct ds3232 *ds3232 = dev_get_drvdata(dev); - if (ds3232->suspended) { - ds3232->suspended = false; - - /* Clear the hardware alarm pend flag */ - schedule_work(&ds3232->work); - - irq_set_irq_wake(ds3232->irq, 0); - } + if (device_may_wakeup(dev)) + disable_irq_wake(ds3232->irq); return 0; } @@ -497,11 +452,6 @@ static int ds3232_i2c_probe(struct i2c_client *client, return ds3232_probe(&client->dev, regmap, client->irq, client->name); } -static int ds3232_i2c_remove(struct i2c_client *client) -{ - return ds3232_remove(&client->dev); -} - static const struct i2c_device_id ds3232_id[] = { { "ds3232", 0 }, { } @@ -514,7 +464,6 @@ static struct i2c_driver ds3232_driver = { .pm = &ds3232_pm_ops, }, .probe = ds3232_i2c_probe, - .remove = ds3232_i2c_remove, .id_table = ds3232_id, }; @@ -611,17 +560,11 @@ static int ds3234_probe(struct spi_device *spi) return ds3232_probe(&spi->dev, regmap, spi->irq, "ds3234"); } -static int ds3234_remove(struct spi_device *spi) -{ - return ds3232_remove(&spi->dev); -} - static struct spi_driver ds3234_driver = { .driver = { .name = "ds3234", }, .probe = ds3234_probe, - .remove = ds3234_remove, }; static int ds3234_register_driver(void)