Loading drivers/esoc/esoc-mdm-drv.c +70 −20 Original line number Diff line number Diff line Loading @@ -13,24 +13,11 @@ #include "mdm-dbg.h" /* Default number of powerup trial requests per session */ #define ESOC_DEF_PON_REQ 2 static unsigned int n_pon_tries = ESOC_DEF_PON_REQ; module_param(n_pon_tries, uint, 0644); MODULE_PARM_DESC(n_pon_tries, "Number of power-on retrials allowed upon boot failure"); enum esoc_boot_fail_action { BOOT_FAIL_ACTION_RETRY, BOOT_FAIL_ACTION_COLD_RESET, BOOT_FAIL_ACTION_SHUTDOWN, BOOT_FAIL_ACTION_PANIC, BOOT_FAIL_ACTION_NOP, }; #define ESOC_DEF_PON_REQ 3 #define ESOC_MAX_PON_TRIES 5 static unsigned int boot_fail_action = BOOT_FAIL_ACTION_NOP; module_param(boot_fail_action, uint, 0644); MODULE_PARM_DESC(boot_fail_action, "Actions: 0:Retry PON; 1:Cold reset; 2:Power-down; 3:APQ Panic; 4:No action"); #define BOOT_FAIL_ACTION_DEF BOOT_FAIL_ACTION_PANIC enum esoc_pon_state { PON_INIT, Loading Loading @@ -62,13 +49,59 @@ struct mdm_drv { struct work_struct ssr_work; struct notifier_block esoc_restart; struct mutex poff_lock; atomic_t boot_fail_action; atomic_t n_pon_tries; }; #define to_mdm_drv(d) container_of(d, struct mdm_drv, cmd_eng) #define S3_RESET_DELAY_MS 1000 static void esoc_client_link_power_off(struct esoc_clink *esoc_clink, unsigned int flags); static void esoc_client_link_mdm_crash(struct esoc_clink *esoc_clink); int esoc_set_boot_fail_action(struct esoc_clink *esoc_clink, u32 action) { struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink); if (action >= BOOT_FAIL_ACTION_LAST) { esoc_mdm_log("Unknown boot fail action requested: %u\n", action); return -EINVAL; } if (!mdm_drv) { esoc_mdm_log("esoc-mdm driver not present\n"); return -EAGAIN; } atomic_set(&mdm_drv->boot_fail_action, action); esoc_mdm_log("Boot fail action configured to %u\n", action); return 0; } int esoc_set_n_pon_tries(struct esoc_clink *esoc_clink, u32 n_tries) { struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink); if (n_tries > ESOC_MAX_PON_TRIES) { esoc_mdm_log( "Num PON tries requested (%u) is over the limit: %u\n", n_tries, ESOC_MAX_PON_TRIES); } if (!mdm_drv) { esoc_mdm_log("esoc-mdm driver not present\n"); return -EAGAIN; } atomic_set(&mdm_drv->n_pon_tries, n_tries); esoc_mdm_log("Num PON tries configured to %u\n", n_tries); return 0; } static int esoc_msm_restart_handler(struct notifier_block *nb, unsigned long action, void *data) { Loading Loading @@ -334,8 +367,15 @@ static void mdm_subsys_retry_powerup_cleanup(struct esoc_clink *esoc_clink, static int mdm_handle_boot_fail(struct esoc_clink *esoc_clink, u8 *pon_trial) { struct mdm_ctrl *mdm = get_esoc_clink_data(esoc_clink); struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink); if (*pon_trial == atomic_read(&mdm_drv->n_pon_tries)) { esoc_mdm_log("Reached max. number of boot trials\n"); atomic_set(&mdm_drv->boot_fail_action, BOOT_FAIL_ACTION_PANIC); } switch (boot_fail_action) { switch (atomic_read(&mdm_drv->boot_fail_action)) { case BOOT_FAIL_ACTION_RETRY: mdm_subsys_retry_powerup_cleanup(esoc_clink, 0); esoc_mdm_log("Request to retry a warm reset\n"); Loading @@ -353,6 +393,14 @@ static int mdm_handle_boot_fail(struct esoc_clink *esoc_clink, u8 *pon_trial) (*pon_trial)++; mdm_power_down(mdm); break; case BOOT_FAIL_ACTION_S3_RESET: mdm_subsys_retry_powerup_cleanup(esoc_clink, ESOC_HOOK_MDM_DOWN); esoc_mdm_log("Doing an S3 reset\n"); (*pon_trial)++; mdm_power_down(mdm); msleep(S3_RESET_DELAY_MS); break; case BOOT_FAIL_ACTION_PANIC: esoc_mdm_log("Calling panic!!\n"); panic("Panic requested on external modem boot failure\n"); Loading Loading @@ -381,7 +429,7 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys) struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink); const struct esoc_clink_ops * const clink_ops = esoc_clink->clink_ops; int timeout = INT_MAX; u8 pon_trial = 1; u8 pon_trial = 0; esoc_mdm_log("Powerup request from SSR\n"); Loading Loading @@ -455,7 +503,7 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys) } else if (mdm_drv->pon_state == PON_SUCCESS) { break; } } while (pon_trial <= n_pon_tries); } while (pon_trial <= atomic_read(&mdm_drv->n_pon_tries)); return 0; } Loading Loading @@ -527,6 +575,8 @@ int esoc_ssr_probe(struct esoc_clink *esoc_clink, struct esoc_drv *drv) mdm_drv->esoc_clink = esoc_clink; mdm_drv->mode = PWR_OFF; mdm_drv->pon_state = PON_INIT; atomic_set(&mdm_drv->boot_fail_action, BOOT_FAIL_ACTION_DEF); atomic_set(&mdm_drv->n_pon_tries, ESOC_DEF_PON_REQ); mdm_drv->esoc_restart.notifier_call = esoc_msm_restart_handler; ret = register_reboot_notifier(&mdm_drv->esoc_restart); if (ret) Loading drivers/esoc/esoc.h +4 −0 Original line number Diff line number Diff line Loading @@ -186,3 +186,7 @@ static inline void notify_esoc_clients(struct esoc_clink *esoc_clink, bool esoc_req_eng_enabled(struct esoc_clink *esoc_clink); bool esoc_cmd_eng_enabled(struct esoc_clink *esoc_clink); #endif /* Modem boot fail actions */ int esoc_set_boot_fail_action(struct esoc_clink *esoc_clink, u32 action); int esoc_set_n_pon_tries(struct esoc_clink *esoc_clink, u32 n_tries); drivers/esoc/esoc_dev.c +6 −0 Original line number Diff line number Diff line Loading @@ -323,6 +323,12 @@ static long esoc_dev_ioctl(struct file *file, unsigned int cmd, return err; case ESOC_GET_LINK_ID: return esoc_get_link_id(esoc_clink, arg); case ESOC_SET_BOOT_FAIL_ACT: get_user(esoc_cmd, (u32 __user *) arg); return esoc_set_boot_fail_action(esoc_clink, esoc_cmd); case ESOC_SET_N_PON_TRIES: get_user(esoc_cmd, (u32 __user *) arg); return esoc_set_n_pon_tries(esoc_clink, esoc_cmd); default: return -EINVAL; }; Loading include/uapi/linux/esoc_ctrl.h +13 −0 Original line number Diff line number Diff line Loading @@ -28,10 +28,23 @@ struct esoc_link_data { #define ESOC_REG_REQ_ENG _IO(ESOC_CODE, 7) #define ESOC_REG_CMD_ENG _IO(ESOC_CODE, 8) #define ESOC_GET_LINK_ID _IOWR(ESOC_CODE, 9, struct esoc_link_data) #define ESOC_SET_BOOT_FAIL_ACT _IOW(ESOC_CODE, 10, unsigned int) #define ESOC_SET_N_PON_TRIES _IOW(ESOC_CODE, 11, unsigned int) #define ESOC_REQ_SEND_SHUTDOWN ESOC_REQ_SEND_SHUTDOWN #define ESOC_REQ_CRASH_SHUTDOWN ESOC_REQ_CRASH_SHUTDOWN #define ESOC_PON_RETRY ESOC_PON_RETRY #define ESOC_BOOT_FAIL_ACTION enum esoc_boot_fail_action { BOOT_FAIL_ACTION_RETRY, BOOT_FAIL_ACTION_COLD_RESET, BOOT_FAIL_ACTION_SHUTDOWN, BOOT_FAIL_ACTION_PANIC, BOOT_FAIL_ACTION_NOP, BOOT_FAIL_ACTION_S3_RESET, BOOT_FAIL_ACTION_LAST, }; enum esoc_evt { ESOC_RUN_STATE = 0x1, Loading Loading
drivers/esoc/esoc-mdm-drv.c +70 −20 Original line number Diff line number Diff line Loading @@ -13,24 +13,11 @@ #include "mdm-dbg.h" /* Default number of powerup trial requests per session */ #define ESOC_DEF_PON_REQ 2 static unsigned int n_pon_tries = ESOC_DEF_PON_REQ; module_param(n_pon_tries, uint, 0644); MODULE_PARM_DESC(n_pon_tries, "Number of power-on retrials allowed upon boot failure"); enum esoc_boot_fail_action { BOOT_FAIL_ACTION_RETRY, BOOT_FAIL_ACTION_COLD_RESET, BOOT_FAIL_ACTION_SHUTDOWN, BOOT_FAIL_ACTION_PANIC, BOOT_FAIL_ACTION_NOP, }; #define ESOC_DEF_PON_REQ 3 #define ESOC_MAX_PON_TRIES 5 static unsigned int boot_fail_action = BOOT_FAIL_ACTION_NOP; module_param(boot_fail_action, uint, 0644); MODULE_PARM_DESC(boot_fail_action, "Actions: 0:Retry PON; 1:Cold reset; 2:Power-down; 3:APQ Panic; 4:No action"); #define BOOT_FAIL_ACTION_DEF BOOT_FAIL_ACTION_PANIC enum esoc_pon_state { PON_INIT, Loading Loading @@ -62,13 +49,59 @@ struct mdm_drv { struct work_struct ssr_work; struct notifier_block esoc_restart; struct mutex poff_lock; atomic_t boot_fail_action; atomic_t n_pon_tries; }; #define to_mdm_drv(d) container_of(d, struct mdm_drv, cmd_eng) #define S3_RESET_DELAY_MS 1000 static void esoc_client_link_power_off(struct esoc_clink *esoc_clink, unsigned int flags); static void esoc_client_link_mdm_crash(struct esoc_clink *esoc_clink); int esoc_set_boot_fail_action(struct esoc_clink *esoc_clink, u32 action) { struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink); if (action >= BOOT_FAIL_ACTION_LAST) { esoc_mdm_log("Unknown boot fail action requested: %u\n", action); return -EINVAL; } if (!mdm_drv) { esoc_mdm_log("esoc-mdm driver not present\n"); return -EAGAIN; } atomic_set(&mdm_drv->boot_fail_action, action); esoc_mdm_log("Boot fail action configured to %u\n", action); return 0; } int esoc_set_n_pon_tries(struct esoc_clink *esoc_clink, u32 n_tries) { struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink); if (n_tries > ESOC_MAX_PON_TRIES) { esoc_mdm_log( "Num PON tries requested (%u) is over the limit: %u\n", n_tries, ESOC_MAX_PON_TRIES); } if (!mdm_drv) { esoc_mdm_log("esoc-mdm driver not present\n"); return -EAGAIN; } atomic_set(&mdm_drv->n_pon_tries, n_tries); esoc_mdm_log("Num PON tries configured to %u\n", n_tries); return 0; } static int esoc_msm_restart_handler(struct notifier_block *nb, unsigned long action, void *data) { Loading Loading @@ -334,8 +367,15 @@ static void mdm_subsys_retry_powerup_cleanup(struct esoc_clink *esoc_clink, static int mdm_handle_boot_fail(struct esoc_clink *esoc_clink, u8 *pon_trial) { struct mdm_ctrl *mdm = get_esoc_clink_data(esoc_clink); struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink); if (*pon_trial == atomic_read(&mdm_drv->n_pon_tries)) { esoc_mdm_log("Reached max. number of boot trials\n"); atomic_set(&mdm_drv->boot_fail_action, BOOT_FAIL_ACTION_PANIC); } switch (boot_fail_action) { switch (atomic_read(&mdm_drv->boot_fail_action)) { case BOOT_FAIL_ACTION_RETRY: mdm_subsys_retry_powerup_cleanup(esoc_clink, 0); esoc_mdm_log("Request to retry a warm reset\n"); Loading @@ -353,6 +393,14 @@ static int mdm_handle_boot_fail(struct esoc_clink *esoc_clink, u8 *pon_trial) (*pon_trial)++; mdm_power_down(mdm); break; case BOOT_FAIL_ACTION_S3_RESET: mdm_subsys_retry_powerup_cleanup(esoc_clink, ESOC_HOOK_MDM_DOWN); esoc_mdm_log("Doing an S3 reset\n"); (*pon_trial)++; mdm_power_down(mdm); msleep(S3_RESET_DELAY_MS); break; case BOOT_FAIL_ACTION_PANIC: esoc_mdm_log("Calling panic!!\n"); panic("Panic requested on external modem boot failure\n"); Loading Loading @@ -381,7 +429,7 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys) struct mdm_drv *mdm_drv = esoc_get_drv_data(esoc_clink); const struct esoc_clink_ops * const clink_ops = esoc_clink->clink_ops; int timeout = INT_MAX; u8 pon_trial = 1; u8 pon_trial = 0; esoc_mdm_log("Powerup request from SSR\n"); Loading Loading @@ -455,7 +503,7 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys) } else if (mdm_drv->pon_state == PON_SUCCESS) { break; } } while (pon_trial <= n_pon_tries); } while (pon_trial <= atomic_read(&mdm_drv->n_pon_tries)); return 0; } Loading Loading @@ -527,6 +575,8 @@ int esoc_ssr_probe(struct esoc_clink *esoc_clink, struct esoc_drv *drv) mdm_drv->esoc_clink = esoc_clink; mdm_drv->mode = PWR_OFF; mdm_drv->pon_state = PON_INIT; atomic_set(&mdm_drv->boot_fail_action, BOOT_FAIL_ACTION_DEF); atomic_set(&mdm_drv->n_pon_tries, ESOC_DEF_PON_REQ); mdm_drv->esoc_restart.notifier_call = esoc_msm_restart_handler; ret = register_reboot_notifier(&mdm_drv->esoc_restart); if (ret) Loading
drivers/esoc/esoc.h +4 −0 Original line number Diff line number Diff line Loading @@ -186,3 +186,7 @@ static inline void notify_esoc_clients(struct esoc_clink *esoc_clink, bool esoc_req_eng_enabled(struct esoc_clink *esoc_clink); bool esoc_cmd_eng_enabled(struct esoc_clink *esoc_clink); #endif /* Modem boot fail actions */ int esoc_set_boot_fail_action(struct esoc_clink *esoc_clink, u32 action); int esoc_set_n_pon_tries(struct esoc_clink *esoc_clink, u32 n_tries);
drivers/esoc/esoc_dev.c +6 −0 Original line number Diff line number Diff line Loading @@ -323,6 +323,12 @@ static long esoc_dev_ioctl(struct file *file, unsigned int cmd, return err; case ESOC_GET_LINK_ID: return esoc_get_link_id(esoc_clink, arg); case ESOC_SET_BOOT_FAIL_ACT: get_user(esoc_cmd, (u32 __user *) arg); return esoc_set_boot_fail_action(esoc_clink, esoc_cmd); case ESOC_SET_N_PON_TRIES: get_user(esoc_cmd, (u32 __user *) arg); return esoc_set_n_pon_tries(esoc_clink, esoc_cmd); default: return -EINVAL; }; Loading
include/uapi/linux/esoc_ctrl.h +13 −0 Original line number Diff line number Diff line Loading @@ -28,10 +28,23 @@ struct esoc_link_data { #define ESOC_REG_REQ_ENG _IO(ESOC_CODE, 7) #define ESOC_REG_CMD_ENG _IO(ESOC_CODE, 8) #define ESOC_GET_LINK_ID _IOWR(ESOC_CODE, 9, struct esoc_link_data) #define ESOC_SET_BOOT_FAIL_ACT _IOW(ESOC_CODE, 10, unsigned int) #define ESOC_SET_N_PON_TRIES _IOW(ESOC_CODE, 11, unsigned int) #define ESOC_REQ_SEND_SHUTDOWN ESOC_REQ_SEND_SHUTDOWN #define ESOC_REQ_CRASH_SHUTDOWN ESOC_REQ_CRASH_SHUTDOWN #define ESOC_PON_RETRY ESOC_PON_RETRY #define ESOC_BOOT_FAIL_ACTION enum esoc_boot_fail_action { BOOT_FAIL_ACTION_RETRY, BOOT_FAIL_ACTION_COLD_RESET, BOOT_FAIL_ACTION_SHUTDOWN, BOOT_FAIL_ACTION_PANIC, BOOT_FAIL_ACTION_NOP, BOOT_FAIL_ACTION_S3_RESET, BOOT_FAIL_ACTION_LAST, }; enum esoc_evt { ESOC_RUN_STATE = 0x1, Loading