Age | Commit message (Collapse) | Author |
|
Signed-off-by: Lukas Voegl <lvoegl@tdt.de>
|
|
Users with QMI or MBIM capable modems may want to ensure that these
are never managed using plain AT commands, as that also involves using
PPP. This fallback to AT could happen if the QMI or MBIM port probing
fails for whatever reason.
The new `ID_MM_REQUIRED` udev tag allows specifying that a given port
MUST be successfully grabbed when creating a new modem object, or
otherwise the modem object will not be created at all (even if there
are other fallback control ports like AT that could have been used).
Use this tag with caution.
It is assumed that when this tag is used some other external process
may be monitoring the existence of the modem object in DBus as exposed
by ModemManager, and if it does not appear for any reason then the
modem would be reseted with some other mechanism (e.g. GPIOs, if
available). If no such mechanism to autorecover the modem is in place,
using this tag may leave the modem exposed in the kernel but ignored
by ModemManager.
This tag must be applied on the specific port for which the existence
and usability must be ensured.
E.g. flagging the MBIM port of the Fibocom L850 module as required:
$ vim /lib/udev/rules.d/78-mm-test.rules
ACTION!="add|change|move|bind", GOTO="mm_test_rules_end"
SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}"
ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0007", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_REQUIRED}="1"
LABEL="mm_test_rules_end"
$ sudo udevadm control --reload
$ sudo udevadm trigger
$ sudo udevadm info -p /sys/class/usbmisc/cdc-wdm0
...
E: ID_MM_REQUIRED=1
E: ID_MM_CANDIDATE=1
|
|
No users left for the getter that takes a reference after a port of
MMBaseModemAT to GTask.
peek_cancellable() is used instead, because the GTask constructor
takes a reference itself.
|
|
The 'link_ports' and 'ports' tables are created during object init(),
but they are fully removed and cleared during dispose(). Given that
the MMDevice executes an explicit g_object_run_dispose(), there may be
cases where a long-running operation that isn't cancelled ends up
being completed by the time the object disposal has already run at
least once.
That would end up crashing the process if we attempt to e.g. iterate
over one of the ports hash tables:
0x00007c3594eb3b93 (libglib-2.0.so.0 - ghash.c: 1180) g_hash_table_iter_next
0x00005b60d86f2563 (ModemManager - mm-base-modem.c: 1133) mm_base_modem_get_port_infos
0x00005b60d870228e (ModemManager - mm-iface-modem.c: 4013) fcc_unlock
0x00007c35950126a8 (libgio-2.0.so.0 - gtask.c: 1230) g_task_return_now
0x00007c35950116fa (libgio-2.0.so.0 - gtask.c: 1300) g_task_return
0x00007c3595011d12 (libgio-2.0.so.0 - gtask.c: 1930) g_task_return_new_error
0x00005b60d87518f2 (ModemManager - mm-broadband-modem-mbim.c: 1970) radio_state_set_up_ready
0x00007c35950126a8 (libgio-2.0.so.0 - gtask.c: 1230) g_task_return_now
0x00007c35950116fa (libgio-2.0.so.0 - gtask.c: 1300) g_task_return
0x00007c35950c486c (libmbim-glib.so.4 - mbim-device.c: 253) transaction_task_complete_and_free
0x00007c35950c714b (libmbim-glib.so.4 - mbim-device.c: 335) transaction_timed_out
0x00007c3594ec1232 (libglib-2.0.so.0 - gmain.c: 4971) g_timeout_dispatch
0x00007c3594ec43fc (libglib-2.0.so.0 - gmain.c: 3417) g_main_context_dispatch
0x00007c3594ec4704 (libglib-2.0.so.0 - gmain.c: 4211) g_main_context_iterate
0x00007c3594ec4978 (libglib-2.0.so.0 - gmain.c: 4411) g_main_loop_run
0x00005b60d86d7c56 (ModemManager - main.c: 217) main
0x00007c3594c526c5 (libc.so.6 + 0x000286c5) __libc_init_first
0x00007c3594c52781 (libc.so.6 + 0x00028781) __libc_start_main
0x00005b60d86d7970 (ModemManager + 0x00061970) _start
Fixes https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/677
Change-Id: I6695c284f86a196e60de7f714bc1671332d08848
|
|
This signal indicates that the port is no longer accessible. Unlike a
udev port removal event, this indication may happen even if the port
is still exposed by the system.
It is designed to detect protocol proxy crashes, and so when such
event is detected by the modem, a full reprobe of the device will be
done to start from scratch the protocol management operations.
|
|
|
|
==10719== Invalid free() / delete / delete[] / realloc()
==10719== at 0x4897D88: free (vg_replace_malloc.c:872)
==10719== by 0x52F091B: g_free (gmem.c:220)
==10719== by 0x530C36B: g_slice_free1 (gslice.c:1185)
==10719== by 0x52D632B: g_error_free (gerror.c:872)
==10719== by 0x192DBF: UnknownInlinedFun (glib-autocleanups.h:54)
==10719== by 0x192DBF: UnknownInlinedFun (glib-autocleanups.h:54)
==10719== by 0x192DBF: sync_ready (mm-base-modem.c:671)
==10719== by 0x50A82CB: g_task_return_now (gtask.c:1232)
==10719== by 0x50A854B: UnknownInlinedFun (gtask.c:1301)
==10719== by 0x50A854B: g_task_return (gtask.c:1258)
==10719== by 0x50AAA4F: g_task_return_new_error (gtask.c:1944)
==10719== by 0x1F44E3: iface_modem_sync_ready (mm-broadband-modem.c:12205)
==10719== by 0x50A82CB: g_task_return_now (gtask.c:1232)
==10719== by 0x50A854B: UnknownInlinedFun (gtask.c:1301)
==10719== by 0x50A854B: g_task_return (gtask.c:1258)
==10719== by 0x1AB86B: interface_syncing_step.lto_priv.0 (mm-iface-modem.c:4644)
==10719== Address 0x910bf30 is 0 bytes inside a block of size 16 free'd
==10719== at 0x4897D88: free (vg_replace_malloc.c:872)
==10719== by 0x52F091B: g_free (gmem.c:220)
==10719== by 0x530C36B: g_slice_free1 (gslice.c:1185)
==10719== by 0x52D632B: g_error_free (gerror.c:872)
==10719== by 0x17565F: UnknownInlinedFun (glib-autocleanups.h:54)
==10719== by 0x17565F: UnknownInlinedFun (glib-autocleanups.h:54)
==10719== by 0x17565F: base_modem_sync_ready (mm-base-manager.c:737)
==10719== by 0x50A82CB: g_task_return_now (gtask.c:1232)
==10719== by 0x50A854B: UnknownInlinedFun (gtask.c:1301)
==10719== by 0x50A854B: g_task_return (gtask.c:1258)
==10719== by 0x192DAB: sync_ready (mm-base-modem.c:674)
==10719== by 0x50A82CB: g_task_return_now (gtask.c:1232)
==10719== by 0x50A854B: UnknownInlinedFun (gtask.c:1301)
==10719== by 0x50A854B: g_task_return (gtask.c:1258)
==10719== by 0x50AAA4F: g_task_return_new_error (gtask.c:1944)
==10719== by 0x1F44E3: iface_modem_sync_ready (mm-broadband-modem.c:12205)
==10719== Block was alloc'd at
==10719== at 0x48952CC: malloc (vg_replace_malloc.c:381)
==10719== by 0x52F3EF3: g_malloc (gmem.c:127)
==10719== by 0x530CD27: g_slice_alloc (gslice.c:1074)
==10719== by 0x530D2B7: g_slice_alloc0 (gslice.c:1100)
==10719== by 0x52D5E7B: g_error_allocate (gerror.c:710)
==10719== by 0x52D690F: UnknownInlinedFun (gerror.c:724)
==10719== by 0x52D690F: g_error_new_valist (gerror.c:766)
==10719== by 0x50AAA43: g_task_return_new_error (gtask.c:1941)
==10719== by 0x1F44E3: iface_modem_sync_ready (mm-broadband-modem.c:12205)
==10719== by 0x50A82CB: g_task_return_now (gtask.c:1232)
==10719== by 0x50A854B: UnknownInlinedFun (gtask.c:1301)
==10719== by 0x50A854B: g_task_return (gtask.c:1258)
==10719== by 0x1AB86B: interface_syncing_step.lto_priv.0 (mm-iface-modem.c:4644)
==10719== by 0x1AB9A3: UnknownInlinedFun (mm-iface-modem.c:4543)
==10719== by 0x1AB9A3: interface_syncing_step.lto_priv.0 (mm-iface-modem.c:4639)
|
|
If any of the control ports ends up timing out 10 consecutive times,
the modem will be flagged as invalid and it will be reprobed from
scratch.
This allows us to detect modems that end up irresponsive in QMI or
MBIM while they're still exposed in e.g. the USB bus.
|
|
|
|
ModemManager handles suspend and resume signals sent from powerd
Fixes https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/547
|
|
Subsystem vendor ID can be used for identifying PCI modems,
so expose the property.
|
|
Commit b497de325 introduced a change by which some common errors (e.g.
SIM missing) would be reported as MM_CORE_ERROR_ABORTED.
This had the undesired effect of making the MMBaseModem object not
flag as valid the modem, because the returned error wasn't
MM_CORE_ERROR_WRONG_STATE.
We now change this logic so that only ABORTED makes the modem object
not flagged as valid, and we'll do that only if the Modem interface
isn't exposed in DBus.
Fixes b497de325
|
|
We no longer have separate mm_base_modem_process_sim_event() and
mm_broadband_modem_sim_hot_swap_detected() methods. The only
difference between both of them was that one of them would attempt to
cleanup the ports context associated to the SIM hot swap event logic
as soon as a swap was detected, in order to avoid queueing up multiple
such events.
The previous logic wasn't working well, though, as there could be
mixed AT+QMI or AT+MBIM devices that would also require that same
cleanup and so we didn't always know which one should have been
called.
Now we have a single mm_iface_modem_process_sim_event() method, which
will trigger the reprobe and disabling, but which will also perform
the cleanup of the SIM ports swap setup as specified by the
implementation.
So, if a plugin explicitly initializes the serial ports context for
SIM hot swap handling, it should also explicitly clean it up.
Also, the initialization of the serial ports context for SIM hot swap
handling is no longer done automatically for all modems, it will be
done only for those modems using it; i.e. the modems that explicitly
report support SIM hot swap handling using AT URCs.
|
|
There are devices with multiple AT ports where only one of them is
supposed to be used for GNSS control (and data).
|
|
|
|
The user may request to disable QRTR support using `--without-qrtr`
even if libqmi has QRTR support.
|
|
Required by MMPortQmi for fetching the TX and RX endpoint IDs
through sysfs from linux 5.14 onwards
|
|
|
|
|
|
The mm_base_modem_sync() method is an asynchronous method that
receives a callback and user data, and therefore we MUST always
complete the async method calling that callback. Set that up with a
GTask as usual.
Also, the mm_base_modem_sync_finish() method should be implemented
along with mm_base_modem_sync(), not in the source file of the
caller of the async method. The finish() always depends on how the
async method was implemented, in our case using a GTask.
|
|
Quick suspend/resume infrastructure for
synchronizing the interfaces when resuming.
|
|
Add support for the Linux wwan subsystem that started to expose
control channel as character devices (e.g. /dev/wwan0p1MBIM...).
Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
|
|
Add support for QRTR devices so modems can be created based on ports
using the QRTR subsystem.
|
|
The GLists maintained in the logic need to be explicitly freed (just
the lists, not the list contents) if we exit early on error or if we
end up deciding that the specific ports are available but unsupported
by the plugin (e.g. if a plugin that doesn't support net ports finds
net ports in the modem).
==225333== 24 bytes in 1 blocks are definitely lost in loss record 2,024 of 5,525
==225333== at 0x483E77F: malloc (vg_replace_malloc.c:307)
==225333== by 0x506C539: g_malloc (in /usr/lib/libglib-2.0.so.0.6600.7)
==225333== by 0x508DC8F: g_slice_alloc (in /usr/lib/libglib-2.0.so.0.6600.7)
==225333== by 0x50636B4: g_list_append (in /usr/lib/libglib-2.0.so.0.6600.7)
==225333== by 0x17E671: mm_base_modem_organize_ports (mm-base-modem.c:1298)
==225333== by 0x1E4409: mm_plugin_create_modem (mm-plugin.c:1094)
==225333== by 0x162C81: mm_device_create_modem (mm-device.c:481)
==225333== by 0x15DE60: device_support_check_ready (mm-base-manager.c:218)
==225333== by 0x4EA8173: ??? (in /usr/lib/libgio-2.0.so.0.6600.7)
==225333== by 0x4EAC6E8: ??? (in /usr/lib/libgio-2.0.so.0.6600.7)
==225333== by 0x16730F: device_context_run_ready (mm-plugin-manager.c:1533)
==225333== by 0x4EA8173: ??? (in /usr/lib/libgio-2.0.so.0.6600.7)
|
|
The MMPortQmi may need to know very early what kind of net ports are
going to be used later on during connection, e.g. to decide what kind
of multiplexing capabilities are available and such.
So, once we have organized ports in the modem, we'll take the driver
of the first network port in the list of data ports, and pass it down
to all QMI ports setup in the modem object.
|
|
When new link ports are created, the QmiDevice link management methods
try to make sure that the port exists in the system by the time the
link addition method returns, but that doesn't guarantee that the port
has also been notified by the kernel to ModemManager (e.g. via udev or
via kernel events).
This new method allows to do a explicit wait for a given port link; if
we already have it it will return right away, and otherwise we'll wait
for it to be notified via the "link port grabbed" signal.
|
|
We will grab the ports and make them available through find_ports() or
peek_port() or get_port().
The link ports are not 'organized' so they won't be available in
e.g. get_data_ports(), which is fine, because we don't want to mix
them with the real data ports exposed by the device.
Link port additions and removals are also notified via signals in the
modem object, so that explicit wait for specific ports can be done.
|
|
Right now just with the support to setup link properties like up/down
state or the link mtu.
This features are required when using QMAP based multiplexing with the
qmi_wwan kernel driver.
|
|
A modem that creates exclusively bearer objects that work with NET
ports (e.g. all QMI or MBIM modems) must not add any TTY port in the
list of data ports.
A modem that creates exclusively bearer objects that work with TTY
ports (e.g. the generic modem) must not add any NET port in the
list of data ports.
A modem that may use both TTY and NET ports should add all in the list
of data ports.
Fixes https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/324
Fixes https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/329
|
|
There's no point in returning a list of all ports with a given name,
just provide a lookup method that returns the single port with the
given name.
|
|
If the lock status cannot be read during a puk unblock attempt, reprobe
the modem. It is likely that the SIM was permanently blocked if the lock
status cannot be read.
|
|
When there are multiple ports with the same purpose (e.g. multiple net
data ports, or multiple QMI control ports), sort them by name by
default.
The port order does not make any difference for ports that have
flagged with a specific purpose (e.g. AT primary).
The sorting is done both in the internal lists and when looking up
ports with find_ports().
|
|
Most older Qualcomm SoCs (e.g. MSM8916, MSM8974, ...) communicate with
the integrated modem via shared memory (SMD channels). This is similar
to QRTR on newer SoCs, but without the "network" layer. In fact, the
older SoCs also have QRTR, but the modem QMI services are not exposed
there.
The mainline Linux kernel exposes SMD channels via the "remote processor
messaging bus" (rpmsg). Through special IOCTL calls it is possible to
create a char device for a rpmsg/SMD channel. We can then use these to
send QMI/AT messages to the modem, much like the ordinary serial char
devices when using a Qualcomm modem through USB.
This commit introduces support for the new 'rpmsg' subsystem, which
allows exporting QMI-capable and AT-capable ports.
By default NO rpmsg port is flagged as candidate, it is assumed that
the plugin adding support for the rpmsg subsystem will add specific
rules to do so (e.g. so that non-modem ports are explicitly not
flagged as candidate).
All rpmsg ports will be probed for AT or QMI capabilities, unless
explicit port type hints (e.g. ID_MM_PORT_TYPE_QMI or
ID_MM_PORT_TYPE_AT_PRIMARY) are set.
These changes are highly based on the initial integration work done by
Stephan Gerhold <stephan@gerhold.net> in postmarketOS, see:
https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/363
|
|
Back in Linux < 3.6 days, the cdc-wdm ports exposed by the QMI driver
were flagged as owned by the 'usb' subsystem. That changed in 3.6 when
the subsystem was renamed to 'usbmisc':
https://mail.gnome.org/archives/networkmanager-list/2012-June/msg00125.html
This patch removes all monitoring of the 'usb' subsystem completely,
which is anyway a valid subsystem but for which we shouldn't need any
special handling. Right now, with newer kernels, we were using that
monitoring exclusively to get notified of full USB device remove
events, which is really not required as we already process the port
removals one by one.
We simplify the logic everywhere that attempted to match either the
'usb' or 'usbmisc' subsystems, and we no longer require the explicit
checks for the port name being named 'cdc-wdm[0-9]*' in the code, as
that is already taken care of by the ID_MM_CANDIDATE udev tag rule.
|
|
We have assumed until now that all QMI ports are based on the
qmi_wwan driver, exposed in the 'usbmisc' subsystem by the cdc-wdm
driver.
This may no longer be true, so allow creating QMI ports with
an explicit subsystem instead of defaulting always to USBMISC.
|
|
We have assumed until now that all MBIM ports are based on the
cdc_mbim driver, exposed in the 'usbmisc' subsystem by the cdc-wdm
driver.
This may no longer be true, so allow creating MBIM ports with
an explicit subsystem instead of defaulting always to USBMISC.
|
|
We have assumed until now that all QCDM ports are based on TTY
drivers, e.g. exposed via USB.
This may no longer be true, so allow creating QCDM ports with
an explicit subsystem instead of defaulting always to TTY.
|
|
Split in its own method the per-subsystem port creation mechanism, and
apply all common AT port settings (e.g. response parser, flags) in a
single place.
|
|
Back in Linux < 3.6 days, the cdc-wdm ports exposed by the QMI driver
were flagged as owned by the 'usb' subsystem. That changed in 3.6 when
the subsystem was renamed to 'usbmisc':
https://mail.gnome.org/archives/networkmanager-list/2012-June/msg00125.html
So, rename the port subsystem type enumn to 'usbmisc'.
|
|
Move the logic out of the base modem, and make it applicable only for
QMI modems.
|
|
Move the logic out of the base modem, and make it applicable only for
MBIM modems.
|
|
So don't re-process them in the generic modem when grabbing the port.
|
|
So that the list of ports shown in the Ports DBus property is also
alphabetically sorted by port name, instead of having a mess like
this:
-----------------------------
System | device: qcom-soc
| drivers: bam-dmux
| plugin: qcom-soc
| primary port: rpmsg0
| ports: rmnet5 (net), rmnet_usb0 (unknown), rmnet4 (net),
| rpmsg1 (at), rmnet3 (net), rpmsg0 (qmi), rmnet2 (net), rmnet1 (net),
| rmnet7 (net), rmnet0 (net), rmnet6 (net)
|
|
At the moment, ignored ports show up as (unknown) in the ports list
in mmcli. This makes it look like something went wrong while probing.
Actually ModemManager already tracks unknown and ignored ports separately
(MM_PORT_TYPE_UNKNOWN vs MM_PORT_TYPE_IGNORED) but the API always exposes
them as MM_MODEM_PORT_TYPE_UNKNOWN.
Add MM_MODEM_PORT_TYPE_IGNORED and use this for ignored ports so they
show up as (ignored) instead in mmcli.
|
|
When the SIM switch doesn't happen as part of an async hot swap
detection, we should trigger the switch handling at base modem level,
which e.g. doesn't require explicit cleanup of the SIM hot swap
detection port context.
|
|
Also link all grabbed ports as owned by the modem.
|
|
|
|
mm-base-modem.c: In function ‘mm_base_modem_organize_ports’:
mm-base-modem.c:1088:9: error: enumeration value ‘MM_PORT_TYPE_UNKNOWN’ not handled in switch [-Werror=switch-enum]
1088 | switch (mm_port_get_port_type (candidate)) {
| ^~~~~~
mm-base-modem.c:1088:9: error: enumeration value ‘MM_PORT_TYPE_IGNORED’ not handled in switch [-Werror=switch-enum]
|
|
The auth provider is now a singleton (since 20ab6550), one single
object that lives throughout the whole program execution, and so we
don't need to keep our own full references around. This fix makes
sure we don't attempt to unref a full auth provider reference we
don't own.
Fixes https://gitlab.freedesktop.org/mobile-broadband/ModemManager/issues/179
|
|
The auth provider setup is a bit over-engineered. Simplify it by
making a single MMAuthProvider object that may or may not use polkit,
depending on configure options. This object is also setup as a
singleton object using the helper MM_DEFINE_SINGLETON_GETTER().
|