Loading drivers/soc/qcom/peripheral-loader.c +5 −12 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ #include <linux/list_sort.h> #include <linux/idr.h> #include <linux/interrupt.h> #include <linux/of_gpio.h> #include <linux/of_irq.h> #include <linux/of_address.h> #include <linux/io.h> #include <linux/dma-mapping.h> Loading Loading @@ -739,25 +739,18 @@ static int pil_parse_devicetree(struct pil_desc *desc) desc->name); if (desc->ops->proxy_unvote && of_find_property(ofnode, "qcom,gpio-proxy-unvote", "qcom,proxy-unvote", NULL)) { clk_ready = of_get_named_gpio(ofnode, "qcom,gpio-proxy-unvote", 0); clk_ready = of_irq_get_byname(ofnode, "qcom,proxy-unvote"); if (clk_ready < 0) { dev_dbg(desc->dev, "[%s]: Error getting proxy unvoting gpio\n", "[%s]: Error getting proxy unvoting irq\n", desc->name); return clk_ready; } clk_ready = gpio_to_irq(clk_ready); if (clk_ready < 0) { dev_err(desc->dev, "[%s]: Error getting proxy unvote IRQ\n", desc->name); return clk_ready; } } desc->proxy_unvote_irq = clk_ready; return 0; Loading drivers/soc/qcom/subsys-pil-tz.c +37 −11 Original line number Diff line number Diff line Loading @@ -19,7 +19,6 @@ #include <linux/clk.h> #include <linux/regulator/consumer.h> #include <linux/interrupt.h> #include <linux/of_gpio.h> #include <linux/delay.h> #include <linux/msm-bus-board.h> Loading @@ -31,6 +30,7 @@ #include <soc/qcom/scm.h> #include <linux/soc/qcom/smem.h> #include <linux/soc/qcom/smem_state.h> #include "peripheral-loader.h" Loading Loading @@ -101,6 +101,7 @@ struct pil_tz_data { bool enable_bus_scaling; bool keep_proxy_regs_on; struct completion stop_ack; struct completion shutdown_ack; struct pil_desc desc; struct subsys_device *subsys; struct subsys_desc subsys_desc; Loading Loading @@ -796,8 +797,8 @@ static void log_failure_reason(const struct pil_tz_data *d) return; smem_reason = qcom_smem_get(QCOM_SMEM_HOST_ANY, d->smem_id, &size); if (!smem_reason || !size) { pr_err("%s SFR: (unknown, smem_get_entry_no_rlock failed).\n", if (IS_ERR(smem_reason) || !size) { pr_err("%s SFR: (unknown, qcom_smem_get failed).\n", name); return; } Loading @@ -819,14 +820,16 @@ static int subsys_shutdown(const struct subsys_desc *subsys, bool force_stop) int ret; if (!subsys_get_crash_status(d->subsys) && force_stop && subsys->force_stop_gpio) { gpio_set_value(subsys->force_stop_gpio, 1); subsys->state) { qcom_smem_state_update_bits(subsys->state, subsys->force_stop_bit, 1); ret = wait_for_completion_timeout(&d->stop_ack, msecs_to_jiffies(STOP_ACK_TIMEOUT_MS)); if (!ret) pr_warn("Timed out on stop ack from %s.\n", subsys->name); gpio_set_value(subsys->force_stop_gpio, 0); qcom_smem_state_update_bits(subsys->state, subsys->force_stop_bit, 0); } pil_shutdown(&d->desc); Loading Loading @@ -868,9 +871,9 @@ static void subsys_crash_shutdown(const struct subsys_desc *subsys) { struct pil_tz_data *d = subsys_to_data(subsys); if (subsys->force_stop_gpio > 0 && !subsys_get_crash_status(d->subsys)) { gpio_set_value(subsys->force_stop_gpio, 1); if (subsys->state && !subsys_get_crash_status(d->subsys)) { qcom_smem_state_update_bits(subsys->state, subsys->force_stop_bit, 1); mdelay(CRASH_STOP_ACK_TO_MS); } } Loading Loading @@ -900,8 +903,7 @@ static irqreturn_t subsys_wdog_bite_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; pr_err("Watchdog bite received from %s!\n", d->subsys_desc.name); if (d->subsys_desc.system_debug && !gpio_get_value(d->subsys_desc.err_fatal_gpio)) if (d->subsys_desc.system_debug) panic("%s: System ramdump requested. Triggering device restart!\n", __func__); subsys_set_crash_status(d->subsys, CRASH_STATUS_WDOG_BITE); Loading @@ -920,6 +922,26 @@ static irqreturn_t subsys_stop_ack_intr_handler(int irq, void *dev_id) return IRQ_HANDLED; } static irqreturn_t subsys_shutdown_ack_intr_handler(int irq, void *dev_id) { struct pil_tz_data *d = subsys_to_data(dev_id); pr_info("Received stop shutdown interrupt from %s\n", d->subsys_desc.name); complete_shutdown_ack(d->subsys); return IRQ_HANDLED; } static irqreturn_t subsys_ramdump_disable_intr_handler(int irq, void *dev_id) { struct pil_tz_data *d = subsys_to_data(dev_id); pr_info("Received ramdump disable interrupt from %s\n", d->subsys_desc.name); d->subsys_desc.ramdump_disable = 1; return IRQ_HANDLED; } static void clear_pbl_done(struct pil_tz_data *d) { uint32_t err_value; Loading Loading @@ -1104,6 +1126,10 @@ static int pil_tz_driver_probe(struct platform_device *pdev) subsys_err_fatal_intr_handler; d->subsys_desc.wdog_bite_handler = subsys_wdog_bite_irq_handler; d->subsys_desc.stop_ack_handler = subsys_stop_ack_intr_handler; d->subsys_desc.shutdown_ack_handler = subsys_shutdown_ack_intr_handler; d->subsys_desc.ramdump_disable_handler = subsys_ramdump_disable_intr_handler; } d->ramdump_dev = create_ramdump_device(d->subsys_desc.name, &pdev->dev); Loading drivers/soc/qcom/subsystem_restart.c +104 −65 Original line number Diff line number Diff line Loading @@ -29,14 +29,15 @@ #include <linux/device.h> #include <linux/idr.h> #include <linux/interrupt.h> #include <linux/of_gpio.h> #include <linux/cdev.h> #include <linux/platform_device.h> #include <soc/qcom/subsystem_restart.h> #include <soc/qcom/subsystem_notif.h> #include <soc/qcom/sysmon.h> #include <trace/events/trace_msm_pil_event.h> #include <linux/soc/qcom/smem_state.h> #include <linux/of_irq.h> #include <linux/of.h> #include <asm/current.h> #include "peripheral-loader.h" Loading Loading @@ -174,6 +175,7 @@ struct subsys_device { struct cdev char_dev; dev_t dev_no; struct completion err_ready; struct completion shutdown_ack; enum crash_status crashed; int notif_state; struct list_head list; Loading @@ -189,6 +191,11 @@ void complete_err_ready(struct subsys_device *subsys) complete(&subsys->err_ready); } void complete_shutdown_ack(struct subsys_device *subsys) { complete(&subsys->shutdown_ack); } static struct subsys_tracking *subsys_get_track(struct subsys_device *subsys) { struct subsys_soc_restart_order *order = subsys->restart_order; Loading Loading @@ -472,7 +479,7 @@ static void do_epoch_check(struct subsys_device *dev) static int is_ramdump_enabled(struct subsys_device *dev) { if (dev->desc->ramdump_disable_gpio) if (dev->desc->ramdump_disable_irq) return !dev->desc->ramdump_disable; return enable_ramdumps; Loading Loading @@ -563,6 +570,11 @@ static void enable_all_irqs(struct subsys_device *dev) enable_irq(dev->desc->err_fatal_irq); if (dev->desc->stop_ack_irq && dev->desc->stop_ack_handler) enable_irq(dev->desc->stop_ack_irq); if (dev->desc->shutdown_ack_irq && dev->desc->shutdown_ack_handler) enable_irq(dev->desc->shutdown_ack_irq); if (dev->desc->ramdump_disable_irq && dev->desc->ramdump_disable_handler) enable_irq(dev->desc->ramdump_disable_irq); if (dev->desc->generic_irq && dev->desc->generic_handler) { enable_irq(dev->desc->generic_irq); irq_set_irq_wake(dev->desc->generic_irq, 1); Loading @@ -581,6 +593,8 @@ static void disable_all_irqs(struct subsys_device *dev) disable_irq(dev->desc->err_fatal_irq); if (dev->desc->stop_ack_irq && dev->desc->stop_ack_handler) disable_irq(dev->desc->stop_ack_irq); if (dev->desc->shutdown_ack_irq && dev->desc->shutdown_ack_handler) disable_irq(dev->desc->shutdown_ack_irq); if (dev->desc->generic_irq && dev->desc->generic_handler) { disable_irq(dev->desc->generic_irq); irq_set_irq_wake(dev->desc->generic_irq, 0); Loading Loading @@ -756,6 +770,7 @@ static void subsys_stop(struct subsys_device *subsys) if (!of_property_read_bool(subsys->desc->dev->of_node, "qcom,pil-force-shutdown")) { subsys_set_state(subsys, SUBSYS_OFFLINING); init_completion(&subsys->shutdown_ack); subsys->desc->sysmon_shutdown_ret = sysmon_send_shutdown(subsys->desc); if (subsys->desc->sysmon_shutdown_ret) Loading Loading @@ -792,27 +807,25 @@ EXPORT_SYMBOL(subsystem_set_fwname); int wait_for_shutdown_ack(struct subsys_desc *desc) { int count; int ret; struct subsys_device *dev; if (!desc || !desc->shutdown_ack_gpio) if (!desc || !desc->shutdown_ack_irq) return 0; dev = find_subsys(desc->name); if (!dev) return 0; for (count = SHUTDOWN_ACK_MAX_LOOPS; count > 0; count--) { if (gpio_get_value(desc->shutdown_ack_gpio)) return count; else if (subsys_get_crash_status(dev)) break; msleep(SHUTDOWN_ACK_DELAY_MS); } pr_err("[%s]: Timed out waiting for shutdown ack\n", desc->name); ret = wait_for_completion_timeout(&dev->shutdown_ack, msecs_to_jiffies(10000)); if (!ret) { pr_err("[%s]: Timed out waiting for shutdown ack\n", desc->name); return -ETIMEDOUT; } return ret; } EXPORT_SYMBOL(wait_for_shutdown_ack); void *__subsystem_get(const char *name, const char *fw_name) Loading Loading @@ -1431,86 +1444,76 @@ static struct subsys_soc_restart_order *ssr_parse_restart_orders(struct return tmp; } static int __get_gpio(struct subsys_desc *desc, const char *prop, int *gpio) { struct device_node *dnode = desc->dev->of_node; int ret = -ENOENT; if (of_find_property(dnode, prop, NULL)) { *gpio = of_get_named_gpio(dnode, prop, 0); ret = *gpio < 0 ? *gpio : 0; } return ret; } static int __get_irq(struct subsys_desc *desc, const char *prop, unsigned int *irq, int *gpio) unsigned int *irq) { int ret, gpiol, irql; ret = __get_gpio(desc, prop, &gpiol); if (ret) return ret; irql = gpio_to_irq(gpiol); int irql = 0; struct device_node *dnode = desc->dev->of_node; if (irql == -ENOENT) irql = -ENXIO; if (of_property_match_string(dnode, "interrupt-names", prop) < 0) return -ENOENT; irql = of_irq_get_byname(dnode, prop); if (irql < 0) { pr_err("[%s]: Error getting IRQ \"%s\"\n", desc->name, prop); return irql; } if (gpio) *gpio = gpiol; *irq = irql; return 0; } static int __get_smem_state(struct subsys_desc *desc, const char *prop, int *smem_bit) { struct device_node *dnode = desc->dev->of_node; if (of_find_property(dnode, "qcom,smem-states", NULL)) { desc->state = qcom_smem_state_get(desc->dev, prop, smem_bit); if (IS_ERR_OR_NULL(desc->state)) { pr_err("Could not get smem-states %s\n", prop); return -ENXIO; } return 0; } return -ENOENT; } static int subsys_parse_devicetree(struct subsys_desc *desc) { struct subsys_soc_restart_order *order; int ret; struct platform_device *pdev = container_of(desc->dev, struct platform_device, dev); ret = __get_irq(desc, "qcom,gpio-err-fatal", &desc->err_fatal_irq, &desc->err_fatal_gpio); ret = __get_irq(desc, "qcom,err-fatal", &desc->err_fatal_irq); if (ret && ret != -ENOENT) return ret; ret = __get_irq(desc, "qcom,gpio-err-ready", &desc->err_ready_irq, NULL); ret = __get_irq(desc, "qcom,err-ready", &desc->err_ready_irq); if (ret && ret != -ENOENT) return ret; ret = __get_irq(desc, "qcom,gpio-stop-ack", &desc->stop_ack_irq, NULL); ret = __get_irq(desc, "qcom,stop-ack", &desc->stop_ack_irq); if (ret && ret != -ENOENT) return ret; ret = __get_gpio(desc, "qcom,gpio-force-stop", &desc->force_stop_gpio); ret = __get_irq(desc, "qcom,ramdump-disabled", &desc->ramdump_disable_irq); if (ret && ret != -ENOENT) return ret; ret = __get_gpio(desc, "qcom,gpio-ramdump-disable", &desc->ramdump_disable_gpio); ret = __get_irq(desc, "qcom,shutdown-ack", &desc->shutdown_ack_irq); if (ret && ret != -ENOENT) return ret; ret = __get_gpio(desc, "qcom,gpio-shutdown-ack", &desc->shutdown_ack_gpio); ret = __get_irq(desc, "qcom,wdog", &desc->wdog_bite_irq); if (ret && ret != -ENOENT) return ret; ret = platform_get_irq(pdev, 0); if (ret > 0) desc->wdog_bite_irq = ret; ret = __get_smem_state(desc, "qcom,force-stop", &desc->force_stop_bit); if (ret && ret != -ENOENT) return ret; if (of_property_read_bool(pdev->dev.of_node, "qcom,pil-generic-irq-handler")) { Loading Loading @@ -1538,23 +1541,25 @@ static int subsys_setup_irqs(struct subsys_device *subsys) int ret; if (desc->err_fatal_irq && desc->err_fatal_handler) { ret = devm_request_irq(desc->dev, desc->err_fatal_irq, ret = devm_request_threaded_irq(desc->dev, desc->err_fatal_irq, NULL, desc->err_fatal_handler, IRQF_TRIGGER_RISING, desc->name, desc); if (ret < 0) { dev_err(desc->dev, "[%s]: Unable to register error fatal IRQ handler!: %d\n", desc->name, ret); dev_err(desc->dev, "[%s]: Unable to register error fatal IRQ handler: %d, irq is %d\n", desc->name, ret, desc->err_fatal_irq); return ret; } disable_irq(desc->err_fatal_irq); } if (desc->stop_ack_irq && desc->stop_ack_handler) { ret = devm_request_irq(desc->dev, desc->stop_ack_irq, ret = devm_request_threaded_irq(desc->dev, desc->stop_ack_irq, NULL, desc->stop_ack_handler, IRQF_TRIGGER_RISING, desc->name, desc); if (ret < 0) { dev_err(desc->dev, "[%s]: Unable to register stop ack handler!: %d\n", dev_err(desc->dev, "[%s]: Unable to register stop ack handler: %d\n", desc->name, ret); return ret; } Loading @@ -1566,19 +1571,47 @@ static int subsys_setup_irqs(struct subsys_device *subsys) desc->wdog_bite_handler, IRQF_TRIGGER_RISING, desc->name, desc); if (ret < 0) { dev_err(desc->dev, "[%s]: Unable to register wdog bite handler!: %d\n", dev_err(desc->dev, "[%s]: Unable to register wdog bite handler: %d\n", desc->name, ret); return ret; } disable_irq(desc->wdog_bite_irq); } if (desc->shutdown_ack_irq && desc->shutdown_ack_handler) { ret = devm_request_threaded_irq(desc->dev, desc->shutdown_ack_irq, NULL, desc->shutdown_ack_handler, IRQF_TRIGGER_RISING, desc->name, desc); if (ret < 0) { dev_err(desc->dev, "[%s]: Unable to register shutdown ack handler: %d\n", desc->name, ret); return ret; } disable_irq(desc->shutdown_ack_irq); } if (desc->ramdump_disable_irq && desc->ramdump_disable_handler) { ret = devm_request_threaded_irq(desc->dev, desc->ramdump_disable_irq, NULL, desc->ramdump_disable_handler, IRQF_TRIGGER_RISING, desc->name, desc); if (ret < 0) { dev_err(desc->dev, "[%s]: Unable to register shutdown ack handler: %d\n", desc->name, ret); return ret; } disable_irq(desc->ramdump_disable_irq); } if (desc->generic_irq && desc->generic_handler) { ret = devm_request_irq(desc->dev, desc->generic_irq, desc->generic_handler, IRQF_TRIGGER_HIGH, desc->name, desc); if (ret < 0) { dev_err(desc->dev, "[%s]: Unable to register generic irq handler!: %d\n", dev_err(desc->dev, "[%s]: Unable to register generic irq handler: %d\n", desc->name, ret); return ret; } Loading @@ -1586,8 +1619,9 @@ static int subsys_setup_irqs(struct subsys_device *subsys) } if (desc->err_ready_irq) { ret = devm_request_irq(desc->dev, ret = devm_request_threaded_irq(desc->dev, desc->err_ready_irq, NULL, subsys_err_ready_intr_handler, IRQF_TRIGGER_RISING, "error_ready_interrupt", subsys); Loading @@ -1611,6 +1645,10 @@ static void subsys_free_irqs(struct subsys_device *subsys) devm_free_irq(desc->dev, desc->err_fatal_irq, desc); if (desc->stop_ack_irq && desc->stop_ack_handler) devm_free_irq(desc->dev, desc->stop_ack_irq, desc); if (desc->shutdown_ack_irq && desc->shutdown_ack_handler) devm_free_irq(desc->dev, desc->shutdown_ack_irq, desc); if (desc->ramdump_disable_irq && desc->ramdump_disable_handler) devm_free_irq(desc->dev, desc->ramdump_disable_irq, desc); if (desc->wdog_bite_irq && desc->wdog_bite_handler) devm_free_irq(desc->dev, desc->wdog_bite_irq, desc); if (desc->err_ready_irq) Loading @@ -1634,6 +1672,7 @@ struct subsys_device *subsys_register(struct subsys_desc *desc) subsys->dev.release = subsys_device_release; subsys->notif_state = -1; subsys->desc->sysmon_pid = -1; subsys->desc->state = NULL; strlcpy(subsys->desc->fw_name, desc->name, sizeof(subsys->desc->fw_name)); Loading include/soc/qcom/subsystem_restart.h +7 −3 Original line number Diff line number Diff line Loading @@ -74,6 +74,8 @@ struct subsys_desc { void (*free_memory)(const struct subsys_desc *desc); irqreturn_t (*err_fatal_handler)(int irq, void *dev_id); irqreturn_t (*stop_ack_handler)(int irq, void *dev_id); irqreturn_t (*shutdown_ack_handler)(int irq, void *dev_id); irqreturn_t (*ramdump_disable_handler)(int irq, void *dev_id); irqreturn_t (*wdog_bite_handler)(int irq, void *dev_id); irqreturn_t (*generic_handler)(int irq, void *dev_id); int is_not_loadable; Loading @@ -83,9 +85,9 @@ struct subsys_desc { unsigned int stop_ack_irq; unsigned int wdog_bite_irq; unsigned int generic_irq; int force_stop_gpio; int ramdump_disable_gpio; int shutdown_ack_gpio; int force_stop_bit; int ramdump_disable_irq; int shutdown_ack_irq; int ramdump_disable; bool no_auth; bool pil_mss_memsetup; Loading @@ -95,6 +97,7 @@ struct subsys_desc { bool system_debug; bool ignore_ssr_failure; const char *edge; struct qcom_smem_state *state; }; /** Loading Loading @@ -136,6 +139,7 @@ extern enum crash_status subsys_get_crash_status(struct subsys_device *dev); void notify_proxy_vote(struct device *device); void notify_proxy_unvote(struct device *device); void complete_err_ready(struct subsys_device *subsys); void complete_shutdown_ack(struct subsys_device *subsys); extern int wait_for_shutdown_ack(struct subsys_desc *desc); #else Loading Loading
drivers/soc/qcom/peripheral-loader.c +5 −12 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ #include <linux/list_sort.h> #include <linux/idr.h> #include <linux/interrupt.h> #include <linux/of_gpio.h> #include <linux/of_irq.h> #include <linux/of_address.h> #include <linux/io.h> #include <linux/dma-mapping.h> Loading Loading @@ -739,25 +739,18 @@ static int pil_parse_devicetree(struct pil_desc *desc) desc->name); if (desc->ops->proxy_unvote && of_find_property(ofnode, "qcom,gpio-proxy-unvote", "qcom,proxy-unvote", NULL)) { clk_ready = of_get_named_gpio(ofnode, "qcom,gpio-proxy-unvote", 0); clk_ready = of_irq_get_byname(ofnode, "qcom,proxy-unvote"); if (clk_ready < 0) { dev_dbg(desc->dev, "[%s]: Error getting proxy unvoting gpio\n", "[%s]: Error getting proxy unvoting irq\n", desc->name); return clk_ready; } clk_ready = gpio_to_irq(clk_ready); if (clk_ready < 0) { dev_err(desc->dev, "[%s]: Error getting proxy unvote IRQ\n", desc->name); return clk_ready; } } desc->proxy_unvote_irq = clk_ready; return 0; Loading
drivers/soc/qcom/subsys-pil-tz.c +37 −11 Original line number Diff line number Diff line Loading @@ -19,7 +19,6 @@ #include <linux/clk.h> #include <linux/regulator/consumer.h> #include <linux/interrupt.h> #include <linux/of_gpio.h> #include <linux/delay.h> #include <linux/msm-bus-board.h> Loading @@ -31,6 +30,7 @@ #include <soc/qcom/scm.h> #include <linux/soc/qcom/smem.h> #include <linux/soc/qcom/smem_state.h> #include "peripheral-loader.h" Loading Loading @@ -101,6 +101,7 @@ struct pil_tz_data { bool enable_bus_scaling; bool keep_proxy_regs_on; struct completion stop_ack; struct completion shutdown_ack; struct pil_desc desc; struct subsys_device *subsys; struct subsys_desc subsys_desc; Loading Loading @@ -796,8 +797,8 @@ static void log_failure_reason(const struct pil_tz_data *d) return; smem_reason = qcom_smem_get(QCOM_SMEM_HOST_ANY, d->smem_id, &size); if (!smem_reason || !size) { pr_err("%s SFR: (unknown, smem_get_entry_no_rlock failed).\n", if (IS_ERR(smem_reason) || !size) { pr_err("%s SFR: (unknown, qcom_smem_get failed).\n", name); return; } Loading @@ -819,14 +820,16 @@ static int subsys_shutdown(const struct subsys_desc *subsys, bool force_stop) int ret; if (!subsys_get_crash_status(d->subsys) && force_stop && subsys->force_stop_gpio) { gpio_set_value(subsys->force_stop_gpio, 1); subsys->state) { qcom_smem_state_update_bits(subsys->state, subsys->force_stop_bit, 1); ret = wait_for_completion_timeout(&d->stop_ack, msecs_to_jiffies(STOP_ACK_TIMEOUT_MS)); if (!ret) pr_warn("Timed out on stop ack from %s.\n", subsys->name); gpio_set_value(subsys->force_stop_gpio, 0); qcom_smem_state_update_bits(subsys->state, subsys->force_stop_bit, 0); } pil_shutdown(&d->desc); Loading Loading @@ -868,9 +871,9 @@ static void subsys_crash_shutdown(const struct subsys_desc *subsys) { struct pil_tz_data *d = subsys_to_data(subsys); if (subsys->force_stop_gpio > 0 && !subsys_get_crash_status(d->subsys)) { gpio_set_value(subsys->force_stop_gpio, 1); if (subsys->state && !subsys_get_crash_status(d->subsys)) { qcom_smem_state_update_bits(subsys->state, subsys->force_stop_bit, 1); mdelay(CRASH_STOP_ACK_TO_MS); } } Loading Loading @@ -900,8 +903,7 @@ static irqreturn_t subsys_wdog_bite_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; pr_err("Watchdog bite received from %s!\n", d->subsys_desc.name); if (d->subsys_desc.system_debug && !gpio_get_value(d->subsys_desc.err_fatal_gpio)) if (d->subsys_desc.system_debug) panic("%s: System ramdump requested. Triggering device restart!\n", __func__); subsys_set_crash_status(d->subsys, CRASH_STATUS_WDOG_BITE); Loading @@ -920,6 +922,26 @@ static irqreturn_t subsys_stop_ack_intr_handler(int irq, void *dev_id) return IRQ_HANDLED; } static irqreturn_t subsys_shutdown_ack_intr_handler(int irq, void *dev_id) { struct pil_tz_data *d = subsys_to_data(dev_id); pr_info("Received stop shutdown interrupt from %s\n", d->subsys_desc.name); complete_shutdown_ack(d->subsys); return IRQ_HANDLED; } static irqreturn_t subsys_ramdump_disable_intr_handler(int irq, void *dev_id) { struct pil_tz_data *d = subsys_to_data(dev_id); pr_info("Received ramdump disable interrupt from %s\n", d->subsys_desc.name); d->subsys_desc.ramdump_disable = 1; return IRQ_HANDLED; } static void clear_pbl_done(struct pil_tz_data *d) { uint32_t err_value; Loading Loading @@ -1104,6 +1126,10 @@ static int pil_tz_driver_probe(struct platform_device *pdev) subsys_err_fatal_intr_handler; d->subsys_desc.wdog_bite_handler = subsys_wdog_bite_irq_handler; d->subsys_desc.stop_ack_handler = subsys_stop_ack_intr_handler; d->subsys_desc.shutdown_ack_handler = subsys_shutdown_ack_intr_handler; d->subsys_desc.ramdump_disable_handler = subsys_ramdump_disable_intr_handler; } d->ramdump_dev = create_ramdump_device(d->subsys_desc.name, &pdev->dev); Loading
drivers/soc/qcom/subsystem_restart.c +104 −65 Original line number Diff line number Diff line Loading @@ -29,14 +29,15 @@ #include <linux/device.h> #include <linux/idr.h> #include <linux/interrupt.h> #include <linux/of_gpio.h> #include <linux/cdev.h> #include <linux/platform_device.h> #include <soc/qcom/subsystem_restart.h> #include <soc/qcom/subsystem_notif.h> #include <soc/qcom/sysmon.h> #include <trace/events/trace_msm_pil_event.h> #include <linux/soc/qcom/smem_state.h> #include <linux/of_irq.h> #include <linux/of.h> #include <asm/current.h> #include "peripheral-loader.h" Loading Loading @@ -174,6 +175,7 @@ struct subsys_device { struct cdev char_dev; dev_t dev_no; struct completion err_ready; struct completion shutdown_ack; enum crash_status crashed; int notif_state; struct list_head list; Loading @@ -189,6 +191,11 @@ void complete_err_ready(struct subsys_device *subsys) complete(&subsys->err_ready); } void complete_shutdown_ack(struct subsys_device *subsys) { complete(&subsys->shutdown_ack); } static struct subsys_tracking *subsys_get_track(struct subsys_device *subsys) { struct subsys_soc_restart_order *order = subsys->restart_order; Loading Loading @@ -472,7 +479,7 @@ static void do_epoch_check(struct subsys_device *dev) static int is_ramdump_enabled(struct subsys_device *dev) { if (dev->desc->ramdump_disable_gpio) if (dev->desc->ramdump_disable_irq) return !dev->desc->ramdump_disable; return enable_ramdumps; Loading Loading @@ -563,6 +570,11 @@ static void enable_all_irqs(struct subsys_device *dev) enable_irq(dev->desc->err_fatal_irq); if (dev->desc->stop_ack_irq && dev->desc->stop_ack_handler) enable_irq(dev->desc->stop_ack_irq); if (dev->desc->shutdown_ack_irq && dev->desc->shutdown_ack_handler) enable_irq(dev->desc->shutdown_ack_irq); if (dev->desc->ramdump_disable_irq && dev->desc->ramdump_disable_handler) enable_irq(dev->desc->ramdump_disable_irq); if (dev->desc->generic_irq && dev->desc->generic_handler) { enable_irq(dev->desc->generic_irq); irq_set_irq_wake(dev->desc->generic_irq, 1); Loading @@ -581,6 +593,8 @@ static void disable_all_irqs(struct subsys_device *dev) disable_irq(dev->desc->err_fatal_irq); if (dev->desc->stop_ack_irq && dev->desc->stop_ack_handler) disable_irq(dev->desc->stop_ack_irq); if (dev->desc->shutdown_ack_irq && dev->desc->shutdown_ack_handler) disable_irq(dev->desc->shutdown_ack_irq); if (dev->desc->generic_irq && dev->desc->generic_handler) { disable_irq(dev->desc->generic_irq); irq_set_irq_wake(dev->desc->generic_irq, 0); Loading Loading @@ -756,6 +770,7 @@ static void subsys_stop(struct subsys_device *subsys) if (!of_property_read_bool(subsys->desc->dev->of_node, "qcom,pil-force-shutdown")) { subsys_set_state(subsys, SUBSYS_OFFLINING); init_completion(&subsys->shutdown_ack); subsys->desc->sysmon_shutdown_ret = sysmon_send_shutdown(subsys->desc); if (subsys->desc->sysmon_shutdown_ret) Loading Loading @@ -792,27 +807,25 @@ EXPORT_SYMBOL(subsystem_set_fwname); int wait_for_shutdown_ack(struct subsys_desc *desc) { int count; int ret; struct subsys_device *dev; if (!desc || !desc->shutdown_ack_gpio) if (!desc || !desc->shutdown_ack_irq) return 0; dev = find_subsys(desc->name); if (!dev) return 0; for (count = SHUTDOWN_ACK_MAX_LOOPS; count > 0; count--) { if (gpio_get_value(desc->shutdown_ack_gpio)) return count; else if (subsys_get_crash_status(dev)) break; msleep(SHUTDOWN_ACK_DELAY_MS); } pr_err("[%s]: Timed out waiting for shutdown ack\n", desc->name); ret = wait_for_completion_timeout(&dev->shutdown_ack, msecs_to_jiffies(10000)); if (!ret) { pr_err("[%s]: Timed out waiting for shutdown ack\n", desc->name); return -ETIMEDOUT; } return ret; } EXPORT_SYMBOL(wait_for_shutdown_ack); void *__subsystem_get(const char *name, const char *fw_name) Loading Loading @@ -1431,86 +1444,76 @@ static struct subsys_soc_restart_order *ssr_parse_restart_orders(struct return tmp; } static int __get_gpio(struct subsys_desc *desc, const char *prop, int *gpio) { struct device_node *dnode = desc->dev->of_node; int ret = -ENOENT; if (of_find_property(dnode, prop, NULL)) { *gpio = of_get_named_gpio(dnode, prop, 0); ret = *gpio < 0 ? *gpio : 0; } return ret; } static int __get_irq(struct subsys_desc *desc, const char *prop, unsigned int *irq, int *gpio) unsigned int *irq) { int ret, gpiol, irql; ret = __get_gpio(desc, prop, &gpiol); if (ret) return ret; irql = gpio_to_irq(gpiol); int irql = 0; struct device_node *dnode = desc->dev->of_node; if (irql == -ENOENT) irql = -ENXIO; if (of_property_match_string(dnode, "interrupt-names", prop) < 0) return -ENOENT; irql = of_irq_get_byname(dnode, prop); if (irql < 0) { pr_err("[%s]: Error getting IRQ \"%s\"\n", desc->name, prop); return irql; } if (gpio) *gpio = gpiol; *irq = irql; return 0; } static int __get_smem_state(struct subsys_desc *desc, const char *prop, int *smem_bit) { struct device_node *dnode = desc->dev->of_node; if (of_find_property(dnode, "qcom,smem-states", NULL)) { desc->state = qcom_smem_state_get(desc->dev, prop, smem_bit); if (IS_ERR_OR_NULL(desc->state)) { pr_err("Could not get smem-states %s\n", prop); return -ENXIO; } return 0; } return -ENOENT; } static int subsys_parse_devicetree(struct subsys_desc *desc) { struct subsys_soc_restart_order *order; int ret; struct platform_device *pdev = container_of(desc->dev, struct platform_device, dev); ret = __get_irq(desc, "qcom,gpio-err-fatal", &desc->err_fatal_irq, &desc->err_fatal_gpio); ret = __get_irq(desc, "qcom,err-fatal", &desc->err_fatal_irq); if (ret && ret != -ENOENT) return ret; ret = __get_irq(desc, "qcom,gpio-err-ready", &desc->err_ready_irq, NULL); ret = __get_irq(desc, "qcom,err-ready", &desc->err_ready_irq); if (ret && ret != -ENOENT) return ret; ret = __get_irq(desc, "qcom,gpio-stop-ack", &desc->stop_ack_irq, NULL); ret = __get_irq(desc, "qcom,stop-ack", &desc->stop_ack_irq); if (ret && ret != -ENOENT) return ret; ret = __get_gpio(desc, "qcom,gpio-force-stop", &desc->force_stop_gpio); ret = __get_irq(desc, "qcom,ramdump-disabled", &desc->ramdump_disable_irq); if (ret && ret != -ENOENT) return ret; ret = __get_gpio(desc, "qcom,gpio-ramdump-disable", &desc->ramdump_disable_gpio); ret = __get_irq(desc, "qcom,shutdown-ack", &desc->shutdown_ack_irq); if (ret && ret != -ENOENT) return ret; ret = __get_gpio(desc, "qcom,gpio-shutdown-ack", &desc->shutdown_ack_gpio); ret = __get_irq(desc, "qcom,wdog", &desc->wdog_bite_irq); if (ret && ret != -ENOENT) return ret; ret = platform_get_irq(pdev, 0); if (ret > 0) desc->wdog_bite_irq = ret; ret = __get_smem_state(desc, "qcom,force-stop", &desc->force_stop_bit); if (ret && ret != -ENOENT) return ret; if (of_property_read_bool(pdev->dev.of_node, "qcom,pil-generic-irq-handler")) { Loading Loading @@ -1538,23 +1541,25 @@ static int subsys_setup_irqs(struct subsys_device *subsys) int ret; if (desc->err_fatal_irq && desc->err_fatal_handler) { ret = devm_request_irq(desc->dev, desc->err_fatal_irq, ret = devm_request_threaded_irq(desc->dev, desc->err_fatal_irq, NULL, desc->err_fatal_handler, IRQF_TRIGGER_RISING, desc->name, desc); if (ret < 0) { dev_err(desc->dev, "[%s]: Unable to register error fatal IRQ handler!: %d\n", desc->name, ret); dev_err(desc->dev, "[%s]: Unable to register error fatal IRQ handler: %d, irq is %d\n", desc->name, ret, desc->err_fatal_irq); return ret; } disable_irq(desc->err_fatal_irq); } if (desc->stop_ack_irq && desc->stop_ack_handler) { ret = devm_request_irq(desc->dev, desc->stop_ack_irq, ret = devm_request_threaded_irq(desc->dev, desc->stop_ack_irq, NULL, desc->stop_ack_handler, IRQF_TRIGGER_RISING, desc->name, desc); if (ret < 0) { dev_err(desc->dev, "[%s]: Unable to register stop ack handler!: %d\n", dev_err(desc->dev, "[%s]: Unable to register stop ack handler: %d\n", desc->name, ret); return ret; } Loading @@ -1566,19 +1571,47 @@ static int subsys_setup_irqs(struct subsys_device *subsys) desc->wdog_bite_handler, IRQF_TRIGGER_RISING, desc->name, desc); if (ret < 0) { dev_err(desc->dev, "[%s]: Unable to register wdog bite handler!: %d\n", dev_err(desc->dev, "[%s]: Unable to register wdog bite handler: %d\n", desc->name, ret); return ret; } disable_irq(desc->wdog_bite_irq); } if (desc->shutdown_ack_irq && desc->shutdown_ack_handler) { ret = devm_request_threaded_irq(desc->dev, desc->shutdown_ack_irq, NULL, desc->shutdown_ack_handler, IRQF_TRIGGER_RISING, desc->name, desc); if (ret < 0) { dev_err(desc->dev, "[%s]: Unable to register shutdown ack handler: %d\n", desc->name, ret); return ret; } disable_irq(desc->shutdown_ack_irq); } if (desc->ramdump_disable_irq && desc->ramdump_disable_handler) { ret = devm_request_threaded_irq(desc->dev, desc->ramdump_disable_irq, NULL, desc->ramdump_disable_handler, IRQF_TRIGGER_RISING, desc->name, desc); if (ret < 0) { dev_err(desc->dev, "[%s]: Unable to register shutdown ack handler: %d\n", desc->name, ret); return ret; } disable_irq(desc->ramdump_disable_irq); } if (desc->generic_irq && desc->generic_handler) { ret = devm_request_irq(desc->dev, desc->generic_irq, desc->generic_handler, IRQF_TRIGGER_HIGH, desc->name, desc); if (ret < 0) { dev_err(desc->dev, "[%s]: Unable to register generic irq handler!: %d\n", dev_err(desc->dev, "[%s]: Unable to register generic irq handler: %d\n", desc->name, ret); return ret; } Loading @@ -1586,8 +1619,9 @@ static int subsys_setup_irqs(struct subsys_device *subsys) } if (desc->err_ready_irq) { ret = devm_request_irq(desc->dev, ret = devm_request_threaded_irq(desc->dev, desc->err_ready_irq, NULL, subsys_err_ready_intr_handler, IRQF_TRIGGER_RISING, "error_ready_interrupt", subsys); Loading @@ -1611,6 +1645,10 @@ static void subsys_free_irqs(struct subsys_device *subsys) devm_free_irq(desc->dev, desc->err_fatal_irq, desc); if (desc->stop_ack_irq && desc->stop_ack_handler) devm_free_irq(desc->dev, desc->stop_ack_irq, desc); if (desc->shutdown_ack_irq && desc->shutdown_ack_handler) devm_free_irq(desc->dev, desc->shutdown_ack_irq, desc); if (desc->ramdump_disable_irq && desc->ramdump_disable_handler) devm_free_irq(desc->dev, desc->ramdump_disable_irq, desc); if (desc->wdog_bite_irq && desc->wdog_bite_handler) devm_free_irq(desc->dev, desc->wdog_bite_irq, desc); if (desc->err_ready_irq) Loading @@ -1634,6 +1672,7 @@ struct subsys_device *subsys_register(struct subsys_desc *desc) subsys->dev.release = subsys_device_release; subsys->notif_state = -1; subsys->desc->sysmon_pid = -1; subsys->desc->state = NULL; strlcpy(subsys->desc->fw_name, desc->name, sizeof(subsys->desc->fw_name)); Loading
include/soc/qcom/subsystem_restart.h +7 −3 Original line number Diff line number Diff line Loading @@ -74,6 +74,8 @@ struct subsys_desc { void (*free_memory)(const struct subsys_desc *desc); irqreturn_t (*err_fatal_handler)(int irq, void *dev_id); irqreturn_t (*stop_ack_handler)(int irq, void *dev_id); irqreturn_t (*shutdown_ack_handler)(int irq, void *dev_id); irqreturn_t (*ramdump_disable_handler)(int irq, void *dev_id); irqreturn_t (*wdog_bite_handler)(int irq, void *dev_id); irqreturn_t (*generic_handler)(int irq, void *dev_id); int is_not_loadable; Loading @@ -83,9 +85,9 @@ struct subsys_desc { unsigned int stop_ack_irq; unsigned int wdog_bite_irq; unsigned int generic_irq; int force_stop_gpio; int ramdump_disable_gpio; int shutdown_ack_gpio; int force_stop_bit; int ramdump_disable_irq; int shutdown_ack_irq; int ramdump_disable; bool no_auth; bool pil_mss_memsetup; Loading @@ -95,6 +97,7 @@ struct subsys_desc { bool system_debug; bool ignore_ssr_failure; const char *edge; struct qcom_smem_state *state; }; /** Loading Loading @@ -136,6 +139,7 @@ extern enum crash_status subsys_get_crash_status(struct subsys_device *dev); void notify_proxy_vote(struct device *device); void notify_proxy_unvote(struct device *device); void complete_err_ready(struct subsys_device *subsys); void complete_shutdown_ack(struct subsys_device *subsys); extern int wait_for_shutdown_ack(struct subsys_desc *desc); #else Loading