diff options
| author | Subrat Dash <sdash@codeaurora.org> | 2016-08-24 18:26:25 +0530 |
|---|---|---|
| committer | Anjaneedevi Kapparapu <akappa@codeaurora.org> | 2016-08-25 16:14:56 +0530 |
| commit | 2354a4c985bcc50f7a020e4c37b11312e926cc29 (patch) | |
| tree | 21c9b97c925a0c06f5fce6cd8188508795e0ede9 | |
| parent | 4013e7cb125c979e3ee77bc2b821586fb707ea2c (diff) | |
qcacld-2.0: Fix Invalid HTC endpoint is observed in the rx header
The urb completion handler is asynchronous. Sometimes it is
called before prestart allocation is complete.
The urb_prestart_cnt is accessed unsynchronized manner from
usb_hif_usb_recv_prestart_complete. It presumes that it
is running out of prestart URBs and new allocation will be
done. Since bundling is not enabled at this point, the new
URBs allocated are not considered for bundling.
Use spin_lock to ensure synchronization in the above scenario.
Change-Id: I8c989aff7985a9ab614d63a71c7f97a0278647e0
CRs-Fixed: 1058095
| -rw-r--r-- | CORE/SERVICES/HIF/USB/hif_usb.c | 1 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/USB/hif_usb_internal.h | 3 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/USB/usbdrv.c | 6 |
3 files changed, 9 insertions, 1 deletions
diff --git a/CORE/SERVICES/HIF/USB/hif_usb.c b/CORE/SERVICES/HIF/USB/hif_usb.c index fa28970389ad..a6a88bf2754c 100644 --- a/CORE/SERVICES/HIF/USB/hif_usb.c +++ b/CORE/SERVICES/HIF/USB/hif_usb.c @@ -471,6 +471,7 @@ static HIF_DEVICE_USB *usb_hif_create(struct usb_interface *interface) spin_lock_init(&(device->cs_lock)); spin_lock_init(&(device->rx_lock)); spin_lock_init(&(device->tx_lock)); + spin_lock_init(&(device->rx_prestart_lock)); device->udev = dev; device->interface = interface; diff --git a/CORE/SERVICES/HIF/USB/hif_usb_internal.h b/CORE/SERVICES/HIF/USB/hif_usb_internal.h index fa9636184ee7..cfe8613bb682 100644 --- a/CORE/SERVICES/HIF/USB/hif_usb_internal.h +++ b/CORE/SERVICES/HIF/USB/hif_usb_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -117,6 +117,7 @@ typedef struct _HIF_DEVICE_USB { spinlock_t cs_lock; spinlock_t tx_lock; spinlock_t rx_lock; + spinlock_t rx_prestart_lock; MSG_BASED_HIF_CALLBACKS htcCallbacks; struct usb_device *udev; struct usb_interface *interface; diff --git a/CORE/SERVICES/HIF/USB/usbdrv.c b/CORE/SERVICES/HIF/USB/usbdrv.c index ab565034852c..112cd71565a5 100644 --- a/CORE/SERVICES/HIF/USB/usbdrv.c +++ b/CORE/SERVICES/HIF/USB/usbdrv.c @@ -439,6 +439,7 @@ static void usb_hif_usb_recv_prestart_complete(struct urb *urb) A_STATUS status = A_OK; adf_nbuf_t buf = NULL; HIF_USB_PIPE *pipe = urb_context->pipe; + unsigned long flags; AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ( "+%s: recv pipe: %d, stat:%d,len:%d urb:0x%p\n", @@ -501,9 +502,11 @@ static void usb_hif_usb_recv_prestart_complete(struct urb *urb) usb_hif_cleanup_recv_urb(urb_context); /* Prestart URBs runs out and now start working receive pipe. */ + spin_lock_irqsave(&pipe->device->rx_prestart_lock, flags); if (--pipe->urb_prestart_cnt == 0) { usb_hif_start_recv_pipes(pipe->device); } + spin_unlock_irqrestore(&pipe->device->rx_prestart_lock, flags); AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ("-%s\n", __func__)); } @@ -758,9 +761,11 @@ static void usb_hif_post_recv_prestart_transfers(HIF_USB_PIPE *recv_pipe, a_uint32_t len; struct urb *urb; int i, usb_status, buffer_length = HIF_USB_RX_BUFFER_SIZE; + unsigned long flags; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__)); + spin_lock_irqsave(&recv_pipe->device->rx_prestart_lock, flags); for (i = 0; i < prestart_urb; i++) { urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe); if (NULL == urb_context) @@ -807,6 +812,7 @@ static void usb_hif_post_recv_prestart_transfers(HIF_USB_PIPE *recv_pipe, recv_pipe->urb_prestart_cnt++; } + spin_unlock_irqrestore(&recv_pipe->device->rx_prestart_lock, flags); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-%s\n", __func__)); } |
