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