aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/serial/ftdi_sio.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index aab567644b99..0ab8474b00cb 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -56,6 +56,7 @@ static __u16 vendor = FTDI_VID;
56static __u16 product; 56static __u16 product;
57 57
58struct ftdi_private { 58struct ftdi_private {
59 struct kref kref;
59 ftdi_chip_type_t chip_type; 60 ftdi_chip_type_t chip_type;
60 /* type of device, either SIO or FT8U232AM */ 61 /* type of device, either SIO or FT8U232AM */
61 int baud_base; /* baud base clock for divisor setting */ 62 int baud_base; /* baud base clock for divisor setting */
@@ -1354,6 +1355,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
1354 return -ENOMEM; 1355 return -ENOMEM;
1355 } 1356 }
1356 1357
1358 kref_init(&priv->kref);
1357 spin_lock_init(&priv->rx_lock); 1359 spin_lock_init(&priv->rx_lock);
1358 spin_lock_init(&priv->tx_lock); 1360 spin_lock_init(&priv->tx_lock);
1359 init_waitqueue_head(&priv->delta_msr_wait); 1361 init_waitqueue_head(&priv->delta_msr_wait);
@@ -1470,6 +1472,13 @@ static void ftdi_shutdown(struct usb_serial *serial)
1470 dbg("%s", __func__); 1472 dbg("%s", __func__);
1471} 1473}
1472 1474
1475static void ftdi_sio_priv_release(struct kref *k)
1476{
1477 struct ftdi_private *priv = container_of(k, struct ftdi_private, kref);
1478
1479 kfree(priv);
1480}
1481
1473static int ftdi_sio_port_remove(struct usb_serial_port *port) 1482static int ftdi_sio_port_remove(struct usb_serial_port *port)
1474{ 1483{
1475 struct ftdi_private *priv = usb_get_serial_port_data(port); 1484 struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1484,7 +1493,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
1484 1493
1485 if (priv) { 1494 if (priv) {
1486 usb_set_serial_port_data(port, NULL); 1495 usb_set_serial_port_data(port, NULL);
1487 kfree(priv); 1496 kref_put(&priv->kref, ftdi_sio_priv_release);
1488 } 1497 }
1489 1498
1490 return 0; 1499 return 0;
@@ -1549,7 +1558,8 @@ static int ftdi_open(struct tty_struct *tty,
1549 dev_err(&port->dev, 1558 dev_err(&port->dev,
1550 "%s - failed submitting read urb, error %d\n", 1559 "%s - failed submitting read urb, error %d\n",
1551 __func__, result); 1560 __func__, result);
1552 1561 else
1562 kref_get(&priv->kref);
1553 1563
1554 return result; 1564 return result;
1555} /* ftdi_open */ 1565} /* ftdi_open */
@@ -1591,11 +1601,11 @@ static void ftdi_close(struct tty_struct *tty,
1591 mutex_unlock(&port->serial->disc_mutex); 1601 mutex_unlock(&port->serial->disc_mutex);
1592 1602
1593 /* cancel any scheduled reading */ 1603 /* cancel any scheduled reading */
1594 cancel_delayed_work(&priv->rx_work); 1604 cancel_delayed_work_sync(&priv->rx_work);
1595 flush_scheduled_work();
1596 1605
1597 /* shutdown our bulk read */ 1606 /* shutdown our bulk read */
1598 usb_kill_urb(port->read_urb); 1607 usb_kill_urb(port->read_urb);
1608 kref_put(&priv->kref, ftdi_sio_priv_release);
1599} /* ftdi_close */ 1609} /* ftdi_close */
1600 1610
1601 1611