]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
usb: cdc-acm: return correct error code on unsupported break
authorOliver Neukum <oneukum@suse.com>
Thu, 7 Dec 2023 13:26:30 +0000 (14:26 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Jan 2024 22:52:52 +0000 (14:52 -0800)
[ Upstream commit 66aad7d8d3ec5a3a8ec2023841bcec2ded5f65c9 ]

In ACM support for sending breaks to devices is optional.
If a device says that it doenot support sending breaks,
the host must respect that.
Given the number of optional features providing tty operations
for each combination is not practical and errors need to be
returned dynamically if unsupported features are requested.

In case a device does not support break, we want the tty layer
to treat that like it treats drivers that statically cannot
support sending a break. It ignores the inability and does nothing.
This patch uses EOPNOTSUPP to indicate that.

Signed-off-by: Oliver Neukum <oneukum@suse.com>
Fixes: 9e98966c7bb94 ("tty: rework break handling")
Link: https://lore.kernel.org/r/20231207132639.18250-1-oneukum@suse.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/tty/tty_io.c
drivers/usb/class/cdc-acm.c

index 82b49aa0f9de94b82f6e57e94bf5538e3fb9a54d..d5191065b6e911dc4cec5f166338e0898e3a1bb0 100644 (file)
@@ -2514,6 +2514,9 @@ static int send_break(struct tty_struct *tty, unsigned int duration)
        if (!retval) {
                msleep_interruptible(duration);
                retval = tty->ops->break_ctl(tty, 0);
+       } else if (retval == -EOPNOTSUPP) {
+               /* some drivers can tell only dynamically */
+               retval = 0;
        }
        tty_write_unlock(tty);
 
index adc154b691d05149024f0e4ab94833abe0390221..f21fd809e44ffd4816022b2a536a822e1b936830 100644 (file)
@@ -896,6 +896,9 @@ static int acm_tty_break_ctl(struct tty_struct *tty, int state)
        struct acm *acm = tty->driver_data;
        int retval;
 
+       if (!(acm->ctrl_caps & USB_CDC_CAP_BRK))
+               return -EOPNOTSUPP;
+
        retval = acm_send_break(acm, state ? 0xffff : 0);
        if (retval < 0)
                dev_dbg(&acm->control->dev,