Loading Kbuild +7 −0 Original line number Diff line number Diff line Loading @@ -184,6 +184,9 @@ ifeq ($(KERNEL_BUILD), 0) #Flag to enable offload packets feature CONFIG_WLAN_OFFLOAD_PACKETS := y #Flag to enable packet capture mode CONFIG_WLAN_FEATURE_PKT_CAPTURE := y #enable TSF get feature CONFIG_WLAN_SYNC_TSF := y #Enable DSRC feature Loading Loading @@ -1316,6 +1319,10 @@ ifeq ($(CONFIG_WLAN_FEATURE_FILS),y) CDEFINES += -DWLAN_FEATURE_FILS_SK endif ifeq ($(CONFIG_WLAN_FEATURE_PKT_CAPTURE),y) CDEFINES += -DWLAN_FEATURE_PKT_CAPTURE endif ifeq ($(CONFIG_CNSS), y) ifeq ($(CONFIG_CNSS_SDIO), y) CDEFINES += -DCONFIG_PLD_SDIO_CNSS Loading core/cds/inc/cds_sched.h +150 −1 Original line number Diff line number Diff line /* * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the Loading Loading @@ -79,8 +79,19 @@ #define CDS_MAX_OL_RX_PKT 4000 #endif /* ** Maximum number of cds messages to be allocated for ** OL MON thread. */ #define CDS_MAX_OL_MON_PKT 4000 typedef void (*cds_ol_rx_thread_cb)(void *context, void *rxpkt, uint16_t staid); typedef void (*cds_ol_mon_thread_cb)( void *context, void *monpkt, uint8_t vdev_id, uint8_t tid, uint8_t status, bool pkt_format); typedef int (*send_mode_change_event_cb)(void); /* Loading Loading @@ -113,6 +124,31 @@ struct cds_ol_rx_pkt { }; /* ** CDS message wrapper for mon data from TXRX */ struct cds_ol_mon_pkt { struct list_head list; void *context; /* mon skb */ void *monpkt; /* vdev id to which this packet is destined */ uint8_t vdev_id; uint8_t tid; /* Tx packet status */ uint8_t status; /* 0 = 802.3 format , 1 = 802.11 format */ bool pkt_format; /* Call back to further send this packet to txrx layer */ cds_ol_mon_thread_cb callback; }; /* ** CDS Scheduler context ** The scheduler context contains the following: Loading Loading @@ -204,6 +240,46 @@ typedef struct _cds_sched_context { /* high throughput required */ bool high_throughput_required; #endif /* MON thread lock */ spinlock_t ol_mon_thread_lock; /* OL MON thread handle */ struct task_struct *ol_mon_thread; /* Handle of Event for MON thread to signal startup */ struct completion ol_mon_start_event; /* Completion object to suspend OL MON thread */ struct completion ol_suspend_mon_event; /* Completion objext to resume OL MON thread */ struct completion ol_resume_mon_event; /* Completion object for OL MON thread shutdown */ struct completion ol_mon_shutdown; /* Waitq for OL MON thread */ wait_queue_head_t ol_mon_wait_queue; unsigned long ol_mon_event_flag; /* MON buffer queue */ struct list_head ol_mon_thread_queue; /* Spinlock to synchronize between tasklet and thread */ spinlock_t ol_mon_queue_lock; /* MON queue length */ unsigned int ol_mon_queue_len; /* Lock to synchronize free buffer queue access */ spinlock_t cds_ol_mon_pkt_freeq_lock; /* Free message queue for OL MON processing */ struct list_head cds_ol_mon_pkt_freeq; /* MON thread affinity cpu */ unsigned long mon_thread_cpu; } cds_sched_context, *p_cds_sched_context; /** Loading Loading @@ -529,6 +605,79 @@ static inline int cds_sched_handle_throughput_req( #endif /** * cds_drop_monpkt() - API to drop pending mon packets * @pschedcontext: Pointer to the global CDS Sched Context * * This api drops all the pending packets in the queue. * * Return: none */ void cds_drop_monpkt(p_cds_sched_context pschedcontext); /** * cds_indicate_monpkt() - API to Indicate rx data packet * @pschedcontext: pointer to CDS Sched Context * @pkt: CDS OL MON pkt pointer containing to mon data message buffer * * Return: none */ void cds_indicate_monpkt(p_cds_sched_context pschedcontext, struct cds_ol_mon_pkt *pkt); /** * cds_wakeup_mon_thread() - wakeup mon thread * @Arg: Pointer to the global CDS Sched Context * * This api wake up cds_ol_mon_thread() to process pkt * * Return: none */ void cds_wakeup_mon_thread(p_cds_sched_context pschedcontext); /** * cds_close_mon_thread() - close the Tlshim MON thread * @p_cds_context: Pointer to the global CDS Context * * This api closes the Tlshim MON thread: * * Return: qdf status */ QDF_STATUS cds_close_mon_thread(void *p_cds_context); /** * cds_alloc_ol_mon_pkt() - API to return next available cds message * @pSchedContext: Pointer to the global CDS Sched Context * * This api returns next available cds message buffer used for mon data * processing * * Return: Pointer to cds message buffer */ struct cds_ol_mon_pkt *cds_alloc_ol_mon_pkt(p_cds_sched_context pschedcontext); /** * cds_free_ol_mon_pkt() - api to release cds message to the freeq * This api returns the cds message used for mon data to the free queue * @pSchedContext: Pointer to the global CDS Sched Context * @pkt: CDS message buffer to be returned to free queue. * * Return: none */ void cds_free_ol_mon_pkt(p_cds_sched_context pschedcontext, struct cds_ol_mon_pkt *pkt); /** * cds_free_ol_mon_pkt_freeq() - free cds buffer free queue * @pSchedContext - pointer to the global CDS Sched Context * * This API does mem free of the buffers available in free cds buffer * queue which is used for mon Data processing. * * Return: none */ void cds_free_ol_mon_pkt_freeq(p_cds_sched_context pschedcontext); /*--------------------------------------------------------------------------- \brief cds_sched_open() - initialize the CDS Scheduler Loading core/cds/src/cds_api.c +8 −0 Original line number Diff line number Diff line Loading @@ -966,6 +966,14 @@ QDF_STATUS cds_post_disable(void) return QDF_STATUS_E_INVAL; } if (cds_get_pktcap_mode_enable()) { qdf_status = cds_close_mon_thread(gp_cds_context); if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { cds_err("Failed to close MON thread!"); return QDF_STATUS_E_INVAL; } } ol_txrx_pdev_pre_detach(txrx_pdev, 1); return QDF_STATUS_SUCCESS; Loading core/cds/src/cds_sched.c +408 −2 Original line number Diff line number Diff line /* * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the Loading Loading @@ -80,6 +80,9 @@ enum notifier_state { struct _cds_sched_context *gp_cds_sched_context; static int cds_mc_thread(void *Arg); static int cds_ol_mon_thread(void *arg); static QDF_STATUS cds_alloc_ol_mon_pkt_freeq(p_cds_sched_context pSchedContext); #ifdef QCA_CONFIG_SMP static int cds_ol_rx_thread(void *arg); static uint32_t affine_cpu; Loading Loading @@ -519,6 +522,25 @@ QDF_STATUS cds_sched_open(void *p_cds_context, mutex_init(&pSchedContext->affinity_lock); pSchedContext->high_throughput_required = false; #endif if (cds_get_pktcap_mode_enable()) { spin_lock_init(&pSchedContext->ol_mon_thread_lock); init_waitqueue_head(&pSchedContext->ol_mon_wait_queue); init_completion(&pSchedContext->ol_mon_start_event); init_completion(&pSchedContext->ol_suspend_mon_event); init_completion(&pSchedContext->ol_resume_mon_event); init_completion(&pSchedContext->ol_mon_shutdown); pSchedContext->ol_mon_event_flag = 0; spin_lock_init(&pSchedContext->ol_mon_queue_lock); spin_lock_init(&pSchedContext->cds_ol_mon_pkt_freeq_lock); INIT_LIST_HEAD(&pSchedContext->ol_mon_thread_queue); spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); INIT_LIST_HEAD(&pSchedContext->cds_ol_mon_pkt_freeq); spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); if (cds_alloc_ol_mon_pkt_freeq(pSchedContext) != QDF_STATUS_SUCCESS) goto mon_freeqalloc_failure; } gp_cds_sched_context = pSchedContext; /* Create the CDS Main Controller thread */ Loading Loading @@ -550,6 +572,20 @@ QDF_STATUS cds_sched_open(void *p_cds_context, QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, ("CDS OL RX thread Created")); #endif if (cds_get_pktcap_mode_enable()) { pSchedContext->ol_mon_thread = kthread_create(cds_ol_mon_thread, pSchedContext, "cds_ol_mon_thread"); if (IS_ERR(pSchedContext->ol_mon_thread)) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, "%s: Could not Create CDS OL MON Thread", __func__); goto OL_MON_THREAD_START_FAILURE; } wake_up_process(pSchedContext->ol_mon_thread); QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, ("CDS OL MON thread Created")); } /* * Now make sure all threads have started before we exit. * Each thread should normally ACK back when it starts. Loading @@ -562,12 +598,28 @@ QDF_STATUS cds_sched_open(void *p_cds_context, QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, "%s: CDS OL Rx Thread has started", __func__); #endif if (cds_get_pktcap_mode_enable()) { wait_for_completion_interruptible( &pSchedContext->ol_mon_start_event); QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, "%s: CDS OL MON Thread has started", __func__); } /* We're good now: Let's get the ball rolling!!! */ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, "%s: CDS Scheduler successfully Opened", __func__); return QDF_STATUS_SUCCESS; OL_MON_THREAD_START_FAILURE: #ifdef QCA_CONFIG_SMP /* Try and force the Main thread controller to exit */ set_bit(RX_SHUTDOWN_EVENT, &pSchedContext->ol_rx_event_flag); set_bit(RX_POST_EVENT, &pSchedContext->ol_rx_event_flag); wake_up_interruptible(&pSchedContext->ol_rx_wait_queue); /* Wait for RX Thread to exit */ wait_for_completion(&pSchedContext->ol_rx_shutdown); #endif OL_RX_THREAD_START_FAILURE: /* Try and force the Main thread controller to exit */ set_bit(MC_SHUTDOWN_EVENT, &pSchedContext->mcEventFlag); Loading @@ -575,10 +627,12 @@ OL_RX_THREAD_START_FAILURE: wake_up_interruptible(&pSchedContext->mcWaitQueue); /* Wait for MC to exit */ wait_for_completion_interruptible(&pSchedContext->McShutdown); #endif MC_THREAD_START_FAILURE: if (cds_get_pktcap_mode_enable()) cds_free_ol_mon_pkt_freeq(gp_cds_sched_context); mon_freeqalloc_failure: #ifdef QCA_CONFIG_SMP qdf_cpuhp_unregister(&pSchedContext->cpuhp_event_handle); cds_free_ol_rx_pkt_freeq(gp_cds_sched_context); Loading Loading @@ -1268,6 +1322,355 @@ static int cds_ol_rx_thread(void *arg) } #endif /** * cds_free_ol_mon_pkt_freeq() - free cds buffer free queue * @pSchedContext - pointer to the global CDS Sched Context * * This API does mem free of the buffers available in free cds buffer * queue which is used for mon Data processing. * * Return: none */ void cds_free_ol_mon_pkt_freeq(p_cds_sched_context pSchedContext) { struct cds_ol_mon_pkt *pkt; spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); while (!list_empty(&pSchedContext->cds_ol_mon_pkt_freeq)) { pkt = list_entry((&pSchedContext->cds_ol_mon_pkt_freeq)->next, typeof(*pkt), list); list_del(&pkt->list); spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); qdf_mem_free(pkt); spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); } spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); } /** * cds_alloc_ol_mon_pkt_freeq() - Function to allocate free buffer queue * @pSchedContext - pointer to the global CDS Sched Context * * This API allocates CDS_MAX_OL_MON_PKT number of cds message buffers * which are used for mon data processing. * * Return: status of memory allocation */ static QDF_STATUS cds_alloc_ol_mon_pkt_freeq(p_cds_sched_context pSchedContext) { struct cds_ol_mon_pkt *pkt, *tmp; int i; for (i = 0; i < CDS_MAX_OL_MON_PKT; i++) { pkt = qdf_mem_malloc(sizeof(*pkt)); if (!pkt) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s Vos packet allocation for ol mon thread failed", __func__); goto free; } spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); list_add_tail(&pkt->list, &pSchedContext->cds_ol_mon_pkt_freeq); spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); } return QDF_STATUS_SUCCESS; free: spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); list_for_each_entry_safe(pkt, tmp, &pSchedContext->cds_ol_mon_pkt_freeq, list) { list_del(&pkt->list); spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); qdf_mem_free(pkt); spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); } spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); return QDF_STATUS_E_NOMEM; } /** * cds_free_ol_mon_pkt() - api to release cds message to the freeq * This api returns the cds message used for mon data to the free queue * @pSchedContext: Pointer to the global CDS Sched Context * @pkt: CDS message buffer to be returned to free queue. * * Return: none */ void cds_free_ol_mon_pkt(p_cds_sched_context pSchedContext, struct cds_ol_mon_pkt *pkt) { memset(pkt, 0, sizeof(*pkt)); spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); list_add_tail(&pkt->list, &pSchedContext->cds_ol_mon_pkt_freeq); spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); } /** * cds_alloc_ol_mon_pkt() - API to return next available cds message * @pSchedContext: Pointer to the global CDS Sched Context * * This api returns next available cds message buffer used for mon data * processing * * Return: Pointer to cds message buffer */ struct cds_ol_mon_pkt *cds_alloc_ol_mon_pkt(p_cds_sched_context pSchedContext) { struct cds_ol_mon_pkt *pkt; spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); if (list_empty(&pSchedContext->cds_ol_mon_pkt_freeq)) { spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); return NULL; } pkt = list_first_entry(&pSchedContext->cds_ol_mon_pkt_freeq, struct cds_ol_mon_pkt, list); list_del(&pkt->list); spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); return pkt; } /** * cds_indicate_monpkt() - indicate mon data packet * @Arg: Pointer to the global CDS Sched Context * @pkt: CDS data message buffer * * This api enqueues the mon packet into ol_mon_thread_queue and notifies * cds_ol_mon_thread() * * Return: none */ void cds_indicate_monpkt(p_cds_sched_context pSchedContext, struct cds_ol_mon_pkt *pkt) { spin_lock_bh(&pSchedContext->ol_mon_queue_lock); list_add_tail(&pkt->list, &pSchedContext->ol_mon_thread_queue); spin_unlock_bh(&pSchedContext->ol_mon_queue_lock); set_bit(RX_POST_EVENT, &pSchedContext->ol_mon_event_flag); wake_up_interruptible(&pSchedContext->ol_mon_wait_queue); } /** * cds_wakeup_mon_thread() - wakeup mon thread * @Arg: Pointer to the global CDS Sched Context * * This api wake up cds_ol_mon_thread() to process pkt * * Return: none */ void cds_wakeup_mon_thread(p_cds_sched_context pSchedContext) { set_bit(RX_POST_EVENT, &pSchedContext->ol_mon_event_flag); wake_up_interruptible(&pSchedContext->ol_mon_wait_queue); } /** * cds_close_mon_thread() - close the Tlshim Rx thread * @p_cds_context: Pointer to the global CDS Context * * This api closes the Tlshim Rx thread: * * Return: qdf status */ QDF_STATUS cds_close_mon_thread(void *p_cds_context) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, "%s: invoked", __func__); if (!gp_cds_sched_context) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: gp_cds_sched_context == NULL", __func__); return QDF_STATUS_E_FAILURE; } if (!gp_cds_sched_context->ol_mon_thread) return QDF_STATUS_SUCCESS; /* Shut down Tlshim Rx thread */ set_bit(RX_SHUTDOWN_EVENT, &gp_cds_sched_context->ol_mon_event_flag); set_bit(RX_POST_EVENT, &gp_cds_sched_context->ol_mon_event_flag); wake_up_interruptible(&gp_cds_sched_context->ol_mon_wait_queue); wait_for_completion(&gp_cds_sched_context->ol_mon_shutdown); gp_cds_sched_context->ol_mon_thread = NULL; cds_drop_monpkt(gp_cds_sched_context); cds_free_ol_mon_pkt_freeq(gp_cds_sched_context); return QDF_STATUS_SUCCESS; } /* cds_close_mon_thread */ /** * cds_drop_monpkt() - api to drop pending mon packets for a sta * @pschedcontext: Pointer to the global CDS Sched Context * * This api drops all queued packets for a station. * * Return: none */ void cds_drop_monpkt(p_cds_sched_context pschedcontext) { struct list_head local_list; struct cds_ol_mon_pkt *pkt, *tmp; qdf_nbuf_t buf, next_buf; INIT_LIST_HEAD(&local_list); spin_lock_bh(&pschedcontext->ol_mon_queue_lock); if (list_empty(&pschedcontext->ol_mon_thread_queue)) { spin_unlock_bh(&pschedcontext->ol_mon_queue_lock); return; } list_for_each_entry_safe(pkt, tmp, &pschedcontext->ol_mon_thread_queue, list) list_move_tail(&pkt->list, &local_list); spin_unlock_bh(&pschedcontext->ol_mon_queue_lock); list_for_each_entry_safe(pkt, tmp, &local_list, list) { list_del(&pkt->list); buf = pkt->monpkt; while (buf) { next_buf = qdf_nbuf_queue_next(buf); qdf_nbuf_free(buf); buf = next_buf; } cds_free_ol_mon_pkt(pschedcontext, pkt); } } /** * cds_mon_from_queue() - function to process pending mon packets * @pschedcontext: Pointer to the global CDS Sched Context * * This api traverses the pending buffer list and calling the callback. * This callback would essentially send the packet to HDD. * * Return: none */ static void cds_mon_from_queue(p_cds_sched_context pschedcontext) { struct cds_ol_mon_pkt *pkt; uint8_t vdev_id; uint8_t tid; spin_lock_bh(&pschedcontext->ol_mon_queue_lock); while (!list_empty(&pschedcontext->ol_mon_thread_queue)) { pkt = list_first_entry(&pschedcontext->ol_mon_thread_queue, struct cds_ol_mon_pkt, list); list_del(&pkt->list); spin_unlock_bh(&pschedcontext->ol_mon_queue_lock); vdev_id = pkt->vdev_id; tid = pkt->tid; pkt->callback(pkt->context, pkt->monpkt, vdev_id, tid, pkt->status, pkt->pkt_format); cds_free_ol_mon_pkt(pschedcontext, pkt); spin_lock_bh(&pschedcontext->ol_mon_queue_lock); } spin_unlock_bh(&pschedcontext->ol_mon_queue_lock); } /** * cds_ol_mon_thread() - cds main tlshim mon thread * @Arg: pointer to the global CDS Sched Context * * This api is the thread handler for mon Data packet processing. * * Return: thread exit code */ static int cds_ol_mon_thread(void *arg) { p_cds_sched_context pschedcontext = (p_cds_sched_context)arg; unsigned long pref_cpu = 0; bool shutdown = false; int status, i; if (!arg) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: Bad Args passed", __func__); return 0; } set_user_nice(current, -1); #ifdef MSM_PLATFORM set_wake_up_idle(true); #endif /** * Find the available cpu core other than cpu 0 and * bind the thread */ for_each_online_cpu(i) { if (i == 0) continue; pref_cpu = i; break; } cds_set_cpus_allowed_ptr(current, pref_cpu); complete(&pschedcontext->ol_mon_start_event); while (!shutdown) { status = wait_event_interruptible( pschedcontext->ol_mon_wait_queue, test_bit(RX_POST_EVENT, &pschedcontext->ol_mon_event_flag) || test_bit(RX_SUSPEND_EVENT, &pschedcontext->ol_mon_event_flag)); if (status == -ERESTARTSYS) break; clear_bit(RX_POST_EVENT, &pschedcontext->ol_mon_event_flag); while (true) { if (test_bit(RX_SHUTDOWN_EVENT, &pschedcontext->ol_mon_event_flag)) { clear_bit(RX_SHUTDOWN_EVENT, &pschedcontext->ol_mon_event_flag); if (test_bit( RX_SUSPEND_EVENT, &pschedcontext->ol_mon_event_flag)) { clear_bit( RX_SUSPEND_EVENT, &pschedcontext->ol_mon_event_flag); complete (&pschedcontext->ol_suspend_mon_event); } QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, "%s: Shutting down OL MON Thread", __func__); shutdown = true; break; } cds_mon_from_queue(pschedcontext); if (test_bit(RX_SUSPEND_EVENT, &pschedcontext->ol_mon_event_flag)) { clear_bit(RX_SUSPEND_EVENT, &pschedcontext->ol_mon_event_flag); spin_lock(&pschedcontext->ol_mon_thread_lock); INIT_COMPLETION (pschedcontext->ol_resume_mon_event); complete(&pschedcontext->ol_suspend_mon_event); spin_unlock(&pschedcontext->ol_mon_thread_lock); wait_for_completion_interruptible (&pschedcontext->ol_resume_mon_event); } break; } } QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, "%s: Exiting CDS OL mon thread", __func__); complete_and_exit(&pschedcontext->ol_mon_shutdown, 0); return 0; } void cds_remove_timer_from_sys_msg(uint32_t timer_cookie) { p_cds_msg_wrapper msg_wrapper = NULL; Loading Loading @@ -1353,6 +1756,9 @@ QDF_STATUS cds_sched_close(void *p_cds_context) cds_close_rx_thread(p_cds_context); if (cds_get_pktcap_mode_enable()) cds_close_mon_thread(p_cds_context); gp_cds_sched_context = NULL; return QDF_STATUS_SUCCESS; } /* cds_sched_close() */ Loading core/dp/htt/htt_rx.c +41 −8 Original line number Diff line number Diff line /* * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the Loading Loading @@ -1211,7 +1211,7 @@ static int htt_rx_amsdu_pop_ll(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, uint32_t *msdu_count) qdf_nbuf_t *head_mon_msdu, uint32_t *msdu_count) { int msdu_len, msdu_chaining = 0; qdf_nbuf_t msdu; Loading @@ -1237,6 +1237,7 @@ htt_rx_amsdu_pop_ll(htt_pdev_handle pdev, + HTT_RX_PPDU_DESC_SIZE32)); } msdu = *head_msdu = htt_rx_netbuf_pop(pdev); *head_mon_msdu = NULL; while (1) { int last_msdu, msdu_len_invalid, msdu_chained; int byte_offset; Loading Loading @@ -1496,6 +1497,7 @@ htt_rx_amsdu_pop_hl( qdf_nbuf_t rx_ind_msg, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, qdf_nbuf_t *head_mon_msdu, uint32_t *msdu_count) { pdev->rx_desc_size_hl = Loading @@ -1513,6 +1515,7 @@ htt_rx_amsdu_pop_hl( (qdf_nbuf_data(rx_ind_msg))); qdf_nbuf_set_next(*tail_msdu, NULL); *head_mon_msdu = NULL; return 0; } Loading @@ -1522,6 +1525,7 @@ htt_rx_frag_pop_hl( qdf_nbuf_t frag_msg, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, qdf_nbuf_t *mon_head_msdu, uint32_t *msdu_count) { qdf_nbuf_pull_head(frag_msg, HTT_RX_FRAG_IND_BYTES); Loading @@ -1536,6 +1540,7 @@ htt_rx_frag_pop_hl( *head_msdu = *tail_msdu = frag_msg; qdf_nbuf_set_next(*tail_msdu, NULL); *mon_head_msdu = NULL; return 0; } Loading Loading @@ -2099,17 +2104,18 @@ static uint8_t htt_mon_rx_get_rtap_flags(struct htt_host_rx_desc_base *rx_desc) /** * htt_rx_mon_get_rx_status() - Update information about the rx status, * which is used later for radiotap updation. * @rx_desc: Pointer to struct htt_host_rx_desc_base * @desc: Pointer to struct htt_host_rx_desc_base * @rx_status: Return variable updated with rx_status * * Return: None */ static void htt_rx_mon_get_rx_status(htt_pdev_handle pdev, struct htt_host_rx_desc_base *rx_desc, void htt_rx_mon_get_rx_status(htt_pdev_handle pdev, void *desc, struct mon_rx_status *rx_status) { uint16_t channel_flags = 0; struct mon_channel *ch_info = &pdev->mon_ch_info; struct htt_host_rx_desc_base *rx_desc = desc; rx_status->tsft = (u_int64_t)TSF_TIMESTAMP(rx_desc); rx_status->chan_freq = ch_info->ch_freq; Loading Loading @@ -2151,6 +2157,7 @@ static int htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, qdf_nbuf_t *head_mon_msdu, uint32_t *replenish_cnt) { qdf_nbuf_t msdu, next, prev = NULL; Loading Loading @@ -2186,6 +2193,7 @@ static int htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, HTT_RX_IN_ORD_PADDR_IND_HDR_BYTES); paddr = htt_rx_in_ord_paddr_get(msg_word); msdu = htt_rx_in_order_netbuf_pop(pdev, paddr); *head_mon_msdu = NULL; if (qdf_unlikely(NULL == msdu)) { qdf_print("%s: netbuf pop failed!\n", __func__); Loading Loading @@ -2378,9 +2386,11 @@ static int htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, qdf_nbuf_t *head_mon_msdu, uint32_t *replenish_cnt) { qdf_nbuf_t msdu, next, prev = NULL; qdf_nbuf_t mon_prev = NULL; uint8_t *rx_ind_data; uint32_t *msg_word; uint32_t rx_ctx_id; Loading @@ -2393,6 +2403,7 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, qdf_mem_info_t mem_map_table = {0}; int ret = 1; bool ipa_smmu = false; qdf_nbuf_t mon_msdu = NULL; HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0); Loading Loading @@ -2428,6 +2439,8 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, paddr = htt_rx_in_ord_paddr_get(msg_word); (*head_msdu) = msdu = htt_rx_in_order_netbuf_pop(pdev, paddr); (*head_mon_msdu) = NULL; if (qdf_unlikely(NULL == msdu)) { qdf_print("%s: netbuf pop failed!\n", __func__); *tail_msdu = NULL; Loading Loading @@ -2492,6 +2505,26 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, msdu_count--; if (cds_get_pktcap_mode_enable() && (ol_cfg_pktcapture_mode(pdev->ctrl_pdev) & PKT_CAPTURE_MODE_DATA_ONLY) && pdev->txrx_pdev->mon_cb && !frag_ind) { mon_msdu = qdf_nbuf_copy(msdu); if (mon_msdu) { qdf_nbuf_push_head(mon_msdu, HTT_RX_STD_DESC_RESERVATION); qdf_nbuf_set_next(mon_msdu, NULL); if (!(*head_mon_msdu)) { *head_mon_msdu = mon_msdu; mon_prev = mon_msdu; } else { qdf_nbuf_set_next(mon_prev, mon_msdu); mon_prev = mon_msdu; } } } /* calling callback function for packet logging */ if (pdev->rx_pkt_dump_cb) { if (qdf_unlikely(RX_DESC_MIC_ERR_IS_SET && Loading Loading @@ -2972,7 +3005,7 @@ int16_t htt_rx_mpdu_desc_rssi_dbm(htt_pdev_handle pdev, void *mpdu_desc) int (*htt_rx_amsdu_pop)(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, uint32_t *msdu_count); qdf_nbuf_t *head_mon_msdu, uint32_t *msdu_count); /* * htt_rx_frag_pop - Loading @@ -2982,7 +3015,7 @@ int (*htt_rx_amsdu_pop)(htt_pdev_handle pdev, int (*htt_rx_frag_pop)(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, uint32_t *msdu_count); qdf_nbuf_t *head_mon_msdu, uint32_t *msdu_count); int (*htt_rx_offload_msdu_cnt)( Loading Loading
Kbuild +7 −0 Original line number Diff line number Diff line Loading @@ -184,6 +184,9 @@ ifeq ($(KERNEL_BUILD), 0) #Flag to enable offload packets feature CONFIG_WLAN_OFFLOAD_PACKETS := y #Flag to enable packet capture mode CONFIG_WLAN_FEATURE_PKT_CAPTURE := y #enable TSF get feature CONFIG_WLAN_SYNC_TSF := y #Enable DSRC feature Loading Loading @@ -1316,6 +1319,10 @@ ifeq ($(CONFIG_WLAN_FEATURE_FILS),y) CDEFINES += -DWLAN_FEATURE_FILS_SK endif ifeq ($(CONFIG_WLAN_FEATURE_PKT_CAPTURE),y) CDEFINES += -DWLAN_FEATURE_PKT_CAPTURE endif ifeq ($(CONFIG_CNSS), y) ifeq ($(CONFIG_CNSS_SDIO), y) CDEFINES += -DCONFIG_PLD_SDIO_CNSS Loading
core/cds/inc/cds_sched.h +150 −1 Original line number Diff line number Diff line /* * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the Loading Loading @@ -79,8 +79,19 @@ #define CDS_MAX_OL_RX_PKT 4000 #endif /* ** Maximum number of cds messages to be allocated for ** OL MON thread. */ #define CDS_MAX_OL_MON_PKT 4000 typedef void (*cds_ol_rx_thread_cb)(void *context, void *rxpkt, uint16_t staid); typedef void (*cds_ol_mon_thread_cb)( void *context, void *monpkt, uint8_t vdev_id, uint8_t tid, uint8_t status, bool pkt_format); typedef int (*send_mode_change_event_cb)(void); /* Loading Loading @@ -113,6 +124,31 @@ struct cds_ol_rx_pkt { }; /* ** CDS message wrapper for mon data from TXRX */ struct cds_ol_mon_pkt { struct list_head list; void *context; /* mon skb */ void *monpkt; /* vdev id to which this packet is destined */ uint8_t vdev_id; uint8_t tid; /* Tx packet status */ uint8_t status; /* 0 = 802.3 format , 1 = 802.11 format */ bool pkt_format; /* Call back to further send this packet to txrx layer */ cds_ol_mon_thread_cb callback; }; /* ** CDS Scheduler context ** The scheduler context contains the following: Loading Loading @@ -204,6 +240,46 @@ typedef struct _cds_sched_context { /* high throughput required */ bool high_throughput_required; #endif /* MON thread lock */ spinlock_t ol_mon_thread_lock; /* OL MON thread handle */ struct task_struct *ol_mon_thread; /* Handle of Event for MON thread to signal startup */ struct completion ol_mon_start_event; /* Completion object to suspend OL MON thread */ struct completion ol_suspend_mon_event; /* Completion objext to resume OL MON thread */ struct completion ol_resume_mon_event; /* Completion object for OL MON thread shutdown */ struct completion ol_mon_shutdown; /* Waitq for OL MON thread */ wait_queue_head_t ol_mon_wait_queue; unsigned long ol_mon_event_flag; /* MON buffer queue */ struct list_head ol_mon_thread_queue; /* Spinlock to synchronize between tasklet and thread */ spinlock_t ol_mon_queue_lock; /* MON queue length */ unsigned int ol_mon_queue_len; /* Lock to synchronize free buffer queue access */ spinlock_t cds_ol_mon_pkt_freeq_lock; /* Free message queue for OL MON processing */ struct list_head cds_ol_mon_pkt_freeq; /* MON thread affinity cpu */ unsigned long mon_thread_cpu; } cds_sched_context, *p_cds_sched_context; /** Loading Loading @@ -529,6 +605,79 @@ static inline int cds_sched_handle_throughput_req( #endif /** * cds_drop_monpkt() - API to drop pending mon packets * @pschedcontext: Pointer to the global CDS Sched Context * * This api drops all the pending packets in the queue. * * Return: none */ void cds_drop_monpkt(p_cds_sched_context pschedcontext); /** * cds_indicate_monpkt() - API to Indicate rx data packet * @pschedcontext: pointer to CDS Sched Context * @pkt: CDS OL MON pkt pointer containing to mon data message buffer * * Return: none */ void cds_indicate_monpkt(p_cds_sched_context pschedcontext, struct cds_ol_mon_pkt *pkt); /** * cds_wakeup_mon_thread() - wakeup mon thread * @Arg: Pointer to the global CDS Sched Context * * This api wake up cds_ol_mon_thread() to process pkt * * Return: none */ void cds_wakeup_mon_thread(p_cds_sched_context pschedcontext); /** * cds_close_mon_thread() - close the Tlshim MON thread * @p_cds_context: Pointer to the global CDS Context * * This api closes the Tlshim MON thread: * * Return: qdf status */ QDF_STATUS cds_close_mon_thread(void *p_cds_context); /** * cds_alloc_ol_mon_pkt() - API to return next available cds message * @pSchedContext: Pointer to the global CDS Sched Context * * This api returns next available cds message buffer used for mon data * processing * * Return: Pointer to cds message buffer */ struct cds_ol_mon_pkt *cds_alloc_ol_mon_pkt(p_cds_sched_context pschedcontext); /** * cds_free_ol_mon_pkt() - api to release cds message to the freeq * This api returns the cds message used for mon data to the free queue * @pSchedContext: Pointer to the global CDS Sched Context * @pkt: CDS message buffer to be returned to free queue. * * Return: none */ void cds_free_ol_mon_pkt(p_cds_sched_context pschedcontext, struct cds_ol_mon_pkt *pkt); /** * cds_free_ol_mon_pkt_freeq() - free cds buffer free queue * @pSchedContext - pointer to the global CDS Sched Context * * This API does mem free of the buffers available in free cds buffer * queue which is used for mon Data processing. * * Return: none */ void cds_free_ol_mon_pkt_freeq(p_cds_sched_context pschedcontext); /*--------------------------------------------------------------------------- \brief cds_sched_open() - initialize the CDS Scheduler Loading
core/cds/src/cds_api.c +8 −0 Original line number Diff line number Diff line Loading @@ -966,6 +966,14 @@ QDF_STATUS cds_post_disable(void) return QDF_STATUS_E_INVAL; } if (cds_get_pktcap_mode_enable()) { qdf_status = cds_close_mon_thread(gp_cds_context); if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { cds_err("Failed to close MON thread!"); return QDF_STATUS_E_INVAL; } } ol_txrx_pdev_pre_detach(txrx_pdev, 1); return QDF_STATUS_SUCCESS; Loading
core/cds/src/cds_sched.c +408 −2 Original line number Diff line number Diff line /* * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the Loading Loading @@ -80,6 +80,9 @@ enum notifier_state { struct _cds_sched_context *gp_cds_sched_context; static int cds_mc_thread(void *Arg); static int cds_ol_mon_thread(void *arg); static QDF_STATUS cds_alloc_ol_mon_pkt_freeq(p_cds_sched_context pSchedContext); #ifdef QCA_CONFIG_SMP static int cds_ol_rx_thread(void *arg); static uint32_t affine_cpu; Loading Loading @@ -519,6 +522,25 @@ QDF_STATUS cds_sched_open(void *p_cds_context, mutex_init(&pSchedContext->affinity_lock); pSchedContext->high_throughput_required = false; #endif if (cds_get_pktcap_mode_enable()) { spin_lock_init(&pSchedContext->ol_mon_thread_lock); init_waitqueue_head(&pSchedContext->ol_mon_wait_queue); init_completion(&pSchedContext->ol_mon_start_event); init_completion(&pSchedContext->ol_suspend_mon_event); init_completion(&pSchedContext->ol_resume_mon_event); init_completion(&pSchedContext->ol_mon_shutdown); pSchedContext->ol_mon_event_flag = 0; spin_lock_init(&pSchedContext->ol_mon_queue_lock); spin_lock_init(&pSchedContext->cds_ol_mon_pkt_freeq_lock); INIT_LIST_HEAD(&pSchedContext->ol_mon_thread_queue); spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); INIT_LIST_HEAD(&pSchedContext->cds_ol_mon_pkt_freeq); spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); if (cds_alloc_ol_mon_pkt_freeq(pSchedContext) != QDF_STATUS_SUCCESS) goto mon_freeqalloc_failure; } gp_cds_sched_context = pSchedContext; /* Create the CDS Main Controller thread */ Loading Loading @@ -550,6 +572,20 @@ QDF_STATUS cds_sched_open(void *p_cds_context, QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, ("CDS OL RX thread Created")); #endif if (cds_get_pktcap_mode_enable()) { pSchedContext->ol_mon_thread = kthread_create(cds_ol_mon_thread, pSchedContext, "cds_ol_mon_thread"); if (IS_ERR(pSchedContext->ol_mon_thread)) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, "%s: Could not Create CDS OL MON Thread", __func__); goto OL_MON_THREAD_START_FAILURE; } wake_up_process(pSchedContext->ol_mon_thread); QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, ("CDS OL MON thread Created")); } /* * Now make sure all threads have started before we exit. * Each thread should normally ACK back when it starts. Loading @@ -562,12 +598,28 @@ QDF_STATUS cds_sched_open(void *p_cds_context, QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, "%s: CDS OL Rx Thread has started", __func__); #endif if (cds_get_pktcap_mode_enable()) { wait_for_completion_interruptible( &pSchedContext->ol_mon_start_event); QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, "%s: CDS OL MON Thread has started", __func__); } /* We're good now: Let's get the ball rolling!!! */ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, "%s: CDS Scheduler successfully Opened", __func__); return QDF_STATUS_SUCCESS; OL_MON_THREAD_START_FAILURE: #ifdef QCA_CONFIG_SMP /* Try and force the Main thread controller to exit */ set_bit(RX_SHUTDOWN_EVENT, &pSchedContext->ol_rx_event_flag); set_bit(RX_POST_EVENT, &pSchedContext->ol_rx_event_flag); wake_up_interruptible(&pSchedContext->ol_rx_wait_queue); /* Wait for RX Thread to exit */ wait_for_completion(&pSchedContext->ol_rx_shutdown); #endif OL_RX_THREAD_START_FAILURE: /* Try and force the Main thread controller to exit */ set_bit(MC_SHUTDOWN_EVENT, &pSchedContext->mcEventFlag); Loading @@ -575,10 +627,12 @@ OL_RX_THREAD_START_FAILURE: wake_up_interruptible(&pSchedContext->mcWaitQueue); /* Wait for MC to exit */ wait_for_completion_interruptible(&pSchedContext->McShutdown); #endif MC_THREAD_START_FAILURE: if (cds_get_pktcap_mode_enable()) cds_free_ol_mon_pkt_freeq(gp_cds_sched_context); mon_freeqalloc_failure: #ifdef QCA_CONFIG_SMP qdf_cpuhp_unregister(&pSchedContext->cpuhp_event_handle); cds_free_ol_rx_pkt_freeq(gp_cds_sched_context); Loading Loading @@ -1268,6 +1322,355 @@ static int cds_ol_rx_thread(void *arg) } #endif /** * cds_free_ol_mon_pkt_freeq() - free cds buffer free queue * @pSchedContext - pointer to the global CDS Sched Context * * This API does mem free of the buffers available in free cds buffer * queue which is used for mon Data processing. * * Return: none */ void cds_free_ol_mon_pkt_freeq(p_cds_sched_context pSchedContext) { struct cds_ol_mon_pkt *pkt; spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); while (!list_empty(&pSchedContext->cds_ol_mon_pkt_freeq)) { pkt = list_entry((&pSchedContext->cds_ol_mon_pkt_freeq)->next, typeof(*pkt), list); list_del(&pkt->list); spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); qdf_mem_free(pkt); spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); } spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); } /** * cds_alloc_ol_mon_pkt_freeq() - Function to allocate free buffer queue * @pSchedContext - pointer to the global CDS Sched Context * * This API allocates CDS_MAX_OL_MON_PKT number of cds message buffers * which are used for mon data processing. * * Return: status of memory allocation */ static QDF_STATUS cds_alloc_ol_mon_pkt_freeq(p_cds_sched_context pSchedContext) { struct cds_ol_mon_pkt *pkt, *tmp; int i; for (i = 0; i < CDS_MAX_OL_MON_PKT; i++) { pkt = qdf_mem_malloc(sizeof(*pkt)); if (!pkt) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s Vos packet allocation for ol mon thread failed", __func__); goto free; } spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); list_add_tail(&pkt->list, &pSchedContext->cds_ol_mon_pkt_freeq); spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); } return QDF_STATUS_SUCCESS; free: spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); list_for_each_entry_safe(pkt, tmp, &pSchedContext->cds_ol_mon_pkt_freeq, list) { list_del(&pkt->list); spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); qdf_mem_free(pkt); spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); } spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); return QDF_STATUS_E_NOMEM; } /** * cds_free_ol_mon_pkt() - api to release cds message to the freeq * This api returns the cds message used for mon data to the free queue * @pSchedContext: Pointer to the global CDS Sched Context * @pkt: CDS message buffer to be returned to free queue. * * Return: none */ void cds_free_ol_mon_pkt(p_cds_sched_context pSchedContext, struct cds_ol_mon_pkt *pkt) { memset(pkt, 0, sizeof(*pkt)); spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); list_add_tail(&pkt->list, &pSchedContext->cds_ol_mon_pkt_freeq); spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); } /** * cds_alloc_ol_mon_pkt() - API to return next available cds message * @pSchedContext: Pointer to the global CDS Sched Context * * This api returns next available cds message buffer used for mon data * processing * * Return: Pointer to cds message buffer */ struct cds_ol_mon_pkt *cds_alloc_ol_mon_pkt(p_cds_sched_context pSchedContext) { struct cds_ol_mon_pkt *pkt; spin_lock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); if (list_empty(&pSchedContext->cds_ol_mon_pkt_freeq)) { spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); return NULL; } pkt = list_first_entry(&pSchedContext->cds_ol_mon_pkt_freeq, struct cds_ol_mon_pkt, list); list_del(&pkt->list); spin_unlock_bh(&pSchedContext->cds_ol_mon_pkt_freeq_lock); return pkt; } /** * cds_indicate_monpkt() - indicate mon data packet * @Arg: Pointer to the global CDS Sched Context * @pkt: CDS data message buffer * * This api enqueues the mon packet into ol_mon_thread_queue and notifies * cds_ol_mon_thread() * * Return: none */ void cds_indicate_monpkt(p_cds_sched_context pSchedContext, struct cds_ol_mon_pkt *pkt) { spin_lock_bh(&pSchedContext->ol_mon_queue_lock); list_add_tail(&pkt->list, &pSchedContext->ol_mon_thread_queue); spin_unlock_bh(&pSchedContext->ol_mon_queue_lock); set_bit(RX_POST_EVENT, &pSchedContext->ol_mon_event_flag); wake_up_interruptible(&pSchedContext->ol_mon_wait_queue); } /** * cds_wakeup_mon_thread() - wakeup mon thread * @Arg: Pointer to the global CDS Sched Context * * This api wake up cds_ol_mon_thread() to process pkt * * Return: none */ void cds_wakeup_mon_thread(p_cds_sched_context pSchedContext) { set_bit(RX_POST_EVENT, &pSchedContext->ol_mon_event_flag); wake_up_interruptible(&pSchedContext->ol_mon_wait_queue); } /** * cds_close_mon_thread() - close the Tlshim Rx thread * @p_cds_context: Pointer to the global CDS Context * * This api closes the Tlshim Rx thread: * * Return: qdf status */ QDF_STATUS cds_close_mon_thread(void *p_cds_context) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, "%s: invoked", __func__); if (!gp_cds_sched_context) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: gp_cds_sched_context == NULL", __func__); return QDF_STATUS_E_FAILURE; } if (!gp_cds_sched_context->ol_mon_thread) return QDF_STATUS_SUCCESS; /* Shut down Tlshim Rx thread */ set_bit(RX_SHUTDOWN_EVENT, &gp_cds_sched_context->ol_mon_event_flag); set_bit(RX_POST_EVENT, &gp_cds_sched_context->ol_mon_event_flag); wake_up_interruptible(&gp_cds_sched_context->ol_mon_wait_queue); wait_for_completion(&gp_cds_sched_context->ol_mon_shutdown); gp_cds_sched_context->ol_mon_thread = NULL; cds_drop_monpkt(gp_cds_sched_context); cds_free_ol_mon_pkt_freeq(gp_cds_sched_context); return QDF_STATUS_SUCCESS; } /* cds_close_mon_thread */ /** * cds_drop_monpkt() - api to drop pending mon packets for a sta * @pschedcontext: Pointer to the global CDS Sched Context * * This api drops all queued packets for a station. * * Return: none */ void cds_drop_monpkt(p_cds_sched_context pschedcontext) { struct list_head local_list; struct cds_ol_mon_pkt *pkt, *tmp; qdf_nbuf_t buf, next_buf; INIT_LIST_HEAD(&local_list); spin_lock_bh(&pschedcontext->ol_mon_queue_lock); if (list_empty(&pschedcontext->ol_mon_thread_queue)) { spin_unlock_bh(&pschedcontext->ol_mon_queue_lock); return; } list_for_each_entry_safe(pkt, tmp, &pschedcontext->ol_mon_thread_queue, list) list_move_tail(&pkt->list, &local_list); spin_unlock_bh(&pschedcontext->ol_mon_queue_lock); list_for_each_entry_safe(pkt, tmp, &local_list, list) { list_del(&pkt->list); buf = pkt->monpkt; while (buf) { next_buf = qdf_nbuf_queue_next(buf); qdf_nbuf_free(buf); buf = next_buf; } cds_free_ol_mon_pkt(pschedcontext, pkt); } } /** * cds_mon_from_queue() - function to process pending mon packets * @pschedcontext: Pointer to the global CDS Sched Context * * This api traverses the pending buffer list and calling the callback. * This callback would essentially send the packet to HDD. * * Return: none */ static void cds_mon_from_queue(p_cds_sched_context pschedcontext) { struct cds_ol_mon_pkt *pkt; uint8_t vdev_id; uint8_t tid; spin_lock_bh(&pschedcontext->ol_mon_queue_lock); while (!list_empty(&pschedcontext->ol_mon_thread_queue)) { pkt = list_first_entry(&pschedcontext->ol_mon_thread_queue, struct cds_ol_mon_pkt, list); list_del(&pkt->list); spin_unlock_bh(&pschedcontext->ol_mon_queue_lock); vdev_id = pkt->vdev_id; tid = pkt->tid; pkt->callback(pkt->context, pkt->monpkt, vdev_id, tid, pkt->status, pkt->pkt_format); cds_free_ol_mon_pkt(pschedcontext, pkt); spin_lock_bh(&pschedcontext->ol_mon_queue_lock); } spin_unlock_bh(&pschedcontext->ol_mon_queue_lock); } /** * cds_ol_mon_thread() - cds main tlshim mon thread * @Arg: pointer to the global CDS Sched Context * * This api is the thread handler for mon Data packet processing. * * Return: thread exit code */ static int cds_ol_mon_thread(void *arg) { p_cds_sched_context pschedcontext = (p_cds_sched_context)arg; unsigned long pref_cpu = 0; bool shutdown = false; int status, i; if (!arg) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: Bad Args passed", __func__); return 0; } set_user_nice(current, -1); #ifdef MSM_PLATFORM set_wake_up_idle(true); #endif /** * Find the available cpu core other than cpu 0 and * bind the thread */ for_each_online_cpu(i) { if (i == 0) continue; pref_cpu = i; break; } cds_set_cpus_allowed_ptr(current, pref_cpu); complete(&pschedcontext->ol_mon_start_event); while (!shutdown) { status = wait_event_interruptible( pschedcontext->ol_mon_wait_queue, test_bit(RX_POST_EVENT, &pschedcontext->ol_mon_event_flag) || test_bit(RX_SUSPEND_EVENT, &pschedcontext->ol_mon_event_flag)); if (status == -ERESTARTSYS) break; clear_bit(RX_POST_EVENT, &pschedcontext->ol_mon_event_flag); while (true) { if (test_bit(RX_SHUTDOWN_EVENT, &pschedcontext->ol_mon_event_flag)) { clear_bit(RX_SHUTDOWN_EVENT, &pschedcontext->ol_mon_event_flag); if (test_bit( RX_SUSPEND_EVENT, &pschedcontext->ol_mon_event_flag)) { clear_bit( RX_SUSPEND_EVENT, &pschedcontext->ol_mon_event_flag); complete (&pschedcontext->ol_suspend_mon_event); } QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, "%s: Shutting down OL MON Thread", __func__); shutdown = true; break; } cds_mon_from_queue(pschedcontext); if (test_bit(RX_SUSPEND_EVENT, &pschedcontext->ol_mon_event_flag)) { clear_bit(RX_SUSPEND_EVENT, &pschedcontext->ol_mon_event_flag); spin_lock(&pschedcontext->ol_mon_thread_lock); INIT_COMPLETION (pschedcontext->ol_resume_mon_event); complete(&pschedcontext->ol_suspend_mon_event); spin_unlock(&pschedcontext->ol_mon_thread_lock); wait_for_completion_interruptible (&pschedcontext->ol_resume_mon_event); } break; } } QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, "%s: Exiting CDS OL mon thread", __func__); complete_and_exit(&pschedcontext->ol_mon_shutdown, 0); return 0; } void cds_remove_timer_from_sys_msg(uint32_t timer_cookie) { p_cds_msg_wrapper msg_wrapper = NULL; Loading Loading @@ -1353,6 +1756,9 @@ QDF_STATUS cds_sched_close(void *p_cds_context) cds_close_rx_thread(p_cds_context); if (cds_get_pktcap_mode_enable()) cds_close_mon_thread(p_cds_context); gp_cds_sched_context = NULL; return QDF_STATUS_SUCCESS; } /* cds_sched_close() */ Loading
core/dp/htt/htt_rx.c +41 −8 Original line number Diff line number Diff line /* * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the Loading Loading @@ -1211,7 +1211,7 @@ static int htt_rx_amsdu_pop_ll(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, uint32_t *msdu_count) qdf_nbuf_t *head_mon_msdu, uint32_t *msdu_count) { int msdu_len, msdu_chaining = 0; qdf_nbuf_t msdu; Loading @@ -1237,6 +1237,7 @@ htt_rx_amsdu_pop_ll(htt_pdev_handle pdev, + HTT_RX_PPDU_DESC_SIZE32)); } msdu = *head_msdu = htt_rx_netbuf_pop(pdev); *head_mon_msdu = NULL; while (1) { int last_msdu, msdu_len_invalid, msdu_chained; int byte_offset; Loading Loading @@ -1496,6 +1497,7 @@ htt_rx_amsdu_pop_hl( qdf_nbuf_t rx_ind_msg, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, qdf_nbuf_t *head_mon_msdu, uint32_t *msdu_count) { pdev->rx_desc_size_hl = Loading @@ -1513,6 +1515,7 @@ htt_rx_amsdu_pop_hl( (qdf_nbuf_data(rx_ind_msg))); qdf_nbuf_set_next(*tail_msdu, NULL); *head_mon_msdu = NULL; return 0; } Loading @@ -1522,6 +1525,7 @@ htt_rx_frag_pop_hl( qdf_nbuf_t frag_msg, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, qdf_nbuf_t *mon_head_msdu, uint32_t *msdu_count) { qdf_nbuf_pull_head(frag_msg, HTT_RX_FRAG_IND_BYTES); Loading @@ -1536,6 +1540,7 @@ htt_rx_frag_pop_hl( *head_msdu = *tail_msdu = frag_msg; qdf_nbuf_set_next(*tail_msdu, NULL); *mon_head_msdu = NULL; return 0; } Loading Loading @@ -2099,17 +2104,18 @@ static uint8_t htt_mon_rx_get_rtap_flags(struct htt_host_rx_desc_base *rx_desc) /** * htt_rx_mon_get_rx_status() - Update information about the rx status, * which is used later for radiotap updation. * @rx_desc: Pointer to struct htt_host_rx_desc_base * @desc: Pointer to struct htt_host_rx_desc_base * @rx_status: Return variable updated with rx_status * * Return: None */ static void htt_rx_mon_get_rx_status(htt_pdev_handle pdev, struct htt_host_rx_desc_base *rx_desc, void htt_rx_mon_get_rx_status(htt_pdev_handle pdev, void *desc, struct mon_rx_status *rx_status) { uint16_t channel_flags = 0; struct mon_channel *ch_info = &pdev->mon_ch_info; struct htt_host_rx_desc_base *rx_desc = desc; rx_status->tsft = (u_int64_t)TSF_TIMESTAMP(rx_desc); rx_status->chan_freq = ch_info->ch_freq; Loading Loading @@ -2151,6 +2157,7 @@ static int htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, qdf_nbuf_t *head_mon_msdu, uint32_t *replenish_cnt) { qdf_nbuf_t msdu, next, prev = NULL; Loading Loading @@ -2186,6 +2193,7 @@ static int htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, HTT_RX_IN_ORD_PADDR_IND_HDR_BYTES); paddr = htt_rx_in_ord_paddr_get(msg_word); msdu = htt_rx_in_order_netbuf_pop(pdev, paddr); *head_mon_msdu = NULL; if (qdf_unlikely(NULL == msdu)) { qdf_print("%s: netbuf pop failed!\n", __func__); Loading Loading @@ -2378,9 +2386,11 @@ static int htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, qdf_nbuf_t *head_mon_msdu, uint32_t *replenish_cnt) { qdf_nbuf_t msdu, next, prev = NULL; qdf_nbuf_t mon_prev = NULL; uint8_t *rx_ind_data; uint32_t *msg_word; uint32_t rx_ctx_id; Loading @@ -2393,6 +2403,7 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, qdf_mem_info_t mem_map_table = {0}; int ret = 1; bool ipa_smmu = false; qdf_nbuf_t mon_msdu = NULL; HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0); Loading Loading @@ -2428,6 +2439,8 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, paddr = htt_rx_in_ord_paddr_get(msg_word); (*head_msdu) = msdu = htt_rx_in_order_netbuf_pop(pdev, paddr); (*head_mon_msdu) = NULL; if (qdf_unlikely(NULL == msdu)) { qdf_print("%s: netbuf pop failed!\n", __func__); *tail_msdu = NULL; Loading Loading @@ -2492,6 +2505,26 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, msdu_count--; if (cds_get_pktcap_mode_enable() && (ol_cfg_pktcapture_mode(pdev->ctrl_pdev) & PKT_CAPTURE_MODE_DATA_ONLY) && pdev->txrx_pdev->mon_cb && !frag_ind) { mon_msdu = qdf_nbuf_copy(msdu); if (mon_msdu) { qdf_nbuf_push_head(mon_msdu, HTT_RX_STD_DESC_RESERVATION); qdf_nbuf_set_next(mon_msdu, NULL); if (!(*head_mon_msdu)) { *head_mon_msdu = mon_msdu; mon_prev = mon_msdu; } else { qdf_nbuf_set_next(mon_prev, mon_msdu); mon_prev = mon_msdu; } } } /* calling callback function for packet logging */ if (pdev->rx_pkt_dump_cb) { if (qdf_unlikely(RX_DESC_MIC_ERR_IS_SET && Loading Loading @@ -2972,7 +3005,7 @@ int16_t htt_rx_mpdu_desc_rssi_dbm(htt_pdev_handle pdev, void *mpdu_desc) int (*htt_rx_amsdu_pop)(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, uint32_t *msdu_count); qdf_nbuf_t *head_mon_msdu, uint32_t *msdu_count); /* * htt_rx_frag_pop - Loading @@ -2982,7 +3015,7 @@ int (*htt_rx_amsdu_pop)(htt_pdev_handle pdev, int (*htt_rx_frag_pop)(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, uint32_t *msdu_count); qdf_nbuf_t *head_mon_msdu, uint32_t *msdu_count); int (*htt_rx_offload_msdu_cnt)( Loading