1 /*
2 * Copyright (c) 2019-2021 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: defines driver functions interfacing with linux kernel
22 */
23
24 #include "wlan_cfg80211.h"
25 #include "wlan_osif_request_manager.h"
26 #include "wlan_fwol_ucfg_api.h"
27 #include "os_if_fwol.h"
28
29 #ifdef WLAN_FEATURE_ELNA
30 #define WLAN_WAIT_TIME_GET_ELNA_BYPASS 1500
31
os_if_fwol_set_elna_bypass(struct wlan_objmgr_vdev * vdev,const struct nlattr * attr)32 int os_if_fwol_set_elna_bypass(struct wlan_objmgr_vdev *vdev,
33 const struct nlattr *attr)
34 {
35 struct set_elna_bypass_request req;
36 QDF_STATUS status;
37
38 req.vdev_id = vdev->vdev_objmgr.vdev_id;
39 req.elna_mode = nla_get_u8(attr);
40 if (req.elna_mode > EXTLNA_MODE_FIRMWARE_DEFAULT) {
41 osif_err("Invalid elna_bypass value %d", req.elna_mode);
42 return -EINVAL;
43 }
44
45 status = ucfg_fwol_set_elna_bypass(vdev, &req);
46 if (!QDF_IS_STATUS_SUCCESS(status))
47 osif_err("Failed to set ELNA BYPASS, %d", status);
48
49 return qdf_status_to_os_return(status);
50 }
51
52 struct osif_get_elna_bypass_priv {
53 enum fwol_extlna_mode elna_mode;
54 };
55
56 /**
57 * os_if_fwol_get_elna_bypass_callback() - Get eLNA bypass callback
58 * @context: Call context
59 * @response: Pointer to response structure
60 *
61 * Return: void
62 */
63 static void
os_if_fwol_get_elna_bypass_callback(void * context,struct get_elna_bypass_response * response)64 os_if_fwol_get_elna_bypass_callback(void *context,
65 struct get_elna_bypass_response *response)
66 {
67 struct osif_request *request;
68 struct osif_get_elna_bypass_priv *priv;
69
70 request = osif_request_get(context);
71 if (!request) {
72 osif_err("Obsolete request");
73 return;
74 }
75
76 priv = osif_request_priv(request);
77 priv->elna_mode = response->elna_mode;
78
79 osif_request_complete(request);
80 osif_request_put(request);
81 }
82
os_if_fwol_get_elna_bypass(struct wlan_objmgr_vdev * vdev,struct sk_buff * skb,const struct nlattr * attr)83 int os_if_fwol_get_elna_bypass(struct wlan_objmgr_vdev *vdev,
84 struct sk_buff *skb,
85 const struct nlattr *attr)
86 {
87 struct get_elna_bypass_request req;
88 void *cookie;
89 struct osif_request *request;
90 struct osif_get_elna_bypass_priv *priv;
91 static const struct osif_request_params params = {
92 .priv_size = sizeof(*priv),
93 .timeout_ms = WLAN_WAIT_TIME_GET_ELNA_BYPASS,
94 };
95 QDF_STATUS status;
96 int ret = 0;
97
98 req.vdev_id = vdev->vdev_objmgr.vdev_id;
99
100 request = osif_request_alloc(¶ms);
101 if (!request) {
102 osif_err("Request allocation failure");
103 return -ENOMEM;
104 }
105 cookie = osif_request_cookie(request);
106
107 status = ucfg_fwol_get_elna_bypass(vdev, &req,
108 os_if_fwol_get_elna_bypass_callback,
109 cookie);
110 if (!QDF_IS_STATUS_SUCCESS(status)) {
111 osif_err("Failed to get ELNA BYPASS, %d", status);
112 ret = qdf_status_to_os_return(status);
113 goto end;
114 }
115
116 ret = osif_request_wait_for_response(request);
117 if (ret) {
118 osif_err("Operation timed out");
119 goto end;
120 }
121
122 priv = osif_request_priv(request);
123 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
124 priv->elna_mode)) {
125 osif_err("put fail with elna_mode:%d", priv->elna_mode);
126 ret = -EINVAL;
127 }
128
129 end:
130 osif_request_put(request);
131 return ret;
132 }
133 #endif /* #ifdef WLAN_FEATURE_ELNA */
134
135 #ifdef WLAN_SEND_DSCP_UP_MAP_TO_FW
os_if_fwol_send_dscp_up_map_to_fw(struct wlan_objmgr_vdev * vdev,uint32_t * dscp_to_up_map)136 int os_if_fwol_send_dscp_up_map_to_fw(struct wlan_objmgr_vdev *vdev,
137 uint32_t *dscp_to_up_map)
138 {
139 QDF_STATUS status;
140
141 status = ucfg_fwol_send_dscp_up_map_to_fw(vdev, dscp_to_up_map);
142 if (!QDF_IS_STATUS_SUCCESS(status))
143 osif_err("Failed to send dscp_up_map to FW, %d", status);
144
145 return qdf_status_to_os_return(status);
146 }
147 #endif
148
149 #ifdef WLAN_FEATURE_MDNS_OFFLOAD
os_if_fwol_enable_mdns_offload(struct wlan_objmgr_psoc * psoc,struct mdns_config_info * mdns_info)150 int os_if_fwol_enable_mdns_offload(struct wlan_objmgr_psoc *psoc,
151 struct mdns_config_info *mdns_info)
152 {
153 int ret = 0;
154 QDF_STATUS status;
155
156 if (!psoc) {
157 osif_err("Null pointer for psoc");
158 return -EINVAL;
159 }
160
161 if (!mdns_info) {
162 osif_err("Invalid mDNS config");
163 return -EINVAL;
164 }
165
166 status = ucfg_fwol_set_mdns_config(psoc, mdns_info);
167 if (!QDF_IS_STATUS_SUCCESS(status)) {
168 osif_err("Failed to set mDNS Config");
169 ret = qdf_status_to_os_return(status);
170 }
171
172 return ret;
173 }
174
os_if_fwol_disable_mdns_offload(struct wlan_objmgr_psoc * psoc)175 int os_if_fwol_disable_mdns_offload(struct wlan_objmgr_psoc *psoc)
176 {
177 struct mdns_config_info *mdns_info = NULL;
178 int ret = 0;
179 QDF_STATUS status;
180
181 if (!psoc) {
182 osif_err("Null pointer for psoc");
183 return -EINVAL;
184 }
185
186 mdns_info = qdf_mem_malloc(sizeof(*mdns_info));
187 if (!mdns_info) {
188 ret = -ENOMEM;
189 goto out;
190 }
191
192 mdns_info->enable = false;
193 status = ucfg_fwol_set_mdns_config(psoc, mdns_info);
194 if (!QDF_IS_STATUS_SUCCESS(status))
195 osif_err("Failed to set mDNS Config");
196 ret = qdf_status_to_os_return(status);
197 out:
198 qdf_mem_free(mdns_info);
199 return ret;
200 }
201 #endif /* WLAN_FEATURE_MDNS_OFFLOAD */
202
203 #ifdef THERMAL_STATS_SUPPORT
os_if_fwol_get_thermal_stats_req(struct wlan_objmgr_psoc * psoc,enum thermal_stats_request_type req,void (* callback)(void * context,struct thermal_throttle_info * response),void * context)204 int os_if_fwol_get_thermal_stats_req(struct wlan_objmgr_psoc *psoc,
205 enum thermal_stats_request_type req,
206 void (*callback)(void *context,
207 struct thermal_throttle_info *response),
208 void *context)
209 {
210 QDF_STATUS status;
211
212
213 status = ucfg_fwol_send_get_thermal_stats_cmd(psoc, req, callback,
214 context);
215 if (!QDF_IS_STATUS_SUCCESS(status))
216 osif_err("Failed to send get thermal stats cmd to FW, %d",
217 status);
218
219 return qdf_status_to_os_return(status);
220 }
221 #endif
222