From patchwork Fri Jan 25 11:33:25 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Liu X-Patchwork-Id: 2044241 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 1FC883FDD1 for ; Fri, 25 Jan 2013 11:34:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756888Ab3AYLeq (ORCPT ); Fri, 25 Jan 2013 06:34:46 -0500 Received: from na3sys009aog126.obsmtp.com ([74.125.149.155]:55612 "EHLO na3sys009aog126.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756763Ab3AYLeq (ORCPT ); Fri, 25 Jan 2013 06:34:46 -0500 Received: from MSI-MTA.marvell.com ([65.219.4.132]) (using TLSv1) by na3sys009aob126.postini.com ([74.125.148.12]) with SMTP ID DSNKUQJt1WFYIZR27S2bEqzsaCPJ6m2K9h4U@postini.com; Fri, 25 Jan 2013 03:34:45 PST Received: from maili.marvell.com ([10.68.76.210]) by MSI-MTA.marvell.com with Microsoft SMTPSVC(6.0.3790.4675); Fri, 25 Jan 2013 03:32:28 -0800 Received: from kliu5-desktop.marvell.com (unknown [10.38.36.240]) by maili.marvell.com (Postfix) with ESMTP id 4F7394E510; Fri, 25 Jan 2013 03:32:24 -0800 (PST) From: Kevin Liu To: linux-mmc@vger.kernel.org, Chris Ball , Andy Shevchenko , Ulf Hansson Cc: Nicolas Pitre , Adrian Hunter , Philip Rakity , Aaron Lu , Shawn Guo , Johan Rudholm , Daniel Drake , Guennadi Liakhovetski , Jerry Huang , Alexander Stein , Girish K S , Haijun Zhang , Viresh Kumar , Heiko Stuebner , Thomas Abraham , Chander Kashyap , Jaehoon Chung , Sebastian Hesselbarth , Zhangfei Gao , Haojian Zhuang , Chao Xie , Kevin Liu , Kevin Liu Subject: [PATCH] mmc: sdio: add wakeup event for suspend/resume Date: Fri, 25 Jan 2013 19:33:25 +0800 Message-Id: <1359113606-3011-1-git-send-email-kliu5@marvell.com> X-Mailer: git-send-email 1.7.9.5 X-OriginalArrivalTime: 25 Jan 2013 11:32:28.0577 (UTC) FILETIME=[A7F7B910:01CDFAEF] Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org If sdio host can wakeup system, interrupts will _NOT_ be disabled and sdio card interrupt may happen during whole suspend/resume process. Then the card interrupts received after suspend while before resume back should be regard as wakeup event. So set a wakeup event at that point. All sdio functions should set the wakeup event individually according to its suspending status. Signed-off-by: Kevin Liu --- drivers/mmc/core/sdio.c | 4 ++++ drivers/mmc/core/sdio_irq.c | 19 +++++++++++++++++++ include/linux/mmc/sdio_func.h | 6 ++++++ 3 files changed, 29 insertions(+) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 3a64933..06675cb 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -904,6 +904,8 @@ static int mmc_sdio_suspend(struct mmc_host *host) err = pmops->suspend(&func->dev); if (err) break; + else + func->func_status = FUNC_SUSPENDED; } } while (err && --i >= 0) { @@ -911,6 +913,7 @@ static int mmc_sdio_suspend(struct mmc_host *host) if (func && sdio_func_present(func) && func->dev.driver) { const struct dev_pm_ops *pmops = func->dev.driver->pm; pmops->resume(&func->dev); + func->func_status = FUNC_RESUMED; } } @@ -967,6 +970,7 @@ static int mmc_sdio_resume(struct mmc_host *host) if (func && sdio_func_present(func) && func->dev.driver) { const struct dev_pm_ops *pmops = func->dev.driver->pm; err = pmops->resume(&func->dev); + func->func_status = FUNC_RESUMED; } } diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index 3d8ceb4..0f204dd 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c @@ -28,6 +28,15 @@ #include "sdio_ops.h" +static void mmc_sdio_irq_wakeup(struct mmc_host *host) +{ + int sec = 3; + + pr_info("%s: hold %d seconds to prevent suspend\n", + mmc_hostname(host), sec); + pm_wakeup_event(mmc_dev(host), 1000 * sec); +} + static int process_sdio_pending_irqs(struct mmc_host *host) { struct mmc_card *card = host->card; @@ -42,6 +51,11 @@ static int process_sdio_pending_irqs(struct mmc_host *host) */ func = card->sdio_single_irq; if (func && host->sdio_irq_pending) { + if (mmc_card_keep_power(host) && + mmc_card_wake_sdio_irq(host) && + (func->func_status == FUNC_SUSPENDED)) { + mmc_sdio_irq_wakeup(host); + } func->irq_handler(func); return 1; } @@ -63,6 +77,11 @@ static int process_sdio_pending_irqs(struct mmc_host *host) mmc_card_id(card)); ret = -EINVAL; } else if (func->irq_handler) { + if (mmc_card_keep_power(host) && + mmc_card_wake_sdio_irq(host) && + (func->func_status == FUNC_SUSPENDED)) { + mmc_sdio_irq_wakeup(host); + } func->irq_handler(func); count++; } else { diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h index 50f0bc9..59f4c23 100644 --- a/include/linux/mmc/sdio_func.h +++ b/include/linux/mmc/sdio_func.h @@ -32,6 +32,11 @@ struct sdio_func_tuple { unsigned char data[0]; }; +enum sdio_func_status { + FUNC_RESUMED = 0, /* default value */ + FUNC_SUSPENDED, +}; + /* * SDIO function devices */ @@ -59,6 +64,7 @@ struct sdio_func { const char **info; /* info strings */ struct sdio_func_tuple *tuples; + enum sdio_func_status func_status; /* SDIO function driver state */ }; #define sdio_func_present(f) ((f)->state & SDIO_STATE_PRESENT)