summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYun Park <yunp@codeaurora.org>2016-08-17 16:26:54 -0700
committerqcabuildsw <qcabuildsw@localhost>2016-12-08 13:53:20 -0800
commitfc1b5c47298a3f28caeb4b61072e994619572f84 (patch)
treeae2125b7e6bbd90b13601419eaba1e8590021a83
parent97e30fa8b711808e3f834eb5076defd4d3d9751f (diff)
qcacld-3.0: IPA uC: Round down Tx/Rx buffer count to nearest power of two
qcacld-2.0 to qcacld-3.0 propagation In certain situation, allocated Tx buffer count could be an arbitrary number, so not power of two. This could violate F/W ring buffer count requirement. If allocated Tx buffer count is not power of two, round down it to the nearest power of two. The same change is also applicable for INI parameters IpaUcTxBufCount and IpaUcRxIndRingCount. Change-Id: I7c119886a669c79adbc7bd9b2c1c1d93de41cf72 CRs-Fixed: 973723
-rw-r--r--core/dp/htt/htt_tx.c72
-rw-r--r--core/hdd/inc/wlan_hdd_cfg.h2
-rw-r--r--core/hdd/src/wlan_hdd_main.c30
3 files changed, 101 insertions, 3 deletions
diff --git a/core/dp/htt/htt_tx.c b/core/dp/htt/htt_tx.c
index a4ca82f154ef..653c838aff39 100644
--- a/core/dp/htt/htt_tx.c
+++ b/core/dp/htt/htt_tx.c
@@ -51,6 +51,8 @@
#include <ol_txrx_internal.h>
#include <htt_internal.h>
+#include <cds_utils.h>
+
/* IPA Micro controler TX data packet HTT Header Preset */
/* 31 | 30 29 | 28 | 27 | 26 22 | 21 16 | 15 13 | 12 8 | 7 0
*----------------------------------------------------------------------------
@@ -1065,10 +1067,12 @@ static int htt_tx_ipa_uc_wdi_tx_buf_alloc(struct htt_pdev_t *pdev,
unsigned int uc_tx_partition_base)
{
unsigned int tx_buffer_count;
+ unsigned int tx_buffer_count_pwr2;
void *buffer_vaddr;
qdf_dma_addr_t buffer_paddr;
uint32_t *header_ptr;
qdf_dma_addr_t *ring_vaddr;
+ uint16_t idx;
ring_vaddr = (qdf_dma_addr_t *)pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr;
/* Allocate TX buffers as many as possible */
@@ -1124,7 +1128,38 @@ static int htt_tx_ipa_uc_wdi_tx_buf_alloc(struct htt_pdev_t *pdev,
ring_vaddr++;
}
- return tx_buffer_count;
+
+ /*
+ * Tx complete ring buffer count should be power of 2.
+ * So, allocated Tx buffer count should be one less than ring buffer
+ * size.
+ */
+ tx_buffer_count_pwr2 = qdf_rounddown_pow_of_two(tx_buffer_count + 1)
+ - 1;
+ if (tx_buffer_count > tx_buffer_count_pwr2) {
+ qdf_print(
+ "%s: Allocated Tx buffer count %d is rounded down to %d",
+ __func__, tx_buffer_count, tx_buffer_count_pwr2);
+
+ /* Free over allocated buffers below power of 2 */
+ for (idx = tx_buffer_count_pwr2; idx < tx_buffer_count; idx++) {
+ if (pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg[idx]) {
+ qdf_mem_free_consistent(
+ pdev->osdev, pdev->osdev->dev,
+ ol_cfg_ipa_uc_tx_buf_size(pdev->ctrl_pdev),
+ pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg[idx],
+ pdev->ipa_uc_tx_rsc.paddr_strg[idx], 0);
+ }
+ }
+ }
+
+ if (tx_buffer_count_pwr2 < 0) {
+ qdf_print("%s: Failed to round down Tx buffer count %d",
+ __func__, tx_buffer_count_pwr2);
+ tx_buffer_count_pwr2 = 0;
+ }
+
+ return tx_buffer_count_pwr2;
}
#else
static int htt_tx_ipa_uc_wdi_tx_buf_alloc(struct htt_pdev_t *pdev,
@@ -1133,10 +1168,12 @@ static int htt_tx_ipa_uc_wdi_tx_buf_alloc(struct htt_pdev_t *pdev,
unsigned int uc_tx_partition_base)
{
unsigned int tx_buffer_count;
+ unsigned int tx_buffer_count_pwr2;
qdf_nbuf_t buffer_vaddr;
qdf_dma_addr_t buffer_paddr;
uint32_t *header_ptr;
uint32_t *ring_vaddr;
+ uint16_t idx;
ring_vaddr = pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr;
/* Allocate TX buffers as many as possible */
@@ -1181,7 +1218,38 @@ static int htt_tx_ipa_uc_wdi_tx_buf_alloc(struct htt_pdev_t *pdev,
ring_vaddr++;
}
- return tx_buffer_count;
+
+ /*
+ * Tx complete ring buffer count should be power of 2.
+ * So, allocated Tx buffer count should be one less than ring buffer
+ * size.
+ */
+ tx_buffer_count_pwr2 = qdf_rounddown_pow_of_two(tx_buffer_count + 1)
+ - 1;
+ if (tx_buffer_count > tx_buffer_count_pwr2) {
+ qdf_print(
+ "%s: Allocated Tx buffer count %d is rounded down to %d",
+ __func__, tx_buffer_count, tx_buffer_count_pwr2);
+
+ /* Free over allocated buffers below power of 2 */
+ for (idx = tx_buffer_count_pwr2; idx < tx_buffer_count; idx++) {
+ if (pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg[idx]) {
+ qdf_mem_free_consistent(
+ pdev->osdev, pdev->osdev->dev,
+ ol_cfg_ipa_uc_tx_buf_size(pdev->ctrl_pdev),
+ pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg[idx],
+ pdev->ipa_uc_tx_rsc.paddr_strg[idx], 0);
+ }
+ }
+ }
+
+ if (tx_buffer_count_pwr2 < 0) {
+ qdf_print("%s: Failed to round down Tx buffer count %d",
+ __func__, tx_buffer_count_pwr2);
+ tx_buffer_count_pwr2 = 0;
+ }
+
+ return tx_buffer_count_pwr2;
}
#endif
diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h
index 492682348f46..0188a1ea3836 100644
--- a/core/hdd/inc/wlan_hdd_cfg.h
+++ b/core/hdd/inc/wlan_hdd_cfg.h
@@ -2544,6 +2544,7 @@ typedef enum {
#define CFG_ROAMING_OFFLOAD_DEFAULT (1)
#endif
+/* IpaUcTxBufCount should be power of 2 */
#define CFG_IPA_UC_TX_BUF_COUNT_NAME "IpaUcTxBufCount"
#define CFG_IPA_UC_TX_BUF_COUNT_MIN (0)
#define CFG_IPA_UC_TX_BUF_COUNT_MAX (2048)
@@ -2554,6 +2555,7 @@ typedef enum {
#define CFG_IPA_UC_TX_BUF_SIZE_MAX (4096)
#define CFG_IPA_UC_TX_BUF_SIZE_DEFAULT (2048)
+/* IpaUcRxIndRingCount should be power of 2 */
#define CFG_IPA_UC_RX_IND_RING_COUNT_NAME "IpaUcRxIndRingCount"
#define CFG_IPA_UC_RX_IND_RING_COUNT_MIN (0)
#define CFG_IPA_UC_RX_IND_RING_COUNT_MAX (2048)
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index a0304a4d47f8..0b31804673be 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -7015,10 +7015,38 @@ static int hdd_update_cds_config(hdd_context_t *hdd_ctx)
/* IPA micro controller data path offload resource config item */
cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
+ if (!is_power_of_2(hdd_ctx->config->IpaUcTxBufCount)) {
+ /* IpaUcTxBufCount should be power of 2 */
+ hdd_err("Round down IpaUcTxBufCount %d to nearest power of 2",
+ hdd_ctx->config->IpaUcTxBufCount);
+ hdd_ctx->config->IpaUcTxBufCount =
+ rounddown_pow_of_two(
+ hdd_ctx->config->IpaUcTxBufCount);
+ if (!hdd_ctx->config->IpaUcTxBufCount) {
+ hdd_err("Failed to round down IpaUcTxBufCount");
+ return -EINVAL;
+ }
+ hdd_err("IpaUcTxBufCount rounded down to %d",
+ hdd_ctx->config->IpaUcTxBufCount);
+ }
cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
+ if (!is_power_of_2(hdd_ctx->config->IpaUcRxIndRingCount)) {
+ /* IpaUcRxIndRingCount should be power of 2 */
+ hdd_err("Round down IpaUcRxIndRingCount %d to nearest power of 2",
+ hdd_ctx->config->IpaUcRxIndRingCount);
+ hdd_ctx->config->IpaUcRxIndRingCount =
+ rounddown_pow_of_two(
+ hdd_ctx->config->IpaUcRxIndRingCount);
+ if (!hdd_ctx->config->IpaUcRxIndRingCount) {
+ hdd_err("Failed to round down IpaUcRxIndRingCount");
+ return -EINVAL;
+ }
+ hdd_err("IpaUcRxIndRingCount rounded down to %d",
+ hdd_ctx->config->IpaUcRxIndRingCount);
+ }
cds_cfg->uc_rxind_ringcount =
- hdd_ctx->config->IpaUcRxIndRingCount;
+ hdd_ctx->config->IpaUcRxIndRingCount;
cds_cfg->uc_tx_partition_base =
hdd_ctx->config->IpaUcTxPartitionBase;
cds_cfg->max_scan = hdd_ctx->config->max_scan_count;