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 * 311 * Return: QDF_STATUS 312 */ 313 QDF_STATUS dp_vdev_set_monitor_mode_buf_rings_tx_2_0(struct dp_pdev *pdev); 314 315 /** 316 * dp_vdev_set_monitor_mode_buf_rings_rx_2_0() - Add buffers to rx ring 317 * @pdev: Pointer to dp_pdev object 318 * 319 * Return: QDF_STATUS 320 */ 321 QDF_STATUS dp_vdev_set_monitor_mode_buf_rings_rx_2_0(struct dp_pdev *pdev); 322 323 #ifdef QCA_ENHANCED_STATS_SUPPORT 324 /** 325 * dp_mon_get_puncture_type() - Get puncture type 326 * @puncture_pattern: puncture bitmap 327 * @bw: Bandwidth 328 */ 329 enum cdp_punctured_modes 330 dp_mon_get_puncture_type(uint16_t puncture_pattern, uint8_t bw); 331 #endif 332 333 /* 334 * dp_mon_desc_get() - get monitor sw descriptor 335 * 336 * @cookie: cookie 337 * 338 * Return: dp_mon_desc 339 */ 340 static inline 341 struct dp_mon_desc *dp_mon_desc_get(uint64_t *cookie) 342 { 343 return (struct dp_mon_desc *)cookie; 344 } 345 346 /** 347 * dp_rx_add_to_free_desc_list() - Adds to a local free descriptor list 348 * 349 * @head: pointer to the head of local free list 350 * @tail: pointer to the tail of local free list 351 * @new: new descriptor that is added to the free list 352 * @func_name: caller func name 353 * 354 * Return: void 355 */ 356 static inline 357 void __dp_mon_add_to_free_desc_list(union dp_mon_desc_list_elem_t **head, 358 union dp_mon_desc_list_elem_t **tail, 359 struct dp_mon_desc *new, 360 const char *func_name) 361 { 362 qdf_assert(head && new); 363 364 new->buf_addr = NULL; 365 new->in_use = 0; 366 367 ((union dp_mon_desc_list_elem_t *)new)->next = *head; 368 *head = (union dp_mon_desc_list_elem_t *)new; 369 /* reset tail if head->next is NULL */ 370 if (!*tail || !(*head)->next) 371 *tail = *head; 372 } 373 374 #define dp_mon_add_to_free_desc_list(head, tail, new) \ 375 __dp_mon_add_to_free_desc_list(head, tail, new, __func__) 376 377 /* 378 * dp_mon_add_desc_list_to_free_list() - append unused desc_list back to 379 * freelist. 380 * 381 * @soc: core txrx main context 382 * @local_desc_list: local desc list provided by the caller 383 * @tail: attach the point to last desc of local desc list 384 * @mon_desc_pool: monitor descriptor pool pointer 385 */ 386 387 void 388 dp_mon_add_desc_list_to_free_list(struct dp_soc *soc, 389 union dp_mon_desc_list_elem_t **local_desc_list, 390 union dp_mon_desc_list_elem_t **tail, 391 struct dp_mon_desc_pool *mon_desc_pool); 392 393 /** 394 * dp_rx_mon_add_frag_to_skb () - Add page frag to skb 395 * 396 * @ppdu_info: PPDU status info 397 * @nbuf: SKB to which frag need to be added 398 * @status_frag: Frag to add 399 * 400 * Return: void 401 */ 402 static inline void 403 dp_rx_mon_add_frag_to_skb(struct hal_rx_ppdu_info *ppdu_info, 404 qdf_nbuf_t nbuf, 405 qdf_frag_t status_frag) 406 { 407 uint16_t num_frags; 408 409 num_frags = qdf_nbuf_get_nr_frags(nbuf); 410 if (num_frags < QDF_NBUF_MAX_FRAGS) { 411 qdf_nbuf_add_rx_frag(status_frag, nbuf, 412 ppdu_info->data - (unsigned char *)status_frag, 413 ppdu_info->hdr_len, 414 RX_MONITOR_BUFFER_SIZE, 415 false); 416 } else { 417 dp_mon_err("num_frags exceeding MAX frags"); 418 qdf_assert_always(0); 419 } 420 } 421 422 #if defined(WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG) ||\ 423 defined(WLAN_SUPPORT_RX_FLOW_TAG) 424 /** dp_mon_rx_update_rx_err_protocol_tag_stats() - Update mon protocols's 425 * statistics from given protocol 426 * type 427 * @pdev: pdev handle 428 * @protocol_index: Protocol index for which the stats should be incremented 429 * 430 * Return: void 431 */ 432 void dp_mon_rx_update_rx_protocol_tag_stats(struct dp_pdev *pdev, 433 uint16_t protocol_index); 434 #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */ 435 436 #if !defined(DISABLE_MON_CONFIG) && defined(QCA_MONITOR_2_0_SUPPORT) 437 /** 438 * dp_mon_get_context_size_be() - get BE specific size for mon pdev/soc 439 * @arch_ops: arch ops pointer 440 * 441 * Return: size in bytes for the context_type 442 */ 443 static inline 444 qdf_size_t dp_mon_get_context_size_be(enum dp_context_type context_type) 445 { 446 switch (context_type) { 447 case DP_CONTEXT_TYPE_MON_SOC: 448 return sizeof(struct dp_mon_soc_be); 449 case DP_CONTEXT_TYPE_MON_PDEV: 450 return sizeof(struct dp_mon_pdev_be); 451 default: 452 return 0; 453 } 454 } 455 #endif 456 457 #ifdef QCA_MONITOR_2_0_SUPPORT 458 /** 459 * dp_get_be_mon_soc_from_dp_mon_soc() - get dp_mon_soc_be from dp_mon_soc 460 * @soc: dp_mon_soc pointer 461 * 462 * Return: dp_mon_soc_be pointer 463 */ 464 static inline 465 struct dp_mon_soc_be *dp_get_be_mon_soc_from_dp_mon_soc(struct dp_mon_soc *soc) 466 { 467 return (struct dp_mon_soc_be *)soc; 468 } 469 470 /** 471 * dp_get_be_mon_pdev_from_dp_mon_pdev() - get dp_mon_pdev_be from dp_mon_pdev 472 * @pdev: dp_mon_pdev pointer 473 * 474 * Return: dp_mon_pdev_be pointer 475 */ 476 static inline 477 struct dp_mon_pdev_be *dp_get_be_mon_pdev_from_dp_mon_pdev(struct dp_mon_pdev *mon_pdev) 478 { 479 return (struct dp_mon_pdev_be *)mon_pdev; 480 } 481 #endif 482 #endif /* _DP_MON_2_0_H_ */ 483