1 /* 2 * Copyright (c) 2016-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 /** 20 * @file cdp_txrx_misc.h 21 * @brief Define the host data path miscellaneous API functions 22 * called by the host control SW and the OS interface module 23 */ 24 #ifndef _CDP_TXRX_MISC_H_ 25 #define _CDP_TXRX_MISC_H_ 26 27 #include "cdp_txrx_handle.h" 28 /** 29 * cdp_tx_non_std() - Allow the control-path SW to send data frames 30 * 31 * @soc - data path soc handle 32 * @data_vdev - which vdev should transmit the tx data frames 33 * @tx_spec - what non-standard handling to apply to the tx data frames 34 * @msdu_list - NULL-terminated list of tx MSDUs 35 * 36 * Generally, all tx data frames come from the OS shim into the txrx layer. 37 * However, there are rare cases such as TDLS messaging where the UMAC 38 * control-path SW creates tx data frames. 39 * This UMAC SW can call this function to provide the tx data frames to 40 * the txrx layer. 41 * The UMAC SW can request a callback for these data frames after their 42 * transmission completes, by using the ol_txrx_data_tx_cb_set function 43 * to register a tx completion callback, and by specifying 44 * ol_tx_spec_no_free as the tx_spec arg when giving the frames to 45 * ol_tx_non_std. 46 * The MSDUs need to have the appropriate L2 header type (802.3 vs. 802.11), 47 * as specified by ol_cfg_frame_type(). 48 * 49 * Return: null - success, skb - failure 50 */ 51 static inline qdf_nbuf_t 52 cdp_tx_non_std(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, 53 enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list) 54 { 55 if (!soc || !soc->ops || !soc->ops->misc_ops) { 56 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, 57 "%s invalid instance", __func__); 58 return NULL; 59 } 60 61 if (soc->ops->misc_ops->tx_non_std) 62 return soc->ops->misc_ops->tx_non_std( 63 vdev, tx_spec, msdu_list); 64 return NULL; 65 } 66 67 /** 68 * cdp_set_ibss_vdev_heart_beat_timer() - Update ibss vdev heart 69 * beat timer 70 * @soc - data path soc handle 71 * @vdev - vdev handle 72 * @timer_value_sec - new heart beat timer value 73 * 74 * Return: Old timer value set in vdev. 75 */ 76 static inline uint16_t 77 cdp_set_ibss_vdev_heart_beat_timer(ol_txrx_soc_handle soc, 78 struct cdp_vdev *vdev, uint16_t timer_value_sec) 79 { 80 if (!soc || !soc->ops || !soc->ops->misc_ops) { 81 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 82 "%s invalid instance", __func__); 83 return 0; 84 } 85 86 if (soc->ops->misc_ops->set_ibss_vdev_heart_beat_timer) 87 return soc->ops->misc_ops->set_ibss_vdev_heart_beat_timer( 88 vdev, timer_value_sec); 89 90 return 0; 91 } 92 93 /** 94 * cdp_set_wisa_mode() - set wisa mode 95 * @soc - data path soc handle 96 * @vdev - vdev handle 97 * @enable - enable or disable 98 * 99 * Return: QDF_STATUS_SUCCESS mode enable success 100 */ 101 static inline QDF_STATUS 102 cdp_set_wisa_mode(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, bool enable) 103 { 104 if (!soc || !soc->ops || !soc->ops->misc_ops) { 105 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 106 "%s invalid instance", __func__); 107 return QDF_STATUS_E_INVAL; 108 } 109 110 if (soc->ops->misc_ops->set_wisa_mode) 111 return soc->ops->misc_ops->set_wisa_mode(vdev, enable); 112 return QDF_STATUS_SUCCESS; 113 } 114 115 /** 116 * cdp_data_stall_cb_register() - register data stall callback 117 * @soc - data path soc handle 118 * @cb - callback function 119 * 120 * Return: QDF_STATUS_SUCCESS register success 121 */ 122 static inline QDF_STATUS cdp_data_stall_cb_register(ol_txrx_soc_handle soc, 123 data_stall_detect_cb cb) 124 { 125 if (!soc || !soc->ops || !soc->ops->misc_ops) { 126 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 127 "%s invalid instance", __func__); 128 return QDF_STATUS_E_INVAL; 129 } 130 131 if (soc->ops->misc_ops->txrx_data_stall_cb_register) 132 return soc->ops->misc_ops->txrx_data_stall_cb_register(cb); 133 return QDF_STATUS_SUCCESS; 134 } 135 136 /** 137 * cdp_data_stall_cb_deregister() - de-register data stall callback 138 * @soc - data path soc handle 139 * @cb - callback function 140 * 141 * Return: QDF_STATUS_SUCCESS de-register success 142 */ 143 static inline QDF_STATUS cdp_data_stall_cb_deregister(ol_txrx_soc_handle soc, 144 data_stall_detect_cb cb) 145 { 146 if (!soc || !soc->ops || !soc->ops->misc_ops) { 147 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 148 "%s invalid instance", __func__); 149 return QDF_STATUS_E_INVAL; 150 } 151 152 if (soc->ops->misc_ops->txrx_data_stall_cb_deregister) 153 return soc->ops->misc_ops->txrx_data_stall_cb_deregister(cb); 154 return QDF_STATUS_SUCCESS; 155 } 156 157 /** 158 * cdp_post_data_stall_event() - post data stall event 159 * @soc - data path soc handle 160 * @indicator: Module triggering data stall 161 * @data_stall_type: data stall event type 162 * @pdev_id: pdev id 163 * @vdev_id_bitmap: vdev id bitmap 164 * @recovery_type: data stall recovery type 165 * 166 * Return: None 167 */ 168 static inline void 169 cdp_post_data_stall_event(ol_txrx_soc_handle soc, 170 enum data_stall_log_event_indicator indicator, 171 enum data_stall_log_event_type data_stall_type, 172 uint32_t pdev_id, uint32_t vdev_id_bitmap, 173 enum data_stall_log_recovery_type recovery_type) 174 { 175 if (!soc || !soc->ops) { 176 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 177 "%s invalid instance", __func__); 178 QDF_BUG(0); 179 return; 180 } 181 182 if (!soc->ops->misc_ops || 183 !soc->ops->misc_ops->txrx_post_data_stall_event) 184 return; 185 186 soc->ops->misc_ops->txrx_post_data_stall_event( 187 indicator, data_stall_type, pdev_id, 188 vdev_id_bitmap, recovery_type); 189 } 190 191 /** 192 * cdp_set_wmm_param() - set wmm parameter 193 * @soc - data path soc handle 194 * @pdev - device instance pointer 195 * @wmm_param - wmm parameter 196 * 197 * Return: none 198 */ 199 static inline void 200 cdp_set_wmm_param(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, 201 struct ol_tx_wmm_param_t wmm_param) 202 { 203 if (!soc || !soc->ops || !soc->ops->misc_ops) { 204 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 205 "%s invalid instance", __func__); 206 return; 207 } 208 209 if (soc->ops->misc_ops->set_wmm_param) 210 return soc->ops->misc_ops->set_wmm_param( 211 pdev, wmm_param); 212 213 return; 214 } 215 216 /** 217 * cdp_runtime_suspend() - suspend 218 * @soc - data path soc handle 219 * @pdev - device instance pointer 220 * 221 * Return: QDF_STATUS_SUCCESS suspend success 222 */ 223 static inline QDF_STATUS cdp_runtime_suspend(ol_txrx_soc_handle soc, 224 struct cdp_pdev *pdev) 225 { 226 if (!soc || !soc->ops || !soc->ops->misc_ops) { 227 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 228 "%s invalid instance", __func__); 229 return QDF_STATUS_E_INVAL; 230 } 231 232 if (soc->ops->misc_ops->runtime_suspend) 233 return soc->ops->misc_ops->runtime_suspend(pdev); 234 235 return QDF_STATUS_SUCCESS; 236 } 237 238 /** 239 * cdp_runtime_resume() - resume 240 * @soc - data path soc handle 241 * @pdev - device instance pointer 242 * 243 * Return: QDF_STATUS_SUCCESS suspend success 244 */ 245 static inline QDF_STATUS cdp_runtime_resume(ol_txrx_soc_handle soc, 246 struct cdp_pdev *pdev) 247 { 248 if (!soc || !soc->ops || !soc->ops->misc_ops) { 249 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 250 "%s invalid instance", __func__); 251 return QDF_STATUS_E_INVAL; 252 } 253 254 if (soc->ops->misc_ops->runtime_resume) 255 return soc->ops->misc_ops->runtime_resume(pdev); 256 257 return QDF_STATUS_SUCCESS; 258 } 259 260 /** 261 * cdp_hl_tdls_flag_reset() - tdls flag reset 262 * @soc - data path soc handle 263 * @vdev - virtual interface handle pointer 264 * @flag 265 * 266 * Return: none 267 */ 268 static inline void 269 cdp_hl_tdls_flag_reset(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, bool flag) 270 { 271 if (!soc || !soc->ops || !soc->ops->misc_ops) { 272 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 273 "%s invalid instance", __func__); 274 return; 275 } 276 277 if (soc->ops->misc_ops->hl_tdls_flag_reset) 278 return soc->ops->misc_ops->hl_tdls_flag_reset(vdev, flag); 279 280 return; 281 } 282 283 /** 284 * cdp_get_opmode() - get vdev operation mode 285 * @soc - data path soc handle 286 * @vdev - virtual interface instance 287 * 288 * Return virtual device operational mode 289 * op_mode_ap, 290 * op_mode_ibss, 291 * op_mode_sta, 292 * op_mode_monitor, 293 * op_mode_ocb, 294 * 295 * return interface id 296 * 0 unknown interface 297 */ 298 static inline int 299 cdp_get_opmode(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) 300 { 301 if (!soc || !soc->ops || !soc->ops->misc_ops) { 302 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 303 "%s invalid instance", __func__); 304 return 0; 305 } 306 307 if (soc->ops->misc_ops->get_opmode) 308 return soc->ops->misc_ops->get_opmode(vdev); 309 return 0; 310 } 311 312 /** 313 * cdp_get_vdev_id() - get vdev id 314 * @soc - data path soc handle 315 * @vdev - virtual interface instance 316 * 317 * get virtual interface id 318 * 319 * return interface id 320 * 0 unknown interface 321 */ 322 static inline uint16_t 323 cdp_get_vdev_id(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) 324 { 325 if (!soc || !soc->ops || !soc->ops->misc_ops) { 326 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 327 "%s invalid instance", __func__); 328 return 0; 329 } 330 331 if (soc->ops->misc_ops->get_vdev_id) 332 return soc->ops->misc_ops->get_vdev_id(vdev); 333 return 0; 334 } 335 336 /** 337 * cdp_get_tx_ack_stats() - get tx ack count for vdev 338 * @soc - data path soc handle 339 * @pdev - data path device instance 340 * @vdev_id - vdev id 341 * 342 * return tx ack count 343 * 0 invalid count 344 */ 345 static inline uint32_t 346 cdp_get_tx_ack_stats(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, 347 uint8_t vdev_id) 348 { 349 if (!soc || !soc->ops || !soc->ops->misc_ops) { 350 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 351 "%s invalid instance", __func__); 352 return 0; 353 } 354 355 if (soc->ops->misc_ops->get_tx_ack_stats) 356 return soc->ops->misc_ops->get_tx_ack_stats(pdev, vdev_id); 357 358 return 0; 359 } 360 361 /** 362 * cdp_bad_peer_txctl_set_setting() - TBD 363 * @soc - data path soc handle 364 * @pdev - data path device instance 365 * @enable - 366 * @period - 367 * @txq_limit - 368 * 369 * TBD 370 * 371 * Return: none 372 */ 373 static inline void 374 cdp_bad_peer_txctl_set_setting(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, 375 int enable, int period, int txq_limit) 376 { 377 if (!soc || !soc->ops || !soc->ops->misc_ops) { 378 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 379 "%s invalid instance", __func__); 380 return; 381 } 382 383 if (soc->ops->misc_ops->bad_peer_txctl_set_setting) 384 return soc->ops->misc_ops->bad_peer_txctl_set_setting(pdev, 385 enable, period, txq_limit); 386 return; 387 } 388 389 /** 390 * cdp_bad_peer_txctl_update_threshold() - TBD 391 * @soc - data path soc handle 392 * @pdev - data path device instance 393 * @level - 394 * @tput_thresh - 395 * @tx_limit - 396 * 397 * TBD 398 * 399 * Return: none 400 */ 401 static inline void 402 cdp_bad_peer_txctl_update_threshold(ol_txrx_soc_handle soc, 403 struct cdp_pdev *pdev, 404 int level, int tput_thresh, int tx_limit) 405 { 406 if (!soc || !soc->ops || !soc->ops->misc_ops) { 407 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 408 "%s invalid instance", __func__); 409 return; 410 } 411 412 if (soc->ops->misc_ops->bad_peer_txctl_update_threshold) 413 return soc->ops->misc_ops->bad_peer_txctl_update_threshold( 414 pdev, level, tput_thresh, tx_limit); 415 return; 416 } 417 418 /** 419 * cdp_mark_first_wakeup_packet() - set flag to indicate that 420 * fw is compatible for marking first packet after wow wakeup 421 * @soc - data path soc handle 422 * @value: 1 for enabled/ 0 for disabled 423 * 424 * Return: None 425 */ 426 static inline void cdp_mark_first_wakeup_packet(ol_txrx_soc_handle soc, 427 uint8_t value) 428 { 429 if (!soc || !soc->ops || !soc->ops->misc_ops) { 430 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 431 "%s invalid instance", __func__); 432 return; 433 } 434 435 if (soc->ops->misc_ops->mark_first_wakeup_packet) 436 return soc->ops->misc_ops->mark_first_wakeup_packet(value); 437 return; 438 } 439 440 441 /** 442 * cds_update_mac_id() - update mac_id for vdev 443 * @soc - data path soc handle 444 * @vdev_id: vdev id 445 * @mac_id: mac id 446 * 447 * Return: none 448 */ 449 static inline void cdp_update_mac_id(void *psoc, uint8_t vdev_id, 450 uint8_t mac_id) 451 { 452 ol_txrx_soc_handle soc = psoc; 453 454 if (!soc || !soc->ops || !soc->ops->misc_ops) { 455 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 456 "%s invalid instance", __func__); 457 return; 458 } 459 460 if (soc->ops->misc_ops->update_mac_id) 461 return soc->ops->misc_ops->update_mac_id(vdev_id, mac_id); 462 return; 463 } 464 465 /** 466 * cdp_flush_rx_frames() - flush cached rx frames 467 * @soc - data path soc handle 468 * @peer: peer 469 * @drop: set flag to drop frames 470 * 471 * Return: None 472 */ 473 static inline void cdp_flush_rx_frames(ol_txrx_soc_handle soc, void *peer, 474 bool drop) 475 { 476 if (!soc || !soc->ops || !soc->ops->misc_ops) { 477 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 478 "%s invalid instance", __func__); 479 return; 480 } 481 482 if (soc->ops->misc_ops->flush_rx_frames) 483 return soc->ops->misc_ops->flush_rx_frames(peer, drop); 484 return; 485 } 486 487 /* 488 * cdp_get_intra_bss_fwd_pkts_count() - to get the total tx and rx packets 489 * that has been forwarded from txrx layer without going to upper layers. 490 * @vdev_id: vdev id 491 * @fwd_tx_packets: pointer to forwarded tx packets count parameter 492 * @fwd_rx_packets: pointer to forwarded rx packets count parameter 493 * 494 * Return: status -> A_OK - success, A_ERROR - failure 495 */ 496 static inline A_STATUS cdp_get_intra_bss_fwd_pkts_count( 497 ol_txrx_soc_handle soc, uint8_t vdev_id, 498 uint64_t *fwd_tx_packets, uint64_t *fwd_rx_packets) 499 { 500 if (!soc || !soc->ops || !soc->ops->misc_ops) { 501 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 502 "%s invalid instance", __func__); 503 return 0; 504 } 505 506 if (soc->ops->misc_ops->get_intra_bss_fwd_pkts_count) 507 return soc->ops->misc_ops->get_intra_bss_fwd_pkts_count( 508 vdev_id, fwd_tx_packets, fwd_rx_packets); 509 510 return 0; 511 } 512 513 /** 514 * cdp_pkt_log_init() - API to initialize packet log 515 * @handle: pdev handle 516 * @scn: HIF context 517 * 518 * Return: void 519 */ 520 static inline void cdp_pkt_log_init(ol_txrx_soc_handle soc, 521 struct cdp_pdev *pdev, void *scn) 522 { 523 if (!soc || !soc->ops || !soc->ops->misc_ops) { 524 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 525 "%s invalid instance", __func__); 526 return; 527 } 528 529 if (soc->ops->misc_ops->pkt_log_init) 530 return soc->ops->misc_ops->pkt_log_init(pdev, scn); 531 532 return; 533 } 534 535 /** 536 * cdp_pkt_log_con_service() - API to connect packet log service 537 * @handle: pdev handle 538 * @scn: HIF context 539 * 540 * Return: void 541 */ 542 static inline void cdp_pkt_log_con_service(ol_txrx_soc_handle soc, 543 struct cdp_pdev *pdev, void *scn) 544 { 545 if (!soc || !soc->ops || !soc->ops->misc_ops) { 546 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 547 "%s invalid instance", __func__); 548 return; 549 } 550 551 if (soc->ops->misc_ops->pkt_log_con_service) 552 return soc->ops->misc_ops->pkt_log_con_service(pdev, scn); 553 554 return; 555 } 556 557 /** 558 * cdp_get_num_rx_contexts() - API to get the number of RX contexts 559 * @soc: soc handle 560 * 561 * Return: number of RX contexts 562 */ 563 static inline int cdp_get_num_rx_contexts(ol_txrx_soc_handle soc) 564 { 565 if (!soc || !soc->ops || !soc->ops->misc_ops) { 566 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 567 "%s invalid instance", __func__); 568 return 0; 569 } 570 571 if (soc->ops->misc_ops->get_num_rx_contexts) 572 return soc->ops->misc_ops->get_num_rx_contexts(soc); 573 574 return 0; 575 } 576 577 /** 578 * cdp_register_packetdump_cb() - API to register packetdump callback 579 * 580 * Register TX/RX callback for data packets, during connection. And per packet 581 * stats will be passed to user-space by @tx_cb/@rx_cb. 582 * 583 * @soc: soc handle 584 * @tx_cb: tx packet callback 585 * @rx_cb: rx packet callback 586 * 587 * Return: void 588 */ 589 static inline void cdp_register_packetdump_cb(ol_txrx_soc_handle soc, 590 ol_txrx_pktdump_cb tx_cb, 591 ol_txrx_pktdump_cb rx_cb) 592 { 593 if (!soc || !soc->ops || !soc->ops->misc_ops) { 594 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 595 "%s invalid instance", __func__); 596 return; 597 } 598 599 if (soc->ops->misc_ops->register_pktdump_cb) 600 return soc->ops->misc_ops->register_pktdump_cb(tx_cb, rx_cb); 601 } 602 603 /** 604 * cdp_deregister_packetdump_cb() - API to unregister packetdump callback 605 * 606 * Deregister callback for TX/RX data packets. 607 * 608 * @soc: soc handle 609 * 610 * Return: void 611 */ 612 static inline void cdp_deregister_packetdump_cb(ol_txrx_soc_handle soc) 613 { 614 if (!soc || !soc->ops || !soc->ops->misc_ops) { 615 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, 616 "%s invalid instance", __func__); 617 return; 618 } 619 620 if (soc->ops->misc_ops->unregister_pktdump_cb) 621 return soc->ops->misc_ops->unregister_pktdump_cb(); 622 } 623 #endif /* _CDP_TXRX_MISC_H_ */ 624