1 /*
2  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2023 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 #include <osdep.h>
21 #include "wmi.h"
22 #include "wmi_unified_priv.h"
23 #include "wmi_unified_dbr_param.h"
24 #include "wmi_unified_dbr_api.h"
25 
26 /**
27  * send_dbr_cfg_cmd_tlv() - configure DMA rings for Direct Buf RX
28  * @wmi_handle: wmi handle
29  * @cfg: dma cfg req
30  *
31  * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
32  */
send_dbr_cfg_cmd_tlv(wmi_unified_t wmi_handle,struct direct_buf_rx_cfg_req * cfg)33 static QDF_STATUS send_dbr_cfg_cmd_tlv(wmi_unified_t wmi_handle,
34 				struct direct_buf_rx_cfg_req *cfg)
35 {
36 	wmi_buf_t buf;
37 	wmi_dma_ring_cfg_req_fixed_param *cmd;
38 	QDF_STATUS ret;
39 	int32_t len = sizeof(*cmd);
40 
41 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
42 	if (!buf) {
43 		wmi_err("wmi_buf_alloc failed");
44 		return QDF_STATUS_E_FAILURE;
45 	}
46 
47 	cmd = (wmi_dma_ring_cfg_req_fixed_param *)wmi_buf_data(buf);
48 
49 	WMITLV_SET_HDR(&cmd->tlv_header,
50 		WMITLV_TAG_STRUC_wmi_dma_ring_cfg_req_fixed_param,
51 		WMITLV_GET_STRUCT_TLVLEN(wmi_dma_ring_cfg_req_fixed_param));
52 
53 	cmd->pdev_id = wmi_handle->ops->convert_host_pdev_id_to_target(
54 						wmi_handle,
55 						cfg->pdev_id);
56 	cmd->mod_id = cfg->mod_id;
57 	cmd->base_paddr_lo = cfg->base_paddr_lo;
58 	cmd->base_paddr_hi = cfg->base_paddr_hi;
59 	cmd->head_idx_paddr_lo = cfg->head_idx_paddr_lo;
60 	cmd->head_idx_paddr_hi = cfg->head_idx_paddr_hi;
61 	cmd->tail_idx_paddr_lo = cfg->tail_idx_paddr_lo;
62 	cmd->tail_idx_paddr_hi = cfg->tail_idx_paddr_hi;
63 	cmd->num_elems = cfg->num_elems;
64 	cmd->buf_size = cfg->buf_size;
65 	cmd->num_resp_per_event = cfg->num_resp_per_event;
66 	cmd->event_timeout_ms = cfg->event_timeout_ms;
67 
68 	wmi_debug("wmi_dma_ring_cfg_req_fixed_param pdev id %d mod id %d"
69 		  "base paddr lo %x base paddr hi %x head idx paddr lo %x"
70 		  "head idx paddr hi %x tail idx paddr lo %x"
71 		  "tail idx addr hi %x num elems %d buf size %d num resp %d"
72 		  "event timeout %d", cmd->pdev_id,
73 		  cmd->mod_id, cmd->base_paddr_lo, cmd->base_paddr_hi,
74 		  cmd->head_idx_paddr_lo, cmd->head_idx_paddr_hi,
75 		  cmd->tail_idx_paddr_lo, cmd->tail_idx_paddr_hi,
76 		  cmd->num_elems, cmd->buf_size, cmd->num_resp_per_event,
77 		  cmd->event_timeout_ms);
78 	wmi_mtrace(WMI_PDEV_DMA_RING_CFG_REQ_CMDID, NO_SESSION, 0);
79 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
80 				WMI_PDEV_DMA_RING_CFG_REQ_CMDID);
81 	if (QDF_IS_STATUS_ERROR(ret)) {
82 		wmi_err(":wmi cmd send failed");
83 		wmi_buf_free(buf);
84 	}
85 
86 	return ret;
87 }
88 
extract_scaling_params_service_ready_ext_tlv(wmi_unified_t wmi_handle,uint8_t * event,uint8_t idx,struct wlan_psoc_host_spectral_scaling_params * param)89 static QDF_STATUS extract_scaling_params_service_ready_ext_tlv(
90 			wmi_unified_t wmi_handle,
91 			uint8_t *event, uint8_t idx,
92 			struct wlan_psoc_host_spectral_scaling_params *param)
93 {
94 	WMI_SERVICE_READY_EXT_EVENTID_param_tlvs *param_buf;
95 	wmi_spectral_bin_scaling_params *spectral_bin_scaling_params;
96 
97 	param_buf = (WMI_SERVICE_READY_EXT_EVENTID_param_tlvs *)event;
98 	if (!param_buf)
99 		return QDF_STATUS_E_INVAL;
100 
101 	spectral_bin_scaling_params = &param_buf->wmi_bin_scaling_params[idx];
102 
103 	param->pdev_id = wmi_handle->ops->convert_target_pdev_id_to_host(
104 					wmi_handle,
105 					spectral_bin_scaling_params->pdev_id);
106 	param->low_level_offset = spectral_bin_scaling_params->low_level_offset;
107 	param->formula_id = spectral_bin_scaling_params->formula_id;
108 	param->high_level_offset =
109 		spectral_bin_scaling_params->high_level_offset;
110 	param->rssi_thr = spectral_bin_scaling_params->rssi_thr;
111 	param->default_agc_max_gain =
112 		spectral_bin_scaling_params->default_agc_max_gain;
113 
114 	return QDF_STATUS_SUCCESS;
115 }
116 
extract_dbr_buf_release_fixed_tlv(wmi_unified_t wmi_handle,uint8_t * event,struct direct_buf_rx_rsp * param)117 static QDF_STATUS extract_dbr_buf_release_fixed_tlv(wmi_unified_t wmi_handle,
118 		uint8_t *event, struct direct_buf_rx_rsp *param)
119 {
120 	WMI_PDEV_DMA_RING_BUF_RELEASE_EVENTID_param_tlvs *param_buf;
121 	wmi_dma_buf_release_fixed_param *ev;
122 
123 	param_buf = (WMI_PDEV_DMA_RING_BUF_RELEASE_EVENTID_param_tlvs *)event;
124 	if (!param_buf)
125 		return QDF_STATUS_E_INVAL;
126 
127 	ev = param_buf->fixed_param;
128 	if (!ev)
129 		return QDF_STATUS_E_INVAL;
130 
131 	param->pdev_id = wmi_handle->ops->convert_target_pdev_id_to_host(
132 								wmi_handle,
133 								ev->pdev_id);
134 	param->mod_id = ev->mod_id;
135 	if ((!param_buf->num_entries) ||
136 	    param_buf->num_entries < ev->num_buf_release_entry) {
137 		wmi_err("actual num of buf release entries less than provided entries");
138 		return QDF_STATUS_E_INVAL;
139 	}
140 	param->num_buf_release_entry = ev->num_buf_release_entry;
141 	if (((!param_buf->num_meta_data) ||
142 	     param_buf->num_meta_data < ev->num_meta_data_entry) &&
143 	     ((!param_buf->num_cv_meta_data) ||
144 	     param_buf->num_cv_meta_data < ev->num_meta_data_entry) &&
145 	     ((!param_buf->num_cqi_meta_data) ||
146 	     param_buf->num_cqi_meta_data < ev->num_meta_data_entry)) {
147 		wmi_err(" actual num of meta data entries less than provided entries");
148 		return QDF_STATUS_E_INVAL;
149 	}
150 	param->num_meta_data_entry = param_buf->num_meta_data;
151 	param->num_cv_meta_data_entry = param_buf->num_cv_meta_data;
152 	param->num_cqi_meta_data_entry = param_buf->num_cqi_meta_data;
153 	wmi_debug("pdev id %d mod id %d num buf release entry %d",
154 		 param->pdev_id, param->mod_id, param->num_buf_release_entry);
155 
156 	return QDF_STATUS_SUCCESS;
157 }
158 
extract_dbr_buf_release_entry_tlv(wmi_unified_t wmi_handle,uint8_t * event,uint8_t idx,struct direct_buf_rx_entry * param)159 static QDF_STATUS extract_dbr_buf_release_entry_tlv(wmi_unified_t wmi_handle,
160 		uint8_t *event, uint8_t idx, struct direct_buf_rx_entry *param)
161 {
162 	WMI_PDEV_DMA_RING_BUF_RELEASE_EVENTID_param_tlvs *param_buf;
163 	wmi_dma_buf_release_entry *entry;
164 
165 	param_buf = (WMI_PDEV_DMA_RING_BUF_RELEASE_EVENTID_param_tlvs *)event;
166 	if (!param_buf)
167 		return QDF_STATUS_E_INVAL;
168 
169 	entry = &param_buf->entries[idx];
170 
171 	if (!entry) {
172 		wmi_err("Entry is NULL");
173 		return QDF_STATUS_E_FAILURE;
174 	}
175 
176 	wmi_debug("paddr_lo[%d] = %x", idx, entry->paddr_lo);
177 
178 	param->paddr_lo = entry->paddr_lo;
179 	param->paddr_hi = entry->paddr_hi;
180 
181 	return QDF_STATUS_SUCCESS;
182 }
183 
extract_dbr_buf_metadata_tlv(wmi_unified_t wmi_handle,uint8_t * event,uint8_t idx,struct direct_buf_rx_metadata * param)184 static QDF_STATUS extract_dbr_buf_metadata_tlv(
185 		wmi_unified_t wmi_handle, uint8_t *event,
186 		uint8_t idx, struct direct_buf_rx_metadata *param)
187 {
188 	WMI_PDEV_DMA_RING_BUF_RELEASE_EVENTID_param_tlvs *param_buf;
189 	wmi_dma_buf_release_spectral_meta_data *entry;
190 
191 	param_buf = (WMI_PDEV_DMA_RING_BUF_RELEASE_EVENTID_param_tlvs *)event;
192 	if (!param_buf)
193 		return QDF_STATUS_E_INVAL;
194 
195 	entry = &param_buf->meta_data[idx];
196 
197 	if (!entry) {
198 		wmi_err("Entry is NULL");
199 		return QDF_STATUS_E_FAILURE;
200 	}
201 
202 	qdf_mem_copy(param->noisefloor, entry->noise_floor,
203 		     qdf_min(sizeof(entry->noise_floor),
204 			     sizeof(param->noisefloor)));
205 	param->reset_delay = entry->reset_delay;
206 	param->cfreq1 = entry->freq1;
207 	param->cfreq2 = entry->freq2;
208 	param->ch_width = entry->ch_width;
209 
210 	return QDF_STATUS_SUCCESS;
211 }
212 
extract_dbr_buf_cv_metadata_tlv(wmi_unified_t wmi_handle,uint8_t * event,uint8_t idx,struct direct_buf_rx_cv_metadata * param)213 static QDF_STATUS extract_dbr_buf_cv_metadata_tlv(
214 		wmi_unified_t wmi_handle, uint8_t *event,
215 		uint8_t idx, struct direct_buf_rx_cv_metadata *param)
216 {
217 	WMI_PDEV_DMA_RING_BUF_RELEASE_EVENTID_param_tlvs *param_buf;
218 	wmi_dma_buf_release_cv_upload_meta_data *ev;
219 
220 	param_buf = (WMI_PDEV_DMA_RING_BUF_RELEASE_EVENTID_param_tlvs *)event;
221 	if (!param_buf)
222 		return QDF_STATUS_E_INVAL;
223 
224 	ev = &param_buf->cv_meta_data[idx];
225 
226 	if (!ev) {
227 		wmi_err("CV metadata is NULL");
228 		return QDF_STATUS_E_FAILURE;
229 	}
230 
231 	param->is_valid = ev->is_valid;
232 	param->fb_type = ev->fb_type;
233 	param->asnr_len =
234 		WMI_DMA_BUF_RELEASE_CV_UPLOAD_GET_ASNR_LENGTH(ev->asnr_params);
235 	param->asnr_offset =
236 		WMI_DMA_BUF_RELEASE_CV_UPLOAD_GET_ASNR_OFFSET(ev->asnr_params);
237 	param->dsnr_len =
238 		WMI_DMA_BUF_RELEASE_CV_UPLOAD_GET_DSNR_LENGTH(ev->dsnr_params);
239 	param->dsnr_offset =
240 		WMI_DMA_BUF_RELEASE_CV_UPLOAD_GET_DSNR_OFFSET(ev->dsnr_params);
241 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_mac_address,
242 				   &param->peer_mac.bytes[0]);
243 	param->fb_params = ev->fb_params;
244 
245 	return QDF_STATUS_SUCCESS;
246 }
247 
extract_dbr_buf_cqi_metadata_tlv(wmi_unified_t wmi_handle,uint8_t * event,uint8_t idx,struct direct_buf_rx_cqi_metadata * param)248 static QDF_STATUS extract_dbr_buf_cqi_metadata_tlv(
249 		wmi_unified_t wmi_handle, uint8_t *event,
250 		uint8_t idx, struct direct_buf_rx_cqi_metadata *param)
251 {
252 	WMI_PDEV_DMA_RING_BUF_RELEASE_EVENTID_param_tlvs *param_buf;
253 	wmi_dma_buf_release_cqi_upload_meta_data *ev;
254 	uint16_t asnr_len, asnr_offset;
255 	uint8_t num_users = 0;
256 	uint8_t i;
257 
258 	param_buf = (WMI_PDEV_DMA_RING_BUF_RELEASE_EVENTID_param_tlvs *)event;
259 	if (!param_buf)
260 		return QDF_STATUS_E_INVAL;
261 
262 	ev = &param_buf->cqi_meta_data[idx];
263 
264 	if (!ev) {
265 		wmi_err("CQI metadata is NULL");
266 		return QDF_STATUS_E_FAILURE;
267 	}
268 
269 	param->fb_params = ev->fb_params_cqi;
270 	asnr_len =
271 		WMI_DMA_BUF_RELEASE_CV_UPLOAD_GET_ASNR_LENGTH(ev->asnr_params);
272 	asnr_offset =
273 		WMI_DMA_BUF_RELEASE_CV_UPLOAD_GET_ASNR_OFFSET(ev->asnr_params);
274 	for (i = 0; i < MAX_NUM_CQI_USERS_IN_STANDALONE_SND; i++) {
275 		if (WMI_DMA_BUF_RELEASE_CQI_UPLOAD_GET_FB_PARAMS_IS_VALID(
276 		    param->fb_params, i)) {
277 			WMI_DMA_BUF_RELEASE_CQI_UPLOAD_SET_FB_PARAMS_IS_VALID(
278 			param->is_valid, 1, i);
279 			param->user_info[i].asnr_len = asnr_len;
280 			param->user_info[i].asnr_offset =
281 				asnr_offset + CQI_USER_DATA_OFFSET(i);
282 			param->user_info[i].fb_params =
283 				WMI_DMA_BUF_RELEASE_CQI_UPLOAD_GET_FB_PARAMS_NC(
284 				param->fb_params, i);
285 
286 			WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_mac_address[i],
287 				&param->user_info[i].peer_mac.bytes[0]);
288 			num_users++;
289 		}
290 	}
291 	param->num_users = num_users;
292 
293 	return QDF_STATUS_SUCCESS;
294 }
295 
wmi_dbr_attach_tlv(wmi_unified_t wmi_handle)296 void wmi_dbr_attach_tlv(wmi_unified_t wmi_handle)
297 {
298 	struct wmi_ops *ops = wmi_handle->ops;
299 
300 	ops->send_dbr_cfg_cmd = send_dbr_cfg_cmd_tlv;
301 	ops->extract_dbr_buf_release_entry = extract_dbr_buf_release_entry_tlv;
302 	ops->extract_dbr_buf_metadata = extract_dbr_buf_metadata_tlv;
303 	ops->extract_dbr_buf_cv_metadata = extract_dbr_buf_cv_metadata_tlv;
304 	ops->extract_dbr_buf_cqi_metadata = extract_dbr_buf_cqi_metadata_tlv;
305 	ops->extract_dbr_buf_release_fixed = extract_dbr_buf_release_fixed_tlv;
306 	ops->extract_scaling_params_service_ready_ext =
307 			extract_scaling_params_service_ready_ext_tlv;
308 }
309