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_FLOW_CONTROL
ID_MM_REQUIRED
ID_MM_MAX_MULTIPLEXED_LINKS
<SUBSECTION Deprecated>
ID_MM_TTY_BLACKLIST
ID_MM_TTY_MANUAL_SCAN_ONLY

View File

@@ -270,6 +270,23 @@
*/
#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
* 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;
gboolean multiplex_supported = TRUE;
guint current_multiplexed_bearers;
guint max_multiplexed_bearers;
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));
if (!g_strcmp0 (data_port_driver, "mhi_net"))
if (!g_strcmp0 (data_port_driver, "mhi_net") || !max_multiplexed_bearers)
multiplex_supported = FALSE;
/* If no multiplex setting given by the user, assume none */
@@ -1236,19 +1245,34 @@ load_settings_from_bearer (MMBearerMbim *self,
multiplex = MM_BEARER_MULTIPLEX_SUPPORT_NONE;
}
if (multiplex_supported &&
(multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUESTED ||
multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUIRED)) {
/* 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 multiplex unsupported, either abort or default to none */
if (!multiplex_supported) {
if (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 (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 */
if (multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUESTED ||
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,
"Multiplexing required but not supported by %s", data_port_driver);
"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,
* so ignore any other setting received in the bearer properties */
ctx->profile_id = mm_bearer_properties_get_profile_id (properties);

View File

@@ -2442,8 +2442,21 @@ load_settings_from_bearer (MMBearerQmi *self,
GError *inner_error = NULL;
const gchar *str;
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));
/* 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 */
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;
}
/* 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 ||
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)));
}

View File

@@ -29,6 +29,7 @@
#include "mm-sms-mbim.h"
#include "ModemManager.h"
#include <ModemManager-tags.h>
#include "mm-context.h"
#include "mm-log-object.h"
#include "mm-errors-types.h"
@@ -2957,6 +2958,7 @@ modem_create_bearer (MMIfaceModem *self,
static MMBearerList *
modem_create_bearer_list (MMIfaceModem *self)
{
MMPortMbim *port;
guint n;
guint n_multiplexed;
@@ -2969,6 +2971,21 @@ modem_create_bearer_list (MMIfaceModem *self)
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);
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 */
return mm_bearer_list_new (n, n_multiplexed);
}

View File

@@ -27,6 +27,7 @@
#include "mm-broadband-modem-qmi.h"
#include "ModemManager.h"
#include <ModemManager-tags.h>
#include "mm-log.h"
#include "mm-errors-types.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)) {
/* The maximum number of multiplexed links is retrieved from the
* MMPortQmi */
/* The maximum number of multiplexed links is retrieved from the MMPortQmi */
n_multiplexed = mm_port_qmi_get_max_multiplexed_links (port);
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 *
mm_broadband_modem_create_device_identifier (MMBroadbandModem *self,
const gchar *ati,

View File

@@ -134,4 +134,10 @@ gboolean mm_broadband_modem_sim_hot_swap_ports_context_init (MMBroadbandModem
GError **error);
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 */