broadband-modem-qmi|mbim: allow limiting multiplexed links with udev tags

Certain QMI or MBIM devices may not be able to support multiplexing at
all, or they may support a limited amount of links.

The new ID_MM_MAX_MULTIPLEXED_LINKS udev tag allows specifying the
maximum number of supported multiplexed links; e.g. 0 to report none
supported or 1 to report that one single multiplexed link is
supported.
This commit is contained in:
Aleksander Morgado
2023-06-15 08:27:13 +00:00
parent 547d40009c
commit 3004a3e532
8 changed files with 174 additions and 15 deletions

View File

@@ -223,6 +223,7 @@ ID_MM_PORT_TYPE_MBIM
ID_MM_TTY_BAUDRATE ID_MM_TTY_BAUDRATE
ID_MM_TTY_FLOW_CONTROL ID_MM_TTY_FLOW_CONTROL
ID_MM_REQUIRED ID_MM_REQUIRED
ID_MM_MAX_MULTIPLEXED_LINKS
<SUBSECTION Deprecated> <SUBSECTION Deprecated>
ID_MM_TTY_BLACKLIST ID_MM_TTY_BLACKLIST
ID_MM_TTY_MANUAL_SCAN_ONLY ID_MM_TTY_MANUAL_SCAN_ONLY

View File

