qcacmn: Trigger sys wakeup for WMI command when WOW is enabled

DHCP packet is received in the IPA exception path when
system is suspending. As part of DHCP packet processing,
WMI_PEER_SET_PARAM_CMDID is sent to FW after WOW is
enabled resulting in self recovery getting triggered by
host.

Fix is to do an explicit system wakeup if a WMI command
has to be sent post WOW enablement.

Change-Id: If1904a4fe5c861deed1b35071be10cb8cc8d6407
CRs-Fixed: 2890913
This commit is contained in:
Yeshwanth Sriram Guntuka
2021-03-16 13:49:31 +05:30
committed by snandini
parent 125c4c2a60
commit 6611374cf4
7 changed files with 327 additions and 4 deletions

View File

@@ -333,6 +333,22 @@ enum hif_event_type {
/* Do check hif_hist_skip_event_record when adding new events */
};
/**
* enum hif_system_pm_state - System PM state
* HIF_SYSTEM_PM_STATE_ON: System in active state
* HIF_SYSTEM_PM_STATE_BUS_RESUMING: bus resume in progress as part of
* system resume
* HIF_SYSTEM_PM_STATE_BUS_SUSPENDING: bus suspend in progress as part of
* system suspend
* HIF_SYSTEM_PM_STATE_BUS_SUSPENDED: bus suspended as part of system suspend
*/
enum hif_system_pm_state {
HIF_SYSTEM_PM_STATE_ON,
HIF_SYSTEM_PM_STATE_BUS_RESUMING,
HIF_SYSTEM_PM_STATE_BUS_SUSPENDING,
HIF_SYSTEM_PM_STATE_BUS_SUSPENDED,
};
#ifdef WLAN_FEATURE_DP_EVENT_HISTORY
#if defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)
@@ -1778,4 +1794,118 @@ static inline
void hif_set_enable_detection(struct hif_opaque_softc *hif_ctx, bool value)
{}
#endif
#ifdef SYSTEM_PM_CHECK
/**
* __hif_system_pm_set_state() - Set system pm state
* @hif: hif opaque handle
* @state: system state
*
* Return: None
*/
void __hif_system_pm_set_state(struct hif_opaque_softc *hif,
enum hif_system_pm_state state);
/**
* hif_system_pm_set_state_on() - Set system pm state to ON
* @hif: hif opaque handle
*
* Return: None
*/
static inline
void hif_system_pm_set_state_on(struct hif_opaque_softc *hif)
{
__hif_system_pm_set_state(hif, HIF_SYSTEM_PM_STATE_ON);
}
/**
* hif_system_pm_set_state_resuming() - Set system pm state to resuming
* @hif: hif opaque handle
*
* Return: None
*/
static inline
void hif_system_pm_set_state_resuming(struct hif_opaque_softc *hif)
{
__hif_system_pm_set_state(hif, HIF_SYSTEM_PM_STATE_BUS_RESUMING);
}
/**
* hif_system_pm_set_state_suspending() - Set system pm state to suspending
* @hif: hif opaque handle
*
* Return: None
*/
static inline
void hif_system_pm_set_state_suspending(struct hif_opaque_softc *hif)
{
__hif_system_pm_set_state(hif, HIF_SYSTEM_PM_STATE_BUS_SUSPENDING);
}
/**
* hif_system_pm_set_state_suspended() - Set system pm state to suspended
* @hif: hif opaque handle
*
* Return: None
*/
static inline
void hif_system_pm_set_state_suspended(struct hif_opaque_softc *hif)
{
__hif_system_pm_set_state(hif, HIF_SYSTEM_PM_STATE_BUS_SUSPENDED);
}
/**
* hif_system_pm_get_state() - Get system pm state
* @hif: hif opaque handle
*
* Return: system state
*/
int32_t hif_system_pm_get_state(struct hif_opaque_softc *hif);
/**
* hif_system_pm_state_check() - Check system state and trigger resume
* if required
* @hif: hif opaque handle
*
* Return: 0 if system is in on state else error code
*/
int hif_system_pm_state_check(struct hif_opaque_softc *hif);
#else
static inline
void __hif_system_pm_set_state(struct hif_opaque_softc *hif,
enum hif_system_pm_state state)
{
}
static inline
void hif_system_pm_set_state_on(struct hif_opaque_softc *hif)
{
}
static inline
void hif_system_pm_set_state_resuming(struct hif_opaque_softc *hif)
{
}
static inline
void hif_system_pm_set_state_suspending(struct hif_opaque_softc *hif)
{
}
static inline
void hif_system_pm_set_state_suspended(struct hif_opaque_softc *hif)
{
}
static inline
int32_t hif_system_pm_get_state(struct hif_opaque_softc *hif)
{
return 0;
}
static inline int hif_system_pm_state_check(struct hif_opaque_softc *hif)
{
return 0;
}
#endif
#endif /* _HIF_H_ */

