static struct tty_driver *gsm_tty_driver;
 
+/* Save dlci open address */
+static int addr_open[256] = { 0 };
+/* Save dlci open count */
+static int addr_cnt;
 /*
  *     This section of the driver logic implements the GSM encodings
  *     both the basic and the 'advanced'. Reliable transport is not
 }
 
 static void gsm_dlci_begin_close(struct gsm_dlci *dlci);
+static void gsm_dlci_close(struct gsm_dlci *dlci);
 
 /**
  *     gsm_control_message     -       DLCI 0 control processing
 {
        u8 buf[1];
        unsigned long flags;
+       struct gsm_dlci *dlci;
+       int i;
+       int address;
 
        switch (command) {
        case CMD_CLD: {
-               struct gsm_dlci *dlci = gsm->dlci[0];
+               if (addr_cnt > 0) {
+                       for (i = 0; i < addr_cnt; i++) {
+                               address = addr_open[i];
+                               dlci = gsm->dlci[address];
+                               gsm_dlci_close(dlci);
+                               addr_open[i] = 0;
+                       }
+               }
                /* Modem wishes to close down */
+               dlci = gsm->dlci[0];
                if (dlci) {
                        dlci->dead = true;
                        gsm->dead = true;
-                       gsm_dlci_begin_close(dlci);
+                       gsm_dlci_close(dlci);
+                       addr_cnt = 0;
+                       gsm_response(gsm, 0, UA|PF);
                }
                }
                break;
        struct gsm_dlci *dlci;
        u8 cr;
        int address;
+       int i, j, k, address_tmp;
        /* We have to sneak a look at the packet body to do the FCS.
           A somewhat layering violation in the spec */
 
                else {
                        gsm_response(gsm, address, UA|PF);
                        gsm_dlci_open(dlci);
+                       /* Save dlci open address */
+                       if (address) {
+                               addr_open[addr_cnt] = address;
+                               addr_cnt++;
+                       }
                }
                break;
        case DISC|PF:
                        return;
                }
                /* Real close complete */
-               gsm_response(gsm, address, UA|PF);
-               gsm_dlci_close(dlci);
+               if (!address) {
+                       if (addr_cnt > 0) {
+                               for (i = 0; i < addr_cnt; i++) {
+                                       address = addr_open[i];
+                                       dlci = gsm->dlci[address];
+                                       gsm_dlci_close(dlci);
+                                       addr_open[i] = 0;
+                               }
+                       }
+                       dlci = gsm->dlci[0];
+                       gsm_dlci_close(dlci);
+                       addr_cnt = 0;
+                       gsm_response(gsm, 0, UA|PF);
+               } else {
+                       gsm_response(gsm, address, UA|PF);
+                       gsm_dlci_close(dlci);
+                       /* clear dlci address */
+                       for (j = 0; j < addr_cnt; j++) {
+                               address_tmp = addr_open[j];
+                               if (address_tmp == address) {
+                                       for (k = j; k < addr_cnt; k++)
+                                               addr_open[k] = addr_open[k+1];
+                               addr_cnt--;
+                               break;
+                               }
+                       }
+               }
                break;
        case UA:
        case UA|PF: