Skip to content

Commit 5b6a865

Browse files
MarkusLassilakartben
authored andcommitted
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>
1 parent 93c3975 commit 5b6a865

File tree

2 files changed

+75
-2
lines changed

2 files changed

+75
-2
lines changed

drivers/modem/Kconfig.cellular

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ config MODEM_CELLULAR
1313
select RING_BUFFER
1414
select NET_L2_PPP_OPTION_MRU
1515
select NET_L2_PPP_PAP
16+
select NET_L2_PPP_MGMT
1617
depends on (DT_HAS_QUECTEL_BG95_ENABLED || \
1718
DT_HAS_SIMCOM_SIM7080_ENABLED || DT_HAS_U_BLOX_SARA_R4_ENABLED || \
1819
DT_HAS_U_BLOX_SARA_R5_ENABLED || DT_HAS_SWIR_HL7800_ENABLED || \

drivers/modem/modem_cellular.c

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ enum modem_cellular_state {
6060
MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT,
6161
MODEM_CELLULAR_STATE_AWAIT_REGISTERED,
6262
MODEM_CELLULAR_STATE_CARRIER_ON,
63+
MODEM_CELLULAR_STATE_DORMANT,
6364
MODEM_CELLULAR_STATE_INIT_POWER_OFF,
6465
MODEM_CELLULAR_STATE_RUN_SHUTDOWN_SCRIPT,
6566
MODEM_CELLULAR_STATE_POWER_OFF_PULSE,
@@ -79,6 +80,7 @@ enum modem_cellular_event {
7980
MODEM_CELLULAR_EVENT_DEREGISTERED,
8081
MODEM_CELLULAR_EVENT_BUS_OPENED,
8182
MODEM_CELLULAR_EVENT_BUS_CLOSED,
83+
MODEM_CELLULAR_EVENT_PPP_DEAD,
8284
};
8385

8486
struct modem_cellular_data {
@@ -126,6 +128,7 @@ struct modem_cellular_data {
126128

127129
/* PPP */
128130
struct modem_ppp *ppp;
131+
struct net_mgmt_event_callback net_mgmt_event_callback;
129132

130133
enum modem_cellular_state state;
131134
const struct device *dev;
@@ -196,6 +199,8 @@ static const char *modem_cellular_state_str(enum modem_cellular_state state)
196199
return "run dial script";
197200
case MODEM_CELLULAR_STATE_CARRIER_ON:
198201
return "carrier on";
202+
case MODEM_CELLULAR_STATE_DORMANT:
203+
return "dormant";
199204
case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
200205
return "init power off";
201206
case MODEM_CELLULAR_STATE_RUN_SHUTDOWN_SCRIPT:
@@ -236,6 +241,8 @@ static const char *modem_cellular_event_str(enum modem_cellular_event event)
236241
return "bus opened";
237242
case MODEM_CELLULAR_EVENT_BUS_CLOSED:
238243
return "bus closed";
244+
case MODEM_CELLULAR_EVENT_PPP_DEAD:
245+
return "ppp dead";
239246
}
240247

241248
return "";
@@ -1021,7 +1028,9 @@ static void modem_cellular_run_dial_script_event_handler(struct modem_cellular_d
10211028
modem_chat_attach(&data->chat, data->dlci1_pipe);
10221029
modem_chat_run_script_async(&data->chat, config->dial_chat_script);
10231030
break;
1024-
1031+
case MODEM_CELLULAR_EVENT_SCRIPT_FAILED:
1032+
modem_cellular_start_timer(data, MODEM_CELLULAR_PERIODIC_SCRIPT_TIMEOUT);
1033+
break;
10251034
case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS:
10261035
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_AWAIT_REGISTERED);
10271036
break;
@@ -1110,7 +1119,7 @@ static void modem_cellular_carrier_on_event_handler(struct modem_cellular_data *
11101119
break;
11111120

11121121
case MODEM_CELLULAR_EVENT_DEREGISTERED:
1113-
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT);
1122+
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_DORMANT);
11141123
break;
11151124

11161125
case MODEM_CELLULAR_EVENT_SUSPEND:
@@ -1125,9 +1134,37 @@ static void modem_cellular_carrier_on_event_handler(struct modem_cellular_data *
11251134
static int modem_cellular_on_carrier_on_state_leave(struct modem_cellular_data *data)
11261135
{
11271136
modem_cellular_stop_timer(data);
1137+
1138+
return 0;
1139+
}
1140+
1141+
static int modem_cellular_on_dormant_state_enter(struct modem_cellular_data *data)
1142+
{
1143+
net_if_dormant_on(modem_ppp_get_iface(data->ppp));
1144+
1145+
return 0;
1146+
}
1147+
1148+
static void modem_cellular_dormant_event_handler(struct modem_cellular_data *data,
1149+
enum modem_cellular_event evt)
1150+
{
1151+
switch (evt) {
1152+
case MODEM_CELLULAR_EVENT_PPP_DEAD:
1153+
modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT);
1154+
break;
1155+
1156+
default:
1157+
break;
1158+
}
1159+
}
1160+
1161+
static int modem_cellular_on_dormant_state_leave(struct modem_cellular_data *data)
1162+
{
11281163
net_if_carrier_off(modem_ppp_get_iface(data->ppp));
11291164
modem_chat_release(&data->chat);
11301165
modem_ppp_release(data->ppp);
1166+
net_if_dormant_off(modem_ppp_get_iface(data->ppp));
1167+
11311168
return 0;
11321169
}
11331170

@@ -1316,6 +1353,10 @@ static int modem_cellular_on_state_enter(struct modem_cellular_data *data)
13161353
ret = modem_cellular_on_carrier_on_state_enter(data);
13171354
break;
13181355

1356+
case MODEM_CELLULAR_STATE_DORMANT:
1357+
ret = modem_cellular_on_dormant_state_enter(data);
1358+
break;
1359+
13191360
case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
13201361
ret = modem_cellular_on_init_power_off_state_enter(data);
13211362
break;
@@ -1377,6 +1418,10 @@ static int modem_cellular_on_state_leave(struct modem_cellular_data *data)
13771418
ret = modem_cellular_on_carrier_on_state_leave(data);
13781419
break;
13791420

1421+
case MODEM_CELLULAR_STATE_DORMANT:
1422+
ret = modem_cellular_on_dormant_state_leave(data);
1423+
break;
1424+
13801425
case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
13811426
ret = modem_cellular_on_init_power_off_state_leave(data);
13821427
break;
@@ -1476,6 +1521,10 @@ static void modem_cellular_event_handler(struct modem_cellular_data *data,
14761521
modem_cellular_carrier_on_event_handler(data, evt);
14771522
break;
14781523

1524+
case MODEM_CELLULAR_STATE_DORMANT:
1525+
modem_cellular_dormant_event_handler(data, evt);
1526+
break;
1527+
14791528
case MODEM_CELLULAR_STATE_INIT_POWER_OFF:
14801529
modem_cellular_init_power_off_event_handler(data, evt);
14811530
break;
@@ -1719,6 +1768,22 @@ static int modem_cellular_pm_action(const struct device *dev, enum pm_device_act
17191768
}
17201769
#endif /* CONFIG_PM_DEVICE */
17211770

1771+
static void net_mgmt_event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event,
1772+
struct net_if *iface)
1773+
{
1774+
struct modem_cellular_data *data =
1775+
CONTAINER_OF(cb, struct modem_cellular_data, net_mgmt_event_callback);
1776+
1777+
switch (mgmt_event) {
1778+
case NET_EVENT_PPP_PHASE_DEAD:
1779+
modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_PPP_DEAD);
1780+
break;
1781+
1782+
default:
1783+
break;
1784+
}
1785+
}
1786+
17221787
static int modem_cellular_init(const struct device *dev)
17231788
{
17241789
struct modem_cellular_data *data = (struct modem_cellular_data *)dev->data;
@@ -1827,6 +1892,13 @@ static int modem_cellular_init(const struct device *dev)
18271892
modem_chat_init(&data->chat, &chat_config);
18281893
}
18291894

1895+
{
1896+
net_mgmt_init_event_callback(&data->net_mgmt_event_callback, net_mgmt_event_handler,
1897+
NET_EVENT_PPP_PHASE_DEAD);
1898+
net_mgmt_add_event_callback(&data->net_mgmt_event_callback);
1899+
}
1900+
1901+
18301902
#ifndef CONFIG_PM_DEVICE
18311903
modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_RESUME);
18321904
#else

0 commit comments

Comments
 (0)