1 /* 2 * Copyright (c) 2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 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 * struct dp_mon_pdev_be - BE specific monitor pdev object 135 * @mon_pdev: monitor pdev structure 136 * @filter_be: filters sent to fw 137 * @tx_mon_mode: tx monitor mode 138 * @tx_mon_filter_length: tx monitor filter length 139 * @tx_monitor_be: pointer to tx monitor be structure 140 * @tx_stats: tx monitor drop stats 141 * @rx_mon_wq_lock: Rx mon workqueue lock 142 * @rx_mon_workqueue: Rx mon workqueue 143 * @rx_mon_work: Rx mon work 144 * @rx_mon_queue: RxMON queue 145 * @rx_mon_free_queue: RxMON ppdu info free element queue 146 * @ppdu_info_lock: RxPPDU ppdu info queue lock 147 * @rx_mon_queue_depth: RxMON queue depth 148 * @desc_count: reaped status desc count 149 * @status: reaped status buffer per ppdu 150 * @lite_mon_rx_config: rx litemon config 151 * @lite_mon_tx_config: tx litemon config 152 * @prev_rxmon_desc: prev destination desc 153 * @prev_rxmon_cookie: prev rxmon cookie 154 * @ppdu_info_cache: PPDU info cache 155 * @total_free_elem: total free element in queue 156 */ 157 struct dp_mon_pdev_be { 158 struct dp_mon_pdev mon_pdev; 159 struct dp_mon_filter_be **filter_be; 160 uint8_t tx_mon_mode; 161 uint8_t tx_mon_filter_length; 162 struct dp_pdev_tx_monitor_be tx_monitor_be; 163 struct dp_tx_monitor_drop_stats tx_stats; 164 qdf_spinlock_t rx_mon_wq_lock; 165 qdf_workqueue_t *rx_mon_workqueue; 166 qdf_work_t rx_mon_work; 167 168 TAILQ_HEAD(, hal_rx_ppdu_info) rx_mon_queue; 169 TAILQ_HEAD(, hal_rx_ppdu_info) rx_mon_free_queue; 170 qdf_spinlock_t ppdu_info_lock; 171 uint16_t rx_mon_queue_depth; 172 uint16_t desc_count; 173 struct dp_mon_desc *status[DP_MON_MAX_STATUS_BUF]; 174 #ifdef QCA_SUPPORT_LITE_MONITOR 175 struct dp_lite_mon_rx_config *lite_mon_rx_config; 176 struct dp_lite_mon_tx_config *lite_mon_tx_config; 177 #endif 178 void *prev_rxmon_desc; 179 uint32_t prev_rxmon_cookie; 180 qdf_kmem_cache_t ppdu_info_cache; 181 uint32_t total_free_elem; 182 }; 183 184 /** 185 * struct dp_mon_soc_be - BE specific monitor soc 186 * @mon_soc: Monitor soc structure 187 * @tx_mon_buf_ring: TxMon replenish ring 188 * @tx_mon_dst_ring: TxMon Destination ring 189 * @tx_desc_mon: descriptor pool for tx mon src ring 190 * @rx_desc_mon: descriptor pool for rx mon src ring 191 * @rx_mon_ring_fill_level: rx mon ring refill level 192 * @tx_mon_ring_fill_level: tx mon ring refill level 193 * @tx_low_thresh_intrs: number of tx mon low threshold interrupts received 194 * @rx_low_thresh_intrs: number of rx mon low threshold interrupts received 195 * @is_dp_mon_soc_initialized: flag to indicate soc is initialized 196 */ 197 struct dp_mon_soc_be { 198 struct dp_mon_soc mon_soc; 199 /* Source ring for Tx monitor */ 200 struct dp_srng tx_mon_buf_ring; 201 struct dp_srng tx_mon_dst_ring[MAX_NUM_LMAC_HW]; 202 203 /* Sw descriptor pool for tx mon source ring */ 204 struct dp_mon_desc_pool tx_desc_mon; 205 /* Sw descriptor pool for rx mon source ring */ 206 struct dp_mon_desc_pool rx_desc_mon; 207 208 uint16_t rx_mon_ring_fill_level; 209 uint16_t tx_mon_ring_fill_level; 210 uint32_t tx_low_thresh_intrs; 211 uint32_t rx_low_thresh_intrs; 212 213 bool is_dp_mon_soc_initialized; 214 }; 215 #endif 216 217 /** 218 * dp_mon_desc_pool_init() - Monitor descriptor pool init 219 * @mon_desc_pool: mon desc pool 220 * @pool_size 221 * 222 * Return: non-zero for failure, zero for success 223 */ 224 QDF_STATUS 225 dp_mon_desc_pool_init(struct dp_mon_desc_pool *mon_desc_pool, 226 uint32_t pool_size); 227 228 /* 229 * dp_mon_desc_pool_deinit()- monitor descriptor pool deinit 230 * @mon_desc_pool: mon desc pool 231 * 232 * Return: None 233 * 234 */ 235 void dp_mon_desc_pool_deinit(struct dp_mon_desc_pool *mon_desc_pool); 236 237 /* 238 * dp_mon_desc_pool_free()- monitor descriptor pool free 239 * @mon_desc_pool: mon desc pool 240 * 241 * Return: None 242 * 243 */ 244 void dp_mon_desc_pool_free(struct dp_mon_desc_pool *mon_desc_pool); 245 246 /** 247 * dp_mon_desc_pool_alloc() - Monitor descriptor pool alloc 248 * @mon_desc_pool: mon desc pool 249 * @pool_size: Pool size 250 * 251 * Return: non-zero for failure, zero for success 252 */ 253 QDF_STATUS dp_mon_desc_pool_alloc(uint32_t pool_size, 254 struct dp_mon_desc_pool *mon_desc_pool); 255 256 /* 257 * dp_mon_pool_frag_unmap_and_free() - free the mon desc frag called during 258 * de-initialization of wifi module. 259 * 260 * @soc: DP soc handle 261 * @mon_desc_pool: monitor descriptor pool pointer 262 * 263 * Return: None 264 */ 265 void dp_mon_pool_frag_unmap_and_free(struct dp_soc *dp_soc, 266 struct dp_mon_desc_pool *mon_desc_pool); 267 268 /* 269 * dp_mon_buffers_replenish() - replenish monitor ring with nbufs 270 * 271 * @soc: core txrx main context 272 * @dp_mon_srng: dp monitor circular ring 273 * @mon_desc_pool: Pointer to free mon descriptor pool 274 * @num_req_buffers: number of buffer to be replenished 275 * @desc_list: list of descs if called from dp_rx_process 276 * or NULL during dp rx initialization or out of buffer 277 * interrupt. 278 * @tail: tail of descs list 279 * @relenish_cnt_ref: pointer to update replenish_cnt 280 * 281 * Return: return success or failure 282 */ 283 QDF_STATUS dp_mon_buffers_replenish(struct dp_soc *dp_soc, 284 struct dp_srng *dp_mon_srng, 285 struct dp_mon_desc_pool *mon_desc_pool, 286 uint32_t num_req_buffers, 287 union dp_mon_desc_list_elem_t **desc_list, 288 union dp_mon_desc_list_elem_t **tail, 289 uint32_t *replenish_cnt_ref); 290 291 /** 292 * dp_mon_filter_show_tx_filter_be() - Show the set filters 293 * @mode: The filter modes 294 * @tlv_filter: tlv filter 295 */ 296 void dp_mon_filter_show_tx_filter_be(enum dp_mon_filter_mode mode, 297 struct dp_mon_filter_be *filter); 298 299 /** 300 * dp_mon_filter_show_rx_filter_be() - Show the set filters 301 * @mode: The filter modes 302 * @tlv_filter: tlv filter 303 */ 304 void dp_mon_filter_show_rx_filter_be(enum dp_mon_filter_mode mode, 305 struct dp_mon_filter_be *filter); 306 307 /** 308 * dp_vdev_set_monitor_mode_buf_rings_tx_2_0() - Add buffers to tx ring 309 * @pdev: Pointer to dp_pdev object 310 * @num_of_buffers: Number of buffers to allocate 311 * 312 * Return: QDF_STATUS 313 */ 314 QDF_STATUS dp_vdev_set_monitor_mode_buf_rings_tx_2_0(struct dp_pdev *pdev, 315 uint16_t num_of_buffers); 316 317 /** 318 * dp_vdev_set_monitor_mode_buf_rings_rx_2_0() - Add buffers to rx ring 319 * @pdev: Pointer to dp_pdev object 320 * 321 * Return: QDF_STATUS 322 */ 323 QDF_STATUS dp_vdev_set_monitor_mode_buf_rings_rx_2_0(struct dp_pdev *pdev); 324 325 #ifdef QCA_ENHANCED_STATS_SUPPORT 326 /** 327 * dp_mon_get_puncture_type() - Get puncture type 328 * @puncture_pattern: puncture bitmap 329 * @bw: Bandwidth 330 */ 331 enum cdp_punctured_modes 332 dp_mon_get_puncture_type(uint16_t puncture_pattern, uint8_t bw); 333 #endif 334 335 /* 336 * dp_mon_desc_get() - get monitor sw descriptor 337 * 338 * @cookie: cookie 339 * 340 * Return: dp_mon_desc 341 */ 342 static inline 343 struct dp_mon_desc *dp_mon_desc_get(uint64_t *cookie) 344 { 345 return (struct dp_mon_desc *)cookie; 346 } 347 348 /** 349 * dp_rx_add_to_free_desc_list() - Adds to a local free descriptor list 350 * 351 * @head: pointer to the head of local free list 352 * @tail: pointer to the tail of local free list 353 * @new: new descriptor that is added to the free list 354 * @func_name: caller func name 355 * 356 * Return: void 357 */ 358 static inline 359 void __dp_mon_add_to_free_desc_list(union dp_mon_desc_list_elem_t **head, 360 union dp_mon_desc_list_elem_t **tail, 361 struct dp_mon_desc *new, 362 const char *func_name) 363 { 364 qdf_assert(head && new); 365 366 new->buf_addr = NULL; 367 new->in_use = 0; 368 369 ((union dp_mon_desc_list_elem_t *)new)->next = *head; 370 *head = (union dp_mon_desc_list_elem_t *)new; 371 /* reset tail if head->next is NULL */ 372 if (!*tail || !(*head)->next) 373 *tail = *head; 374 } 375 376 #define dp_mon_add_to_free_desc_list(head, tail, new) \ 377 __dp_mon_add_to_free_desc_list(head, tail, new, __func__) 378 379 /* 380 * dp_mon_add_desc_list_to_free_list() - append unused desc_list back to 381 * freelist. 382 * 383 * @soc: core txrx main context 384 * @local_desc_list: local desc list provided by the caller 385 * @tail: attach the point to last desc of local desc list 386 * @mon_desc_pool: monitor descriptor pool pointer 387 */ 388 389 void 390 dp_mon_add_desc_list_to_free_list(struct dp_soc *soc, 391 union dp_mon_desc_list_elem_t **local_desc_list, 392 union dp_mon_desc_list_elem_t **tail, 393 struct dp_mon_desc_pool *mon_desc_pool); 394 395 /** 396 * dp_rx_mon_add_frag_to_skb () - Add page frag to skb 397 * 398 * @ppdu_info: PPDU status info 399 * @nbuf: SKB to which frag need to be added 400 * @status_frag: Frag to add 401 * 402 * Return: void 403 */ 404 static inline void 405 dp_rx_mon_add_frag_to_skb(struct hal_rx_ppdu_info *ppdu_info, 406 qdf_nbuf_t nbuf, 407 qdf_frag_t status_frag) 408 { 409 uint16_t num_frags; 410 411 num_frags = qdf_nbuf_get_nr_frags(nbuf); 412 if (num_frags < QDF_NBUF_MAX_FRAGS) { 413 qdf_nbuf_add_rx_frag(status_frag, nbuf, 414 ppdu_info->data - (unsigned char *)status_frag, 415 ppdu_info->hdr_len, 416 RX_MONITOR_BUFFER_SIZE, 417 false); 418 } else { 419 dp_mon_err("num_frags exceeding MAX frags"); 420 qdf_assert_always(0); 421 } 422 } 423 424 #if defined(WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG) ||\ 425 defined(WLAN_SUPPORT_RX_FLOW_TAG) 426 /** dp_mon_rx_update_rx_err_protocol_tag_stats() - Update mon protocols's 427 * statistics from given protocol 428 * type 429 * @pdev: pdev handle 430 * @protocol_index: Protocol index for which the stats should be incremented 431 * 432 * Return: void 433 */ 434 void dp_mon_rx_update_rx_protocol_tag_stats(struct dp_pdev *pdev, 435 uint16_t protocol_index); 436 #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */ 437 438 #if !defined(DISABLE_MON_CONFIG) && defined(QCA_MONITOR_2_0_SUPPORT) 439 /** 440 * dp_mon_get_context_size_be() - get BE specific size for mon pdev/soc 441 * @arch_ops: arch ops pointer 442 * 443 * Return: size in bytes for the context_type 444 */ 445 static inline 446 qdf_size_t dp_mon_get_context_size_be(enum dp_context_type context_type) 447 { 448 switch (context_type) { 449 case DP_CONTEXT_TYPE_MON_SOC: 450 return sizeof(struct dp_mon_soc_be); 451 case DP_CONTEXT_TYPE_MON_PDEV: 452 return sizeof(struct dp_mon_pdev_be); 453 default: 454 return 0; 455 } 456 } 457 #endif 458 459 #ifdef QCA_MONITOR_2_0_SUPPORT 460 /** 461 * dp_get_be_mon_soc_from_dp_mon_soc() - get dp_mon_soc_be from dp_mon_soc 462 * @soc: dp_mon_soc pointer 463 * 464 * Return: dp_mon_soc_be pointer 465 */ 466 static inline 467 struct dp_mon_soc_be *dp_get_be_mon_soc_from_dp_mon_soc(struct dp_mon_soc *soc) 468 { 469 return (struct dp_mon_soc_be *)soc; 470 } 471 472 /** 473 * dp_get_be_mon_pdev_from_dp_mon_pdev() - get dp_mon_pdev_be from dp_mon_pdev 474 * @pdev: dp_mon_pdev pointer 475 * 476 * Return: dp_mon_pdev_be pointer 477 */ 478 static inline 479 struct dp_mon_pdev_be *dp_get_be_mon_pdev_from_dp_mon_pdev(struct dp_mon_pdev *mon_pdev) 480 { 481 return (struct dp_mon_pdev_be *)mon_pdev; 482 } 483 #endif 484 #endif /* _DP_MON_2_0_H_ */ 485