diff options
Diffstat (limited to 'drivers/usb/serial/pl2303.c')
| -rw-r--r-- | drivers/usb/serial/pl2303.c | 90 | 
1 files changed, 54 insertions, 36 deletions
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 892ebdc7a36..60024190136 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -133,12 +133,15 @@ enum pl2303_type {  	HX,		/* HX version of the pl2303 chip */  }; +struct pl2303_serial_private { +	enum pl2303_type type; +}; +  struct pl2303_private {  	spinlock_t lock;  	wait_queue_head_t delta_msr_wait;  	u8 line_control;  	u8 line_status; -	enum pl2303_type type;  };  static int pl2303_vendor_read(__u16 value, __u16 index, @@ -167,14 +170,19 @@ static int pl2303_vendor_write(__u16 value, __u16 index,  static int pl2303_startup(struct usb_serial *serial)  { -	struct pl2303_private *priv; +	struct pl2303_serial_private *spriv;  	enum pl2303_type type = type_0;  	unsigned char *buf; -	int i; + +	spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); +	if (!spriv) +		return -ENOMEM;  	buf = kmalloc(10, GFP_KERNEL); -	if (buf == NULL) +	if (!buf) { +		kfree(spriv);  		return -ENOMEM; +	}  	if (serial->dev->descriptor.bDeviceClass == 0x02)  		type = type_0; @@ -186,15 +194,8 @@ static int pl2303_startup(struct usb_serial *serial)  		type = type_1;  	dev_dbg(&serial->interface->dev, "device type: %d\n", type); -	for (i = 0; i < serial->num_ports; ++i) { -		priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL); -		if (!priv) -			goto cleanup; -		spin_lock_init(&priv->lock); -		init_waitqueue_head(&priv->delta_msr_wait); -		priv->type = type; -		usb_set_serial_port_data(serial->port[i], priv); -	} +	spriv->type = type; +	usb_set_serial_data(serial, spriv);  	pl2303_vendor_read(0x8484, 0, serial, buf);  	pl2303_vendor_write(0x0404, 0, serial); @@ -213,15 +214,40 @@ static int pl2303_startup(struct usb_serial *serial)  	kfree(buf);  	return 0; +} -cleanup: -	kfree(buf); -	for (--i; i >= 0; --i) { -		priv = usb_get_serial_port_data(serial->port[i]); -		kfree(priv); -		usb_set_serial_port_data(serial->port[i], NULL); -	} -	return -ENOMEM; +static void pl2303_release(struct usb_serial *serial) +{ +	struct pl2303_serial_private *spriv; + +	spriv = usb_get_serial_data(serial); +	kfree(spriv); +} + +static int pl2303_port_probe(struct usb_serial_port *port) +{ +	struct pl2303_private *priv; + +	priv = kzalloc(sizeof(*priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; + +	spin_lock_init(&priv->lock); +	init_waitqueue_head(&priv->delta_msr_wait); + +	usb_set_serial_port_data(port, priv); + +	return 0; +} + +static int pl2303_port_remove(struct usb_serial_port *port) +{ +	struct pl2303_private *priv; + +	priv = usb_get_serial_port_data(port); +	kfree(priv); + +	return 0;  }  static int set_control_lines(struct usb_device *dev, u8 value) @@ -240,6 +266,7 @@ static void pl2303_set_termios(struct tty_struct *tty,  		struct usb_serial_port *port, struct ktermios *old_termios)  {  	struct usb_serial *serial = port->serial; +	struct pl2303_serial_private *spriv = usb_get_serial_data(serial);  	struct pl2303_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	unsigned int cflag; @@ -323,7 +350,7 @@ static void pl2303_set_termios(struct tty_struct *tty,  		}  		if (baud > 1228800) {  			/* type_0, type_1 only support up to 1228800 baud */ -			if (priv->type != HX) +			if (spriv->type != HX)  				baud = 1228800;  			else if (baud > 6000000)  				baud = 6000000; @@ -426,7 +453,7 @@ static void pl2303_set_termios(struct tty_struct *tty,  	     buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);  	if (cflag & CRTSCTS) { -		if (priv->type == HX) +		if (spriv->type == HX)  			pl2303_vendor_write(0x0, 0x61, serial);  		else  			pl2303_vendor_write(0x0, 0x41, serial); @@ -468,10 +495,10 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)  {  	struct ktermios tmp_termios;  	struct usb_serial *serial = port->serial; -	struct pl2303_private *priv = usb_get_serial_port_data(port); +	struct pl2303_serial_private *spriv = usb_get_serial_data(serial);  	int result; -	if (priv->type != HX) { +	if (spriv->type != HX) {  		usb_clear_halt(serial->dev, port->write_urb->pipe);  		usb_clear_halt(serial->dev, port->read_urb->pipe);  	} else { @@ -655,17 +682,6 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state)  		dev_err(&port->dev, "error sending break = %d\n", result);  } -static void pl2303_release(struct usb_serial *serial) -{ -	int i; -	struct pl2303_private *priv; - -	for (i = 0; i < serial->num_ports; ++i) { -		priv = usb_get_serial_port_data(serial->port[i]); -		kfree(priv); -	} -} -  static void pl2303_update_line_status(struct usb_serial_port *port,  				      unsigned char *data,  				      unsigned int actual_length) @@ -827,6 +843,8 @@ static struct usb_serial_driver pl2303_device = {  	.read_int_callback =	pl2303_read_int_callback,  	.attach =		pl2303_startup,  	.release =		pl2303_release, +	.port_probe =		pl2303_port_probe, +	.port_remove =		pl2303_port_remove,  };  static struct usb_serial_driver * const serial_drivers[] = {  |