Loading drivers/soc/qcom/subsystem_restart.c +28 −0 Original line number Original line Diff line number Diff line Loading @@ -48,6 +48,10 @@ module_param(disable_restart_work, uint, S_IRUGO | S_IWUSR); static int enable_debug; static int enable_debug; module_param(enable_debug, int, S_IRUGO | S_IWUSR); module_param(enable_debug, int, S_IRUGO | S_IWUSR); /* The maximum shutdown timeout is the product of MAX_LOOPS and DELAY_MS. */ #define SHUTDOWN_ACK_MAX_LOOPS 100 #define SHUTDOWN_ACK_DELAY_MS 100 /** /** * enum p_subsys_state - state of a subsystem (private) * enum p_subsys_state - state of a subsystem (private) * @SUBSYS_NORMAL: subsystem is operating normally * @SUBSYS_NORMAL: subsystem is operating normally Loading Loading @@ -550,6 +554,25 @@ static void disable_all_irqs(struct subsys_device *dev) disable_irq(dev->desc->stop_ack_irq); disable_irq(dev->desc->stop_ack_irq); } } int wait_for_shutdown_ack(struct subsys_desc *desc) { int count; if (desc && !desc->shutdown_ack_gpio) return 0; for (count = SHUTDOWN_ACK_MAX_LOOPS; count > 0; count--) { if (gpio_get_value(desc->shutdown_ack_gpio)) return count; msleep(SHUTDOWN_ACK_DELAY_MS); } pr_err("[%s]: Timed out waiting for shutdown ack\n", desc->name); return -ETIMEDOUT; } EXPORT_SYMBOL(wait_for_shutdown_ack); static int wait_for_err_ready(struct subsys_device *subsys) static int wait_for_err_ready(struct subsys_device *subsys) { { int ret; int ret; Loading Loading @@ -1443,6 +1466,11 @@ static int subsys_parse_devicetree(struct subsys_desc *desc) if (ret && ret != -ENOENT) if (ret && ret != -ENOENT) return ret; return ret; ret = __get_gpio(desc, "qcom,gpio-shutdown-ack", &desc->shutdown_ack_gpio); if (ret && ret != -ENOENT) return ret; ret = platform_get_irq(pdev, 0); ret = platform_get_irq(pdev, 0); if (ret > 0) if (ret > 0) desc->wdog_bite_irq = ret; desc->wdog_bite_irq = ret; Loading drivers/soc/qcom/sysmon-qmi.c +12 −1 Original line number Original line Diff line number Diff line Loading @@ -416,7 +416,7 @@ int sysmon_send_shutdown(struct subsys_desc *dest_desc) struct sysmon_qmi_data *data = NULL, *temp; struct sysmon_qmi_data *data = NULL, *temp; const char *dest_ss = dest_desc->name; const char *dest_ss = dest_desc->name; char req = 0; char req = 0; int ret; int ret, shutdown_ack_ret; if (dest_ss == NULL) if (dest_ss == NULL) return -EINVAL; return -EINVAL; Loading Loading @@ -465,6 +465,17 @@ int sysmon_send_shutdown(struct subsys_desc *dest_desc) goto out; goto out; } } shutdown_ack_ret = wait_for_shutdown_ack(dest_desc); if (shutdown_ack_ret < 0) { pr_err("shutdown_ack SMP2P bit for %s not set\n", data->name); if (!&data->ind_recv.done) { pr_err("QMI shutdown indication not received\n"); ret = shutdown_ack_ret; } goto out; } else if (shutdown_ack_ret > 0) goto out; if (!wait_for_completion_timeout(&data->ind_recv, if (!wait_for_completion_timeout(&data->ind_recv, msecs_to_jiffies(SHUTDOWN_TIMEOUT))) { msecs_to_jiffies(SHUTDOWN_TIMEOUT))) { pr_err("Timed out waiting for shutdown indication from %s\n", pr_err("Timed out waiting for shutdown indication from %s\n", Loading include/soc/qcom/subsystem_restart.h +6 −0 Original line number Original line Diff line number Diff line Loading @@ -74,6 +74,7 @@ struct subsys_desc { unsigned int wdog_bite_irq; unsigned int wdog_bite_irq; int force_stop_gpio; int force_stop_gpio; int ramdump_disable_gpio; int ramdump_disable_gpio; int shutdown_ack_gpio; int ramdump_disable; int ramdump_disable; bool no_auth; bool no_auth; int ssctl_instance_id; int ssctl_instance_id; Loading Loading @@ -119,6 +120,7 @@ extern void subsys_set_crash_status(struct subsys_device *dev, bool crashed); extern bool subsys_get_crash_status(struct subsys_device *dev); extern bool subsys_get_crash_status(struct subsys_device *dev); void notify_proxy_vote(struct device *device); void notify_proxy_vote(struct device *device); void notify_proxy_unvote(struct device *device); void notify_proxy_unvote(struct device *device); extern int wait_for_shutdown_ack(struct subsys_desc *desc); #else #else static inline int subsys_get_restart_level(struct subsys_device *dev) static inline int subsys_get_restart_level(struct subsys_device *dev) Loading Loading @@ -170,6 +172,10 @@ static inline bool subsys_get_crash_status(struct subsys_device *dev) } } static inline void notify_proxy_vote(struct device *device) { } static inline void notify_proxy_vote(struct device *device) { } static inline void notify_proxy_unvote(struct device *device) { } static inline void notify_proxy_unvote(struct device *device) { } static inline int wait_for_shutdown_ack(struct subsys_desc *desc) { return -ENOSYS; } #endif /* CONFIG_MSM_SUBSYSTEM_RESTART */ #endif /* CONFIG_MSM_SUBSYSTEM_RESTART */ #endif #endif Loading
drivers/soc/qcom/subsystem_restart.c +28 −0 Original line number Original line Diff line number Diff line Loading @@ -48,6 +48,10 @@ module_param(disable_restart_work, uint, S_IRUGO | S_IWUSR); static int enable_debug; static int enable_debug; module_param(enable_debug, int, S_IRUGO | S_IWUSR); module_param(enable_debug, int, S_IRUGO | S_IWUSR); /* The maximum shutdown timeout is the product of MAX_LOOPS and DELAY_MS. */ #define SHUTDOWN_ACK_MAX_LOOPS 100 #define SHUTDOWN_ACK_DELAY_MS 100 /** /** * enum p_subsys_state - state of a subsystem (private) * enum p_subsys_state - state of a subsystem (private) * @SUBSYS_NORMAL: subsystem is operating normally * @SUBSYS_NORMAL: subsystem is operating normally Loading Loading @@ -550,6 +554,25 @@ static void disable_all_irqs(struct subsys_device *dev) disable_irq(dev->desc->stop_ack_irq); disable_irq(dev->desc->stop_ack_irq); } } int wait_for_shutdown_ack(struct subsys_desc *desc) { int count; if (desc && !desc->shutdown_ack_gpio) return 0; for (count = SHUTDOWN_ACK_MAX_LOOPS; count > 0; count--) { if (gpio_get_value(desc->shutdown_ack_gpio)) return count; msleep(SHUTDOWN_ACK_DELAY_MS); } pr_err("[%s]: Timed out waiting for shutdown ack\n", desc->name); return -ETIMEDOUT; } EXPORT_SYMBOL(wait_for_shutdown_ack); static int wait_for_err_ready(struct subsys_device *subsys) static int wait_for_err_ready(struct subsys_device *subsys) { { int ret; int ret; Loading Loading @@ -1443,6 +1466,11 @@ static int subsys_parse_devicetree(struct subsys_desc *desc) if (ret && ret != -ENOENT) if (ret && ret != -ENOENT) return ret; return ret; ret = __get_gpio(desc, "qcom,gpio-shutdown-ack", &desc->shutdown_ack_gpio); if (ret && ret != -ENOENT) return ret; ret = platform_get_irq(pdev, 0); ret = platform_get_irq(pdev, 0); if (ret > 0) if (ret > 0) desc->wdog_bite_irq = ret; desc->wdog_bite_irq = ret; Loading
drivers/soc/qcom/sysmon-qmi.c +12 −1 Original line number Original line Diff line number Diff line Loading @@ -416,7 +416,7 @@ int sysmon_send_shutdown(struct subsys_desc *dest_desc) struct sysmon_qmi_data *data = NULL, *temp; struct sysmon_qmi_data *data = NULL, *temp; const char *dest_ss = dest_desc->name; const char *dest_ss = dest_desc->name; char req = 0; char req = 0; int ret; int ret, shutdown_ack_ret; if (dest_ss == NULL) if (dest_ss == NULL) return -EINVAL; return -EINVAL; Loading Loading @@ -465,6 +465,17 @@ int sysmon_send_shutdown(struct subsys_desc *dest_desc) goto out; goto out; } } shutdown_ack_ret = wait_for_shutdown_ack(dest_desc); if (shutdown_ack_ret < 0) { pr_err("shutdown_ack SMP2P bit for %s not set\n", data->name); if (!&data->ind_recv.done) { pr_err("QMI shutdown indication not received\n"); ret = shutdown_ack_ret; } goto out; } else if (shutdown_ack_ret > 0) goto out; if (!wait_for_completion_timeout(&data->ind_recv, if (!wait_for_completion_timeout(&data->ind_recv, msecs_to_jiffies(SHUTDOWN_TIMEOUT))) { msecs_to_jiffies(SHUTDOWN_TIMEOUT))) { pr_err("Timed out waiting for shutdown indication from %s\n", pr_err("Timed out waiting for shutdown indication from %s\n", Loading
include/soc/qcom/subsystem_restart.h +6 −0 Original line number Original line Diff line number Diff line Loading @@ -74,6 +74,7 @@ struct subsys_desc { unsigned int wdog_bite_irq; unsigned int wdog_bite_irq; int force_stop_gpio; int force_stop_gpio; int ramdump_disable_gpio; int ramdump_disable_gpio; int shutdown_ack_gpio; int ramdump_disable; int ramdump_disable; bool no_auth; bool no_auth; int ssctl_instance_id; int ssctl_instance_id; Loading Loading @@ -119,6 +120,7 @@ extern void subsys_set_crash_status(struct subsys_device *dev, bool crashed); extern bool subsys_get_crash_status(struct subsys_device *dev); extern bool subsys_get_crash_status(struct subsys_device *dev); void notify_proxy_vote(struct device *device); void notify_proxy_vote(struct device *device); void notify_proxy_unvote(struct device *device); void notify_proxy_unvote(struct device *device); extern int wait_for_shutdown_ack(struct subsys_desc *desc); #else #else static inline int subsys_get_restart_level(struct subsys_device *dev) static inline int subsys_get_restart_level(struct subsys_device *dev) Loading Loading @@ -170,6 +172,10 @@ static inline bool subsys_get_crash_status(struct subsys_device *dev) } } static inline void notify_proxy_vote(struct device *device) { } static inline void notify_proxy_vote(struct device *device) { } static inline void notify_proxy_unvote(struct device *device) { } static inline void notify_proxy_unvote(struct device *device) { } static inline int wait_for_shutdown_ack(struct subsys_desc *desc) { return -ENOSYS; } #endif /* CONFIG_MSM_SUBSYSTEM_RESTART */ #endif /* CONFIG_MSM_SUBSYSTEM_RESTART */ #endif #endif