modem_cellular: Add dormant state to support network loss
Previously, it was expected that the modem would immediately disconnect and close the PPP link, when the network was lost (+CEREG: 4 is received). Failure to do so, would result in modem attempting to chat with dlci2 channel, where as cellular modem driver would drop to dlci1. This would show as dial script timing out, which would freeze cellular modem driver. Adding dormant state enables graceful disconnection of PPP-link when the network is lost. This allows the modems which do not automatically close with network link loss to close based on PPP link closure. Signed-off-by: Markus Lassila <markus.lassila@nordicsemi.no>
This commit is contained in:
parent
93c3975fe6
commit
5b6a865464
@ -13,6 +13,7 @@ config MODEM_CELLULAR
|
||||
select RING_BUFFER
|
||||
select NET_L2_PPP_OPTION_MRU
|
||||
select NET_L2_PPP_PAP
|
||||
select NET_L2_PPP_MGMT
|
||||
depends on (DT_HAS_QUECTEL_BG95_ENABLED || \
|
||||
DT_HAS_SIMCOM_SIM7080_ENABLED || DT_HAS_U_BLOX_SARA_R4_ENABLED || \
|
||||
DT_HAS_U_BLOX_SARA_R5_ENABLED || DT_HAS_SWIR_HL7800_ENABLED || \
|
||||
|
||||
@ -60,6 +60,7 @@ enum modem_cellular_state {
|
||||
MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT,
|
||||
MODEM_CELLULAR_STATE_AWAIT_REGISTERED,
|
||||
MODEM_CELLULAR_STATE_CARRIER_ON,
|
||||
MODEM_CELLULAR_STATE_DORMANT,
|
||||
MODEM_CELLULAR_STATE_INIT_POWER_OFF,
|
||||
MODEM_CELLULAR_STATE_RUN_SHUTDOWN_SCRIPT,
|
||||
MODEM_CELLULAR_STATE_POWER_OFF_PULSE,
|
||||
@ -79,6 +80,7 @@ enum modem_cellular_event {
|
||||
MODEM_CELLULAR_EVENT_DEREGISTERED,
|
||||
MODEM_CELLULAR_EVENT_BUS_OPENED,
|
||||
MODEM_CELLULAR_EVENT_BUS_CLOSED,
|
||||
MODEM_CELLULAR_EVENT_PPP_DEAD,
|
||||
};
|
||||
|
||||
struct modem_cellular_data {
|
||||
@ -126,6 +128,7 @@ struct modem_cellular_data {
|
||||
|
||||
/* PPP */
|
||||
struct modem_ppp *ppp;
|
||||
struct net_mgmt_event_callback net_mgmt_event_callback;
|
||||
|
||||
enum modem_cellular_state state;
|
||||
const struct device *dev;
|
||||
@ -196,6 +199,8 @@ static const char *modem_cellular_state_str(enum modem_cellular_state state)
|
||||
return "run dial script";
|
||||
case MODEM_CELLULAR_STATE_CARRIER_ON:
|
||||
return "carrier on";
|
||||
case MODEM_CELLULAR_STATE_DORMANT:
|
||||
return "dormant";
|
||||
case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
|
||||
return "init power off";
|
||||
case MODEM_CELLULAR_STATE_RUN_SHUTDOWN_SCRIPT:
|
||||
@ -236,6 +241,8 @@ static const char *modem_cellular_event_str(enum modem_cellular_event event)
|
||||
return "bus opened";
|
||||
case MODEM_CELLULAR_EVENT_BUS_CLOSED:
|
||||
return "bus closed";
|
||||
case MODEM_CELLULAR_EVENT_PPP_DEAD:
|
||||
return "ppp dead";
|
||||
}
|
||||
|
||||
return "";
|
||||
@ -1021,7 +1028,9 @@ static void modem_cellular_run_dial_script_event_handler(struct modem_cellular_d
|
||||
modem_chat_attach(&data->chat, data->dlci1_pipe);
|
||||
modem_chat_run_script_async(&data->chat, config->dial_chat_script);
|
||||
break;
|
||||
|
||||
case MODEM_CELLULAR_EVENT_SCRIPT_FAILED:
|
||||
modem_cellular_start_timer(data, MODEM_CELLULAR_PERIODIC_SCRIPT_TIMEOUT);
|
||||
break;
|
||||
case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
|
||||
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_REGISTERED);
|
||||
break;
|
||||
@ -1110,7 +1119,7 @@ static void modem_cellular_carrier_on_event_handler(struct modem_cellular_data *
|
||||
break;
|
||||
|
||||
case MODEM_CELLULAR_EVENT_DEREGISTERED:
|
||||
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT);
|
||||
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_DORMANT);
|
||||
break;
|
||||
|
||||
case MODEM_CELLULAR_EVENT_SUSPEND:
|
||||
@ -1125,9 +1134,37 @@ static void modem_cellular_carrier_on_event_handler(struct modem_cellular_data *
|
||||
static int modem_cellular_on_carrier_on_state_leave(struct modem_cellular_data *data)
|
||||
{
|
||||
modem_cellular_stop_timer(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int modem_cellular_on_dormant_state_enter(struct modem_cellular_data *data)
|
||||
{
|
||||
net_if_dormant_on(modem_ppp_get_iface(data->ppp));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void modem_cellular_dormant_event_handler(struct modem_cellular_data *data,
|
||||
enum modem_cellular_event evt)
|
||||
{
|
||||
switch (evt) {
|
||||
case MODEM_CELLULAR_EVENT_PPP_DEAD:
|
||||
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int modem_cellular_on_dormant_state_leave(struct modem_cellular_data *data)
|
||||
{
|
||||
net_if_carrier_off(modem_ppp_get_iface(data->ppp));
|
||||
modem_chat_release(&data->chat);
|
||||
modem_ppp_release(data->ppp);
|
||||
net_if_dormant_off(modem_ppp_get_iface(data->ppp));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1316,6 +1353,10 @@ static int modem_cellular_on_state_enter(struct modem_cellular_data *data)
|
||||
ret = modem_cellular_on_carrier_on_state_enter(data);
|
||||
break;
|
||||
|
||||
case MODEM_CELLULAR_STATE_DORMANT:
|
||||
ret = modem_cellular_on_dormant_state_enter(data);
|
||||
break;
|
||||
|
||||
case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
|
||||
ret = modem_cellular_on_init_power_off_state_enter(data);
|
||||
break;
|
||||
@ -1377,6 +1418,10 @@ static int modem_cellular_on_state_leave(struct modem_cellular_data *data)
|
||||
ret = modem_cellular_on_carrier_on_state_leave(data);
|
||||
break;
|
||||
|
||||
case MODEM_CELLULAR_STATE_DORMANT:
|
||||
ret = modem_cellular_on_dormant_state_leave(data);
|
||||
break;
|
||||
|
||||
case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
|
||||
ret = modem_cellular_on_init_power_off_state_leave(data);
|
||||
break;
|
||||
@ -1476,6 +1521,10 @@ static void modem_cellular_event_handler(struct modem_cellular_data *data,
|
||||
modem_cellular_carrier_on_event_handler(data, evt);
|
||||
break;
|
||||
|
||||
case MODEM_CELLULAR_STATE_DORMANT:
|
||||
modem_cellular_dormant_event_handler(data, evt);
|
||||
break;
|
||||
|
||||
case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
|
||||
modem_cellular_init_power_off_event_handler(data, evt);
|
||||
break;
|
||||
@ -1719,6 +1768,22 @@ static int modem_cellular_pm_action(const struct device *dev, enum pm_device_act
|
||||
}
|
||||
#endif /* CONFIG_PM_DEVICE */
|
||||
|
||||
static void net_mgmt_event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event,
|
||||
struct net_if *iface)
|
||||
{
|
||||
struct modem_cellular_data *data =
|
||||
CONTAINER_OF(cb, struct modem_cellular_data, net_mgmt_event_callback);
|
||||
|
||||
switch (mgmt_event) {
|
||||
case NET_EVENT_PPP_PHASE_DEAD:
|
||||
modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_PPP_DEAD);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int modem_cellular_init(const struct device *dev)
|
||||
{
|
||||
struct modem_cellular_data *data = (struct modem_cellular_data *)dev->data;
|
||||
@ -1827,6 +1892,13 @@ static int modem_cellular_init(const struct device *dev)
|
||||
modem_chat_init(&data->chat, &chat_config);
|
||||
}
|
||||
|
||||
{
|
||||
net_mgmt_init_event_callback(&data->net_mgmt_event_callback, net_mgmt_event_handler,
|
||||
NET_EVENT_PPP_PHASE_DEAD);
|
||||
net_mgmt_add_event_callback(&data->net_mgmt_event_callback);
|
||||
}
|
||||
|
||||
|
||||
#ifndef CONFIG_PM_DEVICE
|
||||
modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_RESUME);
|
||||
#else
|
||||
|
||||
Loading…
Reference in New Issue
Block a user