diff options
| author | Himanshu Agarwal <himanaga@qti.qualcomm.com> | 2016-05-19 21:23:27 +0530 |
|---|---|---|
| committer | Anjaneedevi Kapparapu <akappa@codeaurora.org> | 2016-05-30 14:51:47 +0530 |
| commit | 6dfd940d40ca639827253331b23e34401e237fa5 (patch) | |
| tree | c3c1b0a935813b1e051dd3e902f35be07409e970 | |
| parent | 0f628694a6cfb2d7ec23f7c9bece9b2067fbe1e3 (diff) | |
qcacld-2.0: Do runtime resume when a packet comes to fw paused tx queues
Whenever queues are paused by fw and the driver goes in runtime suspend
mode, it is a kind of deadlock condition as for HOST to receive unpause
event from fw, it has to come out of WOW mode but fw does not wakeup the
HOST for unpause event.
Add logic to do runtime pm resume when vdev tx ll queues are paused
by fw and the driver is in runtime suspend mode and then a tx packet
comes to txrx layer from networking stack. Also, add logic to prevent
the driver from going in runtime suspend mode if the tx ll queues are
paused by fw and all the queues are not empty.
Change-Id: Ie9a0c88cb76e4bfebcce16f5e250612330dae893
CRs-Fixed: 1018401
| -rw-r--r-- | CORE/CLD_TXRX/TXRX/ol_tx.c | 8 | ||||
| -rw-r--r-- | CORE/CLD_TXRX/TXRX/ol_txrx.c | 25 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h | 13 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/PCIe/if_pci.c | 6 |
4 files changed, 50 insertions, 2 deletions
diff --git a/CORE/CLD_TXRX/TXRX/ol_tx.c b/CORE/CLD_TXRX/TXRX/ol_tx.c index dc3132f737f7..abcf04cccb5e 100644 --- a/CORE/CLD_TXRX/TXRX/ol_tx.c +++ b/CORE/CLD_TXRX/TXRX/ol_tx.c @@ -51,6 +51,7 @@ /* internal header files relevant only for specific systems (Pronto) */ #include <ol_txrx_encap.h> /* OL_TX_ENCAP, etc */ +#include "vos_lock.h" #define ol_tx_prepare_ll(tx_desc, vdev, msdu, msdu_info) \ do { \ @@ -214,6 +215,13 @@ ol_tx_vdev_pause_queue_append( { adf_os_spin_lock_bh(&vdev->ll_pause.mutex); + if (vdev->ll_pause.paused_reason & + OL_TXQ_PAUSE_REASON_FW) { + if ((!vdev->ll_pause.txq.depth) && + msdu_list) + vos_request_runtime_pm_resume(); + } + while (msdu_list && vdev->ll_pause.txq.depth < vdev->ll_pause.max_q_depth) { diff --git a/CORE/CLD_TXRX/TXRX/ol_txrx.c b/CORE/CLD_TXRX/TXRX/ol_txrx.c index 2b8dbed9411f..f61d6ed5b87e 100644 --- a/CORE/CLD_TXRX/TXRX/ol_txrx.c +++ b/CORE/CLD_TXRX/TXRX/ol_txrx.c @@ -1897,6 +1897,31 @@ ol_txrx_get_tx_pending(ol_txrx_pdev_handle pdev_handle) return (total - pdev->tx_desc.num_free); } +/* + * ol_txrx_get_queue_status() - get vdev tx ll queues status + * pdev_handle: pdev handle + * + * Return: A_OK - if all queues are empty + * A_ERROR - if any queue is not empty + */ +A_STATUS +ol_txrx_get_queue_status(ol_txrx_pdev_handle pdev_handle) +{ + struct ol_txrx_pdev_t *pdev = (ol_txrx_pdev_handle)pdev_handle; + struct ol_txrx_vdev_t *vdev; + A_STATUS status = A_OK; + + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + if ((vdev->ll_pause.paused_reason & OL_TXQ_PAUSE_REASON_FW) && + vdev->ll_pause.txq.depth) { + status = A_ERROR; + break; + } + } + + return status; +} + void ol_txrx_discard_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 5ee07f95bc05..260c7b70b65f 100644 --- a/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h +++ b/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h @@ -766,6 +766,19 @@ int ol_txrx_get_tx_pending( ol_txrx_pdev_handle pdev); +/** + * ol_txrx_get_queue_status() - Get the status of tx queues. + * @pdev: the data physical device object + * + * This api is used while trying to go in suspend mode. + * + * Return - status: A_OK - if all queues are empty + * A_ERROR - if any queue is not empty + */ +A_STATUS +ol_txrx_get_queue_status( + ol_txrx_pdev_handle pdev); + void ol_txrx_dump_tx_desc(ol_txrx_pdev_handle pdev); /** diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.c b/CORE/SERVICES/HIF/PCIe/if_pci.c index 7f78e06f67f1..2b9131afd8eb 100644 --- a/CORE/SERVICES/HIF/PCIe/if_pci.c +++ b/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -1160,7 +1160,8 @@ static int __hif_pci_runtime_suspend(struct pci_dev *pdev) goto out; } - if ((test = ol_txrx_get_tx_pending(txrx_pdev))) { + if ((test = ol_txrx_get_tx_pending(txrx_pdev)) || + ol_txrx_get_queue_status(txrx_pdev)) { pr_err("%s: txrx pending(%d), get: %u, put: %u\n", __func__, test, sc->pm_stats.runtime_get, @@ -2647,7 +2648,8 @@ __hif_pci_suspend(struct pci_dev *pdev, pm_message_t state, bool runtime_pm) goto out; } /* Wait for pending tx completion */ - while (ol_txrx_get_tx_pending(txrx_pdev)) { + while (ol_txrx_get_tx_pending(txrx_pdev) || + ol_txrx_get_queue_status(txrx_pdev)) { 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__); |
