Skip to content

Commit

Permalink
USB: usb-serial: replace shutdown with disconnect, release
Browse files Browse the repository at this point in the history
This patch (as1254) splits up the shutdown method of usb_serial_driver
into a disconnect and a release method.

The problem is that the usb-serial core was calling shutdown during
disconnect handling, but drivers didn't expect it to be called until
after all the open file references had been closed.  The result was an
oops when the close method tried to use memory that had been
deallocated by shutdown.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Jun 16, 2009
1 parent c706ebd commit f9c99bb
Show file tree
Hide file tree
Showing 37 changed files with 297 additions and 198 deletions.
4 changes: 2 additions & 2 deletions drivers/staging/uc2322/aten2011.c
Original file line number Diff line number Diff line change
Expand Up @@ -2336,7 +2336,7 @@ static int ATEN2011_startup(struct usb_serial *serial)
return 0;
}

static void ATEN2011_shutdown(struct usb_serial *serial)
static void ATEN2011_release(struct usb_serial *serial)
{
int i;
struct ATENINTL_port *ATEN2011_port;
Expand Down Expand Up @@ -2382,7 +2382,7 @@ static struct usb_serial_driver aten_serial_driver = {
.tiocmget = ATEN2011_tiocmget,
.tiocmset = ATEN2011_tiocmset,
.attach = ATEN2011_startup,
.shutdown = ATEN2011_shutdown,
.release = ATEN2011_release,
.read_bulk_callback = ATEN2011_bulk_in_callback,
.read_int_callback = ATEN2011_interrupt_callback,
};
Expand Down
5 changes: 2 additions & 3 deletions drivers/usb/serial/aircable.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ static int aircable_attach(struct usb_serial *serial)
return 0;
}

static void aircable_shutdown(struct usb_serial *serial)
static void aircable_release(struct usb_serial *serial)
{

struct usb_serial_port *port = serial->port[0];
Expand All @@ -375,7 +375,6 @@ static void aircable_shutdown(struct usb_serial *serial)
if (priv) {
serial_buf_free(priv->tx_buf);
serial_buf_free(priv->rx_buf);
usb_set_serial_port_data(port, NULL);
kfree(priv);
}
}
Expand Down Expand Up @@ -601,7 +600,7 @@ static struct usb_serial_driver aircable_device = {
.num_ports = 1,
.attach = aircable_attach,
.probe = aircable_probe,
.shutdown = aircable_shutdown,
.release = aircable_release,
.write = aircable_write,
.write_room = aircable_write_room,
.write_bulk_callback = aircable_write_bulk_callback,
Expand Down
7 changes: 3 additions & 4 deletions drivers/usb/serial/belkin_sa.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ static int debug;

/* function prototypes for a Belkin USB Serial Adapter F5U103 */
static int belkin_sa_startup(struct usb_serial *serial);
static void belkin_sa_shutdown(struct usb_serial *serial);
static void belkin_sa_release(struct usb_serial *serial);
static int belkin_sa_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
static void belkin_sa_close(struct usb_serial_port *port);
Expand Down Expand Up @@ -142,7 +142,7 @@ static struct usb_serial_driver belkin_device = {
.tiocmget = belkin_sa_tiocmget,
.tiocmset = belkin_sa_tiocmset,
.attach = belkin_sa_startup,
.shutdown = belkin_sa_shutdown,
.release = belkin_sa_release,
};


Expand Down Expand Up @@ -197,14 +197,13 @@ static int belkin_sa_startup(struct usb_serial *serial)
}


