summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRajeev Kumar <rajekuma@qca.qualcomm.com>2015-08-28 13:07:21 -0700
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2015-08-31 14:14:11 +0530
commitfc0d5d08359b9849df2a9adb29c605c20b9bf10c (patch)
treec32c702943774ae00f7e71330cdce0884212b881
parentff56c623774415815feb0ba3c45d94d318912838 (diff)
qcacld-2.0: Fix race condition in tx desc free count manipulation
- Protect TX descriptor free credits count under tx mutex - Add debug log to dump total credit and free credit count if bus suspend fails because of pending tx Change-Id: I383e19b8c56edac487e3e0d8763e1212f03b7934 CRs-Fixed: 898742
-rw-r--r--CORE/CLD_TXRX/TXRX/ol_tx_send.c2
-rw-r--r--CORE/CLD_TXRX/TXRX/ol_txrx.c23
-rw-r--r--CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h4
-rw-r--r--CORE/SERVICES/HIF/PCIe/if_pci.c1
4 files changed, 28 insertions, 2 deletions
diff --git a/CORE/CLD_TXRX/TXRX/ol_tx_send.c b/CORE/CLD_TXRX/TXRX/ol_tx_send.c
index 28b3b8a458de..320252a852e3 100644
--- a/CORE/CLD_TXRX/TXRX/ol_tx_send.c
+++ b/CORE/CLD_TXRX/TXRX/ol_tx_send.c
@@ -577,8 +577,8 @@ ol_tx_completion_handler(
adf_os_spin_lock(&pdev->tx_mutex);
tx_desc_last->next = pdev->tx_desc.freelist;
pdev->tx_desc.freelist = lcl_freelist;
- adf_os_spin_unlock(&pdev->tx_mutex);
pdev->tx_desc.num_free += (u_int16_t) num_msdus;
+ adf_os_spin_unlock(&pdev->tx_mutex);
} else {
ol_tx_desc_frame_list_free(pdev, &tx_descs, status != htt_tx_status_ok);
}
diff --git a/CORE/CLD_TXRX/TXRX/ol_txrx.c b/CORE/CLD_TXRX/TXRX/ol_txrx.c
index edbe624a2839..88f43de627cf 100644
--- a/CORE/CLD_TXRX/TXRX/ol_txrx.c
+++ b/CORE/CLD_TXRX/TXRX/ol_txrx.c
@@ -1756,6 +1756,29 @@ ol_txrx_peer_find_by_addr(struct ol_txrx_pdev_t *pdev, u_int8_t *peer_mac_addr)
return peer;
}
+/**
+ * ol_txrx_dump_tx_desc() - dump tx desc info
+ * @pdev_handle: Pointer to pdev handle
+ *
+ * Return: none
+ */
+void ol_txrx_dump_tx_desc(ol_txrx_pdev_handle pdev_handle)
+{
+ struct ol_txrx_pdev_t *pdev = pdev_handle;
+ int total;
+
+ if (ol_cfg_is_high_latency(pdev->ctrl_pdev))
+ total = adf_os_atomic_read(&pdev->orig_target_tx_credit);
+ else
+ total = ol_cfg_target_tx_credit(pdev->ctrl_pdev);
+
+ TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
+ "Total tx credits %d free_credits %d",
+ total, pdev->tx_desc.num_free);
+
+ return;
+}
+
int
ol_txrx_get_tx_pending(ol_txrx_pdev_handle pdev_handle)
{
diff --git a/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h b/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h
index f1ac87dfb17f..ce59ca18ff6f 100644
--- a/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h
+++ b/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -678,6 +678,8 @@ int
ol_txrx_get_tx_pending(
ol_txrx_pdev_handle pdev);
+void ol_txrx_dump_tx_desc(ol_txrx_pdev_handle pdev);
+
/**
* @brief Discard all tx frames that are pending in txrx.
* @details
diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.c b/CORE/SERVICES/HIF/PCIe/if_pci.c
index 71cfd543e46e..f9ad96dff4ef 100644
--- a/CORE/SERVICES/HIF/PCIe/if_pci.c
+++ b/CORE/SERVICES/HIF/PCIe/if_pci.c
@@ -2220,6 +2220,7 @@ __hif_pci_suspend(struct pci_dev *pdev, pm_message_t state, bool runtime_pm)
msleep(OL_ATH_TX_DRAIN_WAIT_DELAY);
if (++tx_drain_wait_cnt > OL_ATH_TX_DRAIN_WAIT_CNT) {
printk("%s: tx frames are pending\n", __func__);
+ ol_txrx_dump_tx_desc(txrx_pdev);
goto out;
}
}