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 892ebdc7a364..600241901361 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
| @@ -133,12 +133,15 @@ enum pl2303_type { | |||
| 133 | HX, /* HX version of the pl2303 chip */ | 133 | HX, /* HX version of the pl2303 chip */ |
| 134 | }; | 134 | }; |
| 135 | 135 | ||
| 136 | struct pl2303_serial_private { | ||
| 137 | enum pl2303_type type; | ||
| 138 | }; | ||
| 139 | |||
| 136 | struct pl2303_private { | 140 | struct pl2303_private { |
| 137 | spinlock_t lock; | 141 | spinlock_t lock; |
| 138 | wait_queue_head_t delta_msr_wait; | 142 | wait_queue_head_t delta_msr_wait; |
| 139 | u8 line_control; | 143 | u8 line_control; |
| 140 | u8 line_status; | 144 | u8 line_status; |
| 141 | enum pl2303_type type; | ||
| 142 | }; | 145 | }; |
| 143 | 146 | ||
| 144 | static int pl2303_vendor_read(__u16 value, __u16 index, | 147 | static int pl2303_vendor_read(__u16 value, __u16 index, |
| @@ -167,14 +170,19 @@ static int pl2303_vendor_write(__u16 value, __u16 index, | |||
| 167 | 170 | ||
| 168 | static int pl2303_startup(struct usb_serial *serial) | 171 | static int pl2303_startup(struct usb_serial *serial) |
| 169 | { | 172 | { |
| 170 | struct pl2303_private *priv; | 173 | struct pl2303_serial_private *spriv; |
| 171 | enum pl2303_type type = type_0; | 174 | enum pl2303_type type = type_0; |
| 172 | unsigned char *buf; | 175 | unsigned char *buf; |
| 173 | int i; | 176 | |
| 177 | spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); | ||
| 178 | if (!spriv) | ||
| 179 | return -ENOMEM; | ||
| 174 | 180 | ||
| 175 | buf = kmalloc(10, GFP_KERNEL); | 181 | buf = kmalloc(10, GFP_KERNEL); |
| 176 | if (buf == NULL) | 182 | if (!buf) { |
| 183 | kfree(spriv); | ||
| 177 | return -ENOMEM; | 184 | return -ENOMEM; |
| 185 | } | ||
| 178 | 186 | ||
| 179 | if (serial->dev->descriptor.bDeviceClass == 0x02) | 187 | if (serial->dev->descriptor.bDeviceClass == 0x02) |
| 180 | type = type_0; | 188 | type = type_0; |
| @@ -186,15 +194,8 @@ static int pl2303_startup(struct usb_serial *serial) | |||
| 186 | type = type_1; | 194 | type = type_1; |
| 187 | dev_dbg(&serial->interface->dev, "device type: %d\n", type); | 195 | dev_dbg(&serial->interface->dev, "device type: %d\n", type); |
| 188 | 196 | ||
| 189 | for (i = 0; i < serial->num_ports; ++i) { | 197 | spriv->type = type; |
| 190 | priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL); | 198 | usb_set_serial_data(serial, spriv); |
| 191 | if (!priv) | ||
| 192 | goto cleanup; | ||
| 193 | spin_lock_init(&priv->lock); | ||
| 194 | init_waitqueue_head(&priv->delta_msr_wait); | ||
| 195 | priv->type = type; | ||
| 196 | usb_set_serial_port_data(serial->port[i], priv); | ||
| 197 | } | ||
| 198 | 199 | ||
| 199 | pl2303_vendor_read(0x8484, 0, serial, buf); | 200 | pl2303_vendor_read(0x8484, 0, serial, buf); |
| 200 | pl2303_vendor_write(0x0404, 0, serial); | 201 | pl2303_vendor_write(0x0404, 0, serial); |
| @@ -213,15 +214,40 @@ static int pl2303_startup(struct usb_serial *serial) | |||
| 213 | 214 | ||
| 214 | kfree(buf); | 215 | kfree(buf); |
| 215 | return 0; | 216 | return 0; |
| 217 | } | ||
| 216 | 218 | ||
| 217 | cleanup: | 219 | static void pl2303_release(struct usb_serial *serial) |
| 218 | kfree(buf); | 220 | { |
| 219 | for (--i; i >= 0; --i) { | 221 | struct pl2303_serial_private *spriv; |
| 220 | priv = usb_get_serial_port_data(serial->port[i]); | 222 | |
| 221 | kfree(priv); | 223 | spriv = usb_get_serial_data(serial); |
| 222 | usb_set_serial_port_data(serial->port[i], NULL); | 224 | kfree(spriv); |
| 223 | } | 225 | } |
| 224 | return -ENOMEM; | 226 | |
| 227 | static int pl2303_port_probe(struct usb_serial_port *port) | ||
| 228 | { | ||
| 229 | struct pl2303_private *priv; | ||
| 230 | |||
| 231 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
| 232 | if (!priv) | ||
| 233 | return -ENOMEM; | ||
| 234 | |||
| 235 | spin_lock_init(&priv->lock); | ||
| 236 | init_waitqueue_head(&priv->delta_msr_wait); | ||
| 237 | |||
| 238 | usb_set_serial_port_data(port, priv); | ||
| 239 | |||
| 240 | return 0; | ||
| 241 | } | ||
| 242 | |||
| 243 | static int pl2303_port_remove(struct usb_serial_port *port) | ||
| 244 | { | ||
| 245 | struct pl2303_private *priv; | ||
| 246 | |||
| 247 | priv = usb_get_serial_port_data(port); | ||
| 248 | kfree(priv); | ||
| 249 | |||
| 250 | return 0; | ||
| 225 | } | 251 | } |
| 226 | 252 | ||
| 227 | static int set_control_lines(struct usb_device *dev, u8 value) | 253 | static int set_control_lines(struct usb_device *dev, u8 value) |
| @@ -240,6 +266,7 @@ static void pl2303_set_termios(struct tty_struct *tty, | |||
| 240 | struct usb_serial_port *port, struct ktermios *old_termios) | 266 | struct usb_serial_port *port, struct ktermios *old_termios) |
| 241 | { | 267 | { |
| 242 | struct usb_serial *serial = port->serial; | 268 | struct usb_serial *serial = port->serial; |
| 269 | struct pl2303_serial_private *spriv = usb_get_serial_data(serial); | ||
| 243 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 270 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
| 244 | unsigned long flags; | 271 | unsigned long flags; |
| 245 | unsigned int cflag; | 272 | unsigned int cflag; |
| @@ -323,7 +350,7 @@ static void pl2303_set_termios(struct tty_struct *tty, | |||
| 323 | } | 350 | } |
| 324 | if (baud > 1228800) { | 351 | if (baud > 1228800) { |
| 325 | /* type_0, type_1 only support up to 1228800 baud */ | 352 | /* type_0, type_1 only support up to 1228800 baud */ |
| 326 | if (priv->type != HX) | 353 | if (spriv->type != HX) |
| 327 | baud = 1228800; | 354 | baud = 1228800; |
| 328 | else if (baud > 6000000) | 355 | else if (baud > 6000000) |
| 329 | baud = 6000000; | 356 | baud = 6000000; |
| @@ -426,7 +453,7 @@ static void pl2303_set_termios(struct tty_struct *tty, | |||
| 426 | buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); | 453 | buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); |
| 427 | 454 | ||
| 428 | if (cflag & CRTSCTS) { | 455 | if (cflag & CRTSCTS) { |
| 429 | if (priv->type == HX) | 456 | if (spriv->type == HX) |
| 430 | pl2303_vendor_write(0x0, 0x61, serial); | 457 | pl2303_vendor_write(0x0, 0x61, serial); |
| 431 | else | 458 | else |
| 432 | pl2303_vendor_write(0x0, 0x41, serial); | 459 | pl2303_vendor_write(0x0, 0x41, serial); |
| @@ -468,10 +495,10 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
| 468 | { | 495 | { |
| 469 | struct ktermios tmp_termios; | 496 | struct ktermios tmp_termios; |
| 470 | struct usb_serial *serial = port->serial; | 497 | struct usb_serial *serial = port->serial; |
| 471 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 498 | struct pl2303_serial_private *spriv = usb_get_serial_data(serial); |
| 472 | int result; | 499 | int result; |
| 473 | 500 | ||
| 474 | if (priv->type != HX) { | 501 | if (spriv->type != HX) { |
| 475 | usb_clear_halt(serial->dev, port->write_urb->pipe); | 502 | usb_clear_halt(serial->dev, port->write_urb->pipe); |
| 476 | usb_clear_halt(serial->dev, port->read_urb->pipe); | 503 | usb_clear_halt(serial->dev, port->read_urb->pipe); |
| 477 | } else { | 504 | } else { |
| @@ -655,17 +682,6 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state) | |||
| 655 | dev_err(&port->dev, "error sending break = %d\n", result); | 682 | dev_err(&port->dev, "error sending break = %d\n", result); |
| 656 | } | 683 | } |
| 657 | 684 | ||
| 658 | static void pl2303_release(struct usb_serial *serial) | ||
| 659 | { | ||
| 660 | int i; | ||
| 661 | struct pl2303_private *priv; | ||
| 662 | |||
| 663 | for (i = 0; i < serial->num_ports; ++i) { | ||
| 664 | priv = usb_get_serial_port_data(serial->port[i]); | ||
| 665 | kfree(priv); | ||
| 666 | } | ||
| 667 | } | ||
| 668 | |||
| 669 | static void pl2303_update_line_status(struct usb_serial_port *port, | 685 | static void pl2303_update_line_status(struct usb_serial_port *port, |
| 670 | unsigned char *data, | 686 | unsigned char *data, |
| 671 | unsigned int actual_length) | 687 | unsigned int actual_length) |
| @@ -827,6 +843,8 @@ static struct usb_serial_driver pl2303_device = { | |||
| 827 | .read_int_callback = pl2303_read_int_callback, | 843 | .read_int_callback = pl2303_read_int_callback, |
| 828 | .attach = pl2303_startup, | 844 | .attach = pl2303_startup, |
| 829 | .release = pl2303_release, | 845 | .release = pl2303_release, |
| 846 | .port_probe = pl2303_port_probe, | ||
| 847 | .port_remove = pl2303_port_remove, | ||
| 830 | }; | 848 | }; |
| 831 | 849 | ||
| 832 | static struct usb_serial_driver * const serial_drivers[] = { | 850 | static struct usb_serial_driver * const serial_drivers[] = { |
