qcacmn: Invoke hal_reg_write_need_delay before the register write
hal_reg_write_need_delay is invoked immediately after q_elem->valid check. The first two instructions in hal_reg_write_need_delay could be in the CPU instruction pipeline which could result in possible loading and dereferencing of NULL srng from an invalid q_elem. Fix is to invoke hal_reg_write_need_delay just before hal_process_reg_write_q_elem and also add NULL checks to avoid the srng NULL pointer dereference. Change-Id: I2de50b1e78782e3c91a9cb4477f28d91f9c29439 CRs-Fixed: 2973257
This commit is contained in:

committed by
Madan Koyyalamudi

parent
1104d6d5a7
commit
8ddd31db96
@@ -721,10 +721,17 @@ static inline void hal_reg_write_fill_sched_delay_hist(struct hal_soc *hal,
|
|||||||
static inline bool hal_reg_write_need_delay(struct hal_reg_write_q_elem *elem)
|
static inline bool hal_reg_write_need_delay(struct hal_reg_write_q_elem *elem)
|
||||||
{
|
{
|
||||||
struct hal_srng *srng = elem->srng;
|
struct hal_srng *srng = elem->srng;
|
||||||
struct hal_soc *hal = srng->hal_soc;
|
struct hal_soc *hal;
|
||||||
qdf_time_t now;
|
qdf_time_t now;
|
||||||
qdf_iomem_t real_addr;
|
qdf_iomem_t real_addr;
|
||||||
|
|
||||||
|
if (qdf_unlikely(!srng))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
hal = srng->hal_soc;
|
||||||
|
if (qdf_unlikely(!hal))
|
||||||
|
return false;
|
||||||
|
|
||||||
/* Check if it is target srng, and valid shadow reg */
|
/* Check if it is target srng, and valid shadow reg */
|
||||||
if (qdf_likely(!IS_SRNG_MATCH(srng)))
|
if (qdf_likely(!IS_SRNG_MATCH(srng)))
|
||||||
return false;
|
return false;
|
||||||
@@ -795,10 +802,6 @@ static void hal_reg_write_work(void *arg)
|
|||||||
if (!q_elem->valid)
|
if (!q_elem->valid)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (hal_reg_write_need_delay(q_elem))
|
|
||||||
hal_verbose_debug("Delay reg writer for srng 0x%x, addr 0x%pK",
|
|
||||||
q_elem->srng->ring_id, q_elem->addr);
|
|
||||||
|
|
||||||
q_elem->dequeue_time = qdf_get_log_timestamp();
|
q_elem->dequeue_time = qdf_get_log_timestamp();
|
||||||
ring_id = q_elem->srng->ring_id;
|
ring_id = q_elem->srng->ring_id;
|
||||||
addr = q_elem->addr;
|
addr = q_elem->addr;
|
||||||
@@ -809,6 +812,10 @@ static void hal_reg_write_work(void *arg)
|
|||||||
hal->stats.wstats.dequeues++;
|
hal->stats.wstats.dequeues++;
|
||||||
qdf_atomic_dec(&hal->stats.wstats.q_depth);
|
qdf_atomic_dec(&hal->stats.wstats.q_depth);
|
||||||
|
|
||||||
|
if (hal_reg_write_need_delay(q_elem))
|
||||||
|
hal_verbose_debug("Delay reg writer for srng 0x%x, addr 0x%pK",
|
||||||
|
q_elem->srng->ring_id, q_elem->addr);
|
||||||
|
|
||||||
write_val = hal_process_reg_write_q_elem(hal, q_elem);
|
write_val = hal_process_reg_write_q_elem(hal, q_elem);
|
||||||
hal_verbose_debug("read_idx %u srng 0x%x, addr 0x%pK dequeue_val %u sched delay %llu us",
|
hal_verbose_debug("read_idx %u srng 0x%x, addr 0x%pK dequeue_val %u sched delay %llu us",
|
||||||
hal->read_idx, ring_id, addr, write_val, delta_us);
|
hal->read_idx, ring_id, addr, write_val, delta_us);
|
||||||
|
Reference in New Issue
Block a user