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