If the command we're sending doesn't have a callback, don't try
to call NULL. Triggered if the port got closed (because the modem
crashed, or refcounting errors or whatever) with some code like this:
mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "+CREG=0", 3, NULL, NULL);
Reporting errors instead of just returning permits routines like
mm-generic-gsm.c:simple_get_status() to work again, as their callbacks
get the error they are expecting. To make this work, adapt get_csq_done()
to handle a NULL response when error is set, and make sure that multiple
errors don't step on each other in the mm_callback_info_chain() sequence
created by simple_get_status().
Change-Id: Ie3a72b1ce71b7f117e8b1f3da7a406c4d2da9e02
Otherwise, we can schedule a main loop call to
mm_serial_port_queue_process() for an object that's about to
disappear, leading to a crash.
Change-Id: I433a76855c52536eb2b99a5ecf26ac71afe1f8bb
Fix one more possible memory leak (left un-fixed by d3c2228 but not
caused by it) and ensure that modems that do want flashing get it
by default by adding the missing G_PARAM_CONSTRUCT so FLASH_OK
defaults to TRUE.
Flashing is a technique to break out of the data/PPP stream and
re-enter command stream (like +++) and MM uses it in the generic
paths in various cases. But devices that don't need it (ie, ones
with at least one AT capable port that won't be used for data)
now sometimes appear to have side-effects.
The Ericsson F5521gw firmware R2A07 resets port attributes like
echo and &C and such when the port is flashed, leading to
confusion on the part of MM. Since the Ericsson devices will
always have at least one free AT port they don't need flashing
anyway.
1) use cfsetispeed/cfsetospeed like the TTY manpage suggests
2) ignore parity/framing errors since we're not using parity anyway
3) double-check that all our TTY settings were successfully set
This feature is initially disabled for all modems, but plugins can enable it by
setting a value greater than 0 for the "max-timeouts" property when creating the
modem object.
Make sure all pending work, if any, is torn down when closing
the port, since it's closed, and is likely going to get unreffed
soon and we don't want anything running after the port is dead.
It's only used during probing where some port types (Sierra CnS
and some Icera devices) may send streams of data that we can't
understand until we close the port. It interferes with some SMS
operations, so turn it off for ports opened after probing.
If a port returns EAGAIN on write attempts, previously the code would
spin and attempt to resend the failed byte after send_delay
microseconds. This resulted in up to 3 second hard blocks in
the serial code when sending to ports that don't respond. While
in this blocking loop no other events or dbus commands could be
processed.
Instead, send each byte and reschedule sending the next byte in
send_delay microseconds, so that we can process other events in between
attempts to write to stupid ports.
This doesn't hugely decrease the amount of time that probing
requires, since we still need to probe all ports of the device
before exporting the modem to D-Bus, but it does let MM find
responsive ports much more quickly, and ensures that MM doesn't
block any D-Bus requests.
This is the real fix for 81d0fd148f.
Some devices don't interact well with the option driver or the usb-serial
layer; they don't respond to the USB data requests and thus data never
gets written to that port. When close(2) is called, that data is still
pending and so the tty layer waits 30 seconds before returning from
the close. This is the 'closing_wait' value, which unfortunately is
not able to be modified by ModemManager because most serial drivers
for 3G devices don't implement the .ioctl handler or its TCIOSSERIAL
option to change closing_wait.
This goes along with a kernel patch to various drivers to enable
the TIOCSSERIAL ioctl to modify closing_wait which will be posted
soon.
Some devices don't interact well with the option drivr or the usb-serial
layer; they don't respond to the USB data requests and thus data never
gets written to that port. When close(2) is called, that data is still
pending and so the tty layer waits 30 seconds before returning from
the close. This is the 'closing_wait' value, which unfortunately is
not able to be modified by ModemManager because most serial drivers
for 3G devices don't implement the .ioctl handler or its TCIOSSERIAL
option to change closing_wait.
Print out open/close timestamps to help debug this issue and get a
list of modems that have this problem.
The flash function could be called when the port was closed, and since
the flash function would only be canceled when the port was open,
it could trigger after the port object was destroyed.
This specifically fixes a regression with Novatel GSM secondary
AT port enablement, where the inital pin check closed the port
before the Novatel plugin could send the command to flip secondary
ports to AT mode.
But it's useful elsewhere too, and simplifies a bunch of the PIN
checking code which had to use various ugly methods to track whether
to close the port or not after checking the PIN.
Some ports we know we shouldn't use when we get certain responses
from them. Reading from these ports triggers kernel bugs (at least
on 2.6.31 and 2.6.32) relating to flow control in some drivers
(*cough* hso *cough*), so lets try not to aggravate the kernel too
much. This happens on Icera-based Option devices like the GI0322
(AT&T Quicksilver) for example.
(note: AFAICT this doesn't have any relation to the recent XON/XOFF
patch, since I get this problem without the XON/XOFF patch on both
2.6.31 and 2.6.32 as well)
---
BUG: sleeping function called from invalid context at kernel/mutex.c:94
in_atomic(): 1, irqs_disabled(): 1, pid: 9295, name: modem-manager
Pid: 9295, comm: modem-manager Not tainted 2.6.32.9-67.fc12.x86_64 #1
Call Trace:
<IRQ> [<ffffffff81045d41>] __might_sleep+0xed/0xef
[<ffffffff81454dd0>] mutex_lock+0x24/0x50
[<ffffffff8104811e>] ? enqueue_task_fair+0x2a/0x6d
[<ffffffff812af79f>] tty_throttle+0x1b/0x49
[<ffffffff812af0d9>] n_tty_receive_buf+0xdbb/0xe12
[<ffffffff810459fd>] ? task_rq_unlock+0x11/0x13
[<ffffffff81050c5c>] ? try_to_wake_up+0x2f3/0x305
[<ffffffff8110de0c>] ? __kmalloc+0x37/0x15e
[<ffffffff8110de42>] ? __kmalloc+0x6d/0x15e
[<ffffffff812b12c9>] flush_to_ldisc+0xf8/0x18d
[<ffffffff812b13ae>] tty_flip_buffer_push+0x50/0x61
[<ffffffffa040ccd5>] put_rxbuf_data+0xea/0x124 [hso]
[<ffffffffa040cd97>] put_rxbuf_data_and_resubmit_bulk_urb+0x21/0x6b [hso]
[<ffffffffa040d0b1>] hso_std_serial_read_bulk_callback+0x14d/0x15f [hso]
[<ffffffff8132edf7>] ? dma_unmap_single_attrs.clone.0+0x38/0x3a
[<ffffffff8132ef74>] usb_hcd_giveback_urb+0x91/0xc5
[<ffffffff813417c8>] ehci_urb_done+0x7b/0x90
[<ffffffff81050c5c>] ? try_to_wake_up+0x2f3/0x305
[<ffffffff81341b45>] qh_completions+0x368/0x4b9
[<ffffffff8103e7a0>] ? __wake_up_common+0x4e/0x84
[<ffffffff81343f70>] ehci_work+0x95/0x732
[<ffffffff81045b53>] ? __wake_up+0x44/0x4d
[<ffffffff81070490>] ? insert_work+0x8e/0x9b
[<ffffffff81345f01>] ehci_irq+0x2be/0x420
[<ffffffff8107071a>] ? __queue_work+0x3a/0x41
[<ffffffff81049e43>] ? resched_cpu+0x6e/0x77
[<ffffffff8107075d>] ? delayed_work_timer_fn+0x3c/0x3e
[<ffffffff810b0e44>] ? __rcu_process_callbacks+0x7d/0x28a
[<ffffffff8132e846>] usb_hcd_irq+0x3f/0x7b
[<ffffffff810acd61>] handle_IRQ_event+0x60/0x121
[<ffffffff810aeb8e>] handle_fasteoi_irq+0x8b/0xc7
[<ffffffff81014625>] handle_irq+0x8b/0x96
[<ffffffff81459c14>] do_IRQ+0x5c/0xbc
[<ffffffff81012693>] ret_from_intr+0x0/0x11
This seems to help with Huawei and ZTE devices which often
appeared to stop responding on either primary or secondary ports
at various times. We had this problem a long time ago, but it was
fixed then by always picking the right serial port via the USB
interface number (Huawei) or udev rules files (ZTE). Now that we're
using the second serial port more extensively the problem came
up again, so lets try to fix it for real.
For QCDM devices we want most of what MMSerialPort does, but not
the AT command handling stuff since the commands and responses
aren't AT commands nor are they even strings. So convert everything
that MMSerialPort does into a GByteArray, and let MMAtSerialPort
handle the conversion to strings when necessary.
MM would appear to hang sometimes when writing to serial devices but
in reality was just retrying the write too many times. Make the
retry limit time-based so MM doesn't hang but times the attempt out
instead.
If there's already a command in-progress don't try to send
another until the previous one has timed out. Also use
g_timeout_add_seconds() since precision doesn't really matter for
command timeouts.
Nozomi devices aren't quite ready when the ports show up, so
we have to keep trying to open the port for a few seconds and
eventually it'll succeed. Should really be fixed in the driver
(ie, don't create the ttys until they can actually be used) but
whatever.
It's only relevant when the port is open anyway, and marking the port
disconnected in nm_serial_port_close(), which used to be called from
the finalize() function, would trigger the notifier when stuff was
already cleaned up. So move the nm_serial_port_close() call to
dispose() and remove the connected notifier before we clean the
port up.