port-qmi: compute max amount of multiplexed links supported

For the qmi_wwan driver, we have imposed a limitation of max 4 links
when using the add_mux/del_mux interface, because we're forced to
precreate links before multiplexing may be enabled.

When using rmnet over qmi_wwan, or rmnet over other drivers, we don't
have any limitation other than the one imposed by the WDA protocol
itself. The amount of links that may be created in this case is
1 + (QMI_DEVICE_MUX_ID_MAX - QMI_DEVICE_MUX_ID_MIN).

This information is loaded in the MMPortQmi, used to create the
MMBearerList in the QMI modem, and finally populated in the
'MaxActiveMultiplexedBearers' property of the modem interface.
This commit is contained in:
Aleksander Morgado
2021-03-10 15:17:59 +01:00
parent 499d954857
commit 4f4ce02c43
3 changed files with 84 additions and 1 deletions
+33 -1
View File
@@ -332,6 +332,37 @@ modem_create_bearer (MMIfaceModem *self,
g_object_unref (task);
}
/*****************************************************************************/
/* Create Bearer List (Modem interface) */
static MMBearerList *
modem_create_bearer_list (MMIfaceModem *self)
{
MMPortQmi *port;
guint n;
guint n_multiplexed;
/* The maximum number of available/connected modems is guessed from
* the size of the data ports list. */
n = g_list_length (mm_base_modem_peek_data_ports (MM_BASE_MODEM (self)));
mm_obj_dbg (self, "allowed up to %u active bearers", n);
/* The maximum number of multiplexed links is retrieved from the
* MMPortQmi */
port = mm_broadband_modem_qmi_peek_port_qmi (MM_BROADBAND_MODEM_QMI (self));
if (!port) {
mm_obj_warn (self, "no port to query maximum number of supported network links");
n_multiplexed = 0;
} else {
n_multiplexed = mm_port_qmi_get_max_multiplexed_links (port);
mm_obj_dbg (self, "allowed up to %u active multiplexed bearers", n_multiplexed);
}
/* by default, no multiplexing support */
return mm_bearer_list_new (n, n_multiplexed);
}
/*****************************************************************************/
/* Manufacturer loading (Modem interface) */
@@ -10379,9 +10410,10 @@ iface_modem_init (MMIfaceModem *iface)
iface->setup_sim_hot_swap = mm_shared_qmi_setup_sim_hot_swap;
iface->setup_sim_hot_swap_finish = mm_shared_qmi_setup_sim_hot_swap_finish;
/* Create QMI-specific bearer */
/* Create QMI-specific bearer and bearer list */
iface->create_bearer = modem_create_bearer;
iface->create_bearer_finish = modem_create_bearer_finish;
iface->create_bearer_list = modem_create_bearer_list;
/* Other actions */
iface->reset = mm_shared_qmi_reset;
+50
View File
@@ -50,6 +50,7 @@ struct _MMPortQmiPrivate {
gboolean wda_unsupported;
QmiWdaLinkLayerProtocol llp;
QmiWdaDataAggregationProtocol dap;
guint max_multiplexed_links;
/* preallocated links */
MMPort *preallocated_links_master;
GArray *preallocated_links;
@@ -965,6 +966,12 @@ mm_port_qmi_get_data_aggregation_protocol (MMPortQmi *self)
return self->priv->dap;
}
guint
mm_port_qmi_get_max_multiplexed_links (MMPortQmi *self)
{
return self->priv->max_multiplexed_links;
}
/*****************************************************************************/
static QmiDeviceExpectedDataFormat
@@ -999,12 +1006,14 @@ load_kernel_data_format_capabilities (MMPortQmi *self,
QmiDevice *device,
gboolean *supports_802_3,
gboolean *supports_raw_ip,
gboolean *supports_qmap_raw_ip,
gboolean *supports_qmap_pass_through)
{
/* For any driver other than qmi_wwan, assume raw-ip */
if (mm_port_get_subsys (MM_PORT (self)) != MM_PORT_SUBSYS_USBMISC) {
*supports_802_3 = FALSE;
*supports_raw_ip = TRUE;
*supports_qmap_raw_ip = TRUE;
*supports_qmap_pass_through = FALSE;
return;
}
@@ -1014,10 +1023,19 @@ load_kernel_data_format_capabilities (MMPortQmi *self,
QMI_DEVICE_EXPECTED_DATA_FORMAT_RAW_IP,
NULL);
if (!*supports_raw_ip) {
*supports_qmap_raw_ip = FALSE;
*supports_qmap_pass_through = FALSE;
return;
}
/* We switch to raw-ip to see if we can do link management with qmi_wwan.
* This switch would not truly be required, but the logic afterwards is robust
* enough to support this, nothing to worry about */
if (qmi_device_set_expected_data_format (device, QMI_DEVICE_EXPECTED_DATA_FORMAT_RAW_IP, NULL))
*supports_qmap_raw_ip = qmi_device_check_link_supported (device, NULL);
else
*supports_qmap_raw_ip = FALSE;
*supports_qmap_pass_through = qmi_device_check_expected_data_format_supported (device,
QMI_DEVICE_EXPECTED_DATA_FORMAT_QMAP_PASS_THROUGH,
NULL);
@@ -1072,6 +1090,7 @@ typedef struct {
QmiDeviceExpectedDataFormat kernel_data_format_requested;
gboolean kernel_data_format_802_3_supported;
gboolean kernel_data_format_raw_ip_supported;
gboolean kernel_data_format_qmap_raw_ip_supported;
gboolean kernel_data_format_qmap_pass_through_supported;
gboolean link_management_supported;
@@ -1108,6 +1127,7 @@ internal_setup_data_format_finish (MMPortQmi *self,
QmiDeviceExpectedDataFormat *out_kernel_data_format,
QmiWdaLinkLayerProtocol *out_llp,
QmiWdaDataAggregationProtocol *out_dap,
guint *out_max_multiplexed_links,
GError **error)
{
InternalSetupDataFormatContext *ctx;
@@ -1120,6 +1140,32 @@ internal_setup_data_format_finish (MMPortQmi *self,
*out_llp = ctx->wda_llp_current;
g_assert (ctx->wda_dl_dap_current == ctx->wda_ul_dap_current);
*out_dap = ctx->wda_dl_dap_current;
if (out_max_multiplexed_links) {
if (!ctx->wda_dap_supported) {
*out_max_multiplexed_links = 0;
mm_obj_dbg (self, "wda data aggregation protocol unsupported: no multiplexed bearers allowed");
} else {
/* if multiplex backend may be rmnet, MAX-MIN */
if ((mm_port_get_subsys (MM_PORT (self)) != MM_PORT_SUBSYS_USBMISC) ||
ctx->kernel_data_format_qmap_pass_through_supported) {
*out_max_multiplexed_links = 1 + (QMI_DEVICE_MUX_ID_MAX - QMI_DEVICE_MUX_ID_MIN);
mm_obj_dbg (self, "rmnet link management supported: %u multiplexed bearers allowed",
*out_max_multiplexed_links);
}
/* if multiplex backend may be qmi_wwan, the max preallocated amount :/ */
else if ((mm_port_get_subsys (MM_PORT (self)) == MM_PORT_SUBSYS_USBMISC) &&
ctx->kernel_data_format_qmap_raw_ip_supported) {
*out_max_multiplexed_links = DEFAULT_LINK_PREALLOCATED_AMOUNT;
mm_obj_dbg (self, "qmi_wwan link management supported: %u multiplexed bearers allowed",
*out_max_multiplexed_links);
} else {
*out_max_multiplexed_links = 0;
mm_obj_dbg (self, "qmi_wwan link management unsupported: no multiplexed bearers allowed");
}
}
}
return TRUE;
}
@@ -1501,6 +1547,7 @@ internal_setup_data_format_context_step (GTask *task)
ctx->device,
&ctx->kernel_data_format_802_3_supported,
&ctx->kernel_data_format_raw_ip_supported,
&ctx->kernel_data_format_qmap_raw_ip_supported,
&ctx->kernel_data_format_qmap_pass_through_supported);
ctx->step++;
/* Fall through */
@@ -1703,6 +1750,7 @@ internal_setup_data_format_ready (MMPortQmi *self,
&self->priv->kernel_data_format,
&self->priv->llp,
&self->priv->dap,
NULL, /* not expected to update */
&error))
g_task_return_error (task, error);
else
@@ -1933,6 +1981,7 @@ qmi_device_open_second_ready (QmiDevice *qmi_device,
else
g_assert_not_reached ();
self->priv->dap = QMI_WDA_DATA_AGGREGATION_PROTOCOL_DISABLED;
self->priv->max_multiplexed_links = 0;
}
/* In both error and success, we go to last step */
@@ -1974,6 +2023,7 @@ open_internal_setup_data_format_ready (MMPortQmi *self,
&self->priv->kernel_data_format,
&self->priv->llp,
&self->priv->dap,
&self->priv->max_multiplexed_links,
&error)) {
/* Continue with fallback to LLP requested via CTL */
mm_obj_warn (self, "Couldn't setup data format: %s", error->message);
+1
View File
@@ -99,6 +99,7 @@ guint mm_port_qmi_get_endpoint_interface_number (MMPortQmi *self);
QmiWdaLinkLayerProtocol mm_port_qmi_get_link_layer_protocol (MMPortQmi *self);
QmiWdaDataAggregationProtocol mm_port_qmi_get_data_aggregation_protocol (MMPortQmi *self);
guint mm_port_qmi_get_max_multiplexed_links (MMPortQmi *self);
typedef enum {
MM_PORT_QMI_SETUP_DATA_FORMAT_ACTION_QUERY,