Age | Commit message (Collapse) | Author |
|
Mainly because we need somewhere to stash the call end regex, and
it's silly to have a 3rd instance of that in MMPortSerialAt when
we already have one in the serial parsers that MMPortSerialAt
relies on pretty heavily.
Signed-off-by: Dan Williams <dan@ioncontrol.co>
|
|
Continues removing usage of MMBaseModem in a bunch of files
by splitting out bits of its usage to separate interfaces.
Signed-off-by: Dan Williams <dan@ioncontrol.co>
|
|
Rather than make all of them rely on MMBaseModem for it. This
lets us disentangle dependencies for easier unit testing.
For interfaces, rather than casting directly to MMBaseModem
use intermediate interfaces (MMIfaceAuth and MMIfaceOpLock)
that tests can fake out.
Signed-off-by: Dan Williams <dan@ioncontrol.co>
|
|
The bypass when in testcase mode has nothing to do with the base modem
class; so make it generic.
Signed-off-by: Dan Williams <dan@ioncontrol.co>
|
|
base_modem_invalid_idle() needs to keep a reference to the
MMBaseModem until its done. But if the modem is cancelled during
removal right before we're trying to forget about it, keeping
that reference can prevent everything getting cleaned up by
MMBaseModem's dispose() until after the mainloop has run again
and all our removal operations are supposedly complete.
MMDevice uses an explicit dispose() trigger that mitigates
most of this (and requires it for other reasons, like breaking
reference cycles between the modem and it's various child
classes) but it's somewhat error-prone to keep the modem
around if we don't really need to.
Signed-off-by: Dan Williams <dan@ioncontrol.co>
|
|
Signed-off-by: Dan Williams <dan@ioncontrol.co>
|
|
Signed-off-by: Dan Williams <dan@ioncontrol.co>
|
|
Expose a new list of 'IgnoredPorts' via D-Bus and therefore remove the use of `MM_MODEM_PORT_TYPE_IGNORED`
Signed-off-by: Lukas Voegl <lvoegl@tdt.de>
|
|
Subsystem device ID can be used for identifying PCI modems,
so expose the property.
Signed-off-by: Sushrut Shree Trivedi <quic_sushruts@quicinc.com>
|
|
If we are going to inhibit the modem or fully reprobe it after a SIM
switch event, we should forbid further operations done with the modem
object.
This logic can be tested by queing different operations one after the
other, and then adding a last device inhibition ("override" operation)
that should trigger the early abort of all non-running operations,
e.g.:
mmcli -m a -e &
sleep 0.2
mmcli -m a --3gpp-set-initial-eps-bearer-settings="apn=internet,ip-type=ipv4v6,force=true" &
sleep 0.2
mmcli -m a -d &
sleep 0.2
mmcli -m a -e &
sleep 0.2
mmcli -m a --set-power-state-low &
sleep 0.2
mmcli -m a -e &
sleep 0.2
mmcli -m a --inhibit
This previous sequence produces MM logs as follows:
<dbg> [1726567756.430308] [modem0] [operation 22] default - enable: scheduled
<dbg> [1726567756.430806] [modem0] [operation 22] default - enable: lock acquired
<dbg> [1726567756.623746] [modem0] [operation 23] default - set-initial-eps-bearer-settings: scheduled
<dbg> [1726567756.751743] [modem0] [operation 22] default - enable: lock released
<dbg> [1726567756.752027] [modem0] [operation 23] default - set-initial-eps-bearer-settings: lock acquired
<dbg> [1726567756.823739] [modem0] [operation 24] default - disable: scheduled
<dbg> [1726567757.049581] [modem0] [operation 25] default - enable: scheduled
<dbg> [1726567757.250165] [modem0] [operation 26] default - set-power-state: scheduled
<dbg> [1726567757.450518] [modem0] [operation 27] default - enable: scheduled
<dbg> [1726567757.676362] [modem0] [operation 28] override - disabling: override requested - no new operations will be allowed
<dbg> [1726567757.678792] [modem0] [operation 24] default - disable: aborted early
<dbg> [1726567757.679866] [modem0] [operation 25] default - enable: aborted early
<dbg> [1726567757.680157] [modem0] [operation 26] default - set-power-state: aborted early
<dbg> [1726567757.680496] [modem0] [operation 27] default - enable: aborted early
<dbg> [1726567759.695780] [modem0] [operation 23] default - set-initial-eps-bearer-settings: lock released
<dbg> [1726567759.695935] [modem0] [operation 28] override - disabling: lock acquired
<dbg> [1726567759.872196] [modem0] [operation 28] override - disabling: lock released
|
|
If a request to lock the operation with the override type arrives, all
pending operations will be immediately cancelled, and no new lock
requests will be allowed.
|
|
Each of these now holds an exclusive lock, so all these operations are
synchronized.
This logic can be tested by queing different enable/disable operations
one after the other, e.g.:
mmcli -m a -d & --> Disable 1
sleep 0.2
mmcli -m a -e & --> Enable 1
sleep 0.2
mmcli -m a -e & --> Enable 2
sleep 0.2
mmcli -m a -d & --> Disable 2
sleep 0.2
mmcli -m a -e & --> Enable 3
sleep 0.2
mmcli -m a -d & --> Disable 3
This previous sequence produces MM logs as follows:
<dbg> [1726566352.936025] [modem0] [operation 9] default - disable: scheduled --> Disable 1 requested
<dbg> [1726566352.936399] [modem0] [operation 9] default - disable: lock acquired --> Disable 1 started
<dbg> [1726566353.136445] [modem0] [operation 10] default - enable: scheduled --> Enable 1 requested
<dbg> [1726566353.202980] [modem0] [operation 9] default - disable: lock released --> Disable 1 finished
<dbg> [1726566353.203526] [modem0] [operation 10] default - enable: lock acquired --> Enable 1 started
<dbg> [1726566353.320057] [modem0] [operation 11] default - enable: scheduled --> Enable 2 requested
<dbg> [1726566353.440931] [modem0] [operation 10] default - enable: lock released --> Enable 1 finished
<dbg> [1726566353.443238] [modem0] [operation 11] default - enable: lock acquired --> Enable 2 started
<dbg> [1726566353.452984] [modem0] [operation 11] default - enable: lock released --> Enable 2 finished
<dbg> [1726566353.517512] [modem0] [operation 12] default - disable: scheduled --> Disable 2 requested
<dbg> [1726566353.517699] [modem0] [operation 12] default - disable: lock acquired --> Disable 2 started
<dbg> [1726566353.688695] [modem0] [operation 12] default - disable: lock released --> Disable 2 finished
<dbg> [1726566353.718237] [modem0] [operation 13] default - enable: scheduled --> Enable 3 requested
<dbg> [1726566353.718417] [modem0] [operation 13] default - enable: lock acquired --> Enable 3 started
<dbg> [1726566353.937122] [modem0] [operation 14] default - disable: scheduled --> Disable 3 requested
<dbg> [1726566353.970791] [modem0] [operation 13] default - enable: lock released --> Enable 3 finished
<dbg> [1726566353.970964] [modem0] [operation 14] default - disable: lock acquired --> Disable 3 started
<dbg> [1726566354.170938] [modem0] [operation 14] default - disable: lock released --> Disable 3 finished
|
|
Follow up changes will introduce support to run exclusive enable and
disable operations, effectively ensuring that only one enabling or
disabling task is processed at any given time, so the support for
completing parallel operations with the same result is no longer
needed.
That logic was anyway flawed, as it did not consider complex cases
like a disable request received between two enable requests, the order
of incoming requests was not maintained.
The main reason for adding the parallel enable/disable operation logic
was for the case where 2 separate users tried to enable the modem at
the same time. In that case, we did not want to run 2 separate
enabling operations from scratch, and completing one would complete
the second one as well. With the new operation lock logic, the same
result is achieved, as the 2nd enabling operation would find the modem
already enabled, if the 1st one succeeded.
This removal is done before introducing the new exclusive operation
support in the enable/disable path in order to make it easier and more
consistent with other operations that will also be included in the
synchronization.
|
|
There are certain operations that cannot be run in parallel, e.g. one
should not disable and bring the modem to low power mode while there
are also incoming requests to enable the modem. This type of errors
will typically happen when multiple DBus clients are trying to use the
same modem at the same time for different purposes.
We do not have any way to have DBus clients take exclusive ownership
of a given modem object, so the best we can do for now is trying to
synchronize operations that cannot be run together, preserving the
order in which they arrived, and running them one by one.
|
|
|
|
So that plugins can provide their own implementations as needed.
|
|
When we don't care about the type of AT port to use, prefer the QMI or
MBIM based ones if any available.
|
|
There are cases where the user wants to configure some actions
to be run on a modem before ModemManager takes over full control.
The new "modem setup" dispatcher scripts allow running operations
in the modem after the port probing has happened and we know which
ports are usable in the device.
The scripts may e.g. change device configuration, enable modem
logging infrastructure, or any other process that would otherwise
conflict with MM's own modem management operations.
|
|
|
|
|
|
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.
|