diff options
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
| -rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 8100f1d25904..d9fcdaedf389 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
| @@ -56,6 +56,7 @@ static __u16 vendor = FTDI_VID; | |||
| 56 | static __u16 product; | 56 | static __u16 product; |
| 57 | 57 | ||
| 58 | struct ftdi_private { | 58 | struct 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 */ |
| @@ -669,6 +670,8 @@ static struct usb_device_id id_table_combined [] = { | |||
| 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 }, |
| 671 | { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, | 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 }, | ||
| 672 | { }, /* Optional parameter entry */ | 675 | { }, /* Optional parameter entry */ |
| 673 | { } /* Terminating entry */ | 676 | { } /* Terminating entry */ |
| 674 | }; | 677 | }; |
| @@ -1352,6 +1355,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) | |||
| 1352 | return -ENOMEM; | 1355 | return -ENOMEM; |
| 1353 | } | 1356 | } |
| 1354 | 1357 | ||
| 1358 | kref_init(&priv->kref); | ||
| 1355 | spin_lock_init(&priv->rx_lock); | 1359 | spin_lock_init(&priv->rx_lock); |
| 1356 | spin_lock_init(&priv->tx_lock); | 1360 | spin_lock_init(&priv->tx_lock); |
| 1357 | init_waitqueue_head(&priv->delta_msr_wait); | 1361 | init_waitqueue_head(&priv->delta_msr_wait); |
| @@ -1468,6 +1472,13 @@ static void ftdi_shutdown(struct usb_serial *serial) | |||
| 1468 | dbg("%s", __func__); | 1472 | dbg("%s", __func__); |
| 1469 | } | 1473 | } |
| 1470 | 1474 | ||
| 1475 | static 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 | |||
| 1471 | static int ftdi_sio_port_remove(struct usb_serial_port *port) | 1482 | static int ftdi_sio_port_remove(struct usb_serial_port *port) |
| 1472 | { | 1483 | { |
| 1473 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1484 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
| @@ -1476,14 +1487,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) | |||
| 1476 | 1487 | ||
| 1477 | remove_sysfs_attrs(port); | 1488 | remove_sysfs_attrs(port); |
| 1478 | 1489 | ||
| 1479 | /* all open ports are closed at this point | 1490 | kref_put(&priv->kref, ftdi_sio_priv_release); |
| 1480 | * (by usbserial.c:__serial_close, which calls ftdi_close) | ||
| 1481 | */ | ||
| 1482 | |||
| 1483 | if (priv) { | ||
| 1484 | usb_set_serial_port_data(port, NULL); | ||
| 1485 | kfree(priv); | ||
| 1486 | } | ||
| 1487 | 1491 | ||
| 1488 | return 0; | 1492 | return 0; |
| 1489 | } | 1493 | } |
| @@ -1547,7 +1551,8 @@ static int ftdi_open(struct tty_struct *tty, | |||
| 1547 | dev_err(&port->dev, | 1551 | dev_err(&port->dev, |
| 1548 | "%s - failed submitting read urb, error %d\n", | 1552 | "%s - failed submitting read urb, error %d\n", |
| 1549 | __func__, result); | 1553 | __func__, result); |
| 1550 | 1554 | else | |
| 1555 | kref_get(&priv->kref); | ||
| 1551 | 1556 | ||
| 1552 | return result; | 1557 | return result; |
| 1553 | } /* ftdi_open */ | 1558 | } /* ftdi_open */ |
| @@ -1589,11 +1594,11 @@ static void ftdi_close(struct tty_struct *tty, | |||
| 1589 | mutex_unlock(&port->serial->disc_mutex); | 1594 | mutex_unlock(&port->serial->disc_mutex); |
| 1590 | 1595 | ||
| 1591 | /* cancel any scheduled reading */ | 1596 | /* cancel any scheduled reading */ |
| 1592 | cancel_delayed_work(&priv->rx_work); | 1597 | cancel_delayed_work_sync(&priv->rx_work); |
| 1593 | flush_scheduled_work(); | ||
| 1594 | 1598 | ||
| 1595 | /* shutdown our bulk read */ | 1599 | /* shutdown our bulk read */ |
| 1596 | usb_kill_urb(port->read_urb); | 1600 | usb_kill_urb(port->read_urb); |
| 1601 | kref_put(&priv->kref, ftdi_sio_priv_release); | ||
| 1597 | } /* ftdi_close */ | 1602 | } /* ftdi_close */ |
| 1598 | 1603 | ||
| 1599 | 1604 | ||
