Skip to content

Commit

Permalink
cdc-acm: fix race between callback and unthrottle
Browse files Browse the repository at this point in the history
Abn URB may be may marked free only after the buffer has been
processed or there is a small window during which it could
be submitted on another CPU and overwrite an unprocessed buffer

Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Oliver Neukum authored and Greg Kroah-Hartman committed Mar 26, 2015
1 parent c0ab6bb commit 36e59e0
Showing 1 changed file with 10 additions and 2 deletions.
12 changes: 10 additions & 2 deletions drivers/usb/class/cdc-acm.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,25 +417,33 @@ static void acm_read_bulk_callback(struct urb *urb)
struct acm_rb *rb = urb->context;
struct acm *acm = rb->instance;
unsigned long flags;
int status = urb->status;

dev_vdbg(&acm->data->dev, "%s - urb %d, len %d\n", __func__,
rb->index, urb->actual_length);
set_bit(rb->index, &acm->read_urbs_free);

if (!acm->dev) {
set_bit(rb->index, &acm->read_urbs_free);
dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__);
return;
}

if (urb->status) {
set_bit(rb->index, &acm->read_urbs_free);
dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n",
__func__, urb->status);
__func__, status);
return;
}

usb_mark_last_busy(acm->dev);

acm_process_read_urb(acm, urb);
/*
* Unthrottle may run on another CPU which needs to see events
* in the same order. Submission has an implict barrier
*/
smp_mb__before_atomic();
set_bit(rb->index, &acm->read_urbs_free);

/* throttle device if requested by tty */
spin_lock_irqsave(&acm->read_lock, flags);
Expand Down

0 comments on commit 36e59e0

Please sign in to comment.