From: chitranshmandhaniya@gmail.com
To: hansg@kernel.org, ilpo.jarvinen@linux.intel.com
Cc: platform-driver-x86@vger.kernel.org,
linux-kernel@vger.kernel.org, Chitransh_Mandhaniya@dell.com
Subject: [PATCH v3 2/2] platform/x86: dell-uart-backlight: recover from stray
Date: Fri, 16 Oct 2026 15:03:02 +0530 [thread overview]
Message-ID: <20261016093302.55528-3-chitranshmandhaniya@gmail.com> (raw)
In-Reply-To: <20261016093302.55528-1-chitranshmandhaniya@gmail.com>
From: Chitransh Mandhaniya <Chitransh_Mandhaniya@dell.com>
On some Dell AIO machines the EC occasionally inserts a spurious byte
after the cmd-echo in UART backlight response frames. A get-brightness
reply "04 0c 0a e5" arrives as "04 0c 0d 0a e5". The length field still
reflects the original frame size, so the parser consumes the stray byte
as payload and mistakes the real payload for the checksum, returning
-EIO.
On the first checksum failure for a fully received frame, drop the byte
at the first payload offset, shift the remaining data down by one, and
call dell_uart_bl_receive_data() again to re-fetch the checksum byte
from the wire. Track total consumed bytes so the exact count is
returned to serdev.
The resync is guarded by resp_idx == resp_len to ensure a complete frame
was received, preventing memmove on a truncated or out-of-range length
field.
Limit this single-byte resync to once per command via a resync_used flag
cleared at the start of each transaction. A second mismatch is still a
hard error. Well-formed replies never enter the recovery path.
While at it, switch mutex_init() to devm_mutex_init() so the mutex is
automatically destroyed via devres, fixing a missing mutex_destroy()
on the teardown path.
Tested on Dell OptiPlex AIO 7410 65W (0TKWC4) where the EC inserts a
stray byte on every get-brightness response -- resync fixes it
transparently.
Suggested-by: ilpo.jarvinen@linux.intel.com
Signed-off-by: Chitransh Mandhaniya <Chitransh_Mandhaniya@dell.com>
---
.../platform/x86/dell/dell-uart-backlight.c | 35 ++++++++++++++++---
1 file changed, 31 insertions(+), 4 deletions(-)
diff --git a/drivers/platform/x86/dell/dell-uart-backlight.c b/drivers/platform/x86/dell/dell-uart-backlight.c
index af9c5f9a566f..b0df479a4658 100644
--- a/drivers/platform/x86/dell/dell-uart-backlight.c
+++ b/drivers/platform/x86/dell/dell-uart-backlight.c
@@ -60,6 +60,7 @@ struct dell_uart_backlight {
u8 resp_len;
u8 resp_max_len;
u8 pending_cmd;
+ bool resync_used;
int status;
int power;
};
@@ -91,6 +92,7 @@ static int dell_uart_bl_command(struct dell_uart_backlight *dell_bl,
dell_bl->resp_len = -1; /* Invalid / unset */
dell_bl->resp_max_len = resp_max_len;
dell_bl->pending_cmd = cmd[1];
+ dell_bl->resync_used = false;
/* The TTY buffer should be big enough to take the entire cmd in one go */
ret = serdev_device_write_buf(to_serdev_device(dell_bl->dev), cmd, cmd_len);
@@ -256,7 +258,7 @@ static size_t dell_uart_bl_receive_data(struct dell_uart_backlight *dell_bl,
static size_t dell_uart_bl_receive(struct serdev_device *serdev, const u8 *data, size_t len)
{
struct dell_uart_backlight *dell_bl = serdev_device_get_drvdata(serdev);
- size_t ret;
+ size_t consumed;
dev_dbg(dell_bl->dev, "Recv: %*ph\n", (int)len, data);
@@ -266,12 +268,35 @@ static size_t dell_uart_bl_receive(struct serdev_device *serdev, const u8 *data,
return len;
}
- ret = dell_uart_bl_receive_data(dell_bl, data, len);
+ consumed = dell_uart_bl_receive_data(dell_bl, data, len);
if (dell_bl->status == -EBUSY)
return len; /* Response not complete yet */
+ /*
+ * Stray byte after cmd-echo? Drop it, shift data down, re-fetch
+ * checksum. Only attempt when a full frame was received (resp_idx ==
+ * resp_len) to avoid acting on a truncated length field.
+ */
+ if (dell_bl->status == -EIO && !dell_bl->resync_used &&
+ dell_bl->resp_idx == dell_bl->resp_len &&
+ dell_bl->resp_len > MIN_RESP_LEN) {
+ dell_bl->resync_used = true;
+ dell_bl->status = -EBUSY;
+
+ dev_dbg(dell_bl->dev, "Resync: dropping stray byte 0x%02x at offset %d\n",
+ dell_bl->resp[RESP_DATA], RESP_DATA);
+
+ memmove(&dell_bl->resp[RESP_DATA], &dell_bl->resp[RESP_DATA + 1],
+ dell_bl->resp_len - RESP_DATA - 1);
+ dell_bl->resp_idx = dell_bl->resp_len - 1;
+
+ consumed += dell_uart_bl_receive_data(dell_bl, data + consumed, len - consumed);
+ if (dell_bl->status == -EBUSY)
+ return len; /* Need more data for checksum byte */
+ }
+
wake_up(&dell_bl->wait_queue);
- return ret;
+ return consumed;
}
static const struct serdev_device_ops dell_uart_bl_serdev_ops = {
@@ -291,7 +316,9 @@ static int dell_uart_bl_serdev_probe(struct serdev_device *serdev)
if (!dell_bl)
return -ENOMEM;
- mutex_init(&dell_bl->mutex);
+ ret = devm_mutex_init(dev, &dell_bl->mutex);
+ if (ret)
+ return ret;
init_waitqueue_head(&dell_bl->wait_queue);
dell_bl->dev = dev;
--
2.43.0
next prev parent reply other threads:[~2026-10-16 9:33 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-04 11:03 [PATCH] platform/x86: dell-uart-backlight: recover from stray EC response byte chitranshmandhaniya
2026-10-14 11:50 ` Ilpo Järvinen
2026-10-15 7:43 ` [PATCH v2 0/2] " chitranshmandhaniya
2026-10-15 7:43 ` [PATCH v2 1/2] platform/x86: dell-uart-backlight: extract dell_uart_bl_receive_data() helper chitranshmandhaniya
2026-10-15 7:43 ` [PATCH v2 2/2] platform/x86: dell-uart-backlight: recover from stray EC response byte chitranshmandhaniya
2026-10-15 10:12 ` Ilpo Järvinen
2026-10-15 10:24 ` Ilpo Järvinen
2026-10-16 9:33 ` [PATCH v3 0/2] platform/x86: dell-uart-backlight: stray byte recovery and cleanup chitranshmandhaniya
2026-10-16 9:33 ` [PATCH v3 1/2] platform/x86: dell-uart-backlight: extract chitranshmandhaniya
2026-10-16 9:33 ` chitranshmandhaniya [this message]
2026-10-16 10:07 ` [PATCH v3 2/2] platform/x86: dell-uart-backlight: recover from stray Ilpo Järvinen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261016093302.55528-3-chitranshmandhaniya@gmail.com \
--to=chitranshmandhaniya@gmail.com \
--cc=Chitransh_Mandhaniya@dell.com \
--cc=hansg@kernel.org \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=platform-driver-x86@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®