diff options
author | Thomas Pugliese <thomas.pugliese@gmail.com> | 2013-10-07 10:53:57 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-10-19 05:19:21 -0700 |
commit | 679ee475a1c19243c8f50a5a76f6b7519b24c1a3 (patch) | |
tree | a1cee61ed77804e87b138621bc77f90cc24db11c /drivers/usb/wusbcore/wa-rpipe.c | |
parent | 8114fabc94cc94e4eb50050a99f7ee5573fa37d9 (diff) | |
download | linux-679ee475a1c19243c8f50a5a76f6b7519b24c1a3.tar.gz linux-679ee475a1c19243c8f50a5a76f6b7519b24c1a3.tar.bz2 linux-679ee475a1c19243c8f50a5a76f6b7519b24c1a3.zip |
usb: wusbcore: serialize access to the HWA data out endpoint
This patch serializes access to the HWA data transfer out (DTO)
endpoint. This prevents a situation where two transfer requests being
sent concurrently to separate downstream endpoints could interleave
their transfer request and transfer data packets causing data
corruption. The transfer processing code will now attempt to acquire
the DTO resource before sending a transfer to the HWA. If it cannot
acquire the resource, the RPIPE that the transfer is assigned to will
be placed on a waiting list. When the DTO resource is released, the
actor releasing the resource will serivce the RPIPEs that are waiting.
Signed-off-by: Thomas Pugliese <thomas.pugliese@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/wusbcore/wa-rpipe.c')
-rw-r--r-- | drivers/usb/wusbcore/wa-rpipe.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c index 554b16bd22f1..50de1d2c7b72 100644 --- a/drivers/usb/wusbcore/wa-rpipe.c +++ b/drivers/usb/wusbcore/wa-rpipe.c @@ -143,17 +143,18 @@ static void rpipe_init(struct wa_rpipe *rpipe) kref_init(&rpipe->refcnt); spin_lock_init(&rpipe->seg_lock); INIT_LIST_HEAD(&rpipe->seg_list); + INIT_LIST_HEAD(&rpipe->list_node); } static unsigned rpipe_get_idx(struct wahc *wa, unsigned rpipe_idx) { unsigned long flags; - spin_lock_irqsave(&wa->rpipe_bm_lock, flags); + spin_lock_irqsave(&wa->rpipe_lock, flags); rpipe_idx = find_next_zero_bit(wa->rpipe_bm, wa->rpipes, rpipe_idx); if (rpipe_idx < wa->rpipes) set_bit(rpipe_idx, wa->rpipe_bm); - spin_unlock_irqrestore(&wa->rpipe_bm_lock, flags); + spin_unlock_irqrestore(&wa->rpipe_lock, flags); return rpipe_idx; } @@ -162,9 +163,9 @@ static void rpipe_put_idx(struct wahc *wa, unsigned rpipe_idx) { unsigned long flags; - spin_lock_irqsave(&wa->rpipe_bm_lock, flags); + spin_lock_irqsave(&wa->rpipe_lock, flags); clear_bit(rpipe_idx, wa->rpipe_bm); - spin_unlock_irqrestore(&wa->rpipe_bm_lock, flags); + spin_unlock_irqrestore(&wa->rpipe_lock, flags); } void rpipe_destroy(struct kref *_rpipe) |