manager: make sure we don't reset the modem twice in a row

This patch adds a 3s delay when resetting the modem during which we 
avoid triggering a new reset. This makes sure we don't trigger a reset 
twice in a row.

It also disables any related running timer to avoid being re-triggered 
unnecessarily.
This commit is contained in:
Arnaud Ferraris
2020-12-18 00:45:58 +01:00
parent c39000bf93
commit 74b91c7d58
4 changed files with 34 additions and 8 deletions

View File

@@ -110,10 +110,27 @@ void modem_configure(struct EG25Manager *manager)
at_sequence_configure(manager); at_sequence_configure(manager);
} }
static gboolean modem_reset_done(struct EG25Manager* manager)
{
manager->modem_state = EG25_STATE_RESUMING;
manager->reset_timer = 0;
return FALSE;
}
void modem_reset(struct EG25Manager *manager) void modem_reset(struct EG25Manager *manager)
{ {
int fd, ret, len = strlen(manager->modem_usb_id); int fd, ret, len = strlen(manager->modem_usb_id);
if (manager->reset_timer)
return;
if (manager->suspend_source) {
g_source_remove(manager->suspend_source);
manager->suspend_source = 0;
}
manager->modem_state = EG25_STATE_RESETTING;
fd = open("/sys/bus/usb/drivers/usb/unbind", O_WRONLY); fd = open("/sys/bus/usb/drivers/usb/unbind", O_WRONLY);
if (fd < 0) if (fd < 0)
goto error; goto error;
@@ -127,16 +144,20 @@ void modem_reset(struct EG25Manager *manager)
goto error; goto error;
ret = write(fd, manager->modem_usb_id, len); ret = write(fd, manager->modem_usb_id, len);
if (ret < len) if (ret < len)
g_warning("Couldn't unbind modem: wrote %d/%d bytes", ret, len); g_warning("Couldn't bind modem: wrote %d/%d bytes", ret, len);
close(fd); close(fd);
/*
* 3s is long enough to make sure the modem has been bound back and
* short enough to ensure it hasn't been acquired by ModemManager
*/
manager->reset_timer = g_timeout_add_seconds(3, G_SOURCE_FUNC(modem_reset_done), manager);
return; return;
error: error:
// Everything else failed, reset the modem // Everything else failed, reset the modem
at_sequence_reset(manager); at_sequence_reset(manager);
manager->modem_state = EG25_STATE_RESETTING;
} }
void modem_suspend(struct EG25Manager *manager) void modem_suspend(struct EG25Manager *manager)

View File

@@ -26,6 +26,11 @@ enum EG25State {
struct EG25Manager { struct EG25Manager {
GMainLoop *loop; GMainLoop *loop;
guint reset_timer;
int at_fd;
guint at_source;
GList *at_cmds;
enum EG25State modem_state; enum EG25State modem_state;
gchar *modem_usb_id; gchar *modem_usb_id;
@@ -40,10 +45,6 @@ struct EG25Manager {
guint suspend_source; guint suspend_source;
int at_fd;
guint at_source;
GList *at_cmds;
struct gpiod_chip *gpiochip[2]; struct gpiod_chip *gpiochip[2];
struct gpiod_line *gpio_out[5]; struct gpiod_line *gpio_out[5];
struct gpiod_line *gpio_in[2]; struct gpiod_line *gpio_in[2];

View File

@@ -35,7 +35,10 @@ static void add_modem(struct EG25Manager *manager, GDBusObject *object)
g_assert(manager->mm_modem != NULL); g_assert(manager->mm_modem != NULL);
if (manager->modem_state == EG25_STATE_RESUMING) { if (manager->modem_state == EG25_STATE_RESUMING) {
g_source_remove(manager->suspend_source); if (manager->suspend_source) {
g_source_remove(manager->suspend_source);
manager->suspend_source = 0;
}
modem_resume_post(manager); modem_resume_post(manager);
manager->modem_state = EG25_STATE_CONFIGURED; manager->modem_state = EG25_STATE_CONFIGURED;
} }

View File

@@ -20,6 +20,7 @@
static gboolean check_modem_resume(struct EG25Manager *manager) static gboolean check_modem_resume(struct EG25Manager *manager)
{ {
g_message("Modem wasn't probed in time, restart it!"); g_message("Modem wasn't probed in time, restart it!");
manager->suspend_source = 0;
modem_reset(manager); modem_reset(manager);
return FALSE; return FALSE;