1 /* 2 * Copyright (c) 2016-2020 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 #include <osdep.h> 21 #include <qdf_module.h> 22 #include <qdf_list.h> 23 #include <qdf_platform.h> 24 #include <wmi_unified_vdev_tlv.h> 25 #include <wlan_vdev_mgr_tgt_if_tx_defs.h> 26 27 static QDF_STATUS 28 send_vdev_config_ratemask_cmd_tlv(struct wmi_unified *wmi_handle, 29 struct config_ratemask_params *param) 30 { 31 wmi_vdev_config_ratemask_cmd_fixed_param *cmd; 32 wmi_buf_t buf; 33 int32_t len = sizeof(*cmd); 34 35 buf = wmi_buf_alloc(wmi_handle, len); 36 if (!buf) { 37 wmi_err("wmi_buf_alloc failed"); 38 return QDF_STATUS_E_FAILURE; 39 } 40 cmd = (wmi_vdev_config_ratemask_cmd_fixed_param *)wmi_buf_data(buf); 41 WMITLV_SET_HDR(&cmd->tlv_header, 42 WMITLV_TAG_STRUC_wmi_vdev_config_ratemask_fixed_param, 43 WMITLV_GET_STRUCT_TLVLEN( 44 wmi_vdev_config_ratemask_cmd_fixed_param)); 45 cmd->vdev_id = param->vdev_id; 46 cmd->type = param->type; 47 cmd->mask_lower32 = param->lower32; 48 cmd->mask_higher32 = param->higher32; 49 cmd->mask_lower32_2 = param->lower32_2; 50 cmd->mask_higher32_2 = param->higher32_2; 51 52 wmi_debug("vdev_id %d type %d lower32 0x%x lower32_2 0x%x", 53 cmd->vdev_id, cmd->type, cmd->mask_lower32, 54 cmd->mask_lower32_2); 55 wmi_debug("higher32 0x%x higher32_2 0x%x", cmd->mask_higher32, 56 cmd->mask_higher32_2); 57 wmi_mtrace(WMI_VDEV_RATEMASK_CMDID, cmd->vdev_id, 0); 58 if (wmi_unified_cmd_send(wmi_handle, buf, len, 59 WMI_VDEV_RATEMASK_CMDID)) { 60 wmi_err("Setting vdev ratemask failed"); 61 wmi_buf_free(buf); 62 return QDF_STATUS_E_FAILURE; 63 } 64 65 return QDF_STATUS_SUCCESS; 66 } 67 68 static QDF_STATUS 69 send_beacon_send_cmd_tlv(struct wmi_unified *wmi_handle, 70 struct beacon_params *param) 71 { 72 QDF_STATUS ret; 73 wmi_bcn_send_from_host_cmd_fixed_param *cmd; 74 wmi_buf_t wmi_buf; 75 qdf_dma_addr_t dma_addr; 76 uint32_t dtim_flag = 0; 77 78 wmi_buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd)); 79 if (!wmi_buf) { 80 wmi_err("wmi_buf_alloc failed"); 81 return QDF_STATUS_E_NOMEM; 82 } 83 if (param->is_dtim_count_zero) { 84 dtim_flag |= WMI_BCN_SEND_DTIM_ZERO; 85 if (param->is_bitctl_reqd) { 86 /* deliver CAB traffic in next DTIM beacon */ 87 dtim_flag |= WMI_BCN_SEND_DTIM_BITCTL_SET; 88 } 89 } 90 cmd = (wmi_bcn_send_from_host_cmd_fixed_param *)wmi_buf_data(wmi_buf); 91 WMITLV_SET_HDR( 92 &cmd->tlv_header, 93 WMITLV_TAG_STRUC_wmi_bcn_send_from_host_cmd_fixed_param, 94 WMITLV_GET_STRUCT_TLVLEN 95 (wmi_bcn_send_from_host_cmd_fixed_param)); 96 cmd->vdev_id = param->vdev_id; 97 cmd->data_len = qdf_nbuf_len(param->wbuf); 98 cmd->frame_ctrl = param->frame_ctrl; 99 cmd->dtim_flag = dtim_flag; 100 dma_addr = qdf_nbuf_get_frag_paddr(param->wbuf, 0); 101 cmd->frag_ptr_lo = qdf_get_lower_32_bits(dma_addr); 102 #if defined(HTT_PADDR64) 103 cmd->frag_ptr_hi = qdf_get_upper_32_bits(dma_addr) & 0x1F; 104 #endif 105 cmd->bcn_antenna = param->bcn_txant; 106 107 wmi_mtrace(WMI_PDEV_SEND_BCN_CMDID, cmd->vdev_id, 0); 108 ret = wmi_unified_cmd_send(wmi_handle, wmi_buf, sizeof(*cmd), 109 WMI_PDEV_SEND_BCN_CMDID); 110 if (ret != QDF_STATUS_SUCCESS) { 111 wmi_err("Failed to send bcn: %d", ret); 112 wmi_buf_free(wmi_buf); 113 } 114 115 return ret; 116 } 117 118 static QDF_STATUS 119 extract_tbttoffset_num_vdevs_tlv(struct wmi_unified *wmi_handle, void *evt_buf, 120 uint32_t *num_vdevs) 121 { 122 WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf; 123 wmi_tbtt_offset_event_fixed_param *tbtt_offset_event; 124 uint32_t vdev_map; 125 126 param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *)evt_buf; 127 if (!param_buf) { 128 wmi_err("Invalid tbtt update ext event buffer"); 129 return QDF_STATUS_E_INVAL; 130 } 131 tbtt_offset_event = param_buf->fixed_param; 132 vdev_map = tbtt_offset_event->vdev_map; 133 *num_vdevs = wmi_vdev_map_to_num_vdevs(vdev_map); 134 135 return QDF_STATUS_SUCCESS; 136 } 137 138 static QDF_STATUS 139 send_peer_filter_set_tx_cmd_tlv(struct wmi_unified *wmi_handle, 140 uint8_t macaddr[], 141 struct set_tx_peer_filter *param) 142 { 143 wmi_peer_tx_filter_cmd_fixed_param *cmd; 144 wmi_buf_t buf; 145 uint32_t len = sizeof(*cmd); 146 147 buf = wmi_buf_alloc(wmi_handle, len); 148 if (!buf) 149 return QDF_STATUS_E_FAILURE; 150 151 cmd = (wmi_peer_tx_filter_cmd_fixed_param *)wmi_buf_data(buf); 152 WMITLV_SET_HDR(&cmd->tlv_header, 153 WMITLV_TAG_STRUC_wmi_peer_tx_filter_cmd_fixed_param, 154 WMITLV_GET_STRUCT_TLVLEN( 155 wmi_peer_tx_filter_cmd_fixed_param)); 156 157 cmd->vdev_id = param->vdev_id; 158 cmd->action = param->action; 159 WMI_CHAR_ARRAY_TO_MAC_ADDR(macaddr, &cmd->addr); 160 161 wmi_mtrace(WMI_PEER_TX_FILTER_CMDID, cmd->vdev_id, 0); 162 if (wmi_unified_cmd_send(wmi_handle, buf, len, 163 WMI_PEER_TX_FILTER_CMDID)) { 164 wmi_err("Failed to set neighbour rx param"); 165 wmi_buf_free(buf); 166 return QDF_STATUS_E_FAILURE; 167 } 168 169 return QDF_STATUS_SUCCESS; 170 } 171 172 static QDF_STATUS 173 send_vdev_set_neighbour_rx_cmd_tlv(struct wmi_unified *wmi_handle, 174 uint8_t macaddr[QDF_MAC_ADDR_SIZE], 175 struct set_neighbour_rx_params *param) 176 { 177 wmi_vdev_filter_nrp_config_cmd_fixed_param *cmd; 178 wmi_buf_t buf; 179 int32_t len = sizeof(*cmd); 180 181 buf = wmi_buf_alloc(wmi_handle, len); 182 if (!buf) { 183 wmi_err("wmi_buf_alloc failed"); 184 return QDF_STATUS_E_FAILURE; 185 } 186 cmd = (wmi_vdev_filter_nrp_config_cmd_fixed_param *)wmi_buf_data(buf); 187 WMITLV_SET_HDR(&cmd->tlv_header, 188 WMITLV_TAG_STRUC_wmi_vdev_filter_nrp_config_cmd_fixed_param, 189 WMITLV_GET_STRUCT_TLVLEN( 190 wmi_vdev_filter_nrp_config_cmd_fixed_param)); 191 cmd->vdev_id = param->vdev_id; 192 cmd->bssid_idx = param->idx; 193 cmd->action = param->action; 194 cmd->type = param->type; 195 WMI_CHAR_ARRAY_TO_MAC_ADDR(macaddr, &cmd->addr); 196 cmd->flag = 0; 197 198 wmi_mtrace(WMI_VDEV_FILTER_NEIGHBOR_RX_PACKETS_CMDID, cmd->vdev_id, 0); 199 if (wmi_unified_cmd_send(wmi_handle, buf, len, 200 WMI_VDEV_FILTER_NEIGHBOR_RX_PACKETS_CMDID)) { 201 wmi_err("Failed to set neighbour rx param"); 202 wmi_buf_free(buf); 203 return QDF_STATUS_E_FAILURE; 204 } 205 206 return QDF_STATUS_SUCCESS; 207 } 208 209 static QDF_STATUS 210 extract_vdev_start_resp_tlv(struct wmi_unified *wmi_handle, void *evt_buf, 211 struct vdev_start_response *vdev_rsp) 212 { 213 WMI_VDEV_START_RESP_EVENTID_param_tlvs *param_buf; 214 wmi_vdev_start_response_event_fixed_param *ev; 215 216 param_buf = (WMI_VDEV_START_RESP_EVENTID_param_tlvs *)evt_buf; 217 if (!param_buf) { 218 wmi_err("Invalid start response event buffer"); 219 return QDF_STATUS_E_INVAL; 220 } 221 222 ev = param_buf->fixed_param; 223 if (!ev) { 224 wmi_err("Invalid start response event buffer"); 225 return QDF_STATUS_E_INVAL; 226 } 227 228 qdf_mem_zero(vdev_rsp, sizeof(*vdev_rsp)); 229 230 vdev_rsp->vdev_id = ev->vdev_id; 231 vdev_rsp->requestor_id = ev->requestor_id; 232 switch (ev->resp_type) { 233 case WMI_VDEV_START_RESP_EVENT: 234 vdev_rsp->resp_type = WMI_HOST_VDEV_START_RESP_EVENT; 235 break; 236 case WMI_VDEV_RESTART_RESP_EVENT: 237 vdev_rsp->resp_type = WMI_HOST_VDEV_RESTART_RESP_EVENT; 238 break; 239 default: 240 wmi_err("Invalid start response event buffer"); 241 break; 242 }; 243 vdev_rsp->status = ev->status; 244 vdev_rsp->chain_mask = ev->chain_mask; 245 vdev_rsp->smps_mode = ev->smps_mode; 246 vdev_rsp->mac_id = ev->mac_id; 247 vdev_rsp->cfgd_tx_streams = ev->cfgd_tx_streams; 248 vdev_rsp->cfgd_rx_streams = ev->cfgd_rx_streams; 249 vdev_rsp->max_allowed_tx_power = ev->max_allowed_tx_power; 250 251 return QDF_STATUS_SUCCESS; 252 } 253 254 static QDF_STATUS 255 extract_vdev_delete_resp_tlv(struct wmi_unified *wmi_handle, void *evt_buf, 256 struct vdev_delete_response *delete_rsp) 257 { 258 WMI_VDEV_DELETE_RESP_EVENTID_param_tlvs *param_buf; 259 wmi_vdev_delete_resp_event_fixed_param *ev; 260 261 param_buf = (WMI_VDEV_DELETE_RESP_EVENTID_param_tlvs *)evt_buf; 262 if (!param_buf) { 263 wmi_err("Invalid vdev delete response event buffer"); 264 return QDF_STATUS_E_INVAL; 265 } 266 267 ev = param_buf->fixed_param; 268 if (!ev) { 269 wmi_err("Invalid vdev delete response event"); 270 return QDF_STATUS_E_INVAL; 271 } 272 273 qdf_mem_zero(delete_rsp, sizeof(*delete_rsp)); 274 delete_rsp->vdev_id = ev->vdev_id; 275 276 return QDF_STATUS_SUCCESS; 277 } 278 279 static QDF_STATUS extract_vdev_peer_delete_all_response_event_tlv( 280 wmi_unified_t wmi_hdl, 281 void *evt_buf, 282 struct peer_delete_all_response *param) 283 { 284 WMI_VDEV_DELETE_ALL_PEER_RESP_EVENTID_param_tlvs *param_buf; 285 wmi_vdev_delete_all_peer_resp_event_fixed_param *ev; 286 287 param_buf = (WMI_VDEV_DELETE_ALL_PEER_RESP_EVENTID_param_tlvs *)evt_buf; 288 289 ev = (wmi_vdev_delete_all_peer_resp_event_fixed_param *) 290 param_buf->fixed_param; 291 if (!ev) { 292 wmi_err("Invalid peer_delete all response"); 293 return QDF_STATUS_E_FAILURE; 294 } 295 296 param->vdev_id = ev->vdev_id; 297 param->status = ev->status; 298 299 return QDF_STATUS_SUCCESS; 300 } 301 302 static QDF_STATUS 303 extract_vdev_stopped_param_tlv(struct wmi_unified *wmi_handle, 304 void *evt_buf, uint32_t *vdev_id) 305 { 306 WMI_VDEV_STOPPED_EVENTID_param_tlvs *param_buf; 307 wmi_vdev_stopped_event_fixed_param *resp_event; 308 309 param_buf = (WMI_VDEV_STOPPED_EVENTID_param_tlvs *)evt_buf; 310 if (!param_buf) { 311 wmi_err("Invalid event buffer"); 312 return QDF_STATUS_E_INVAL; 313 } 314 resp_event = param_buf->fixed_param; 315 *vdev_id = resp_event->vdev_id; 316 317 return QDF_STATUS_SUCCESS; 318 } 319 320 static QDF_STATUS extract_ext_tbttoffset_num_vdevs_tlv( 321 wmi_unified_t wmi_hdl, 322 void *evt_buf, 323 uint32_t *num_vdevs) 324 { 325 WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *param_buf; 326 wmi_tbtt_offset_ext_event_fixed_param *tbtt_offset_ext_event; 327 328 param_buf = (WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *)evt_buf; 329 if (!param_buf) { 330 wmi_err("Invalid tbtt update ext event buffer"); 331 return QDF_STATUS_E_INVAL; 332 } 333 tbtt_offset_ext_event = param_buf->fixed_param; 334 335 *num_vdevs = tbtt_offset_ext_event->num_vdevs; 336 337 return QDF_STATUS_SUCCESS; 338 } 339 340 static QDF_STATUS extract_tbttoffset_update_params_tlv( 341 wmi_unified_t wmi_hdl, 342 void *evt_buf, uint8_t idx, 343 struct tbttoffset_params *tbtt_param) 344 { 345 WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf; 346 wmi_tbtt_offset_event_fixed_param *tbtt_offset_event; 347 uint32_t vdev_map; 348 349 param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *)evt_buf; 350 if (!param_buf) { 351 wmi_err("Invalid tbtt update event buffer"); 352 return QDF_STATUS_E_INVAL; 353 } 354 355 tbtt_offset_event = param_buf->fixed_param; 356 vdev_map = tbtt_offset_event->vdev_map; 357 tbtt_param->vdev_id = wmi_vdev_map_to_vdev_id(vdev_map, idx); 358 if (tbtt_param->vdev_id == WLAN_INVALID_VDEV_ID) 359 return QDF_STATUS_E_INVAL; 360 tbtt_param->tbttoffset = 361 param_buf->tbttoffset_list[tbtt_param->vdev_id]; 362 if (param_buf->tbtt_qtime_low_us_list) 363 tbtt_param->vdev_tbtt_qtime_lo = 364 param_buf->tbtt_qtime_low_us_list[tbtt_param->vdev_id]; 365 if (param_buf->tbtt_qtime_high_us_list) 366 tbtt_param->vdev_tbtt_qtime_hi = 367 param_buf->tbtt_qtime_high_us_list[tbtt_param->vdev_id]; 368 369 return QDF_STATUS_SUCCESS; 370 } 371 372 static QDF_STATUS extract_ext_tbttoffset_update_params_tlv( 373 wmi_unified_t wmi_hdl, 374 void *evt_buf, uint8_t idx, 375 struct tbttoffset_params *tbtt_param) 376 { 377 WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *param_buf; 378 wmi_tbtt_offset_info *tbtt_offset_info; 379 380 param_buf = (WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *)evt_buf; 381 if (!param_buf) { 382 wmi_err("Invalid tbtt update event buffer"); 383 return QDF_STATUS_E_INVAL; 384 } 385 tbtt_offset_info = ¶m_buf->tbtt_offset_info[idx]; 386 387 tbtt_param->vdev_id = tbtt_offset_info->vdev_id; 388 tbtt_param->tbttoffset = tbtt_offset_info->tbttoffset; 389 tbtt_param->vdev_tbtt_qtime_lo = tbtt_offset_info->tbtt_qtime_low_us; 390 tbtt_param->vdev_tbtt_qtime_hi = tbtt_offset_info->tbtt_qtime_high_us; 391 392 return QDF_STATUS_SUCCESS; 393 } 394 395 static QDF_STATUS extract_muedca_params_tlv(wmi_unified_t wmi_hdl, 396 void *evt_buf, 397 struct muedca_params *muedca_param_list) 398 { 399 WMI_MUEDCA_PARAMS_CONFIG_EVENTID_param_tlvs *param_buf; 400 wmi_muedca_params_config_event_fixed_param *muedca_param; 401 int i; 402 403 param_buf = (WMI_MUEDCA_PARAMS_CONFIG_EVENTID_param_tlvs *)evt_buf; 404 if (!param_buf) { 405 wmi_err("Invalid muedca evt buffer"); 406 return QDF_STATUS_E_INVAL; 407 } 408 muedca_param = param_buf->fixed_param; 409 410 muedca_param_list->pdev_id = wmi_hdl->ops-> 411 convert_target_pdev_id_to_host(wmi_hdl, 412 muedca_param->pdev_id); 413 for (i = 0; i < WMI_AC_MAX; i++) { 414 muedca_param_list->muedca_aifsn[i] = muedca_param->aifsn[i] & 415 WMI_MUEDCA_PARAM_MASK; 416 muedca_param_list->muedca_ecwmin[i] = muedca_param->ecwmin[i] & 417 WMI_MUEDCA_PARAM_MASK; 418 muedca_param_list->muedca_ecwmax[i] = muedca_param->ecwmax[i] & 419 WMI_MUEDCA_PARAM_MASK; 420 muedca_param_list->muedca_timer[i] = muedca_param->muedca_expiration_time[i] & 421 WMI_MUEDCA_PARAM_MASK; 422 } 423 424 return QDF_STATUS_SUCCESS; 425 } 426 427 void wmi_vdev_attach_tlv(struct wmi_unified *wmi_handle) 428 { 429 struct wmi_ops *wmi_ops; 430 431 if (!wmi_handle) { 432 wmi_err("null wmi handle"); 433 return; 434 } 435 436 wmi_ops = wmi_handle->ops; 437 wmi_ops->extract_vdev_delete_resp = extract_vdev_delete_resp_tlv; 438 wmi_ops->extract_vdev_stopped_param = extract_vdev_stopped_param_tlv; 439 wmi_ops->extract_vdev_start_resp = extract_vdev_start_resp_tlv; 440 wmi_ops->extract_vdev_peer_delete_all_response_event = 441 extract_vdev_peer_delete_all_response_event_tlv; 442 wmi_ops->extract_tbttoffset_num_vdevs = 443 extract_tbttoffset_num_vdevs_tlv; 444 wmi_ops->extract_tbttoffset_update_params = 445 extract_tbttoffset_update_params_tlv; 446 wmi_ops->extract_ext_tbttoffset_update_params = 447 extract_ext_tbttoffset_update_params_tlv; 448 wmi_ops->extract_ext_tbttoffset_num_vdevs = 449 extract_ext_tbttoffset_num_vdevs_tlv; 450 wmi_ops->extract_muedca_params_handler = 451 extract_muedca_params_tlv; 452 wmi_ops->send_vdev_set_neighbour_rx_cmd = 453 send_vdev_set_neighbour_rx_cmd_tlv; 454 wmi_ops->send_beacon_send_cmd = send_beacon_send_cmd_tlv; 455 wmi_ops->send_vdev_config_ratemask_cmd = 456 send_vdev_config_ratemask_cmd_tlv; 457 wmi_ops->send_peer_filter_set_tx_cmd = send_peer_filter_set_tx_cmd_tlv; 458 } 459