From nobody Thu Sep 24 21:19:00 2026 Received: from mout02.posteo.de (mout02.posteo.de [185.67.36.66]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4328037C911 for ; Sun, 20 Sep 2026 14:30:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.67.36.66 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789914612; cv=none; b=LF6ljUrNJl1TYTEKx0ppXAzaSNd0Xzwh28iqAumg7wU53/sVyWMr6GNVjPzv/WWyZzX0xF/6fT+LAnY1hHro2j634S34RRECeapAemfeyXidQjHeQThu5QRyhbG8DGpsshgEU3fsWnVtU6s1PKmMBESZppj+bUvYXdhcX8GWD80= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789914612; c=relaxed/simple; bh=/fMAcO+ftttYi+uUEagRZ+sTL7X7DJ+w5m64YxpfCNE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Hhpdt7W8XCxGxfkykeTtGYjmAixdJjDZqhWJWcUDvmSMBdCKuO2k6icldIgylN3aOOj2VD7qkrQLH9l6EJr5SXwY84o8TEe1xg/3f2IYAQhiOMYZ5SEwJupi5Vt0IzRbKSr1clrkgCMH5ElJlyWXWxiImOCt7l0RJ39vMSI/yw0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=posteo.de; spf=pass smtp.mailfrom=posteo.de; dkim=pass (2048-bit key) header.d=posteo.de header.i=@posteo.de header.b=Pg1yl4Gv; arc=none smtp.client-ip=185.67.36.66 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=posteo.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=posteo.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=posteo.de header.i=@posteo.de header.b="Pg1yl4Gv" Received: from submission (posteo.de [185.67.36.169]) by mout02.posteo.de (Postfix) with ESMTPS id D490F240101 for ; Sun, 20 Sep 2026 16:29:59 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=posteo.de; s=1984.8680eb; t=1789914599; bh=u0nIJ8CVi5r4jIStW9VLW1QJern+HgJu1P9wDpDmQlM=; h=From:Date:Subject:MIME-Version:Content-Type: Content-Transfer-Encoding:Message-Id:To:Cc:Autocrypt:OpenPGP:From; b=Pg1yl4GvPd+psKHFUxLCj/y/tP/5ZMRHm7Htz3yz2O8j7y8SIbWiaLon9GHTBIukO BBjh9GFGtMV82bTvWHTGvdaLWQYgC4Ki1z9VZl+541x4cnBGZ5VgOPAHRJYp8kD9JC HUQHE0tb3oHTv5yIIInrD7/sdzwfHaV07tofAwUjk7TJ7wxNBe0Xq1zf/jVaGaSyt6 3U8o69xvusEZyofHfo+3kdvKyLX20HFVqbH1fih0uUK88BaCBskFpQSpPeXvWt46nJ +GAbxNlzAwBe/73ODPBOGwzVaFFiDdokxjtfN416IiepV/ulOxdDt12nms0pC6kO6r rodABtEQ8Dzww== Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4hnpfX651Hz9rxM; Sun, 20 Sep 2026 16:29:56 +0200 (CEST) From: Markus Probst Date: Sun, 20 Sep 2026 14:29:58 +0000 Subject: [PATCH v2 1/3] tty: serdev: Export functions to pause receive_buf callback calls 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: <20260920-rust_serdev_probe_refactor-v2-1-43b855162f5d@posteo.de> References: <20260920-rust_serdev_probe_refactor-v2-0-43b855162f5d@posteo.de> In-Reply-To: <20260920-rust_serdev_probe_refactor-v2-0-43b855162f5d@posteo.de> To: Ayush Singh , Johan Hovold , Alex Elder , Greg Kroah-Hartman , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , Eric Biggers , Ard Biesheuvel , Lorenzo Stoakes , Vlastimil Babka , "Liam R. Howlett" , Uladzislau Rezki , Jiri Slaby , "Rafael J. Wysocki" Cc: greybus-dev@lists.linaro.org, linux-serial@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, driver-core@lists.linux.dev, Markus Probst X-Developer-Signature: v=1; a=openpgp-sha256; l=6630; i=markus.probst@posteo.de; h=from:subject:message-id; bh=/fMAcO+ftttYi+uUEagRZ+sTL7X7DJ+w5m64YxpfCNE=; b=owEBiQJ2/ZANAwAIATR2H/jnrUPSAcsmYgBqr+3hy1rIDm+TCAvEEoYJEZLG9954cATfbdvoD LAB05EWDUCJAk8EAAEIADkWIQSCdBjE9KxY53IwxHM0dh/4561D0gUCaq/t4RsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMiwyLDIACgkQNHYf+OetQ9KoWA//SFTlgv89y/aaUnJxTdL/Q8ObdI9TfbJ 87ngiOAQ32THMfIIp2Y2vxm/KlnyI4i0jG4YckgkN4e/s4qpZxRbH/1Ihfo5lqXDuzxHiua7tOO jnhYHY0lO0gEgiEa+NyDB9Y0CqH+0sCRxsXld9DFduJHMqOjCiiC58LtsrdC72HQQk68f0S/ZwB TrRxtcL99N9zbnGmS6mStAcSqLFXablM107M8rINoG6TSRL7ogO1IV7w0Rl6vuPbcM0yMLQTKYk tSwLaBrA5XVmuLtix4wfdl7tybWTF2UFvTGwTHu4VptWJYZ1UV7lhluXkZsGfT+7XFIzFR9Mht3 V3o0KLO2PCqAxlNzudrEanrYKfvGBnkV+Th0XqwVnQbNZH4qZ1qFscYmRkr7QcNEEF05aHdoMG9 /8ipwAFGUpE/dfK+oT1QQAli0T7Y+bnGXcw81EurvmUKbC+6fJInH0SmzpRR0rEa+zMkfXhm+Fl +0z5BifM0w7bPZzLla1T6yTfsQWMTjwd+bB8NXzIrLE1JpSFeZE90hbyhZWtrrNX7iX/Ve+L4ac YsbnVXQeL9XCEcwxLi3ueppnjAdGpMgeIpnGQG83gLJ9teyQq0jAJrfHAJ/4BHiNlyeZEEM458f O/2LOiVNZya2mJpYgzmr/NQpFU58k7xQnoG2bOSbxxQTrP68FWsA= X-Developer-Key: i=markus.probst@posteo.de; a=openpgp; fpr=827418C4F4AC58E77230C47334761FF8E7AD43D2 Autocrypt: addr=markus.probst@posteo.de; prefer-encrypt=mutual; keydata=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 aBeNN4ijKZchBXHPgVx+YtWRHfcm4l8= OpenPGP: url=https://posteo.de/keys/markus.probst@posteo.de.asc; preference=encrypt These functions will be used to simply the serdev rust abstraction. It also contributes to the fixing of 2 race conditions in the serdev rust abstraction. Signed-off-by: Markus Probst --- drivers/tty/serdev/core.c | 50 +++++++++++++++++++++++++++++++++= +++- drivers/tty/serdev/serdev-ttyport.c | 38 ++++++++++++++++++++++++++++ include/linux/serdev.h | 6 +++++ 3 files changed, 93 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index 7500efcdfc21..7d24f16710cb 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -187,6 +187,51 @@ void serdev_device_close(struct serdev_device *serdev) } EXPORT_SYMBOL_GPL(serdev_device_close); =20 +/** + * serdev_device_pause_rx() - pause data receive + * @serdev: serdev device + * + * Pause calls to receive_buf. + * + * The caller must guarantee that this does not run concurrently with + * `serdev_device_open` or `serdev_device_close`. + * + * Note that if a call to receive_buf is currently executed, the function = will + * sleep until it has finished. + */ +void serdev_device_pause_rx(struct serdev_device *serdev) +{ + struct serdev_controller *ctrl =3D serdev->ctrl; + + if (!ctrl || !ctrl->ops->pause_rx) + return; + + ctrl->ops->pause_rx(ctrl); +} +EXPORT_SYMBOL_GPL(serdev_device_pause_rx); + +/** + * serdev_device_resume_rx() - resume data receive + * @serdev: serdev device + * + * Resume calls to receive_buf. + * + * The caller must guarantee that this does not run concurrently with + * `serdev_device_open` or `serdev_device_close`. + * + * This can be called even if not paused to ensure data receive is active. + */ +void serdev_device_resume_rx(struct serdev_device *serdev) +{ + struct serdev_controller *ctrl =3D serdev->ctrl; + + if (!ctrl || !ctrl->ops->resume_rx) + return; + + ctrl->ops->resume_rx(ctrl); +} +EXPORT_SYMBOL_GPL(serdev_device_resume_rx); + static void devm_serdev_device_close(void *serdev) { serdev_device_close(serdev); @@ -398,6 +443,7 @@ EXPORT_SYMBOL_GPL(serdev_device_break_ctl); static int serdev_drv_probe(struct device *dev) { const struct serdev_device_driver *sdrv =3D to_serdev_device_driver(dev->= driver); + struct serdev_device *sdev =3D to_serdev_device(dev); int ret; =20 ret =3D dev_pm_domain_attach(dev, PD_FLAG_ATTACH_POWER_ON | @@ -405,7 +451,9 @@ static int serdev_drv_probe(struct device *dev) if (ret) return ret; =20 - return sdrv->probe(to_serdev_device(dev)); + serdev_device_resume_rx(sdev); + + return sdrv->probe(sdev); } =20 static void serdev_drv_remove(struct device *dev) diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serde= v-ttyport.c index bab1b143b8a6..e8aa89e733bd 100644 --- a/drivers/tty/serdev/serdev-ttyport.c +++ b/drivers/tty/serdev/serdev-ttyport.c @@ -7,8 +7,10 @@ #include #include #include +#include "../tty.h" =20 #define SERPORT_ACTIVE 1 +#define SERPORT_PAUSE_RX 2 =20 struct serport { struct tty_port *port; @@ -32,6 +34,14 @@ static size_t ttyport_receive_buf(struct tty_port *port,= const u8 *cp, if (!test_bit(SERPORT_ACTIVE, &serport->flags)) return 0; =20 + if (test_bit(SERPORT_PAUSE_RX, &serport->flags)) + return 0; + + /* + * Ensure writes by the driver are visible before allowing traffic to res= ume. + */ + smp_mb__after_atomic(); + ret =3D serdev_controller_receive_buf(ctrl, cp, count); =20 dev_WARN_ONCE(&ctrl->dev, ret > count, @@ -156,6 +166,32 @@ static void ttyport_close(struct serdev_controller *ct= rl) tty_release_struct(tty, serport->tty_idx); } =20 +static void ttyport_pause_rx(struct serdev_controller *ctrl) +{ + struct serport *serport =3D serdev_controller_get_drvdata(ctrl); + struct tty_struct *tty =3D serport->tty; + + set_bit(SERPORT_PAUSE_RX, &serport->flags); + + if (test_bit(SERPORT_ACTIVE, &serport->flags)) + tty_buffer_flush_work(tty->port); +} + +static void ttyport_resume_rx(struct serdev_controller *ctrl) +{ + struct serport *serport =3D serdev_controller_get_drvdata(ctrl); + struct tty_struct *tty =3D serport->tty; + + /* + * Ensure writes by the driver are visible before allowing traffic to res= ume. + */ + smp_mb__before_atomic(); + clear_bit(SERPORT_PAUSE_RX, &serport->flags); + + if (test_bit(SERPORT_ACTIVE, &serport->flags)) + tty_buffer_restart_work(tty->port); +} + static unsigned int ttyport_set_baudrate(struct serdev_controller *ctrl, u= nsigned int speed) { struct serport *serport =3D serdev_controller_get_drvdata(ctrl); @@ -260,6 +296,8 @@ static const struct serdev_controller_ops ctrl_ops =3D { .get_tiocm =3D ttyport_get_tiocm, .set_tiocm =3D ttyport_set_tiocm, .break_ctl =3D ttyport_break_ctl, + .pause_rx =3D ttyport_pause_rx, + .resume_rx =3D ttyport_resume_rx, }; =20 struct device *serdev_tty_port_register(struct tty_port *port, diff --git a/include/linux/serdev.h b/include/linux/serdev.h index b6c3d957ec15..5cf05df17ddf 100644 --- a/include/linux/serdev.h +++ b/include/linux/serdev.h @@ -89,6 +89,8 @@ struct serdev_controller_ops { int (*get_tiocm)(struct serdev_controller *); int (*set_tiocm)(struct serdev_controller *, unsigned int, unsigned int); int (*break_ctl)(struct serdev_controller *ctrl, unsigned int break_state= ); + void (*pause_rx)(struct serdev_controller *ctrl); + void (*resume_rx)(struct serdev_controller *ctrl); }; =20 /** @@ -194,6 +196,8 @@ static inline size_t serdev_controller_receive_buf(stru= ct serdev_controller *ctr int serdev_device_open(struct serdev_device *); void serdev_device_close(struct serdev_device *); int devm_serdev_device_open(struct device *, struct serdev_device *); +void serdev_device_pause_rx(struct serdev_device *serdev); +void serdev_device_resume_rx(struct serdev_device *serdev); unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned i= nt); void serdev_device_set_flow_control(struct serdev_device *, bool); int serdev_device_write_buf(struct serdev_device *, const u8 *, size_t); @@ -233,6 +237,8 @@ static inline int serdev_device_open(struct serdev_devi= ce *sdev) return -ENODEV; } static inline void serdev_device_close(struct serdev_device *sdev) {} +static inline void serdev_device_pause_rx(struct serdev_device *serdev) {} +static inline void serdev_device_resume_rx(struct serdev_device *serdev) {} static inline unsigned int serdev_device_set_baudrate(struct serdev_device= *sdev, unsigned int baudrate) { return 0; --=20 2.55.0 From nobody Thu Sep 24 21:19:00 2026 Received: from mout02.posteo.de (mout02.posteo.de [185.67.36.66]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CC3383C9893 for ; Sun, 20 Sep 2026 14:30:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.67.36.66 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789914614; cv=none; b=XDkApDp1kBjmc6Da5HpKn+xveYKx7bXi9/p6ti1Pbm7Y8F1qAe8gWADaUJjPQ5T+XB/6iDTi2nYSNmLfgy1FjwRdfcXMhk2INraEX/TjcZJDD5MnTIzlq1C11DxmugagcjdTRsKD8Qs4lPqDGMn+2Tujj50t2LpjSsJ7qmINRNY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789914614; c=relaxed/simple; bh=xmTFRFw7V/HU3JXIe69biF6uXSYP9tKIxk/FBu1sWo0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kv22A7OTVc2b1V7Ynmpix83L5QYkZ926SPOCDcGc1riq9usxXFJndlZ8ENlFsRsPx8Z8IOaGmsA99rDBOqB5icgXH2Vv2FBnIL73OAXlT4aDBPqNpTcLBnLjBclZNGTxtwOvh9fgayo+n4VIVgVerYPV0n4WZ93SGqBXgeWNm8k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=posteo.de; spf=pass smtp.mailfrom=posteo.de; dkim=pass (2048-bit key) header.d=posteo.de header.i=@posteo.de header.b=mupY/qTf; arc=none smtp.client-ip=185.67.36.66 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=posteo.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=posteo.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=posteo.de header.i=@posteo.de header.b="mupY/qTf" Received: from submission (posteo.de [185.67.36.169]) by mout02.posteo.de (Postfix) with ESMTPS id E0951240108 for ; Sun, 20 Sep 2026 16:30:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=posteo.de; s=1984.8680eb; t=1789914601; bh=UTm4yQVbwMpMizb1S87Kb2YZ7hCkc36LgIfvhH/1KKk=; h=From:Date:Subject:MIME-Version:Content-Type: Content-Transfer-Encoding:Message-Id:To:Cc:Autocrypt:OpenPGP:From; b=mupY/qTf3Ksh8UBh7StrsKqT0NUoZ+PQO6O2O+xCg66yRfGKDLaGRs/UmzCsxVeFF BF6igW3w2rOOy6j9v25Q18ajKBog/nW/BRVArkwGk0mz7xNqllMli+ALWSVYat/kva ITCSGTvNqoi3SjRdIEC4T0OQiNaFSlEUC3L6Ewoi1FEclBP3HBDb5ueAfSglIb2yqY mxNgoqB4F79ElN/isUBZ/9fNP9ehl29zZ3FixYZ3roBGg0UkXI2Ax0VkWkBLy84FyP DQSouiKGnfewli8a+qGrxyeMpahbRorU/K8AMJuqchJjkHN50o5E0iNxRw0mmst7ap z5tvfFYSaS+YA== Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4hnpfZ4dVpz9rxD; Sun, 20 Sep 2026 16:29:58 +0200 (CEST) From: Markus Probst Date: Sun, 20 Sep 2026 14:30:00 +0000 Subject: [PATCH v2 2/3] rust: serdev: Replace `active` mutex with receive pause 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: <20260920-rust_serdev_probe_refactor-v2-2-43b855162f5d@posteo.de> References: <20260920-rust_serdev_probe_refactor-v2-0-43b855162f5d@posteo.de> In-Reply-To: <20260920-rust_serdev_probe_refactor-v2-0-43b855162f5d@posteo.de> To: Ayush Singh , Johan Hovold , Alex Elder , Greg Kroah-Hartman , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , Eric Biggers , Ard Biesheuvel , Lorenzo Stoakes , Vlastimil Babka , "Liam R. Howlett" , Uladzislau Rezki , Jiri Slaby , "Rafael J. Wysocki" Cc: greybus-dev@lists.linaro.org, linux-serial@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, driver-core@lists.linux.dev, Markus Probst , Sashiko Bot X-Developer-Signature: v=1; a=openpgp-sha256; l=6499; i=markus.probst@posteo.de; h=from:subject:message-id; bh=xmTFRFw7V/HU3JXIe69biF6uXSYP9tKIxk/FBu1sWo0=; b=owEBiQJ2/ZANAwAIATR2H/jnrUPSAcsmYgBqr+3hdAQL5ne9/6sq8Hf8jnAp1RJtJDa83lLjy Dmj0q73lkiJAk8EAAEIADkWIQSCdBjE9KxY53IwxHM0dh/4561D0gUCaq/t4RsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMiwyLDIACgkQNHYf+OetQ9Lvbw//RsIfTq/cUbCp3WvwHgwjuE9TRVG+waI FF3hpNhlQ7RQZepyQUz79EkFTPhIUrcTXyeIBSZ7M/QlBGsDB61aaQPoBR81RnOqNfGYF6BF1Yk 1JHG7DLWtBM4qC4jvAJPRxATHKoEA1Y2R8Rsvc4zG+BsAjiI2dWlw2R80b/vQyu+rJFsmF/FwnR 4jUFweDIdZVslWeLNgXKqVw2PEuJRWXOf/T4KNndwOVoxvtgd6YdbvpYwlghZunD1MeElWrVQTX jzPhHRTYD6zzqnmiscDe05eEDZd+eXLFf08uIBLyiwzo6v2jsEwmoVRjdoJo7J+Ojdd2mzDDhQi 4sOcDXKHCLm2TaS0RJI7gLerOeWzHII4ocf8nfQEFaF2sOts1HiPSfMnF/+j4ZKF5TUUH/1BZ4x zyn2yeN+F0GcsJlK4hSeOXeob3XW0pZWM5WCGV6Tw1aKs/Lddln3iqgtYcCV7DXAFf8u4S9ao0I A4EIxHtgogqLTDxWYrgR/U0udEhw0ydcuG70gzUF7giPCNcOAl5ldtojzF/D2BR77ZABKtGM0kb tX/GXuA8WFqpGiA+Cob7tCxL7ADweXLk0sXEbEwXzszlhRTqNeuJ46yM3TvT3otXASoXZfBuFRZ gz3Gg/c47OGlBVIdaZmthrDf/vEhwItGWdfjWtLOTgOtbhLZeZvE= X-Developer-Key: i=markus.probst@posteo.de; a=openpgp; fpr=827418C4F4AC58E77230C47334761FF8E7AD43D2 Autocrypt: addr=markus.probst@posteo.de; prefer-encrypt=mutual; keydata=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 aBeNN4ijKZchBXHPgVx+YtWRHfcm4l8= OpenPGP: url=https://posteo.de/keys/markus.probst@posteo.de.asc; preference=encrypt There are currently 2 race conditions: - in probe if `Driver::probe` returns Err - in unbind . In those cases the driver data will be set to NULL before the serdev device was closed. If data is received while the driver data is dropped, the `receive_buf_callback` might try to access the `active` mutex on a null pointer. Removing the need for `receive_buf_callback` to lock the `active` mutex fixes these. Fixes: 99f59aa82341 ("rust: add basic serial device bus abstractions") Reported-by: Sashiko Bot Closes: https://lore.kernel.org/linux-serial/20260905000836.C8FC91F00A3D@sm= tp.kernel.org/ Closes: https://lore.kernel.org/linux-serial/20260903222159.70A911F000E9@sm= tp.kernel.org/ Signed-off-by: Markus Probst --- rust/kernel/serdev.rs | 60 ++++++++++++-----------------------------------= ---- 1 file changed, 14 insertions(+), 46 deletions(-) diff --git a/rust/kernel/serdev.rs b/rust/kernel/serdev.rs index 17ca504b7f8d..c16d6593a8d2 100644 --- a/rust/kernel/serdev.rs +++ b/rust/kernel/serdev.rs @@ -13,13 +13,9 @@ to_result, VTABLE_DEFAULT_ERROR, // }, - new_mutex, of, prelude::*, - sync::{ - aref::AlwaysRefCounted, - Mutex, // - }, + sync::aref::AlwaysRefCounted, time::Jiffies, types::{ Opaque, @@ -103,40 +99,11 @@ pub struct PrivateData<'bound, T: Driver> { #[pin] driver: UnsafeCell>>, open: UnsafeCell, - /// Whether `receive_buf_callback` is allowed to call `Driver::receive= `. - /// - /// If locked, the receive_buf_callback will be blocked on data recept= ion. - /// This is the case while the driver is being probed or while [`Priva= teData`] is being dropped. - /// This is necessary, because we need to open the serdev device befor= e the driver has been - /// probed in order to allow it to be configured, which allows `receiv= e_buf_callback` to be - /// called. Thus we need to block data until probe completes and the d= river data becomes - /// initialized. - /// - /// If unlocked and true, the receive_buf_callback will forward the da= ta to - /// `Driver::receive`. This is the normal state of operation. - /// - /// If unlocked and false, the receive_buf_callback will throw away th= e data. - /// This is only the case, if the serdev device is open and - /// - the driver returned an error in probe - /// or - /// - the driver data already has been dropped, because it was unbound. - #[pin] - active: Mutex, } =20 #[pinned_drop] impl PinnedDrop for PrivateData<'_, T> { fn drop(self: Pin<&mut Self>) { - let mut active =3D self.active.lock(); - if *active { - // SAFETY: - // - We have exclusive access to `self.driver`. - // - `self.driver` is guaranteed to be initialized. - unsafe { (*self.driver.get()).assume_init_drop() }; - *active =3D false; - } - drop(active); - // SAFETY: We have exclusive access to `self.open`. if unsafe { *self.open.get() } { // SAFETY: `self.sdev.as_raw()` is guaranteed to be a pointer = to a valid @@ -170,7 +137,6 @@ extern "C" fn probe_callback(sdev: *mut bindings::serde= v_device) -> kernel::ffi: sdev: &**sdev, driver: MaybeUninit::>::zeroed().into(), open: false.into(), - active <- new_mutex!(false), }))?; // SAFETY: We just set drvdata to `PrivateData<'_, T>`. let private_data =3D unsafe { sdev.as_ref().drvdata_borrow::>() }; @@ -178,11 +144,12 @@ extern "C" fn probe_callback(sdev: *mut bindings::ser= dev_device) -> kernel::ffi: // SAFETY: We just set drvdata to `PrivateData<'_, T>`. drop(unsafe { sdev.as_ref().drvdata_obtain::>() }); }); - let mut active =3D private_data.active.lock(); - // SAFETY: `sdev.as_raw()` is guaranteed to be a valid pointer= to `serdev_device`. unsafe { bindings::serdev_device_set_client_ops(sdev.as_raw(),= Self::OPS) }; =20 + // SAFETY: `sdev.as_raw()` is guaranteed to be a valid pointer= to `serdev_device`. + unsafe { bindings::serdev_device_pause_rx(sdev.as_raw()) }; + // SAFETY: The serial device bus only ever calls the probe cal= lback with a valid pointer // to a `serdev_device`. to_result(unsafe { bindings::serdev_device_open(sdev.as_raw())= })?; @@ -199,12 +166,12 @@ extern "C" fn probe_callback(sdev: *mut bindings::ser= dev_device) -> kernel::ffi: // - `private_data.driver` is pinned. let result =3D unsafe { pin_init::raw_try_init(driver.as_mut_p= tr(), data) }; =20 - *active =3D result.is_ok(); - - drop(active); - result.map(|()| { private_data.dismiss(); + + // SAFETY: `sdev.as_raw()` is guaranteed to be a valid poi= nter to `serdev_device`. + unsafe { bindings::serdev_device_resume_rx(sdev.as_raw()) = }; + 0 }) }) @@ -231,6 +198,12 @@ extern "C" fn remove_callback(sdev: *mut bindings::ser= dev_device) { let data_pinned =3D unsafe { Pin::new_unchecked(data.assume_init_r= ef()) }; =20 T::unbind(sdev, data_pinned); + + // SAFETY: `sdev.as_raw()` is guaranteed to be a valid pointer to = `serdev_device`. + unsafe { bindings::serdev_device_pause_rx(sdev.as_raw()) }; + + // SAFETY: We already established that `data` is guaranteed to be = initialized. + unsafe { data.assume_init_drop() }; } =20 extern "C" fn receive_buf_callback( @@ -248,11 +221,6 @@ extern "C" fn receive_buf_callback( // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called // and stored a `Pin>>`. let private_data =3D unsafe { sdev.as_ref().drvdata_borrow::>() }; - let active =3D private_data.active.lock(); - - if !*active { - return length; - } =20 // SAFETY: No one has exclusive access to `private_data.driver`. let data =3D unsafe { &*private_data.driver.get() }; --=20 2.55.0 From nobody Thu Sep 24 21:19:00 2026 Received: from mout02.posteo.de (mout02.posteo.de [185.67.36.66]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 63E873E40E5 for ; Sun, 20 Sep 2026 14:30:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.67.36.66 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789914621; cv=none; b=uXaPUggS6lPTS+SZ+TfyAVPv8zuo/UmCxJO5zDTCqYB6eJmzRQzvOdlpQ7Q2ubZe26QNphyU5OQbw3P7AUlDQ8VzNtEXD/aeCBMMMCxFkeaGTgeeDVy/nq3jJaOMkkBMU5PPxq7u4NRUAPQaGZpspv5EZHpOHfV/bWg5/s74l6o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789914621; c=relaxed/simple; bh=WQslHMs2svOlSFQafK7q53v+0G7DlzBK6lZSGEX3Nu4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bjYG/SBgE5oRUDXA4OipRD1CQUWlcmZ8wSUCHEmzMFK5uuxbkVGsYXfigsOt9sQRmPq+kIHd8bJOUYyiQjsbx6y+X+XbmgxnhFkp2Gmwj6pQxPQDtfwOrelWrFgRi2lu2vGWnvPSDczGTmLtnlEiMCWwdhePXqPu29htoetnOrI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=posteo.de; spf=pass smtp.mailfrom=posteo.de; dkim=pass (2048-bit key) header.d=posteo.de header.i=@posteo.de header.b=ksLpQgFD; arc=none smtp.client-ip=185.67.36.66 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=posteo.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=posteo.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=posteo.de header.i=@posteo.de header.b="ksLpQgFD" Received: from submission (posteo.de [185.67.36.169]) by mout02.posteo.de (Postfix) with ESMTPS id 3D2E4240105 for ; Sun, 20 Sep 2026 16:30:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=posteo.de; s=1984.8680eb; t=1789914604; bh=v2EF/fsRX2gtP/07bUp+y+QrpNj7xZBjUZMkm63RIN4=; h=From:Date:Subject:MIME-Version:Content-Type: Content-Transfer-Encoding:Message-Id:To:Cc:Autocrypt:OpenPGP:From; b=ksLpQgFDxFyxH1OSgbqyhzGsrQKvDGYkkmqrnXRV3fkdR91lfgKfasIw+d2sMEx0W VRvUGVYyh9CQ9oygt4bTfVg8mboizrT0wl+EBeb8AprrtBrE/IISkndwW9STznfYs5 P5dwctQFX7LEnOAV42pLznTBbBD+8aky6NuAjmOjqYSl529fJCaH0m0NKN4zt2ag7+ z21uSr4OSaJIqkvKeMMRpYrRfwxdhCx3/iPP1myXOxKWorgp292QRsjahL1v1bLKVA anPrRpYXBgMgwXmaTycTbG8ThWjLymVS+gQgIFgkMGpGeavZRTxa5l3oTyK5F8cGyf 872LTqyo4MfWw== Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4hnpfc3gzqz9rxK; Sun, 20 Sep 2026 16:30:00 +0200 (CEST) From: Markus Probst Date: Sun, 20 Sep 2026 14:30:02 +0000 Subject: [PATCH v2 3/3] rust: serdev: Simplify callbacks 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: <20260920-rust_serdev_probe_refactor-v2-3-43b855162f5d@posteo.de> References: <20260920-rust_serdev_probe_refactor-v2-0-43b855162f5d@posteo.de> In-Reply-To: <20260920-rust_serdev_probe_refactor-v2-0-43b855162f5d@posteo.de> To: Ayush Singh , Johan Hovold , Alex Elder , Greg Kroah-Hartman , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , Eric Biggers , Ard Biesheuvel , Lorenzo Stoakes , Vlastimil Babka , "Liam R. Howlett" , Uladzislau Rezki , Jiri Slaby , "Rafael J. Wysocki" Cc: greybus-dev@lists.linaro.org, linux-serial@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, driver-core@lists.linux.dev, Markus Probst X-Developer-Signature: v=1; a=openpgp-sha256; l=8348; i=markus.probst@posteo.de; h=from:subject:message-id; bh=WQslHMs2svOlSFQafK7q53v+0G7DlzBK6lZSGEX3Nu4=; b=owEBiQJ2/ZANAwAIATR2H/jnrUPSAcsmYgBqr+3hXnkwSElbMhKBY/wt8YrQadUQeSi6NeGQh zRgtKx5mHWJAk8EAAEIADkWIQSCdBjE9KxY53IwxHM0dh/4561D0gUCaq/t4RsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMiwyLDIACgkQNHYf+OetQ9KEFxAAhIKOPibUkb71SAF587krLQ5cMwqa6Si 80t2thOKksTx98YJluDMqUQaks6ukr2ZHSHQyjv6bNmma/Z2wQmPimnimPmtvPCiNqZGamsloOF GZpXjx0JW8uAkO2S2E5Ps5uAZpMbB2Q+WGIEsTGcAriRk6n893wDn7LDlDZhmf4bh4SDoBekeCk /78yczYSBCV5klu5BffDVl0wd4FqI5arN7j3GXiRVf/0Z92ivtzreNmgYG1R3FcPkLyMFP9XeuO AMGe/eRYtWgdTQ5zhbqjs4w+1nN8UfVvqWVJzkt8uzoKG+C5N4q+NpGLxdI5+l3iqfWs2cKvGLm W2SPGdrc9vety62MLMaCxerGGEnTXYNa3wUb6VzVQd9MrKUoWn9IHTZfN/v2mP03GvjzFCzbsmq O8oACs9zorM7DTwVjGxQOEQc/w6hefzwJxzAEIs1C8QN6u5tOVfdeZMv31qh0JlOK4RNHZL1RJ2 DxI2M2w8ZO1IcSSkb1TSsgyK5NzAgZ9JRISw8AJ3GKea3x6tFKCwSquGyYs+w5qvx5dewIEnNRd kCrnj3mQPX3U1hxhvhRbQQGCEaG8z2s9fl7zOJb4b4j/VRXGvNaIJPhlFl1ChM8AJDn9TmpGeJZ JwuocnCA1ILoWh+F6QwTC5Aru1lpr4teIHKz92q0DD7qfUsozqNE= X-Developer-Key: i=markus.probst@posteo.de; a=openpgp; fpr=827418C4F4AC58E77230C47334761FF8E7AD43D2 Autocrypt: addr=markus.probst@posteo.de; prefer-encrypt=mutual; keydata=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 aBeNN4ijKZchBXHPgVx+YtWRHfcm4l8= OpenPGP: url=https://posteo.de/keys/markus.probst@posteo.de.asc; preference=encrypt Initialize the driver's private data directly on `PrivateData`. Introduce `OpenGuard` for resource cleanup. Signed-off-by: Markus Probst --- rust/kernel/serdev.rs | 131 ++++++++++++++++++++--------------------------= ---- 1 file changed, 52 insertions(+), 79 deletions(-) diff --git a/rust/kernel/serdev.rs b/rust/kernel/serdev.rs index c16d6593a8d2..3f9165e16776 100644 --- a/rust/kernel/serdev.rs +++ b/rust/kernel/serdev.rs @@ -17,16 +17,12 @@ prelude::*, sync::aref::AlwaysRefCounted, time::Jiffies, - types::{ - Opaque, - ScopeGuard, // - }, // + types::Opaque, // }; =20 use core::{ - cell::UnsafeCell, marker::PhantomData, - mem::{offset_of, MaybeUninit}, + mem::offset_of, ptr::NonNull, // }; =20 @@ -92,24 +88,36 @@ unsafe fn unregister(sdrv: &Opaque) { } } =20 +struct OpenGuard<'bound> { + sdev: &'bound Device, +} + +impl Drop for OpenGuard<'_> { + fn drop(&mut self) { + // SAFETY: + // - `self.sdev.as_raw()` is guaranteed to be a pointer to a valid + // `struct serdev_device`. + // - The existence of self proves that the device is open. + unsafe { bindings::serdev_device_close(self.sdev.as_raw()) }; + } +} + #[doc(hidden)] -#[pin_data(PinnedDrop)] +#[pin_data] pub struct PrivateData<'bound, T: Driver> { - sdev: &'bound Device, #[pin] - driver: UnsafeCell>>, - open: UnsafeCell, + driver: T::Data<'bound>, + open: OpenGuard<'bound>, } =20 -#[pinned_drop] -impl PinnedDrop for PrivateData<'_, T> { - fn drop(self: Pin<&mut Self>) { - // SAFETY: We have exclusive access to `self.open`. - if unsafe { *self.open.get() } { - // SAFETY: `self.sdev.as_raw()` is guaranteed to be a pointer = to a valid - // `struct serdev_device`. - unsafe { bindings::serdev_device_close(self.sdev.as_raw()) }; - } +impl<'bound, T: Driver> PrivateData<'bound, T> { + #[inline] + fn driver_data(self: Pin<&Self>) -> Pin<&T::Data<'bound>> { + // SAFETY: We treat the result as pinned. + let inner =3D unsafe { Pin::into_inner_unchecked(self) }; + + // SAFETY: `self.driver` is pinned. + unsafe { Pin::new_unchecked(&inner.driver) } } } =20 @@ -134,46 +142,30 @@ extern "C" fn probe_callback(sdev: *mut bindings::ser= dev_device) -> kernel::ffi: =20 from_result(|| { sdev.as_ref().set_drvdata(try_pin_init!(PrivateData:: { - sdev: &**sdev, - driver: MaybeUninit::>::zeroed().into(), - open: false.into(), + open: { + // SAFETY: + // - `sdev.as_raw()` is guaranteed to be a valid point= er to + // `serdev_device`. + // - It is safe to call before open. + unsafe { bindings::serdev_device_set_client_ops(sdev.a= s_raw(), Self::OPS) }; + + // SAFETY: `sdev.as_raw()` is guaranteed to be a valid= pointer to + // `serdev_device`. + unsafe { bindings::serdev_device_pause_rx(sdev.as_raw(= )) }; + + // SAFETY: `sdev.as_raw()` is guaranteed to be a valid= pointer to + // `serdev_device`. + to_result(unsafe { bindings::serdev_device_open(sdev.a= s_raw()) })?; + + OpenGuard { sdev } + }, + driver <- T::probe(sdev, info), }))?; - // SAFETY: We just set drvdata to `PrivateData<'_, T>`. - let private_data =3D unsafe { sdev.as_ref().drvdata_borrow::>() }; - let private_data =3D ScopeGuard::new_with_data(private_data, |= _| { - // SAFETY: We just set drvdata to `PrivateData<'_, T>`. - drop(unsafe { sdev.as_ref().drvdata_obtain::>() }); - }); - // SAFETY: `sdev.as_raw()` is guaranteed to be a valid pointer= to `serdev_device`. - unsafe { bindings::serdev_device_set_client_ops(sdev.as_raw(),= Self::OPS) }; =20 // SAFETY: `sdev.as_raw()` is guaranteed to be a valid pointer= to `serdev_device`. - unsafe { bindings::serdev_device_pause_rx(sdev.as_raw()) }; - - // SAFETY: The serial device bus only ever calls the probe cal= lback with a valid pointer - // to a `serdev_device`. - to_result(unsafe { bindings::serdev_device_open(sdev.as_raw())= })?; - - // SAFETY: We have exclusive access to `private_data.open`. - unsafe { *private_data.open.get() =3D true }; - - let data =3D T::probe(sdev, info); + unsafe { bindings::serdev_device_resume_rx(sdev.as_raw()) }; =20 - // SAFETY: We have exclusive access to `private_data.driver`. - let driver =3D unsafe { &mut *private_data.driver.get() }; - // SAFETY: - // - `driver.as_mut_ptr()` is a valid pointer to uninitialized= data. - // - `private_data.driver` is pinned. - let result =3D unsafe { pin_init::raw_try_init(driver.as_mut_p= tr(), data) }; - - result.map(|()| { - private_data.dismiss(); - - // SAFETY: `sdev.as_raw()` is guaranteed to be a valid poi= nter to `serdev_device`. - unsafe { bindings::serdev_device_resume_rx(sdev.as_raw()) = }; - - 0 - }) + Ok(0) }) } =20 @@ -189,21 +181,10 @@ extern "C" fn remove_callback(sdev: *mut bindings::se= rdev_device) { // and stored a `Pin>>`. let private_data =3D unsafe { sdev.as_ref().drvdata_borrow::>() }; =20 - // SAFETY: No one has exclusive access to `private_data.driver`. - let data =3D unsafe { &*private_data.driver.get() }; - // SAFETY: - // - `private_data.driver` is pinned. - // - `remove_callback` is only ever called after a successful call= to `probe_callback`, - // hence it's guaranteed that `private_data.driver` was initiali= zed. - let data_pinned =3D unsafe { Pin::new_unchecked(data.assume_init_r= ef()) }; - - T::unbind(sdev, data_pinned); + T::unbind(sdev, private_data.driver_data()); =20 // SAFETY: `sdev.as_raw()` is guaranteed to be a valid pointer to = `serdev_device`. unsafe { bindings::serdev_device_pause_rx(sdev.as_raw()) }; - - // SAFETY: We already established that `data` is guaranteed to be = initialized. - unsafe { data.assume_init_drop() }; } =20 extern "C" fn receive_buf_callback( @@ -211,6 +192,9 @@ extern "C" fn receive_buf_callback( buf: *const u8, length: usize, ) -> usize { + // SAFETY: `buf` is guaranteed to be non-null and has the size of = `length`. + let buf =3D unsafe { core::slice::from_raw_parts(buf, length) }; + // SAFETY: The serial device bus only ever calls the receive buf c= allback with a valid // pointer to a `struct serdev_device`. // @@ -222,18 +206,7 @@ extern "C" fn receive_buf_callback( // and stored a `Pin>>`. let private_data =3D unsafe { sdev.as_ref().drvdata_borrow::>() }; =20 - // SAFETY: No one has exclusive access to `private_data.driver`. - let data =3D unsafe { &*private_data.driver.get() }; - // SAFETY: - // - `private_data.driver` is pinned. - // - `receive_buf_callback` is only ever called after a successful= call to `probe_callback`, - // hence it's guaranteed that `private_data.driver` was initiali= zed. - let data_pinned =3D unsafe { Pin::new_unchecked(data.assume_init_r= ef()) }; - - // SAFETY: `buf` is guaranteed to be non-null and has the size of = `length`. - let buf =3D unsafe { core::slice::from_raw_parts(buf, length) }; - - T::receive(sdev, data_pinned, buf) + T::receive(sdev, private_data.driver_data(), buf) } } =20 --=20 2.55.0