qcacmn: Fix race condition in tx lookup queue during tx completion

Tx lookup queue holds the reference of the packet that is successfully
transmitted via CE pipe. Tx lookup queue  method can be called from
tx path and from tasklet simultaneously for the same endpoint.
One context can get the packet reference in its local lookup Queue and the
other context may not find the reference as this is not brought back
from lookupQueue to TxLookupQueue.

Fix this by adding a per endpoint lookup queue lock.

Change-Id: I0f4872f695e9ab15c27c91e733449f03871f4262
CRs-Fixed: 2047390
这个提交包含在:
Govind Singh
2017-05-16 12:15:51 +05:30
提交者 snandini
父节点 899e775769
当前提交 c505cdc689
修改 3 个文件,包含 28 行新增11 行删除

查看文件

@@ -142,7 +142,8 @@ void htc_dump(HTC_HANDLE HTCHandle, uint8_t CmdId, bool start)
static void htc_cleanup(HTC_TARGET *target)
{
HTC_PACKET *pPacket;
/* qdf_nbuf_t netbuf; */
int i;
HTC_ENDPOINT *endpoint;
if (target->hif_dev != NULL) {
hif_detach_htc(target->hif_dev);
@@ -180,6 +181,10 @@ static void htc_cleanup(HTC_TARGET *target)
qdf_spinlock_destroy(&target->HTCRxLock);
qdf_spinlock_destroy(&target->HTCTxLock);
qdf_spinlock_destroy(&target->HTCCreditLock);
for (i = 0; i < ENDPOINT_MAX; i++) {
endpoint = &target->endpoint[i];
qdf_spinlock_destroy(&endpoint->lookup_queue_lock);
}
/* free our instance */
qdf_mem_free(target);
@@ -262,6 +267,10 @@ HTC_HANDLE htc_create(void *ol_sc, struct htc_init_info *pInfo,
qdf_spinlock_create(&target->HTCRxLock);
qdf_spinlock_create(&target->HTCTxLock);
qdf_spinlock_create(&target->HTCCreditLock);
for (i = 0; i < ENDPOINT_MAX; i++) {
pEndpoint = &target->endpoint[i];
qdf_spinlock_create(&pEndpoint->lookup_queue_lock);
}
target->is_nodrop_pkt = false;
target->wmi_ep_count = 1;

查看文件

@@ -174,6 +174,7 @@ typedef struct _HTC_ENDPOINT {
#endif
bool TxCreditFlowEnabled;
bool async_update; /* packets can be queued asynchronously */
qdf_spinlock_t lookup_queue_lock;
} HTC_ENDPOINT;
#ifdef HTC_EP_STAT_PROFILING
@@ -289,6 +290,8 @@ do { \
#define UNLOCK_HTC_TX(t) qdf_spin_unlock_bh(&(t)->HTCTxLock)
#define LOCK_HTC_CREDIT(t) qdf_spin_lock_bh(&(t)->HTCCreditLock)
#define UNLOCK_HTC_CREDIT(t) qdf_spin_unlock_bh(&(t)->HTCCreditLock)
#define LOCK_HTC_EP_TX_LOOKUP(t) qdf_spin_lock_bh(&(t)->lookup_queue_lock)
#define UNLOCK_HTC_EP_TX_LOOKUP(t) qdf_spin_unlock_bh(&(t)->lookup_queue_lock)
#define GET_HTC_TARGET_FROM_HANDLE(hnd) ((HTC_TARGET *)(hnd))

查看文件

@@ -1901,6 +1901,8 @@ static HTC_PACKET *htc_lookup_tx_packet(HTC_TARGET *target,
HTC_PACKET_QUEUE lookupQueue;
INIT_HTC_PACKET_QUEUE(&lookupQueue);
LOCK_HTC_EP_TX_LOOKUP(pEndpoint);
LOCK_HTC_TX(target);
/* mark that HIF has indicated the send complete for another packet */
@@ -1910,10 +1912,12 @@ static HTC_PACKET *htc_lookup_tx_packet(HTC_TARGET *target,
pPacket = htc_packet_dequeue(&pEndpoint->TxLookupQueue);
if (qdf_unlikely(!pPacket)) {
UNLOCK_HTC_TX(target);
UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint);
return NULL;
}
if (netbuf == (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket)) {
UNLOCK_HTC_TX(target);
UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint);
return pPacket;
}
HTC_PACKET_ENQUEUE(&lookupQueue, pPacket);
@@ -1949,6 +1953,7 @@ static HTC_PACKET *htc_lookup_tx_packet(HTC_TARGET *target,
HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxLookupQueue,
&lookupQueue);
UNLOCK_HTC_TX(target);
UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint);
return pFoundPacket;
}