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