@@ -270,6 +270,23 @@
*/ */
#define ID_MM_REQUIRED "ID_MM_REQUIRED" #define ID_MM_REQUIRED "ID_MM_REQUIRED"
/**
* ID_MM_MAX_MULTIPLEXED_LINKS:
*
* This is a device-specific tag that allows users to specify the maximum amount
* of multiplexed links the modem supports.
*
* An integer value greater or equal than 0 must be given. The value 0 in this
* tag completely disables the multiplexing support in the device.
*
* This setting does nothing if the modem doesn't support multiplexing, or if the
* value configured is greater than the one specified by the modem itself (e.g.
* the control protocol in use also limits this value).
*
* Since: 1.22
*/
#define ID_MM_MAX_MULTIPLEXED_LINKS "ID_MM_MAX_MULTIPLEXED_LINKS"
/* /*
* The following symbols are deprecated. We don't add them to -compat * The following symbols are deprecated. We don't add them to -compat
* because this -tags file is not really part of the installed API. * because this -tags file is not really part of the installed API.

View File

@@ -1221,10 +1221,19 @@ load_settings_from_bearer (MMBearerMbim *self,
{ {
MMBearerMultiplexSupport multiplex; MMBearerMultiplexSupport multiplex;
gboolean multiplex_supported = TRUE; gboolean multiplex_supported = TRUE;
guint current_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),
&current_multiplexed_bearers,
&max_multiplexed_bearers,
error))
return FALSE;
/* Check multiplex support in the kernel and the device */
data_port_driver = mm_kernel_device_get_driver (mm_port_peek_kernel_device (ctx->data)); data_port_driver = mm_kernel_device_get_driver (mm_port_peek_kernel_device (ctx->data));
if (!g_strcmp0 (data_port_driver, "mhi_net")) if (!g_strcmp0 (data_port_driver, "mhi_net") || !max_multiplexed_bearers)
multiplex_supported = FALSE; multiplex_supported = FALSE;
/* If no multiplex setting given by the user, assume none */ /* If no multiplex setting given by the user, assume none */
@@ -1236,17 +1245,32 @@ load_settings_from_bearer (MMBearerMbim *self,
multiplex = MM_BEARER_MULTIPLEX_SUPPORT_NONE; multiplex = MM_BEARER_MULTIPLEX_SUPPORT_NONE;
} }
if (multiplex_supported && /* If multiplex unsupported, either abort or default to none */
(multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUESTED || if (!multiplex_supported) {
multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUIRED)) { if (multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUIRED) {
/* the link prefix hint given must be modem-specific */ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
ctx->link_prefix_hint = g_strdup_printf ("mbimmux%u.", mm_base_modem_get_dbus_id (MM_BASE_MODEM (ctx->modem))); "Multiplexing required but not supported");
return FALSE;
}
if (multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUESTED) {
mm_obj_dbg (self, "Multiplexing unsupported");
multiplex = MM_BEARER_MULTIPLEX_SUPPORT_NONE;
}
} }
if (!multiplex_supported && multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUIRED) { /* Go on with multiplexing enabled */
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, if (multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUESTED ||
"Multiplexing required but not supported by %s", data_port_driver); multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUIRED) {
return FALSE; g_assert (multiplex_supported);
if (current_multiplexed_bearers == max_multiplexed_bearers) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Maximum number of multiplexed bearers reached");
return FALSE;
}
/* the link prefix hint given must be modem-specific */
ctx->link_prefix_hint = g_strdup_printf ("mbimmux%u.", mm_base_modem_get_dbus_id (MM_BASE_MODEM (ctx->modem)));
} }
/* If profile id is given, we'll load all settings from the stored profile, /* If profile id is given, we'll load all settings from the stored profile,

View File

@@ -2442,8 +2442,21 @@ load_settings_from_bearer (MMBearerQmi *self,
GError *inner_error = NULL; GError *inner_error = NULL;
const gchar *str; const gchar *str;
const gchar *data_port_driver; const gchar *data_port_driver;
guint current_multiplexed_bearers;
guint max_multiplexed_bearers;
gboolean multiplex_supported = TRUE;
if (!mm_broadband_modem_get_active_multiplexed_bearers (MM_BROADBAND_MODEM (ctx->modem),
&current_multiplexed_bearers,
&max_multiplexed_bearers,
error))
return FALSE;
/* Check multiplex support in the kernel and the device */
data_port_driver = mm_kernel_device_get_driver (mm_port_peek_kernel_device (ctx->data)); data_port_driver = mm_kernel_device_get_driver (mm_port_peek_kernel_device (ctx->data));
/* All drivers should support multiplexing */
if (!max_multiplexed_bearers)
multiplex_supported = FALSE;
/* If no multiplex setting given by the user, assume none; unless in IPA */ /* If no multiplex setting given by the user, assume none; unless in IPA */
ctx->multiplex = mm_bearer_properties_get_multiplex (properties); ctx->multiplex = mm_bearer_properties_get_multiplex (properties);
@@ -2456,9 +2469,31 @@ load_settings_from_bearer (MMBearerQmi *self,
ctx->multiplex = MM_BEARER_MULTIPLEX_SUPPORT_NONE; ctx->multiplex = MM_BEARER_MULTIPLEX_SUPPORT_NONE;
} }
/* The link prefix hint given must be modem-specific */ /* If multiplex unsupported, either abort or default to none */
if (!multiplex_supported) {
if (ctx->multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUIRED) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Multiplexing required but not supported");
return FALSE;
}
if (ctx->multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUESTED) {
mm_obj_dbg (self, "Multiplexing unsupported");
ctx->multiplex = MM_BEARER_MULTIPLEX_SUPPORT_NONE;
}
}
/* Go on with multiplexing enabled */
if (ctx->multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUESTED || if (ctx->multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUESTED ||
ctx->multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUIRED) { ctx->multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUIRED) {
g_assert (multiplex_supported);
if (current_multiplexed_bearers == max_multiplexed_bearers) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Maximum number of multiplexed bearers reached");
return FALSE;
}
/* The link prefix hint given must be modem-specific */
ctx->link_prefix_hint = g_strdup_printf ("qmapmux%u.", mm_base_modem_get_dbus_id (MM_BASE_MODEM (modem))); ctx->link_prefix_hint = g_strdup_printf ("qmapmux%u.", mm_base_modem_get_dbus_id (MM_BASE_MODEM (modem)));
} }

View File

