qcacmn: Stop the monitor reap timer at dp suspend
In case of wlan suspend if packet log is enabled stop the monitor reap timer and reap the pending frames in the ring. Also in case of FW target suspend ACK status reap monitor status ring. During target suspend FW will disable the monitor status ring. This change will make sure no pending frames in the ring during start of system suspend and the target suspend. Change-Id: I350fa508f3ddd125d5e00a7fc60e89507ce8fb4e CRs-Fixed: 2604389
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2017, 2019 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2017, 2019-2020 The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -69,4 +69,27 @@ static inline QDF_STATUS cdp_bus_resume(ol_txrx_soc_handle soc,
|
|||||||
return QDF_STATUS_E_NOSUPPORT;
|
return QDF_STATUS_E_NOSUPPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cdp_process_wow_ack() - Process wow ack response
|
||||||
|
* @soc: data path soc handle
|
||||||
|
* @pdev_id: id of dp pdev handle
|
||||||
|
*
|
||||||
|
* Do any required data path operations for target wow ack
|
||||||
|
* suspend response.
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static inline void cdp_process_wow_ack_rsp(ol_txrx_soc_handle soc,
|
||||||
|
uint8_t pdev_id)
|
||||||
|
{
|
||||||
|
if (!soc || !soc->ops || !soc->ops->bus_ops) {
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s invalid instance", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (soc->ops->bus_ops->process_wow_ack_rsp)
|
||||||
|
return soc->ops->bus_ops->process_wow_ack_rsp(soc, pdev_id);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _CDP_TXRX_BUS_H_ */
|
#endif /* _CDP_TXRX_BUS_H_ */
|
||||||
|
@@ -1518,10 +1518,12 @@ struct cdp_tx_delay_ops {
|
|||||||
* struct cdp_bus_ops - mcl bus suspend/resume ops
|
* struct cdp_bus_ops - mcl bus suspend/resume ops
|
||||||
* @bus_suspend: handler for bus suspend
|
* @bus_suspend: handler for bus suspend
|
||||||
* @bus_resume: handler for bus resume
|
* @bus_resume: handler for bus resume
|
||||||
|
* @process_wow_ack_rsp: handler for wow ack response
|
||||||
*/
|
*/
|
||||||
struct cdp_bus_ops {
|
struct cdp_bus_ops {
|
||||||
QDF_STATUS (*bus_suspend)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id);
|
QDF_STATUS (*bus_suspend)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id);
|
||||||
QDF_STATUS (*bus_resume)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id);
|
QDF_STATUS (*bus_resume)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id);
|
||||||
|
void (*process_wow_ack_rsp)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -201,6 +201,9 @@ static uint8_t dp_soc_ring_if_nss_offloaded(struct dp_soc *soc,
|
|||||||
/* Threshold for peer's cached buf queue beyond which frames are dropped */
|
/* Threshold for peer's cached buf queue beyond which frames are dropped */
|
||||||
#define DP_RX_CACHED_BUFQ_THRESH 64
|
#define DP_RX_CACHED_BUFQ_THRESH 64
|
||||||
|
|
||||||
|
/* Budget to reap monitor status ring */
|
||||||
|
#define DP_MON_REAP_BUDGET 1024
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* default_dscp_tid_map - Default DSCP-TID mapping
|
* default_dscp_tid_map - Default DSCP-TID mapping
|
||||||
*
|
*
|
||||||
@@ -338,30 +341,43 @@ uint32_t dp_soc_get_mon_mask_for_interrupt_mode(struct dp_soc *soc, int intr_ctx
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dp_service_mon_rings()- timer to reap monitor rings
|
* dp_service_mon_rings()- service monitor rings
|
||||||
|
* @soc: soc dp handle
|
||||||
|
* @quota: number of ring entry that can be serviced
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void dp_service_mon_rings(struct dp_soc *soc, uint32_t quota)
|
||||||
|
{
|
||||||
|
int ring = 0, work_done;
|
||||||
|
struct dp_pdev *pdev = NULL;
|
||||||
|
|
||||||
|
for (ring = 0 ; ring < MAX_NUM_LMAC_HW; ring++) {
|
||||||
|
pdev = dp_get_pdev_for_lmac_id(soc, ring);
|
||||||
|
if (!pdev)
|
||||||
|
continue;
|
||||||
|
work_done = dp_mon_process(soc, ring, quota);
|
||||||
|
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
|
||||||
|
FL("Reaped %d descs from Monitor rings"),
|
||||||
|
work_done);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dp_mon_reap_timer_handler()- timer to reap monitor rings
|
||||||
* reqd as we are not getting ppdu end interrupts
|
* reqd as we are not getting ppdu end interrupts
|
||||||
* @arg: SoC Handle
|
* @arg: SoC Handle
|
||||||
*
|
*
|
||||||
* Return:
|
* Return:
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void dp_service_mon_rings(void *arg)
|
static void dp_mon_reap_timer_handler(void *arg)
|
||||||
{
|
{
|
||||||
struct dp_soc *soc = (struct dp_soc *)arg;
|
struct dp_soc *soc = (struct dp_soc *)arg;
|
||||||
int ring = 0, work_done;
|
|
||||||
struct dp_pdev *pdev = NULL;
|
|
||||||
|
|
||||||
for (ring = 0 ; ring < MAX_NUM_LMAC_HW; ring++) {
|
dp_service_mon_rings(soc, QCA_NAPI_BUDGET);
|
||||||
pdev = dp_get_pdev_for_lmac_id(soc, ring);
|
|
||||||
if (!pdev)
|
|
||||||
continue;
|
|
||||||
work_done = dp_mon_process(soc, ring,
|
|
||||||
QCA_NAPI_BUDGET);
|
|
||||||
|
|
||||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
|
|
||||||
FL("Reaped %d descs from Monitor rings"),
|
|
||||||
work_done);
|
|
||||||
}
|
|
||||||
|
|
||||||
qdf_timer_mod(&soc->mon_reap_timer, DP_INTR_POLL_TIMER_MS);
|
qdf_timer_mod(&soc->mon_reap_timer, DP_INTR_POLL_TIMER_MS);
|
||||||
}
|
}
|
||||||
@@ -4670,8 +4686,8 @@ static QDF_STATUS dp_rxdma_ring_config(struct dp_soc *soc)
|
|||||||
* Needed until we enable ppdu end interrupts
|
* Needed until we enable ppdu end interrupts
|
||||||
*/
|
*/
|
||||||
qdf_timer_init(soc->osdev, &soc->mon_reap_timer,
|
qdf_timer_init(soc->osdev, &soc->mon_reap_timer,
|
||||||
dp_service_mon_rings, (void *)soc,
|
dp_mon_reap_timer_handler, (void *)soc,
|
||||||
QDF_TIMER_TYPE_WAKE_APPS);
|
QDF_TIMER_TYPE_WAKE_APPS);
|
||||||
soc->reap_timer_init = 1;
|
soc->reap_timer_init = 1;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -10666,8 +10682,7 @@ static struct cdp_ipa_ops dp_ops_ipa = {
|
|||||||
static QDF_STATUS dp_bus_suspend(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
|
static QDF_STATUS dp_bus_suspend(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
|
||||||
{
|
{
|
||||||
struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
|
struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
|
||||||
struct cdp_pdev *pdev = (struct cdp_pdev *)
|
struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
|
||||||
dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
|
|
||||||
int timeout = SUSPEND_DRAIN_WAIT;
|
int timeout = SUSPEND_DRAIN_WAIT;
|
||||||
int drain_wait_delay = 50; /* 50 ms */
|
int drain_wait_delay = 50; /* 50 ms */
|
||||||
|
|
||||||
@@ -10677,7 +10692,7 @@ static QDF_STATUS dp_bus_suspend(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Abort if there are any pending TX packets */
|
/* Abort if there are any pending TX packets */
|
||||||
while (dp_get_tx_pending(pdev) > 0) {
|
while (dp_get_tx_pending((struct cdp_pdev *)pdev) > 0) {
|
||||||
qdf_sleep(drain_wait_delay);
|
qdf_sleep(drain_wait_delay);
|
||||||
if (timeout <= 0) {
|
if (timeout <= 0) {
|
||||||
dp_err("TX frames are pending, abort suspend");
|
dp_err("TX frames are pending, abort suspend");
|
||||||
@@ -10689,22 +10704,70 @@ static QDF_STATUS dp_bus_suspend(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
|
|||||||
if (soc->intr_mode == DP_INTR_POLL)
|
if (soc->intr_mode == DP_INTR_POLL)
|
||||||
qdf_timer_stop(&soc->int_timer);
|
qdf_timer_stop(&soc->int_timer);
|
||||||
|
|
||||||
|
/* Stop monitor reap timer and reap any pending frames in ring */
|
||||||
|
if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED &&
|
||||||
|
soc->reap_timer_init) {
|
||||||
|
qdf_timer_sync_cancel(&soc->mon_reap_timer);
|
||||||
|
dp_service_mon_rings(soc, DP_MON_REAP_BUDGET);
|
||||||
|
}
|
||||||
|
|
||||||
return QDF_STATUS_SUCCESS;
|
return QDF_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QDF_STATUS dp_bus_resume(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
|
static QDF_STATUS dp_bus_resume(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
|
||||||
{
|
{
|
||||||
struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
|
struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
|
||||||
|
struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
|
||||||
|
|
||||||
|
if (qdf_unlikely(!pdev)) {
|
||||||
|
dp_err("pdev is NULL");
|
||||||
|
return QDF_STATUS_E_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (soc->intr_mode == DP_INTR_POLL)
|
if (soc->intr_mode == DP_INTR_POLL)
|
||||||
qdf_timer_mod(&soc->int_timer, DP_INTR_POLL_TIMER_MS);
|
qdf_timer_mod(&soc->int_timer, DP_INTR_POLL_TIMER_MS);
|
||||||
|
|
||||||
|
/* Start monitor reap timer */
|
||||||
|
if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED &&
|
||||||
|
soc->reap_timer_init)
|
||||||
|
qdf_timer_mod(&soc->mon_reap_timer,
|
||||||
|
DP_INTR_POLL_TIMER_MS);
|
||||||
|
|
||||||
return QDF_STATUS_SUCCESS;
|
return QDF_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dp_process_wow_ack_rsp() - process wow ack response
|
||||||
|
* @soc_hdl: datapath soc handle
|
||||||
|
* @pdev_id: data path pdev handle id
|
||||||
|
*
|
||||||
|
* Return: none
|
||||||
|
*/
|
||||||
|
static void dp_process_wow_ack_rsp(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
|
||||||
|
{
|
||||||
|
struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
|
||||||
|
struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
|
||||||
|
|
||||||
|
if (qdf_unlikely(!pdev)) {
|
||||||
|
dp_err("pdev is NULL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* As part of wow enable FW disables the mon status ring and in wow ack
|
||||||
|
* response from FW reap mon status ring to make sure no packets pending
|
||||||
|
* in the ring.
|
||||||
|
*/
|
||||||
|
if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED &&
|
||||||
|
soc->reap_timer_init) {
|
||||||
|
dp_service_mon_rings(soc, DP_MON_REAP_BUDGET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static struct cdp_bus_ops dp_ops_bus = {
|
static struct cdp_bus_ops dp_ops_bus = {
|
||||||
.bus_suspend = dp_bus_suspend,
|
.bus_suspend = dp_bus_suspend,
|
||||||
.bus_resume = dp_bus_resume
|
.bus_resume = dp_bus_resume,
|
||||||
|
.process_wow_ack_rsp = dp_process_wow_ack_rsp,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user