Commit ca79b7b4 authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman

USB: cdc-acm: fix incorrect throtteling, make set_control optional

this is Joris' fixes reshuffelled and features renamed as David requested.

- acm_set_control is not mandatory, honour that
- throtteling is reset upon open
- throtteling is read consistently when processing input data
Signed-off-by: default avatarJoris van Rantwijk <jorispubl@xs4all.nl>
Signed-off-by: default avatarOliver Neukum <oneukum@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 3f141e2a
...@@ -326,10 +326,16 @@ static void acm_rx_tasklet(unsigned long _acm) ...@@ -326,10 +326,16 @@ static void acm_rx_tasklet(unsigned long _acm)
struct tty_struct *tty = acm->tty; struct tty_struct *tty = acm->tty;
struct acm_ru *rcv; struct acm_ru *rcv;
unsigned long flags; unsigned long flags;
int i = 0; unsigned char throttled;
dbg("Entering acm_rx_tasklet"); dbg("Entering acm_rx_tasklet");
if (!ACM_READY(acm) || acm->throttle) if (!ACM_READY(acm))
return;
spin_lock(&acm->throttle_lock);
throttled = acm->throttle;
spin_unlock(&acm->throttle_lock);
if (throttled)
return; return;
next_buffer: next_buffer:
...@@ -346,22 +352,20 @@ static void acm_rx_tasklet(unsigned long _acm) ...@@ -346,22 +352,20 @@ static void acm_rx_tasklet(unsigned long _acm)
dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
tty_buffer_request_room(tty, buf->size); tty_buffer_request_room(tty, buf->size);
if (!acm->throttle) spin_lock(&acm->throttle_lock);
throttled = acm->throttle;
spin_unlock(&acm->throttle_lock);
if (!throttled)
tty_insert_flip_string(tty, buf->base, buf->size); tty_insert_flip_string(tty, buf->base, buf->size);
tty_flip_buffer_push(tty); tty_flip_buffer_push(tty);
spin_lock(&acm->throttle_lock); if (throttled) {
if (acm->throttle) { dbg("Throttling noticed");
dbg("Throtteling noticed");
memmove(buf->base, buf->base + i, buf->size - i);
buf->size -= i;
spin_unlock(&acm->throttle_lock);
spin_lock_irqsave(&acm->read_lock, flags); spin_lock_irqsave(&acm->read_lock, flags);
list_add(&buf->list, &acm->filled_read_bufs); list_add(&buf->list, &acm->filled_read_bufs);
spin_unlock_irqrestore(&acm->read_lock, flags); spin_unlock_irqrestore(&acm->read_lock, flags);
return; return;
} }
spin_unlock(&acm->throttle_lock);
spin_lock_irqsave(&acm->read_lock, flags); spin_lock_irqsave(&acm->read_lock, flags);
list_add(&buf->list, &acm->spare_read_bufs); list_add(&buf->list, &acm->spare_read_bufs);
...@@ -467,7 +471,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) ...@@ -467,7 +471,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
goto bail_out; goto bail_out;
} }
if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS)) if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) &&
(acm->ctrl_caps & USB_CDC_CAP_LINE))
goto full_bailout; goto full_bailout;
INIT_LIST_HEAD(&acm->spare_read_urbs); INIT_LIST_HEAD(&acm->spare_read_urbs);
...@@ -480,6 +485,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) ...@@ -480,6 +485,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
list_add(&(acm->rb[i].list), &acm->spare_read_bufs); list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
} }
acm->throttle = 0;
tasklet_schedule(&acm->urb_task); tasklet_schedule(&acm->urb_task);
done: done:
......
...@@ -73,6 +73,13 @@ struct usb_cdc_acm_descriptor { ...@@ -73,6 +73,13 @@ struct usb_cdc_acm_descriptor {
__u8 bmCapabilities; __u8 bmCapabilities;
} __attribute__ ((packed)); } __attribute__ ((packed));
/* capabilities from 5.2.3.3 */
#define USB_CDC_COMM_FEATURE 0x01
#define USB_CDC_CAP_LINE 0x02
#define USB_CDC_CAP_BRK 0x04
#define USB_CDC_CAP_NOTIFY 0x08
/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */ /* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
struct usb_cdc_union_desc { struct usb_cdc_union_desc {
__u8 bLength; __u8 bLength;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment