From 478749a365ed3e6beee7a7fc4fd7c166a477de32 Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Wed, 23 Sep 2020 12:27:31 +0530 Subject: [PATCH] qcacmn: Do RTPM put during cleanup when HTT ver resp is not received For HTT h2t message which has a response from FW, runtime get is done in HTC layer and the corresponding runtime_put is done as part of the HTT response processing. In a scenario where the HTT response is not received from FW or not processed by host, runtime_put is not done as part of cleanup and panic is triggered due to get/put imbalance. Fix is to do RTPM put as part of htc cleanup when the HTT response from FW is not received or processed. Change-Id: I17ccb7c3e2293c95f5f233d36c6ef38a75733cce CRs-Fixed: 2779113 --- dp/wifi3.0/dp_htt.c | 12 ++++++++++-- htc/htc.c | 27 +++++++++++++++++++++++++++ htc/htc_api.h | 14 ++++++++++++++ htc/htc_internal.h | 4 ++++ htc/htc_packet.h | 4 +++- htc/htc_send.c | 26 ++++++++++++++++++++++++++ 6 files changed, 84 insertions(+), 3 deletions(-) diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index f7368b173c..8f6bbc469e 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/dp/wifi3.0/dp_htt.c @@ -793,7 +793,7 @@ static int htt_h2t_ver_req_msg(struct htt_soc *soc) SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt, dp_htt_h2t_send_complete_free_netbuf, qdf_nbuf_data(msg), qdf_nbuf_len(msg), soc->htc_endpoint, - 1); /* tag - not relevant here */ + HTC_TX_PACKET_TAG_RTPM_PUT_RC); SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); status = DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_VERSION_REQ, @@ -4562,7 +4562,15 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) case HTT_T2H_MSG_TYPE_VERSION_CONF: { - htc_pm_runtime_put(soc->htc_soc); + /* + * HTC maintains runtime pm count for H2T messages that + * have a response msg from FW. This count ensures that + * in the case FW does not sent out the response or host + * did not process this indication runtime_put happens + * properly in the cleanup path. + */ + if (htc_dec_return_runtime_cnt(soc->htc_soc) >= 0) + htc_pm_runtime_put(soc->htc_soc); soc->tgt_ver.major = HTT_VER_CONF_MAJOR_GET(*msg_word); soc->tgt_ver.minor = HTT_VER_CONF_MINOR_GET(*msg_word); QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, diff --git a/htc/htc.c b/htc/htc.c index fd7f9f9fba..c1a3677ced 100644 --- a/htc/htc.c +++ b/htc/htc.c @@ -154,6 +154,9 @@ static void htc_cleanup(HTC_TARGET *target) HTC_PACKET_QUEUE *pkt_queue; qdf_nbuf_t netbuf; + while (htc_dec_return_runtime_cnt((void *)target) >= 0) + hif_pm_runtime_put(target->hif_dev, RTPM_ID_HTC); + if (target->hif_dev) { hif_detach_htc(target->hif_dev); hif_mask_interrupt_call(target->hif_dev); @@ -271,9 +274,32 @@ static void htc_runtime_pm_deinit(HTC_TARGET *target) qdf_destroy_work(0, &target->queue_kicker); } +int32_t htc_dec_return_runtime_cnt(HTC_HANDLE htc) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc); + + return qdf_atomic_dec_return(&target->htc_runtime_cnt); +} + +/** + * htc_init_runtime_cnt: Initialize htc runtime count + * @htc: HTC handle + * + * Return: None + */ +static inline +void htc_init_runtime_cnt(HTC_TARGET *target) +{ + qdf_atomic_init(&target->htc_runtime_cnt); +} #else static inline void htc_runtime_pm_init(HTC_TARGET *target) { } static inline void htc_runtime_pm_deinit(HTC_TARGET *target) { } + +static inline +void htc_init_runtime_cnt(HTC_TARGET *target) +{ +} #endif #if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) @@ -378,6 +404,7 @@ HTC_HANDLE htc_create(void *ol_sc, struct htc_init_info *pInfo, } while (false); htc_recv_init(target); + htc_init_runtime_cnt(target); HTC_TRACE("-htc_create: (0x%pK)", target); diff --git a/htc/htc_api.h b/htc/htc_api.h index b56ab819a3..322c1cc071 100644 --- a/htc/htc_api.h +++ b/htc/htc_api.h @@ -790,9 +790,23 @@ void htc_clear_bundle_stats(HTC_HANDLE HTCHandle); #ifdef FEATURE_RUNTIME_PM int htc_pm_runtime_get(HTC_HANDLE htc_handle); int htc_pm_runtime_put(HTC_HANDLE htc_handle); + +/** + * htc_dec_return_runtime_cnt: Decrement htc runtime count + * @htc: HTC handle + * + * Return: value of runtime count after decrement + */ +int32_t htc_dec_return_runtime_cnt(HTC_HANDLE htc); #else static inline int htc_pm_runtime_get(HTC_HANDLE htc_handle) { return 0; } static inline int htc_pm_runtime_put(HTC_HANDLE htc_handle) { return 0; } + +static inline +int32_t htc_dec_return_runtime_cnt(HTC_HANDLE htc) +{ + return -1; +} #endif /** diff --git a/htc/htc_internal.h b/htc/htc_internal.h index 28151a1f5c..1b60255925 100644 --- a/htc/htc_internal.h +++ b/htc/htc_internal.h @@ -260,6 +260,10 @@ typedef struct _HTC_TARGET { /* flag to enable packet send debug */ bool htc_pkt_dbg; +#ifdef FEATURE_RUNTIME_PM + /* Runtime count for H2T msg with response */ + qdf_atomic_t htc_runtime_cnt; +#endif } HTC_TARGET; diff --git a/htc/htc_packet.h b/htc/htc_packet.h index d07fa7deee..68551303cc 100644 --- a/htc/htc_packet.h +++ b/htc/htc_packet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, 2016-2017, 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2016-2017, 2019-2020 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 @@ -76,6 +76,8 @@ struct htc_tx_packet_info { /* Tag packet for runtime put after sending */ #define HTC_TX_PACKET_TAG_RUNTIME_PUT (HTC_TX_PACKET_TAG_USER_DEFINED + 3) +/*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_FLAG_FIXUP_NETBUF (1 << 0) #define HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA (1 << 1) diff --git a/htc/htc_send.c b/htc/htc_send.c index 4b6b479f4e..bbf078ef06 100644 --- a/htc/htc_send.c +++ b/htc/htc_send.c @@ -176,10 +176,27 @@ static void log_packet_info(HTC_TARGET *target, HTC_PACKET *pPacket) qdf_nbuf_push_head(netbuf, sizeof(HTC_FRAME_HDR)); } } + +/** + * htc_inc_runtime_cnt: Increment htc runtime count + * @target: handle of HTC context + * + * Return: None + */ +static inline +void htc_inc_runtime_cnt(HTC_TARGET *target) +{ + qdf_atomic_inc(&target->htc_runtime_cnt); +} #else static void log_packet_info(HTC_TARGET *target, HTC_PACKET *pPacket) { } + +static inline +void htc_inc_runtime_cnt(HTC_TARGET *target) +{ +} #endif void htc_send_complete_check_cleanup(void *context) @@ -716,6 +733,7 @@ static QDF_STATUS htc_issue_packets(HTC_TARGET *target, uint8_t *buf = NULL; int (*update_ep_padding_credit)(void *, int); void *ctx = NULL; + bool rt_put_in_resp; update_ep_padding_credit = pEndpoint->EpCallBacks.ep_padding_credit_update; @@ -726,6 +744,7 @@ static QDF_STATUS htc_issue_packets(HTC_TARGET *target, ("+htc_issue_packets: Queue: %pK, Pkts %d\n", pPktQueue, HTC_PACKET_QUEUE_DEPTH(pPktQueue))); while (true) { + rt_put_in_resp = false; if (HTC_TX_BUNDLE_ENABLED(target) && HTC_PACKET_QUEUE_DEPTH(pPktQueue) >= HTC_MIN_MSG_PER_BUNDLE) { @@ -837,6 +856,10 @@ static QDF_STATUS htc_issue_packets(HTC_TARGET *target, */ if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_RUNTIME_PUT) rt_put = true; + else if (pPacket->PktInfo.AsTx.Tag == + HTC_TX_PACKET_TAG_RTPM_PUT_RC) + rt_put_in_resp = true; + #if DEBUG_BUNDLE qdf_print(" Send single EP%d buffer size:0x%x, total:0x%x.", pEndpoint->Id, @@ -922,6 +945,9 @@ static QDF_STATUS htc_issue_packets(HTC_TARGET *target, RTPM_ID_HTC); rt_put = false; } + + if (rt_put_in_resp) + htc_inc_runtime_cnt(target); } if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {