prima: Support for get_concurrency_matrix
Provide the driver support to return concurrency matrix
where each index represents a combination of features which work
concurrently.
Change-Id: Ia929b139f4cf61bc546af23a9b6ee54944e55ea9
CRs-Fixed: 746842
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 8d28350..f6f5a19 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -143,6 +143,7 @@
#endif
#define HDD_CHANNEL_14 14
+#define WLAN_HDD_MAX_FEATURE_SET 8
#ifdef WLAN_FEATURE_LINK_LAYER_STATS
/*
@@ -4452,6 +4453,87 @@
return -EINVAL;
}
+static int
+wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ void *data, int data_len)
+{
+ uint32_t feature_set_matrix[WLAN_HDD_MAX_FEATURE_SET] = {0};
+ uint8_t i, feature_sets, max_feature_sets;
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
+ struct sk_buff *reply_skb;
+
+ ENTER();
+
+ if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
+ data, data_len, NULL)) {
+ hddLog(LOGE, FL("Invalid ATTR"));
+ return -EINVAL;
+ }
+
+ /* Parse and fetch max feature set */
+ if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
+ hddLog(LOGE, FL("Attr max feature set size failed"));
+ return -EINVAL;
+ }
+ max_feature_sets = nla_get_u32(
+ tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
+ hddLog(LOG1, FL("Max feature set size (%d)"), max_feature_sets);
+
+ /* Fill feature combination matrix */
+ feature_sets = 0;
+ if (feature_sets >= WLAN_HDD_MAX_FEATURE_SET) goto max_buffer_err;
+ feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
+ WIFI_FEATURE_P2P;
+
+ if (feature_sets >= WLAN_HDD_MAX_FEATURE_SET) goto max_buffer_err;
+ feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
+ WIFI_FEATURE_SOFT_AP;
+
+ if (feature_sets >= WLAN_HDD_MAX_FEATURE_SET) goto max_buffer_err;
+ feature_set_matrix[feature_sets++] = WIFI_FEATURE_P2P |
+ WIFI_FEATURE_SOFT_AP;
+
+ if (feature_sets >= WLAN_HDD_MAX_FEATURE_SET) goto max_buffer_err;
+ feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
+ WIFI_FEATURE_SOFT_AP |
+ WIFI_FEATURE_P2P;
+
+ /* Add more feature combinations here */
+
+ feature_sets = VOS_MIN(feature_sets, max_feature_sets);
+ hddLog(LOG1, FL("Number of feature sets (%d)"), feature_sets);
+ hddLog(LOG1, "Feature set matrix");
+ for (i = 0; i < feature_sets; i++)
+ hddLog(LOG1, "[%d] 0x%02X", i, feature_set_matrix[i]);
+
+ reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
+ sizeof(u32) * feature_sets +
+ NLMSG_HDRLEN);
+
+ if (reply_skb) {
+ if (nla_put_u32(reply_skb,
+ QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
+ feature_sets) ||
+ nla_put(reply_skb,
+ QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
+ sizeof(u32) * feature_sets, feature_set_matrix)) {
+ hddLog(LOGE, FL("nla put fail"));
+ kfree_skb(reply_skb);
+ return -EINVAL;
+ }
+
+ return cfg80211_vendor_cmd_reply(reply_skb);
+ }
+ hddLog(LOGE, FL("Feature set matrix: buffer alloc fail"));
+ return -ENOMEM;
+
+max_buffer_err:
+ hddLog(LOGE, FL("Feature set max buffer size reached. feature_sets(%d) max(%d)"),
+ feature_sets, WLAN_HDD_MAX_FEATURE_SET);
+ return -EINVAL;
+}
+
static const struct nla_policy
wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
+1] =
@@ -4718,6 +4800,13 @@
WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = wlan_hdd_cfg80211_set_spoofed_mac_oui
},
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = wlan_hdd_cfg80211_get_concurrency_matrix
+ },
};
/* vendor specific events */