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[] = { |