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

Commit 5e3b9a77 authored by Maheswara Sarma's avatar Maheswara Sarma
Browse files

Merge commit '4a8efff2' into wlan-cmn.driver.lnx.2.0.8.r3-rel

Change-Id: I1073ac9d41f947762b0516bd96837868b8972fac
parents a0fad75b 4a8efff2
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -10495,27 +10495,27 @@ static void dp_display_srng_info(struct cdp_soc_t *soc_hdl)
	dp_info("SRNG HP-TP data:");
	for (i = 0; i < soc->num_tcl_data_rings; i++) {
		hal_get_sw_hptp(hal_soc, soc->tcl_data_ring[i].hal_srng,
				&hp, &tp);
				&tp, &hp);
		dp_info("TCL DATA ring[%d]: hp=0x%x, tp=0x%x", i, hp, tp);

		hal_get_sw_hptp(hal_soc, soc->tx_comp_ring[i].hal_srng,
				&hp, &tp);
				&tp, &hp);
		dp_info("TX comp ring[%d]: hp=0x%x, tp=0x%x", i, hp, tp);
	}

	for (i = 0; i < soc->num_reo_dest_rings; i++) {
		hal_get_sw_hptp(hal_soc, soc->reo_dest_ring[i].hal_srng,
				&hp, &tp);
				&tp, &hp);
		dp_info("REO DST ring[%d]: hp=0x%x, tp=0x%x", i, hp, tp);
	}

	hal_get_sw_hptp(hal_soc, soc->reo_exception_ring.hal_srng, &hp, &tp);
	hal_get_sw_hptp(hal_soc, soc->reo_exception_ring.hal_srng, &tp, &hp);
	dp_info("REO exception ring: hp=0x%x, tp=0x%x", hp, tp);

	hal_get_sw_hptp(hal_soc, soc->rx_rel_ring.hal_srng, &hp, &tp);
	hal_get_sw_hptp(hal_soc, soc->rx_rel_ring.hal_srng, &tp, &hp);
	dp_info("WBM RX release ring: hp=0x%x, tp=0x%x", hp, tp);

	hal_get_sw_hptp(hal_soc, soc->wbm_desc_rel_ring.hal_srng, &hp, &tp);
	hal_get_sw_hptp(hal_soc, soc->wbm_desc_rel_ring.hal_srng, &tp, &hp);
	dp_info("WBM desc release ring: hp=0x%x, tp=0x%x", hp, tp);
}

+0 −23
Original line number Diff line number Diff line
@@ -1411,27 +1411,6 @@ qdf_nbuf_t dp_rx_mon_restitch_mpdu(struct dp_soc *soc, uint32_t mac_id,
}
#endif

#ifdef DP_MON_RSSI_IN_DBM
/*
 * dp_rx_mon_rssi_convert(): convert rssi_comb from unit dBm to dB
 *		to match with radiotap further conversion requirement
 * @rx_status: monitor mode rx status pointer
 *
 * Return: none
 */
static inline
void dp_rx_mon_rssi_convert(struct mon_rx_status *rx_status)
{
	rx_status->rssi_comb = rx_status->rssi_comb -
				rx_status->chan_noise_floor;
}
#else
static inline
void dp_rx_mon_rssi_convert(struct mon_rx_status *rx_status)
{
}
#endif

/*
 * dp_rx_mon_deliver(): function to deliver packets to stack
 * @soc: DP soc
@@ -1469,8 +1448,6 @@ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id,
		pdev->ppdu_info.rx_status.device_id = soc->device_id;
		pdev->ppdu_info.rx_status.chan_noise_floor =
			pdev->chan_noise_floor;
		/* convert rssi_comb from dBm to positive dB value */
		dp_rx_mon_rssi_convert(&pdev->ppdu_info.rx_status);

		dp_handle_tx_capture(soc, pdev, mon_mpdu);

