From patchwork Tue May 2 09:12:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phil Reid X-Patchwork-Id: 9707707 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8288060245 for ; Tue, 2 May 2017 09:13:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7464B28419 for ; Tue, 2 May 2017 09:13:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 694552841E; Tue, 2 May 2017 09:13:58 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1414C28419 for ; Tue, 2 May 2017 09:13:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751374AbdEBJNy (ORCPT ); Tue, 2 May 2017 05:13:54 -0400 Received: from anchovy1.45ru.net.au ([203.30.46.145]:33407 "EHLO anchovy.45ru.net.au" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751516AbdEBJMm (ORCPT ); Tue, 2 May 2017 05:12:42 -0400 Received: (qmail 3026 invoked by uid 5089); 2 May 2017 09:12:39 -0000 Received: by simscan 1.2.0 ppid: 2958, pid: 2960, t: 0.0321s scanners: regex: 1.2.0 attach: 1.2.0 clamav: 0.88.3/m:40/d:1950 X-RBL: $rbltext Received: from unknown (HELO preid-centos7.electromag.com.au) (preid@electromag.com.au@203.59.230.133) by anchovy1.45ru.net.au with ESMTPA; 2 May 2017 09:12:39 -0000 Received: by preid-centos7.electromag.com.au (Postfix, from userid 1000) id B728E302B9ED9; Tue, 2 May 2017 17:12:37 +0800 (AWST) From: Phil Reid To: wsa@the-dreams.de, robh+dt@kernel.org, mark.rutland@arm.com, sre@kernel.org, peda@axentia.se, preid@electromag.com.au, linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-pm@vger.kernel.org, benjamin.tissoires@redhat.com Subject: [PATCH v6 1/8] i2c: i2c-smbus: Support threaded irqs. Date: Tue, 2 May 2017 17:12:19 +0800 Message-Id: <1493716346-58517-2-git-send-email-preid@electromag.com.au> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1493716346-58517-1-git-send-email-preid@electromag.com.au> References: <1493716346-58517-1-git-send-email-preid@electromag.com.au> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP handle_nested_irq calls the threaded irq handler. So if the smbus_alert irq is being generated via this an null address is dereferenced. 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 | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index f9271c7..b272493 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -72,13 +72,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 (;;) { @@ -115,6 +114,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); @@ -148,12 +158,14 @@ static int smbalert_probe(struct i2c_client *ara, alert->alert_edge_triggered = setup->alert_edge_triggered; alert->irq = setup->irq; - INIT_WORK(&alert->alert, smbus_alert); + INIT_WORK(&alert->alert, smbalert_work); alert->ara = ara; if (setup->irq > 0) { - res = devm_request_irq(&ara->dev, setup->irq, smbalert_irq, - 0, "smbus_alert", alert); + res = devm_request_threaded_irq(&ara->dev, alert->irq, + smbalert_irq, smbus_alert, + IRQF_SHARED | IRQF_ONESHOT, + "smbus_alert", alert); if (res) return res; }