1 /* 2 * Copyright (c) 2018-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 #include "wmi_unified_api.h" 20 #include "wmi.h" 21 #include "wmi_version.h" 22 #include "wmi_unified_priv.h" 23 #include <wlan_defs.h> 24 #include "target_if.h" 25 #include "wma.h" 26 #include "wlan_ocb_ucfg_api.h" 27 #include "wlan_ocb_main.h" 28 29 void wmi_ocb_ut_attach(struct wmi_unified *wmi_handle); 30 31 static inline struct wlan_ocb_rx_ops * 32 target_if_ocb_get_rx_ops(struct wlan_objmgr_psoc *psoc) 33 { 34 struct wlan_objmgr_pdev *pdev; 35 struct ocb_pdev_obj *pdev_obj; 36 37 pdev = wlan_objmgr_get_pdev_by_id(psoc, 0, 38 WLAN_OCB_SB_ID); 39 pdev_obj = (struct ocb_pdev_obj *) 40 wlan_objmgr_pdev_get_comp_private_obj(pdev, 41 WLAN_UMAC_COMP_OCB); 42 return &pdev_obj->ocb_rxops; 43 } 44 45 /** 46 * fake_vdev_create_cmd_tlv() - send VDEV create command to fw 47 * @wmi_handle: wmi handle 48 * @param: pointer to hold vdev create parameter 49 * @macaddr: vdev mac address 50 * 51 * Return: QDF_STATUS_SUCCESS for success or error code 52 */ 53 static QDF_STATUS fake_vdev_create_cmd_tlv(wmi_unified_t wmi_handle, 54 uint8_t macaddr[QDF_MAC_ADDR_SIZE], 55 struct vdev_create_params *param) 56 { 57 WMI_LOGP("%s : called", __func__); 58 return QDF_STATUS_SUCCESS; 59 } 60 61 /** 62 * fake_vdev_delete_cmd_tlv() - send VDEV delete command to fw 63 * @wmi_handle: wmi handle 64 * @if_id: vdev id 65 * 66 * Return: QDF_STATUS_SUCCESS for success or error code 67 */ 68 static QDF_STATUS fake_vdev_delete_cmd_tlv(wmi_unified_t wmi_handle, 69 uint8_t if_id) 70 { 71 WMI_LOGP("%s : called", __func__); 72 return QDF_STATUS_SUCCESS; 73 } 74 75 /** 76 * fake_ocb_set_utc_time_cmd_tlv() - send the UTC time to the firmware 77 * @wmi_handle: pointer to the wmi handle 78 * @utc: pointer to the UTC time struct 79 * 80 * Return: 0 on succes 81 */ 82 static QDF_STATUS fake_ocb_set_utc_time_cmd_tlv(wmi_unified_t wmi_handle, 83 struct ocb_utc_param *utc) 84 { 85 WMI_LOGP("%s : called", __func__); 86 return QDF_STATUS_SUCCESS; 87 } 88 89 /** 90 * fake_ocb_get_tsf_timer_cmd_tlv() - get ocb tsf timer val 91 * @wmi_handle: pointer to the wmi handle 92 * @request: pointer to the request 93 * 94 * Return: 0 on succes 95 */ 96 static QDF_STATUS fake_ocb_get_tsf_timer_cmd_tlv(wmi_unified_t wmi_handle, 97 uint8_t vdev_id) 98 { 99 QDF_STATUS status; 100 struct wlan_objmgr_psoc *psoc; 101 struct wlan_ocb_rx_ops *ocb_rx_ops; 102 struct ocb_get_tsf_timer_response response; 103 ol_scn_t scn = (ol_scn_t) wmi_handle->scn_handle; 104 105 WMI_LOGP("%s : called", __func__); 106 psoc = target_if_get_psoc_from_scn_hdl(scn); 107 if (!psoc) { 108 WMI_LOGP("null psoc"); 109 return -EINVAL; 110 } 111 response.vdev_id = vdev_id; 112 response.timer_high = 0x1234; 113 response.timer_low = 0x5678; 114 115 ocb_rx_ops = target_if_ocb_get_rx_ops(psoc); 116 if (ocb_rx_ops->ocb_tsf_timer) { 117 status = ocb_rx_ops->ocb_tsf_timer(psoc, &response); 118 if (status != QDF_STATUS_SUCCESS) { 119 WMI_LOGP("ocb_tsf_timer failed."); 120 return -EINVAL; 121 } 122 } else { 123 WMI_LOGP("No ocb_tsf_timer callback"); 124 return -EINVAL; 125 } 126 return QDF_STATUS_SUCCESS; 127 } 128 129 /** 130 * fake_dcc_clear_stats_cmd_tlv() - command to clear the DCC stats 131 * @wmi_handle: pointer to the wmi handle 132 * @vdev_id: vdev id 133 * @dcc_stats_bitmap: dcc status bitmap 134 * 135 * Return: 0 on succes 136 */ 137 static QDF_STATUS fake_dcc_clear_stats_cmd_tlv(wmi_unified_t wmi_handle, 138 uint32_t vdev_id, uint32_t dcc_stats_bitmap) 139 { 140 WMI_LOGP("%s : called", __func__); 141 return QDF_STATUS_SUCCESS; 142 } 143 144 wmi_dcc_ndl_stats_per_channel chan1_info[2] = { 145 [0] = {.chan_info = 5860, 146 .tx_power_datarate = 23 | (10 << 8), 147 .carrier_sense_est_comm_range = 107 | (198 << 13), 148 .dcc_stats = 78 | (56 << 8) | (345 << 16), 149 .packet_stats = 1278 | (789 << 14), 150 .channel_busy_time = 1389, 151 }, 152 [1] = {.chan_info = 5880, 153 .tx_power_datarate = 53 | (17 << 8), 154 .carrier_sense_est_comm_range = 137 | (198 << 13), 155 .dcc_stats = 78 | (66 << 8) | (245 << 16), 156 .packet_stats = 1278 | (889 << 14), 157 .channel_busy_time = 2389, 158 }, 159 }; 160 161 /** 162 * fake_dcc_get_stats_cmd_tlv() - get the DCC channel stats 163 * @wmi_handle: pointer to the wmi handle 164 * @get_stats_param: pointer to the dcc stats 165 * 166 * Return: 0 on succes 167 */ 168 static QDF_STATUS fake_dcc_get_stats_cmd_tlv(wmi_unified_t wmi_handle, 169 struct ocb_dcc_get_stats_param *get_stats_param) 170 { 171 QDF_STATUS status; 172 struct wlan_objmgr_psoc *psoc; 173 struct wlan_ocb_rx_ops *ocb_rx_ops; 174 ol_scn_t scn = (ol_scn_t) wmi_handle->scn_handle; 175 struct ocb_dcc_get_stats_response *response; 176 WMI_LOGP("%s : called", __func__); 177 178 psoc = target_if_get_psoc_from_scn_hdl(scn); 179 if (!psoc) { 180 WMI_LOGP("null psoc"); 181 return -EINVAL; 182 } 183 response = qdf_mem_malloc(sizeof(*response) + 2 * 184 sizeof(wmi_dcc_ndl_stats_per_channel)); 185 response->num_channels = 2; 186 response->channel_stats_array_len = 2 * 187 sizeof(wmi_dcc_ndl_stats_per_channel); 188 response->vdev_id = get_stats_param->vdev_id; 189 response->channel_stats_array = (uint8_t *)response + sizeof(*response); 190 qdf_mem_copy(response->channel_stats_array, 191 &chan1_info, 192 2 * sizeof(wmi_dcc_ndl_stats_per_channel)); 193 WMI_LOGP("channel1 freq %d, channel2 freq %d", chan1_info[0].chan_info, 194 chan1_info[1].chan_info); 195 ocb_rx_ops = target_if_ocb_get_rx_ops(psoc); 196 if (ocb_rx_ops->ocb_dcc_stats_indicate) { 197 status = ocb_rx_ops->ocb_dcc_stats_indicate(psoc, 198 response, true); 199 if (status != QDF_STATUS_SUCCESS) { 200 WMI_LOGP("dcc_stats_indicate failed."); 201 status = -EINVAL; 202 } else { 203 status = 0; 204 } 205 } else { 206 WMI_LOGP("No dcc_stats_indicate callback"); 207 status = -EINVAL; 208 } 209 210 qdf_mem_free(response); 211 return QDF_STATUS_SUCCESS; 212 } 213 214 /** 215 * fake_dcc_update_ndl_cmd_tlv() - command to update the NDL data 216 * @wmi_handle: pointer to the wmi handle 217 * @update_ndl_param: pointer to the request parameters 218 * 219 * Return: 0 on success 220 */ 221 static QDF_STATUS fake_dcc_update_ndl_cmd_tlv(wmi_unified_t wmi_handle, 222 struct ocb_dcc_update_ndl_param *update_ndl_param) 223 { 224 QDF_STATUS status; 225 struct wlan_objmgr_psoc *psoc; 226 struct wlan_ocb_rx_ops *ocb_rx_ops; 227 ol_scn_t scn = (ol_scn_t) wmi_handle->scn_handle; 228 struct ocb_dcc_update_ndl_response *resp; 229 WMI_LOGP("%s : called", __func__); 230 /* Allocate and populate the response */ 231 resp = qdf_mem_malloc(sizeof(*resp)); 232 if (!resp) 233 return -ENOMEM; 234 235 resp->vdev_id = update_ndl_param->vdev_id; 236 resp->status = 0; 237 238 psoc = target_if_get_psoc_from_scn_hdl(scn); 239 if (!psoc) { 240 WMI_LOGP("null psoc"); 241 return -EINVAL; 242 } 243 244 ocb_rx_ops = target_if_ocb_get_rx_ops(psoc); 245 if (ocb_rx_ops->ocb_dcc_ndl_update) { 246 status = ocb_rx_ops->ocb_dcc_ndl_update(psoc, resp); 247 if (status != QDF_STATUS_SUCCESS) { 248 WMI_LOGP("dcc_ndl_update failed."); 249 status = -EINVAL; 250 } else { 251 status = 0; 252 } 253 } else { 254 WMI_LOGP("No dcc_ndl_update callback"); 255 status = -EINVAL; 256 } 257 258 qdf_mem_free(resp); 259 return QDF_STATUS_SUCCESS; 260 } 261 262 /** 263 * fake_ocb_set_config_cmd_tlv() - send the OCB config to the FW 264 * @wmi_handle: pointer to the wmi handle 265 * @config: the OCB configuration 266 * 267 * Return: 0 on success 268 */ 269 static QDF_STATUS fake_ocb_set_config_cmd_tlv(wmi_unified_t wmi_handle, 270 struct ocb_config *config) 271 { 272 u32 i; 273 QDF_STATUS status; 274 struct wlan_objmgr_psoc *psoc; 275 struct wlan_ocb_rx_ops *ocb_rx_ops; 276 ol_scn_t scn = (ol_scn_t) wmi_handle->scn_handle; 277 278 WMI_LOGP("%s : called", __func__); 279 WMI_LOGI("%s: vdev_id=%d, channel_count=%d, schedule_size=%d, flag=%x", 280 __func__, config->vdev_id, config->channel_count, 281 config->schedule_size, config->flags); 282 283 for (i = 0; i < config->channel_count; i++) { 284 WMI_LOGI("%s: channel info for channel %d" 285 " chan_freq=%d, bandwidth=%d, " QDF_MAC_ADDRESS_STR 286 " max_pwr=%d, min_pwr=%d, reg_pwr=%d, antenna_max=%d, " 287 "flags=%d", __func__, i, config->channels[i].chan_freq, 288 config->channels[i].bandwidth, 289 QDF_MAC_ADDR_ARRAY( 290 config->channels[i].mac_address.bytes), 291 config->channels[i].max_pwr, 292 config->channels[i].min_pwr, 293 config->channels[i].reg_pwr, 294 config->channels[i].antenna_max, 295 config->channels[i].flags); 296 } 297 298 for (i = 0; i < config->schedule_size; i++) { 299 WMI_LOGI("%s: schedule info for channel %d: " 300 "chan_fre=%d, total_duration=%d, guard_intreval=%d", 301 __func__, i, config->schedule[i].chan_freq, 302 config->schedule[i].total_duration, 303 config->schedule[i].guard_interval); 304 } 305 psoc = target_if_get_psoc_from_scn_hdl(scn); 306 if (!psoc) { 307 WMI_LOGP("null psoc"); 308 return -EINVAL; 309 } 310 311 ocb_rx_ops = target_if_ocb_get_rx_ops(psoc); 312 if (ocb_rx_ops->ocb_set_config_status) { 313 status = ocb_rx_ops->ocb_set_config_status(psoc, 0); 314 if (status != QDF_STATUS_SUCCESS) { 315 WMI_LOGP("ocb_set_config_status failed."); 316 return -EINVAL; 317 } 318 } else { 319 WMI_LOGP("No ocb_set_config_status callback"); 320 return -EINVAL; 321 } 322 return QDF_STATUS_SUCCESS; 323 } 324 325 /** 326 * fake_ocb_stop_timing_advert_cmd_tlv() - stop sending the 327 * timing advertisement frames on a channel 328 * @wmi_handle: pointer to the wmi handle 329 * @timing_advert: pointer to the timing advertisement struct 330 * 331 * Return: 0 on succes 332 */ 333 static QDF_STATUS fake_ocb_stop_timing_advert_cmd_tlv(wmi_unified_t wmi_handle, 334 struct ocb_timing_advert_param *timing_advert) 335 { 336 WMI_LOGP("%s : called", __func__); 337 return QDF_STATUS_SUCCESS; 338 } 339 340 /** 341 * fake_ocb_start_timing_advert_cmd_tlv() - start sending the 342 * timing advertisement frames on a channel 343 * @wmi_handle: pointer to the wmi handle 344 * @timing_advert: pointer to the timing advertisement struct 345 * 346 * Return: 0 on succes 347 */ 348 static QDF_STATUS 349 fake_ocb_start_timing_advert_cmd_tlv(wmi_unified_t wmi_handle, 350 struct ocb_timing_advert_param *timing_advert) 351 { 352 WMI_LOGP("%s : called", __func__); 353 return QDF_STATUS_SUCCESS; 354 } 355 356 /** 357 * fake_peer_create_cmd_tlv() - send peer create command to fw 358 * @wmi: wmi handle 359 * @peer_addr: peer mac address 360 * @peer_type: peer type 361 * @vdev_id: vdev id 362 * 363 * Return: QDF_STATUS_SUCCESS for success or error code 364 */ 365 static QDF_STATUS fake_peer_create_cmd_tlv(wmi_unified_t wmi, 366 struct peer_create_params *param) 367 { 368 WMI_LOGP("%s : called", __func__); 369 return QDF_STATUS_SUCCESS; 370 } 371 372 /** 373 * fake_peer_delete_cmd_tlv() - send PEER delete command to fw 374 * @wmi: wmi handle 375 * @peer_addr: peer mac addr 376 * @vdev_id: vdev id 377 * 378 * Return: QDF_STATUS_SUCCESS for success or error code 379 */ 380 static QDF_STATUS fake_peer_delete_cmd_tlv(wmi_unified_t wmi, 381 uint8_t peer_addr[QDF_MAC_ADDR_SIZE], 382 uint8_t vdev_id) 383 { 384 WMI_LOGP("%s : called", __func__); 385 return QDF_STATUS_SUCCESS; 386 } 387 388 /** 389 * fake_vdev_start_cmd_tlv() - send vdev start request to fw 390 * @wmi_handle: wmi handle 391 * @req: vdev start params 392 * 393 * Return: QDF status 394 */ 395 static QDF_STATUS fake_vdev_start_cmd_tlv(wmi_unified_t wmi_handle, 396 struct vdev_start_params *req) 397 { 398 tp_wma_handle wma = (tp_wma_handle) wmi_handle->scn_handle; 399 WMI_LOGP("%s : called", __func__); 400 WMI_LOGI("%s: vdev_id %d freq %d chanmode %d ch_info is_dfs %d " 401 "beacon interval %d dtim %d center_chan %d center_freq2 %d " 402 "max_txpow: 0x%x " 403 "Tx SS %d, Rx SS %d, ldpc_rx: %d, cac %d, regd %d, HE ops: %d", 404 __func__, (int)req->vdev_id, req->channel.mhz, 405 req->channel.phy_mode, 406 (int)req->channel.dfs_set, req->beacon_intval, req->dtim_period, 407 req->channel.cfreq1, req->channel.cfreq2, 408 req->channel.maxregpower, 409 req->preferred_tx_streams, req->preferred_rx_streams, 410 (int)req->ldpc_rx_enabled, req->cac_duration_ms, 411 req->regdomain, req->he_ops); 412 wma_remove_vdev_req(wma, req->vdev_id, 413 WMA_TARGET_REQ_TYPE_VDEV_START); 414 ucfg_ocb_config_channel(wma->pdev); 415 return QDF_STATUS_SUCCESS; 416 } 417 418 /** 419 * fake_vdev_down_cmd_tlv() - send vdev down command to fw 420 * @wmi: wmi handle 421 * @vdev_id: vdev id 422 * 423 * Return: QDF_STATUS_SUCCESS for success or error code 424 */ 425 static QDF_STATUS fake_vdev_down_cmd_tlv(wmi_unified_t wmi, uint8_t vdev_id) 426 { 427 WMI_LOGP("%s : called", __func__); 428 return QDF_STATUS_SUCCESS; 429 } 430 431 /** 432 * fake_vdev_set_param_cmd_tlv() - WMI vdev set parameter function 433 * @param wmi_handle : handle to WMI. 434 * @param macaddr : MAC address 435 * @param param : pointer to hold vdev set parameter 436 * 437 * Return: 0 on success and -ve on failure. 438 */ 439 static QDF_STATUS fake_vdev_set_param_cmd_tlv(wmi_unified_t wmi_handle, 440 struct vdev_set_params *param) 441 { 442 WMI_LOGP("%s : called", __func__); 443 return QDF_STATUS_SUCCESS; 444 } 445 446 /** 447 * fake_set_enable_disable_mcc_adaptive_scheduler_cmd_tlv() - 448 * faked API to enable/disable mcc scheduler 449 * @wmi_handle: wmi handle 450 * @mcc_adaptive_scheduler: enable/disable 451 * 452 * This function enable/disable mcc adaptive scheduler in fw. 453 * 454 * Return: QDF_STATUS_SUCCESS for success or error code 455 */ 456 static QDF_STATUS fake_set_enable_disable_mcc_adaptive_scheduler_cmd_tlv( 457 wmi_unified_t wmi_handle, uint32_t mcc_adaptive_scheduler, 458 uint32_t pdev_id) 459 { 460 WMI_LOGP("%s : called", __func__); 461 return QDF_STATUS_SUCCESS; 462 } 463 464 /* 465 * fake_process_set_ie_info_cmd_tlv() - Function to send IE info to firmware 466 * @wmi_handle: Pointer to WMi handle 467 * @ie_data: Pointer for ie data 468 * 469 * This function sends IE information to firmware 470 * 471 * Return: QDF_STATUS_SUCCESS for success otherwise failure 472 * 473 */ 474 static QDF_STATUS fake_process_set_ie_info_cmd_tlv(wmi_unified_t wmi_handle, 475 struct vdev_ie_info_param *ie_info) 476 { 477 WMI_LOGP("%s : called", __func__); 478 return QDF_STATUS_SUCCESS; 479 } 480 481 void wmi_ocb_ut_attach(struct wmi_unified *wmi_handle) 482 { 483 struct wmi_ops *wmi_ops; 484 485 if (!wmi_handle) { 486 WMI_LOGP("%s: null wmi handle", __func__); 487 return; 488 } 489 490 wmi_ops = wmi_handle->ops; 491 wmi_ops->send_vdev_create_cmd = fake_vdev_create_cmd_tlv; 492 wmi_ops->send_vdev_delete_cmd = fake_vdev_delete_cmd_tlv; 493 wmi_ops->send_vdev_down_cmd = fake_vdev_down_cmd_tlv; 494 wmi_ops->send_vdev_start_cmd = fake_vdev_start_cmd_tlv; 495 wmi_ops->send_peer_create_cmd = fake_peer_create_cmd_tlv; 496 wmi_ops->send_peer_delete_cmd = fake_peer_delete_cmd_tlv; 497 wmi_ops->send_vdev_set_param_cmd = fake_vdev_set_param_cmd_tlv; 498 wmi_ops->send_ocb_set_utc_time_cmd = fake_ocb_set_utc_time_cmd_tlv; 499 wmi_ops->send_ocb_get_tsf_timer_cmd = fake_ocb_get_tsf_timer_cmd_tlv; 500 wmi_ops->send_dcc_clear_stats_cmd = fake_dcc_clear_stats_cmd_tlv; 501 wmi_ops->send_dcc_get_stats_cmd = fake_dcc_get_stats_cmd_tlv; 502 wmi_ops->send_dcc_update_ndl_cmd = fake_dcc_update_ndl_cmd_tlv; 503 wmi_ops->send_ocb_set_config_cmd = fake_ocb_set_config_cmd_tlv; 504 wmi_ops->send_ocb_stop_timing_advert_cmd = 505 fake_ocb_stop_timing_advert_cmd_tlv; 506 wmi_ops->send_ocb_start_timing_advert_cmd = 507 fake_ocb_start_timing_advert_cmd_tlv; 508 wmi_ops->send_set_enable_disable_mcc_adaptive_scheduler_cmd = 509 fake_set_enable_disable_mcc_adaptive_scheduler_cmd_tlv; 510 wmi_ops->send_process_set_ie_info_cmd = 511 fake_process_set_ie_info_cmd_tlv; 512 } 513