From patchwork Thu Sep 8 15:31:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: hotran X-Patchwork-Id: 9321679 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 3B99560752 for ; Thu, 8 Sep 2016 15:32:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2C90529861 for ; Thu, 8 Sep 2016 15:32:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 21113298D9; Thu, 8 Sep 2016 15:32:26 +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.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable 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 72BC929861 for ; Thu, 8 Sep 2016 15:32:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935947AbcIHPcT (ORCPT ); Thu, 8 Sep 2016 11:32:19 -0400 Received: from mail-pf0-f173.google.com ([209.85.192.173]:35029 "EHLO mail-pf0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757681AbcIHPbe (ORCPT ); Thu, 8 Sep 2016 11:31:34 -0400 Received: by mail-pf0-f173.google.com with SMTP id w87so19283319pfk.2 for ; Thu, 08 Sep 2016 08:31:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=apm.com; s=apm; h=from:to:cc:subject:date:message-id; bh=E21XIXXeJRKpRmPxAlGWLFtLTOfcOnCGQaeuoXnegYc=; b=m3FP4/vTFW408oVCCAtkiWLt8rIefL0igvIC9LRnTiFupZwBzRcM9eXXazkWoE8yCl VugVaFAEtWgoOWESlO969n21pZZLlEOGuGAuqP86peba0Y6RyT/Ke0dAqtmVIn1Llqqx EOcCaqBC11kNuQ9JVPe+NGpMafEnm+CVi0R10= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=E21XIXXeJRKpRmPxAlGWLFtLTOfcOnCGQaeuoXnegYc=; b=GTUK60a5G6TNnMg9EaQ3DYaHMm6dKPEot1Pld6OjfXM09rssNM5FC8nNIaPLaxIAbN fsXWUXvlCPaVO6YmqcksrGOwzmFB3yCXlusx6kZcqHh3OvwVZf5vne+78VxWj6QAV60U RS65J65BPg/uEQ7/ehRPX8X4fM62JfKrNGq9HeZdzMbpFlyR1P76hpmb6grk+Fr4sB0K eTXOZuvkAbuR+QgFhfZatUY9W1AJLCqG+IXlD4REo5EZEuimghb94PiClnKZjQTdmLte cDvWZwtM5zagQR0qSgcuww8jsa5wuphWHQMg37GIyWKFDLohMPfpHHMOpjcuVMXCyZ+c lO7Q== X-Gm-Message-State: AE9vXwPM5SaMfGY5lO6ZVOlkjAui1cFhSENStdBL0YiFTDgFteWABVs9bsQ868/CcgOm0Pj8 X-Received: by 10.98.7.80 with SMTP id b77mr412649pfd.136.1473348694059; Thu, 08 Sep 2016 08:31:34 -0700 (PDT) Received: from hotran_localhost.amcc.com ([206.80.4.98]) by smtp.gmail.com with ESMTPSA id 7sm57227893pfk.6.2016.09.08.08.31.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 08 Sep 2016 08:31:33 -0700 (PDT) From: Hoan Tran To: Guenter Roeck , Jean Delvare Cc: linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org, Itaru Kitayama , lho@apm.com, Duc Dang , Hoan Tran Subject: [PATCH v2] hwmon: xgene: Fix crash when alarm occurs before driver probe Date: Thu, 8 Sep 2016 08:31:04 -0700 Message-Id: <1473348664-24547-1-git-send-email-hotran@apm.com> X-Mailer: git-send-email 1.9.1 Sender: linux-hwmon-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The system crashes during probing xgene-hwmon driver when temperature alarm interrupt occurs before. It's because - xgene_hwmon_probe() requests mailbox channel which also enables the mailbox interrupt. - As temperature alarm interrupt is pending, ISR runs and crashes when accesses into invalid resourse as unmapped PCC shared memory. This patch fixes this issue by saving this alarm message and scheduling a bottom handler after xgene_hwmon_probe() finish. Signed-off-by: Hoan Tran Reported-by: Itaru Kitayama --- v2 * Check hwmon_dev and resp_pending to determine the driver is not ready * Remove init_flag and rx_pending * Replace EBUSY by ENODEV v1 * Initial drivers/hwmon/xgene-hwmon.c | 69 ++++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c index bc78a5d..ea53537 100644 --- a/drivers/hwmon/xgene-hwmon.c +++ b/drivers/hwmon/xgene-hwmon.c @@ -465,13 +465,34 @@ static void xgene_hwmon_evt_work(struct work_struct *work) } } +static int xgene_hwmon_rx_ready(struct xgene_hwmon_dev *ctx, void *msg) +{ + if (IS_ERR(ctx->hwmon_dev) && !ctx->resp_pending) { + /* Enqueue to the FIFO */ + kfifo_in_spinlocked(&ctx->async_msg_fifo, msg, + sizeof(struct slimpro_resp_msg), + &ctx->kfifo_lock); + return -ENODEV; + } + + return 0; +} + /* * This function is called when the SLIMpro Mailbox received a message */ static void xgene_hwmon_rx_cb(struct mbox_client *cl, void *msg) { struct xgene_hwmon_dev *ctx = to_xgene_hwmon_dev(cl); - struct slimpro_resp_msg amsg; + + /* + * While the driver registers with the mailbox framework, an interrupt + * can be pending before the probe function completes its + * initialization. If such condition occurs, just queue up the message + * as the driver is not ready for servicing the callback. + */ + if (xgene_hwmon_rx_ready(ctx, msg) < 0) + return; /* * Response message format: @@ -500,12 +521,8 @@ static void xgene_hwmon_rx_cb(struct mbox_client *cl, void *msg) return; } - amsg.msg = ((u32 *)msg)[0]; - amsg.param1 = ((u32 *)msg)[1]; - amsg.param2 = ((u32 *)msg)[2]; - /* Enqueue to the FIFO */ - kfifo_in_spinlocked(&ctx->async_msg_fifo, &amsg, + kfifo_in_spinlocked(&ctx->async_msg_fifo, msg, sizeof(struct slimpro_resp_msg), &ctx->kfifo_lock); /* Schedule the bottom handler */ schedule_work(&ctx->workq); @@ -520,6 +537,15 @@ static void xgene_hwmon_pcc_rx_cb(struct mbox_client *cl, void *msg) struct acpi_pcct_shared_memory *generic_comm_base = ctx->pcc_comm_addr; struct slimpro_resp_msg amsg; + /* + * While the driver registers with the mailbox framework, an interrupt + * can be pending before the probe function completes its + * initialization. If such condition occurs, just queue up the message + * as the driver is not ready for servicing the callback. + */ + if (xgene_hwmon_rx_ready(ctx, &amsg) < 0) + return; + msg = generic_comm_base + 1; /* Check if platform sends interrupt */ if (!xgene_word_tst_and_clr(&generic_comm_base->status, @@ -596,6 +622,17 @@ static int xgene_hwmon_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ctx); cl = &ctx->mbox_client; + spin_lock_init(&ctx->kfifo_lock); + mutex_init(&ctx->rd_mutex); + + rc = kfifo_alloc(&ctx->async_msg_fifo, + sizeof(struct slimpro_resp_msg) * ASYNC_MSG_FIFO_SIZE, + GFP_KERNEL); + if (rc) + goto out_mbox_free; + + INIT_WORK(&ctx->workq, xgene_hwmon_evt_work); + /* Request mailbox channel */ cl->dev = &pdev->dev; cl->tx_done = xgene_hwmon_tx_done; @@ -676,17 +713,6 @@ static int xgene_hwmon_probe(struct platform_device *pdev) ctx->usecs_lat = PCC_NUM_RETRIES * cppc_ss->latency; } - spin_lock_init(&ctx->kfifo_lock); - mutex_init(&ctx->rd_mutex); - - rc = kfifo_alloc(&ctx->async_msg_fifo, - sizeof(struct slimpro_resp_msg) * ASYNC_MSG_FIFO_SIZE, - GFP_KERNEL); - if (rc) - goto out_mbox_free; - - INIT_WORK(&ctx->workq, xgene_hwmon_evt_work); - ctx->hwmon_dev = hwmon_device_register_with_groups(ctx->dev, "apm_xgene", ctx, @@ -697,17 +723,22 @@ static int xgene_hwmon_probe(struct platform_device *pdev) goto out; } + /* + * Schedule the bottom handler if there is a pending message. + */ + schedule_work(&ctx->workq); + dev_info(&pdev->dev, "APM X-Gene SoC HW monitor driver registered\n"); return 0; out: - kfifo_free(&ctx->async_msg_fifo); -out_mbox_free: if (acpi_disabled) mbox_free_channel(ctx->mbox_chan); else pcc_mbox_free_channel(ctx->mbox_chan); +out_mbox_free: + kfifo_free(&ctx->async_msg_fifo); return rc; }