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 <dbrownell@users.sourceforge.net>
Cc: David Engraf <david.engraf@netcom.eu>
Acked-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-static inline int acm_wb_is_used(struct acm *acm, int wbn)
-{
- return acm->wb[wbn].use;
-}
-
unsigned long flags;
spin_lock_irqsave(&acm->write_lock, flags);
unsigned long flags;
spin_lock_irqsave(&acm->write_lock, flags);
wb->use = 0;
acm->transmitting--;
spin_unlock_irqrestore(&acm->write_lock, flags);
wb->use = 0;
acm->transmitting--;
spin_unlock_irqrestore(&acm->write_lock, flags);
static int acm_write_start(struct acm *acm, int wbn)
{
unsigned long flags;
static int acm_write_start(struct acm *acm, int wbn)
{
unsigned long flags;
+ struct acm_wb *wb = &acm->wb[wbn];
int rc;
spin_lock_irqsave(&acm->write_lock, flags);
if (!acm->dev) {
int rc;
spin_lock_irqsave(&acm->write_lock, flags);
if (!acm->dev) {
spin_unlock_irqrestore(&acm->write_lock, flags);
return -ENODEV;
}
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) {
dbg("%s susp_count: %d", __func__, acm->susp_count);
if (acm->susp_count) {
- acm->old_ready = acm->write_ready;
schedule_work(&acm->waker);
spin_unlock_irqrestore(&acm->write_lock, flags);
return 0; /* A white lie */
}
usb_mark_last_busy(acm->dev);
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);
rc = acm_start_wb(acm, wb);
spin_unlock_irqrestore(&acm->write_lock, flags);
static void acm_waker(struct work_struct *waker)
{
struct acm *acm = container_of(waker, struct acm, waker);
static void acm_waker(struct work_struct *waker)
{
struct acm *acm = container_of(waker, struct acm, waker);
int rv;
rv = usb_autopm_get_interface(acm->control);
int rv;
rv = usb_autopm_get_interface(acm->control);
acm_start_wb(acm, acm->delayed_wb);
acm->delayed_wb = NULL;
}
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);
}
usb_autopm_put_interface(acm->control);
}
* Do not let the line discipline to know that we have a reserve,
* or it might get too enthusiastic.
*/
* 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)
}
static int acm_tty_chars_in_buffer(struct tty_struct *tty)
spin_lock_init(&acm->write_lock);
spin_lock_init(&acm->read_lock);
mutex_init(&acm->mutex);
spin_lock_init(&acm->write_lock);
spin_lock_init(&acm->read_lock);
mutex_init(&acm->mutex);
acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
struct list_head spare_read_bufs;
struct list_head filled_read_bufs;
int write_used; /* number of non-empty write buffers */
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;
int processing;
int transmitting;
spinlock_t write_lock;