Received: by 2002:a05:6a10:af89:0:0:0:0 with SMTP id iu9csp5516296pxb; Wed, 26 Jan 2022 13:56:20 -0800 (PST) X-Google-Smtp-Source: ABdhPJyszpopngfcpE58avevXz7kjcxk96SVNKlAO9x4rGVz4kdI2X+1xPP2jQ12TRCQ5pH/83x9 X-Received: by 2002:a17:906:c28d:: with SMTP id r13mr550402ejz.389.1643234180103; Wed, 26 Jan 2022 13:56:20 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1643234180; cv=none; d=google.com; s=arc-20160816; b=gTR4RCY8Eh30t9GmVCGfifckxtS7GOU6FyxviG9L012ne+h19hZQoUKus/gWiRmTAr M/lSeW/wYKrWRIUtEVuZegUwSpLBaB0Pfbo5nUCah11+AjQT+uraa5oZNXbvX7WhbbLg dBwWFQYSVU7qg+vZjx3jUXQa5xTjPbzPqvckgAZD4ezJy9cti1ufdqyaqP84RrnFOJr4 znfoAVOyDFlmPnAnbdrldgbxx6sAVVy9bohW26fSkc/mVkMfrq/Wjr+641dmqw8KsXl2 FwyDScUl+FA5ncHF8y+A8IhSp2Y7FodH9LXL5ONL5WHzh+OZGAZN/OI07mYwvGCNXEb+ pIlQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:user-agent:references:in-reply-to :subject:cc:to:from:message-id:date:dkim-signature:dkim-signature; bh=9CXY7MFbJ1saOKK9+Yf3pb9u+zx6DrRm92wfkukypJU=; b=hq3dS+hWZyCK/cKp2j1z/eU2qHlYON7ir0o1ZgVQB4bG8LIohPqMF5IrhpFqcPtN2B yDZyeaQz5E/b1C4EYc7daGYOsWthTMYZjatVEurLJWClcj86V0KmJf0EM2TplVGKIGAU OfVY5PQDIp63lH2HXtr/IM0JKlBg2iHbC/v+j+yJ6Ees9AA11ZhrAxYL5JU8SrZqGmEy UpuaUUtWzfVUtEiOKZ2g9VLA7UM46vb4G7nC3IwZQP87dY3v8VR/wWbXKfMJAHqtocc4 TDuyyaLPtLubcH2KdGzp9y8zxGvtaUw0Ee3coYzj68wM+tQzGmMaobjfwz/KmHY8QWbE gMDA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@suse.de header.s=susede2_rsa header.b=j9C4LuPO; dkim=neutral (no key) header.i=@suse.de header.s=susede2_ed25519 header.b=Zcv47eTl; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=suse.de Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id gn27si251512ejc.879.2022.01.26.13.55.53; Wed, 26 Jan 2022 13:56:20 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@suse.de header.s=susede2_rsa header.b=j9C4LuPO; dkim=neutral (no key) header.i=@suse.de header.s=susede2_ed25519 header.b=Zcv47eTl; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=suse.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236226AbiAZPYh (ORCPT + 99 others); Wed, 26 Jan 2022 10:24:37 -0500 Received: from smtp-out2.suse.de ([195.135.220.29]:37366 "EHLO smtp-out2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236079AbiAZPYh (ORCPT ); Wed, 26 Jan 2022 10:24:37 -0500 Received: from relay2.suse.de (relay2.suse.de [149.44.160.134]) by smtp-out2.suse.de (Postfix) with ESMTP id 343C01F3B0; Wed, 26 Jan 2022 15:24:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1643210676; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=9CXY7MFbJ1saOKK9+Yf3pb9u+zx6DrRm92wfkukypJU=; b=j9C4LuPOb5XoFVk6uxHIO8WC5JbJfuf9jmV9L6Kx2lRSXZEqcFPNULeh0IL+8Klm088Mhv VVABBZSIxItC72DaJhTo4TIEe8RAPpl51T+Jup4gOlFOoA78p9Rg2std/7tu5wRVElYPkj 5rM1DiS2T2ol6/t79eDHWxsAlWOJRfA= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1643210676; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=9CXY7MFbJ1saOKK9+Yf3pb9u+zx6DrRm92wfkukypJU=; b=Zcv47eTlQd7aDCA72boLRhzkKoNf/ZcDAsLb7bnW2iDfHVLc2QbqnzOKDYdAl7axDb5SQH b6sfpqO/K/rKaIBA== Received: from alsa1.suse.de (alsa1.suse.de [10.160.4.42]) by relay2.suse.de (Postfix) with ESMTP id 1D799A3B81; Wed, 26 Jan 2022 15:24:36 +0000 (UTC) Date: Wed, 26 Jan 2022 16:24:36 +0100 Message-ID: From: Takashi Iwai To: Alexander Sergeyev Cc: Jeremy Szu , tiwai@suse.com, "moderated list:SOUND" , Kailang Yang , open list , Huacai Chen , Jian-Hong Pan , Hui Wang , PeiSen Hou Subject: Re: [PATCH 1/4] ALSA: hda/realtek: fix mute/micmute LEDs for HP 855 G8 In-Reply-To: <20220122205637.7gzurdu7xl4sthxw@localhost.localdomain> References: <20220112201824.qmphnz2hx4frda6e@localhost.localdomain> <20220113183141.kla37mbqmo4x6wxp@localhost.localdomain> <20220114183720.n46wealclg6spxkp@localhost.localdomain> <20220115152215.kprws5nja2i43qax@localhost.localdomain> <20220119093249.eaxem33bjqjxcher@localhost.localdomain> <20220122190522.ycaygrqcen7d3hj2@localhost.localdomain> <20220122205637.7gzurdu7xl4sthxw@localhost.localdomain> User-Agent: Wanderlust/2.15.9 (Almost Unreal) SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL/10.8 Emacs/25.3 (x86_64-suse-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Sat, 22 Jan 2022 21:56:37 +0100, Alexander Sergeyev wrote: > > On Sat, Jan 22, 2022 at 10:05:24PM +0300, Alexander Sergeyev wrote: > > I'm not sure about kernel log buffering or maybe the device support for > > pipelining, but is it okay that alc_update_coefex_idx() seem to overlap? > > Given that the CPU number is the same in alc_update_coefex_idx(), it seems > these calls execution is interrupted and interleaved on the same core. > > And, actually, there are two LEDs to set (mute and micmute). Am I onto > something here? That's an interesting finding, and yes, such a race is quite possible. Below is a quick fix as an attempt to cover it. Could you give it a try? BTW, the fix for the unbind problem was submitted. It's a slightly more simplified version than what I posted here beforehand. thanks, Takashi -- 8< -- From: Takashi Iwai Subject: [PATCH] ALSA: hda: realtek: Fix race at concurrent COEF updates The COEF access is done with two steps: setting the index then read or write the data. When multiple COEF accesses are performed concurrently, the index and data might be paired unexpectedly. In most cases, this isn't a big problem as the COEF setup is done at the initialization, but some dynamic changes like the mute LED may hit such a race. For avoiding the racy COEF accesses, this patch introduces a new mutex coef_mutex to alc_spec, and wrap the COEF accessing functions with it. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 61 ++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 668274e52674..a5677be0a405 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -98,6 +98,7 @@ struct alc_spec { unsigned int gpio_mic_led_mask; struct alc_coef_led mute_led_coef; struct alc_coef_led mic_led_coef; + struct mutex coef_mutex; hda_nid_t headset_mic_pin; hda_nid_t headphone_mic_pin; @@ -137,8 +138,8 @@ struct alc_spec { * COEF access helper functions */ -static int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, - unsigned int coef_idx) +static int __alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, + unsigned int coef_idx) { unsigned int val; @@ -147,28 +148,61 @@ static int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, return val; } +static int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, + unsigned int coef_idx) +{ + struct alc_spec *spec = codec->spec; + unsigned int val; + + mutex_lock(&spec->coef_mutex); + val = __alc_read_coefex_idx(codec, nid, coef_idx); + mutex_unlock(&spec->coef_mutex); + return val; +} + #define alc_read_coef_idx(codec, coef_idx) \ alc_read_coefex_idx(codec, 0x20, coef_idx) -static void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid, - unsigned int coef_idx, unsigned int coef_val) +static void __alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid, + unsigned int coef_idx, unsigned int coef_val) { snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, coef_idx); snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PROC_COEF, coef_val); } +static void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid, + unsigned int coef_idx, unsigned int coef_val) +{ + struct alc_spec *spec = codec->spec; + + mutex_lock(&spec->coef_mutex); + __alc_write_coefex_idx(codec, nid, coef_idx, coef_val); + mutex_unlock(&spec->coef_mutex); +} + #define alc_write_coef_idx(codec, coef_idx, coef_val) \ alc_write_coefex_idx(codec, 0x20, coef_idx, coef_val) +static void __alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid, + unsigned int coef_idx, unsigned int mask, + unsigned int bits_set) +{ + unsigned int val = __alc_read_coefex_idx(codec, nid, coef_idx); + + if (val != -1) + __alc_write_coefex_idx(codec, nid, coef_idx, + (val & ~mask) | bits_set); +} + static void alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid, unsigned int coef_idx, unsigned int mask, unsigned int bits_set) { - unsigned int val = alc_read_coefex_idx(codec, nid, coef_idx); + struct alc_spec *spec = codec->spec; - if (val != -1) - alc_write_coefex_idx(codec, nid, coef_idx, - (val & ~mask) | bits_set); + mutex_lock(&spec->coef_mutex); + __alc_update_coefex_idx(codec, nid, coef_idx, mask, bits_set); + mutex_unlock(&spec->coef_mutex); } #define alc_update_coef_idx(codec, coef_idx, mask, bits_set) \ @@ -201,13 +235,17 @@ struct coef_fw { static void alc_process_coef_fw(struct hda_codec *codec, const struct coef_fw *fw) { + struct alc_spec *spec = codec->spec; + + mutex_lock(&spec->coef_mutex); for (; fw->nid; fw++) { if (fw->mask == (unsigned short)-1) - alc_write_coefex_idx(codec, fw->nid, fw->idx, fw->val); + __alc_write_coefex_idx(codec, fw->nid, fw->idx, fw->val); else - alc_update_coefex_idx(codec, fw->nid, fw->idx, - fw->mask, fw->val); + __alc_update_coefex_idx(codec, fw->nid, fw->idx, + fw->mask, fw->val); } + mutex_unlock(&spec->coef_mutex); } /* @@ -1153,6 +1191,7 @@ static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid) codec->spdif_status_reset = 1; codec->forced_resume = 1; codec->patch_ops = alc_patch_ops; + mutex_init(&spec->coef_mutex); err = alc_codec_rename_from_preset(codec); if (err < 0) { -- 2.31.1