blob: fe2755fc18a441b23c2cd91887c55562ae19d042 [file] [log] [blame]
Jiani Liua5f17222019-03-04 16:22:33 +08001/*
2 * Copyright (c) 2019 The Linux Foundation. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/**
20 * DOC: wlan_hdd_coex_config.c
21 *
22 * The implementation of coex configuration
23 *
24 */
25
26#include "wlan_hdd_main.h"
27#include "wmi_unified_param.h"
28#include "wlan_hdd_coex_config.h"
29#include "qca_vendor.h"
30#include "wlan_osif_request_manager.h"
31#include "osif_sync.h"
32
33static const struct nla_policy
34coex_config_three_way_policy[QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_MAX + 1] = {
35 [QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE] = {
36 .type = NLA_U32},
37 [QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_1] = {.type = NLA_U32},
38 [QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_2] = {.type = NLA_U32},
39 [QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_3] = {.type = NLA_U32},
40 [QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_4] = {.type = NLA_U32},
41};
42
43static const uint32_t
44config_type_to_wmi_tbl[QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_TYPE_MAX] = {
45 [QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_COEX_RESET] =
46 WMI_COEX_CONFIG_THREE_WAY_COEX_RESET,
47 [QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_COEX_START] =
48 WMI_COEX_CONFIG_THREE_WAY_COEX_START,
49};
50
51/**
52 * __wlan_hdd_cfg80211_set_coex_config() - set coex configuration
53 * parameters
54 * @wiphy: pointer to wireless wiphy structure.
55 * @wdev: pointer to wireless_dev structure.
56 * @data: pointer to limit off-channel command parameters.
57 * @data_len: the length in byte of limit off-channel command parameters.
58 *
59 * Return: An error code or 0 on success.
60 */
61static int __wlan_hdd_cfg80211_set_coex_config(struct wiphy *wiphy,
62 struct wireless_dev *wdev,
63 const void *data, int data_len)
64{
65 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
66 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
67 struct nlattr *tb[QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_MAX + 1];
68 uint32_t config_type;
69 struct coex_config_params coex_cfg_params = {0};
70 int errno;
71 QDF_STATUS status;
72
73 hdd_enter();
74
75 errno = wlan_hdd_validate_context(hdd_ctx);
76 if (errno != 0)
77 return errno;
78
79 if (wlan_cfg80211_nla_parse(tb,
80 QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_MAX,
81 data, data_len,
82 coex_config_three_way_policy)) {
83 hdd_err("Invalid coex config ATTR");
84 return -EINVAL;
85 }
86
87 if (!tb[QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE]) {
88 hdd_err("coex config - attr config_type failed");
89 return -EINVAL;
90 }
91
92 config_type = nla_get_u32(
93 tb[QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE]);
94 if (config_type >= QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_TYPE_MAX) {
95 hdd_err("config_type value %d exceeded Max value %d",
96 config_type,
97 QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_TYPE_MAX);
98 return -EINVAL;
99 }
100 coex_cfg_params.config_type = config_type_to_wmi_tbl[config_type];
101 if (coex_cfg_params.config_type <
102 WMI_COEX_CONFIG_THREE_WAY_DELAY_PARA ||
103 coex_cfg_params.config_type >
104 WMI_COEX_CONFIG_THREE_WAY_COEX_START) {
105 hdd_err("config_type_wmi val error %d",
106 coex_cfg_params.config_type);
107 return -EINVAL;
108 }
109
110 hdd_debug("config_type %d, config_type_wmi %d",
111 config_type, coex_cfg_params.config_type);
112
113 if (!tb[QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_1]) {
114 hdd_err("coex config - attr priority1 failed");
115 return -EINVAL;
116 }
117 coex_cfg_params.config_arg1 = nla_get_u32(
118 tb[QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_1]);
119
120 hdd_debug("priority1 0x%x", coex_cfg_params.config_arg1);
121
122 if (!tb[QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_2]) {
123 hdd_err("coex config - attr priority2 failed");
124 return -EINVAL;
125 }
126 coex_cfg_params.config_arg2 = nla_get_u32(
127 tb[QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_2]);
128
129 hdd_debug("priority2 0x%x", coex_cfg_params.config_arg2);
130
131 if (!tb[QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_3]) {
132 hdd_err("coex config - attr priority3 failed");
133 return -EINVAL;
134 }
135 coex_cfg_params.config_arg3 = nla_get_u32(
136 tb[QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_3]);
137
138 hdd_debug("priority3 0x%x", coex_cfg_params.config_arg3);
139
140 if (!tb[QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_4]) {
141 hdd_err("coex config - attr priority4 failed");
142 return -EINVAL;
143 }
144 coex_cfg_params.config_arg4 = nla_get_u32(
145 tb[QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_4]);
146
147 hdd_debug("priority4 0x%x", coex_cfg_params.config_arg4);
148
149 coex_cfg_params.vdev_id = adapter->vdev_id;
150 status = sme_send_coex_config_cmd(&coex_cfg_params);
151 if (QDF_IS_STATUS_ERROR(status)) {
152 hdd_err("Failed to send coex config params");
153 return -EINVAL;
154 }
155
156 return 0;
157}
158
159/**
160 * wlan_hdd_cfg80211_set_coex_config() - set coex configuration
161 * @wiphy: pointer to wireless wiphy structure.
162 * @wdev: pointer to wireless_dev structure.
163 * @data: pointer to limit off-channel command parameters.
164 * @data_len: the length in byte of limit off-channel command parameters.
165 *
166 *
167 * Return: An error code or 0 on success.
168 */
169int wlan_hdd_cfg80211_set_coex_config(struct wiphy *wiphy,
170 struct wireless_dev *wdev,
171 const void *data, int data_len)
172{
173 int errno;
174 struct osif_vdev_sync *vdev_sync;
175
176 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
177 if (errno)
178 return errno;
179
180 errno = __wlan_hdd_cfg80211_set_coex_config(wiphy, wdev,
181 data, data_len);
182
183 osif_vdev_sync_op_stop(vdev_sync);
184
185 return errno;
186}