View File

@@ -898,6 +898,7 @@ struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx,
qdf_atomic_init(&scn->active_grp_tasklet_cnt);
qdf_atomic_init(&scn->link_suspended);
qdf_atomic_init(&scn->tasklet_from_intr);
hif_system_pm_set_state_on(GET_HIF_OPAQUE_HDL(scn));
qdf_mem_copy(&scn->callbacks, cbk,
sizeof(struct hif_driver_state_callbacks));
scn->bus_type = bus_type;
@@ -2035,3 +2036,41 @@ void hif_set_ce_service_max_rx_ind_flush(struct hif_opaque_softc *hif,
hif_ctx->ce_service_max_rx_ind_flush =
ce_service_max_rx_ind_flush;
}
#ifdef SYSTEM_PM_CHECK
void __hif_system_pm_set_state(struct hif_opaque_softc *hif,
enum hif_system_pm_state state)
{
struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif);
qdf_atomic_set(&hif_ctx->sys_pm_state, state);
}
int32_t hif_system_pm_get_state(struct hif_opaque_softc *hif)
{
struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif);
return qdf_atomic_read(&hif_ctx->sys_pm_state);
}
int hif_system_pm_state_check(struct hif_opaque_softc *hif)
{
struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif);
int32_t sys_pm_state;
if (!hif_ctx) {
hif_err("hif context is null");
return -EFAULT;
}
sys_pm_state = qdf_atomic_read(&hif_ctx->sys_pm_state);
if (sys_pm_state == HIF_SYSTEM_PM_STATE_BUS_SUSPENDING ||
sys_pm_state == HIF_SYSTEM_PM_STATE_BUS_SUSPENDED) {
hif_info("Triggering system wakeup");
qdf_pm_system_wakeup();
return -EAGAIN;
}
return 0;
}
#endif

View File

