diff --git a/arch/arm64/configs/vendor/pineapple_GKI.config b/arch/arm64/configs/vendor/pineapple_GKI.config index 7aff8f60b0a6..dd903e36c353 100644 --- a/arch/arm64/configs/vendor/pineapple_GKI.config +++ b/arch/arm64/configs/vendor/pineapple_GKI.config @@ -50,6 +50,7 @@ CONFIG_MSM_QMP=m CONFIG_NOP_USB_XCEIV=m CONFIG_NVMEM_SPMI_SDAM=m CONFIG_PCI_MSM=m +CONFIG_PDR_INDICATION_NOTIF_TIMEOUT=9000 CONFIG_PHY_QCOM_UFS=m CONFIG_PHY_QCOM_UFS_QRBTC_SDM845=m CONFIG_PINCTRL_MSM=m @@ -86,6 +87,7 @@ CONFIG_QCOM_MEM_BUF_DEV=m # CONFIG_QCOM_MINIDUMP is not set # CONFIG_QCOM_MSM_IPCC is not set CONFIG_QCOM_PANIC_ON_NOTIF_TIMEOUT=y +CONFIG_QCOM_PANIC_ON_PDR_NOTIF_TIMEOUT=y CONFIG_QCOM_PDC=m CONFIG_QCOM_PDR_HELPERS=m CONFIG_QCOM_PIL_INFO=m diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index c5c5ac2ebdba..80074ad79960 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -134,6 +134,24 @@ config QCOM_PDR_HELPERS crash/recover without disrupting the other PDs running on the same Q6 ADSP. +config QCOM_PANIC_ON_PDR_NOTIF_TIMEOUT + bool "Trigger kernel panic when PDR notification timeout expires" + help + This is a debug feature where a kernel panic is triggered when + pdr notification to the APPS client is taking too long. This scneario + can happen if the one of notifier gets stuck and due to which subsystem + did not get ack back from APPS in time and trigger timeout panic. + So, trigger a kernel panic in APPS if PDR notifications is taking + too long. + +config PDR_INDICATION_NOTIF_TIMEOUT + int "Pdr notifications timeout in ms" + default 3000 + help + The amount of time, in milliseconds, that should elapse between + the start and end of notifications, before a warning + is emitted. + config QCOM_QMI_HELPERS tristate depends on NET diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c index f06080f74884..0dfe2f3a9e23 100644 --- a/drivers/soc/qcom/pdr_interface.c +++ b/drivers/soc/qcom/pdr_interface.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -10,6 +11,9 @@ #include #include "pdr_internal.h" +#include "../../remoteproc/qcom_common.h" + +#define PDR_IND_NOTIF_TIMEOUT CONFIG_PDR_INDICATION_NOTIF_TIMEOUT struct pdr_service { char service_name[SERVREG_NAME_LENGTH + 1]; @@ -67,8 +71,12 @@ struct pdr_list_node { u16 transaction_id; struct pdr_service *pds; struct list_head node; + struct timer_list timer; }; +static const char * const ind_notif_timeout_msg = + "PDR: Indication notifier %s, state: 0x%x, trans-id: %d\n taking too long"; + static int pdr_locator_new_server(struct qmi_handle *qmi, struct qmi_service *svc) { @@ -270,19 +278,38 @@ static int pdr_send_indack_msg(struct pdr_handle *pdr, struct pdr_service *pds, return ret; } +static void ind_notif_timeout_handler(struct timer_list *t) +{ + struct pdr_list_node *ind = from_timer(ind, t, timer); + struct pdr_service *pds = ind->pds; + + if (IS_ENABLED(CONFIG_QCOM_PANIC_ON_PDR_NOTIF_TIMEOUT) && + system_state != SYSTEM_RESTART && + system_state != SYSTEM_POWER_OFF && + system_state != SYSTEM_HALT && + !qcom_device_shutdown_in_progress) + panic(ind_notif_timeout_msg, pds->service_path, pds->state, ind->transaction_id); + else + WARN(1, ind_notif_timeout_msg, pds->service_path, pds->state, ind->transaction_id); +} + static void pdr_indack_work(struct work_struct *work) { struct pdr_handle *pdr = container_of(work, struct pdr_handle, indack_work); struct pdr_list_node *ind, *tmp; struct pdr_service *pds; + unsigned long timeout; list_for_each_entry_safe(ind, tmp, &pdr->indack_list, node) { pds = ind->pds; mutex_lock(&pdr->status_lock); pds->state = ind->curr_state; + timeout = jiffies + msecs_to_jiffies(PDR_IND_NOTIF_TIMEOUT); + mod_timer(&ind->timer, timeout); pdr->status(pds->state, pds->service_path, pdr->priv); + del_timer_sync(&ind->timer); mutex_unlock(&pdr->status_lock); /* Ack the indication after clients release the PD resources */ @@ -338,6 +365,7 @@ static void pdr_indication_cb(struct qmi_handle *qmi, ind->curr_state = ind_msg->curr_state; ind->pds = pds; + timer_setup(&ind->timer, ind_notif_timeout_handler, 0); mutex_lock(&pdr->list_lock); list_add_tail(&ind->node, &pdr->indack_list); mutex_unlock(&pdr->list_lock);