Loading drivers/soc/qcom/icnss.c +104 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,10 @@ static char *icnss_driver_event_to_str(enum icnss_driver_event_type type) return "PD_SERVICE_DOWN"; case ICNSS_DRIVER_EVENT_FW_EARLY_CRASH_IND: return "FW_EARLY_CRASH_IND"; case ICNSS_DRIVER_EVENT_IDLE_SHUTDOWN: return "IDLE_SHUTDOWN"; case ICNSS_DRIVER_EVENT_IDLE_RESTART: return "IDLE_RESTART"; case ICNSS_DRIVER_EVENT_MAX: return "EVENT_MAX"; } Loading Loading @@ -972,6 +976,7 @@ static int icnss_pd_restart_complete(struct icnss_priv *priv) icnss_call_driver_shutdown(priv); clear_bit(ICNSS_PDR, &priv->state); clear_bit(ICNSS_MODEM_CRASHED, &priv->state); clear_bit(ICNSS_REJUVENATE, &priv->state); clear_bit(ICNSS_PD_RESTART, &priv->state); priv->early_crash_ind = false; Loading Loading @@ -1228,6 +1233,51 @@ static int icnss_driver_event_early_crash_ind(struct icnss_priv *priv, return 0; } static int icnss_driver_event_idle_shutdown(void *data) { int ret = 0; if (!penv->ops || !penv->ops->idle_shutdown) return 0; if (test_bit(ICNSS_MODEM_CRASHED, &penv->state) || test_bit(ICNSS_PDR, &penv->state) || test_bit(ICNSS_REJUVENATE, &penv->state)) { icnss_pr_err("SSR/PDR is already in-progress during idle shutdown callback\n"); ret = -EBUSY; } else { icnss_pr_dbg("Calling driver idle shutdown, state: 0x%lx\n", penv->state); icnss_block_shutdown(true); ret = penv->ops->idle_shutdown(&penv->pdev->dev); icnss_block_shutdown(false); } return ret; } static int icnss_driver_event_idle_restart(void *data) { int ret = 0; if (!penv->ops || !penv->ops->idle_restart) return 0; if (test_bit(ICNSS_MODEM_CRASHED, &penv->state) || test_bit(ICNSS_PDR, &penv->state) || test_bit(ICNSS_REJUVENATE, &penv->state)) { icnss_pr_err("SSR/PDR is already in-progress during idle restart callback\n"); ret = -EBUSY; } else { icnss_pr_dbg("Calling driver idle restart, state: 0x%lx\n", penv->state); icnss_block_shutdown(true); ret = penv->ops->idle_restart(&penv->pdev->dev); icnss_block_shutdown(false); } return ret; } static void icnss_driver_event_work(struct work_struct *work) { Loading Loading @@ -1274,6 +1324,12 @@ static void icnss_driver_event_work(struct work_struct *work) ret = icnss_driver_event_early_crash_ind(penv, event->data); break; case ICNSS_DRIVER_EVENT_IDLE_SHUTDOWN: ret = icnss_driver_event_idle_shutdown(event->data); break; case ICNSS_DRIVER_EVENT_IDLE_RESTART: ret = icnss_driver_event_idle_restart(event->data); break; default: icnss_pr_err("Invalid Event type: %d", event->type); kfree(event); Loading Loading @@ -1339,6 +1395,9 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, priv->is_ssr = true; if (notif->crashed) set_bit(ICNSS_MODEM_CRASHED, &priv->state); if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed && atomic_read(&priv->is_shutdown)) { atomic_set(&priv->is_shutdown, false); Loading Loading @@ -2172,6 +2231,48 @@ int icnss_trigger_recovery(struct device *dev) } EXPORT_SYMBOL(icnss_trigger_recovery); int icnss_idle_shutdown(struct device *dev) { struct icnss_priv *priv = dev_get_drvdata(dev); if (!priv) { icnss_pr_err("Invalid drvdata: dev %pK", dev); return -EINVAL; } if (test_bit(ICNSS_MODEM_CRASHED, &priv->state) || test_bit(ICNSS_PDR, &priv->state) || test_bit(ICNSS_REJUVENATE, &penv->state)) { icnss_pr_err("SSR/PDR is already in-progress during idle shutdown\n"); return -EBUSY; } return icnss_driver_event_post(ICNSS_DRIVER_EVENT_IDLE_SHUTDOWN, ICNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL); } EXPORT_SYMBOL(icnss_idle_shutdown); int icnss_idle_restart(struct device *dev) { struct icnss_priv *priv = dev_get_drvdata(dev); if (!priv) { icnss_pr_err("Invalid drvdata: dev %pK", dev); return -EINVAL; } if (test_bit(ICNSS_MODEM_CRASHED, &priv->state) || test_bit(ICNSS_PDR, &priv->state) || test_bit(ICNSS_REJUVENATE, &penv->state)) { icnss_pr_err("SSR/PDR is already in-progress during idle restart\n"); return -EBUSY; } return icnss_driver_event_post(ICNSS_DRIVER_EVENT_IDLE_RESTART, ICNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL); } EXPORT_SYMBOL(icnss_idle_restart); static int icnss_get_vreg_info(struct device *dev, struct icnss_vreg_info *vreg_info) { Loading Loading @@ -2574,6 +2675,9 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv) continue; case ICNSS_PDR: seq_puts(s, "PDR TRIGGERED"); continue; case ICNSS_MODEM_CRASHED: seq_puts(s, "MODEM CRASHED"); } seq_printf(s, "UNKNOWN-%d", i); Loading drivers/soc/qcom/icnss_private.h +3 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,8 @@ enum icnss_driver_event_type { ICNSS_DRIVER_EVENT_UNREGISTER_DRIVER, ICNSS_DRIVER_EVENT_PD_SERVICE_DOWN, ICNSS_DRIVER_EVENT_FW_EARLY_CRASH_IND, ICNSS_DRIVER_EVENT_IDLE_SHUTDOWN, ICNSS_DRIVER_EVENT_IDLE_RESTART, ICNSS_DRIVER_EVENT_MAX, }; Loading Loading @@ -155,6 +157,7 @@ enum icnss_driver_state { ICNSS_MODE_ON, ICNSS_BLOCK_SHUTDOWN, ICNSS_PDR, ICNSS_MODEM_CRASHED, }; struct ce_irq_list { Loading include/soc/qcom/icnss.h +4 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ struct icnss_driver_ops { int (*suspend_noirq)(struct device *dev); int (*resume_noirq)(struct device *dev); int (*uevent)(struct device *dev, struct icnss_uevent_data *uevent); int (*idle_shutdown)(struct device *dev); int (*idle_restart)(struct device *dev); }; Loading Loading @@ -140,4 +142,6 @@ extern bool icnss_is_rejuvenate(void); extern int icnss_trigger_recovery(struct device *dev); extern void icnss_block_shutdown(bool status); extern bool icnss_is_pdr(void); extern int icnss_idle_restart(struct device *dev); extern int icnss_idle_shutdown(struct device *dev); #endif /* _ICNSS_WLAN_H_ */ Loading
drivers/soc/qcom/icnss.c +104 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,10 @@ static char *icnss_driver_event_to_str(enum icnss_driver_event_type type) return "PD_SERVICE_DOWN"; case ICNSS_DRIVER_EVENT_FW_EARLY_CRASH_IND: return "FW_EARLY_CRASH_IND"; case ICNSS_DRIVER_EVENT_IDLE_SHUTDOWN: return "IDLE_SHUTDOWN"; case ICNSS_DRIVER_EVENT_IDLE_RESTART: return "IDLE_RESTART"; case ICNSS_DRIVER_EVENT_MAX: return "EVENT_MAX"; } Loading Loading @@ -972,6 +976,7 @@ static int icnss_pd_restart_complete(struct icnss_priv *priv) icnss_call_driver_shutdown(priv); clear_bit(ICNSS_PDR, &priv->state); clear_bit(ICNSS_MODEM_CRASHED, &priv->state); clear_bit(ICNSS_REJUVENATE, &priv->state); clear_bit(ICNSS_PD_RESTART, &priv->state); priv->early_crash_ind = false; Loading Loading @@ -1228,6 +1233,51 @@ static int icnss_driver_event_early_crash_ind(struct icnss_priv *priv, return 0; } static int icnss_driver_event_idle_shutdown(void *data) { int ret = 0; if (!penv->ops || !penv->ops->idle_shutdown) return 0; if (test_bit(ICNSS_MODEM_CRASHED, &penv->state) || test_bit(ICNSS_PDR, &penv->state) || test_bit(ICNSS_REJUVENATE, &penv->state)) { icnss_pr_err("SSR/PDR is already in-progress during idle shutdown callback\n"); ret = -EBUSY; } else { icnss_pr_dbg("Calling driver idle shutdown, state: 0x%lx\n", penv->state); icnss_block_shutdown(true); ret = penv->ops->idle_shutdown(&penv->pdev->dev); icnss_block_shutdown(false); } return ret; } static int icnss_driver_event_idle_restart(void *data) { int ret = 0; if (!penv->ops || !penv->ops->idle_restart) return 0; if (test_bit(ICNSS_MODEM_CRASHED, &penv->state) || test_bit(ICNSS_PDR, &penv->state) || test_bit(ICNSS_REJUVENATE, &penv->state)) { icnss_pr_err("SSR/PDR is already in-progress during idle restart callback\n"); ret = -EBUSY; } else { icnss_pr_dbg("Calling driver idle restart, state: 0x%lx\n", penv->state); icnss_block_shutdown(true); ret = penv->ops->idle_restart(&penv->pdev->dev); icnss_block_shutdown(false); } return ret; } static void icnss_driver_event_work(struct work_struct *work) { Loading Loading @@ -1274,6 +1324,12 @@ static void icnss_driver_event_work(struct work_struct *work) ret = icnss_driver_event_early_crash_ind(penv, event->data); break; case ICNSS_DRIVER_EVENT_IDLE_SHUTDOWN: ret = icnss_driver_event_idle_shutdown(event->data); break; case ICNSS_DRIVER_EVENT_IDLE_RESTART: ret = icnss_driver_event_idle_restart(event->data); break; default: icnss_pr_err("Invalid Event type: %d", event->type); kfree(event); Loading Loading @@ -1339,6 +1395,9 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, priv->is_ssr = true; if (notif->crashed) set_bit(ICNSS_MODEM_CRASHED, &priv->state); if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed && atomic_read(&priv->is_shutdown)) { atomic_set(&priv->is_shutdown, false); Loading Loading @@ -2172,6 +2231,48 @@ int icnss_trigger_recovery(struct device *dev) } EXPORT_SYMBOL(icnss_trigger_recovery); int icnss_idle_shutdown(struct device *dev) { struct icnss_priv *priv = dev_get_drvdata(dev); if (!priv) { icnss_pr_err("Invalid drvdata: dev %pK", dev); return -EINVAL; } if (test_bit(ICNSS_MODEM_CRASHED, &priv->state) || test_bit(ICNSS_PDR, &priv->state) || test_bit(ICNSS_REJUVENATE, &penv->state)) { icnss_pr_err("SSR/PDR is already in-progress during idle shutdown\n"); return -EBUSY; } return icnss_driver_event_post(ICNSS_DRIVER_EVENT_IDLE_SHUTDOWN, ICNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL); } EXPORT_SYMBOL(icnss_idle_shutdown); int icnss_idle_restart(struct device *dev) { struct icnss_priv *priv = dev_get_drvdata(dev); if (!priv) { icnss_pr_err("Invalid drvdata: dev %pK", dev); return -EINVAL; } if (test_bit(ICNSS_MODEM_CRASHED, &priv->state) || test_bit(ICNSS_PDR, &priv->state) || test_bit(ICNSS_REJUVENATE, &penv->state)) { icnss_pr_err("SSR/PDR is already in-progress during idle restart\n"); return -EBUSY; } return icnss_driver_event_post(ICNSS_DRIVER_EVENT_IDLE_RESTART, ICNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL); } EXPORT_SYMBOL(icnss_idle_restart); static int icnss_get_vreg_info(struct device *dev, struct icnss_vreg_info *vreg_info) { Loading Loading @@ -2574,6 +2675,9 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv) continue; case ICNSS_PDR: seq_puts(s, "PDR TRIGGERED"); continue; case ICNSS_MODEM_CRASHED: seq_puts(s, "MODEM CRASHED"); } seq_printf(s, "UNKNOWN-%d", i); Loading
drivers/soc/qcom/icnss_private.h +3 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,8 @@ enum icnss_driver_event_type { ICNSS_DRIVER_EVENT_UNREGISTER_DRIVER, ICNSS_DRIVER_EVENT_PD_SERVICE_DOWN, ICNSS_DRIVER_EVENT_FW_EARLY_CRASH_IND, ICNSS_DRIVER_EVENT_IDLE_SHUTDOWN, ICNSS_DRIVER_EVENT_IDLE_RESTART, ICNSS_DRIVER_EVENT_MAX, }; Loading Loading @@ -155,6 +157,7 @@ enum icnss_driver_state { ICNSS_MODE_ON, ICNSS_BLOCK_SHUTDOWN, ICNSS_PDR, ICNSS_MODEM_CRASHED, }; struct ce_irq_list { Loading
include/soc/qcom/icnss.h +4 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ struct icnss_driver_ops { int (*suspend_noirq)(struct device *dev); int (*resume_noirq)(struct device *dev); int (*uevent)(struct device *dev, struct icnss_uevent_data *uevent); int (*idle_shutdown)(struct device *dev); int (*idle_restart)(struct device *dev); }; Loading Loading @@ -140,4 +142,6 @@ extern bool icnss_is_rejuvenate(void); extern int icnss_trigger_recovery(struct device *dev); extern void icnss_block_shutdown(bool status); extern bool icnss_is_pdr(void); extern int icnss_idle_restart(struct device *dev); extern int icnss_idle_shutdown(struct device *dev); #endif /* _ICNSS_WLAN_H_ */