Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e27b1097 authored by Linux Build Service Account's avatar Linux Build Service Account
Browse files

Merge ab9f60b5 on remote branch

Change-Id: If112ddd2ea16ef0c3db2d60e5b9cb1ddeb84189c
parents 99686a22 ab9f60b5
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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
@@ -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
+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
@@ -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);

/*
@@ -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:
@@ -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;

/**
@@ -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
+8 −0
Original line number Diff line number Diff line
@@ -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;
+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
@@ -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;
@@ -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 */
@@ -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.
@@ -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);
@@ -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);
@@ -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;
@@ -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() */
+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
@@ -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;
@@ -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;
@@ -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 =
@@ -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;
}

@@ -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);
@@ -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;
}

@@ -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;
@@ -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;
@@ -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__);
@@ -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;
@@ -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);

@@ -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;
@@ -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 &&
@@ -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 -
@@ -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