aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/ftdi_sio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r--drivers/usb/serial/ftdi_sio.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index dcc87aaa8628..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 */
@@ -668,6 +669,9 @@ static struct usb_device_id id_table_combined [] = {
668 { USB_DEVICE(DE_VID, WHT_PID) }, 669 { USB_DEVICE(DE_VID, WHT_PID) },
669 { USB_DEVICE(ADI_VID, ADI_GNICE_PID), 670 { USB_DEVICE(ADI_VID, ADI_GNICE_PID),
670 .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, 671 .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
672 { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
673 { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
674 .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
671 { }, /* Optional parameter entry */ 675 { }, /* Optional parameter entry */
672 { } /* Terminating entry */ 676 { } /* Terminating entry */
673}; 677};
@@ -1351,6 +1355,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
1351 return -ENOMEM; 1355 return -ENOMEM;
1352 } 1356 }
1353 1357
1358 kref_init(&priv->kref);
1354 spin_lock_init(&priv->rx_lock); 1359 spin_lock_init(&priv->rx_lock);
1355 spin_lock_init(&priv->tx_lock); 1360 spin_lock_init(&priv->tx_lock);
1356 init_waitqueue_head(&priv->delta_msr_wait); 1361 init_waitqueue_head(&priv->delta_msr_wait);
@@ -1467,6 +1472,13 @@ static void ftdi_shutdown(struct usb_serial *serial)
1467 dbg("%s", __func__); 1472 dbg("%s", __func__);
1468} 1473}
1469 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
1470static int ftdi_sio_port_remove(struct usb_serial_port *port) 1482static int ftdi_sio_port_remove(struct usb_serial_port *port)
1471{ 1483{
1472 struct ftdi_private *priv = usb_get_serial_port_data(port); 1484 struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1481,7 +1493,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
1481 1493
1482 if (priv) { 1494 if (priv) {
1483 usb_set_serial_port_data(port, NULL); 1495 usb_set_serial_port_data(port, NULL);
1484 kfree(priv); 1496 kref_put(&priv->kref, ftdi_sio_priv_release);
1485 } 1497 }
1486 1498
1487 return 0; 1499 return 0;
@@ -1546,7 +1558,8 @@ static int ftdi_open(struct tty_struct *tty,
1546 dev_err(&port->dev, 1558 dev_err(&port->dev,
1547 "%s - failed submitting read urb, error %d\n", 1559 "%s - failed submitting read urb, error %d\n",
1548 __func__, result); 1560 __func__, result);
1549 1561 else
1562 kref_get(&priv->kref);
1550 1563
1551 return result; 1564 return result;
1552} /* ftdi_open */ 1565} /* ftdi_open */
@@ -1588,11 +1601,11 @@ static void ftdi_close(struct tty_struct *tty,
1588 mutex_unlock(&port->serial->disc_mutex); 1601 mutex_unlock(&port->serial->disc_mutex);
1589 1602
1590 /* cancel any scheduled reading */ 1603 /* cancel any scheduled reading */
1591 cancel_delayed_work(&priv->rx_work); 1604 cancel_delayed_work_sync(&priv->rx_work);
1592 flush_scheduled_work();
1593 1605
1594 /* shutdown our bulk read */ 1606 /* shutdown our bulk read */
1595 usb_kill_urb(port->read_urb); 1607 usb_kill_urb(port->read_urb);
1608 kref_put(&priv->kref, ftdi_sio_priv_release);
1596} /* ftdi_close */ 1609} /* ftdi_close */
1597 1610
1598 1611