mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-24 21:54:34 -04:00
qcacld-3.0: Open a mon thread for packet capture mode
Create a mon thread to process the packets for pktcapture mode only if packet capture mode is enabled. Change-Id: I64e3687d08acd0d27019ed9e11b5b92b13fcd878 CRs-Fixed: 2528545
This commit is contained in:
parent
9182d59ad6
commit
f1d581361d
6 changed files with 837 additions and 5 deletions
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2012-2020 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
|
||||
|
|
@ -77,6 +77,88 @@ struct cds_ol_rx_pkt {
|
|||
|
||||
};
|
||||
|
||||
#ifdef WLAN_FEATURE_PKT_CAPTURE
|
||||
/*
|
||||
* Maximum number of cds messages to be allocated for
|
||||
* OL MON thread.
|
||||
*/
|
||||
#define CDS_MAX_OL_MON_PKT 4000
|
||||
|
||||
struct cds_sched_mon_context {
|
||||
/* 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;
|
||||
|
||||
};
|
||||
|
||||
#endif /* WLAN_FEATURE_PKT_CAPTURE */
|
||||
typedef void (*cds_ol_mon_thread_cb)(
|
||||
void *context, void *monpkt,
|
||||
uint8_t vdev_id, uint8_t tid,
|
||||
uint8_t status, bool pkt_format);
|
||||
|
||||
/*
|
||||
* 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:
|
||||
|
|
@ -140,6 +222,10 @@ typedef struct _cds_sched_context {
|
|||
bool rx_affinity_required;
|
||||
uint8_t conf_rx_thread_ul_affinity;
|
||||
#endif
|
||||
|
||||
#ifdef WLAN_FEATURE_PKT_CAPTURE
|
||||
struct cds_sched_mon_context sched_mon_ctx;
|
||||
#endif /* WLAN_FEATURE_PKT_CAPTURE */
|
||||
} cds_sched_context, *p_cds_sched_context;
|
||||
|
||||
/**
|
||||
|
|
@ -551,4 +637,162 @@ void cds_shutdown_notifier_call(void);
|
|||
*/
|
||||
void cds_resume_rx_thread(void);
|
||||
|
||||
#ifdef WLAN_FEATURE_PKT_CAPTURE
|
||||
/**
|
||||
* cds_resume_mon_thread() - resume mon thread by completing its resume event
|
||||
*
|
||||
* Resume MON thread by completing RX thread resume event
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void cds_resume_mon_thread(void);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* This api closes the Tlshim MON thread:
|
||||
*
|
||||
* Return: qdf status
|
||||
*/
|
||||
QDF_STATUS cds_close_mon_thread(void);
|
||||
|
||||
/**
|
||||
* cds_open_mon_thread() - open the Tlshim MON thread
|
||||
* @pSchedContext: Pointer to the global CDS Sched Context
|
||||
*
|
||||
* This api opens the Tlshim MON thread:
|
||||
*
|
||||
* Return: qdf status
|
||||
*/
|
||||
QDF_STATUS cds_open_mon_thread(p_cds_sched_context pschedcontext);
|
||||
|
||||
/**
|
||||
* cds_alloc_mon_thread() - alloc resources for MON thread
|
||||
* @pSchedContext: Pointer to the global CDS Sched Context
|
||||
*
|
||||
* This api alloc resources for MON thread:
|
||||
*
|
||||
* Return: qdf status
|
||||
*/
|
||||
QDF_STATUS cds_alloc_mon_thread(p_cds_sched_context pschedcontext);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
#else
|
||||
static inline
|
||||
void cds_resume_mon_thread(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void cds_drop_monpkt(p_cds_sched_context pschedcontext)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void cds_indicate_monpkt(p_cds_sched_context pschedcontext,
|
||||
struct cds_ol_mon_pkt *pkt)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void cds_wakeup_mon_thread(p_cds_sched_context pschedcontext)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
QDF_STATUS cds_close_mon_thread(void)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static inline
|
||||
QDF_STATUS cds_open_mon_thread(p_cds_sched_context pschedcontext)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static inline
|
||||
QDF_STATUS cds_alloc_mon_thread(p_cds_sched_context pschedcontext)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct cds_ol_mon_pkt *cds_alloc_ol_mon_pkt(p_cds_sched_context pschedcontext)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline
|
||||
void cds_free_ol_mon_pkt(p_cds_sched_context pschedcontext,
|
||||
struct cds_ol_mon_pkt *pkt)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void cds_free_ol_mon_pkt_freeq(p_cds_sched_context pschedcontext)
|
||||
{
|
||||
}
|
||||
#endif /* WLAN_FEATURE_PKT_CAPTURE */
|
||||
#endif /* #ifndef __CDS_SCHED_H */
|
||||
|
|
|
|||
|
|
@ -1134,6 +1134,12 @@ QDF_STATUS cds_post_disable(void)
|
|||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
qdf_status = cds_close_mon_thread();
|
||||
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
|
||||
cds_err("Failed to close MON thread!");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
cdp_pdev_pre_detach(cds_get_context(QDF_MODULE_ID_SOC),
|
||||
OL_TXRX_PDEV_ID, 1);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2014-2020 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
|
||||
|
|
@ -56,6 +56,17 @@ enum notifier_state {
|
|||
} notifier_state;
|
||||
|
||||
static p_cds_sched_context gp_cds_sched_context;
|
||||
|
||||
#ifdef WLAN_FEATURE_PKT_CAPTURE
|
||||
static int cds_ol_mon_thread(void *arg);
|
||||
static QDF_STATUS cds_alloc_ol_mon_pkt_freeq(p_cds_sched_context pschedcontext);
|
||||
static inline
|
||||
int cds_set_mon_cpus_allowed_ptr(struct task_struct *task, unsigned long cpu)
|
||||
{
|
||||
return set_cpus_allowed_ptr(task, cpumask_of(cpu));
|
||||
}
|
||||
#endif /* WLAN_FEATURE_PKT_CAPTURE */
|
||||
|
||||
#ifdef QCA_CONFIG_SMP
|
||||
static int cds_ol_rx_thread(void *arg);
|
||||
static uint32_t affine_cpu;
|
||||
|
|
@ -507,6 +518,10 @@ QDF_STATUS cds_sched_open(void *p_cds_context,
|
|||
pSchedContext->high_throughput_required = false;
|
||||
pSchedContext->rx_affinity_required = false;
|
||||
#endif
|
||||
|
||||
if (QDF_STATUS_SUCCESS != cds_alloc_mon_thread(pSchedContext))
|
||||
goto mon_freeqalloc_failure;
|
||||
|
||||
gp_cds_sched_context = pSchedContext;
|
||||
|
||||
#ifdef QCA_CONFIG_SMP
|
||||
|
|
@ -524,14 +539,29 @@ QDF_STATUS cds_sched_open(void *p_cds_context,
|
|||
wait_for_completion_interruptible(&pSchedContext->ol_rx_start_event);
|
||||
cds_debug("CDS OL Rx Thread has started");
|
||||
#endif
|
||||
|
||||
if (QDF_STATUS_SUCCESS != cds_open_mon_thread(pSchedContext))
|
||||
goto OL_MON_THREAD_START_FAILURE;
|
||||
|
||||
/* We're good now: Let's get the ball rolling!!! */
|
||||
cds_debug("CDS Scheduler successfully Opened");
|
||||
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
|
||||
|
||||
#ifdef QCA_CONFIG_SMP
|
||||
OL_RX_THREAD_START_FAILURE:
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
|
@ -887,6 +917,9 @@ QDF_STATUS cds_sched_close(void)
|
|||
}
|
||||
|
||||
cds_close_rx_thread();
|
||||
|
||||
cds_close_mon_thread();
|
||||
|
||||
gp_cds_sched_context = NULL;
|
||||
return QDF_STATUS_SUCCESS;
|
||||
} /* cds_sched_close() */
|
||||
|
|
@ -1040,3 +1073,462 @@ int cds_get_gfp_flags(void)
|
|||
return flags;
|
||||
}
|
||||
|
||||
#ifdef WLAN_FEATURE_PKT_CAPTURE
|
||||
/**
|
||||
* 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;
|
||||
|
||||
if (!cds_is_pktcapture_enabled())
|
||||
return;
|
||||
|
||||
spin_lock_bh(&pschedcontext->sched_mon_ctx.cds_ol_mon_pkt_freeq_lock);
|
||||
while (!list_empty(&pschedcontext->
|
||||
sched_mon_ctx.cds_ol_mon_pkt_freeq)) {
|
||||
pkt = list_entry((&pschedcontext->
|
||||
sched_mon_ctx.cds_ol_mon_pkt_freeq)->next,
|
||||
typeof(*pkt), list);
|
||||
list_del(&pkt->list);
|
||||
spin_unlock_bh(&pschedcontext->
|
||||
sched_mon_ctx.cds_ol_mon_pkt_freeq_lock);
|
||||
qdf_mem_free(pkt);
|
||||
spin_lock_bh(&pschedcontext->
|
||||
sched_mon_ctx.cds_ol_mon_pkt_freeq_lock);
|
||||
}
|
||||
spin_unlock_bh(&pschedcontext->sched_mon_ctx.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->
|
||||
sched_mon_ctx.cds_ol_mon_pkt_freeq_lock);
|
||||
list_add_tail(&pkt->list, &pschedcontext->
|
||||
sched_mon_ctx.cds_ol_mon_pkt_freeq);
|
||||
spin_unlock_bh(&pschedcontext->
|
||||
sched_mon_ctx.cds_ol_mon_pkt_freeq_lock);
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
free:
|
||||
spin_lock_bh(&pschedcontext->sched_mon_ctx.cds_ol_mon_pkt_freeq_lock);
|
||||
list_for_each_entry_safe(pkt, tmp,
|
||||
&pschedcontext->
|
||||
sched_mon_ctx.cds_ol_mon_pkt_freeq,
|
||||
list) {
|
||||
list_del(&pkt->list);
|
||||
spin_unlock_bh(&pschedcontext->
|
||||
sched_mon_ctx.cds_ol_mon_pkt_freeq_lock);
|
||||
qdf_mem_free(pkt);
|
||||
spin_lock_bh(&pschedcontext->
|
||||
sched_mon_ctx.cds_ol_mon_pkt_freeq_lock);
|
||||
}
|
||||
spin_unlock_bh(&pschedcontext->sched_mon_ctx.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->sched_mon_ctx.cds_ol_mon_pkt_freeq_lock);
|
||||
list_add_tail(&pkt->list,
|
||||
&pschedcontext->sched_mon_ctx.cds_ol_mon_pkt_freeq);
|
||||
spin_unlock_bh(&pschedcontext->sched_mon_ctx.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->sched_mon_ctx.cds_ol_mon_pkt_freeq_lock);
|
||||
if (list_empty(&pschedcontext->sched_mon_ctx.cds_ol_mon_pkt_freeq)) {
|
||||
spin_unlock_bh(&pschedcontext->
|
||||
sched_mon_ctx.cds_ol_mon_pkt_freeq_lock);
|
||||
return NULL;
|
||||
}
|
||||
pkt = list_first_entry(&pschedcontext->
|
||||
sched_mon_ctx.cds_ol_mon_pkt_freeq,
|
||||
struct cds_ol_mon_pkt, list);
|
||||
list_del(&pkt->list);
|
||||
spin_unlock_bh(&pschedcontext->sched_mon_ctx.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->sched_mon_ctx.ol_mon_queue_lock);
|
||||
list_add_tail(&pkt->list, &pschedcontext->
|
||||
sched_mon_ctx.ol_mon_thread_queue);
|
||||
spin_unlock_bh(&pschedcontext->sched_mon_ctx.ol_mon_queue_lock);
|
||||
set_bit(RX_POST_EVENT, &pschedcontext->sched_mon_ctx.ol_mon_event_flag);
|
||||
wake_up_interruptible(&pschedcontext->sched_mon_ctx.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->sched_mon_ctx.ol_mon_event_flag);
|
||||
wake_up_interruptible(&pschedcontext->sched_mon_ctx.ol_mon_wait_queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* cds_close_mon_thread() - close the Tlshim Rx thread
|
||||
*
|
||||
* This api closes the Tlshim Rx thread:
|
||||
*
|
||||
* Return: qdf status
|
||||
*/
|
||||
QDF_STATUS cds_close_mon_thread(void)
|
||||
{
|
||||
if (!cds_is_pktcapture_enabled())
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
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->sched_mon_ctx.ol_mon_thread)
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
/* Shut down Tlshim Rx thread */
|
||||
set_bit(RX_SHUTDOWN_EVENT,
|
||||
&gp_cds_sched_context->sched_mon_ctx.ol_mon_event_flag);
|
||||
set_bit(RX_POST_EVENT,
|
||||
&gp_cds_sched_context->sched_mon_ctx.ol_mon_event_flag);
|
||||
wake_up_interruptible(&gp_cds_sched_context->
|
||||
sched_mon_ctx.ol_mon_wait_queue);
|
||||
wait_for_completion(&gp_cds_sched_context->
|
||||
sched_mon_ctx.ol_mon_shutdown);
|
||||
gp_cds_sched_context->sched_mon_ctx.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_open_mon_thread() - open the Tlshim Rx thread
|
||||
*
|
||||
* This api open the Tlshim Rx thread:
|
||||
*
|
||||
* Return: qdf status
|
||||
*/
|
||||
QDF_STATUS cds_open_mon_thread(p_cds_sched_context pschedcontext)
|
||||
{
|
||||
if (!cds_is_pktcapture_enabled())
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
pschedcontext->sched_mon_ctx.ol_mon_thread = kthread_create(
|
||||
cds_ol_mon_thread,
|
||||
pschedcontext,
|
||||
"cds_ol_mon_thread");
|
||||
if (IS_ERR(pschedcontext->sched_mon_ctx.ol_mon_thread)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: Could not Create CDS OL MON Thread",
|
||||
__func__);
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
wake_up_process(pschedcontext->sched_mon_ctx.ol_mon_thread);
|
||||
cds_debug("CDS OL MON thread Created");
|
||||
|
||||
wait_for_completion_interruptible(
|
||||
&pschedcontext->sched_mon_ctx.ol_mon_start_event);
|
||||
cds_debug("CDS OL MON Thread has started");
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->sched_mon_ctx.ol_mon_queue_lock);
|
||||
if (list_empty(&pschedcontext->sched_mon_ctx.ol_mon_thread_queue)) {
|
||||
spin_unlock_bh(&pschedcontext->sched_mon_ctx.ol_mon_queue_lock);
|
||||
return;
|
||||
}
|
||||
list_for_each_entry_safe(pkt, tmp,
|
||||
&pschedcontext->
|
||||
sched_mon_ctx.ol_mon_thread_queue,
|
||||
list)
|
||||
list_move_tail(&pkt->list, &local_list);
|
||||
|
||||
spin_unlock_bh(&pschedcontext->sched_mon_ctx.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->sched_mon_ctx.ol_mon_queue_lock);
|
||||
while (!list_empty(&pschedcontext->sched_mon_ctx.ol_mon_thread_queue)) {
|
||||
pkt = list_first_entry(&pschedcontext->
|
||||
sched_mon_ctx.ol_mon_thread_queue,
|
||||
struct cds_ol_mon_pkt, list);
|
||||
list_del(&pkt->list);
|
||||
spin_unlock_bh(&pschedcontext->sched_mon_ctx.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->sched_mon_ctx.ol_mon_queue_lock);
|
||||
}
|
||||
spin_unlock_bh(&pschedcontext->sched_mon_ctx.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_mon_cpus_allowed_ptr(current, pref_cpu);
|
||||
|
||||
complete(&pschedcontext->sched_mon_ctx.ol_mon_start_event);
|
||||
|
||||
while (!shutdown) {
|
||||
status =
|
||||
wait_event_interruptible(
|
||||
pschedcontext->sched_mon_ctx.ol_mon_wait_queue,
|
||||
test_bit(RX_POST_EVENT,
|
||||
&pschedcontext->
|
||||
sched_mon_ctx.ol_mon_event_flag) ||
|
||||
test_bit(RX_SUSPEND_EVENT,
|
||||
&pschedcontext->
|
||||
sched_mon_ctx.ol_mon_event_flag));
|
||||
if (status == -ERESTARTSYS)
|
||||
break;
|
||||
|
||||
clear_bit(RX_POST_EVENT,
|
||||
&pschedcontext->sched_mon_ctx.ol_mon_event_flag);
|
||||
while (true) {
|
||||
if (test_bit(RX_SHUTDOWN_EVENT,
|
||||
&pschedcontext->
|
||||
sched_mon_ctx.ol_mon_event_flag)) {
|
||||
clear_bit(RX_SHUTDOWN_EVENT,
|
||||
&pschedcontext->
|
||||
sched_mon_ctx.ol_mon_event_flag);
|
||||
if (test_bit(
|
||||
RX_SUSPEND_EVENT,
|
||||
&pschedcontext->
|
||||
sched_mon_ctx.ol_mon_event_flag)) {
|
||||
clear_bit(
|
||||
RX_SUSPEND_EVENT,
|
||||
&pschedcontext->
|
||||
sched_mon_ctx.ol_mon_event_flag);
|
||||
complete
|
||||
(&pschedcontext->
|
||||
sched_mon_ctx.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->
|
||||
sched_mon_ctx.ol_mon_event_flag)) {
|
||||
clear_bit(RX_SUSPEND_EVENT,
|
||||
&pschedcontext->
|
||||
sched_mon_ctx.ol_mon_event_flag);
|
||||
spin_lock(&pschedcontext->
|
||||
sched_mon_ctx.ol_mon_thread_lock);
|
||||
INIT_COMPLETION
|
||||
(pschedcontext->
|
||||
sched_mon_ctx.ol_resume_mon_event);
|
||||
complete(&pschedcontext->
|
||||
sched_mon_ctx.ol_suspend_mon_event);
|
||||
spin_unlock(&pschedcontext->
|
||||
sched_mon_ctx.ol_mon_thread_lock);
|
||||
wait_for_completion_interruptible
|
||||
(&pschedcontext->
|
||||
sched_mon_ctx.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->sched_mon_ctx.ol_mon_shutdown, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cds_resume_mon_thread(void)
|
||||
{
|
||||
p_cds_sched_context cds_sched_context;
|
||||
|
||||
cds_sched_context = get_cds_sched_ctxt();
|
||||
if (!cds_sched_context) {
|
||||
cds_err("cds_sched_context is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
complete(&cds_sched_context->sched_mon_ctx.ol_resume_mon_event);
|
||||
}
|
||||
|
||||
QDF_STATUS
|
||||
cds_alloc_mon_thread(p_cds_sched_context pschedcontext)
|
||||
{
|
||||
if (!cds_is_pktcapture_enabled())
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
spin_lock_init(&pschedcontext->sched_mon_ctx.ol_mon_thread_lock);
|
||||
init_waitqueue_head(&pschedcontext->sched_mon_ctx.ol_mon_wait_queue);
|
||||
init_completion(&pschedcontext->sched_mon_ctx.ol_mon_start_event);
|
||||
init_completion(&pschedcontext->sched_mon_ctx.ol_suspend_mon_event);
|
||||
init_completion(&pschedcontext->sched_mon_ctx.ol_resume_mon_event);
|
||||
init_completion(&pschedcontext->sched_mon_ctx.ol_mon_shutdown);
|
||||
pschedcontext->sched_mon_ctx.ol_mon_event_flag = 0;
|
||||
spin_lock_init(&pschedcontext->sched_mon_ctx.ol_mon_queue_lock);
|
||||
spin_lock_init(&pschedcontext->sched_mon_ctx.cds_ol_mon_pkt_freeq_lock);
|
||||
INIT_LIST_HEAD(&pschedcontext->sched_mon_ctx.ol_mon_thread_queue);
|
||||
spin_lock_bh(&pschedcontext->sched_mon_ctx.cds_ol_mon_pkt_freeq_lock);
|
||||
INIT_LIST_HEAD(&pschedcontext->sched_mon_ctx.cds_ol_mon_pkt_freeq);
|
||||
spin_unlock_bh(&pschedcontext->sched_mon_ctx.cds_ol_mon_pkt_freeq_lock);
|
||||
|
||||
return cds_alloc_ol_mon_pkt_freeq(pschedcontext);
|
||||
}
|
||||
#endif /* WLAN_FEATURE_PKT_CAPTURE */
|
||||
|
|
|
|||
|
|
@ -1622,6 +1622,10 @@ struct hdd_context {
|
|||
|
||||
bool is_scheduler_suspended;
|
||||
|
||||
#ifdef WLAN_FEATURE_PKT_CAPTURE
|
||||
bool is_ol_mon_thread_suspended;
|
||||
#endif
|
||||
|
||||
#ifdef QCA_CONFIG_SMP
|
||||
bool is_ol_rx_thread_suspended;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2014-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2012, 2014-2020 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
|
||||
|
|
@ -534,6 +534,36 @@ hdd_wlan_fake_apps_suspend(struct wiphy *wiphy, struct net_device *dev,
|
|||
}
|
||||
#endif /* WLAN_SUSPEND_RESUME_TEST */
|
||||
|
||||
#ifdef WLAN_FEATURE_PKT_CAPTURE
|
||||
/**
|
||||
* wlan_hdd_mon_thread_resume() - Resume MON thread
|
||||
* @hdd_ctx: HDD context
|
||||
*
|
||||
* Check if MON thread is suspended, and resume if yes.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void wlan_hdd_mon_thread_resume(struct hdd_context *hdd_ctx);
|
||||
|
||||
/**
|
||||
* wlan_hdd_mon_thread_suspend() - Suspend MON thread
|
||||
* @hdd_ctx: HDD context
|
||||
*
|
||||
* To suspend MON thread
|
||||
*
|
||||
* Return: 0 for success
|
||||
*/
|
||||
int wlan_hdd_mon_thread_suspend(struct hdd_context *hdd_ctx);
|
||||
|
||||
#else
|
||||
static inline void wlan_hdd_mon_thread_resume(struct hdd_context *hdd_ctx) {}
|
||||
static inline int wlan_hdd_mon_thread_suspend(struct hdd_context *hdd_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WLAN_FEATURE_PKT_CAPTURE */
|
||||
|
||||
#ifdef QCA_CONFIG_SMP
|
||||
/**
|
||||
* wlan_hdd_rx_thread_resume() - Resume RX thread
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2012-2020 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
|
||||
|
|
@ -123,6 +123,46 @@ void hdd_wlan_offload_event(uint8_t type, uint8_t state)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef WLAN_FEATURE_PKT_CAPTURE
|
||||
|
||||
/* timeout in msec to wait for RX_THREAD to suspend */
|
||||
#define HDD_MONTHREAD_SUSPEND_TIMEOUT 200
|
||||
|
||||
void wlan_hdd_mon_thread_resume(struct hdd_context *hdd_ctx)
|
||||
{
|
||||
if (hdd_ctx->is_ol_mon_thread_suspended) {
|
||||
cds_resume_mon_thread();
|
||||
hdd_ctx->is_ol_mon_thread_suspended = false;
|
||||
}
|
||||
}
|
||||
|
||||
int wlan_hdd_mon_thread_suspend(struct hdd_context *hdd_ctx)
|
||||
{
|
||||
p_cds_sched_context cds_sched_context = get_cds_sched_ctxt();
|
||||
int rc;
|
||||
|
||||
if (!cds_sched_context)
|
||||
return -EINVAL;
|
||||
|
||||
set_bit(RX_SUSPEND_EVENT,
|
||||
&cds_sched_context->sched_mon_ctx.ol_mon_event_flag);
|
||||
wake_up_interruptible(&cds_sched_context->
|
||||
sched_mon_ctx.ol_mon_wait_queue);
|
||||
rc = wait_for_completion_timeout(
|
||||
&cds_sched_context->sched_mon_ctx.ol_suspend_mon_event,
|
||||
msecs_to_jiffies(HDD_MONTHREAD_SUSPEND_TIMEOUT));
|
||||
if (!rc) {
|
||||
clear_bit(RX_SUSPEND_EVENT,
|
||||
&cds_sched_context->sched_mon_ctx.ol_mon_event_flag);
|
||||
hdd_err("Failed to stop tl_shim mon thread");
|
||||
return -EINVAL;
|
||||
}
|
||||
hdd_ctx->is_ol_mon_thread_suspended = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef QCA_CONFIG_SMP
|
||||
|
||||
/* timeout in msec to wait for RX_THREAD to suspend */
|
||||
|
|
@ -1313,6 +1353,9 @@ QDF_STATUS hdd_wlan_shutdown(void)
|
|||
|
||||
dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC));
|
||||
|
||||
if (cds_is_pktcapture_enabled())
|
||||
wlan_hdd_mon_thread_resume(hdd_ctx);
|
||||
|
||||
/*
|
||||
* After SSR, FW clear its txrx stats. In host,
|
||||
* as adapter is intact so those counts are still
|
||||
|
|
@ -1718,6 +1761,9 @@ static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
|
|||
if (hdd_ctx->enable_dp_rx_threads)
|
||||
dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC));
|
||||
|
||||
if (cds_is_pktcapture_enabled())
|
||||
wlan_hdd_mon_thread_resume(hdd_ctx);
|
||||
|
||||
qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
|
||||
TRACE_CODE_HDD_CFG80211_RESUME_WLAN,
|
||||
NO_SESSION, hdd_ctx->is_wiphy_suspended);
|
||||
|
|
@ -1914,6 +1960,11 @@ static int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
|
|||
if (hdd_ctx->enable_dp_rx_threads)
|
||||
dp_txrx_suspend(cds_get_context(QDF_MODULE_ID_SOC));
|
||||
|
||||
if (cds_is_pktcapture_enabled()) {
|
||||
if (wlan_hdd_mon_thread_suspend(hdd_ctx))
|
||||
goto resume_ol_mon;
|
||||
}
|
||||
|
||||
qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
|
||||
TRACE_CODE_HDD_CFG80211_SUSPEND_WLAN,
|
||||
NO_SESSION, hdd_ctx->is_wiphy_suspended);
|
||||
|
|
@ -1934,6 +1985,11 @@ resume_dp_thread:
|
|||
if (hdd_ctx->enable_dp_rx_threads)
|
||||
dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC));
|
||||
|
||||
resume_ol_mon:
|
||||
/* Resume tlshim MON thread */
|
||||
if (cds_is_pktcapture_enabled())
|
||||
wlan_hdd_mon_thread_resume(hdd_ctx);
|
||||
|
||||
resume_ol_rx:
|
||||
/* Resume tlshim Rx thread */
|
||||
wlan_hdd_rx_thread_resume(hdd_ctx);
|
||||
|
|
|
|||
Loading…
Reference in a new issue