aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksandermj@chromium.org>2023-06-15 08:27:13 +0000
committerAleksander Morgado <aleksandermj@chromium.org>2023-06-16 20:58:04 +0000
commit3004a3e53263625da0b26e50c9107f1bad5b371e (patch)
treee9377da944a3ec31e6b297d407716a998f8928fd /src
parent547d40009c665d523e15cabfee028fc2604660dd (diff)
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.
Diffstat (limited to 'src')
-rw-r--r--src/mm-bearer-mbim.c44
-rw-r--r--src/mm-bearer-qmi.c37
-rw-r--r--src/mm-broadband-modem-mbim.c21
-rw-r--r--src/mm-broadband-modem-qmi.c17
-rw-r--r--src/mm-broadband-modem.c46
-rw-r--r--src/mm-broadband-modem.h6
6 files changed, 156 insertions, 15 deletions
diff --git a/src/mm-bearer-mbim.c b/src/mm-bearer-mbim.c
index fc434c78..e956a90d 100644
--- a/src/mm-bearer-mbim.c
+++ b/src/mm-bearer-mbim.c
@@ -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,17 +1245,32 @@ 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) {
- g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
- "Multiplexing required but not supported by %s", data_port_driver);
- return FALSE;
+ /* 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,
+ "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,
diff --git a/src/mm-bearer-qmi.c b/src/mm-bearer-qmi.c
index caf925db..54f2e934 100644
--- a/src/mm-bearer-qmi.c
+++ b/src/mm-bearer-qmi.c
@@ -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)));
}
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c
index 48a235a9..81c81da0 100644
--- a/src/mm-broadband-modem-mbim.c
+++ b/src/mm-broadband-modem-mbim.c
@@ -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,8 +2958,9 @@ modem_create_bearer (MMIfaceModem *self,
static MMBearerList *
modem_create_bearer_list (MMIfaceModem *self)
{
- guint n;
- guint n_multiplexed;
+ MMPortMbim *port;
+ guint n;
+ guint n_multiplexed;
/* The maximum number of available/connected modems is guessed from
* 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);
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);
}
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index 95cc56b0..153b420e 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -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);
+ }
+ }
}
}
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index c733d938..d3892456 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -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,
diff --git a/src/mm-broadband-modem.h b/src/mm-broadband-modem.h
index d2ce65a5..e6463de6 100644
--- a/src/mm-broadband-modem.h
+++ b/src/mm-broadband-modem.h
@@ -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 */