Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4cb5e42f authored by Tilman Schmidt's avatar Tilman Schmidt Committed by David S. Miller
Browse files

isdn/gigaset: unclog bas_gigaset AT response pipe



Recover from a lost HD_RECEIVEATDATA_ACK message by sending a
zero-length HD_READ_ATMESSAGE command when ev_layer sends "+++".

Signed-off-by: default avatarTilman Schmidt <tilman@imap.cc>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 60798c68
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -1896,6 +1896,28 @@ static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb)
	 * The next command will reopen the AT channel automatically.
	 */
	if (cb->len == 3 && !memcmp(cb->buf, "+++", 3)) {
		/* If an HD_RECEIVEATDATA_ACK message remains unhandled
		 * because of an error, the base never sends another one.
		 * The response channel is thus effectively blocked.
		 * Closing and reopening the AT channel does *not* clear
		 * this condition.
		 * As a stopgap measure, submit a zero-length AT read
		 * before closing the AT channel. This has the undocumented
		 * effect of triggering a new HD_RECEIVEATDATA_ACK message
		 * from the base if necessary.
		 * The subsequent AT channel close then discards any pending
		 * messages.
		 */
		spin_lock_irqsave(&cs->lock, flags);
		if (!(cs->hw.bas->basstate & BS_ATRDPEND)) {
			kfree(cs->hw.bas->rcvbuf);
			cs->hw.bas->rcvbuf = NULL;
			cs->hw.bas->rcvbuf_size = 0;
			cs->hw.bas->retry_cmd_in = 0;
			atread_submit(cs, 0);
		}
		spin_unlock_irqrestore(&cs->lock, flags);

		rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT);
		if (cb->wake_tasklet)
			tasklet_schedule(cb->wake_tasklet);