Received: by 2002:a05:6a10:1a4d:0:0:0:0 with SMTP id nk13csp1653954pxb; Wed, 9 Feb 2022 01:17:59 -0800 (PST) X-Google-Smtp-Source: ABdhPJymghP/kZMmr8bb75X0N8RovH/8t8OpC3vlQ9D/kO5a8SHMw9CCKoD9Vkx3NbMeQbb7pbMW X-Received: by 2002:a17:90b:3882:: with SMTP id mu2mr1536824pjb.150.1644398278496; Wed, 09 Feb 2022 01:17:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1644398278; cv=none; d=google.com; s=arc-20160816; b=gby4J7sGl74kF1GPibUCRErOl73MN513Xpqxz3SZV4yEaHDvltlLIuaR4zmZOLV1dE hEK/eRnUxbT+waH2Pt9+9Z4+fKqPWi70Xyw9JEwaTY+O+A6k8qbQx0c/uMu7CxbnoVig O4mLju76gDHZ7KWOh5grvjm48bujwkJSphlbainOTSwklHHcD9h8/BEJtJPeelXVnu3y jbI0JAkjyobU843QWxnxKhrmPXMkPCrjiyd+i57d0o4P/2LYFYnKQfGNhr970FHIimMB dxtkQJYFMrxFNfBXaT5evW9hvb721nAIUkkUL+ka4aJXfacR0FUPiJ8tj6PJKlJdXop9 uWIA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=Kh0F5KM9Ham8qodDxvghac1eX629CeYlEW0DYnSNd4w=; b=tqfL4MPeUWcFnXRWuO0tEkyH74shptJQXUJXM3YGZLtjAKkIbQ8RDK4rZNL85/wEb6 VkIPpmlCecwiZNMgj3b1UjC0s5sC4J+aYhZg187SraJQK2pD9u2yv1OvdBcwFnAQ3LxZ TbVfe/Q7Kqut2hdF6QhpfHPsSA++jQi1ARqBT/vaVn4wytDikVdtk0fuWPQXJuJjbxLY vHpjqS7y1GjHPfQk/xUvRSsFCn9KyldvWqOtBRdvXgQ67oR/o2F9RfM+bLrnrvMAXaj2 P6bRfBneelq856g8IKVpx3CT7k96k7O0G36V1lmvKRFOj2dmy+7pC/SxamKv4BbEy3mT Hn5w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=SofHlcAE; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [2620:137:e000::1:18]) by mx.google.com with ESMTPS id bf16si9180216pgb.57.2022.02.09.01.17.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Feb 2022 01:17:58 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) client-ip=2620:137:e000::1:18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=SofHlcAE; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 81384E032A93; Wed, 9 Feb 2022 00:55:21 -0800 (PST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1388328AbiBGLnc (ORCPT + 99 others); Mon, 7 Feb 2022 06:43:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45128 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1385522AbiBGLb4 (ORCPT ); Mon, 7 Feb 2022 06:31:56 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 141FAC03E963; Mon, 7 Feb 2022 03:30:38 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id AD4AAB80EC3; Mon, 7 Feb 2022 11:30:37 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id F1FD8C004E1; Mon, 7 Feb 2022 11:30:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1644233436; bh=ax9fryblx6QV7qJ+qvkUKsP1d+CzKmmJDTBUlRRYv54=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SofHlcAEqJe1VyQvKZkohCeYA5SPsoCkK7fsWFRdQeVI+mQBJzxyPDukVH+x5V7X5 uhXnXbICSGI6BBK3LuudArPlfGOw8U+JSJmSTe1PYaYGKtY13Vhur93x5/CqMyWZWA /38NsH1oEhiEykwR0McL+MJBw0daJUG+CGCDziGY= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Alexander Sergeyev , Takashi Iwai Subject: [PATCH 5.16 012/126] ALSA: hda: realtek: Fix race at concurrent COEF updates Date: Mon, 7 Feb 2022 12:05:43 +0100 Message-Id: <20220207103804.489874256@linuxfoundation.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220207103804.053675072@linuxfoundation.org> References: <20220207103804.053675072@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Takashi Iwai commit b837a9f5ab3bdfab9233c9f98a6bef717673a3e5 upstream. 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. Reported-by: Alexander Sergeyev Cc: Link: https://lore.kernel.org/r/20220111195229.a77wrpjclqwrx4bx@localhost.localdomain Link: https://lore.kernel.org/r/20220131075738.24323-1-tiwai@suse.de Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 61 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 11 deletions(-) --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -97,6 +97,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; @@ -132,8 +133,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; @@ -142,28 +143,61 @@ static int alc_read_coefex_idx(struct hd 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) \ @@ -196,13 +230,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); } /* @@ -1148,6 +1186,7 @@ static int alc_alloc_spec(struct hda_cod 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) {