From patchwork Wed Sep 21 08:41:10 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phil Reid X-Patchwork-Id: 672668 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3sfClY4Mflz9sBX for ; Wed, 21 Sep 2016 18:41:29 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754998AbcIUIl1 (ORCPT ); Wed, 21 Sep 2016 04:41:27 -0400 Received: from 203-59-230-133.perm.iinet.net.au ([203.59.230.133]:37050 "EHLO preid-centos7.electromag.com.au" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754523AbcIUIlZ (ORCPT ); Wed, 21 Sep 2016 04:41:25 -0400 Received: by preid-centos7.electromag.com.au (Postfix, from userid 1000) id 94D2435E12232; Wed, 21 Sep 2016 16:41:18 +0800 (AWST) From: Phil Reid To: wsa@the-dreams.de, robh+dt@kernel.org, mark.rutland@arm.com, sre@kernel.org, andrea.merello@gmail.com, preid@electromag.com.au, karl-heinz@schneider-inet.de, arnd@arndb.de, linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-pm@vger.kernel.org Subject: [PATCH v5 2/6] i2c: i2c-smbus: Support threaded irq. Date: Wed, 21 Sep 2016 16:41:10 +0800 Message-Id: <1474447274-90821-3-git-send-email-preid@electromag.com.au> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1474447274-90821-1-git-send-email-preid@electromag.com.au> References: <1474447274-90821-1-git-send-email-preid@electromag.com.au> Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org handle_nested_irq calls the threaded irq handler. So if the smbus_alert irq is being generated via this an null address is derefenced. Split IRQ up into separate functions to allow thread / non thread irq to work correctly. Signed-off-by: Phil Reid --- drivers/i2c/i2c-smbus.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index 5806db3..b641cc2 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -73,13 +73,12 @@ static int smbus_do_alert(struct device *dev, void *addrp) * The alert IRQ handler needs to hand work off to a task which can issue * SMBus calls, because those sleeping calls can't be made in IRQ context. */ -static void smbus_alert(struct work_struct *work) +static irqreturn_t smbus_alert(int irq, void *d) { - struct i2c_smbus_alert *alert; + struct i2c_smbus_alert *alert = d; struct i2c_client *ara; unsigned short prev_addr = 0; /* Not a valid address */ - alert = container_of(work, struct i2c_smbus_alert, alert); ara = alert->ara; for (;;) { @@ -116,6 +115,17 @@ static void smbus_alert(struct work_struct *work) prev_addr = data.addr; } + return IRQ_HANDLED; +} + +static void smbalert_work(struct work_struct *work) +{ + struct i2c_smbus_alert *alert; + + alert = container_of(work, struct i2c_smbus_alert, alert); + + smbus_alert(alert->irq, alert); + /* We handled all alerts; re-enable level-triggered IRQs */ if (!alert->alert_edge_triggered) enable_irq(alert->irq); @@ -158,12 +168,13 @@ static int smbalert_probe(struct i2c_client *ara, alert->alert_edge_triggered = (irq_type & IRQ_TYPE_EDGE_BOTH); } - INIT_WORK(&alert->alert, smbus_alert); + INIT_WORK(&alert->alert, smbalert_work); alert->ara = ara; if (alert->irq > 0) { - res = devm_request_irq(&ara->dev, alert->irq, smbalert_irq, - 0, "smbus_alert", alert); + res = devm_request_threaded_irq(&ara->dev, alert->irq, + smbalert_irq, smbus_alert, + 0, "smbus_alert", alert); if (res) return res; }