@@ -29,6 +29,7 @@
#include "mm-sms-mbim.h" #include "mm-sms-mbim.h"
#include "ModemManager.h" #include "ModemManager.h"
#include <ModemManager-tags.h>
#include "mm-context.h" #include "mm-context.h"
#include "mm-log-object.h" #include "mm-log-object.h"
#include "mm-errors-types.h" #include "mm-errors-types.h"
@@ -2957,8 +2958,9 @@ modem_create_bearer (MMIfaceModem *self,
static MMBearerList * static MMBearerList *
modem_create_bearer_list (MMIfaceModem *self) modem_create_bearer_list (MMIfaceModem *self)
{ {
guint n; MMPortMbim *port;
guint n_multiplexed; guint n;
guint n_multiplexed;
/* The maximum number of available/connected modems is guessed from /* The maximum number of available/connected modems is guessed from
* the size of the data ports list. */ * the size of the data ports list. */
@@ -2969,6 +2971,21 @@ modem_create_bearer_list (MMIfaceModem *self)
n_multiplexed = (MBIM_DEVICE_SESSION_ID_MAX - MBIM_DEVICE_SESSION_ID_MIN + 1); n_multiplexed = (MBIM_DEVICE_SESSION_ID_MAX - MBIM_DEVICE_SESSION_ID_MIN + 1);
mm_obj_dbg (self, "allowed up to %u active multiplexed bearers", n_multiplexed); mm_obj_dbg (self, "allowed up to %u active multiplexed bearers", n_multiplexed);
port = mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (self));
if (port &&
mm_kernel_device_has_global_property (mm_port_peek_kernel_device (MM_PORT (port)),
ID_MM_MAX_MULTIPLEXED_LINKS)) {
guint n_multiplexed_limited;
n_multiplexed_limited = mm_kernel_device_get_global_property_as_int (
mm_port_peek_kernel_device (MM_PORT (port)),
ID_MM_MAX_MULTIPLEXED_LINKS);
if (n_multiplexed_limited < n_multiplexed) {
n_multiplexed = n_multiplexed_limited;
mm_obj_dbg (self, "limited to %u active multiplexed bearers", n_multiplexed);
}
}
/* by default, no multiplexing support */ /* by default, no multiplexing support */
return mm_bearer_list_new (n, n_multiplexed); return mm_bearer_list_new (n, n_multiplexed);
} }

View File

@@ -27,6 +27,7 @@
#include "mm-broadband-modem-qmi.h" #include "mm-broadband-modem-qmi.h"
#include "ModemManager.h" #include "ModemManager.h"
#include <ModemManager-tags.h>
#include "mm-log.h" #include "mm-log.h"
#include "mm-errors-types.h" #include "mm-errors-types.h"
#include "mm-modem-helpers.h" #include "mm-modem-helpers.h"
@@ -435,10 +436,22 @@ modem_create_bearer_list (MMIfaceModem *self)
} }
if (kernel_data_modes & (MM_PORT_QMI_KERNEL_DATA_MODE_MUX_RMNET | MM_PORT_QMI_KERNEL_DATA_MODE_MUX_QMIWWAN)) { if (kernel_data_modes & (MM_PORT_QMI_KERNEL_DATA_MODE_MUX_RMNET | MM_PORT_QMI_KERNEL_DATA_MODE_MUX_QMIWWAN)) {
/* The maximum number of multiplexed links is retrieved from the /* The maximum number of multiplexed links is retrieved from the MMPortQmi */
* MMPortQmi */
n_multiplexed = mm_port_qmi_get_max_multiplexed_links (port); n_multiplexed = mm_port_qmi_get_max_multiplexed_links (port);
mm_obj_dbg (self, "allowed up to %u active multiplexed bearers", n_multiplexed); mm_obj_dbg (self, "allowed up to %u active multiplexed bearers", n_multiplexed);
if (mm_kernel_device_has_global_property (mm_port_peek_kernel_device (MM_PORT (port)),
ID_MM_MAX_MULTIPLEXED_LINKS)) {
guint n_multiplexed_limited;
n_multiplexed_limited = mm_kernel_device_get_global_property_as_int (
mm_port_peek_kernel_device (MM_PORT (port)),
ID_MM_MAX_MULTIPLEXED_LINKS);
if (n_multiplexed_limited < n_multiplexed) {
n_multiplexed = n_multiplexed_limited;
mm_obj_dbg (self, "limited to %u active multiplexed bearers", n_multiplexed);
}
}
} }
} }

View File

@@ -12860,6 +12860,52 @@ 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,

View File

@@ -134,4 +134,10 @@ 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);
#endif /* MM_BROADBAND_MODEM_H */ #endif /* MM_BROADBAND_MODEM_H */