Hi,

Here's a patch against 2.4.11 that fixes problems with all of the
usb-serial drivers that show up when running with slab debugging
enabled.  The problem shows up when a user program has a port open, and
the device is removed.  When the port is closed later, the close
function of the driver would try to unlink urbs that were gone, or talk
to a device that was gone.  This patch also fixes the problem that a
number of people have reported having with the visor driver crashing at
the end of a Clie or Palm m500 sync.

thanks,

greg k-h


diff --minimal -Nru a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
--- a/drivers/usb/serial/belkin_sa.c    Wed Oct 10 19:23:06 2001
+++ b/drivers/usb/serial/belkin_sa.c    Wed Oct 10 19:23:06 2001
@@ -23,8 +23,8 @@
  *    framework in, but haven't analyzed the "tty_flip" interface yet.
  * -- Add support for flush commands
  * -- Add everything that is missing :)
- * 
- * (30-May-2001 gkh
+ *
+ * 30-May-2001 gkh
  *     switched from using spinlock to a semaphore, which fixes lots of problems.
  *
  * 08-Apr-2001 gb
@@ -350,6 +350,15 @@
 
 static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
 {
+       struct usb_serial *serial;
+
+       if (port_paranoia_check (port, __FUNCTION__))
+               return;
+
+       serial = get_usb_serial (port, __FUNCTION__);
+       if (!serial)
+               return;
+
        dbg(__FUNCTION__" port %d", port->number);
 
        down (&port->sem);
@@ -357,10 +366,12 @@
        --port->open_count;
 
        if (port->open_count <= 0) {
-               /* shutdown our bulk reads and writes */
-               usb_unlink_urb (port->write_urb);
-               usb_unlink_urb (port->read_urb);
-               usb_unlink_urb (port->interrupt_in_urb);        /* wgg - do I need 
this? I think so. */
+               if (serial->dev) {
+                       /* shutdown our bulk reads and writes */
+                       usb_unlink_urb (port->write_urb);
+                       usb_unlink_urb (port->read_urb);
+                       usb_unlink_urb (port->interrupt_in_urb);
+               }
                port->active = 0;
        }
        
@@ -636,7 +647,7 @@
        usb_serial_register (&belkin_old_device);
        usb_serial_register (&peracom_device);
        usb_serial_register (&gocom232_device);
-       info(DRIVER_VERSION ":" DRIVER_DESC);
+       info(DRIVER_DESC " " DRIVER_VERSION);
        return 0;
 }
 
diff --minimal -Nru a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
--- a/drivers/usb/serial/cyberjack.c    Wed Oct 10 19:23:07 2001
+++ b/drivers/usb/serial/cyberjack.c    Wed Oct 10 19:23:07 2001
@@ -198,10 +198,12 @@
        --port->open_count;
 
        if (port->open_count <= 0) {
-               /* shutdown any bulk reads that might be going on */
-               usb_unlink_urb (port->write_urb);
-               usb_unlink_urb (port->read_urb);
-               usb_unlink_urb (port->interrupt_in_urb);
+               if (port->serial->dev) {
+                       /* shutdown any bulk reads that might be going on */
+                       usb_unlink_urb (port->write_urb);
+                       usb_unlink_urb (port->read_urb);
+                       usb_unlink_urb (port->interrupt_in_urb);
+               }
 
                port->active = 0;
                port->open_count = 0;
diff --minimal -Nru a/drivers/usb/serial/digi_acceleport.c 
b/drivers/usb/serial/digi_acceleport.c
--- a/drivers/usb/serial/digi_acceleport.c      Wed Oct 10 19:23:07 2001
+++ b/drivers/usb/serial/digi_acceleport.c      Wed Oct 10 19:23:07 2001
@@ -1591,53 +1591,55 @@
        if( tty->ldisc.flush_buffer )
                tty->ldisc.flush_buffer( tty );
 
-       /* wait for transmit idle */
-       if( (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) {
-               digi_transmit_idle( port, DIGI_CLOSE_TIMEOUT );
-       }
+       if (port->serial->dev) {
+               /* wait for transmit idle */
+               if( (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) {
+                       digi_transmit_idle( port, DIGI_CLOSE_TIMEOUT );
+               }
 
-       /* drop DTR and RTS */
-       digi_set_modem_signals( port, 0, 0 );
+               /* drop DTR and RTS */
+               digi_set_modem_signals( port, 0, 0 );
 
-       /* disable input flow control */
-       buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
-       buf[1] = priv->dp_port_num;
-       buf[2] = DIGI_DISABLE;
-       buf[3] = 0;
+               /* disable input flow control */
+               buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
+               buf[1] = priv->dp_port_num;
+               buf[2] = DIGI_DISABLE;
+               buf[3] = 0;
 
-       /* disable output flow control */
-       buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
-       buf[5] = priv->dp_port_num;
-       buf[6] = DIGI_DISABLE;
-       buf[7] = 0;
+               /* disable output flow control */
+               buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
+               buf[5] = priv->dp_port_num;
+               buf[6] = DIGI_DISABLE;
+               buf[7] = 0;
 
-       /* disable reading modem signals automatically */
-       buf[8] = DIGI_CMD_READ_INPUT_SIGNALS;
-       buf[9] = priv->dp_port_num;
-       buf[10] = DIGI_DISABLE;
-       buf[11] = 0;
+               /* disable reading modem signals automatically */
+               buf[8] = DIGI_CMD_READ_INPUT_SIGNALS;
+               buf[9] = priv->dp_port_num;
+               buf[10] = DIGI_DISABLE;
+               buf[11] = 0;
 
-       /* disable receive */
-       buf[12] = DIGI_CMD_RECEIVE_ENABLE;
-       buf[13] = priv->dp_port_num;
-       buf[14] = DIGI_DISABLE;
-       buf[15] = 0;
+               /* disable receive */
+               buf[12] = DIGI_CMD_RECEIVE_ENABLE;
+               buf[13] = priv->dp_port_num;
+               buf[14] = DIGI_DISABLE;
+               buf[15] = 0;
 
-       /* flush fifos */
-       buf[16] = DIGI_CMD_IFLUSH_FIFO;
-       buf[17] = priv->dp_port_num;
-       buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
-       buf[19] = 0;
+               /* flush fifos */
+               buf[16] = DIGI_CMD_IFLUSH_FIFO;
+               buf[17] = priv->dp_port_num;
+               buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
+               buf[19] = 0;
 
-       if( (ret=digi_write_oob_command( port, buf, 20, 0 )) != 0 )
-               dbg( "digi_close: write oob failed, ret=%d", ret );
+               if( (ret=digi_write_oob_command( port, buf, 20, 0 )) != 0 )
+                       dbg( "digi_close: write oob failed, ret=%d", ret );
 
-       /* wait for final commands on oob port to complete */
-       interruptible_sleep_on_timeout( &priv->dp_flush_wait,
-               DIGI_CLOSE_TIMEOUT );
+               /* wait for final commands on oob port to complete */
+               interruptible_sleep_on_timeout( &priv->dp_flush_wait,
+                       DIGI_CLOSE_TIMEOUT );
 
-       /* shutdown any outstanding bulk writes */
-       usb_unlink_urb (port->write_urb);
+               /* shutdown any outstanding bulk writes */
+               usb_unlink_urb (port->write_urb);
+       }
 
        tty->closing = 0;
 
diff --minimal -Nru a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
--- a/drivers/usb/serial/empeg.c        Wed Oct 10 19:23:06 2001
+++ b/drivers/usb/serial/empeg.c        Wed Oct 10 19:23:06 2001
@@ -217,8 +217,10 @@
        --port->open_count;
 
        if (port->open_count <= 0) {
-               /* shutdown our bulk read */
-               usb_unlink_urb (port->read_urb);
+               if (serial->dev) {
+                       /* shutdown our bulk read */
+                       usb_unlink_urb (port->read_urb);
+               }
                port->active = 0;
                port->open_count = 0;
        }
diff --minimal -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c     Wed Oct 10 19:23:05 2001
+++ b/drivers/usb/serial/ftdi_sio.c     Wed Oct 10 19:23:05 2001
@@ -371,29 +371,31 @@
        --port->open_count;
 
        if (port->open_count <= 0) {
-               if (c_cflag & HUPCL){
-                       /* Disable flow control */
-                       if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 
0),
-                                           FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
-                                           FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-                                           0, 0, 
-                                           buf, 0, WDR_TIMEOUT) < 0) {
-                               err("error from flowcontrol urb");
-                       }           
+               if (serial->dev) {
+                       if (c_cflag & HUPCL){
+                               /* Disable flow control */
+                               if (usb_control_msg(serial->dev, 
+                                                   usb_sndctrlpipe(serial->dev, 0),
+                                                   FTDI_SIO_SET_FLOW_CTRL_REQUEST,
+                                                   
+FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+                                                   0, 0, buf, 0, WDR_TIMEOUT) < 0) {
+                                       err("error from flowcontrol urb");
+                               }           
 
-                       /* drop DTR */
-                       if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0), LOW) 
< 0){
-                               err("Error from DTR LOW urb");
-                       }
-                       /* drop RTS */
-                       if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) 
< 0) {
-                               err("Error from RTS LOW urb");
-                       }       
-               } /* Note change no line is hupcl is off */
+                               /* drop DTR */
+                               if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 
+0), LOW) < 0){
+                                       err("Error from DTR LOW urb");
+                               }
+                               /* drop RTS */
+                               if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 
+0),LOW) < 0) {
+                                       err("Error from RTS LOW urb");
+                               }       
+                       } /* Note change no line is hupcl is off */
 
