1 /* 2 * Copyright (c) 2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #ifndef _DP_MON_2_0_H_ 19 #define _DP_MON_2_0_H_ 20 21 #if !defined(DISABLE_MON_CONFIG) 22 #include <qdf_lock.h> 23 #include <dp_types.h> 24 #include <dp_mon.h> 25 #include <dp_mon_filter.h> 26 #include <dp_htt.h> 27 #include <dp_mon.h> 28 #include <dp_tx_mon_2.0.h> 29 30 #define DP_MON_RING_FILL_LEVEL_DEFAULT 2048 31 #define DP_MON_DATA_BUFFER_SIZE 2048 32 #define DP_MON_DESC_MAGIC 0xdeadabcd 33 #define DP_MON_MAX_STATUS_BUF 1200 34 #define DP_MON_QUEUE_DEPTH_MAX 16 35 #define DP_MON_MSDU_LOGGING 0 36 #define DP_MON_MPDU_LOGGING 1 37 38 #define DP_MON_DECAP_FORMAT_INVALID 0xff 39 #define DP_MON_MIN_FRAGS_FOR_RESTITCH 2 40 41 /* monitor frame filter modes */ 42 enum dp_mon_frm_filter_mode { 43 /* mode filter pass */ 44 DP_MON_FRM_FILTER_MODE_FP = 0, 45 /* mode monitor direct */ 46 DP_MON_FRM_FILTER_MODE_MD = 1, 47 /* mode monitor other */ 48 DP_MON_FRM_FILTER_MODE_MO = 2, 49 /* mode filter pass monitor other */ 50 DP_MON_FRM_FILTER_MODE_FP_MO = 3, 51 }; 52 53 /* mpdu filter categories */ 54 enum dp_mpdu_filter_category { 55 /* category filter pass */ 56 DP_MPDU_FILTER_CATEGORY_FP = 0, 57 /* category monitor direct */ 58 DP_MPDU_FILTER_CATEGORY_MD = 1, 59 /* category monitor other */ 60 DP_MPDU_FILTER_CATEGORY_MO = 2, 61 /* category filter pass monitor override */ 62 DP_MPDU_FILTER_CATEGORY_FP_MO = 3, 63 }; 64 65 /** 66 * struct dp_mon_filter_be - Monitor TLV filter 67 * @rx_tlv_filter: Rx MON TLV filter 68 * @tx_tlv_filter: Tx MON TLV filter 69 * @tx_valid: enable/disable Tx Mon TLV filter 70 */ 71 struct dp_mon_filter_be { 72 struct dp_mon_filter rx_tlv_filter; 73 #ifdef QCA_MONITOR_2_0_SUPPORT 74 struct htt_tx_ring_tlv_filter tx_tlv_filter; 75 #endif 76 bool tx_valid; 77 }; 78 79 /** 80 * struct dp_mon_desc 81 * 82 * @buf_addr: virtual address 83 * @paddr: physical address 84 * @in_use: desc is in use 85 * @unmapped: used to mark desc an unmapped if the corresponding 86 * nbuf is already unmapped 87 * @end_offset: offset in status buffer where DMA ended 88 * @cookie: unique desc identifier 89 * @magic: magic number to validate desc data 90 */ 91 struct dp_mon_desc { 92 uint8_t *buf_addr; 93 qdf_dma_addr_t paddr; 94 uint8_t in_use:1, 95 unmapped:1; 96 uint16_t end_offset; 97 uint32_t cookie; 98 uint32_t magic; 99 }; 100 101 /** 102 * struct dp_mon_desc_list_elem_t 103 * @next: Next pointer to form free list 104 * @mon_desc: DP mon descriptor 105 */ 106 union dp_mon_desc_list_elem_t { 107 union dp_mon_desc_list_elem_t *next; 108 struct dp_mon_desc mon_desc; 109 }; 110 111 /** 112 * struct dp_mon_desc_pool - monitor desc pool 113 * @pool_size: number of descriptor in the pool 114 * @array: pointer to array of descriptor 115 * @freelist: pointer to free descriptor list 116 * @lock: Protection for the descriptor pool 117 * @owner: owner for nbuf 118 * @buf_size: Buffer size 119 * @buf_alignment: Buffer alignment 120 * @pf_cache: page frag cache 121 */ 122 struct dp_mon_desc_pool { 123 uint32_t pool_size; 124 union dp_mon_desc_list_elem_t *array; 125 union dp_mon_desc_list_elem_t *freelist; 126 qdf_spinlock_t lock; 127 uint8_t owner; 128 uint16_t buf_size; 129 uint8_t buf_alignment; 130 qdf_frag_cache_t pf_cache; 131 }; 132 133 /* 134 * NB: intentionally not using kernel-doc comment because the kernel-doc 135 * script does not handle the TAILQ_HEAD macro 136 * struct dp_mon_pdev_be - BE specific monitor pdev object 137 * @mon_pdev: monitor pdev structure 138 * @filter_be: filters sent to fw 139 * @tx_mon_mode: tx monitor mode 140 * @tx_mon_filter_length: tx monitor filter length 141 * @tx_monitor_be: pointer to tx monitor be structure 142 * @tx_stats: tx monitor drop stats 143 * @rx_mon_wq_lock: Rx mon workqueue lock 144 * @rx_mon_workqueue: Rx mon workqueue 145 * @rx_mon_work: Rx mon work 146 * @rx_mon_queue: RxMON queue 147 * @rx_mon_free_queue: RxMON ppdu info free element queue 148 * @ppdu_info_lock: RxPPDU ppdu info queue lock 149 * @rx_mon_queue_depth: RxMON queue depth 150 * @desc_count: reaped status desc count 151 * @status: reaped status buffer per ppdu 152 * @lite_mon_rx_config: rx litemon config 153 * @lite_mon_tx_config: tx litemon config 154 * @prev_rxmon_desc: prev destination desc 155 * @prev_rxmon_cookie: prev rxmon cookie 156 * @ppdu_info_cache: PPDU info cache 157 * @total_free_elem: total free element in queue 158 */ 159 struct dp_mon_pdev_be { 160 struct dp_mon_pdev mon_pdev; 161 struct dp_mon_filter_be **filter_be; 162 uint8_t tx_mon_mode; 163 uint8_t tx_mon_filter_length; 164 struct dp_pdev_tx_monitor_be tx_monitor_be; 165 struct dp_tx_monitor_drop_stats tx_stats; 166 qdf_spinlock_t rx_mon_wq_lock; 167 qdf_workqueue_t *rx_mon_workqueue; 168 qdf_work_t rx_mon_work; 169 170 TAILQ_HEAD(, hal_rx_ppdu_info) rx_mon_queue; 171 TAILQ_HEAD(, hal_rx_ppdu_info) rx_mon_free_queue; 172 qdf_spinlock_t ppdu_info_lock; 173 uint16_t rx_mon_queue_depth; 174 uint16_t desc_count; 175 struct dp_mon_desc *status[DP_MON_MAX_STATUS_BUF]; 176 #ifdef QCA_SUPPORT_LITE_MONITOR 177 struct dp_lite_mon_rx_config *lite_mon_rx_config; 178 struct dp_lite_mon_tx_config *lite_mon_tx_config; 179 #endif 180 void *prev_rxmon_desc; 181 uint32_t prev_rxmon_cookie; 182 qdf_kmem_cache_t ppdu_info_cache; 183 uint32_t total_free_elem; 184 }; 185 186 /** 187 * struct dp_mon_soc_be - BE specific monitor soc 188 * @mon_soc: Monitor soc structure 189 * @tx_mon_buf_ring: TxMon replenish ring 190 * @tx_mon_dst_ring: TxMon Destination ring 191 * @tx_desc_mon: descriptor pool for tx mon src ring 192 * @rx_desc_mon: descriptor pool for rx mon src ring 193 * @rx_mon_ring_fill_level: rx mon ring refill level 194 * @tx_mon_ring_fill_level: tx mon ring refill level 195 * @tx_low_thresh_intrs: number of tx mon low threshold interrupts received 196 * @rx_low_thresh_intrs: number of rx mon low threshold interrupts received 197 * @is_dp_mon_soc_initialized: flag to indicate soc is initialized 198 */ 199 struct dp_mon_soc_be { 200 struct dp_mon_soc mon_soc; 201 /* Source ring for Tx monitor */ 202 struct dp_srng tx_mon_buf_ring; 203 struct dp_srng tx_mon_dst_ring[MAX_NUM_LMAC_HW]; 204 205 /* Sw descriptor pool for tx mon source ring */ 206 struct dp_mon_desc_pool tx_desc_mon; 207 /* Sw descriptor pool for rx mon source ring */ 208 struct dp_mon_desc_pool rx_desc_mon; 209 210 uint16_t rx_mon_ring_fill_level; 211 uint16_t tx_mon_ring_fill_level; 212 uint32_t tx_low_thresh_intrs; 213 uint32_t rx_low_thresh_intrs; 214 215 bool is_dp_mon_soc_initialized; 216 }; 217 #endif 218 219 /** 220 * dp_mon_desc_pool_init() - Monitor descriptor pool init 221 * @mon_desc_pool: mon desc pool 222 * @pool_size: Pool size 223 * 224 * Return: non-zero for failure, zero for success 225 */ 226 QDF_STATUS 227 dp_mon_desc_pool_init(struct dp_mon_desc_pool *mon_desc_pool, 228 uint32_t pool_size); 229 230 /** 231 * dp_mon_desc_pool_deinit()- monitor descriptor pool deinit 232 * @mon_desc_pool: mon desc pool 233 * 234 * Return: None 235 * 236 */ 237 void dp_mon_desc_pool_deinit(struct dp_mon_desc_pool *mon_desc_pool); 238 239 /** 240 * dp_mon_desc_pool_free()- monitor descriptor pool free 241 * @mon_desc_pool: mon desc pool 242 * 243 * Return: None 244 * 245 */ 246 void dp_mon_desc_pool_free(struct dp_mon_desc_pool *mon_desc_pool); 247 248 /** 249 * dp_mon_desc_pool_alloc() - Monitor descriptor pool alloc 250 * @pool_size: Pool size 251 * @mon_desc_pool: mon desc pool 252 * 253 * Return: non-zero for failure, zero for success 254 */ 255 QDF_STATUS dp_mon_desc_pool_alloc(uint32_t pool_size, 256 struct dp_mon_desc_pool *mon_desc_pool); 257 258 /** 259 * dp_mon_pool_frag_unmap_and_free() - free the mon desc frag called during 260 * de-initialization of wifi module. 261 * 262 * @dp_soc: DP soc handle 263 * @mon_desc_pool: monitor descriptor pool pointer 264 * 265 * Return: None 266 */ 267 void dp_mon_pool_frag_unmap_and_free(struct dp_soc *dp_soc, 268 struct dp_mon_desc_pool *mon_desc_pool); 269 270 /** 271 * dp_mon_buffers_replenish() - replenish monitor ring with nbufs 272 * 273 * @dp_soc: core txrx main context 274 * @dp_mon_srng: dp monitor circular ring 275 * @mon_desc_pool: Pointer to free mon descriptor pool 276 * @num_req_buffers: number of buffer to be replenished 277 * @desc_list: list of descs if called from dp_rx_process 278 * or NULL during dp rx initialization or out of buffer 279 * interrupt. 280 * @tail: tail of descs list 281 * @replenish_cnt_ref: pointer to update replenish_cnt 282 * 283 * Return: return success or failure 284 */ 285 QDF_STATUS dp_mon_buffers_replenish(struct dp_soc *dp_soc, 286 struct dp_srng *dp_mon_srng, 287 struct dp_mon_desc_pool *mon_desc_pool, 288 uint32_t num_req_buffers, 289 union dp_mon_desc_list_elem_t **desc_list, 290 union dp_mon_desc_list_elem_t **tail, 291 uint32_t *replenish_cnt_ref); 292 293 /** 294 * dp_mon_filter_show_tx_filter_be() - Show the set filters 295 * @mode: The filter modes 296 * @filter: tlv filter 297 */ 298 void dp_mon_filter_show_tx_filter_be(enum dp_mon_filter_mode mode, 299 struct dp_mon_filter_be *filter); 300 301 /** 302 * dp_mon_filter_show_rx_filter_be() - Show the set filters 303 * @mode: The filter modes 304 * @filter: tlv filter 305 */ 306 void dp_mon_filter_show_rx_filter_be(enum dp_mon_filter_mode mode, 307 struct dp_mon_filter_be *filter); 308 309 /** 310 * dp_vdev_set_monitor_mode_buf_rings_tx_2_0() - Add buffers to tx ring 311 * @pdev: Pointer to dp_pdev object 312 * @num_of_buffers: Number of buffers to allocate 313 * 314 * Return: QDF_STATUS 315 */ 316 QDF_STATUS dp_vdev_set_monitor_mode_buf_rings_tx_2_0(struct dp_pdev *pdev, 317 uint16_t num_of_buffers); 318 319 /** 320 * dp_vdev_set_monitor_mode_buf_rings_rx_2_0() - Add buffers to rx ring 321 * @pdev: Pointer to dp_pdev object 322 * 323 * Return: QDF_STATUS 324 */ 325 QDF_STATUS dp_vdev_set_monitor_mode_buf_rings_rx_2_0(struct dp_pdev *pdev); 326 327 #ifdef QCA_ENHANCED_STATS_SUPPORT 328 /** 329 * dp_mon_get_puncture_type() - Get puncture type 330 * @puncture_pattern: puncture bitmap 331 * @bw: Bandwidth 332 */ 333 enum cdp_punctured_modes 334 dp_mon_get_puncture_type(uint16_t puncture_pattern, uint8_t bw); 335 #endif 336 337 /** 338 * dp_mon_desc_get() - get monitor sw descriptor 339 * 340 * @cookie: cookie 341 * 342 * Return: dp_mon_desc 343 */ 344 static inline 345 struct dp_mon_desc *dp_mon_desc_get(uint64_t *cookie) 346 { 347 return (struct dp_mon_desc *)cookie; 348 } 349 350 /** 351 * __dp_mon_add_to_free_desc_list() - Adds to a local free descriptor list 352 * 353 * @head: pointer to the head of local free list 354 * @tail: pointer to the tail of local free list 355 * @new: new descriptor that is added to the free list 356 * @func_name: caller func name 357 * 358 * Return: void 359 */ 360 static inline 361 void __dp_mon_add_to_free_desc_list(union dp_mon_desc_list_elem_t **head, 362 union dp_mon_desc_list_elem_t **tail, 363 struct dp_mon_desc *new, 364 const char *func_name) 365 { 366 qdf_assert(head && new); 367 368 new->buf_addr = NULL; 369 new->in_use = 0; 370 371 ((union dp_mon_desc_list_elem_t *)new)->next = *head; 372 *head = (union dp_mon_desc_list_elem_t *)new; 373 /* reset tail if head->next is NULL */ 374 if (!*tail || !(*head)->next) 375 *tail = *head; 376 } 377 378 #define dp_mon_add_to_free_desc_list(head, tail, new) \ 379 __dp_mon_add_to_free_desc_list(head, tail, new, __func__) 380 381 /** 382 * dp_mon_add_desc_list_to_free_list() - append unused desc_list back to 383 * freelist. 384 * 385 * @soc: core txrx main context 386 * @local_desc_list: local desc list provided by the caller 387 * @tail: attach the point to last desc of local desc list 388 * @mon_desc_pool: monitor descriptor pool pointer 389 */ 390 391 void 392 dp_mon_add_desc_list_to_free_list(struct dp_soc *soc, 393 union dp_mon_desc_list_elem_t **local_desc_list, 394 union dp_mon_desc_list_elem_t **tail, 395 struct dp_mon_desc_pool *mon_desc_pool); 396 397 /** 398 * dp_rx_mon_add_frag_to_skb() - Add page frag to skb 399 * 400 * @ppdu_info: PPDU status info 401 * @nbuf: SKB to which frag need to be added 402 * @status_frag: Frag to add 403 * 404 * Return: void 405 */ 406 static inline void 407 dp_rx_mon_add_frag_to_skb(struct hal_rx_ppdu_info *ppdu_info, 408 qdf_nbuf_t nbuf, 409 qdf_frag_t status_frag) 410 { 411 uint16_t num_frags; 412 413 num_frags = qdf_nbuf_get_nr_frags(nbuf); 414 if (num_frags < QDF_NBUF_MAX_FRAGS) { 415 qdf_nbuf_add_rx_frag(status_frag, nbuf, 416 ppdu_info->data - (unsigned char *)status_frag, 417 ppdu_info->hdr_len, 418 RX_MONITOR_BUFFER_SIZE, 419 false); 420 } else { 421 dp_mon_err("num_frags exceeding MAX frags"); 422 qdf_assert_always(0); 423 } 424 } 425 426 #if defined(WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG) ||\ 427 defined(WLAN_SUPPORT_RX_FLOW_TAG) 428 /** 429 * dp_mon_rx_update_rx_protocol_tag_stats() - Update mon protocols's 430 * statistics from given protocol 431 * type 432 * @pdev: pdev handle 433 * @protocol_index: Protocol index for which the stats should be incremented 434 * 435 * Return: void 436 */ 437 void dp_mon_rx_update_rx_protocol_tag_stats(struct dp_pdev *pdev, 438 uint16_t protocol_index); 439 #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */ 440 441 #if !defined(DISABLE_MON_CONFIG) && defined(QCA_MONITOR_2_0_SUPPORT) 442 /** 443 * dp_mon_get_context_size_be() - get BE specific size for mon pdev/soc 444 * @context_type: context type for which the size is needed 445 * 446 * Return: size in bytes for the context_type 447 */ 448 static inline 449 qdf_size_t dp_mon_get_context_size_be(enum dp_context_type context_type) 450 { 451 switch (context_type) { 452 case DP_CONTEXT_TYPE_MON_SOC: 453 return sizeof(struct dp_mon_soc_be); 454 case DP_CONTEXT_TYPE_MON_PDEV: 455 return sizeof(struct dp_mon_pdev_be); 456 default: 457 return 0; 458 } 459 } 460 #endif 461 462 #ifdef QCA_MONITOR_2_0_SUPPORT 463 /** 464 * dp_get_be_mon_soc_from_dp_mon_soc() - get dp_mon_soc_be from dp_mon_soc 465 * @soc: dp_mon_soc pointer 466 * 467 * Return: dp_mon_soc_be pointer 468 */ 469 static inline 470 struct dp_mon_soc_be *dp_get_be_mon_soc_from_dp_mon_soc(struct dp_mon_soc *soc) 471 { 472 return (struct dp_mon_soc_be *)soc; 473 } 474 475 /** 476 * dp_get_be_mon_pdev_from_dp_mon_pdev() - get dp_mon_pdev_be from dp_mon_pdev 477 * @mon_pdev: dp_mon_pdev pointer 478 * 479 * Return: dp_mon_pdev_be pointer 480 */ 481 static inline 482 struct dp_mon_pdev_be *dp_get_be_mon_pdev_from_dp_mon_pdev(struct dp_mon_pdev *mon_pdev) 483 { 484 return (struct dp_mon_pdev_be *)mon_pdev; 485 } 486 #endif 487 #endif /* _DP_MON_2_0_H_ */ 488