summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohit Khanna <mkhanna@qca.qualcomm.com>2015-10-14 20:21:05 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2015-10-21 00:24:47 -0700
commit80f4dc4c08b001ff9180a18cd4ceeb4dbf1cc6bd (patch)
tree91c07556f6c4a3963f9c0018bb01c5c9217bf41c
parentb34e0e2ac99060c00b64daf183b4210b3d0d6b83 (diff)
qcacld-2.0: allow rps cpu map to be read from ini
- Currently wlan driver only sends WLAN_SVC_RPS_ENABLE_IND message along with the interface name to cnss-daemon. This change allows wlan driver to send rps cpu mask from the ini file (for each rx queue) to be sent along with this message. - Enable RPS mask as "e e e e" by default in WLAN ini file. Change-Id: I869d4dd70533eefbff03ed97976700d4e0e75c1d CRs-Fixed: 919192
-rw-r--r--CORE/HDD/inc/wlan_hdd_cfg.h46
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg.c54
-rw-r--r--CORE/HDD/src/wlan_hdd_dp_utils.c41
-rw-r--r--CORE/SVC/external/wlan_nlink_common.h31
-rwxr-xr-xfirmware_bin/WCNSS_qcom_cfg.ini6
5 files changed, 171 insertions, 7 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index 41dabfd6cf15..c61bb22f3432 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -2532,6 +2532,47 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */
#define CFG_RX_HANDLE_DEFAULT (WLAN_HDD_RX_HANDLE_RX_THREAD)
#endif /* MDM_PLATFORM */
+/* List of RPS CPU maps for different rx queues registered by WLAN driver
+ * Ref - Kernel/Documentation/networking/scaling.txt
+ * RPS CPU map for a particular RX queue, selects CPU(s) for bottom half
+ * processing of RX packets. For example, for a system with 4 CPUs,
+ * 0xe: Use CPU1 - CPU3 and donot use CPU0.
+ * 0x0: RPS is disabled, packets are processed on the interrupting CPU.
+.*
+ * WLAN driver registers NUM_TX_QUEUES queues for tx and rx each during
+ * alloc_netdev_mq. Hence, we need to have a cpu mask for each of the rx queues.
+ *
+ * For example, if the NUM_TX_QUEUES is 4, a sample WLAN ini entry may look like
+ * rpsRxQueueCpuMapList=a b c d
+ * For a 4 CPU system (CPU0 - CPU3), this implies:
+ * 0xa - (1010) use CPU1, CPU3 for rx queue 0
+ * 0xb - (1011) use CPU0, CPU1 and CPU3 for rx queue 1
+ * 0xc - (1100) use CPU2, CPU3 for rx queue 2
+ * 0xd - (1101) use CPU0, CPU2 and CPU3 for rx queue 3
+
+ * In practice, we may want to avoid the cores which are heavily loaded.
+ */
+
+/* Name of the ini file entry to specify RPS map for different RX queus */
+#define CFG_RPS_RX_QUEUE_CPU_MAP_LIST_NAME "rpsRxQueueCpuMapList"
+
+/* Default value of rpsRxQueueCpuMapList. Different platforms may have
+ * different configurations for NUM_TX_QUEUES and # of cpus, and will need to
+ * configure an appropriate value via ini file. Setting default value to 'e' to
+ * avoid use of CPU0 (since its heavily used by other system processes) by rx
+ * queue 0, which is currently being used for rx packet processing.
+ */
+#define CFG_RPS_RX_QUEUE_CPU_MAP_LIST_DEFAULT "e"
+
+/* Maximum length of string used to hold a list of cpu maps for various rx
+ * queues. Considering a 16 core system with 5 rx queues, a RPS CPU map
+ * list may look like -
+ * rpsRxQueueCpuMapList = ffff ffff ffff ffff ffff
+ * (all 5 rx queues can be processed on all 16 cores)
+ * max string len = 24 + 1(for '\0'). Considering 30 to be on safe side.
+ */
+#define CFG_RPS_RX_QUEUE_CPU_MAP_LIST_LEN 30
+
/* SAR Thermal limit values for 2g and 5g */
#define CFG_SET_TXPOWER_LIMIT2G_NAME "TxPower2g"
@@ -3762,6 +3803,7 @@ typedef struct
v_U32_t TxPower5g;
v_U32_t gEnableDebugLog;
v_U8_t rxhandle;
+ uint8_t cpu_map_list[CFG_RPS_RX_QUEUE_CPU_MAP_LIST_LEN];
v_BOOL_t fDfsPhyerrFilterOffload;
v_U8_t gSapPreferredChanLocation;
v_U8_t gDisableDfsJapanW53;
@@ -4098,6 +4140,10 @@ VOS_STATUS hdd_string_to_u8_array( char *str, tANI_U8 *intArray, tANI_U8 *len,
VOS_STATUS hdd_hex_string_to_u8_array(char *str, uint8_t *array, uint8_t *len,
uint8_t array_max_len);
+VOS_STATUS hdd_hex_string_to_u16_array(char *str,
+ uint16_t *int_array, uint8_t *len, uint8_t int_array_max_len);
+
+
#ifdef MDNS_OFFLOAD
VOS_STATUS hdd_string_to_string_array(char *data, uint8_t *datalist,
char separator, uint8_t *num_entries,
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index 4dd0157b8777..3073955e9066 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -3245,6 +3245,12 @@ REG_TABLE_ENTRY g_registry_table[] =
CFG_RX_HANDLE_DEFAULT,
CFG_RX_HANDLE_MIN,
CFG_RX_HANDLE_MAX),
+
+ REG_VARIABLE_STRING( CFG_RPS_RX_QUEUE_CPU_MAP_LIST_NAME, WLAN_PARAM_String,
+ hdd_config_t, cpu_map_list,
+ VAR_FLAGS_OPTIONAL,
+ (void *)CFG_RPS_RX_QUEUE_CPU_MAP_LIST_DEFAULT ),
+
REG_VARIABLE( CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_NAME, WLAN_PARAM_Integer,
hdd_config_t, fDfsPhyerrFilterOffload,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
@@ -5644,6 +5650,54 @@ VOS_STATUS hdd_string_to_u8_array(char *str, uint8_t *array,
array_max_len, false);
}
+/**
+ * hdd_hex_string_to_u16_array() - convert a hex string to a uint16 array
+ * @str: input string
+ * @int_array: pointer to input array of type uint16
+ * @len: pointer to number of elements which the function adds to the array
+ * @int_array_max_len: maximum number of elements in input uint16 array
+ *
+ * This function is used to convert a space separated hex string to an array of
+ * uint16_t. For example, an input string str = "a b c d" would be converted to
+ * a unint16 array, int_array = {0xa, 0xb, 0xc, 0xd}, *len = 4.
+ * This assumes that input value int_array_max_len >= 4.
+ *
+ * Return: VOS_STATUS_SUCCESS - if the conversion is successful
+ * non zero value - if the conversion is a failure
+ */
+VOS_STATUS hdd_hex_string_to_u16_array(char *str,
+ uint16_t *int_array, uint8_t *len, uint8_t int_array_max_len)
+{
+ char *s = str;
+ int val = 0;
+ if (str == NULL || int_array == NULL || len == NULL)
+ return VOS_STATUS_E_INVAL;
+
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("str %p intArray %p intArrayMaxLen %d"),
+ s, int_array, int_array_max_len);
+
+ *len = 0;
+
+ while ((s != NULL) && (*len < int_array_max_len)) {
+ /*
+ * Increment length only if sscanf successfully extracted one
+ * element. Any other return value means error. Ignore it.
+ */
+ if (sscanf(s, "%x", &val) == 1) {
+ int_array[*len] = (uint16_t) val;
+ hddLog(VOS_TRACE_LEVEL_DEBUG,
+ FL("s %p val %x intArray[%d]=0x%x"),
+ s, val, *len, int_array[*len]);
+ *len += 1;
+ }
+ s = strpbrk(s, " ");
+ if (s)
+ s++;
+ }
+ return VOS_STATUS_SUCCESS;
+}
+
#ifdef MDNS_OFFLOAD
VOS_STATUS hdd_string_to_string_array(char *data, uint8_t *datalist,
char separator, uint8_t *num_entries,
diff --git a/CORE/HDD/src/wlan_hdd_dp_utils.c b/CORE/HDD/src/wlan_hdd_dp_utils.c
index 69cbf2a47617..16a153151295 100644
--- a/CORE/HDD/src/wlan_hdd_dp_utils.c
+++ b/CORE/HDD/src/wlan_hdd_dp_utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -40,6 +40,7 @@
----------------------------------------------------------------------------*/
#include <wlan_hdd_dp_utils.h>
#include <wlan_hdd_main.h>
+#include <sirDebug.h>
/**-----------------------------------------------------------------------------
Preprocessor definitions and constants
@@ -234,17 +235,49 @@ VOS_STATUS hdd_string_to_hex( char *pSrcMac, int length, char *pDescMac )
*/
void hdd_dp_util_send_rps_ind(hdd_context_t *hdd_ctxt)
{
+ int i = 0;
+ uint8_t cpu_map_list_len = 0;
hdd_adapter_t *adapter;
hdd_adapter_list_node_t *adapter_node, *next;
VOS_STATUS status = VOS_STATUS_SUCCESS;
+ struct wlan_rps_data rps_data;
+
+ rps_data.num_queues = NUM_TX_QUEUES;
+
+ hddLog(LOG1, FL("cpu_map_list '%s'"), hdd_ctxt->cfg_ini->cpu_map_list);
+
+ /* in case no cpu map list is provided, simply return */
+ if (!strlen(hdd_ctxt->cfg_ini->cpu_map_list)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("no cpu map list found"));
+ return;
+ }
+
+ if (VOS_STATUS_SUCCESS !=
+ hdd_hex_string_to_u16_array(hdd_ctxt->cfg_ini->cpu_map_list,
+ rps_data.cpu_map_list,
+ &cpu_map_list_len,
+ WLAN_SVC_IFACE_NUM_QUEUES)) {
+ return;
+ }
+
+ rps_data.num_queues =
+ (cpu_map_list_len < rps_data.num_queues) ?
+ cpu_map_list_len : rps_data.num_queues;
+
+ for (i = 0; i < rps_data.num_queues; i++) {
+ hddLog(LOG1, FL("cpu_map_list[%d] = 0x%x"),
+ i, rps_data.cpu_map_list[i]);
+ }
status = hdd_get_front_adapter (hdd_ctxt, &adapter_node);
while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) {
adapter = adapter_node->pAdapter;
- if (NULL != adapter)
+ if (NULL != adapter) {
+ strlcpy(rps_data.ifname, adapter->dev->name,
+ sizeof(rps_data.ifname));
wlan_hdd_send_svc_nlink_msg(WLAN_SVC_RPS_ENABLE_IND,
- (void *)adapter->dev->name,
- strlen(adapter->dev->name));
+ &rps_data, sizeof(rps_data));
+ }
status = hdd_get_next_adapter (hdd_ctxt, adapter_node, &next);
adapter_node = next;
}
diff --git a/CORE/SVC/external/wlan_nlink_common.h b/CORE/SVC/external/wlan_nlink_common.h
index 6c1bd32aa9c7..8bf9f87e3b10 100644
--- a/CORE/SVC/external/wlan_nlink_common.h
+++ b/CORE/SVC/external/wlan_nlink_common.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -38,7 +38,9 @@
#define WLAN_NLINK_COMMON_H__
#include <linux/netlink.h>
-
+#ifdef QCA_FEATURE_RPS
+#include <linux/if.h>
+#endif
/*---------------------------------------------------------------------------
* External Functions
*-------------------------------------------------------------------------*/
@@ -103,6 +105,12 @@
#define WLAN_SVC_MAX_NUM_CHAN 128
#define WLAN_SVC_COUNTRY_CODE_LEN 3
+/*
+ * Maximim number of queues supported by WLAN driver. Setting an upper
+ * limit. Actual number of queues may be smaller than this value.
+ */
+#define WLAN_SVC_IFACE_NUM_QUEUES 6
+
// Event data for WLAN_BTC_QUERY_STATE_RSP & WLAN_STA_ASSOC_DONE_IND
typedef struct
{
@@ -155,6 +163,25 @@ struct wlan_version_data {
char fw_version[WLAN_SVC_MAX_STR_LEN];
};
+#ifdef QCA_FEATURE_RPS
+/**
+ * struct wlan_rps_data - structure to send RPS info to cnss-daemon
+ * @ifname: interface name for which the RPS data belongs to
+ * @num_queues: number of rx queues for which RPS data is being sent
+ * @cpu_map_list: array of cpu maps for different rx queues supported by
+ * the wlan driver
+ *
+ * The structure specifies the format of data exchanged between wlan
+ * driver and cnss-daemon. On receipt of the data, cnss-daemon is expected
+ * to apply the 'cpu_map' for each rx queue belonging to the interface 'ifname'
+ */
+struct wlan_rps_data {
+ char ifname[IFNAMSIZ];
+ uint16_t num_queues;
+ uint16_t cpu_map_list[WLAN_SVC_IFACE_NUM_QUEUES];
+};
+#endif
+
struct wlan_dfs_info {
uint16_t channel;
uint8_t country_code[WLAN_SVC_COUNTRY_CODE_LEN];
diff --git a/firmware_bin/WCNSS_qcom_cfg.ini b/firmware_bin/WCNSS_qcom_cfg.ini
index f8686eeaf31a..78f539463b24 100755
--- a/firmware_bin/WCNSS_qcom_cfg.ini
+++ b/firmware_bin/WCNSS_qcom_cfg.ini
@@ -499,7 +499,11 @@ isP2pDeviceAddrAdministrated=1
# 0: no rx thread, no RPS, for MDM
# 1: RX thread
# 2: RPS
-rxhandle=1
+rxhandle=2
+
+# Set RPS CPU MAP as 0xe for the 4 RX queues
+# This allows use of CPU1-CPU3 but not CPU0 for 4 RX queues
+rpsRxQueueCpuMapList=e e e e
# Set Thermal Power limit
TxPower2g=10