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:

committed by
snandini

parent
125c4c2a60
commit
6611374cf4
130
hif/inc/hif.h
130
hif/inc/hif.h
@@ -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_ */
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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_ */
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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),
|
||||
|
Reference in New Issue
Block a user