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:
@@ -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
|
||||
|
@@ -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.
|
||||
|
@@ -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),
|
||||
¤t_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,
|
||||
|
@@ -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),
|
||||
¤t_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)));
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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 */
|
||||
|
Reference in New Issue
Block a user