static void belkin_sa_shutdown(struct usb_serial *serial)
static void belkin_sa_release(struct usb_serial *serial)
{
struct belkin_sa_private *priv;
int i;

dbg("%s", __func__);

/* stop reads and writes on all ports */
for (i = 0; i < serial->num_ports; ++i) {
/* My special items, the standard routines free my urbs */
priv = usb_get_serial_port_data(serial->port[i]);
Expand Down
6 changes: 3 additions & 3 deletions drivers/usb/serial/cp210x.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *,
unsigned int, unsigned int);
static void cp210x_break_ctl(struct tty_struct *, int);
static int cp210x_startup(struct usb_serial *);
static void cp210x_shutdown(struct usb_serial *);
static void cp210x_disconnect(struct usb_serial *);

static int debug;

Expand Down Expand Up @@ -137,7 +137,7 @@ static struct usb_serial_driver cp210x_device = {
.tiocmget = cp210x_tiocmget,
.tiocmset = cp210x_tiocmset,
.attach = cp210x_startup,
.shutdown = cp210x_shutdown,
.disconnect = cp210x_disconnect,
};

/* Config request types */
Expand Down Expand Up @@ -792,7 +792,7 @@ static int cp210x_startup(struct usb_serial *serial)
return 0;
}

static void cp210x_shutdown(struct usb_serial *serial)
static void cp210x_disconnect(struct usb_serial *serial)
{
int i;

Expand Down
20 changes: 15 additions & 5 deletions drivers/usb/serial/cyberjack.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ static int debug;

/* Function prototypes */
static int cyberjack_startup(struct usb_serial *serial);
static void cyberjack_shutdown(struct usb_serial *serial);
static void cyberjack_disconnect(struct usb_serial *serial);
static void cyberjack_release(struct usb_serial *serial);
static int cyberjack_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
static void cyberjack_close(struct usb_serial_port *port);
Expand Down Expand Up @@ -94,7 +95,8 @@ static struct usb_serial_driver cyberjack_device = {
.id_table = id_table,
.num_ports = 1,
.attach = cyberjack_startup,
.shutdown = cyberjack_shutdown,
.disconnect = cyberjack_disconnect,
.release = cyberjack_release,
.open = cyberjack_open,
.close = cyberjack_close,
.write = cyberjack_write,
Expand Down Expand Up @@ -148,17 +150,25 @@ static int cyberjack_startup(struct usb_serial *serial)
return 0;
}

static void cyberjack_shutdown(struct usb_serial *serial)
static void cyberjack_disconnect(struct usb_serial *serial)
{
int i;

dbg("%s", __func__);

for (i = 0; i < serial->num_ports; ++i) {
for (i = 0; i < serial->num_ports; ++i)
usb_kill_urb(serial->port[i]->interrupt_in_urb);
}

static void cyberjack_release(struct usb_serial *serial)
{
int i;

dbg("%s", __func__);

for (i = 0; i < serial->num_ports; ++i) {
/* My special items, the standard routines free my urbs */
kfree(usb_get_serial_port_data(serial->port[i]));
usb_set_serial_port_data(serial->port[i], NULL);
}
}

Expand Down
11 changes: 5 additions & 6 deletions drivers/usb/serial/cypress_m8.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ struct cypress_buf {
static int cypress_earthmate_startup(struct usb_serial *serial);
static int cypress_hidcom_startup(struct usb_serial *serial);
static int cypress_ca42v2_startup(struct usb_serial *serial);
static void cypress_shutdown(struct usb_serial *serial);
static void cypress_release(struct usb_serial *serial);
static int cypress_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
static void cypress_close(struct usb_serial_port *port);
Expand Down Expand Up @@ -215,7 +215,7 @@ static struct usb_serial_driver cypress_earthmate_device = {
.id_table = id_table_earthmate,
.num_ports = 1,
.attach = cypress_earthmate_startup,
.shutdown = cypress_shutdown,
.release = cypress_release,
.open = cypress_open,
.close = cypress_close,
.dtr_rts = cypress_dtr_rts,
Expand All @@ -242,7 +242,7 @@ static struct usb_serial_driver cypress_hidcom_device = {
.id_table = id_table_cyphidcomrs232,
.num_ports = 1,
.attach = cypress_hidcom_startup,
.shutdown = cypress_shutdown,
.release = cypress_release,
.open = cypress_open,
.close = cypress_close,
.dtr_rts = cypress_dtr_rts,
Expand All @@ -269,7 +269,7 @@ static struct usb_serial_driver cypress_ca42v2_device = {
.id_table = id_table_nokiaca42v2,
.num_ports = 1,
.attach = cypress_ca42v2_startup,
.shutdown = cypress_shutdown,
.release = cypress_release,
.open = cypress_open,
.close = cypress_close,
.dtr_rts = cypress_dtr_rts,
Expand Down Expand Up @@ -616,7 +616,7 @@ static int cypress_ca42v2_startup(struct usb_serial *serial)
} /* cypress_ca42v2_startup */


static void cypress_shutdown(struct usb_serial *serial)
static void cypress_release(struct usb_serial *serial)
{
struct cypress_private *priv;

Expand All @@ -629,7 +629,6 @@ static void cypress_shutdown(struct usb_serial *serial)
if (priv) {
cypress_buf_free(priv->buf);
kfree(priv);
usb_set_serial_port_data(serial->port[0], NULL);
}
}

Expand Down
20 changes: 15 additions & 5 deletions drivers/usb/serial/digi_acceleport.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,8 @@ static int digi_carrier_raised(struct usb_serial_port *port);
static void digi_dtr_rts(struct usb_serial_port *port, int on);
static int digi_startup_device(struct usb_serial *serial);
static int digi_startup(struct usb_serial *serial);
static void digi_shutdown(struct usb_serial *serial);
static void digi_disconnect(struct usb_serial *serial);
static void digi_release(struct usb_serial *serial);
static void digi_read_bulk_callback(struct urb *urb);
static int digi_read_inb_callback(struct urb *urb);
static int digi_read_oob_callback(struct urb *urb);
Expand Down Expand Up @@ -524,7 +525,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {
.tiocmget = digi_tiocmget,
.tiocmset = digi_tiocmset,
.attach = digi_startup,
.shutdown = digi_shutdown,
.disconnect = digi_disconnect,
.release = digi_release,
};

static struct usb_serial_driver digi_acceleport_4_device = {
Expand All @@ -550,7 +552,8 @@ static struct usb_serial_driver digi_acceleport_4_device = {
.tiocmget = digi_tiocmget,
.tiocmset = digi_tiocmset,
.attach = digi_startup,
.shutdown = digi_shutdown,
.disconnect = digi_disconnect,
.release = digi_release,
};


Expand Down Expand Up @@ -1556,16 +1559,23 @@ static int digi_startup(struct usb_serial *serial)
}


static void digi_shutdown(struct usb_serial *serial)
static void digi_disconnect(struct usb_serial *serial)
{
int i;
dbg("digi_shutdown: TOP, in_interrupt()=%ld", in_interrupt());
dbg("digi_disconnect: TOP, in_interrupt()=%ld", in_interrupt());

/* stop reads and writes on all ports */
for (i = 0; i < serial->type->num_ports + 1; i++) {
usb_kill_urb(serial->port[i]->read_urb);
usb_kill_urb(serial->port[i]->write_urb);
}
}


static void digi_release(struct usb_serial *serial)
{
int i;
dbg("digi_release: TOP, in_interrupt()=%ld", in_interrupt());

/* free the private data structures for all ports */
/* number of regular ports + 1 for the out-of-band port */
Expand Down
8 changes: 0 additions & 8 deletions drivers/usb/serial/empeg.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ static int empeg_chars_in_buffer(struct tty_struct *tty);
static void empeg_throttle(struct tty_struct *tty);
static void empeg_unthrottle(struct tty_struct *tty);
static int empeg_startup(struct usb_serial *serial);
static void empeg_shutdown(struct usb_serial *serial);
static void empeg_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios);
static void empeg_write_bulk_callback(struct urb *urb);
Expand Down Expand Up @@ -124,7 +123,6 @@ static struct usb_serial_driver empeg_device = {
.throttle = empeg_throttle,
.unthrottle = empeg_unthrottle,
.attach = empeg_startup,
.shutdown = empeg_shutdown,
.set_termios = empeg_set_termios,
.write = empeg_write,
.write_room = empeg_write_room,
Expand Down Expand Up @@ -427,12 +425,6 @@ static int empeg_startup(struct usb_serial *serial)
}


static void empeg_shutdown(struct usb_serial *serial)
{
dbg("%s", __func__);
}


static void empeg_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
Expand Down
14 changes: 0 additions & 14 deletions drivers/usb/serial/ftdi_sio.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,6 @@ static const char *ftdi_chip_name[] = {
/* function prototypes for a FTDI serial converter */
static int ftdi_sio_probe(struct usb_serial *serial,
const struct usb_device_id *id);
static void ftdi_shutdown(struct usb_serial *serial);
static int ftdi_sio_port_probe(struct usb_serial_port *port);
static int ftdi_sio_port_remove(struct usb_serial_port *port);
static int ftdi_open(struct tty_struct *tty,
Expand Down Expand Up @@ -779,7 +778,6 @@ static struct usb_serial_driver ftdi_sio_device = {
.ioctl = ftdi_ioctl,
.set_termios = ftdi_set_termios,
.break_ctl = ftdi_break_ctl,
.shutdown = ftdi_shutdown,
};


Expand Down Expand Up @@ -1594,18 +1592,6 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
return 0;
}

/* ftdi_shutdown is called from usbserial:usb_serial_disconnect
* it is called when the usb device is disconnected
*
* usbserial:usb_serial_disconnect
* calls __serial_close for each open of the port
* shutdown is called then (ie ftdi_shutdown)
*/
static void ftdi_shutdown(struct usb_serial *serial)
{
dbg("%s", __func__);
}

static void ftdi_sio_priv_release(struct kref *k)
{
struct ftdi_private *priv = container_of(k, struct ftdi_private, kref);
Expand Down
16 changes: 13 additions & 3 deletions drivers/usb/serial/garmin_gps.c
Original file line number Diff line number Diff line change
Expand Up @@ -1475,7 +1475,7 @@ static int garmin_attach(struct usb_serial *serial)
}


static void garmin_shutdown(struct usb_serial *serial)
static void garmin_disconnect(struct usb_serial *serial)
{
struct usb_serial_port *port = serial->port[0];
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
Expand All @@ -1484,8 +1484,17 @@ static void garmin_shutdown(struct usb_serial *serial)

usb_kill_urb(port->interrupt_in_urb);
del_timer_sync(&garmin_data_p->timer);
}


static void garmin_release(struct usb_serial *serial)
{
struct usb_serial_port *port = serial->port[0];
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);

dbg("%s", __func__);

kfree(garmin_data_p);
usb_set_serial_port_data(port, NULL);
}


Expand All @@ -1504,7 +1513,8 @@ static struct usb_serial_driver garmin_device = {
.throttle = garmin_throttle,
.unthrottle = garmin_unthrottle,
.attach = garmin_attach,
.shutdown = garmin_shutdown,
.disconnect = garmin_disconnect,
.release = garmin_release,
.write = garmin_write,
.write_room = garmin_write_room,
.write_bulk_callback = garmin_write_bulk_callback,
Expand Down
9 changes: 7 additions & 2 deletions drivers/usb/serial/generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ struct usb_serial_driver usb_serial_generic_device = {
.id_table = generic_device_ids,
.usb_driver = &generic_driver,
.num_ports = 1,
.shutdown = usb_serial_generic_shutdown,
.disconnect = usb_serial_generic_disconnect,
.release = usb_serial_generic_release,
.throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle,
.resume = usb_serial_generic_resume,
Expand Down Expand Up @@ -551,7 +552,7 @@ int usb_serial_handle_break(struct usb_serial_port *port)
}
EXPORT_SYMBOL_GPL(usb_serial_handle_break);

void usb_serial_generic_shutdown(struct usb_serial *serial)
void usb_serial_generic_disconnect(struct usb_serial *serial)
{
int i;

Expand All @@ -562,3 +563,7 @@ void usb_serial_generic_shutdown(struct usb_serial *serial)
generic_cleanup(serial->port[i]);
}

void usb_serial_generic_release(struct usb_serial *serial)
{
dbg("%s", __func__);
}
Loading

0 comments on commit f9c99bb

Please sign in to comment.