drivers: gsm: Wait for NET_EVENT_IF_DOWN in in gsm_ppp_stop
Waits until the network interface goes down before switching the GSM_MUX. It uses the NET_MGMT_EVENT to signal a semaphore to contiue when closed. This allows for the LCP state machine to properly terminate. When skipping this wait, the second time connecting, the connection might fail. Tested on a real modem. Fixes GSM PPP behavior in combination with: #41802 Signed-off-by: Sjors Hettinga <s.a.hettinga@gmail.com>
This commit is contained in:
parent
e535cc76db
commit
60beb291df
2 changed files with 32 additions and 0 deletions
|
@ -6,6 +6,8 @@ config MODEM_GSM_PPP
|
|||
select MODEM_CONTEXT
|
||||
select MODEM_CMD_HANDLER
|
||||
select MODEM_IFACE_UART
|
||||
select NET_MGMT
|
||||
select NET_MGMT_EVENT
|
||||
help
|
||||
Enable GSM modems that support standard AT commands and PPP.
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ static struct gsm_modem {
|
|||
struct modem_cmd_handler_data cmd_handler_data;
|
||||
uint8_t cmd_match_buf[GSM_CMD_READ_BUF];
|
||||
struct k_sem sem_response;
|
||||
struct k_sem sem_if_down;
|
||||
|
||||
struct modem_iface_uart_data gsm_data;
|
||||
struct k_work_delayable gsm_configure_work;
|
||||
|
@ -97,6 +98,7 @@ static struct gsm_modem {
|
|||
|
||||
gsm_modem_power_cb modem_on_cb;
|
||||
gsm_modem_power_cb modem_off_cb;
|
||||
struct net_mgmt_event_callback gsm_mgmt_cb;
|
||||
} gsm;
|
||||
|
||||
NET_BUF_POOL_DEFINE(gsm_recv_pool, GSM_RECV_MAX_BUF, GSM_RECV_BUF_SIZE,
|
||||
|
@ -1058,6 +1060,9 @@ void gsm_ppp_stop(const struct device *dev)
|
|||
|
||||
net_if_l2(iface)->enable(iface, false);
|
||||
|
||||
/* wait for the interface to be properly down */
|
||||
(void)k_sem_take(&gsm->sem_if_down, K_FOREVER);
|
||||
|
||||
if (IS_ENABLED(CONFIG_GSM_MUX)) {
|
||||
/* Lower mux_enabled flag to trigger re-sending AT+CMUX etc */
|
||||
gsm->mux_enabled = false;
|
||||
|
@ -1097,6 +1102,26 @@ const struct gsm_ppp_modem_info *gsm_ppp_modem_info(const struct device *dev)
|
|||
return &gsm->minfo;
|
||||
}
|
||||
|
||||
static void gsm_mgmt_event_handler(struct net_mgmt_event_callback *cb,
|
||||
uint32_t mgmt_event, struct net_if *iface)
|
||||
{
|
||||
if ((mgmt_event & NET_EVENT_IF_DOWN) != mgmt_event) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Right now we only support 1 GSM instance */
|
||||
if (iface != gsm.iface) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mgmt_event == NET_EVENT_IF_DOWN) {
|
||||
LOG_INF("GSM network interface down");
|
||||
/* raise semaphore to indicate the interface is down */
|
||||
k_sem_give(&gsm.sem_if_down);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int gsm_init(const struct device *dev)
|
||||
{
|
||||
struct gsm_modem *gsm = dev->data;
|
||||
|
@ -1115,6 +1140,7 @@ static int gsm_init(const struct device *dev)
|
|||
gsm->cmd_handler_data.eol = "\r";
|
||||
|
||||
k_sem_init(&gsm->sem_response, 0, 1);
|
||||
k_sem_init(&gsm->sem_if_down, 0, 1);
|
||||
|
||||
r = modem_cmd_handler_init(&gsm->context.cmd_handler,
|
||||
&gsm->cmd_handler_data);
|
||||
|
@ -1174,6 +1200,10 @@ static int gsm_init(const struct device *dev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
net_mgmt_init_event_callback(&gsm->gsm_mgmt_cb, gsm_mgmt_event_handler,
|
||||
NET_EVENT_IF_DOWN);
|
||||
net_mgmt_add_event_callback(&gsm->gsm_mgmt_cb);
|
||||
|
||||
if (IS_ENABLED(CONFIG_GSM_PPP_AUTOSTART)) {
|
||||
gsm_ppp_start(dev);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue