Skip to content

Commit

Permalink
USB: ftdi_sio: remove obsolete port data refcounting
Browse files Browse the repository at this point in the history
Remove the port data refcounting and release the private data
explicitly at port remove.

The port data refcounting was used to make sure the port data was not
freed until the last tty reference was closed. Since moving over to tty
ports, the underlying assumptions are no longer valid as close is now
called as part of tty port shutdown, which can occur before the final
tty reference is dropped on device disconnect.

This means that the private port data refcounting is now completely
useless, as the last reference will always be dropped on port_remove.

Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Johan Hovold authored and Greg Kroah-Hartman committed Mar 25, 2013
1 parent afc2c9a commit 4cba98f
Showing 1 changed file with 2 additions and 32 deletions.
34 changes: 2 additions & 32 deletions drivers/usb/serial/ftdi_sio.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ static __u16 vendor = FTDI_VID;
static __u16 product;

struct ftdi_private {
struct kref kref;
enum ftdi_chip_type chip_type;
/* type of device, either SIO or FT8U232AM */
int baud_base; /* baud base clock for divisor setting */
Expand Down Expand Up @@ -910,7 +909,6 @@ static int ftdi_sio_probe(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, struct usb_serial_port *port);
static void ftdi_close(struct usb_serial_port *port);
static void ftdi_dtr_rts(struct usb_serial_port *port, int on);
static void ftdi_process_read_urb(struct urb *urb);
static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
Expand Down Expand Up @@ -950,7 +948,6 @@ static struct usb_serial_driver ftdi_sio_device = {
.port_probe = ftdi_sio_port_probe,
.port_remove = ftdi_sio_port_remove,
.open = ftdi_open,
.close = ftdi_close,
.dtr_rts = ftdi_dtr_rts,
.throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle,
Expand Down Expand Up @@ -1687,7 +1684,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
return -ENOMEM;
}

kref_init(&priv->kref);
mutex_init(&priv->cfg_lock);

priv->flags = ASYNC_LOW_LATENCY;
Expand Down Expand Up @@ -1825,13 +1821,6 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
return 0;
}

static void ftdi_sio_priv_release(struct kref *k)
{
struct ftdi_private *priv = container_of(k, struct ftdi_private, kref);

kfree(priv);
}

static int ftdi_sio_port_remove(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
Expand All @@ -1840,7 +1829,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)

remove_sysfs_attrs(port);

kref_put(&priv->kref, ftdi_sio_priv_release);
kfree(priv);

return 0;
}
Expand All @@ -1850,7 +1839,6 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
struct ktermios dummy;
struct usb_device *dev = port->serial->dev;
struct ftdi_private *priv = usb_get_serial_port_data(port);
int result;

/* No error checking for this (will get errors later anyway) */
/* See ftdi_sio.h for description of what is reset */
Expand All @@ -1869,12 +1857,7 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
ftdi_set_termios(tty, port, &dummy);
}

/* Start reading from the device */
result = usb_serial_generic_open(tty, port);
if (!result)
kref_get(&priv->kref);

return result;
return usb_serial_generic_open(tty, port);
}

static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
Expand All @@ -1899,19 +1882,6 @@ static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
}

/*
* usbserial:__serial_close only calls ftdi_close if the point is open
*
* This only gets called when it is the last close
*/
static void ftdi_close(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);

usb_serial_generic_close(port);
kref_put(&priv->kref, ftdi_sio_priv_release);
}

/* The SIO requires the first byte to have:
* B0 1
* B1 0
Expand Down

0 comments on commit 4cba98f

Please sign in to comment.