-               /* shutdown our bulk reads and writes */
-               usb_unlink_urb (port->write_urb);
-               usb_unlink_urb (port->read_urb);
+                       /* shutdown our bulk reads and writes */
+                       usb_unlink_urb (port->write_urb);
+                       usb_unlink_urb (port->read_urb);
+               }
                port->active = 0;
                port->open_count = 0;
        } else {  
diff --minimal -Nru a/drivers/usb/serial/io_edgeport.c 
b/drivers/usb/serial/io_edgeport.c
--- a/drivers/usb/serial/io_edgeport.c  Wed Oct 10 19:23:06 2001
+++ b/drivers/usb/serial/io_edgeport.c  Wed Oct 10 19:23:06 2001
@@ -1241,42 +1241,45 @@
        --port->open_count;
 
        if (port->open_count <= 0) {
-               // block until tx is empty
-               block_until_tx_empty(edge_port);
-       
-               edge_port->closePending = TRUE;
-       
-               /* flush and chase */
-               edge_port->chaseResponsePending = TRUE;
-       
-               dbg(__FUNCTION__" - Sending IOSP_CMD_CHASE_PORT");
-               status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
-               if (status == 0) {
-                       // block until chase finished
-                       block_until_chase_response(edge_port);
-               } else {
-                       edge_port->chaseResponsePending = FALSE;
+               if (serial->dev) {
+                       // block until tx is empty
+                       block_until_tx_empty(edge_port);
+
+                       edge_port->closePending = TRUE;
+
+                       /* flush and chase */
+                       edge_port->chaseResponsePending = TRUE;
+
+                       dbg(__FUNCTION__" - Sending IOSP_CMD_CHASE_PORT");
+                       status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
+                       if (status == 0) {
+                               // block until chase finished
+                               block_until_chase_response(edge_port);
+                       } else {
+                               edge_port->chaseResponsePending = FALSE;
+                       }
+
+                       /* close the port */
+                       dbg(__FUNCTION__" - Sending IOSP_CMD_CLOSE_PORT");
+                       send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
+
+                       //port->close = TRUE;
+                       edge_port->closePending = FALSE;
+                       edge_port->open = FALSE;
+                       edge_port->openPending = FALSE;
+
+                       if (edge_port->write_urb) {
+                               usb_unlink_urb (edge_port->write_urb);
+                       }
                }
        
-               /* close the port */
-               dbg(__FUNCTION__" - Sending IOSP_CMD_CLOSE_PORT");
-               send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
-       
-               //port->close = TRUE;
-               edge_port->closePending = FALSE;
-               edge_port->open = FALSE;
-               edge_port->openPending = FALSE;
-       
                if (edge_port->write_urb) {
                        /* if this urb had a transfer buffer already (old transfer) 
free it */
                        if (edge_port->write_urb->transfer_buffer != NULL) {
                                kfree(edge_port->write_urb->transfer_buffer);
                        }
-       
-                       usb_unlink_urb (edge_port->write_urb);
                        usb_free_urb   (edge_port->write_urb);
                }
-       
                if (edge_port->txfifo.fifo) {
                        kfree(edge_port->txfifo.fifo);
                }
diff --minimal -Nru a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
--- a/drivers/usb/serial/ir-usb.c       Wed Oct 10 19:23:07 2001
+++ b/drivers/usb/serial/ir-usb.c       Wed Oct 10 19:23:07 2001
@@ -14,6 +14,10 @@
  * please use the usb-irda driver, as it contains the proper error checking and
  * other goodness of a full IrDA stack.
  *
+ * Portions of this driver were taken from drivers/net/irda/irda-usb.c, which
+ * was written by Roman Weissgaerber <[EMAIL PROTECTED]>, Dag Brattli
+ * <[EMAIL PROTECTED]>, and Jean Tourrilhes <[EMAIL PROTECTED]>
+
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
  * 2001_Oct_07 greg kh
@@ -112,7 +116,7 @@
  * offer to us, describing their IrDA characteristics. We will use that in
  * irda_usb_init_qos()
  */
-static inline struct irda_class_desc *irda_usb_find_class_desc(struct usb_device 
*dev, unsigned int ifnum)
+static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev, 
+unsigned int ifnum)
 {
        struct usb_interface_descriptor *interface;
        struct irda_class_desc *desc;
@@ -229,8 +233,10 @@
        --port->open_count;
 
        if (port->open_count <= 0) {
-               /* shutdown our bulk read */
-               usb_unlink_urb (port->read_urb);
+               if (serial->dev) {
+                       /* shutdown our bulk read */
+                       usb_unlink_urb (port->read_urb);
+               }
                port->active = 0;
                port->open_count = 0;
 
diff --minimal -Nru a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
--- a/drivers/usb/serial/keyspan.c      Wed Oct 10 19:23:06 2001
+++ b/drivers/usb/serial/keyspan.c      Wed Oct 10 19:23:06 2001
@@ -920,10 +920,14 @@
 static void keyspan_close(struct usb_serial_port *port, struct file *filp)
 {
        int                     i;
-       struct usb_serial       *serial = port->serial; /* FIXME should so sanity 
check */
+       struct usb_serial       *serial;
        struct keyspan_serial_private   *s_priv;
        struct keyspan_port_private     *p_priv;
 
+       serial = get_usb_serial (port, __FUNCTION__);
+       if (!serial)
+               return;
+
        dbg("keyspan_close called\n");
        s_priv = (struct keyspan_serial_private *)(serial->private);
        p_priv = (struct keyspan_port_private *)(port->private);
@@ -931,7 +935,8 @@
        p_priv->rts_state = 0;
        p_priv->dtr_state = 0;
        
-       keyspan_send_setup(port, 1);
+       if (serial->dev)
+               keyspan_send_setup(port, 1);
 
        /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
                dbg("close - urb in progress\n");
@@ -944,18 +949,15 @@
 
        if (--port->open_count <= 0) {
                if (port->active) {
-                       /* Stop reading/writing urbs */
-                       stop_urb(p_priv->inack_urb);
-                       stop_urb(p_priv->outcont_urb);
-                       for (i = 0; i < 2; i++) {
-                               stop_urb(p_priv->in_urbs[i]);
-                               stop_urb(p_priv->out_urbs[i]);
+                       if (serial->dev) {
+                               /* Stop reading/writing urbs */
+                               stop_urb(p_priv->inack_urb);
+                               stop_urb(p_priv->outcont_urb);
+                               for (i = 0; i < 2; i++) {
+                                       stop_urb(p_priv->in_urbs[i]);
+                                       stop_urb(p_priv->out_urbs[i]);
+                               }
                        }
-                       /* Now done in shutdown 
-                       if (atomic_dec_return(&s_priv->active_count) <= 0) {
-                               stop_urb(s_priv->instat_urb);
-                               stop_urb(s_priv->glocont_urb);
-                       } */
                }
                port->active = 0;
                port->open_count = 0;
diff --minimal -Nru a/drivers/usb/serial/keyspan_pda.c 
b/drivers/usb/serial/keyspan_pda.c
--- a/drivers/usb/serial/keyspan_pda.c  Wed Oct 10 19:23:05 2001
+++ b/drivers/usb/serial/keyspan_pda.c  Wed Oct 10 19:23:05 2001
@@ -743,13 +743,15 @@
        --port->open_count;
 
        if (port->open_count <= 0) {
-               /* the normal serial device seems to always shut off DTR and RTS now */
-               if (port->tty->termios->c_cflag & HUPCL)
-                       keyspan_pda_set_modem_info(serial, 0);
+               if (serial->dev) {
+                       /* the normal serial device seems to always shut off DTR and 
+RTS now */
+                       if (port->tty->termios->c_cflag & HUPCL)
+                               keyspan_pda_set_modem_info(serial, 0);
 
-               /* shutdown our bulk reads and writes */
-               usb_unlink_urb (port->write_urb);
-               usb_unlink_urb (port->interrupt_in_urb);
+                       /* shutdown our bulk reads and writes */
+                       usb_unlink_urb (port->write_urb);
+                       usb_unlink_urb (port->interrupt_in_urb);
+               }
                port->active = 0;
                port->open_count = 0;
        }
diff --minimal -Nru a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
--- a/drivers/usb/serial/mct_u232.c     Wed Oct 10 19:23:06 2001
+++ b/drivers/usb/serial/mct_u232.c     Wed Oct 10 19:23:06 2001
@@ -475,11 +475,12 @@
        --port->open_count;
 
        if (port->open_count <= 0) {
-               /* shutdown our bulk reads and writes */
-               usb_unlink_urb (port->write_urb);
-               usb_unlink_urb (port->read_urb);
-               /* wgg - do I need this? I think so. */
-               usb_unlink_urb (port->interrupt_in_urb);
+               if (port->serial->dev) {
+                       /* shutdown our urbs */
+                       usb_unlink_urb (port->write_urb);
+                       usb_unlink_urb (port->read_urb);
+                       usb_unlink_urb (port->interrupt_in_urb);
+               }
                port->active = 0;
        }
        
diff --minimal -Nru a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
--- a/drivers/usb/serial/omninet.c      Wed Oct 10 19:23:05 2001
+++ b/drivers/usb/serial/omninet.c      Wed Oct 10 19:23:05 2001
@@ -216,14 +216,15 @@
        --port->open_count;
 
        if (port->open_count <= 0) {
-               od = (struct omninet_data *)port->private;
-               wport = &serial->port[1];
-
-               usb_unlink_urb (wport->write_urb);
-               usb_unlink_urb (port->read_urb);
+               if (serial->dev) {
+                       wport = &serial->port[1];
+                       usb_unlink_urb (wport->write_urb);
+                       usb_unlink_urb (port->read_urb);
+               }
 
                port->active = 0;
                port->open_count = 0;
+               od = (struct omninet_data *)port->private;
                if (od)
                        kfree(od);
        }
diff --minimal -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
--- a/drivers/usb/serial/pl2303.c       Wed Oct 10 19:23:06 2001
+++ b/drivers/usb/serial/pl2303.c       Wed Oct 10 19:23:06 2001
@@ -434,40 +434,53 @@
 
 static void pl2303_close (struct usb_serial_port *port, struct file *filp)
 {
+       struct usb_serial *serial;
        struct pl2303_private *priv;
        unsigned int c_cflag;
        int result;
 
        if (port_paranoia_check (port, __FUNCTION__))
                return;
-
+       serial = get_usb_serial (port, __FUNCTION__);
+       if (!serial)
+               return;
+       
        dbg (__FUNCTION__ " - port %d", port->number);
 
        down (&port->sem);
 
        --port->open_count;
        if (port->open_count <= 0) {
-               c_cflag = port->tty->termios->c_cflag;
-               if (c_cflag & HUPCL) {
-                       /* drop DTR and RTS */
-                       priv = port->private;
-                       priv->line_control = 0;
-                       set_control_lines (port->serial->dev, priv->line_control);
-               }
+               if (serial->dev) {
+                       c_cflag = port->tty->termios->c_cflag;
+                       if (c_cflag & HUPCL) {
+                               /* drop DTR and RTS */
+                               priv = port->private;
+                               priv->line_control = 0;
+                               set_control_lines (port->serial->dev,
+                                                  priv->line_control);
+                       }
 
-               /* shutdown our urbs */
-               dbg (__FUNCTION__ " - shutting down urbs");
-               result = usb_unlink_urb (port->write_urb);
-               if (result)
-                       dbg (__FUNCTION__ " - usb_unlink_urb (write_urb) failed with 
reason: %d", result);
+                       /* shutdown our urbs */
+                       dbg (__FUNCTION__ " - shutting down urbs");
+                       result = usb_unlink_urb (port->write_urb);
+                       if (result)
+                               dbg (__FUNCTION__ " - usb_unlink_urb "
+                                    "(write_urb) failed with reason: %d",
+                                    result);
 
-               result = usb_unlink_urb (port->read_urb);
-               if (result)
-                       dbg (__FUNCTION__ " - usb_unlink_urb (read_urb) failed with 
reason: %d", result);
+                       result = usb_unlink_urb (port->read_urb);
+                       if (result)
+                               dbg (__FUNCTION__ " - usb_unlink_urb "
+                                    "(read_urb) failed with reason: %d",
+                                    result);
 
-               result = usb_unlink_urb (port->interrupt_in_urb);
-               if (result)
-                       dbg (__FUNCTION__ " - usb_unlink_urb (interrupt_in_urb) failed 
with reason: %d", result);
+                       result = usb_unlink_urb (port->interrupt_in_urb);
+                       if (result)
+                               dbg (__FUNCTION__ " - usb_unlink_urb "
+                                    "(interrupt_in_urb) failed with reason: %d",
+                                    result);
+               }
 
                port->active = 0;
                port->open_count = 0;
diff --minimal -Nru a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
--- a/drivers/usb/serial/usb-serial.h   Wed Oct 10 19:23:06 2001
+++ b/drivers/usb/serial/usb-serial.h   Wed Oct 10 19:23:06 2001
@@ -11,6 +11,10 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
+ * (10/10/2001) gkh
+ *     added vendor and product to serial structure.  Needed to determine device
+ *     owner when the device is disconnected.
+ *
  * (05/30/2001) gkh
  *     added sem to port structure and removed port_lock
  *
@@ -96,6 +100,8 @@
        char                            num_interrupt_in;       /* number of interrupt 
in endpoints we have */
        char                            num_bulk_in;            /* number of bulk in 
endpoints we have */
        char                            num_bulk_out;           /* number of bulk out 
endpoints we have */
+       __u16                           vendor;                 /* vendor id of this 
+device */
+       __u16                           product;                /* product id of this 
+device */
        struct usb_serial_port          port[MAX_NUM_PORTS];
 
        void *                  private;                /* data private to the 
specific driver */
diff --minimal -Nru a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
--- a/drivers/usb/serial/usbserial.c    Wed Oct 10 19:23:07 2001
+++ b/drivers/usb/serial/usbserial.c    Wed Oct 10 19:23:07 2001
@@ -14,7 +14,12 @@
  * based on a driver by Brad Keryan)
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
- * 
+ *
+ * (10/10/2001) gkh
+ *     usb_serial_disconnect() now sets the serial->dev pointer is to NULL to
+ *     help prevent child drivers from accessing the device since it is now
+ *     gone.
+ *
  * (09/13/2001) gkh
  *     Moved generic driver initialize after we have registered with the USB
  *     core.  Thanks to Randy Dunlap for pointing this problem out.
@@ -344,9 +349,9 @@
        shutdown:               generic_shutdown,
 };
 
-#define if_generic_do(x)                                       \
-       if ((serial->dev->descriptor.idVendor == vendor) &&     \
-           (serial->dev->descriptor.idProduct == product))     \
+#define if_generic_do(x)                       \
+       if ((serial->vendor == vendor) &&       \
+           (serial->product == product))       \
                        x
 #else
 #define if_generic_do(x)
@@ -462,10 +467,15 @@
 int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, 
int length, __u8 bRequest)
 {
        int result;
-       unsigned char *transfer_buffer =  kmalloc (length, GFP_KERNEL);
+       unsigned char *transfer_buffer;
 
-//     dbg("ezusb_writememory %x, %d", address, length);
+       /* dbg("ezusb_writememory %x, %d", address, length); */
+       if (!serial->dev) {
+               dbg(__FUNCTION__ " - no physical device present, failing.");
+               return -ENODEV;
+       }
 
+       transfer_buffer =  kmalloc (length, GFP_KERNEL);
        if (!transfer_buffer) {
                err(__FUNCTION__ " - kmalloc(%d) failed.", length);
                return -ENOMEM;
@@ -821,11 +831,13 @@
        --port->open_count;
 
        if (port->open_count <= 0) {
-               /* shutdown any bulk reads that might be going on */
-               if (serial->num_bulk_out)
-                       usb_unlink_urb (port->write_urb);
-               if (serial->num_bulk_in)
-                       usb_unlink_urb (port->read_urb);
+               if (serial->dev) {
+                       /* shutdown any bulk reads that might be going on */
+                       if (serial->num_bulk_out)
+                               usb_unlink_urb (port->write_urb);
+                       if (serial->num_bulk_in)
+                               usb_unlink_urb (port->read_urb);
+               }
                
                port->active = 0;
                port->open_count = 0;
@@ -1186,6 +1198,8 @@
        serial->num_bulk_in = num_bulk_in;
        serial->num_bulk_out = num_bulk_out;
        serial->num_interrupt_in = num_interrupt_in;
+       serial->vendor = dev->descriptor.idVendor;
+       serial->product = dev->descriptor.idProduct;
 
        /* if this device type has a startup function, call it */
        if (type->startup) {
@@ -1338,6 +1352,7 @@
                                serial->port[i].tty->driver_data = NULL;
                }
 
+               serial->dev = NULL;
                serial_shutdown (serial);
 
                for (i = 0; i < serial->num_ports; ++i)
diff --minimal -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c        Wed Oct 10 19:23:06 2001
+++ b/drivers/usb/serial/visor.c        Wed Oct 10 19:23:06 2001
@@ -380,21 +380,26 @@
        --port->open_count;
 
        if (port->open_count <= 0) {
-               transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
-               if (!transfer_buffer) {
-                       err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12);
-               } else {
-                       /* send a shutdown message to the device */
-                       usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), 
VISOR_CLOSE_NOTIFICATION,
-                                       0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 
300);
-                       kfree (transfer_buffer);
+               if (serial->dev) {
+                       /* only send a shutdown message if the 
+                        * device is still here */
+                       transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
+                       if (!transfer_buffer) {
+                               err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12);
+                       } else {
+                               /* send a shutdown message to the device */
+                               usb_control_msg (serial->dev,
+                                                usb_rcvctrlpipe(serial->dev, 0),
+                                                VISOR_CLOSE_NOTIFICATION, 0xc2,
+                                                0x0000, 0x0000, 
+                                                transfer_buffer, 0x12, 300);
+                               kfree (transfer_buffer);
+                       }
+                       /* shutdown our bulk read */
+                       usb_unlink_urb (port->read_urb);
                }
-
-               /* shutdown our bulk read */
-               usb_unlink_urb (port->read_urb);
                port->active = 0;
                port->open_count = 0;
-
        }
        up (&port->sem);
 

_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to