Merge request !1378 from 'suspend-bearer-timeout'

base-manager: increase suspend timeout for each active bearer

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1378
This commit is contained in:
Dan Williams
2025-07-28 09:20:50 -05:00
9 changed files with 148 additions and 65 deletions
+22 -2
View File
@@ -1167,6 +1167,7 @@ mm_base_manager_cleanup (MMBaseManager *self,
GHashTableIter iter; GHashTableIter iter;
MMDevice *device; MMDevice *device;
gboolean disable, remove, low_power, terse; gboolean disable, remove, low_power, terse;
guint active_bearers = 0;
g_return_if_fail (self != NULL); g_return_if_fail (self != NULL);
g_return_if_fail (MM_IS_BASE_MANAGER (self)); g_return_if_fail (MM_IS_BASE_MANAGER (self));
@@ -1193,7 +1194,20 @@ mm_base_manager_cleanup (MMBaseManager *self,
g_hash_table_iter_init (&iter, self->priv->devices); g_hash_table_iter_init (&iter, self->priv->devices);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) {
DeviceCleanupContext *dctx; DeviceCleanupContext *dctx;
GTask *task; GTask *task;
MMBaseModem *modem;
modem = mm_device_peek_modem (device);
if (modem) {
guint count = 0;
mm_iface_modem_count_bearers (MM_IFACE_MODEM (modem),
MM_IFACE_MODEM_COUNT_BEARERS_FLAG_ACTIVE,
&count,
NULL,
NULL);
active_bearers += count;
}
task = g_task_new (device, task = g_task_new (device,
NULL, NULL,
@@ -1201,12 +1215,18 @@ mm_base_manager_cleanup (MMBaseManager *self,
ctx); ctx);
ctx->tasks = g_slist_append (ctx->tasks, task); ctx->tasks = g_slist_append (ctx->tasks, task);
dctx = device_cleanup_context_new (mm_device_peek_modem (device), flags); dctx = device_cleanup_context_new (modem, flags);
g_task_set_task_data (task, dctx, (GDestroyNotify)device_cleanup_context_free); g_task_set_task_data (task, dctx, (GDestroyNotify)device_cleanup_context_free);
device_cleanup_step (task); device_cleanup_step (task);
} }
/* Increase cleanup timeout for each connected bearer; disconnecting a
* bearer can take many seconds.
*/
if (active_bearers)
mm_sleep_context_timeout_backoff (sleep_ctx, active_bearers * 20);
/* Complete cleanup if there were no devices */ /* Complete cleanup if there were no devices */
manager_cleanup_context_maybe_complete (ctx, NULL, NULL, FALSE); manager_cleanup_context_maybe_complete (ctx, NULL, NULL, FALSE);
} }
+5 -4
View File
@@ -1459,10 +1459,11 @@ load_settings_from_bearer (MMBearerMbim *self,
guint max_multiplexed_bearers; guint max_multiplexed_bearers;
const gchar *data_port_driver; const gchar *data_port_driver;
if (!mm_broadband_modem_get_active_multiplexed_bearers (MM_BROADBAND_MODEM (ctx->modem), if (!mm_iface_modem_count_bearers (MM_IFACE_MODEM (ctx->modem),
&current_multiplexed_bearers, MM_IFACE_MODEM_COUNT_BEARERS_FLAG_MULTIPLEXED,
&max_multiplexed_bearers, &current_multiplexed_bearers,
error)) &max_multiplexed_bearers,
error))
return FALSE; return FALSE;
/* Check multiplex support in the kernel and the device */ /* Check multiplex support in the kernel and the device */
+5 -4
View File
@@ -2425,10 +2425,11 @@ load_settings_from_bearer (MMBearerQmi *self,
guint max_multiplexed_bearers; guint max_multiplexed_bearers;
gboolean multiplex_supported = TRUE; gboolean multiplex_supported = TRUE;
if (!mm_broadband_modem_get_active_multiplexed_bearers (MM_BROADBAND_MODEM (ctx->modem), if (!mm_iface_modem_count_bearers (MM_IFACE_MODEM (ctx->modem),
&current_multiplexed_bearers, MM_IFACE_MODEM_COUNT_BEARERS_FLAG_MULTIPLEXED,
&max_multiplexed_bearers, &current_multiplexed_bearers,
error)) &max_multiplexed_bearers,
error))
return FALSE; return FALSE;
/* Check multiplex support in the kernel and the device */ /* Check multiplex support in the kernel and the device */
-46
View File
@@ -13809,52 +13809,6 @@ mm_broadband_modem_get_current_charset (MMBroadbandModem *self)
/*****************************************************************************/ /*****************************************************************************/
static void
bearer_count_multiplexed_connected (MMBaseBearer *bearer,
guint *count)
{
/* The Multiplexed property is only set if connected, so it's enough to check
* that one to see if we're connected and multiplexed */
if (mm_gdbus_bearer_get_multiplexed (MM_GDBUS_BEARER (bearer)))
*count += 1;
}
gboolean
mm_broadband_modem_get_active_multiplexed_bearers (MMBroadbandModem *self,
guint *out_current,
guint *out_max,
GError **error)
{
g_autoptr(MMBearerList) list = NULL;
guint max;
guint count = 0;
g_object_get (self,
MM_IFACE_MODEM_BEARER_LIST, &list,
NULL);
if (!list) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Bearer list unavailable");
return FALSE;
}
max = mm_bearer_list_get_max_active_multiplexed (list);
mm_bearer_list_foreach (list,
(MMBearerListForeachFunc)bearer_count_multiplexed_connected,
&count);
g_assert (!(!max && count));
if (out_max)
*out_max = max;
if (out_current)
*out_current = count;
return TRUE;
}
/*****************************************************************************/
gchar * gchar *
mm_broadband_modem_create_device_identifier (MMBroadbandModem *self, mm_broadband_modem_create_device_identifier (MMBroadbandModem *self,
const gchar *ati, const gchar *ati,
-6
View File
@@ -135,12 +135,6 @@ gboolean mm_broadband_modem_sim_hot_swap_ports_context_init (MMBroadbandModem
GError **error); GError **error);
void mm_broadband_modem_sim_hot_swap_ports_context_reset (MMBroadbandModem *self); void mm_broadband_modem_sim_hot_swap_ports_context_reset (MMBroadbandModem *self);
/* Helper to manage multiplexed bearers */
gboolean mm_broadband_modem_get_active_multiplexed_bearers (MMBroadbandModem *self,
guint *out_current,
guint *out_max,
GError **error);
/* Helper to manage initial EPS bearer */ /* Helper to manage initial EPS bearer */
gint mm_broadband_modem_get_initial_eps_bearer_cid (MMBroadbandModem *self); gint mm_broadband_modem_get_initial_eps_bearer_cid (MMBroadbandModem *self);
+68
View File
@@ -6784,6 +6784,74 @@ mm_iface_modem_get_current_modes (MMIfaceModem *self,
/*****************************************************************************/ /*****************************************************************************/
typedef struct {
const MMIfaceModemCountBearersFlags flags;
guint count;
} CountBearersContext;
static void
bearer_count (MMBaseBearer *bearer,
CountBearersContext *ctx)
{
MMBearerStatus status;
status = mm_base_bearer_get_status (MM_BASE_BEARER (bearer));
if (ctx->flags & MM_IFACE_MODEM_COUNT_BEARERS_FLAG_MULTIPLEXED) {
/* The Multiplexed property is only set if connected, so it's enough to check
* that one to see if we're connected and multiplexed */
if (mm_gdbus_bearer_get_multiplexed (MM_GDBUS_BEARER (bearer)))
ctx->count++;
} else if (ctx->flags & MM_IFACE_MODEM_COUNT_BEARERS_FLAG_CONNECTED) {
if (status == MM_BEARER_STATUS_CONNECTED)
ctx->count++;
} else if (ctx->flags & MM_IFACE_MODEM_COUNT_BEARERS_FLAG_ACTIVE) {
if (status >= MM_BEARER_STATUS_CONNECTING)
ctx->count++;
} else
ctx->count++;
}
gboolean
mm_iface_modem_count_bearers (MMIfaceModem *self,
MMIfaceModemCountBearersFlags flags,
guint *out_current,
guint *out_max,
GError **error)
{
g_autoptr(MMBearerList) list = NULL;
guint max = 0;
CountBearersContext ctx = {
.flags = flags,
.count = 0,
};
g_object_get (self,
MM_IFACE_MODEM_BEARER_LIST, &list,
NULL);
if (!list) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Bearer list unavailable");
return FALSE;
}
if (flags & MM_IFACE_MODEM_COUNT_BEARERS_FLAG_MULTIPLEXED)
max = mm_bearer_list_get_max_active_multiplexed (list);
else
max = mm_bearer_list_get_max_active (list);
mm_bearer_list_foreach (list, (MMBearerListForeachFunc)bearer_count, &ctx);
g_assert (max >= ctx.count);
if (out_max)
*out_max = max;
if (out_current)
*out_current = ctx.count;
return TRUE;
}
/*****************************************************************************/
static void static void
mm_iface_modem_default_init (MMIfaceModemInterface *iface) mm_iface_modem_default_init (MMIfaceModemInterface *iface)
{ {
+15
View File
@@ -622,4 +622,19 @@ void mm_iface_modem_process_sim_event (MMIfaceModem *self);
gboolean mm_iface_modem_is_primary_sim_slot_switch_ongoing (MMIfaceModem *self); gboolean mm_iface_modem_is_primary_sim_slot_switch_ongoing (MMIfaceModem *self);
typedef enum {
/* Connecting or connected bearers */
MM_IFACE_MODEM_COUNT_BEARERS_FLAG_ACTIVE = 0x1,
/* Fully connected bearers */
MM_IFACE_MODEM_COUNT_BEARERS_FLAG_CONNECTED = 0x2,
/* Multiplexed implies connected */
MM_IFACE_MODEM_COUNT_BEARERS_FLAG_MULTIPLEXED = 0x4,
} MMIfaceModemCountBearersFlags;
gboolean mm_iface_modem_count_bearers (MMIfaceModem *self,
MMIfaceModemCountBearersFlags flags,
guint *out_current,
guint *out_max,
GError **error);
#endif /* MM_IFACE_MODEM_H */ #endif /* MM_IFACE_MODEM_H */
+30 -3
View File
@@ -27,6 +27,7 @@ G_DEFINE_TYPE_EXTENDED (MMSleepContext, mm_sleep_context, G_TYPE_OBJECT, 0,
struct _MMSleepContextPrivate { struct _MMSleepContextPrivate {
GTask *task; GTask *task;
guint timeout_id; guint timeout_id;
gint64 timeout_start;
}; };
enum { enum {
@@ -52,6 +53,7 @@ timeout_cleanup (MMSleepContext *self)
if (self->priv->timeout_id) if (self->priv->timeout_id)
g_source_remove (self->priv->timeout_id); g_source_remove (self->priv->timeout_id);
self->priv->timeout_id = 0; self->priv->timeout_id = 0;
self->priv->timeout_start = 0;
} }
void void
@@ -95,6 +97,33 @@ operation_ready (MMSleepContext *self,
g_signal_emit (self, signals[DONE], 0, error); g_signal_emit (self, signals[DONE], 0, error);
} }
static void
timeout_add (MMSleepContext *self,
guint interval)
{
timeout_cleanup (self);
self->priv->timeout_start = g_get_monotonic_time ();
self->priv->timeout_id = g_timeout_add_seconds (interval,
(GSourceFunc)operation_timeout,
self);
}
void
mm_sleep_context_timeout_backoff (MMSleepContext *self,
guint more_seconds)
{
gint64 cur_time;
gint64 new_interval;
new_interval = more_seconds * G_USEC_PER_SEC;
if (self->priv->timeout_start) {
cur_time = g_get_monotonic_time ();
new_interval += (cur_time - self->priv->timeout_start);
}
timeout_add (self, new_interval / G_USEC_PER_SEC);
}
/*****************************************************************************/ /*****************************************************************************/
MMSleepContext * MMSleepContext *
@@ -107,9 +136,7 @@ mm_sleep_context_new (guint timeout_seconds)
NULL, NULL,
(GAsyncReadyCallback)operation_ready, (GAsyncReadyCallback)operation_ready,
NULL); NULL);
self->priv->timeout_id = g_timeout_add_seconds (timeout_seconds, timeout_add (self, timeout_seconds);
(GSourceFunc)operation_timeout,
self);
mm_obj_dbg (self, "new context with %d second timeout", timeout_seconds); mm_obj_dbg (self, "new context with %d second timeout", timeout_seconds);
return self; return self;
+3
View File
@@ -51,6 +51,9 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMSleepContext, g_object_unref)
MMSleepContext *mm_sleep_context_new (guint timeout_seconds); MMSleepContext *mm_sleep_context_new (guint timeout_seconds);
void mm_sleep_context_timeout_backoff (MMSleepContext *self,
guint more_seconds);
/* The MMSleepContext assumes ownership of @error */ /* The MMSleepContext assumes ownership of @error */
void mm_sleep_context_complete (MMSleepContext *self, void mm_sleep_context_complete (MMSleepContext *self,
GError *error); GError *error);