From 934da4635c2d05cef474e5243ef05df95b2ad264 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 6 Aug 2008 18:44:12 -0700 Subject: [PATCH] usb: cdc-acm: stop dropping tx buffers The "increase cdc-acm write throughput" patch left in place two now-obsolete mechanisms, either of which can make the cdc-acm driver drop TX data (nasty!). This patch removes them: - The write_ready flag ... if an URB and buffer were found, they can (and should!) always be used. - TX path acm_wb_is_used() ... used when the buffer was just allocated, so that check is pointless. Also fix a won't-yet-matter leak of a write buffer on a disconnect path. Signed-off-by: David Brownell Cc: David Engraf Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 32 +++----------------------------- drivers/usb/class/cdc-acm.h | 2 -- 2 files changed, 3 insertions(+), 31 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 910247d191e8..a9dd28f446d8 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -144,11 +144,6 @@ static int acm_wb_is_avail(struct acm *acm) return n; } -static inline int acm_wb_is_used(struct acm *acm, int wbn) -{ - return acm->wb[wbn].use; -} - /* * Finish write. */ @@ -157,7 +152,6 @@ static void acm_write_done(struct acm *acm, struct acm_wb *wb) unsigned long flags; spin_lock_irqsave(&acm->write_lock, flags); - acm->write_ready = 1; wb->use = 0; acm->transmitting--; spin_unlock_irqrestore(&acm->write_lock, flags); @@ -190,40 +184,25 @@ static int acm_start_wb(struct acm *acm, struct acm_wb *wb) static int acm_write_start(struct acm *acm, int wbn) { unsigned long flags; - struct acm_wb *wb; + struct acm_wb *wb = &acm->wb[wbn]; int rc; spin_lock_irqsave(&acm->write_lock, flags); if (!acm->dev) { + wb->use = 0; spin_unlock_irqrestore(&acm->write_lock, flags); return -ENODEV; } - if (!acm->write_ready) { - spin_unlock_irqrestore(&acm->write_lock, flags); - return 0; /* A white lie */ - } - - wb = &acm->wb[wbn]; - if(acm_wb_is_avail(acm) <= 1) - acm->write_ready = 0; - dbg("%s susp_count: %d", __func__, acm->susp_count); if (acm->susp_count) { - acm->old_ready = acm->write_ready; acm->delayed_wb = wb; - acm->write_ready = 0; schedule_work(&acm->waker); spin_unlock_irqrestore(&acm->write_lock, flags); return 0; /* A white lie */ } usb_mark_last_busy(acm->dev); - if (!acm_wb_is_used(acm, wbn)) { - spin_unlock_irqrestore(&acm->write_lock, flags); - return 0; - } - rc = acm_start_wb(acm, wb); spin_unlock_irqrestore(&acm->write_lock, flags); @@ -512,7 +491,6 @@ static void acm_softint(struct work_struct *work) static void acm_waker(struct work_struct *waker) { struct acm *acm = container_of(waker, struct acm, waker); - unsigned long flags; int rv; rv = usb_autopm_get_interface(acm->control); @@ -524,9 +502,6 @@ static void acm_waker(struct work_struct *waker) acm_start_wb(acm, acm->delayed_wb); acm->delayed_wb = NULL; } - spin_lock_irqsave(&acm->write_lock, flags); - acm->write_ready = acm->old_ready; - spin_unlock_irqrestore(&acm->write_lock, flags); usb_autopm_put_interface(acm->control); } @@ -697,7 +672,7 @@ static int acm_tty_write_room(struct tty_struct *tty) * Do not let the line discipline to know that we have a reserve, * or it might get too enthusiastic. */ - return (acm->write_ready && acm_wb_is_avail(acm)) ? acm->writesize : 0; + return acm_wb_is_avail(acm) ? acm->writesize : 0; } static int acm_tty_chars_in_buffer(struct tty_struct *tty) @@ -1076,7 +1051,6 @@ static int acm_probe (struct usb_interface *intf, spin_lock_init(&acm->write_lock); spin_lock_init(&acm->read_lock); mutex_init(&acm->mutex); - acm->write_ready = 1; acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress); buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index 85c3aaaab7c5..94266362ca68 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -106,8 +106,6 @@ struct acm { struct list_head spare_read_bufs; struct list_head filled_read_bufs; int write_used; /* number of non-empty write buffers */ - int write_ready; /* write urb is not running */ - int old_ready; int processing; int transmitting; spinlock_t write_lock;