+2 −4
Original line number Diff line number Diff line
@@ -455,8 +455,7 @@ static inline void hal_srng_write_address_32_mb(struct hal_soc *hal_soc,
{
	qdf_iowrite32(addr, value);
}
#elif defined(FEATURE_HAL_DELAYED_REG_WRITE) || \
	defined(FEATURE_HAL_DELAYED_REG_WRITE_V2)
#elif defined(FEATURE_HAL_DELAYED_REG_WRITE)
static inline void hal_srng_write_address_32_mb(struct hal_soc *hal_soc,
						struct hal_srng *srng,
						void __iomem *addr,
@@ -778,8 +777,7 @@ static inline void hal_write32_mb_confirm_retry(struct hal_soc *hal_soc,
}
#endif /* GENERIC_SHADOW_REGISTER_ACCESS_ENABLE */

#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \
	defined(FEATURE_HAL_DELAYED_REG_WRITE_V2)
#if defined(FEATURE_HAL_DELAYED_REG_WRITE)
/**
 * hal_dump_reg_write_srng_stats() - dump SRNG reg write stats
 * @hal_soc: HAL soc handle
+6 −42
Original line number Diff line number Diff line
/*
 * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2021 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
@@ -25,8 +25,7 @@
#include "qdf_mem.h"
#include "qdf_nbuf.h"
#include "pld_common.h"
#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \
	defined(FEATURE_HAL_DELAYED_REG_WRITE_V2)
#if defined(FEATURE_HAL_DELAYED_REG_WRITE)
#include "qdf_defer.h"
#include "qdf_timer.h"
#endif
@@ -259,8 +258,7 @@ typedef struct hal_ring_handle *hal_ring_handle_t;
 */
#define HAL_SRNG_FLUSH_EVENT BIT(0)

#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \
	defined(FEATURE_HAL_DELAYED_REG_WRITE_V2)
#if defined(FEATURE_HAL_DELAYED_REG_WRITE)

/**
 * struct hal_reg_write_q_elem - delayed register write queue element
@@ -339,21 +337,6 @@ struct hal_reg_write_soc_stats {
	uint32_t sched_delay[REG_WRITE_SCHED_DELAY_HIST_MAX];
	uint32_t dequeue_delay;
};

#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2
struct hal_reg_write_tcl_stats {
	uint32_t wq_delayed;
	uint32_t wq_direct;
	uint32_t timer_enq;
	uint32_t timer_direct;
	uint32_t enq_timer_set;
	uint32_t direct_timer_set;
	uint32_t timer_reset;
	qdf_time_t enq_time;
	qdf_time_t deq_time;
	uint32_t sched_delay[REG_WRITE_SCHED_DELAY_HIST_MAX];
};
#endif
#endif

/* Common SRNG ring structure for source and destination rings */
@@ -476,10 +459,7 @@ struct hal_srng {
	/* last ring desc entry cleared */
	uint32_t last_desc_cleared;
#endif
#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \
	defined(FEATURE_HAL_DELAYED_REG_WRITE_V2)
	/* Previous hp/tp (based on ring dir) value written to the reg */
	uint32_t last_reg_wr_val;
#if defined(FEATURE_HAL_DELAYED_REG_WRITE)
	/* flag to indicate whether srng is already queued for delayed write */
	uint8_t reg_write_in_progress;
	/* last dequeue elem time stamp */
@@ -718,8 +698,7 @@ struct hal_hw_txrx_ops {
 */
struct hal_soc_stats {
	uint32_t reg_write_fail;
#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \
	defined(FEATURE_HAL_DELAYED_REG_WRITE_V2)
#if defined(FEATURE_HAL_DELAYED_REG_WRITE)
	struct hal_reg_write_soc_stats wstats;
#endif
#ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE
@@ -835,20 +814,6 @@ struct hal_soc {
	/* read index used by worker thread to dequeue/write registers */
	uint32_t read_idx;
#endif /*FEATURE_HAL_DELAYED_REG_WRITE */
#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2
	/* delayed work for TCL reg write to be queued into workqueue */
	qdf_work_t tcl_reg_write_work;
	/* workqueue for TCL delayed register writes */
	qdf_workqueue_t *tcl_reg_write_wq;
	/* flag denotes whether TCL delayed write work is active */
	qdf_atomic_t tcl_work_active;
	/* flag indiactes TCL write happening from direct context */
	bool tcl_direct;
	/* timer to handle the pending TCL reg writes */
	qdf_timer_t tcl_reg_write_timer;
	/* stats related to TCL reg write */
	struct hal_reg_write_tcl_stats tcl_stats;
#endif /* FEATURE_HAL_DELAYED_REG_WRITE_V2 */
	qdf_atomic_t active_work_cnt;
#ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE
	struct shadow_reg_config
@@ -857,8 +822,7 @@ struct hal_soc {
#endif
};

#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \
	defined(FEATURE_HAL_DELAYED_REG_WRITE_V2)
#if defined(FEATURE_HAL_DELAYED_REG_WRITE)
/**
 *  hal_delayed_reg_write() - delayed regiter write
 * @hal_soc: HAL soc handle
+3 −462
Original line number Diff line number Diff line
@@ -446,8 +446,7 @@ uint32_t hal_get_target_type(hal_soc_handle_t hal_soc_hdl)

qdf_export_symbol(hal_get_target_type);

#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \
	defined(FEATURE_HAL_DELAYED_REG_WRITE_V2)
#if defined(FEATURE_HAL_DELAYED_REG_WRITE)
/**
 * hal_is_reg_write_tput_level_high() - throughput level for delayed reg writes
 * @hal: hal_soc pointer
@@ -501,41 +500,6 @@ void hal_dump_reg_write_srng_stats(hal_soc_handle_t hal_soc_hdl)
		  hal_fill_reg_write_srng_stats(srng, buf, sizeof(buf)));
}

#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2
/**
 * hal_dump_tcl_stats() - dump the TCL reg write stats
 * @hal: hal_soc pointer
 *
 * Return: None
 */
static inline void hal_dump_tcl_stats(struct hal_soc *hal)
{
	struct hal_srng *srng = hal_get_srng(hal, HAL_SRNG_SW2TCL1);
	uint32_t *hist = hal->tcl_stats.sched_delay;
	char buf[HAL_REG_WRITE_SRNG_STATS_LEN];

	hal_debug("TCL: %s sched-delay hist %u %u %u %u",
		  hal_fill_reg_write_srng_stats(srng, buf, sizeof(buf)),
		  hist[REG_WRITE_SCHED_DELAY_SUB_100us],
		  hist[REG_WRITE_SCHED_DELAY_SUB_1000us],
		  hist[REG_WRITE_SCHED_DELAY_SUB_5000us],
		  hist[REG_WRITE_SCHED_DELAY_GT_5000us]);
	hal_debug("wq_dly %u wq_dir %u tim_enq %u tim_dir %u enq_tim_cnt %u dir_tim_cnt %u rst_tim_cnt %u",
		  hal->tcl_stats.wq_delayed,
		  hal->tcl_stats.wq_direct,
		  hal->tcl_stats.timer_enq,
		  hal->tcl_stats.timer_direct,
		  hal->tcl_stats.enq_timer_set,
		  hal->tcl_stats.direct_timer_set,
		  hal->tcl_stats.timer_reset);
}

#else
static inline void hal_dump_tcl_stats(struct hal_soc *hal)
{
}
#endif

void hal_dump_reg_write_stats(hal_soc_handle_t hal_soc_hdl)
{
	uint32_t *hist;
@@ -553,8 +517,6 @@ void hal_dump_reg_write_stats(hal_soc_handle_t hal_soc_hdl)
		  hist[REG_WRITE_SCHED_DELAY_SUB_1000us],
		  hist[REG_WRITE_SCHED_DELAY_SUB_5000us],
		  hist[REG_WRITE_SCHED_DELAY_GT_5000us]);

	hal_dump_tcl_stats(hal);
}

int hal_get_reg_write_pending_work(void *hal_soc)
@@ -577,46 +539,6 @@ int hal_get_reg_write_pending_work(void *hal_soc)
#define HAL_REG_WRITE_QUEUE_LEN 32
#endif

#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2
/**
 * hal_process_reg_write_q_elem() - process a regiter write queue element
 * @hal: hal_soc pointer
 * @q_elem: pointer to hal regiter write queue element
 *
 * Return: The value which was written to the address
 */
static uint32_t
hal_process_reg_write_q_elem(struct hal_soc *hal,
			     struct hal_reg_write_q_elem *q_elem)
{
	struct hal_srng *srng = q_elem->srng;
	uint32_t write_val;

	SRNG_LOCK(&srng->lock);
	srng->reg_write_in_progress = false;
	srng->wstats.dequeues++;

	if (srng->ring_dir == HAL_SRNG_SRC_RING) {
		write_val = srng->u.src_ring.hp;
		q_elem->dequeue_val = write_val;
		q_elem->valid = 0;
		SRNG_UNLOCK(&srng->lock);
		hal_write_address_32_mb(hal,
					srng->u.src_ring.hp_addr,
					write_val, false);
	} else {
		write_val = srng->u.dst_ring.tp;
		q_elem->dequeue_val = write_val;
		q_elem->valid = 0;
		SRNG_UNLOCK(&srng->lock);
		hal_write_address_32_mb(hal,
					srng->u.dst_ring.tp_addr,
					write_val, false);
	}

	return write_val;
}
#else
/**
 * hal_process_reg_write_q_elem() - process a regiter write queue element
 * @hal: hal_soc pointer
@@ -656,7 +578,6 @@ hal_process_reg_write_q_elem(struct hal_soc *hal,

	return write_val;
}
#endif

/**
 * hal_reg_write_fill_sched_delay_hist() - fill reg write delay histogram in hal
@@ -818,8 +739,8 @@ static void hal_reg_write_work(void *arg)

static void __hal_flush_reg_write_work(struct hal_soc *hal)
{
	qdf_cancel_work(&hal->reg_write_work);

	qdf_flush_work(&hal->reg_write_work);
	qdf_disable_work(&hal->reg_write_work);
}

void hal_flush_reg_write_work(hal_soc_handle_t hal_handle)
@@ -962,383 +883,6 @@ static inline void hal_delayed_reg_write_deinit(struct hal_soc *hal)
}
#endif

#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2
#ifdef MEMORY_DEBUG
/**
 * hal_reg_write_get_timestamp() - Function to get the timestamp
 *
 * Return: return present simestamp
 */
static inline qdf_time_t hal_del_reg_write_get_ts(void)
{
	return qdf_get_log_timestamp();
}

/**
 * hal_del_reg_write_ts_usecs() - Convert the timestamp to micro secs
 * @ts: timestamp value to be converted
 *
 * Return: return the timestamp in micro secs
 */
static inline qdf_time_t hal_del_reg_write_ts_usecs(qdf_time_t ts)
{
	return qdf_log_timestamp_to_usecs(ts);
}

/**
 * hal_tcl_write_fill_sched_delay_hist() - fill TCL reg write delay histogram
 * @hal: hal_soc pointer
 * @delay: delay in us
 *
 * Return: None
 */
static inline void hal_tcl_write_fill_sched_delay_hist(struct hal_soc *hal)
{
	uint32_t *hist;
	uint32_t delay_us;

	hal->tcl_stats.deq_time = hal_del_reg_write_get_ts();
	delay_us = hal_del_reg_write_ts_usecs(hal->tcl_stats.deq_time -
					      hal->tcl_stats.enq_time);

	hist = hal->tcl_stats.sched_delay;
	if (delay_us < 100)
		hist[REG_WRITE_SCHED_DELAY_SUB_100us]++;
	else if (delay_us < 1000)
		hist[REG_WRITE_SCHED_DELAY_SUB_1000us]++;
	else if (delay_us < 5000)
		hist[REG_WRITE_SCHED_DELAY_SUB_5000us]++;
	else
		hist[REG_WRITE_SCHED_DELAY_GT_5000us]++;
}

#else
static inline qdf_time_t hal_del_reg_write_get_ts(void)
{
	return 0;
}

static inline qdf_time_t hal_del_reg_write_ts_usecs(qdf_time_t ts)
{
	return 0;
}

static inline void hal_tcl_write_fill_sched_delay_hist(struct hal_soc *hal)
{
}
#endif

/**
 * hal_tcl_reg_write_work() - Worker to process delayed SW2TCL1 writes
 * @arg: hal_soc pointer
 *
 * Return: None
 */
static void hal_tcl_reg_write_work(void *arg)
{
	struct hal_soc *hal = arg;
	struct hal_srng *srng = hal_get_srng(hal, HAL_SRNG_SW2TCL1);

	SRNG_LOCK(&srng->lock);
	srng->wstats.dequeues++;
	hal_tcl_write_fill_sched_delay_hist(hal);

	/*
	 * During the tranition of low to high tput scenario, reg write moves
	 * from delayed to direct write context, there is a little chance that
	 * worker thread gets scheduled later than direct context write which
	 * already wrote the latest HP value. This check can catch that case
	 * and avoid the repetitive writing of the same HP value.
	 */
	if (srng->last_reg_wr_val != srng->u.src_ring.hp) {
		srng->last_reg_wr_val = srng->u.src_ring.hp;
		if (hal->tcl_direct) {
			/*
			 * TCL reg writes have been moved to direct context and
			 * the assumption is that PCIe bus stays in Active state
			 * during high tput, hence its fine to write the HP
			 * while the SRNG_LOCK is being held.
			 */
			hal->tcl_stats.wq_direct++;
			hal_write_address_32_mb(hal, srng->u.src_ring.hp_addr,
						srng->last_reg_wr_val, false);
			srng->reg_write_in_progress = false;
			SRNG_UNLOCK(&srng->lock);
		} else {
			/*
			 * TCL reg write to happen in delayed context,
			 * write operation might take time due to possibility of
			 * PCIe bus stays in low power state during low tput,
			 * Hence release the SRNG_LOCK before writing.
			 */
			hal->tcl_stats.wq_delayed++;
			srng->reg_write_in_progress = false;
			SRNG_UNLOCK(&srng->lock);
			hal_write_address_32_mb(hal, srng->u.src_ring.hp_addr,
						srng->last_reg_wr_val, false);
		}
	} else {
		srng->reg_write_in_progress = false;
		SRNG_UNLOCK(&srng->lock);
	}

	/*
	 * Decrement active_work_cnt to make sure that hif_try_complete_tasks
	 * will wait. This will avoid race condition between delayed register
	 * worker and bus suspend (system suspend or runtime suspend).
	 *
	 * The following decrement should be done at the end!
	 */
	qdf_atomic_dec(&hal->active_work_cnt);
	qdf_atomic_set(&hal->tcl_work_active, false);
}

static void __hal_flush_tcl_reg_write_work(struct hal_soc *hal)
{
	qdf_cancel_work(&hal->tcl_reg_write_work);
}

/**
 * hal_tcl_reg_write_enqueue() - enqueue TCL register writes into kworker
 * @hal_soc: hal_soc pointer
 * @srng: srng pointer
 * @addr: iomem address of regiter
 * @value: value to be written to iomem address
 *
 * This function executes from within the SRNG LOCK
 *
 * Return: None
 */
static void hal_tcl_reg_write_enqueue(struct hal_soc *hal_soc,
				      struct hal_srng *srng,
				      void __iomem *addr,
				      uint32_t value)
{
	hal_soc->tcl_stats.enq_time = hal_del_reg_write_get_ts();

	if (qdf_queue_work(hal_soc->qdf_dev, hal_soc->tcl_reg_write_wq,
			   &hal_soc->tcl_reg_write_work)) {
		srng->reg_write_in_progress  = true;
		qdf_atomic_inc(&hal_soc->active_work_cnt);
		qdf_atomic_set(&hal_soc->tcl_work_active, true);
		srng->wstats.enqueues++;
	} else {
		hal_soc->tcl_stats.enq_timer_set++;
		qdf_timer_mod(&hal_soc->tcl_reg_write_timer, 1);
	}
}

/**
 * hal_tcl_reg_write_timer() - timer handler to take care of pending TCL writes
 * @arg: srng handle
 *
 * This function handles the pending TCL reg writes missed due to the previous
 * scheduled worker running.
 *
 * Return: None
 */
static void hal_tcl_reg_write_timer(void *arg)
{
	hal_ring_handle_t srng_hdl = arg;
	struct hal_srng *srng;
	struct hal_soc *hal;

	srng = (struct hal_srng *)srng_hdl;
	hal = srng->hal_soc;

	if (hif_pm_runtime_get(hal->hif_handle, RTPM_ID_DW_TX_HW_ENQUEUE,
			       true)) {
		hal_srng_set_event(srng_hdl, HAL_SRNG_FLUSH_EVENT);
		hal_srng_inc_flush_cnt(srng_hdl);
		goto fail;
	}

	SRNG_LOCK(&srng->lock);
	if (hal->tcl_direct) {
		/*
		 * Due to the previous scheduled worker still running,
		 * direct reg write cannot be performed, so posted the
		 * pending writes to timer context.
		 */
		if (srng->last_reg_wr_val != srng->u.src_ring.hp) {
			srng->last_reg_wr_val = srng->u.src_ring.hp;
			srng->wstats.direct++;
			hal->tcl_stats.timer_direct++;
			hal_write_address_32_mb(hal, srng->u.src_ring.hp_addr,
						srng->last_reg_wr_val, false);
		}
	} else {
		/*
		 * Due to the previous scheduled worker still running,
		 * queue_work from delayed context would fail,
		 * so retry from timer context.
		 */
		if (qdf_queue_work(hal->qdf_dev, hal->tcl_reg_write_wq,
				   &hal->tcl_reg_write_work)) {
			srng->reg_write_in_progress  = true;
			qdf_atomic_inc(&hal->active_work_cnt);
			qdf_atomic_set(&hal->tcl_work_active, true);
			srng->wstats.enqueues++;
			hal->tcl_stats.timer_enq++;
		} else {
			if (srng->last_reg_wr_val != srng->u.src_ring.hp) {
				hal->tcl_stats.timer_reset++;
				qdf_timer_mod(&hal->tcl_reg_write_timer, 1);
			}
		}
	}
	SRNG_UNLOCK(&srng->lock);
	hif_pm_runtime_put(hal->hif_handle, RTPM_ID_DW_TX_HW_ENQUEUE);

fail:
	return;
}

/**
 * hal_delayed_tcl_reg_write_init() - Initialization for delayed TCL reg writes
 * @hal_soc: hal_soc pointer
 *
 * Initialize main data structures to process TCL register writes in a delayed
 * workqueue.
 *
 * Return: QDF_STATUS_SUCCESS on success else a QDF error.
 */
static QDF_STATUS hal_delayed_tcl_reg_write_init(struct hal_soc *hal)
{
	struct hal_srng *srng = hal_get_srng(hal, HAL_SRNG_SW2TCL1);
	QDF_STATUS status;

	hal->tcl_reg_write_wq =
		qdf_alloc_high_prior_ordered_workqueue("hal_tcl_reg_write_wq");
	if (!hal->tcl_reg_write_wq) {
		hal_err("hal_tcl_reg_write_wq alloc failed");
		return QDF_STATUS_E_NOMEM;
	}

	status = qdf_create_work(0, &hal->tcl_reg_write_work,
				 hal_tcl_reg_write_work, hal);
	if (status != QDF_STATUS_SUCCESS) {
		hal_err("tcl_reg_write_work create failed");
		goto fail;
	}

	status = qdf_timer_init(hal->qdf_dev, &hal->tcl_reg_write_timer,
				hal_tcl_reg_write_timer, (void *)srng,
				QDF_TIMER_TYPE_WAKE_APPS);
	if (status != QDF_STATUS_SUCCESS) {
		hal_err("tcl_reg_write_timer init failed");
		goto fail;
	}

	qdf_atomic_init(&hal->tcl_work_active);

	return QDF_STATUS_SUCCESS;

fail:
	qdf_destroy_workqueue(0, hal->tcl_reg_write_wq);
	return status;
}

/**
 * hal_delayed_tcl_reg_write_deinit() - De-Initialize delayed TCL reg writes
 * @hal_soc: hal_soc pointer
 *
 * De-initialize main data structures to process TCL register writes in a
 * delayed workqueue.
 *
 * Return: None
 */
static void hal_delayed_tcl_reg_write_deinit(struct hal_soc *hal)
{
	qdf_timer_stop(&hal->tcl_reg_write_timer);
	qdf_timer_free(&hal->tcl_reg_write_timer);

	__hal_flush_tcl_reg_write_work(hal);
	qdf_flush_workqueue(0, hal->tcl_reg_write_wq);
	qdf_destroy_workqueue(0, hal->tcl_reg_write_wq);
}

#else
static inline QDF_STATUS hal_delayed_tcl_reg_write_init(struct hal_soc *hal)
{
	return QDF_STATUS_SUCCESS;
}

static inline void hal_delayed_tcl_reg_write_deinit(struct hal_soc *hal)
{
}
#endif

#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2
#ifdef FEATURE_HAL_DELAYED_REG_WRITE
static inline void hal_reg_write_enqueue_v2(struct hal_soc *hal_soc,
					    struct hal_srng *srng,
					    void __iomem *addr,
					    uint32_t value)
{
	hal_reg_write_enqueue(hal_soc, srng, addr, value);
}
#else
static inline void hal_reg_write_enqueue_v2(struct hal_soc *hal_soc,
					    struct hal_srng *srng,
					    void __iomem *addr,
					    uint32_t value)
{
	qdf_atomic_inc(&hal_soc->stats.wstats.direct);
	srng->wstats.direct++;
	hal_write_address_32_mb(hal_soc, addr, value, false);
}
#endif
void hal_delayed_reg_write(struct hal_soc *hal_soc,
			   struct hal_srng *srng,
			   void __iomem *addr,
			   uint32_t value)
{
	switch (srng->ring_type) {
	case TCL_DATA:
		if (hal_is_reg_write_tput_level_high(hal_soc)) {
			hal_soc->tcl_direct = true;
			if (srng->reg_write_in_progress ||
			    !qdf_atomic_read(&hal_soc->tcl_work_active)) {
				/*
				 * Now the delayed work have either completed
				 * the writing or not even scheduled and would
				 * be blocked by SRNG_LOCK, hence it is fine to
				 * do direct write here.
				 */
				srng->last_reg_wr_val = srng->u.src_ring.hp;
				srng->wstats.direct++;
				hal_write_address_32_mb(hal_soc, addr,
							srng->last_reg_wr_val,
							false);
			} else {
				hal_soc->tcl_stats.direct_timer_set++;
				qdf_timer_mod(&hal_soc->tcl_reg_write_timer, 1);
			}
		} else {
			hal_soc->tcl_direct = false;
			if (srng->reg_write_in_progress) {
				srng->wstats.coalesces++;
			} else {
				hal_tcl_reg_write_enqueue(hal_soc, srng,
							  addr, value);
			}
		}
		break;
	case CE_SRC:
	case CE_DST:
	case CE_DST_STATUS:
		hal_reg_write_enqueue_v2(hal_soc, srng, addr, value);
		break;
	default:
		qdf_atomic_inc(&hal_soc->stats.wstats.direct);
		srng->wstats.direct++;
		hal_write_address_32_mb(hal_soc, addr, value, false);
		break;
	}
}

#else
#ifdef FEATURE_HAL_DELAYED_REG_WRITE
#ifdef QCA_WIFI_QCA6750
void hal_delayed_reg_write(struct hal_soc *hal_soc,
@@ -1398,7 +942,6 @@ void hal_delayed_reg_write(struct hal_soc *hal_soc,
}
#endif
#endif
#endif

/**
 * hal_attach - Initialize HAL layer
@@ -1470,7 +1013,6 @@ void *hal_attach(struct hif_opaque_softc *hif_handle, qdf_device_t qdf_dev)

	qdf_atomic_init(&hal->active_work_cnt);
	hal_delayed_reg_write_init(hal);
	hal_delayed_tcl_reg_write_init(hal);

	return (void *)hal;

@@ -1521,7 +1063,6 @@ extern void hal_detach(void *hal_soc)
	struct hal_soc *hal = (struct hal_soc *)hal_soc;

	hal_delayed_reg_write_deinit(hal);
	hal_delayed_tcl_reg_write_deinit(hal);

	qdf_mem_free_consistent(hal->qdf_dev, hal->qdf_dev->dev,
		sizeof(*(hal->shadow_rdptr_mem_vaddr)) * HAL_SRNG_ID_MAX,
Loading