From 26e2742f2f7416549da3fe74952bff57cfd2c3d4 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Tue, 8 Nov 2022 16:17:34 +0530 Subject: [PATCH] icnss2: Add support for Hibernate low power mode Hibernate is a system wide power mode during which Modem would be brought down along with DDR and the RAM contents would be saved on the disk (suspend-to-Disk). Modem would be do graceful shutdown in Hibernate mode, so BEFORE_SUBSYS_DOWN notification will be received. Based on dtsi node "is_low_power", if BEFORE_SUBSYS_DOWN with notif->crashed bit not set is received, platform driver will trigger an idle shutdown and set low power mode. On AFTER_SUBSYS_DOWN notification, low power mode will be cleared if it was set and ramdump collection will happen only in case of crash. Change-Id: I7b618e7c23950e4055079cde237ed75d6861620f CRs-Fixed: 3394501 --- icnss2/main.c | 25 +++++++++++++++++++++++-- icnss2/main.h | 1 + 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/icnss2/main.c b/icnss2/main.c index a5ee81f0e2..d09b6df554 100644 --- a/icnss2/main.c +++ b/icnss2/main.c @@ -2171,10 +2171,25 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, switch (code) { case QCOM_SSR_BEFORE_SHUTDOWN: + if (!notif->crashed && + priv->low_power_support) { /* Hibernate */ + if (test_bit(ICNSS_MODE_ON, &priv->state)) + icnss_driver_event_post( + priv, ICNSS_DRIVER_EVENT_IDLE_SHUTDOWN, + ICNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL); + set_bit(ICNSS_LOW_POWER, &priv->state); + } break; case QCOM_SSR_AFTER_SHUTDOWN: - icnss_pr_info("Collecting msa0 segment dump\n"); - icnss_msa0_ramdump(priv); + /* Collect ramdump only when there was a crash. */ + if (notif->crashed) { + icnss_pr_info("Collecting msa0 segment dump\n"); + icnss_msa0_ramdump(priv); + } + + if (test_bit(ICNSS_LOW_POWER, &priv->state) && + priv->low_power_support) + clear_bit(ICNSS_LOW_POWER, &priv->state); goto out; default: goto out; @@ -4049,6 +4064,12 @@ static int icnss_resource_parse(struct icnss_priv *priv) } } + if (of_property_read_bool(pdev->dev.of_node, + "qcom,is_low_power")) { + priv->low_power_support = true; + icnss_pr_dbg("Deep Sleep/Hibernate mode supported\n"); + } + if (of_property_read_u32(pdev->dev.of_node, "qcom,rf_subtype", &priv->rf_subtype) == 0) { priv->is_rf_subtype_valid = true; diff --git a/icnss2/main.h b/icnss2/main.h index bd36ac98dd..d7b0c6f404 100644 --- a/icnss2/main.h +++ b/icnss2/main.h @@ -499,6 +499,7 @@ struct icnss_priv { struct workqueue_struct *soc_update_wq; unsigned long device_config; bool wpss_supported; + u8 low_power_support; bool is_rf_subtype_valid; u32 rf_subtype; u8 is_slate_rfa;