Merge ~alfonsosanchezbeato/snappy-hwe-snaps/+git/modem-manager:workaround-serial-pls62 into ~snappy-hwe-team/snappy-hwe-snaps/+git/modem-manager:modem-manager/1.8.0

Proposed by Alfonso Sanchez-Beato
Status: Merged
Approved by: Konrad Zapałowicz
Approved revision: ec7f5f82fe095bd821ad353282851fbc6022df03
Merged at revision: cc696d7f9511fb1bf74213c1ae6652db0aa5f3f3
Proposed branch: ~alfonsosanchezbeato/snappy-hwe-snaps/+git/modem-manager:workaround-serial-pls62
Merge into: ~snappy-hwe-team/snappy-hwe-snaps/+git/modem-manager:modem-manager/1.8.0
Diff against target: 290 lines (+274/-0)
1 file modified
plugins/cinterion/mm-broadband-bearer-pls62.c (+274/-0)
Reviewer Review Type Date Requested Status
Konrad Zapałowicz (community) Approve
System Enablement Bot continuous-integration Approve
Review via email: mp+369240@code.launchpad.net

Commit message

bearer: workaround serial not responding in PLS62-W

Do not try to deactivate the PDP context for the Gemalto PLS62-W modem,
let NM do the job for us. The reason is that due to a modem firmware
bug, if the timing between pppd and us deactivating is unfortunate, the
port ends up in a state in which it is unusable. Note also that this LTE
modem cannot really disconnect while attached, so the AT command always
returns an error anyway. Fixes LP: #1829293.

Description of the change

bearer: workaround serial not responding in PLS62-W

Do not try to deactivate the PDP context for the Gemalto PLS62-W modem,
let NM do the job for us. The reason is that due to a modem firmware
bug, if the timing between pppd and us deactivating is unfortunate, the
port ends up in a state in which it is unusable. Note also that this LTE
modem cannot really disconnect while attached, so the AT command always
returns an error anyway. Fixes LP: #1829293.

