aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-06-07 14:42:08 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-06-17 16:37:07 -0400
commit71c2fb03fc5800f24b66b730cbb9fddc22df40d3 (patch)
treed4a773e32aa14fe75de0a30dd9db934b7f8349e1 /drivers/usb/class
parent455b4f7e18e741c0603f9030f9a1897f4c5150c1 (diff)
USB: cdc-acm: remove unneeded spin_lock_irqsave/restore on write path
When writing data we were: lock do some work unlock call function lock do some work unlock return return It turns out, that "function" was only ever called in the one place, so instead of locking/unlocking for no good reason, just inline the function and only grab the lock once. This has sped up the pathological case of sending 1 byte packets to a loop-back cdc-acm device from 49600 bytes per second to 50100 bytes a second on my workstation. A tiny increase yes, but noticable, and now the spinlock isn't the hottest thing on the perf graph anymore. Yes, we are still waiting for the hardware for the most part, but getting rid of a spinlock_irq_save() call for every packet is still a good thing. And we end up deleting lines of code, always a win overall. This was found by using a Teensy 3.0 device and the test program and firmware located at: http://www.pjrc.com/teensy/benchmark_usb_serial_receive.html Reported-by: Paul Stoffregen <paul@pjrc.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/class')
-rw-r--r--drivers/usb/class/cdc-acm.c52
1 files changed, 19 insertions, 33 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 9b1cbcf8fb7f..9f49bfe4c6f4 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -216,38 +216,6 @@ static int acm_start_wb(struct acm *acm, struct acm_wb *wb)
216 return rc; 216 return rc;
217} 217}
218 218
219static int acm_write_start(struct acm *acm, int wbn)
220{
221 unsigned long flags;
222 struct acm_wb *wb = &acm->wb[wbn];
223 int rc;
224
225 spin_lock_irqsave(&acm->write_lock, flags);
226 if (!acm->dev) {
227 wb->use = 0;
228 spin_unlock_irqrestore(&acm->write_lock, flags);
229 return -ENODEV;
230 }
231
232 dev_vdbg(&acm->data->dev, "%s - susp_count %d\n", __func__,
233 acm->susp_count);
234 usb_autopm_get_interface_async(acm->control);
235 if (acm->susp_count) {
236 if (!acm->delayed_wb)
237 acm->delayed_wb = wb;
238 else
239 usb_autopm_put_interface_async(acm->control);
240 spin_unlock_irqrestore(&acm->write_lock, flags);
241 return 0; /* A white lie */
242 }
243 usb_mark_last_busy(acm->dev);
244
245 rc = acm_start_wb(acm, wb);
246 spin_unlock_irqrestore(&acm->write_lock, flags);
247
248 return rc;
249
250}
251/* 219/*
252 * attributes exported through sysfs 220 * attributes exported through sysfs
253 */ 221 */
@@ -653,13 +621,31 @@ static int acm_tty_write(struct tty_struct *tty,
653 } 621 }
654 wb = &acm->wb[wbn]; 622 wb = &acm->wb[wbn];
655 623
624 if (!acm->dev) {
625 wb->use = 0;
626 spin_unlock_irqrestore(&acm->write_lock, flags);
627 return -ENODEV;
628 }
629
656 count = (count > acm->writesize) ? acm->writesize : count; 630 count = (count > acm->writesize) ? acm->writesize : count;
657 dev_vdbg(&acm->data->dev, "%s - write %d\n", __func__, count); 631 dev_vdbg(&acm->data->dev, "%s - write %d\n", __func__, count);
658 memcpy(wb->buf, buf, count); 632 memcpy(wb->buf, buf, count);
659 wb->len = count; 633 wb->len = count;
634
635 usb_autopm_get_interface_async(acm->control);
636 if (acm->susp_count) {
637 if (!acm->delayed_wb)
638 acm->delayed_wb = wb;
639 else
640 usb_autopm_put_interface_async(acm->control);
641 spin_unlock_irqrestore(&acm->write_lock, flags);
642 return count; /* A white lie */
643 }
644 usb_mark_last_busy(acm->dev);
645
646 stat = acm_start_wb(acm, wb);
660 spin_unlock_irqrestore(&acm->write_lock, flags); 647 spin_unlock_irqrestore(&acm->write_lock, flags);
661 648
662 stat = acm_write_start(acm, wbn);
663 if (stat < 0) 649 if (stat < 0)
664 return stat; 650 return stat;
665 return count; 651 return count;