1 /* 2 * Copyright (c) 2018 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[IEEE80211_ADDR_LEN], 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 WMI_LOGP("%s:Error allocating memory for the response.", 234 __func__); 235 return -ENOMEM; 236 } 237 resp->vdev_id = update_ndl_param->vdev_id; 238 resp->status = 0; 239 240 psoc = target_if_get_psoc_from_scn_hdl(scn); 241 if (!psoc) { 242 WMI_LOGP("null psoc"); 243 return -EINVAL; 244 } 245 246 ocb_rx_ops = target_if_ocb_get_rx_ops(psoc); 247 if (ocb_rx_ops->ocb_dcc_ndl_update) { 248 status = ocb_rx_ops->ocb_dcc_ndl_update(psoc, resp); 249 if (status != QDF_STATUS_SUCCESS) { 250 WMI_LOGP("dcc_ndl_update failed."); 251 status = -EINVAL; 252 } else { 253 status = 0; 254 } 255 } else { 256 WMI_LOGP("No dcc_ndl_update callback"); 257 status = -EINVAL; 258 } 259 260 qdf_mem_free(resp); 261 return QDF_STATUS_SUCCESS; 262 } 263 264 /** 265 * fake_ocb_set_config_cmd_tlv() - send the OCB config to the FW 266 * @wmi_handle: pointer to the wmi handle 267 * @config: the OCB configuration 268 * 269 * Return: 0 on success 270 */ 271 static QDF_STATUS fake_ocb_set_config_cmd_tlv(wmi_unified_t wmi_handle, 272 struct ocb_config *config) 273 { 274 u32 i; 275 QDF_STATUS status; 276 struct wlan_objmgr_psoc *psoc; 277 struct wlan_ocb_rx_ops *ocb_rx_ops; 278 ol_scn_t scn = (ol_scn_t) wmi_handle->scn_handle; 279 280 WMI_LOGP("%s : called", __func__); 281 WMI_LOGI("%s: vdev_id=%d, channel_count=%d, schedule_size=%d, flag=%x", 282 __func__, config->vdev_id, config->channel_count, 283 config->schedule_size, config->flags); 284 285 for (i = 0; i < config->channel_count; i++) { 286 WMI_LOGI("%s: channel info for channel %d" 287 " chan_freq=%d, bandwidth=%d, " QDF_MAC_ADDRESS_STR 288 " max_pwr=%d, min_pwr=%d, reg_pwr=%d, antenna_max=%d, " 289 "flags=%d", __func__, i, config->channels[i].chan_freq, 290 config->channels[i].bandwidth, 291 QDF_MAC_ADDR_ARRAY( 292 config->channels[i].mac_address.bytes), 293 config->channels[i].max_pwr, 294 config->channels[i].min_pwr, 295 config->channels[i].reg_pwr, 296 config->channels[i].antenna_max, 297 config->channels[i].flags); 298 } 299 300 for (i = 0; i < config->schedule_size; i++) { 301 WMI_LOGI("%s: schedule info for channel %d: " 302 "chan_fre=%d, total_duration=%d, guard_intreval=%d", 303 __func__, i, config->schedule[i].chan_freq, 304 config->schedule[i].total_duration, 305 config->schedule[i].guard_interval); 306 } 307 psoc = target_if_get_psoc_from_scn_hdl(scn); 308 if (!psoc) { 309 WMI_LOGP("null psoc"); 310 return -EINVAL; 311 } 312 313 ocb_rx_ops = target_if_ocb_get_rx_ops(psoc); 314 if (ocb_rx_ops->ocb_set_config_status) { 315 status = ocb_rx_ops->ocb_set_config_status(psoc, 0); 316 if (status != QDF_STATUS_SUCCESS) { 317 WMI_LOGP("ocb_set_config_status failed."); 318 return -EINVAL; 319 } 320 } else { 321 WMI_LOGP("No ocb_set_config_status callback"); 322 return -EINVAL; 323 } 324 return QDF_STATUS_SUCCESS; 325 } 326 327 /** 328 * fake_ocb_stop_timing_advert_cmd_tlv() - stop sending the 329 * timing advertisement frames on a channel 330 * @wmi_handle: pointer to the wmi handle 331 * @timing_advert: pointer to the timing advertisement struct 332 * 333 * Return: 0 on succes 334 */ 335 static QDF_STATUS fake_ocb_stop_timing_advert_cmd_tlv(wmi_unified_t wmi_handle, 336 struct ocb_timing_advert_param *timing_advert) 337 { 338 WMI_LOGP("%s : called", __func__); 339 return QDF_STATUS_SUCCESS; 340 } 341 342 /** 343 * fake_ocb_start_timing_advert_cmd_tlv() - start sending the 344 * timing advertisement frames on a channel 345 * @wmi_handle: pointer to the wmi handle 346 * @timing_advert: pointer to the timing advertisement struct 347 * 348 * Return: 0 on succes 349 */ 350 static QDF_STATUS 351 fake_ocb_start_timing_advert_cmd_tlv(wmi_unified_t wmi_handle, 352 struct ocb_timing_advert_param *timing_advert) 353 { 354 WMI_LOGP("%s : called", __func__); 355 return QDF_STATUS_SUCCESS; 356 } 357 358 /** 359 * fake_peer_create_cmd_tlv() - send peer create command to fw 360 * @wmi: wmi handle 361 * @peer_addr: peer mac address 362 * @peer_type: peer type 363 * @vdev_id: vdev id 364 * 365 * Return: QDF_STATUS_SUCCESS for success or error code 366 */ 367 static QDF_STATUS fake_peer_create_cmd_tlv(wmi_unified_t wmi, 368 struct peer_create_params *param) 369 { 370 WMI_LOGP("%s : called", __func__); 371 return QDF_STATUS_SUCCESS; 372 } 373 374 /** 375 * fake_peer_delete_cmd_tlv() - send PEER delete command to fw 376 * @wmi: wmi handle 377 * @peer_addr: peer mac addr 378 * @vdev_id: vdev id 379 * 380 * Return: QDF_STATUS_SUCCESS for success or error code 381 */ 382 static QDF_STATUS fake_peer_delete_cmd_tlv(wmi_unified_t wmi, 383 uint8_t peer_addr[IEEE80211_ADDR_LEN], 384 uint8_t vdev_id) 385 { 386 WMI_LOGP("%s : called", __func__); 387 return QDF_STATUS_SUCCESS; 388 } 389 390 /** 391 * fake_vdev_start_cmd_tlv() - send vdev start request to fw 392 * @wmi_handle: wmi handle 393 * @req: vdev start params 394 * 395 * Return: QDF status 396 */ 397 static QDF_STATUS fake_vdev_start_cmd_tlv(wmi_unified_t wmi_handle, 398 struct vdev_start_params *req) 399 { 400 tp_wma_handle wma = (tp_wma_handle) wmi_handle->scn_handle; 401 WMI_LOGP("%s : called", __func__); 402 WMI_LOGI("%s: vdev_id %d freq %d chanmode %d ch_info is_dfs %d " 403 "beacon interval %d dtim %d center_chan %d center_freq2 %d " 404 "max_txpow: 0x%x " 405 "Tx SS %d, Rx SS %d, ldpc_rx: %d, cac %d, regd %d, HE ops: %d", 406 __func__, (int)req->vdev_id, req->channel.mhz, 407 req->channel.phy_mode, 408 (int)req->channel.dfs_set, req->beacon_intval, req->dtim_period, 409 req->channel.cfreq1, req->channel.cfreq2, 410 req->channel.maxregpower, 411 req->preferred_tx_streams, req->preferred_rx_streams, 412 (int)req->ldpc_rx_enabled, req->cac_duration_ms, 413 req->regdomain, req->he_ops); 414 wma_remove_vdev_req(wma, req->vdev_id, 415 WMA_TARGET_REQ_TYPE_VDEV_START); 416 #ifndef CONFIG_VDEV_SM 417 wma_vdev_set_mlme_state(wma, req->vdev_id, 418 WLAN_VDEV_S_RUN); 419 #endif 420 ucfg_ocb_config_channel(wma->pdev); 421 return QDF_STATUS_SUCCESS; 422 } 423 424 /** 425 * fake_vdev_down_cmd_tlv() - send vdev down command to fw 426 * @wmi: wmi handle 427 * @vdev_id: vdev id 428 * 429 * Return: QDF_STATUS_SUCCESS for success or error code 430 */ 431 static QDF_STATUS fake_vdev_down_cmd_tlv(wmi_unified_t wmi, uint8_t vdev_id) 432 { 433 WMI_LOGP("%s : called", __func__); 434 return QDF_STATUS_SUCCESS; 435 } 436 437 /** 438 * fake_vdev_set_param_cmd_tlv() - WMI vdev set parameter function 439 * @param wmi_handle : handle to WMI. 440 * @param macaddr : MAC address 441 * @param param : pointer to hold vdev set parameter 442 * 443 * Return: 0 on success and -ve on failure. 444 */ 445 static QDF_STATUS fake_vdev_set_param_cmd_tlv(wmi_unified_t wmi_handle, 446 struct vdev_set_params *param) 447 { 448 WMI_LOGP("%s : called", __func__); 449 return QDF_STATUS_SUCCESS; 450 } 451 452 /** 453 * fake_set_enable_disable_mcc_adaptive_scheduler_cmd_tlv() - 454 * faked API to enable/disable mcc scheduler 455 * @wmi_handle: wmi handle 456 * @mcc_adaptive_scheduler: enable/disable 457 * 458 * This function enable/disable mcc adaptive scheduler in fw. 459 * 460 * Return: QDF_STATUS_SUCCESS for success or error code 461 */ 462 static QDF_STATUS fake_set_enable_disable_mcc_adaptive_scheduler_cmd_tlv( 463 wmi_unified_t wmi_handle, uint32_t mcc_adaptive_scheduler, 464 uint32_t pdev_id) 465 { 466 WMI_LOGP("%s : called", __func__); 467 return QDF_STATUS_SUCCESS; 468 } 469 470 /* 471 * fake_process_set_ie_info_cmd_tlv() - Function to send IE info to firmware 472 * @wmi_handle: Pointer to WMi handle 473 * @ie_data: Pointer for ie data 474 * 475 * This function sends IE information to firmware 476 * 477 * Return: QDF_STATUS_SUCCESS for success otherwise failure 478 * 479 */ 480 static QDF_STATUS fake_process_set_ie_info_cmd_tlv(wmi_unified_t wmi_handle, 481 struct vdev_ie_info_param *ie_info) 482 { 483 WMI_LOGP("%s : called", __func__); 484 return QDF_STATUS_SUCCESS; 485 } 486 487 void wmi_ocb_ut_attach(struct wmi_unified *wmi_handle) 488 { 489 struct wmi_ops *wmi_ops; 490 491 if (!wmi_handle) { 492 WMI_LOGP("%s: null wmi handle", __func__); 493 return; 494 } 495 496 wmi_ops = wmi_handle->ops; 497 wmi_ops->send_vdev_create_cmd = fake_vdev_create_cmd_tlv; 498 wmi_ops->send_vdev_delete_cmd = fake_vdev_delete_cmd_tlv; 499 wmi_ops->send_vdev_down_cmd = fake_vdev_down_cmd_tlv; 500 wmi_ops->send_vdev_start_cmd = fake_vdev_start_cmd_tlv; 501 wmi_ops->send_peer_create_cmd = fake_peer_create_cmd_tlv; 502 wmi_ops->send_peer_delete_cmd = fake_peer_delete_cmd_tlv; 503 wmi_ops->send_vdev_set_param_cmd = fake_vdev_set_param_cmd_tlv; 504 wmi_ops->send_ocb_set_utc_time_cmd = fake_ocb_set_utc_time_cmd_tlv; 505 wmi_ops->send_ocb_get_tsf_timer_cmd = fake_ocb_get_tsf_timer_cmd_tlv; 506 wmi_ops->send_dcc_clear_stats_cmd = fake_dcc_clear_stats_cmd_tlv; 507 wmi_ops->send_dcc_get_stats_cmd = fake_dcc_get_stats_cmd_tlv; 508 wmi_ops->send_dcc_update_ndl_cmd = fake_dcc_update_ndl_cmd_tlv; 509 wmi_ops->send_ocb_set_config_cmd = fake_ocb_set_config_cmd_tlv; 510 wmi_ops->send_ocb_stop_timing_advert_cmd = 511 fake_ocb_stop_timing_advert_cmd_tlv; 512 wmi_ops->send_ocb_start_timing_advert_cmd = 513 fake_ocb_start_timing_advert_cmd_tlv; 514 wmi_ops->send_set_enable_disable_mcc_adaptive_scheduler_cmd = 515 fake_set_enable_disable_mcc_adaptive_scheduler_cmd_tlv; 516 wmi_ops->send_process_set_ie_info_cmd = 517 fake_process_set_ie_info_cmd_tlv; 518 } 519