summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPrashanth Bhatta <bhattap@qca.qualcomm.com>2014-06-03 09:54:05 -0700
committerPitani Venkata Rajesh Kumar <c_vpitan@qti.qualcomm.com>2014-06-07 00:56:36 +0530
commitdd5cec7983f23e336bef9828ec0e5124822bc8e2 (patch)
tree0bc9a6ba94e3dfdaa97b4293fbf7dee039a98224
parent81c9f2a3c6f811de4db2a2d923dfd444c340c60a (diff)
qcacld: ipa: Fix spinlock lock-up issue
On IPA TX and RX path, spin lock is used but IPA call backs are called in soft irq context and leading to lock-up. This spin lock protection is added to prevent accessing IPA data structure when interface is disconnected. But this protection is only required on TX path and RX path IPA shouldn't receive any packets as disconnect happened from lower layer itself. Fixing this issue by using spin_lock_bh and removing the usage of spin lock on RX path. Change-Id: I7f3bd21192296328ad9f94eafc9139b82dc7ba09 CRs-fixed: 667732
-rw-r--r--CORE/HDD/src/wlan_hdd_ipa.c35
1 files changed, 13 insertions, 22 deletions
diff --git a/CORE/HDD/src/wlan_hdd_ipa.c b/CORE/HDD/src/wlan_hdd_ipa.c
index 35e2548ab404..6241785f2733 100644
--- a/CORE/HDD/src/wlan_hdd_ipa.c
+++ b/CORE/HDD/src/wlan_hdd_ipa.c
@@ -158,7 +158,7 @@ struct hdd_ipa_iface_context {
uint8_t iface_id; /* This iface ID */
uint8_t sta_id; /* This iface station ID */
- vos_spin_lock_t interface_lock;
+ adf_os_spinlock_t interface_lock;
uint32_t ifa_address;
};
@@ -722,8 +722,8 @@ static void hdd_ipa_process_evt(int evt, void *priv)
rxt = priv;
adapter = hdd_ipa->hdd_ctx->sta_to_adapter[rxt->sta_id];
- if (!adapter ||
- (adapter && adapter->magic != WLAN_HDD_ADAPTER_MAGIC)) {
+ if (!adapter || !adapter->ipa_context ||
+ adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
HDD_IPA_LOG(VOS_TRACE_LEVEL_ERROR, "Invalid sta_id");
buf = rxt->rx_buf_list;
while (buf) {
@@ -739,12 +739,6 @@ static void hdd_ipa_process_evt(int evt, void *priv)
iface_context =
(struct hdd_ipa_iface_context *) adapter->ipa_context;
- if (iface_context) {
- vos_spin_lock_acquire(&iface_context->interface_lock);
- }
- else {
- return;
- }
/* send_desc_head is a anchor node */
send_desc_head = hdd_ipa_get_desc_from_freeq();
@@ -767,7 +761,6 @@ static void hdd_ipa_process_evt(int evt, void *priv)
#ifdef HDD_IPA_EXTRA_DP_COUNTERS
hdd_ipa->stats.rxt_dh_drop++;
#endif
- vos_spin_lock_release(&iface_context->interface_lock);
return;
}
@@ -818,7 +811,6 @@ static void hdd_ipa_process_evt(int evt, void *priv)
#endif
buf = next_buf;
}
- vos_spin_lock_release(&iface_context->interface_lock);
#ifdef HDD_IPA_EXTRA_DP_COUNTERS
if (cur_cnt == 0)
@@ -1105,21 +1097,20 @@ static void hdd_ipa_i2w_cb(void *priv, enum ipa_dp_evt_type evt,
hdd_ipa->stats.tx_ipa_recv++;
- vos_spin_lock_acquire(&iface_context->interface_lock);
- if (iface_context->adapter) {
- interface_id = iface_context->adapter->sessionId;
- }
- else{
+ adf_os_spin_lock_bh(&iface_context->interface_lock);
+ if (!iface_context->adapter) {
HDD_IPA_LOG(VOS_TRACE_LEVEL_WARN, "Interface Down");
ipa_free_skb(ipa_tx_desc);
- vos_spin_lock_release(&iface_context->interface_lock);
+ adf_os_spin_unlock_bh(&iface_context->interface_lock);
return;
}
- vos_spin_lock_release(&iface_context->interface_lock);
+ interface_id = iface_context->adapter->sessionId;
++iface_context->adapter->stats.tx_packets;
iface_context->adapter->stats.tx_bytes += ipa_tx_desc->skb->len;
+ adf_os_spin_unlock_bh(&iface_context->interface_lock);
+
skb = WLANTL_SendIPA_DataFrame(hdd_ipa->hdd_ctx->pvosContext,
iface_context->tl_context, ipa_tx_desc->skb, interface_id);
if (skb) {
@@ -1485,11 +1476,11 @@ static void hdd_ipa_cleanup_iface(struct hdd_ipa_iface_context *iface_context)
hdd_ipa_clean_hdr(iface_context->adapter);
- vos_spin_lock_acquire(&iface_context->interface_lock);
+ adf_os_spin_lock_bh(&iface_context->interface_lock);
iface_context->adapter->ipa_context = NULL;
iface_context->adapter = NULL;
iface_context->tl_context = NULL;
- vos_spin_lock_release(&iface_context->interface_lock);
+ adf_os_spin_unlock_bh(&iface_context->interface_lock);
iface_context->ifa_address = 0;
}
@@ -1941,7 +1932,7 @@ VOS_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx)
iface_context->prod_client =
hdd_ipa_adapter_2_client[i].prod_client;
iface_context->iface_id = i;
- vos_spin_lock_init(&iface_context->interface_lock);
+ adf_os_spinlock_init(&iface_context->interface_lock);
}
ret = hdd_ipa_setup_rm(hdd_ipa);
@@ -1989,7 +1980,7 @@ VOS_STATUS hdd_ipa_cleanup(hdd_context_t *hdd_ctx)
/* destory the interface lock */
for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
iface_context = &hdd_ipa->iface_context[i];
- vos_spin_lock_destroy(&iface_context->interface_lock);
+ adf_os_spinlock_destroy(&iface_context->interface_lock);
}
hdd_ipa_debugfs_remove(hdd_ipa);