n_gsm: fix wait_event in gsmtty_modem_update when modem reset happened
authorsamix.lebsir <samix.lebsir@intel.com>
Mon, 26 Dec 2011 15:30:35 +0000 (16:30 +0100)
committerbuildbot <buildbot@intel.com>
Tue, 27 Dec 2011 13:31:58 +0000 (05:31 -0800)
BZ: 14542

Scenario:
When gsmtty_modem_update send CMD_MSC to modem, it would stay in wait_event(ctrl->done) for control response.
If modem reset at this time, mux would never receive response from modem.
Then API open would stay in wait_event for ever, even if gsm_dlci_close.

The patch add "gsm->dead" condition in the wait_event of both gsm_control_send() and gsm_control_wait().
If gsm->dead, both gsm_control_send and gsm_control_wait should wake up from wait_event.

Change-Id: I1ad39a85686d1f1f1b75971c99f9450fa093b7db
Signed-off-by: samix.lebsir <samix.lebsir@intel.com>
Reviewed-on: http://android.intel.com:8080/29981
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
drivers/tty/n_gsm.c

index 2359c96..fe85e32 100644 (file)
@@ -1349,12 +1349,17 @@ static struct gsm_control *gsm_control_send(struct gsm_mux *gsm,
        if (ctrl == NULL)
                return NULL;
 retry:
-       wait_event(gsm->event, gsm->pending_cmd == NULL);
+       wait_event(gsm->event, gsm->pending_cmd == NULL || gsm->dead);
        spin_lock_irqsave(&gsm->control_lock, flags);
-       if (gsm->pending_cmd != NULL) {
+       if ((gsm->pending_cmd != NULL) && !gsm->dead) {
                spin_unlock_irqrestore(&gsm->control_lock, flags);
                goto retry;
        }
+       if (gsm->dead) {
+               spin_unlock_irqrestore(&gsm->control_lock, flags);
+               kfree(ctrl);
+               return NULL;
+       }
        ctrl->cmd = command;
        ctrl->data = data;
        ctrl->len = clen;
@@ -1378,8 +1383,18 @@ retry:
 
 static int gsm_control_wait(struct gsm_mux *gsm, struct gsm_control *control)
 {
+       unsigned long flags;
        int err;
-       wait_event(gsm->event, control->done == 1);
+       wait_event(gsm->event, control->done == 1 || gsm->dead);
+       if (gsm->dead) {
+               spin_lock_irqsave(&gsm->control_lock, flags);
+               if (control == gsm->pending_cmd) {
+                       del_timer(&gsm->t2_timer);
+                       gsm->pending_cmd = NULL;
+               }
+               control->error = -ETIMEDOUT;
+               spin_unlock_irqrestore(&gsm->control_lock, flags);
+       }
        err = control->error;
        kfree(control);
        return err;