summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSubrat Dash <sdash@codeaurora.org>2016-08-24 18:26:25 +0530
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-08-25 16:14:56 +0530
commit2354a4c985bcc50f7a020e4c37b11312e926cc29 (patch)
tree21c9b97c925a0c06f5fce6cd8188508795e0ede9
parent4013e7cb125c979e3ee77bc2b821586fb707ea2c (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.c1
-rw-r--r--CORE/SERVICES/HIF/USB/hif_usb_internal.h3
-rw-r--r--CORE/SERVICES/HIF/USB/usbdrv.c6
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__));
}