From nobody Tue Jun 16 16:00:10 2026 Received: from mail-dy1-f173.google.com (mail-dy1-f173.google.com [74.125.82.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C52AD3559E1 for ; Thu, 30 Apr 2026 21:15:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777583729; cv=none; b=HA3G9ZPN6yy1UMJY6StDOfJMkuMHB2A8RORrXJY2AnEzg68dPNVFrcCaP0FIgIMkgJOTGsRGv+OHjDkrmWGv8caiAZN5DCReSocHzq4YYbcjCOcoiHWGlMRZUv58FD2zRF14HWPvcxcSAGLylxf1otdoD6HOSKbPF9445IWax9g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777583729; c=relaxed/simple; bh=BN5ueWQJ5UCvj7amzpZ4Tl+GzvSYKqtZXakjbyID2uA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZtkGqvLKQToEsNdFshLHqJB0qhtn3kH1fOjFvsPdmFmdViu/Qv5+Th616ZVQLohWEkQ8qJu728pJ5mF4lrkUpSDr4ZV2L9tjvdQqEMqSMJWrZ2Nv+xMwyuV9l56T+hwhqdNRPvtMYTbPqYMn/QY3+tfBZjIjUHF87vgF2SzVZzE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=RFge01hL; arc=none smtp.client-ip=74.125.82.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RFge01hL" Received: by mail-dy1-f173.google.com with SMTP id 5a478bee46e88-2ba9c484e5eso1643030eec.1 for ; Thu, 30 Apr 2026 14:15:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777583727; x=1778188527; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=WhEnXpcubRBw0ZYj7SBybvpNtrwaT7DIm0tUKJlUVgM=; b=RFge01hLfWxC2kqu736QzPO2/idZeyNOaN5j0cXml42YzwVQyomRl50An4tJNPGrRA BgRUcg69axYivfRhki6vXhWL6Xnpyoj44u838bwcJQsoajP3btxj+OrGoHMILLlvcc/J v+82Cu920meZgQwn3M0GkQ6WUKuDzDhfnmox9lyq5SvDdcbfDepde29CFdNgMarCI9gi yPwUScaQqyk5KZ0v8KTY+uxFpCOzZR6Nmcl0Fwb94nEJ6XGu+QEc2qAQdaOPKzQ2Hn8X NAqh0BXdCFThrasJk6M59OMl9C4g3bNv2qfQzghMJk8Ks/aqEQ44Xj90xCxmmE/j5jkY vHsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777583727; x=1778188527; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=WhEnXpcubRBw0ZYj7SBybvpNtrwaT7DIm0tUKJlUVgM=; b=E5UFZpNXD6dSdTB5ioyKp8cgEyRwujFQ9jqMAchwfn5fA/iUw3NJxyKaCg3T/VkssB rnuDfJK6UWiXzh5uqbSNCKmwiVmZjZoilS+Ia73wI9hGe+UqjnHmTTBK5Pc18GSgQx3Y FllGmaWNEBd8bzRKRgp1NAXqJSng+fh5shhlLjPsEndpsDxKBFX2mbW1Z24QoXCKBE5d 7NPAzoTzSPE6hhByMihFP4s3DtRbzyX5z3dLsX3XVCq0McpkUMy+ZEZfmMElPFxWXvBY +E+ReptNWhnt/pq14OjGOZ8qvNu70W+Fgl6UzyJ0AJG0cs2xK46U+eaqocxww3coqP0T Xc6A== X-Forwarded-Encrypted: i=1; AFNElJ+oUtEBpczYt4NaGH3jWZ+i/sDGJoN7HFJPcraiAYWTR2jGtwsEEqrsoZIMRwmVt14CINwda0AP181cdTw=@vger.kernel.org X-Gm-Message-State: AOJu0YzQM2TWD7Oo5/02UFUtxkMyMLjaPAaiZ2KIuBYJ53lb/3/T1fZB pqNj/7juVbaXXBn6jSHbx4d2DtAgihtyYMRcH2eDTf2sBNsmnqToDMid X-Gm-Gg: AeBDieuCptS2CBqAaeIEqOSvyTQT6y7iKgeVtdnT61yrjYFh5o3KEHCNwbLeYJlQlrp KfNAEzTIu9gFqoNT7aoEC2Z0krGY8+TDU1TDYp5wsp4yNUlRzsoJpw7/yqIJEBwM7SqViFv5cFQ NrQDkcY9qB2CjgI0Jf3errfol7w9MiRdH5btAncVrt7KyDyozVjvYgjgUoo5aIkm24aFrKJtlIc HZTld/sKLZX0r+m4DSl7v2DkfFN2X5T6+i8L39f9Nlq3ZuxcDyH5WOBY/7miTtG6FkOq8s0QjtC aHgTefX2SkIAuVWerRbRpczLKXQs1QfFNu+hRPHeTumDsgOQhQEjSMHLDbs5IqXeI8ZYncVjPF9 gtOnN8PUUGZEzNXFg0BDj7JBY/9WrCTp1+MrYy61ihMcIlJ3E8/52p2C8vMPaazVP1lt/7SiD3S 3CnZlE+YLGjySY0Y93ftYZzNIm7G3qCtrYI3pxB1Vxs+43Lca+v52KUDf93MK9T8EcpJl3IuWA1 NZYrBx5jLsW X-Received: by 2002:a05:7300:cac8:b0:2d9:2b54:ea9c with SMTP id 5a478bee46e88-2ed3f15d505mr2387958eec.18.1777583726713; Thu, 30 Apr 2026 14:15:26 -0700 (PDT) Received: from [192.168.1.18] (177-4-161-87.user3p.v-tal.net.br. [177.4.161.87]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2ee3b783a95sm1581959eec.22.2026.04.30.14.15.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Apr 2026 14:15:26 -0700 (PDT) From: =?utf-8?q?C=C3=A1ssio_Gabriel?= Date: Thu, 30 Apr 2026 18:15:10 -0300 Subject: [PATCH v2 1/2] firmware_loader: Add cancel helper for async requests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260430-alsa-hda-tas2781-fw-callback-teardown-v2-1-2c7d89cb3175@gmail.com> References: <20260430-alsa-hda-tas2781-fw-callback-teardown-v2-0-2c7d89cb3175@gmail.com> In-Reply-To: <20260430-alsa-hda-tas2781-fw-callback-teardown-v2-0-2c7d89cb3175@gmail.com> To: Luis Chamberlain , Russ Weight , Danilo Krummrich , Greg Kroah-Hartman , "Rafael J. Wysocki" , Takashi Iwai , Shenghao Ding , Kevin Lu , Baojun Xu , Jaroslav Kysela Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org, Takashi Iwai , =?utf-8?q?C=C3=A1ssio_Gabriel?= X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=6044; i=cassiogabrielcontato@gmail.com; h=from:subject:message-id; bh=BN5ueWQJ5UCvj7amzpZ4Tl+GzvSYKqtZXakjbyID2uA=; b=owGbwMvMwCV2IdZeKur/u2bG02pJDJmfj6UYvvw3P+ZXfilTT/xBR/fD5mkL1vFMvFI+sfZjq Mt0RbH7HaUsDGJcDLJiiiyrkxZZ7ul6cLU+boUHzBxWJpAhDFycAjARC2ZGhlM3BWcKeTX/f7n/ Zvh7PvGUTcKhO1coMn31fqJ/fK7iZXtGhh/GuwNPWVn0CC598XX3Tok3iqU77NTkZzq116/pra8 9wQYA X-Developer-Key: i=cassiogabrielcontato@gmail.com; a=openpgp; fpr=AB62A239BC8AE0D57F5EA848D05D3F1A5AFFEE83 request_firmware_nowait() keeps the callback module pinned and holds a device reference until the firmware work completes. Callers still have no way to cancel or synchronize the queued callback before tearing down their driver-private state. Track async firmware work with devres and add request_firmware_nowait_cancel(). The helper cancels work that has not started yet and waits for an already-running callback to return. If the request has already completed, it is a no-op. The devres release path uses the same synchronization so device teardown cannot free the firmware work state while the queued work can still run. Signed-off-by: C=C3=A1ssio Gabriel --- drivers/base/firmware_loader/main.c | 82 +++++++++++++++++++++++++++++++++= ---- include/linux/firmware.h | 9 ++++ 2 files changed, 83 insertions(+), 8 deletions(-) diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_lo= ader/main.c index a11b30dda23b..d7d80949ecd7 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -1140,6 +1140,30 @@ struct firmware_work { u32 opt_flags; }; =20 +static void firmware_work_free(struct firmware_work *fw_work) +{ + put_device(fw_work->device); /* taken in request_firmware_nowait() */ + module_put(fw_work->module); + kfree_const(fw_work->name); +} + +static int firmware_work_match(struct device *dev, void *res, void *data) +{ + return res =3D=3D data; +} + +static void firmware_work_release(struct device *dev, void *res) +{ + struct firmware_work *fw_work =3D res; + + /* + * Devres release can run before the async work has completed, so + * synchronize it before dropping the references used by the worker. + */ + cancel_work_sync(&fw_work->work); + firmware_work_free(fw_work); +} + static void request_firmware_work_func(struct work_struct *work) { struct firmware_work *fw_work; @@ -1150,11 +1174,16 @@ static void request_firmware_work_func(struct work_= struct *work) _request_firmware(&fw, fw_work->name, fw_work->device, NULL, 0, 0, fw_work->opt_flags); fw_work->cont(fw, fw_work->context); - put_device(fw_work->device); /* taken in request_firmware_nowait() */ =20 - module_put(fw_work->module); - kfree_const(fw_work->name); - kfree(fw_work); + /* + * If teardown already removed the devres entry, it owns the final + * cleanup after cancel_work_sync() waits for this worker. + */ + if (devres_remove(fw_work->device, firmware_work_release, + firmware_work_match, fw_work)) { + firmware_work_free(fw_work); + devres_free(fw_work); + } } =20 =20 @@ -1165,14 +1194,14 @@ static int _request_firmware_nowait( { struct firmware_work *fw_work; =20 - fw_work =3D kzalloc_obj(struct firmware_work, gfp); + fw_work =3D devres_alloc(firmware_work_release, sizeof(*fw_work), gfp); if (!fw_work) return -ENOMEM; =20 fw_work->module =3D module; fw_work->name =3D kstrdup_const(name, gfp); if (!fw_work->name) { - kfree(fw_work); + devres_free(fw_work); return -ENOMEM; } fw_work->device =3D device; @@ -1184,18 +1213,19 @@ static int _request_firmware_nowait( =20 if (!uevent && fw_cache_is_setup(device, name)) { kfree_const(fw_work->name); - kfree(fw_work); + devres_free(fw_work); return -EOPNOTSUPP; } =20 if (!try_module_get(module)) { kfree_const(fw_work->name); - kfree(fw_work); + devres_free(fw_work); return -EFAULT; } =20 get_device(fw_work->device); INIT_WORK(&fw_work->work, request_firmware_work_func); + devres_add(device, fw_work); schedule_work(&fw_work->work); return 0; } @@ -1259,6 +1289,42 @@ int firmware_request_nowait_nowarn( } EXPORT_SYMBOL_GPL(firmware_request_nowait_nowarn); =20 +static int firmware_work_cont_match(struct device *dev, void *res, void *d= ata) +{ + struct firmware_work *fw_work =3D res; + + return fw_work->cont =3D=3D data; +} + +/** + * request_firmware_nowait_cancel() - cancel an async firmware request + * @device: device for which the firmware is being loaded + * @cont: callback passed to request_firmware_nowait() + * + * Cancel a pending request_firmware_nowait() request for @device and @con= t. + * If the associated work has already started, this function waits until t= he + * callback has returned. If the callback has already completed, this func= tion + * does nothing. + * + * This function may sleep. + */ +void request_firmware_nowait_cancel(struct device *device, + void (*cont)(const struct firmware *fw, + void *context)) +{ + struct firmware_work *fw_work; + + fw_work =3D devres_remove(device, firmware_work_release, + firmware_work_cont_match, cont); + if (!fw_work) + return; + + cancel_work_sync(&fw_work->work); + firmware_work_free(fw_work); + devres_free(fw_work); +} +EXPORT_SYMBOL_GPL(request_firmware_nowait_cancel); + #ifdef CONFIG_FW_CACHE static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain); =20 diff --git a/include/linux/firmware.h b/include/linux/firmware.h index aae1b85ffc10..ce55b4987726 100644 --- a/include/linux/firmware.h +++ b/include/linux/firmware.h @@ -110,6 +110,9 @@ int request_firmware_nowait( struct module *module, bool uevent, const char *name, struct device *device, gfp_t gfp, void *context, void (*cont)(const struct firmware *fw, void *context)); +void request_firmware_nowait_cancel(struct device *device, + void (*cont)(const struct firmware *fw, + void *context)); int request_firmware_direct(const struct firmware **fw, const char *name, struct device *device); int request_firmware_into_buf(const struct firmware **firmware_p, @@ -157,6 +160,12 @@ static inline int request_firmware_nowait( return -EINVAL; } =20 +static inline void request_firmware_nowait_cancel(struct device *device, + void (*cont)(const struct firmware *fw, + void *context)) +{ +} + static inline void release_firmware(const struct firmware *fw) { } --=20 2.54.0 From nobody Tue Jun 16 16:00:10 2026 Received: from mail-dy1-f180.google.com (mail-dy1-f180.google.com [74.125.82.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 679F23AB276 for ; Thu, 30 Apr 2026 21:15:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777583733; cv=none; b=XQx95gbaJEq0OCAfghMe1avisLSrX9l3Lkwggjz+ae7HMPtVHsgAv1Dl95Lu1eZq9pmh4cJHsPfw2y5PgJnq6vbDuumYL7HQGURlo1gK+Yp8z290JwD9luUJvPnYdZIFoBMvrK8ubjpTa+uSERstq0r492jcW3RA/Hm3zfdQSP8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777583733; c=relaxed/simple; bh=a2/4NZb1cq6S5TUZgGQmvZJsMsttNjgFGxtg5rSSmVY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=sW7SKr45CWRW1xSJZX0L7o/M7e/DcyIr8bLvsuEIUO2GKVu4t1Qx4q4uAmAnCelrmshX02ibaaHFxbM2uW7qb5ABPdGCv8slsJ/qlMtiy6w77jp5yvyV/I8ZsuYIi9+85g5R9VYfZcCk6je4p0due9FZTlvOSEW6im+PZlqu5W4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=kKxwnJEG; arc=none smtp.client-ip=74.125.82.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kKxwnJEG" Received: by mail-dy1-f180.google.com with SMTP id 5a478bee46e88-2c15849aa2cso2098782eec.0 for ; Thu, 30 Apr 2026 14:15:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777583732; x=1778188532; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=u5HU0juTrz/+bwfhVRVrLsU2IXIIJwo9lCW9lyuPHrs=; b=kKxwnJEGCtsHTgv4VoUkOt1Th28Qyo02lxw30BFbeDfYQyLew/K+5otDe21Ogss4eG 6BJitBwQfeU0jaKi6qb3nEfmaQXS5oO04PLigJyVNMpGG2SN0AHpgb+BxCQdkReRZUzo ukgcnAC/z8M7FBNJy4SI2IDxqJap0IWqkXShs2ou3A6DOclsLEGzE/m+Q9dLyTmQA0zn 9OCtZfQa3myC9btptJeW2wh5JqNDZtMagARtDC9vrKiOSub6QqcuoBu8dzcbPaGebBkG hxtvXpTfE992B+mz1ZeGfh4QIe/WCIP2ylM3oCg+ym1IbmHd9Y8MGcz/WEoWkdHonTTO 3muQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777583732; x=1778188532; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=u5HU0juTrz/+bwfhVRVrLsU2IXIIJwo9lCW9lyuPHrs=; b=Hw0bKst3rlJwDsrg+D6LO4Uq8nI53IXXBvVjGUGcMKLjSpEiVWRdquB6hduSX0gFLW mMkjDUyS1NSjNRukSWiCyIxWAADP3q5S4A734Gc4kICurK3PtxfxTDFwpjpZ1sf/Zz19 Am5IXQEA7T8WQ1AMAhY0Fa7gYdClmLsEADw7EmoCbHpSGdXZqEaLbpRJA4CkxXIwpl14 8VrYbs1tFwFVkn4zF6AnKjoS129vqJmI9qAiWMr35ByOTujrMoWnufAIWlFOhxB4eb66 4U2JXSYY4+mRdNVJ4SSL/ZcsaxvyevniXQA7IrZM9DNgzm/7bqjJug8ckY/S3Htc4emO 9Huw== X-Forwarded-Encrypted: i=1; AFNElJ/2U9X/LQmx7c86xnj5SyWGlwdxrRcHmPiMhzaw3I5nQa83Uxy0vSIsb6IGxNHJV/yFRpqmbl+/WD340Qc=@vger.kernel.org X-Gm-Message-State: AOJu0YwAXsqJaoSqRHkT5ahXdv4A6kq9QoLIZ6fY2zAktghke9+jlr/1 jUc6LmzKexp1Xh9fFYkrxnCt2h3vVYGZPE8spV8BFvMAprTTBFFYpU/d X-Gm-Gg: AeBDietwcn2QNB6XsPhTwR8ac+3gEA8VkpJb/oK4QOnvxRo24DhtF8hONdEAG8RTSyA 2C9F2KA9f6QpTXzS/HJkSilpuYVxecAE2gLv53nMKeqjqYw/BglNq5bjqsbFqfDxwDu/5HHlTyf 7QjslytZd/JUWTcqOgmE57ty1nH+L4s/6q0TQHGrhzE6oMbVO+AeGS64KIemOq85Mq8H6bQ2I8X ajgSh226tlYbDxzipVP0UgCoNKDpafUqIIBft3In18lzDVBQlTraO4wRPrEksQaXQsyT+BKO5hR 4AuO+s8myYv301k3JHJOVjCokfsURywYO8LqMkUbNGIvu/mm44+jlrgU1nojtI5EOWvUpXjsX7d siLusH5WNaIbDxip+xXICCAL+G1uK08sgCiMEHTeuf0bOD9voRGxoWD+0VK48yfWoq4uG39Koa6 bcW0b2w16aml+jTO1lbtrjkcCn/jEkSUlaeB03hc9NXm5s7ARHf7nKYP8sPX9JoqihvGlff6x9V wbFph+hI+wN X-Received: by 2002:a05:7300:cac8:b0:2ce:25be:c8e8 with SMTP id 5a478bee46e88-2ed3f15d4e0mr2351042eec.17.1777583731421; Thu, 30 Apr 2026 14:15:31 -0700 (PDT) Received: from [192.168.1.18] (177-4-161-87.user3p.v-tal.net.br. [177.4.161.87]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2ee3b783a95sm1581959eec.22.2026.04.30.14.15.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Apr 2026 14:15:31 -0700 (PDT) From: =?utf-8?q?C=C3=A1ssio_Gabriel?= Date: Thu, 30 Apr 2026 18:15:11 -0300 Subject: [PATCH v2 2/2] ALSA: hda/tas2781: Cancel async firmware request at unbind Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260430-alsa-hda-tas2781-fw-callback-teardown-v2-2-2c7d89cb3175@gmail.com> References: <20260430-alsa-hda-tas2781-fw-callback-teardown-v2-0-2c7d89cb3175@gmail.com> In-Reply-To: <20260430-alsa-hda-tas2781-fw-callback-teardown-v2-0-2c7d89cb3175@gmail.com> To: Luis Chamberlain , Russ Weight , Danilo Krummrich , Greg Kroah-Hartman , "Rafael J. Wysocki" , Takashi Iwai , Shenghao Ding , Kevin Lu , Baojun Xu , Jaroslav Kysela Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org, Takashi Iwai , =?utf-8?q?C=C3=A1ssio_Gabriel?= , stable@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=2197; i=cassiogabrielcontato@gmail.com; h=from:subject:message-id; bh=a2/4NZb1cq6S5TUZgGQmvZJsMsttNjgFGxtg5rSSmVY=; b=owGbwMvMwCV2IdZeKur/u2bG02pJDJmfj6W+ZUkUXdEW9+/VnoZpvg5rn7+9absxJKC+v2dqp 7FQ6bGDHaUsDGJcDLJiiiyrkxZZ7ul6cLU+boUHzBxWJpAhDFycAjCRL3EM/1S+9qy722QU1d+t lBwu6vzwg32OG3/QW6Pp0zpMxRWZvzIyLHQPWvF4+95dJxoMtv6+VurxX0XFy3vVFMfrmtktnYk feAA= X-Developer-Key: i=cassiogabrielcontato@gmail.com; a=openpgp; fpr=AB62A239BC8AE0D57F5EA848D05D3F1A5AFFEE83 TAS2781 HDA I2C and SPI queue RCA firmware loading from component bind with request_firmware_nowait(). The firmware loader keeps the callback module pinned and holds a device reference, but the callback still uses driver-private HDA state. Component unbind removes controls and DSP state immediately. Later device removal tears down the TAS2781 private data, including codec_lock. If the async firmware callback runs after unbind has started, it can operate on state that is being torn down. Cancel or synchronize the async firmware request before removing controls and DSP state. A queued callback is cancelled, and an already-running callback is allowed to finish before unbind continues. Fixes: 5be27f1e3ec9 ("ALSA: hda/tas2781: Add tas2781 HDA driver") Fixes: bb5f86ea50ff ("ALSA: hda/tas2781: Add tas2781 hda SPI driver") Cc: stable@vger.kernel.org Signed-off-by: C=C3=A1ssio Gabriel --- sound/hda/codecs/side-codecs/tas2781_hda_i2c.c | 2 ++ sound/hda/codecs/side-codecs/tas2781_hda_spi.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c b/sound/hda/cod= ecs/side-codecs/tas2781_hda_i2c.c index 67240ce184e1..34c6940f3521 100644 --- a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c +++ b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c @@ -588,6 +588,8 @@ static void tas2781_hda_unbind(struct device *dev, comp->playback_hook =3D NULL; } =20 + request_firmware_nowait_cancel(tas_hda->priv->dev, tasdev_fw_ready); + tas2781_hda_remove_controls(tas_hda); =20 tasdevice_config_info_remove(tas_hda->priv); diff --git a/sound/hda/codecs/side-codecs/tas2781_hda_spi.c b/sound/hda/cod= ecs/side-codecs/tas2781_hda_spi.c index 0e4f3553f273..6b0d6c764009 100644 --- a/sound/hda/codecs/side-codecs/tas2781_hda_spi.c +++ b/sound/hda/codecs/side-codecs/tas2781_hda_spi.c @@ -750,6 +750,8 @@ static void tas2781_hda_unbind(struct device *dev, stru= ct device *master, comp->playback_hook =3D NULL; } =20 + request_firmware_nowait_cancel(tas_priv->dev, tasdev_fw_ready); + tas2781_hda_remove_controls(tas_hda); =20 tasdevice_config_info_remove(tas_priv); --=20 2.54.0