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 <osdep.h> 20 #include "wmi.h" 21 #include "wmi_unified_priv.h" 22 #include "wmi_unified_twt_param.h" 23 #include "wmi_unified_twt_api.h" 24 25 static QDF_STATUS send_twt_enable_cmd_tlv(wmi_unified_t wmi_handle, 26 struct wmi_twt_enable_param *params) 27 { 28 wmi_twt_enable_cmd_fixed_param *cmd; 29 wmi_buf_t buf; 30 QDF_STATUS status; 31 32 buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd)); 33 if (!buf) { 34 WMI_LOGE("Failed to allocate memory"); 35 return QDF_STATUS_E_FAILURE; 36 } 37 38 cmd = (wmi_twt_enable_cmd_fixed_param *) wmi_buf_data(buf); 39 WMITLV_SET_HDR(&cmd->tlv_header, 40 WMITLV_TAG_STRUC_wmi_twt_enable_cmd_fixed_param, 41 WMITLV_GET_STRUCT_TLVLEN 42 (wmi_twt_enable_cmd_fixed_param)); 43 44 cmd->pdev_id = 45 wmi_handle->ops->convert_pdev_id_host_to_target( 46 wmi_handle, 47 params->pdev_id); 48 cmd->sta_cong_timer_ms = params->sta_cong_timer_ms; 49 cmd->mbss_support = params->mbss_support; 50 cmd->default_slot_size = params->default_slot_size; 51 cmd->congestion_thresh_setup = params->congestion_thresh_setup; 52 cmd->congestion_thresh_teardown = params->congestion_thresh_teardown; 53 cmd->congestion_thresh_critical = params->congestion_thresh_critical; 54 cmd->interference_thresh_teardown = 55 params->interference_thresh_teardown; 56 cmd->interference_thresh_setup = params->interference_thresh_setup; 57 cmd->min_no_sta_setup = params->min_no_sta_setup; 58 cmd->min_no_sta_teardown = params->min_no_sta_teardown; 59 cmd->no_of_bcast_mcast_slots = params->no_of_bcast_mcast_slots; 60 cmd->min_no_twt_slots = params->min_no_twt_slots; 61 cmd->max_no_sta_twt = params->max_no_sta_twt; 62 cmd->mode_check_interval = params->mode_check_interval; 63 cmd->add_sta_slot_interval = params->add_sta_slot_interval; 64 cmd->remove_sta_slot_interval = params->remove_sta_slot_interval; 65 cmd->flags = params->flags; 66 67 status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd), 68 WMI_TWT_ENABLE_CMDID); 69 if (QDF_IS_STATUS_ERROR(status)) { 70 WMI_LOGE("Failed to send WMI_TWT_ENABLE_CMDID"); 71 wmi_buf_free(buf); 72 } 73 74 return status; 75 } 76 77 78 static QDF_STATUS send_twt_disable_cmd_tlv(wmi_unified_t wmi_handle, 79 struct wmi_twt_disable_param *params) 80 { 81 wmi_twt_disable_cmd_fixed_param *cmd; 82 wmi_buf_t buf; 83 QDF_STATUS status; 84 85 buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd)); 86 if (!buf) { 87 WMI_LOGE("Failed to allocate memory"); 88 return QDF_STATUS_E_FAILURE; 89 } 90 91 cmd = (wmi_twt_disable_cmd_fixed_param *) wmi_buf_data(buf); 92 WMITLV_SET_HDR(&cmd->tlv_header, 93 WMITLV_TAG_STRUC_wmi_twt_disable_cmd_fixed_param, 94 WMITLV_GET_STRUCT_TLVLEN 95 (wmi_twt_disable_cmd_fixed_param)); 96 97 cmd->pdev_id = 98 wmi_handle->ops->convert_pdev_id_host_to_target( 99 wmi_handle, 100 params->pdev_id); 101 102 status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd), 103 WMI_TWT_DISABLE_CMDID); 104 if (QDF_IS_STATUS_ERROR(status)) { 105 WMI_LOGE("Failed to send WMI_TWT_DISABLE_CMDID"); 106 wmi_buf_free(buf); 107 } 108 109 return status; 110 } 111 112 static QDF_STATUS send_twt_add_dialog_cmd_tlv(wmi_unified_t wmi_handle, 113 struct wmi_twt_add_dialog_param *params) 114 { 115 wmi_twt_add_dialog_cmd_fixed_param *cmd; 116 wmi_buf_t buf; 117 QDF_STATUS status; 118 119 buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd)); 120 if (!buf) { 121 WMI_LOGE("Failed to allocate memory"); 122 return QDF_STATUS_E_FAILURE; 123 } 124 125 cmd = (wmi_twt_add_dialog_cmd_fixed_param *) wmi_buf_data(buf); 126 WMITLV_SET_HDR(&cmd->tlv_header, 127 WMITLV_TAG_STRUC_wmi_twt_add_dialog_cmd_fixed_param, 128 WMITLV_GET_STRUCT_TLVLEN 129 (wmi_twt_add_dialog_cmd_fixed_param)); 130 131 cmd->vdev_id = params->vdev_id; 132 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->peer_macaddr, &cmd->peer_macaddr); 133 cmd->dialog_id = params->dialog_id; 134 cmd->wake_intvl_us = params->wake_intvl_us; 135 cmd->wake_intvl_mantis = params->wake_intvl_mantis; 136 cmd->wake_dura_us = params->wake_dura_us; 137 cmd->sp_offset_us = params->sp_offset_us; 138 TWT_FLAGS_SET_CMD(cmd->flags, params->twt_cmd); 139 TWT_FLAGS_SET_BROADCAST(cmd->flags, params->flag_bcast); 140 TWT_FLAGS_SET_TRIGGER(cmd->flags, params->flag_trigger); 141 TWT_FLAGS_SET_FLOW_TYPE(cmd->flags, params->flag_flow_type); 142 TWT_FLAGS_SET_PROTECTION(cmd->flags, params->flag_protection); 143 144 status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd), 145 WMI_TWT_ADD_DIALOG_CMDID); 146 if (QDF_IS_STATUS_ERROR(status)) { 147 WMI_LOGE("Failed to send WMI_TWT_ADD_DIALOG_CMDID"); 148 wmi_buf_free(buf); 149 } 150 151 return status; 152 } 153 154 static QDF_STATUS send_twt_del_dialog_cmd_tlv(wmi_unified_t wmi_handle, 155 struct wmi_twt_del_dialog_param *params) 156 { 157 wmi_twt_del_dialog_cmd_fixed_param *cmd; 158 wmi_buf_t buf; 159 QDF_STATUS status; 160 161 buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd)); 162 if (!buf) { 163 WMI_LOGE("Failed to allocate memory"); 164 return QDF_STATUS_E_FAILURE; 165 } 166 167 cmd = (wmi_twt_del_dialog_cmd_fixed_param *) wmi_buf_data(buf); 168 WMITLV_SET_HDR(&cmd->tlv_header, 169 WMITLV_TAG_STRUC_wmi_twt_del_dialog_cmd_fixed_param, 170 WMITLV_GET_STRUCT_TLVLEN 171 (wmi_twt_del_dialog_cmd_fixed_param)); 172 173 cmd->vdev_id = params->vdev_id; 174 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->peer_macaddr, &cmd->peer_macaddr); 175 cmd->dialog_id = params->dialog_id; 176 177 status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd), 178 WMI_TWT_DEL_DIALOG_CMDID); 179 if (QDF_IS_STATUS_ERROR(status)) { 180 WMI_LOGE("Failed to send WMI_TWT_DEL_DIALOG_CMDID"); 181 wmi_buf_free(buf); 182 } 183 184 return status; 185 } 186 187 static QDF_STATUS send_twt_pause_dialog_cmd_tlv(wmi_unified_t wmi_handle, 188 struct wmi_twt_pause_dialog_cmd_param *params) 189 { 190 wmi_twt_pause_dialog_cmd_fixed_param *cmd; 191 wmi_buf_t buf; 192 QDF_STATUS status; 193 194 buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd)); 195 if (!buf) { 196 WMI_LOGE("Failed to allocate memory"); 197 return QDF_STATUS_E_FAILURE; 198 } 199 200 cmd = (wmi_twt_pause_dialog_cmd_fixed_param *) wmi_buf_data(buf); 201 WMITLV_SET_HDR(&cmd->tlv_header, 202 WMITLV_TAG_STRUC_wmi_twt_pause_dialog_cmd_fixed_param, 203 WMITLV_GET_STRUCT_TLVLEN 204 (wmi_twt_pause_dialog_cmd_fixed_param)); 205 206 cmd->vdev_id = params->vdev_id; 207 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->peer_macaddr, &cmd->peer_macaddr); 208 cmd->dialog_id = params->dialog_id; 209 210 status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd), 211 WMI_TWT_PAUSE_DIALOG_CMDID); 212 if (QDF_IS_STATUS_ERROR(status)) { 213 WMI_LOGE("Failed to send WMI_TWT_PAUSE_DIALOG_CMDID"); 214 wmi_buf_free(buf); 215 } 216 217 return status; 218 } 219 220 static QDF_STATUS send_twt_resume_dialog_cmd_tlv(wmi_unified_t wmi_handle, 221 struct wmi_twt_resume_dialog_cmd_param *params) 222 { 223 wmi_twt_resume_dialog_cmd_fixed_param *cmd; 224 wmi_buf_t buf; 225 QDF_STATUS status; 226 227 buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd)); 228 if (!buf) { 229 WMI_LOGE("Failed to allocate memory"); 230 return QDF_STATUS_E_FAILURE; 231 } 232 233 cmd = (wmi_twt_resume_dialog_cmd_fixed_param *) wmi_buf_data(buf); 234 WMITLV_SET_HDR(&cmd->tlv_header, 235 WMITLV_TAG_STRUC_wmi_twt_resume_dialog_cmd_fixed_param, 236 WMITLV_GET_STRUCT_TLVLEN 237 (wmi_twt_resume_dialog_cmd_fixed_param)); 238 239 cmd->vdev_id = params->vdev_id; 240 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->peer_macaddr, &cmd->peer_macaddr); 241 cmd->dialog_id = params->dialog_id; 242 cmd->sp_offset_us = params->sp_offset_us; 243 cmd->next_twt_size = params->next_twt_size; 244 245 status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd), 246 WMI_TWT_RESUME_DIALOG_CMDID); 247 if (QDF_IS_STATUS_ERROR(status)) { 248 WMI_LOGE("Failed to send WMI_TWT_RESUME_DIALOG_CMDID"); 249 wmi_buf_free(buf); 250 } 251 252 return status; 253 } 254 255 static QDF_STATUS extract_twt_enable_comp_event_tlv(wmi_unified_t wmi_handle, 256 uint8_t *evt_buf, 257 struct wmi_twt_enable_complete_event_param *params) 258 { 259 WMI_TWT_ENABLE_COMPLETE_EVENTID_param_tlvs *param_buf; 260 wmi_twt_enable_complete_event_fixed_param *ev; 261 262 param_buf = (WMI_TWT_ENABLE_COMPLETE_EVENTID_param_tlvs *)evt_buf; 263 if (!param_buf) { 264 WMI_LOGE("evt_buf is NULL"); 265 return QDF_STATUS_E_INVAL; 266 } 267 268 ev = param_buf->fixed_param; 269 270 params->pdev_id = 271 wmi_handle->ops->convert_pdev_id_target_to_host(wmi_handle, 272 ev->pdev_id); 273 params->status = ev->status; 274 275 return QDF_STATUS_SUCCESS; 276 } 277 278 static QDF_STATUS extract_twt_disable_comp_event_tlv(wmi_unified_t wmi_handle, 279 uint8_t *evt_buf, 280 struct wmi_twt_disable_complete_event *params) 281 { 282 WMI_TWT_DISABLE_COMPLETE_EVENTID_param_tlvs *param_buf; 283 wmi_twt_disable_complete_event_fixed_param *ev; 284 285 param_buf = (WMI_TWT_DISABLE_COMPLETE_EVENTID_param_tlvs *)evt_buf; 286 if (!param_buf) { 287 WMI_LOGE("evt_buf is NULL"); 288 return QDF_STATUS_E_INVAL; 289 } 290 291 ev = param_buf->fixed_param; 292 293 #if 0 294 params->pdev_id = 295 wmi_handle->ops->convert_pdev_id_target_to_host(ev->pdev_id); 296 params->status = ev->status; 297 #endif 298 299 return QDF_STATUS_SUCCESS; 300 } 301 302 static QDF_STATUS extract_twt_add_dialog_comp_event_tlv( 303 wmi_unified_t wmi_handle, 304 uint8_t *evt_buf, 305 struct wmi_twt_add_dialog_complete_event_param *params) 306 { 307 WMI_TWT_ADD_DIALOG_COMPLETE_EVENTID_param_tlvs *param_buf; 308 wmi_twt_add_dialog_complete_event_fixed_param *ev; 309 310 param_buf = (WMI_TWT_ADD_DIALOG_COMPLETE_EVENTID_param_tlvs *)evt_buf; 311 if (!param_buf) { 312 WMI_LOGE("evt_buf is NULL"); 313 return QDF_STATUS_E_INVAL; 314 } 315 316 ev = param_buf->fixed_param; 317 318 params->vdev_id = ev->vdev_id; 319 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr, params->peer_macaddr); 320 params->status = ev->status; 321 params->dialog_id = ev->dialog_id; 322 323 return QDF_STATUS_SUCCESS; 324 } 325 326 static QDF_STATUS extract_twt_del_dialog_comp_event_tlv( 327 wmi_unified_t wmi_handle, 328 uint8_t *evt_buf, 329 struct wmi_twt_del_dialog_complete_event_param *params) 330 { 331 WMI_TWT_DEL_DIALOG_COMPLETE_EVENTID_param_tlvs *param_buf; 332 wmi_twt_del_dialog_complete_event_fixed_param *ev; 333 334 param_buf = (WMI_TWT_DEL_DIALOG_COMPLETE_EVENTID_param_tlvs *)evt_buf; 335 if (!param_buf) { 336 WMI_LOGE("evt_buf is NULL"); 337 return QDF_STATUS_E_INVAL; 338 } 339 340 ev = param_buf->fixed_param; 341 342 params->vdev_id = ev->vdev_id; 343 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr, params->peer_macaddr); 344 params->dialog_id = ev->dialog_id; 345 346 return QDF_STATUS_SUCCESS; 347 } 348 349 static QDF_STATUS extract_twt_pause_dialog_comp_event_tlv( 350 wmi_unified_t wmi_handle, 351 uint8_t *evt_buf, 352 struct wmi_twt_pause_dialog_complete_event_param *params) 353 { 354 WMI_TWT_PAUSE_DIALOG_COMPLETE_EVENTID_param_tlvs *param_buf; 355 wmi_twt_pause_dialog_complete_event_fixed_param *ev; 356 357 param_buf = (WMI_TWT_PAUSE_DIALOG_COMPLETE_EVENTID_param_tlvs *)evt_buf; 358 if (!param_buf) { 359 WMI_LOGE("evt_buf is NULL"); 360 return QDF_STATUS_E_INVAL; 361 } 362 363 ev = param_buf->fixed_param; 364 365 params->vdev_id = ev->vdev_id; 366 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr, params->peer_macaddr); 367 params->status = ev->status; 368 params->dialog_id = ev->dialog_id; 369 370 return QDF_STATUS_SUCCESS; 371 } 372 373 static QDF_STATUS extract_twt_resume_dialog_comp_event_tlv( 374 wmi_unified_t wmi_handle, 375 uint8_t *evt_buf, 376 struct wmi_twt_resume_dialog_complete_event_param *params) 377 { 378 WMI_TWT_RESUME_DIALOG_COMPLETE_EVENTID_param_tlvs *param_buf; 379 wmi_twt_resume_dialog_complete_event_fixed_param *ev; 380 381 param_buf = 382 (WMI_TWT_RESUME_DIALOG_COMPLETE_EVENTID_param_tlvs *)evt_buf; 383 if (!param_buf) { 384 WMI_LOGE("evt_buf is NULL"); 385 return QDF_STATUS_E_INVAL; 386 } 387 388 ev = param_buf->fixed_param; 389 390 params->vdev_id = ev->vdev_id; 391 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr, params->peer_macaddr); 392 params->status = ev->status; 393 params->dialog_id = ev->dialog_id; 394 395 return QDF_STATUS_SUCCESS; 396 } 397 398 void wmi_twt_attach_tlv(wmi_unified_t wmi_handle) 399 { 400 struct wmi_ops *ops = wmi_handle->ops; 401 402 ops->send_twt_enable_cmd = send_twt_enable_cmd_tlv; 403 ops->send_twt_disable_cmd = send_twt_disable_cmd_tlv; 404 ops->send_twt_add_dialog_cmd = send_twt_add_dialog_cmd_tlv; 405 ops->send_twt_del_dialog_cmd = send_twt_del_dialog_cmd_tlv; 406 ops->send_twt_pause_dialog_cmd = send_twt_pause_dialog_cmd_tlv; 407 ops->send_twt_resume_dialog_cmd = send_twt_resume_dialog_cmd_tlv; 408 ops->extract_twt_enable_comp_event = extract_twt_enable_comp_event_tlv; 409 ops->extract_twt_disable_comp_event = 410 extract_twt_disable_comp_event_tlv; 411 ops->extract_twt_add_dialog_comp_event = 412 extract_twt_add_dialog_comp_event_tlv; 413 ops->extract_twt_del_dialog_comp_event = 414 extract_twt_del_dialog_comp_event_tlv; 415 ops->extract_twt_pause_dialog_comp_event = 416 extract_twt_pause_dialog_comp_event_tlv; 417 ops->extract_twt_resume_dialog_comp_event = 418 extract_twt_resume_dialog_comp_event_tlv; 419 } 420