From: Johan Hovold <johan@kernel.org>
To: Johan Hovold <johan@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 07/11] USB: serial: digi_acceleport: stop OOB I/O when not in use
Date: Wed, 10 Jun 2026 15:22:28 +0200 [thread overview]
Message-ID: <20260610132232.356139-8-johan@kernel.org> (raw)
In-Reply-To: <20260610132232.356139-1-johan@kernel.org>
The driver submits the OOB read URB on first open of a port and does not
stop it until the device is disconnected.
Add an open counter and submit the URB on first open and stop it on last
close to avoid wasting resources (e.g. power) when the device is not in
use.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/digi_acceleport.c | 100 ++++++++++++++-------------
1 file changed, 51 insertions(+), 49 deletions(-)
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index e14cf133808f..efa853a57bb2 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -176,10 +176,10 @@
/* Structures */
struct digi_serial {
- spinlock_t ds_serial_lock;
+ struct mutex open_mutex;
struct usb_serial_port *ds_oob_port; /* out-of-band port */
int ds_oob_port_num; /* index of out-of-band port */
- int ds_device_started;
+ int open_count;
};
struct digi_port {
@@ -226,9 +226,7 @@ static unsigned int digi_chars_in_buffer(struct tty_struct *tty);
static int digi_open(struct tty_struct *tty, struct usb_serial_port *port);
static void digi_close(struct usb_serial_port *port);
static void digi_dtr_rts(struct usb_serial_port *port, int on);
-static int digi_startup_device(struct usb_serial *serial);
static int digi_startup(struct usb_serial *serial);
-static void digi_disconnect(struct usb_serial *serial);
static void digi_release(struct usb_serial *serial);
static int digi_port_probe(struct usb_serial_port *port);
static void digi_port_remove(struct usb_serial_port *port);
@@ -281,7 +279,6 @@ static struct usb_serial_driver digi_acceleport_2_device = {
.tiocmget = digi_tiocmget,
.tiocmset = digi_tiocmset,
.attach = digi_startup,
- .disconnect = digi_disconnect,
.release = digi_release,
.port_probe = digi_port_probe,
.port_remove = digi_port_remove,
@@ -310,7 +307,6 @@ static struct usb_serial_driver digi_acceleport_4_device = {
.tiocmget = digi_tiocmget,
.tiocmset = digi_tiocmset,
.attach = digi_startup,
- .disconnect = digi_disconnect,
.release = digi_release,
.port_probe = digi_port_probe,
.port_remove = digi_port_remove,
@@ -1034,6 +1030,43 @@ static void digi_dtr_rts(struct usb_serial_port *port, int on)
digi_set_modem_signals(port, on * (TIOCM_DTR | TIOCM_RTS), 1);
}
+static int digi_open_oob_port(struct usb_serial *serial)
+{
+ struct digi_serial *serial_priv = usb_get_serial_data(serial);
+ struct usb_serial_port *oob_port = serial_priv->ds_oob_port;
+ int ret = 0;
+
+ mutex_lock(&serial_priv->open_mutex);
+
+ if (serial_priv->open_count++ == 0) {
+ ret = usb_submit_urb(oob_port->read_urb, GFP_KERNEL);
+ if (ret) {
+ dev_err(&serial->interface->dev, "failed to submit OOB read urb: %d\n",
+ ret);
+ serial_priv->open_count--;
+ }
+ }
+
+ mutex_unlock(&serial_priv->open_mutex);
+
+ return ret;
+}
+
+static void digi_close_oob_port(struct usb_serial *serial)
+{
+ struct digi_serial *serial_priv = usb_get_serial_data(serial);
+ struct usb_serial_port *oob_port = serial_priv->ds_oob_port;
+
+ mutex_lock(&serial_priv->open_mutex);
+
+ if (serial_priv->open_count-- == 1) {
+ usb_kill_urb(oob_port->read_urb);
+ usb_kill_urb(oob_port->write_urb);
+ }
+
+ mutex_unlock(&serial_priv->open_mutex);
+}
+
static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct digi_port *priv = usb_get_serial_port_data(port);
@@ -1041,9 +1074,9 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
unsigned char buf[32];
int ret;
- /* be sure the device is started up */
- if (digi_startup_device(port->serial) != 0)
- return -ENXIO;
+ ret = digi_open_oob_port(port->serial);
+ if (ret)
+ return ret;
/* read modem signals automatically whenever they change */
buf[0] = DIGI_CMD_READ_INPUT_SIGNALS;
@@ -1071,10 +1104,15 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (ret) {
dev_err(&port->dev, "failed to submit read urb: %d\n", ret);
- return ret;
+ goto err_close_oob;
}
return 0;
+
+err_close_oob:
+ digi_close_oob_port(port->serial);
+
+ return ret;
}
static void digi_close(struct usb_serial_port *port)
@@ -1137,36 +1175,8 @@ static void digi_close(struct usb_serial_port *port)
/* shutdown any outstanding bulk writes */
usb_kill_urb(port->write_urb);
-}
-
-/*
- * Digi Startup Device
- *
- * Starts read on the OOB port. Must be called AFTER startup, with
- * urbs initialized. Returns 0 if successful, non-zero error otherwise.
- */
-static int digi_startup_device(struct usb_serial *serial)
-{
- struct digi_serial *serial_priv = usb_get_serial_data(serial);
- struct usb_serial_port *oob_port = serial_priv->ds_oob_port;
- int ret;
-
- /* be sure this happens exactly once */
- spin_lock(&serial_priv->ds_serial_lock);
- if (serial_priv->ds_device_started) {
- spin_unlock(&serial_priv->ds_serial_lock);
- return 0;
- }
- serial_priv->ds_device_started = 1;
- spin_unlock(&serial_priv->ds_serial_lock);
- ret = usb_submit_urb(oob_port->read_urb, GFP_KERNEL);
- if (ret) {
- dev_err(&serial->interface->dev, "failed to submit OOB read urb: %d\n", ret);
- return ret;
- }
-
- return 0;
+ digi_close_oob_port(port->serial);
}
static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
@@ -1198,7 +1208,8 @@ static int digi_startup(struct usb_serial *serial)
if (!serial_priv)
return -ENOMEM;
- spin_lock_init(&serial_priv->ds_serial_lock);
+ mutex_init(&serial_priv->open_mutex);
+
serial_priv->ds_oob_port_num = serial->type->num_ports;
serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];
@@ -1214,15 +1225,6 @@ static int digi_startup(struct usb_serial *serial)
return 0;
}
-static void digi_disconnect(struct usb_serial *serial)
-{
- struct digi_serial *serial_priv = usb_get_serial_data(serial);
- struct usb_serial_port *oob_port = serial_priv->ds_oob_port;
-
- usb_kill_urb(oob_port->read_urb);
- usb_kill_urb(oob_port->write_urb);
-}
-
static void digi_release(struct usb_serial *serial)
{
struct digi_serial *serial_priv;
--
2.53.0
next prev parent reply other threads:[~2026-06-10 13:22 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-10 13:22 [PATCH 00/11] USB: serial: digi_acceleport: registration fix and cleanups Johan Hovold
2026-06-10 13:22 ` [PATCH 01/11] USB: serial: digi_acceleport: fix port registration order Johan Hovold
2026-06-10 13:22 ` [PATCH 02/11] USB: serial: digi_acceleport: drop unused wait queue Johan Hovold
2026-06-10 13:22 ` [PATCH 03/11] USB: serial: digi_acceleport: always stop write urb on close Johan Hovold
2026-06-10 13:22 ` [PATCH 04/11] USB: serial: digi_acceleport: add oob port helper Johan Hovold
2026-06-10 13:22 ` [PATCH 05/11] USB: serial: digi_acceleport: clean up declarations and whitespace Johan Hovold
2026-06-10 13:22 ` [PATCH 06/11] USB: serial: digi_acceleport: drop redundant driver data sanity checks Johan Hovold
2026-06-10 13:22 ` Johan Hovold [this message]
2026-06-10 13:22 ` [PATCH 08/11] USB: serial: digi_acceleport: drop unused in-buf define Johan Hovold
2026-06-10 13:22 ` [PATCH 09/11] USB: serial: digi_acceleport: clean up xfer buf length expression Johan Hovold
2026-06-10 13:22 ` [PATCH 10/11] USB: serial: digi_acceleport: clean up write completion Johan Hovold
2026-06-10 13:22 ` [PATCH 11/11] USB: serial: digi_acceleport: clean up inb command submission Johan Hovold
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=20260610132232.356139-8-johan@kernel.org \
--to=johan@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.