To post a comment you must log in.
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Konrad Zapałowicz (kzapalowicz) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/plugins/cinterion/mm-broadband-bearer-pls62.c b/plugins/cinterion/mm-broadband-bearer-pls62.c
2index 3d9b147..f2a7ae5 100644
3--- a/plugins/cinterion/mm-broadband-bearer-pls62.c
4+++ b/plugins/cinterion/mm-broadband-bearer-pls62.c
5@@ -283,6 +283,278 @@ dial_3gpp (MMBroadbandBearer *self,
6 }
7
8 /*****************************************************************************/
9+/* Detailed disconnect context */
10+
11+typedef struct {
12+ MMBaseModem *modem;
13+ MMPortSerialAt *primary;
14+ MMPortSerialAt *secondary;
15+ MMPort *data;
16+
17+ /* 3GPP-specific */
18+ gchar *cgact_command;
19+ gboolean cgact_sent;
20+} DetailedDisconnectContext;
21+
22+static gboolean
23+detailed_disconnect_finish (MMBroadbandBearer *self,
24+ GAsyncResult *res,
25+ GError **error)
26+{
27+ return g_task_propagate_boolean (G_TASK (res), error);
28+}
29+
30+static void
31+detailed_disconnect_context_free (DetailedDisconnectContext *ctx)
32+{
33+ if (ctx->cgact_command)
34+ g_free (ctx->cgact_command);
35+ g_object_unref (ctx->data);
36+ g_object_unref (ctx->primary);
37+ if (ctx->secondary)
38+ g_object_unref (ctx->secondary);
39+ g_object_unref (ctx->modem);
40+ g_free (ctx);
41+}
42+
43+static DetailedDisconnectContext *
44+detailed_disconnect_context_new (MMBroadbandModem *modem,
45+ MMPortSerialAt *primary,
46+ MMPortSerialAt *secondary,
47+ MMPort *data)
48+{
49+ DetailedDisconnectContext *ctx;
50+
51+ ctx = g_new0 (DetailedDisconnectContext, 1);
52+ ctx->modem = MM_BASE_MODEM (g_object_ref (modem));
53+ ctx->primary = g_object_ref (primary);
54+ ctx->secondary = (secondary ? g_object_ref (secondary) : NULL);
55+ ctx->data = g_object_ref (data);
56+
57+ return ctx;
58+}
59+
60+/*****************************************************************************/
61+/* 3GPP disconnect */
62+
63+static void
64+cgact_data_ready (MMBaseModem *modem,
65+ GAsyncResult *res,
66+ GTask *task)
67+{
68+
69+ GError *error = NULL;
70+
71+ /* Ignore errors for now */
72+ mm_base_modem_at_command_full_finish (modem, res, &error);
73+ if (error) {
74+ mm_dbg ("PDP context deactivation failed (not fatal): %s", error->message);
75+ g_error_free (error);
76+ }
77+
78+ g_task_return_boolean (task, TRUE);
79+ g_object_unref (task);
80+}
81+
82+static void
83+data_flash_3gpp_ready (MMPortSerial *data,
84+ GAsyncResult *res,
85+ GTask *task)
86+{
87+ MMBroadbandBearer *self;
88+ DetailedDisconnectContext *ctx;
89+ GError *error = NULL;
90+
91+ self = g_task_get_source_object (task);
92+ ctx = g_task_get_task_data (task);
93+
94+ mm_port_serial_flash_finish (data, res, &error);
95+
96+ /* We kept the serial port open during connection, now we close that open
97+ * count */
98+ mm_port_serial_close (data);
99+
100+ /* Port is disconnected; update the state */
101+ mm_port_set_connected (MM_PORT (data), FALSE);
102+
103+ if (error) {
104+ /* Ignore "NO CARRIER" response when modem disconnects and any flash
105+ * failures we might encounter. Other errors are hard errors.
106+ */
107+ if (!g_error_matches (error,
108+ MM_CONNECTION_ERROR,
109+ MM_CONNECTION_ERROR_NO_CARRIER) &&
110+ !g_error_matches (error,
111+ MM_SERIAL_ERROR,
112+ MM_SERIAL_ERROR_FLASH_FAILED)) {
113+ /* Fatal */
114+ g_task_return_error (task, error);
115+ g_object_unref (task);
116+ return;
117+ }
118+
119+ mm_dbg ("Port flashing failed (not fatal): %s", error->message);
120+ g_error_free (error);
121+ }
122+
123+ /* Run init port sequence in the data port */
124+ mm_port_serial_at_run_init_sequence (MM_PORT_SERIAL_AT (data));
125+
126+ /* Don't bother doing the CGACT again if it was already done on the
127+ * primary or secondary port */
128+ if (ctx->cgact_sent) {
129+ mm_dbg ("PDP disconnection already sent");
130+ g_task_return_boolean (task, TRUE);
131+ g_object_unref (task);
132+ return;
133+ }
134+
135+ /* Send another CGACT on the primary port (also the data port when the modem
136+ * only has one serial port) if the previous one failed. Some modems, like
137+ * the Huawei E173 (fw 11.126.15.00.445) stop responding on their primary
138+ * port when the CGACT is sent on the separte data port.
139+ */
140+ if (MM_PORT_SERIAL (ctx->primary) == data)
141+ mm_dbg ("Sending PDP context deactivation in primary/data port...");
142+ else
143+ mm_dbg ("Sending PDP context deactivation in primary port again...");
144+
145+ mm_base_modem_at_command_full (ctx->modem,
146+ ctx->primary,
147+ ctx->cgact_command,
148+ 10,
149+ FALSE,
150+ FALSE, /* raw */
151+ NULL, /* cancellable */
152+ (GAsyncReadyCallback)cgact_data_ready,
153+ task);
154+}
155+
156+static void
157+data_reopen_3gpp_ready (MMPortSerial *data,
158+ GAsyncResult *res,
159+ GTask *task)
160+{
161+ DetailedDisconnectContext *ctx;
162+ GError *error = NULL;
163+
164+ g_object_set (data, MM_PORT_SERIAL_AT_INIT_SEQUENCE_ENABLED, TRUE, NULL);
165+
166+ if (!mm_port_serial_reopen_finish (data, res, &error)) {
167+ /* Fatal */
168+ g_task_return_error (task, error);
169+ g_object_unref (task);
170+ return;
171+ }
172+
173+ ctx = g_task_get_task_data (task);
174+
175+ /* Just flash the data port */
176+ mm_dbg ("Flashing data port (%s)...", mm_port_get_device (MM_PORT (ctx->data)));
177+ mm_port_serial_flash (MM_PORT_SERIAL (ctx->data),
178+ 1000,
179+ TRUE,
180+ (GAsyncReadyCallback)data_flash_3gpp_ready,
181+ task);
182+}
183+
184+static void
185+data_reopen_3gpp (GTask *task)
186+{
187+ DetailedDisconnectContext *ctx;
188+
189+ ctx = g_task_get_task_data (task);
190+
191+ /* We don't want to run init sequence right away during the reopen, as we're
192+ * going to flash afterwards. */
193+ g_object_set (ctx->data, MM_PORT_SERIAL_AT_INIT_SEQUENCE_ENABLED, FALSE, NULL);
194+
195+ /* Fully reopen the port before flashing */
196+ mm_dbg ("Reopening data port (%s)...", mm_port_get_device (MM_PORT (ctx->data)));
197+ mm_port_serial_reopen (MM_PORT_SERIAL (ctx->data),
198+ 1000,
199+ (GAsyncReadyCallback)data_reopen_3gpp_ready,
200+ task);
201+}
202+
203+static void
204+cgact_ready (MMBaseModem *modem,
205+ GAsyncResult *res,
206+ GTask *task)
207+{
208+ DetailedDisconnectContext *ctx;
209+ GError *error = NULL;
210+
211+ ctx = g_task_get_task_data (task);
212+
213+ mm_base_modem_at_command_full_finish (modem, res, &error);
214+ if (!error)
215+ ctx->cgact_sent = TRUE;
216+ else {
217+ mm_dbg ("PDP context deactivation failed (not fatal): %s", error->message);
218+ g_error_free (error);
219+ }
220+
221+ data_reopen_3gpp (task);
222+}
223+
224+static void
225+disconnect_3gpp (MMBroadbandBearer *self,
226+ MMBroadbandModem *modem,
227+ MMPortSerialAt *primary,
228+ MMPortSerialAt *secondary,
229+ MMPort *data,
230+ guint cid,
231+ GAsyncReadyCallback callback,
232+ gpointer user_data)
233+{
234+ DetailedDisconnectContext *ctx;
235+ GTask *task;
236+
237+ g_assert (primary != NULL);
238+
239+ /* Generic 3GPP plays only with SERIAL data ports */
240+ g_assert (MM_IS_PORT_SERIAL (data));
241+
242+ ctx = detailed_disconnect_context_new (modem, primary, secondary, data);
243+
244+ /* If no specific CID was used, disable all PDP contexts */
245+ ctx->cgact_command = (cid > 0 ?
246+ g_strdup_printf ("+CGACT=0,%d", cid) :
247+ g_strdup_printf ("+CGACT=0"));
248+
249+ task = g_task_new (self, NULL, callback, user_data);
250+ g_task_set_task_data (task, ctx, (GDestroyNotify)detailed_disconnect_context_free);
251+
252+ /* If the primary port is NOT connected (doesn't have to be the data port),
253+ * we'll send CGACT there */
254+ if (!mm_port_get_connected (MM_PORT (ctx->primary))) {
255+ mm_dbg ("Sending PDP context deactivation in primary port...");
256+ mm_base_modem_at_command_full (ctx->modem,
257+ ctx->primary,
258+ ctx->cgact_command,
259+ 10,
260+ FALSE,
261+ FALSE, /* raw */
262+ NULL, /* cancellable */
263+ (GAsyncReadyCallback)cgact_ready,
264+ task);
265+ return;
266+ }
267+
268+ /* If the primary port is busy with a data call, do not try to deactivate,
269+ * let NM do the job for us. The reason is that due to a modem firmware bug
270+ * in the PLS62-W, if the timing between pppd and us disconnecting is
271+ * unfortunate, the port ends up in a state in which it is unusable. Note
272+ * also that this LTE modem cannot really disconnect while attached, so
273+ * trying to do so ends in error anyway.
274+ */
275+ mm_info ("PLS62-W modem, letting NM do the disconnect...");
276+ /* Go on to reopen & flash the data/primary port */
277+ data_reopen_3gpp (task);
278+}
279+
280+/*****************************************************************************/
281 /* Setup and Init Bearers */
282
283 MMBaseBearer *
284@@ -336,4 +608,6 @@ mm_broadband_bearer_pls62_class_init (MMBroadbandBearerPls62Class *klass)
285
286 broadband_bearer_class->dial_3gpp = dial_3gpp;
287 broadband_bearer_class->dial_3gpp_finish = dial_3gpp_finish;
288+ broadband_bearer_class->disconnect_3gpp = disconnect_3gpp;
289+ broadband_bearer_class->disconnect_3gpp_finish = detailed_disconnect_finish;
290 }

Subscribers

People subscribed via source and target branches