projects
/
cascardo
/
linux.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
USB: cdc-acm: simplify runtime PM locking
[cascardo/linux.git]
/
drivers
/
usb
/
class
/
cdc-acm.c
diff --git
a/drivers/usb/class/cdc-acm.c
b/drivers/usb/class/cdc-acm.c
index
2258827
..
bc7a2a6
100644
(file)
--- a/
drivers/usb/class/cdc-acm.c
+++ b/
drivers/usb/class/cdc-acm.c
@@
-428,7
+428,7
@@
static void acm_read_bulk_callback(struct urb *urb)
/* throttle device if requested by tty */
spin_lock_irqsave(&acm->read_lock, flags);
acm->throttled = acm->throttle_req;
/* throttle device if requested by tty */
spin_lock_irqsave(&acm->read_lock, flags);
acm->throttled = acm->throttle_req;
- if (!acm->throttled
&& !acm->susp_count
) {
+ if (!acm->throttled) {
spin_unlock_irqrestore(&acm->read_lock, flags);
acm_submit_read_urb(acm, rb->index, GFP_ATOMIC);
} else {
spin_unlock_irqrestore(&acm->read_lock, flags);
acm_submit_read_urb(acm, rb->index, GFP_ATOMIC);
} else {
@@
-506,6
+506,7
@@
static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
{
struct acm *acm = container_of(port, struct acm, port);
int retval = -ENODEV;
{
struct acm *acm = container_of(port, struct acm, port);
int retval = -ENODEV;
+ int i;
dev_dbg(&acm->control->dev, "%s\n", __func__);
dev_dbg(&acm->control->dev, "%s\n", __func__);
@@
-525,21
+526,17
@@
static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
acm->control->needs_remote_wakeup = 1;
acm->ctrlurb->dev = acm->dev;
acm->control->needs_remote_wakeup = 1;
acm->ctrlurb->dev = acm->dev;
- if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
+ retval = usb_submit_urb(acm->ctrlurb, GFP_KERNEL);
+ if (retval) {
dev_err(&acm->control->dev,
"%s - usb_submit_urb(ctrl irq) failed\n", __func__);
dev_err(&acm->control->dev,
"%s - usb_submit_urb(ctrl irq) failed\n", __func__);
- usb_autopm_put_interface(acm->control);
goto error_submit_urb;
}
acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS;
goto error_submit_urb;
}
acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS;
- if (acm_set_control(acm, acm->ctrlout) < 0 &&
- (acm->ctrl_caps & USB_CDC_CAP_LINE)) {
- usb_autopm_put_interface(acm->control);
+ retval = acm_set_control(acm, acm->ctrlout);
+ if (retval < 0 && (acm->ctrl_caps & USB_CDC_CAP_LINE))
goto error_set_control;
goto error_set_control;
- }
-
- usb_autopm_put_interface(acm->control);
/*
* Unthrottle device in case the TTY was closed while throttled.
/*
* Unthrottle device in case the TTY was closed while throttled.
@@
-549,23
+546,30
@@
static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
acm->throttle_req = 0;
spin_unlock_irq(&acm->read_lock);
acm->throttle_req = 0;
spin_unlock_irq(&acm->read_lock);
- if (acm_submit_read_urbs(acm, GFP_KERNEL))
+ retval = acm_submit_read_urbs(acm, GFP_KERNEL);
+ if (retval)
goto error_submit_read_urbs;
goto error_submit_read_urbs;
+ usb_autopm_put_interface(acm->control);
+
mutex_unlock(&acm->mutex);
return 0;
error_submit_read_urbs:
mutex_unlock(&acm->mutex);
return 0;
error_submit_read_urbs:
+ for (i = 0; i < acm->rx_buflimit; i++)
+ usb_kill_urb(acm->read_urbs[i]);
acm->ctrlout = 0;
acm_set_control(acm, acm->ctrlout);
error_set_control:
usb_kill_urb(acm->ctrlurb);
error_submit_urb:
acm->ctrlout = 0;
acm_set_control(acm, acm->ctrlout);
error_set_control:
usb_kill_urb(acm->ctrlurb);
error_submit_urb:
+ usb_autopm_put_interface(acm->control);
error_get_interface:
disconnected:
mutex_unlock(&acm->mutex);
error_get_interface:
disconnected:
mutex_unlock(&acm->mutex);
- return retval;
+
+ return usb_translate_errors(retval);
}
static void acm_port_destruct(struct tty_port *port)
}
static void acm_port_destruct(struct tty_port *port)
@@
-586,12
+590,13
@@
static void acm_port_shutdown(struct tty_port *port)
struct urb *urb;
struct acm_wb *wb;
int i;
struct urb *urb;
struct acm_wb *wb;
int i;
+ int pm_err;
dev_dbg(&acm->control->dev, "%s\n", __func__);
mutex_lock(&acm->mutex);
if (!acm->disconnected) {
dev_dbg(&acm->control->dev, "%s\n", __func__);
mutex_lock(&acm->mutex);
if (!acm->disconnected) {
- usb_autopm_get_interface(acm->control);
+
pm_err =
usb_autopm_get_interface(acm->control);
acm_set_control(acm, acm->ctrlout = 0);
for (;;) {
acm_set_control(acm, acm->ctrlout = 0);
for (;;) {
@@
-609,7
+614,8
@@
static void acm_port_shutdown(struct tty_port *port)
for (i = 0; i < acm->rx_buflimit; i++)
usb_kill_urb(acm->read_urbs[i]);
acm->control->needs_remote_wakeup = 0;
for (i = 0; i < acm->rx_buflimit; i++)
usb_kill_urb(acm->read_urbs[i]);
acm->control->needs_remote_wakeup = 0;
- usb_autopm_put_interface(acm->control);
+ if (!pm_err)
+ usb_autopm_put_interface(acm->control);
}
mutex_unlock(&acm->mutex);
}
}
mutex_unlock(&acm->mutex);
}
@@
-668,7
+674,13
@@
static int acm_tty_write(struct tty_struct *tty,
memcpy(wb->buf, buf, count);
wb->len = count;
memcpy(wb->buf, buf, count);
wb->len = count;
- usb_autopm_get_interface_async(acm->control);
+ stat = usb_autopm_get_interface_async(acm->control);
+ if (stat) {
+ wb->use = 0;
+ spin_unlock_irqrestore(&acm->write_lock, flags);
+ return stat;
+ }
+
if (acm->susp_count) {
usb_anchor_urb(wb->urb, &acm->delayed);
spin_unlock_irqrestore(&acm->write_lock, flags);
if (acm->susp_count) {
usb_anchor_urb(wb->urb, &acm->delayed);
spin_unlock_irqrestore(&acm->write_lock, flags);
@@
-1534,24
+1546,20
@@
static int acm_suspend(struct usb_interface *intf, pm_message_t message)
struct acm *acm = usb_get_intfdata(intf);
int cnt;
struct acm *acm = usb_get_intfdata(intf);
int cnt;
- spin_lock_irq(&acm->read_lock);
- spin_lock(&acm->write_lock);
+ spin_lock_irq(&acm->write_lock);
if (PMSG_IS_AUTO(message)) {
if (acm->transmitting) {
if (PMSG_IS_AUTO(message)) {
if (acm->transmitting) {
- spin_unlock(&acm->write_lock);
- spin_unlock_irq(&acm->read_lock);
+ spin_unlock_irq(&acm->write_lock);
return -EBUSY;
}
}
cnt = acm->susp_count++;
return -EBUSY;
}
}
cnt = acm->susp_count++;
- spin_unlock(&acm->write_lock);
- spin_unlock_irq(&acm->read_lock);
+ spin_unlock_irq(&acm->write_lock);
if (cnt)
return 0;
if (cnt)
return 0;
- if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags))
- stop_data_traffic(acm);
+ stop_data_traffic(acm);
return 0;
}
return 0;
}
@@
-1562,8
+1570,7
@@
static int acm_resume(struct usb_interface *intf)
struct urb *urb;
int rv = 0;
struct urb *urb;
int rv = 0;
- spin_lock_irq(&acm->read_lock);
- spin_lock(&acm->write_lock);
+ spin_lock_irq(&acm->write_lock);
if (--acm->susp_count)
goto out;
if (--acm->susp_count)
goto out;
@@
-1589,8
+1596,7
@@
static int acm_resume(struct usb_interface *intf)
rv = acm_submit_read_urbs(acm, GFP_ATOMIC);
}
out:
rv = acm_submit_read_urbs(acm, GFP_ATOMIC);
}
out:
- spin_unlock(&acm->write_lock);
- spin_unlock_irq(&acm->read_lock);
+ spin_unlock_irq(&acm->write_lock);
return rv;
}
return rv;
}