1 2 /* 3 * Copyright (c) 2018 The Linux Foundation. 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 "wmi.h" 22 #include "wmi_unified_priv.h" 23 #include "wmi_unified_twt_param.h" 24 #include "wmi_unified_twt_api.h" 25 26 static QDF_STATUS send_twt_enable_cmd_tlv(wmi_unified_t wmi_handle, 27 struct wmi_twt_enable_param *params) 28 { 29 wmi_twt_enable_cmd_fixed_param *cmd; 30 wmi_buf_t buf; 31 QDF_STATUS status; 32 33 buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd)); 34 if (!buf) { 35 WMI_LOGE("Failed to allocate memory"); 36 return QDF_STATUS_E_FAILURE; 37 } 38 39 cmd = (wmi_twt_enable_cmd_fixed_param *) wmi_buf_data(buf); 40 WMITLV_SET_HDR(&cmd->tlv_header, 41 WMITLV_TAG_STRUC_wmi_twt_enable_cmd_fixed_param, 42 WMITLV_GET_STRUCT_TLVLEN 43 (wmi_twt_enable_cmd_fixed_param)); 44 45 cmd->pdev_id = 46 wmi_handle->ops->convert_pdev_id_host_to_target( 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 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 242 status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd), 243 WMI_TWT_RESUME_DIALOG_CMDID); 244 if (QDF_IS_STATUS_ERROR(status)) { 245 WMI_LOGE("Failed to send WMI_TWT_RESUME_DIALOG_CMDID"); 246 wmi_buf_free(buf); 247 } 248 249 return status; 250 } 251 252 static QDF_STATUS extract_twt_enable_comp_event_tlv(wmi_unified_t wmi_handle, 253 uint8_t *evt_buf, 254 struct wmi_twt_enable_complete_event_param *params) 255 { 256 WMI_TWT_ENABLE_COMPLETE_EVENTID_param_tlvs *param_buf; 257 wmi_twt_enable_complete_event_fixed_param *ev; 258 259 param_buf = (WMI_TWT_ENABLE_COMPLETE_EVENTID_param_tlvs *)evt_buf; 260 if (!param_buf) { 261 WMI_LOGE("evt_buf is NULL"); 262 return QDF_STATUS_E_INVAL; 263 } 264 265 ev = param_buf->fixed_param; 266 267 params->pdev_id = 268 wmi_handle->ops->convert_pdev_id_target_to_host(ev->pdev_id); 269 params->status = ev->status; 270 271 return QDF_STATUS_SUCCESS; 272 } 273 274 static QDF_STATUS extract_twt_disable_comp_event_tlv(wmi_unified_t wmi_handle, 275 uint8_t *evt_buf, 276 struct wmi_twt_disable_complete_event *params) 277 { 278 WMI_TWT_DISABLE_COMPLETE_EVENTID_param_tlvs *param_buf; 279 wmi_twt_disable_complete_event_fixed_param *ev; 280 281 param_buf = (WMI_TWT_DISABLE_COMPLETE_EVENTID_param_tlvs *)evt_buf; 282 if (!param_buf) { 283 WMI_LOGE("evt_buf is NULL"); 284 return QDF_STATUS_E_INVAL; 285 } 286 287 ev = param_buf->fixed_param; 288 289 #if 0 290 params->pdev_id = 291 wmi_handle->ops->convert_pdev_id_target_to_host(ev->pdev_id); 292 params->status = ev->status; 293 #endif 294 295 return QDF_STATUS_SUCCESS; 296 } 297 298 static QDF_STATUS extract_twt_add_dialog_comp_event_tlv( 299 wmi_unified_t wmi_handle, 300 uint8_t *evt_buf, 301 struct wmi_twt_add_dialog_complete_event_param *params) 302 { 303 WMI_TWT_ADD_DIALOG_COMPLETE_EVENTID_param_tlvs *param_buf; 304 wmi_twt_add_dialog_complete_event_fixed_param *ev; 305 306 param_buf = (WMI_TWT_ADD_DIALOG_COMPLETE_EVENTID_param_tlvs *)evt_buf; 307 if (!param_buf) { 308 WMI_LOGE("evt_buf is NULL"); 309 return QDF_STATUS_E_INVAL; 310 } 311 312 ev = param_buf->fixed_param; 313 314 params->vdev_id = ev->vdev_id; 315 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr, params->peer_macaddr); 316 params->status = ev->status; 317 params->dialog_id = ev->dialog_id; 318 319 return QDF_STATUS_SUCCESS; 320 } 321 322 static QDF_STATUS extract_twt_del_dialog_comp_event_tlv( 323 wmi_unified_t wmi_handle, 324 uint8_t *evt_buf, 325 struct wmi_twt_del_dialog_complete_event_param *params) 326 { 327 WMI_TWT_DEL_DIALOG_COMPLETE_EVENTID_param_tlvs *param_buf; 328 wmi_twt_del_dialog_complete_event_fixed_param *ev; 329 330 param_buf = (WMI_TWT_DEL_DIALOG_COMPLETE_EVENTID_param_tlvs *)evt_buf; 331 if (!param_buf) { 332 WMI_LOGE("evt_buf is NULL"); 333 return QDF_STATUS_E_INVAL; 334 } 335 336 ev = param_buf->fixed_param; 337 338 params->vdev_id = ev->vdev_id; 339 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr, params->peer_macaddr); 340 params->dialog_id = ev->dialog_id; 341 342 return QDF_STATUS_SUCCESS; 343 } 344 345 static QDF_STATUS extract_twt_pause_dialog_comp_event_tlv( 346 wmi_unified_t wmi_handle, 347 uint8_t *evt_buf, 348 struct wmi_twt_pause_dialog_complete_event_param *params) 349 { 350 WMI_TWT_PAUSE_DIALOG_COMPLETE_EVENTID_param_tlvs *param_buf; 351 wmi_twt_pause_dialog_complete_event_fixed_param *ev; 352 353 param_buf = (WMI_TWT_PAUSE_DIALOG_COMPLETE_EVENTID_param_tlvs *)evt_buf; 354 if (!param_buf) { 355 WMI_LOGE("evt_buf is NULL"); 356 return QDF_STATUS_E_INVAL; 357 } 358 359 ev = param_buf->fixed_param; 360 361 params->vdev_id = ev->vdev_id; 362 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr, params->peer_macaddr); 363 params->status = ev->status; 364 params->dialog_id = ev->dialog_id; 365 366 return QDF_STATUS_SUCCESS; 367 } 368 369 static QDF_STATUS extract_twt_resume_dialog_comp_event_tlv( 370 wmi_unified_t wmi_handle, 371 uint8_t *evt_buf, 372 struct wmi_twt_resume_dialog_complete_event_param *params) 373 { 374 WMI_TWT_RESUME_DIALOG_COMPLETE_EVENTID_param_tlvs *param_buf; 375 wmi_twt_resume_dialog_complete_event_fixed_param *ev; 376 377 param_buf = 378 (WMI_TWT_RESUME_DIALOG_COMPLETE_EVENTID_param_tlvs *)evt_buf; 379 if (!param_buf) { 380 WMI_LOGE("evt_buf is NULL"); 381 return QDF_STATUS_E_INVAL; 382 } 383 384 ev = param_buf->fixed_param; 385 386 params->vdev_id = ev->vdev_id; 387 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr, params->peer_macaddr); 388 params->status = ev->status; 389 params->dialog_id = ev->dialog_id; 390 391 return QDF_STATUS_SUCCESS; 392 } 393 394 void wmi_twt_attach_tlv(wmi_unified_t wmi_handle) 395 { 396 struct wmi_ops *ops = wmi_handle->ops; 397 398 ops->send_twt_enable_cmd = send_twt_enable_cmd_tlv; 399 ops->send_twt_disable_cmd = send_twt_disable_cmd_tlv; 400 ops->send_twt_add_dialog_cmd = send_twt_add_dialog_cmd_tlv; 401 ops->send_twt_del_dialog_cmd = send_twt_del_dialog_cmd_tlv; 402 ops->send_twt_pause_dialog_cmd = send_twt_pause_dialog_cmd_tlv; 403 ops->send_twt_resume_dialog_cmd = send_twt_resume_dialog_cmd_tlv; 404 ops->extract_twt_enable_comp_event = extract_twt_enable_comp_event_tlv; 405 ops->extract_twt_disable_comp_event = 406 extract_twt_disable_comp_event_tlv; 407 ops->extract_twt_add_dialog_comp_event = 408 extract_twt_add_dialog_comp_event_tlv; 409 ops->extract_twt_del_dialog_comp_event = 410 extract_twt_del_dialog_comp_event_tlv; 411 ops->extract_twt_pause_dialog_comp_event = 412 extract_twt_pause_dialog_comp_event_tlv; 413 ops->extract_twt_resume_dialog_comp_event = 414 extract_twt_resume_dialog_comp_event_tlv; 415 } 416