qcacld-3.0: Resume/suspend of mon thread for packet capture
Resume/suspend of mon thread for packet capture mode. Change-Id: Ib814de13f82181aef923bdc739d018027ea9a173 CRs-Fixed: 2618657
This commit is contained in:

committed by
nshrivas

parent
aa481cc459
commit
a7e26ef49f
@@ -78,88 +78,6 @@ 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:
|
||||
@@ -223,10 +141,6 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -637,162 +551,4 @@ 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 */
|
||||
|
@@ -1139,12 +1139,6 @@ 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);
|
||||
|
||||
|
@@ -57,16 +57,6 @@ enum 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;
|
||||
@@ -518,10 +508,6 @@ 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
|
||||
@@ -539,29 +525,12 @@ 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);
|
||||
@@ -918,8 +887,6 @@ 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() */
|
||||
@@ -1073,462 +1040,3 @@ 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 */
|
||||
|
@@ -1624,10 +1624,6 @@ 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
|
||||
|
@@ -551,36 +551,6 @@ 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
|
||||
|
@@ -82,6 +82,7 @@
|
||||
#include "wlan_mlme_ucfg_api.h"
|
||||
#include "wlan_osif_request_manager.h"
|
||||
#include <wlan_hdd_sar_limits.h>
|
||||
#include "wlan_pkt_capture_ucfg_api.h"
|
||||
|
||||
/* Preprocessor definitions and constants */
|
||||
#ifdef QCA_WIFI_NAPIER_EMULATION
|
||||
@@ -124,46 +125,6 @@ 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 */
|
||||
@@ -1349,6 +1310,7 @@ static void hdd_ssr_restart_sap(struct hdd_context *hdd_ctx)
|
||||
QDF_STATUS hdd_wlan_shutdown(void)
|
||||
{
|
||||
struct hdd_context *hdd_ctx;
|
||||
struct hdd_adapter *adapter;
|
||||
void *soc = cds_get_context(QDF_MODULE_ID_SOC);
|
||||
|
||||
hdd_info("WLAN driver shutting down!");
|
||||
@@ -1377,8 +1339,11 @@ 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);
|
||||
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) {
|
||||
adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
|
||||
if (adapter)
|
||||
ucfg_pkt_capture_resume_mon_thread(adapter->vdev);
|
||||
}
|
||||
|
||||
/*
|
||||
* After SSR, FW clear its txrx stats. In host,
|
||||
@@ -1730,6 +1695,7 @@ static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
|
||||
{
|
||||
struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
struct hdd_adapter *adapter;
|
||||
int exit_code;
|
||||
|
||||
hdd_enter();
|
||||
@@ -1785,8 +1751,11 @@ 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);
|
||||
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) {
|
||||
adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
|
||||
if (adapter)
|
||||
ucfg_pkt_capture_resume_mon_thread(adapter->vdev);
|
||||
}
|
||||
|
||||
qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
|
||||
TRACE_CODE_HDD_CFG80211_RESUME_WLAN,
|
||||
@@ -1992,9 +1961,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;
|
||||
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) {
|
||||
adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
|
||||
if (adapter)
|
||||
if (ucfg_pkt_capture_suspend_mon_thread(adapter->vdev))
|
||||
goto resume_pkt_capture_mon_thread;
|
||||
}
|
||||
|
||||
qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
|
||||
@@ -2017,10 +1988,13 @@ 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_pkt_capture_mon_thread:
|
||||
/* Resume packet capture MON thread */
|
||||
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) {
|
||||
adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
|
||||
if (adapter)
|
||||
ucfg_pkt_capture_resume_mon_thread(adapter->vdev);
|
||||
}
|
||||
|
||||
resume_ol_rx:
|
||||
/* Resume tlshim Rx thread */
|
||||
|
Reference in New Issue
Block a user