1 /* 2 * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: wlan_hdd_concurrency_matrix.c 22 * 23 * WLAN concurrency matrix functions 24 * 25 */ 26 27 #include "osif_sync.h" 28 #include <wlan_hdd_includes.h> 29 #include <linux/netdevice.h> 30 #include <linux/skbuff.h> 31 #include <linux/etherdevice.h> 32 #include <linux/if_ether.h> 33 #include <wlan_hdd_concurrency_matrix.h> 34 35 #define CDS_MAX_FEATURE_SET 8 36 #define MAX_CONCURRENT_MATRIX \ 37 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX 38 #define MATRIX_CONFIG_PARAM_SET_SIZE_MAX \ 39 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX 40 41 const struct nla_policy 42 wlan_hdd_get_concurrency_matrix_policy[MAX_CONCURRENT_MATRIX + 1] = { 43 [MATRIX_CONFIG_PARAM_SET_SIZE_MAX] = {.type = NLA_U32}, 44 }; 45 46 /** 47 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix 48 * @wiphy: pointer phy adapter 49 * @wdev: pointer to wireless device structure 50 * @data: pointer to data buffer 51 * @data_len: length of data 52 * 53 * This routine will give concurrency matrix 54 * 55 * Return: int status code 56 */ 57 static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)58 __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy, 59 struct wireless_dev *wdev, 60 const void *data, 61 int data_len) 62 { 63 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0}; 64 uint8_t i, feature_sets, max_feature_sets; 65 struct nlattr *tb[MAX_CONCURRENT_MATRIX + 1]; 66 struct sk_buff *reply_skb; 67 uint32_t skb_len = NLMSG_HDRLEN; 68 struct hdd_context *hdd_ctx = wiphy_priv(wiphy); 69 int ret; 70 71 hdd_enter_dev(wdev->netdev); 72 73 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) { 74 hdd_err("Command not allowed in FTM mode"); 75 return -EPERM; 76 } 77 78 ret = wlan_hdd_validate_context(hdd_ctx); 79 if (ret) 80 return ret; 81 82 if (wlan_cfg80211_nla_parse(tb, MAX_CONCURRENT_MATRIX, data, data_len, 83 wlan_hdd_get_concurrency_matrix_policy)) { 84 hdd_err("Invalid ATTR"); 85 return -EINVAL; 86 } 87 88 /* Parse and fetch max feature set */ 89 if (!tb[MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) { 90 hdd_err("Attr max feature set size failed"); 91 return -EINVAL; 92 } 93 max_feature_sets = nla_get_u32(tb[MATRIX_CONFIG_PARAM_SET_SIZE_MAX]); 94 hdd_debug("Max feature set size: %d", max_feature_sets); 95 96 /* Fill feature combination matrix */ 97 feature_sets = 0; 98 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA | 99 WIFI_FEATURE_P2P; 100 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA | 101 WIFI_FEATURE_NAN; 102 /* Add more feature combinations here */ 103 104 feature_sets = QDF_MIN(feature_sets, max_feature_sets); 105 hdd_debug("Number of feature sets: %d", feature_sets); 106 hdd_debug("Feature set matrix"); 107 for (i = 0; i < feature_sets; i++) 108 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]); 109 110 skb_len += sizeof(u32) + sizeof(u32) * feature_sets; 111 reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len); 112 if (!reply_skb) { 113 hdd_err("Feature set matrix: buffer alloc fail"); 114 return -ENOMEM; 115 } 116 117 if (nla_put_u32(reply_skb, 118 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE, 119 feature_sets) || 120 nla_put(reply_skb, 121 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET, 122 sizeof(u32) * feature_sets, 123 feature_set_matrix)) { 124 hdd_err("nla put fail"); 125 wlan_cfg80211_vendor_free_skb(reply_skb); 126 return -EINVAL; 127 } 128 return wlan_cfg80211_vendor_cmd_reply(reply_skb); 129 } 130 131 #undef MAX_CONCURRENT_MATRIX 132 #undef MATRIX_CONFIG_PARAM_SET_SIZE_MAX 133 wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)134 int wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy, 135 struct wireless_dev *wdev, 136 const void *data, 137 int data_len) 138 { 139 struct osif_psoc_sync *psoc_sync; 140 int errno; 141 142 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync); 143 if (errno) 144 return errno; 145 146 errno = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev, 147 data, data_len); 148 149 osif_psoc_sync_op_stop(psoc_sync); 150 151 return errno; 152 } 153 154