Loading dp/wifi3.0/dp_main.c +6 −6 Original line number Diff line number Diff line Loading @@ -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); } Loading dp/wifi3.0/dp_rx_mon_dest.c +0 −23 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading hal/wifi3.0/hal_api.h +2 −4 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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 Loading hal/wifi3.0/hal_internal.h +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 Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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 */ Loading Loading @@ -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 */ Loading Loading @@ -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 Loading Loading @@ -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 Loading @@ -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 Loading hal/wifi3.0/hal_srng.c +3 −462 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading @@ -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) Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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) Loading Loading @@ -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, Loading Loading @@ -1398,7 +942,6 @@ void hal_delayed_reg_write(struct hal_soc *hal_soc, } #endif #endif #endif /** * hal_attach - Initialize HAL layer Loading Loading @@ -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; Loading Loading @@ -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 Loading
dp/wifi3.0/dp_main.c +6 −6 Original line number Diff line number Diff line Loading @@ -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); } Loading
dp/wifi3.0/dp_rx_mon_dest.c +0 −23 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading
hal/wifi3.0/hal_api.h +2 −4 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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 Loading
hal/wifi3.0/hal_internal.h +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 Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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 */ Loading Loading @@ -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 */ Loading Loading @@ -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 Loading Loading @@ -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 Loading @@ -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 Loading
hal/wifi3.0/hal_srng.c +3 −462 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading @@ -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) Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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) Loading Loading @@ -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, Loading Loading @@ -1398,7 +942,6 @@ void hal_delayed_reg_write(struct hal_soc *hal_soc, } #endif #endif #endif /** * hal_attach - Initialize HAL layer Loading Loading @@ -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; Loading Loading @@ -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