@@ -292,6 +292,9 @@ struct hif_softc {
#ifdef HIF_DETECTION_LATENCY_ENABLE
struct hif_latency_detect latency_detect;
#endif
#ifdef SYSTEM_PM_CHECK
qdf_atomic_t sys_pm_state;
#endif
};
static inline

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2014, 2016-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2013-2014, 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
@@ -860,4 +860,19 @@ void htc_print_credit_history(HTC_HANDLE htc, uint32_t count,
print(print_priv, "HTC Credit History Feature is disabled");
}
#endif
#ifdef SYSTEM_PM_CHECK
/**
* htc_system_resume() - Send out any pending WMI/HTT
* messages pending in htc queues on system resume.
* @htc: HTC handle
*
* Return: None
*/
void htc_system_resume(HTC_HANDLE htc);
#else
static inline void htc_system_resume(HTC_HANDLE htc)
{
}
#endif
#endif /* _HTC_API_H_ */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2014, 2016-2017, 2019-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2013-2014, 2016-2017, 2019-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
@@ -79,6 +79,9 @@ struct htc_tx_packet_info {
/*Tag packet for runtime put in response or cleanup */
#define HTC_TX_PACKET_TAG_RTPM_PUT_RC (HTC_TX_PACKET_TAG_USER_DEFINED + 4)
#define HTC_TX_PACKET_SYSTEM_SUSPEND (HTC_TX_PACKET_TAG_USER_DEFINED + 5)
#define HTC_TX_PACKET_SYSTEM_RESUME (HTC_TX_PACKET_TAG_USER_DEFINED + 6)
#define HTC_TX_PACKET_FLAG_FIXUP_NETBUF (1 << 0)
#define HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA (1 << 1)

View File

@@ -736,6 +736,7 @@ static QDF_STATUS htc_issue_packets(HTC_TARGET *target,
int (*update_ep_padding_credit)(void *, int);
void *ctx = NULL;
bool rt_put_in_resp;
int32_t sys_state = HIF_SYSTEM_PM_STATE_ON;
update_ep_padding_credit =
pEndpoint->EpCallBacks.ep_padding_credit_update;
@@ -851,6 +852,11 @@ static QDF_STATUS htc_issue_packets(HTC_TARGET *target,
pEndpoint->UL_PipeID, false);
}
if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_SYSTEM_SUSPEND) {
sys_state = hif_system_pm_get_state(target->hif_dev);
hif_system_pm_set_state_suspending(target->hif_dev);
}
htc_packet_set_magic_cookie(pPacket, HTC_PACKET_MAGIC_COOKIE);
/*
* For HTT messages without a response from fw,
@@ -885,6 +891,12 @@ static QDF_STATUS htc_issue_packets(HTC_TARGET *target,
if (status != QDF_STATUS_SUCCESS) {
if (rt_put_in_resp)
htc_dec_return_runtime_cnt((void *)target);
if (pPacket->PktInfo.AsTx.Tag ==
HTC_TX_PACKET_SYSTEM_SUSPEND)
__hif_system_pm_set_state(target->hif_dev,
sys_state);
if (pEndpoint->EpCallBacks.ep_padding_credit_update) {
if (used_extra_tx_credit) {
ctx = pEndpoint->EpCallBacks.pContext;
@@ -1057,6 +1069,41 @@ htc_send_pkts_rtpm_dbgid_get(HTC_SERVICE_ID service_id)
return rtpm_dbgid;
}
#ifdef SYSTEM_PM_CHECK
/**
* extract_htc_system_resume_pkts(): Move system pm resume packets from endpoint
* into queue
* @endpoint: which enpoint to extract packets from
* @queue: a queue to store extracted packets in.
*
* Remove pm packets from the endpoint's tx queue and enqueue
* them into a queue
*/
static void extract_htc_system_resume_pkts(HTC_ENDPOINT *endpoint,
HTC_PACKET_QUEUE *queue)
{
HTC_PACKET *packet;
/* only WMI endpoint has power management packets */
if (endpoint->service_id != WMI_CONTROL_SVC)
return;
ITERATE_OVER_LIST_ALLOW_REMOVE(&endpoint->TxQueue.QueueHead, packet,
HTC_PACKET, ListLink) {
if (packet->PktInfo.AsTx.Tag == HTC_TX_PACKET_SYSTEM_RESUME) {
HTC_PACKET_REMOVE(&endpoint->TxQueue, packet);
HTC_PACKET_ENQUEUE(queue, packet);
}
} ITERATE_END
}
#else
static inline
void extract_htc_system_resume_pkts(HTC_ENDPOINT *endpoint,
HTC_PACKET_QUEUE *queue)
{
}
#endif
/**
* get_htc_send_packets_credit_based() - get packets based on available credits
* @target: HTC target on which packets need to be sent
@@ -1082,6 +1129,8 @@ static void get_htc_send_packets_credit_based(HTC_TARGET *target,
bool do_pm_get = false;
wlan_rtpm_dbgid rtpm_dbgid = 0;
int ret;
HTC_PACKET_QUEUE sys_pm_queue;
bool sys_pm_check = false;
/*** NOTE : the TX lock is held when this function is called ***/
AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
@@ -1090,8 +1139,16 @@ static void get_htc_send_packets_credit_based(HTC_TARGET *target,
INIT_HTC_PACKET_QUEUE(&pm_queue);
extract_htc_pm_packets(pEndpoint, &pm_queue);
if (HTC_QUEUE_EMPTY(&pm_queue)) {
tx_queue = &pEndpoint->TxQueue;
do_pm_get = true;
INIT_HTC_PACKET_QUEUE(&sys_pm_queue);
extract_htc_system_resume_pkts(pEndpoint, &sys_pm_queue);
if (HTC_QUEUE_EMPTY(&sys_pm_queue)) {
tx_queue = &pEndpoint->TxQueue;
sys_pm_check = true;
} else {
tx_queue = &sys_pm_queue;
}
} else {
tx_queue = &pm_queue;
}
@@ -1127,6 +1184,13 @@ static void get_htc_send_packets_credit_based(HTC_TARGET *target,
break;
}
if (sys_pm_check &&
hif_system_pm_state_check(target->hif_dev)) {
if (do_pm_get)
hif_pm_runtime_put(target->hif_dev, rtpm_dbgid);
break;
}
AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
(" Got head packet:%pK , Queue Depth: %d\n",
pPacket,
@@ -1275,6 +1339,11 @@ static void get_htc_send_packets(HTC_TARGET *target,
hif_pm_runtime_put(target->hif_dev, rtpm_dbgid);
break;
}
ret = hif_system_pm_state_check(target->hif_dev);
if (ret)
break;
AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
(" Got packet:%pK , New Queue Depth: %d\n",
pPacket,
@@ -2722,3 +2791,24 @@ struct ol_ath_htc_stats *ieee80211_ioctl_get_htc_stats(HTC_HANDLE HTCHandle)
return &(target->htc_pkt_stats);
}
#ifdef SYSTEM_PM_CHECK
void htc_system_resume(HTC_HANDLE htc)
{
HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc);
HTC_ENDPOINT *endpoint = NULL;
int i;
if (!target)
return;
for (i = 0; i < ENDPOINT_MAX; i++) {
endpoint = &target->endpoint[i];
if (endpoint->service_id == 0)
continue;
htc_try_send(target, endpoint, NULL);
}
}
#endif

View File

@@ -1942,14 +1942,54 @@ static inline void wmi_unified_debug_dump(wmi_unified_t wmi_handle)
"WMI_NON_TLV_TARGET"));
}
#ifdef SYSTEM_PM_CHECK
/**
* wmi_set_system_pm_pkt_tag() - API to set tag for system pm packets
* @htc_tag: HTC tag
* @buf: wmi cmd buffer
* @cmd_id: cmd id
*
* Return: None
*/
static void wmi_set_system_pm_pkt_tag(uint16_t *htc_tag, wmi_buf_t buf,
uint32_t cmd_id)
{
switch (cmd_id) {
case WMI_WOW_ENABLE_CMDID:
case WMI_PDEV_SUSPEND_CMDID:
*htc_tag = HTC_TX_PACKET_SYSTEM_SUSPEND;
break;
case WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID:
case WMI_PDEV_RESUME_CMDID:
*htc_tag = HTC_TX_PACKET_SYSTEM_RESUME;
break;
case WMI_D0_WOW_ENABLE_DISABLE_CMDID:
if (wmi_is_legacy_d0wow_disable_cmd(buf, cmd_id))
*htc_tag = HTC_TX_PACKET_SYSTEM_RESUME;
else
*htc_tag = HTC_TX_PACKET_SYSTEM_SUSPEND;
break;
default:
break;
}
}
#else
static inline void wmi_set_system_pm_pkt_tag(uint16_t *htc_tag, wmi_buf_t buf,
uint32_t cmd_id)
{
}
#endif
QDF_STATUS wmi_unified_cmd_send_fl(wmi_unified_t wmi_handle, wmi_buf_t buf,
uint32_t len, uint32_t cmd_id,
const char *func, uint32_t line)
{
HTC_PACKET *pkt;
uint16_t htc_tag = 0;
bool rtpm_inprogress;
if (wmi_get_runtime_pm_inprogress(wmi_handle)) {
rtpm_inprogress = wmi_get_runtime_pm_inprogress(wmi_handle);
if (rtpm_inprogress) {
htc_tag = wmi_handle->ops->wmi_set_htc_tx_tag(wmi_handle, buf,
cmd_id);
} else if (qdf_atomic_read(&wmi_handle->is_target_suspended) &&
@@ -2011,6 +2051,9 @@ QDF_STATUS wmi_unified_cmd_send_fl(wmi_unified_t wmi_handle, wmi_buf_t buf,
return QDF_STATUS_E_NOMEM;
}
if (!rtpm_inprogress)
wmi_set_system_pm_pkt_tag(&htc_tag, buf, cmd_id);
SET_HTC_PACKET_INFO_TX(pkt,
NULL,
qdf_nbuf_data(buf), len + sizeof(WMI_CMD_HDR),