diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-06-11 01:58:01 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-06-11 01:58:01 -0700 | 
| commit | 4894e4aca82aca927d0404ce61f021f790de4b1e (patch) | |
| tree | bbe0d083829f5858295298f188d885367cf4b1f6 /drivers/usb/serial/ftdi_sio.c | |
| parent | 05e882f890038c702a4f15d385135d03cf74ad48 (diff) | |
| parent | 07a2039b8eb0af4ff464efd3dfd95de5c02648c6 (diff) | |
| download | olio-linux-3.10-4894e4aca82aca927d0404ce61f021f790de4b1e.tar.xz olio-linux-3.10-4894e4aca82aca927d0404ce61f021f790de4b1e.zip  | |
Merge commit 'v2.6.30' into next
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 8100f1d2590..d9fcdaedf38 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -56,6 +56,7 @@ static __u16 vendor = FTDI_VID;  static __u16 product;  struct ftdi_private { +	struct kref kref;  	ftdi_chip_type_t chip_type;  				/* type of device, either SIO or FT8U232AM */  	int baud_base;		/* baud base clock for divisor setting */ @@ -669,6 +670,8 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(ADI_VID, ADI_GNICE_PID),  		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },  	{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, +	{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), +		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },  	{ },					/* Optional parameter entry */  	{ }					/* Terminating entry */  }; @@ -1352,6 +1355,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)  		return -ENOMEM;  	} +	kref_init(&priv->kref);  	spin_lock_init(&priv->rx_lock);  	spin_lock_init(&priv->tx_lock);  	init_waitqueue_head(&priv->delta_msr_wait); @@ -1468,6 +1472,13 @@ 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); + +	kfree(priv); +} +  static int ftdi_sio_port_remove(struct usb_serial_port *port)  {  	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)  	remove_sysfs_attrs(port); -	/* all open ports are closed at this point -	 *    (by usbserial.c:__serial_close, which calls ftdi_close) -	 */ - -	if (priv) { -		usb_set_serial_port_data(port, NULL); -		kfree(priv); -	} +	kref_put(&priv->kref, ftdi_sio_priv_release);  	return 0;  } @@ -1547,7 +1551,8 @@ static int ftdi_open(struct tty_struct *tty,  		dev_err(&port->dev,  			"%s - failed submitting read urb, error %d\n",  			__func__, result); - +	else +		kref_get(&priv->kref);  	return result;  } /* ftdi_open */ @@ -1589,11 +1594,11 @@ static void ftdi_close(struct tty_struct *tty,  	mutex_unlock(&port->serial->disc_mutex);  	/* cancel any scheduled reading */ -	cancel_delayed_work(&priv->rx_work); -	flush_scheduled_work(); +	cancel_delayed_work_sync(&priv->rx_work);  	/* shutdown our bulk read */  	usb_kill_urb(port->read_urb); +	kref_put(&priv->kref, ftdi_sio_priv_release);  } /* ftdi_close */  |