From patchwork Mon Mar 16 04:47:15 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuninori Morimoto X-Patchwork-Id: 6015441 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 4E2E2BF90F for ; Mon, 16 Mar 2015 04:53:53 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3F4FA203EB for ; Mon, 16 Mar 2015 04:53:52 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id C5E2220376 for ; Mon, 16 Mar 2015 04:53:50 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id E16F7261522; Mon, 16 Mar 2015 05:53:49 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id 32F76260541; Mon, 16 Mar 2015 05:49:38 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id CE62D260541; Mon, 16 Mar 2015 05:49:36 +0100 (CET) Received: from relmlie2.idc.renesas.com (relmlor3.renesas.com [210.160.252.173]) by alsa0.perex.cz (Postfix) with ESMTP id DBC30260686 for ; Mon, 16 Mar 2015 05:47:19 +0100 (CET) Received: from unknown (HELO relmlir3.idc.renesas.com) ([10.200.68.153]) by relmlie2.idc.renesas.com with ESMTP; 16 Mar 2015 13:47:18 +0900 Received: from relmlac3.idc.renesas.com (relmlac3.idc.renesas.com [10.200.69.23]) by relmlir3.idc.renesas.com (Postfix) with ESMTP id 7892A4155A; Mon, 16 Mar 2015 13:47:18 +0900 (JST) Received: by relmlac3.idc.renesas.com (Postfix, from userid 0) id 607EA1806F; Mon, 16 Mar 2015 13:47:18 +0900 (JST) Received: from relmlac3.idc.renesas.com (localhost [127.0.0.1]) by relmlac3.idc.renesas.com (Postfix) with ESMTP id 5B8CB1800A; Mon, 16 Mar 2015 13:47:18 +0900 (JST) Received: from relmlii2.idc.renesas.com [10.200.68.66] by relmlac3.idc.renesas.com with ESMTP id PAA17226; Mon, 16 Mar 2015 13:47:18 +0900 X-IronPort-AV: E=Sophos;i="5.11,407,1422889200"; d="scan'208";a="183126498" Received: from mail-sg1lp0086.outbound.protection.outlook.com (HELO APAC01-SG1-obe.outbound.protection.outlook.com) ([207.46.51.86]) by relmlii2.idc.renesas.com with ESMTP/TLS/AES256-SHA; 16 Mar 2015 13:47:17 +0900 Received: from morimoto-PC.renesas.com (211.11.155.132) by SINPR06MB314.apcprd06.prod.outlook.com (10.141.115.145) with Microsoft SMTP Server (TLS) id 15.1.112.16; Mon, 16 Mar 2015 04:47:15 +0000 Message-ID: <87zj7dim6d.wl%kuninori.morimoto.gx@renesas.com> From: Kuninori Morimoto User-Agent: Wanderlust/2.15.9 Emacs/24.3 Mule/6.0 To: Mark Brown In-Reply-To: <87egopk13d.wl%kuninori.morimoto.gx@renesas.com> References: <87egopk13d.wl%kuninori.morimoto.gx@renesas.com> MIME-Version: 1.0 (generated by SEMI-EPG 1.14.7 - "Harue") Date: Mon, 16 Mar 2015 04:47:15 +0000 X-Originating-IP: [211.11.155.132] X-ClientProxiedBy: TY1PR01CA0010.jpnprd01.prod.outlook.com (25.161.131.148) To SINPR06MB314.apcprd06.prod.outlook.com (10.141.115.145) Authentication-Results: kernel.org; dkim=none (message not signed) header.d=none; X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:SINPR06MB314; X-Forefront-Antispam-Report: BMV:1; SFV:NSPM; SFS:(10019020)(6009001)(110136001)(53416004)(40100003)(46406003)(77096005)(83506001)(87976001)(122386002)(42186005)(19580395003)(92566002)(86362001)(66066001)(2950100001)(62966003)(77156002)(50986999)(76176999)(54356999)(229853001)(36756003)(46102003)(33646002)(19580405001)(50466002); DIR:OUT; SFP:1102; SCL:1; SRVR:SINPR06MB314; H:morimoto-PC.renesas.com; FPR:; SPF:None; MLV:sfv; LANG:en; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(5002010)(5005006); SRVR:SINPR06MB314; BCL:0; PCL:0; RULEID:; SRVR:SINPR06MB314; X-Forefront-PRVS: 05177D47DC X-OriginatorOrg: renesas.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Mar 2015 04:47:15.4521 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: SINPR06MB314 Cc: Linux-ALSA , Simon , shiiba , Liam Girdwood , Das Biju Subject: [alsa-devel] [PATCH 10/12 v2] ASoC: rsnd: don't call clk_prepare_enable/unprepare() from inside spin lock X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP From: Kuninori Morimoto clk_prepare_enable/unprepare() uses mutex inside, and it uses __schedule(). Then, raw_spin_lock/unlock_irq() is called, and it breaks Renesas sound driver's spin lock irq. This patch moves clk_prepare_enable/unprepare to out of spin lock area. Special thanks to Das Biju. Reported-by: Das Biju Signed-off-by: Kuninori Morimoto --- v1 -> v2 - no change sound/soc/sh/rcar/core.c | 29 ++++++++++++++++++++++++++++- sound/soc/sh/rcar/dvc.c | 12 +----------- sound/soc/sh/rcar/rsnd.h | 9 +++++++-- sound/soc/sh/rcar/src.c | 6 ++---- sound/soc/sh/rcar/ssi.c | 22 ++++++++++++++++++---- 5 files changed, 56 insertions(+), 22 deletions(-) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 54042d9..e6c1c7a4 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -190,7 +190,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) ({ \ struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ struct device *dev = rsnd_priv_to_dev(priv); \ - u32 mask = 1 << __rsnd_mod_shift_##func; \ + u32 mask = (1 << __rsnd_mod_shift_##func) & ~(1 << 31); \ u32 call = __rsnd_mod_call_##func << __rsnd_mod_shift_##func; \ int ret = 0; \ if ((mod->status & mask) == call) { \ @@ -222,6 +222,27 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) ret; \ }) +int rsnd_mod_clk(struct rsnd_mod *mod, int enable) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct device *dev = rsnd_priv_to_dev(priv); + + /* + * clk_prepare_enable/unprepare() should not be called + * from inside spin lock + */ + if (enable) + clk_prepare_enable(mod->clk); + else + clk_disable_unprepare(mod->clk); + + dev_dbg(dev, "%s[%d] clk %s\n", + rsnd_mod_name(mod), rsnd_mod_id(mod), + enable ? "ON" : "OFF"); + + return 0; +} + static int rsnd_dai_connect(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { @@ -345,6 +366,9 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, int ret; unsigned long flags; + if (cmd == SNDRV_PCM_TRIGGER_START) + rsnd_dai_call(clk, io, 1); + rsnd_lock(priv, flags); switch (cmd) { @@ -385,6 +409,9 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, dai_trigger_end: rsnd_unlock(priv, flags); + if (cmd == SNDRV_PCM_TRIGGER_STOP) + rsnd_dai_call(clk, io, 0); + return ret; } diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index aeeef13..9420349 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -166,8 +166,6 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, return -EINVAL; } - rsnd_mod_hw_start(dvc_mod); - /* * fixme * it doesn't support CTU/MIX @@ -191,14 +189,6 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, return 0; } -static int rsnd_dvc_quit(struct rsnd_mod *mod, - struct rsnd_priv *priv) -{ - rsnd_mod_hw_stop(mod); - - return 0; -} - static int rsnd_dvc_start(struct rsnd_mod *mod, struct rsnd_priv *priv) { @@ -286,9 +276,9 @@ static struct rsnd_mod_ops rsnd_dvc_ops = { .probe = rsnd_dvc_probe_gen2, .remove = rsnd_dvc_remove_gen2, .init = rsnd_dvc_init, - .quit = rsnd_dvc_quit, .start = rsnd_dvc_start, .stop = rsnd_dvc_stop, + .clk = rsnd_mod_clk, .pcm_new = rsnd_dvc_pcm_new, }; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 52c401c..40a12f4 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -237,6 +237,7 @@ struct rsnd_mod_ops { struct rsnd_priv *priv); int (*stop)(struct rsnd_mod *mod, struct rsnd_priv *priv); + int (*clk)(struct rsnd_mod *mod, int enable); int (*pcm_new)(struct rsnd_mod *mod, struct snd_soc_pcm_runtime *rtd); int (*fallback)(struct rsnd_mod *mod, @@ -262,6 +263,9 @@ struct rsnd_mod { * 2 0: start 1: stop * 3 0: pcm_new * 4 0: fallback + * + * 31 bit is always called (see __rsnd_mod_call) + * 31 0: clk */ #define __rsnd_mod_shift_probe 0 #define __rsnd_mod_shift_remove 0 @@ -271,6 +275,7 @@ struct rsnd_mod { #define __rsnd_mod_shift_stop 2 #define __rsnd_mod_shift_pcm_new 3 #define __rsnd_mod_shift_fallback 4 +#define __rsnd_mod_shift_clk 31 /* always called */ #define __rsnd_mod_call_probe 0 #define __rsnd_mod_call_remove 1 @@ -280,13 +285,12 @@ struct rsnd_mod { #define __rsnd_mod_call_stop 1 #define __rsnd_mod_call_pcm_new 0 #define __rsnd_mod_call_fallback 0 +#define __rsnd_mod_call_clk 0 #define rsnd_mod_to_priv(mod) (rsnd_io_to_priv(rsnd_mod_to_io(mod))) #define rsnd_mod_to_dma(mod) (&(mod)->dma) #define rsnd_mod_to_io(mod) ((mod)->io) #define rsnd_mod_id(mod) ((mod)->id) -#define rsnd_mod_hw_start(mod) clk_prepare_enable((mod)->clk) -#define rsnd_mod_hw_stop(mod) clk_disable_unprepare((mod)->clk) void rsnd_mod_init(struct rsnd_mod *mod, struct rsnd_mod_ops *ops, @@ -294,6 +298,7 @@ void rsnd_mod_init(struct rsnd_mod *mod, enum rsnd_mod_type type, int id); char *rsnd_mod_name(struct rsnd_mod *mod); +int rsnd_mod_clk(struct rsnd_mod *mod, int enable); struct dma_chan *rsnd_mod_dma_req(struct rsnd_mod *mod); /* diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index cc93f32..83032ee 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -292,8 +292,6 @@ static int rsnd_src_init(struct rsnd_mod *mod) { struct rsnd_src *src = rsnd_mod_to_src(mod); - rsnd_mod_hw_start(mod); - src->err = 0; /* @@ -311,8 +309,6 @@ static int rsnd_src_quit(struct rsnd_mod *mod, struct rsnd_src *src = rsnd_mod_to_src(mod); struct device *dev = rsnd_priv_to_dev(priv); - rsnd_mod_hw_stop(mod); - if (src->err) dev_warn(dev, "%s[%d] under/over flow err = %d\n", rsnd_mod_name(mod), rsnd_mod_id(mod), src->err); @@ -523,6 +519,7 @@ static struct rsnd_mod_ops rsnd_src_gen1_ops = { .quit = rsnd_src_quit, .start = rsnd_src_start_gen1, .stop = rsnd_src_stop_gen1, + .clk = rsnd_mod_clk, }; /* @@ -803,6 +800,7 @@ static struct rsnd_mod_ops rsnd_src_gen2_ops = { .quit = rsnd_src_quit, .start = rsnd_src_start_gen2, .stop = rsnd_src_stop_gen2, + .clk = rsnd_mod_clk, }; struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 060d3d2..583ca97 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -176,6 +176,22 @@ static void rsnd_ssi_master_clk_stop(struct rsnd_ssi *ssi) rsnd_adg_ssi_clk_stop(&ssi->mod); } +static int rsnd_ssi_clk(struct rsnd_mod *mod, int enable) +{ + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + struct rsnd_dai *rdai = rsnd_io_to_rdai(io); + + rsnd_mod_clk(mod, enable); + + if (rsnd_rdai_is_clk_master(rdai)) { + if (rsnd_ssi_clk_from_parent(ssi)) + rsnd_mod_clk(&ssi->parent->mod, enable); + } + + return 0; +} + static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, struct rsnd_dai_stream *io) { @@ -186,8 +202,6 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, u32 cr; if (0 == ssi->usrcnt) { - rsnd_mod_hw_start(&ssi->mod); - if (rsnd_rdai_is_clk_master(rdai)) { if (rsnd_ssi_clk_from_parent(ssi)) rsnd_ssi_hw_start(ssi->parent, io); @@ -258,8 +272,6 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi) else rsnd_ssi_master_clk_stop(ssi); } - - rsnd_mod_hw_stop(&ssi->mod); } dev_dbg(dev, "%s[%d] hw stopped\n", @@ -462,6 +474,7 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .quit = rsnd_ssi_quit, .start = rsnd_ssi_start, .stop = rsnd_ssi_stop, + .clk = rsnd_ssi_clk, }; static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, @@ -581,6 +594,7 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { .quit = rsnd_ssi_quit, .start = rsnd_ssi_dma_start, .stop = rsnd_ssi_dma_stop, + .clk = rsnd_ssi_clk, .fallback = rsnd_ssi_fallback, };