aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/kobil_sct.c
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2008-07-22 06:09:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-22 16:03:22 -0400
commit95da310e66ee8090119596c70ca8432e57f9a97f (patch)
tree7f18c30e9c9ad4d7d53df6453fa338be06f09a85 /drivers/usb/serial/kobil_sct.c
parent1aa3692da57c773e5c76de55c5c4a953962d360e (diff)
usb_serial: API all change
USB serial likes to use port->tty back pointers for the real work it does and to do so without any actual locking. Unfortunately when you consider hangup events, hangup/parallel reopen or even worse hangup followed by parallel close events the tty->port and port->tty pointers are not guaranteed to be the same as port->tty is the active tty while tty->port is the port the tty may or may not still be attached to. So rework the entire API to pass the tty struct. For console cases we need to pass both for now. This shows up multiple drivers that immediately crash with USB console some of which have been fixed in the process. Longer term we need a proper tty as console abstraction Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/usb/serial/kobil_sct.c')
-rw-r--r--drivers/usb/serial/kobil_sct.c80
1 files changed, 44 insertions, 36 deletions
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 693f00da7c03..40c67f0096b1 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -70,19 +70,22 @@ static int debug;
70/* Function prototypes */ 70/* Function prototypes */
71static int kobil_startup (struct usb_serial *serial); 71static int kobil_startup (struct usb_serial *serial);
72static void kobil_shutdown (struct usb_serial *serial); 72static void kobil_shutdown (struct usb_serial *serial);
73static int kobil_open (struct usb_serial_port *port, struct file *filp); 73static int kobil_open (struct tty_struct *tty,
74static void kobil_close (struct usb_serial_port *port, struct file *filp); 74 struct usb_serial_port *port, struct file *filp);
75static int kobil_write (struct usb_serial_port *port, 75static void kobil_close (struct tty_struct *tty, struct usb_serial_port *port,
76 struct file *filp);
77static int kobil_write (struct tty_struct *tty, struct usb_serial_port *port,
76 const unsigned char *buf, int count); 78 const unsigned char *buf, int count);
77static int kobil_write_room(struct usb_serial_port *port); 79static int kobil_write_room(struct tty_struct *tty);
78static int kobil_ioctl(struct usb_serial_port *port, struct file *file, 80static int kobil_ioctl(struct tty_struct *tty, struct file *file,
79 unsigned int cmd, unsigned long arg); 81 unsigned int cmd, unsigned long arg);
80static int kobil_tiocmget(struct usb_serial_port *port, struct file *file); 82static int kobil_tiocmget(struct tty_struct *tty, struct file *file);
81static int kobil_tiocmset(struct usb_serial_port *port, struct file *file, 83static int kobil_tiocmset(struct tty_struct *tty, struct file *file,
82 unsigned int set, unsigned int clear); 84 unsigned int set, unsigned int clear);
83static void kobil_read_int_callback( struct urb *urb ); 85static void kobil_read_int_callback( struct urb *urb );
84static void kobil_write_callback( struct urb *purb ); 86static void kobil_write_callback( struct urb *purb );
85static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old); 87static void kobil_set_termios(struct tty_struct *tty,
88 struct usb_serial_port *port, struct ktermios *old);
86 89
87 90
88static struct usb_device_id id_table [] = { 91static struct usb_device_id id_table [] = {
@@ -201,8 +204,8 @@ static void kobil_shutdown (struct usb_serial *serial)
201 dbg("%s - port %d", __func__, serial->port[0]->number); 204 dbg("%s - port %d", __func__, serial->port[0]->number);
202 205
203 for (i=0; i < serial->num_ports; ++i) { 206 for (i=0; i < serial->num_ports; ++i) {
204 while (serial->port[i]->open_count > 0) { 207 while (serial->port[i]->port.count > 0) {
205 kobil_close (serial->port[i], NULL); 208 kobil_close (NULL, serial->port[i], NULL);
206 } 209 }
207 kfree(usb_get_serial_port_data(serial->port[i])); 210 kfree(usb_get_serial_port_data(serial->port[i]));
208 usb_set_serial_port_data(serial->port[i], NULL); 211 usb_set_serial_port_data(serial->port[i], NULL);
@@ -210,7 +213,8 @@ static void kobil_shutdown (struct usb_serial *serial)
210} 213}
211 214
212 215
213static int kobil_open (struct usb_serial_port *port, struct file *filp) 216static int kobil_open(struct tty_struct *tty,
217 struct usb_serial_port *port, struct file *filp)
214{ 218{
215 int result = 0; 219 int result = 0;
216 struct kobil_private *priv; 220 struct kobil_private *priv;
@@ -229,14 +233,15 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
229 * the data through, otherwise it is scheduled, and with high 233 * the data through, otherwise it is scheduled, and with high
230 * data rates (like with OHCI) data can get lost. 234 * data rates (like with OHCI) data can get lost.
231 */ 235 */
232 port->tty->low_latency = 1; 236 if (tty) {
233 237 tty->low_latency = 1;
234 // without this, every push_tty_char is echoed :-( 238
235 port->tty->termios->c_lflag = 0; 239 /* Default to echo off and other sane device settings */
236 port->tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE); 240 tty->termios->c_lflag = 0;
237 port->tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF; 241 tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE);
238 port->tty->termios->c_oflag &= ~ONLCR; // do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) 242 tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
239 243 tty->termios->c_oflag &= ~ONLCR; // do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D)
244 }
240 // allocate memory for transfer buffer 245 // allocate memory for transfer buffer
241 transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); 246 transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
242 if (! transfer_buffer) { 247 if (! transfer_buffer) {
@@ -330,7 +335,8 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
330} 335}
331 336
332 337
333static void kobil_close (struct usb_serial_port *port, struct file *filp) 338static void kobil_close(struct tty_struct *tty,
339 struct usb_serial_port *port, struct file *filp)
334{ 340{
335 dbg("%s - port %d", __func__, port->number); 341 dbg("%s - port %d", __func__, port->number);
336 342
@@ -360,7 +366,7 @@ static void kobil_read_int_callback(struct urb *urb)
360 return; 366 return;
361 } 367 }
362 368
363 tty = port->tty; 369 tty = port->port.tty;
364 if (urb->actual_length) { 370 if (urb->actual_length) {
365 371
366 // BEGIN DEBUG 372 // BEGIN DEBUG
@@ -395,7 +401,7 @@ static void kobil_write_callback( struct urb *purb )
395} 401}
396 402
397 403
398static int kobil_write (struct usb_serial_port *port, 404static int kobil_write (struct tty_struct *tty, struct usb_serial_port *port,
399 const unsigned char *buf, int count) 405 const unsigned char *buf, int count)
400{ 406{
401 int length = 0; 407 int length = 0;
@@ -417,12 +423,9 @@ static int kobil_write (struct usb_serial_port *port,
417 423
418 // Copy data to buffer 424 // Copy data to buffer
419 memcpy (priv->buf + priv->filled, buf, count); 425 memcpy (priv->buf + priv->filled, buf, count);
420
421 usb_serial_debug_data(debug, &port->dev, __func__, count, priv->buf + priv->filled); 426 usb_serial_debug_data(debug, &port->dev, __func__, count, priv->buf + priv->filled);
422
423 priv->filled = priv->filled + count; 427 priv->filled = priv->filled + count;
424 428
425
426 // only send complete block. TWIN, KAAN SIM and adapter K use the same protocol. 429 // only send complete block. TWIN, KAAN SIM and adapter K use the same protocol.
427 if ( ((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) || 430 if ( ((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) ||
428 ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4))) ) { 431 ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4))) ) {
@@ -478,15 +481,17 @@ static int kobil_write (struct usb_serial_port *port,
478} 481}
479 482
480 483
481static int kobil_write_room (struct usb_serial_port *port) 484static int kobil_write_room (struct tty_struct *tty)
482{ 485{
483 //dbg("%s - port %d", __func__, port->number); 486 //dbg("%s - port %d", __func__, port->number);
487 /* FIXME */
484 return 8; 488 return 8;
485} 489}
486 490
487 491
488static int kobil_tiocmget(struct usb_serial_port *port, struct file *file) 492static int kobil_tiocmget(struct tty_struct *tty, struct file *file)
489{ 493{
494 struct usb_serial_port *port = tty->driver_data;
490 struct kobil_private * priv; 495 struct kobil_private * priv;
491 int result; 496 int result;
492 unsigned char *transfer_buffer; 497 unsigned char *transfer_buffer;
@@ -524,9 +529,10 @@ static int kobil_tiocmget(struct usb_serial_port *port, struct file *file)
524 return result; 529 return result;
525} 530}
526 531
527static int kobil_tiocmset(struct usb_serial_port *port, struct file *file, 532static int kobil_tiocmset(struct tty_struct *tty, struct file *file,
528 unsigned int set, unsigned int clear) 533 unsigned int set, unsigned int clear)
529{ 534{
535 struct usb_serial_port *port = tty->driver_data;
530 struct kobil_private * priv; 536 struct kobil_private * priv;
531 int result; 537 int result;
532 int dtr = 0; 538 int dtr = 0;
@@ -590,12 +596,13 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
590 return (result < 0) ? result : 0; 596 return (result < 0) ? result : 0;
591} 597}
592 598
593static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old) 599static void kobil_set_termios(struct tty_struct *tty,
600 struct usb_serial_port *port, struct ktermios *old)
594{ 601{
595 struct kobil_private * priv; 602 struct kobil_private * priv;
596 int result; 603 int result;
597 unsigned short urb_val = 0; 604 unsigned short urb_val = 0;
598 int c_cflag = port->tty->termios->c_cflag; 605 int c_cflag = tty->termios->c_cflag;
599 speed_t speed; 606 speed_t speed;
600 void * settings; 607 void * settings;
601 608
@@ -604,7 +611,7 @@ static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old
604 // This device doesn't support ioctl calls 611 // This device doesn't support ioctl calls
605 return; 612 return;
606 613
607 switch (speed = tty_get_baud_rate(port->tty)) { 614 switch (speed = tty_get_baud_rate(tty)) {
608 case 1200: 615 case 1200:
609 urb_val = SUSBCR_SBR_1200; 616 urb_val = SUSBCR_SBR_1200;
610 break; 617 break;
@@ -634,8 +641,8 @@ static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old
634 urb_val |= SUSBCR_SPASB_NoParity; 641 urb_val |= SUSBCR_SPASB_NoParity;
635 strcat(settings, "No Parity"); 642 strcat(settings, "No Parity");
636 } 643 }
637 port->tty->termios->c_cflag &= ~CMSPAR; 644 tty->termios->c_cflag &= ~CMSPAR;
638 tty_encode_baud_rate(port->tty, speed, speed); 645 tty_encode_baud_rate(tty, speed, speed);
639 646
640 result = usb_control_msg( port->serial->dev, 647 result = usb_control_msg( port->serial->dev,
641 usb_rcvctrlpipe(port->serial->dev, 0 ), 648 usb_rcvctrlpipe(port->serial->dev, 0 ),
@@ -650,8 +657,9 @@ static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old
650 kfree(settings); 657 kfree(settings);
651} 658}
652 659
653static int kobil_ioctl(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) 660static int kobil_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
654{ 661{
662 struct usb_serial_port *port = tty->driver_data;
655 struct kobil_private * priv = usb_get_serial_port_data(port); 663 struct kobil_private * priv = usb_get_serial_port_data(port);
656 unsigned char *transfer_buffer; 664 unsigned char *transfer_buffer;
657 int transfer_buffer_length = 8; 665 int transfer_buffer_length = 8;
@@ -662,7 +670,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file * file, unsigne
662 return 0; 670 return 0;
663 671
664 switch (cmd) { 672 switch (cmd) {
665 case TCFLSH: // 0x540B 673 case TCFLSH:
666 transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL); 674 transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL);
667 if (! transfer_buffer) 675 if (! transfer_buffer)
668 return -ENOBUFS; 676 return -ENOBUFS;
@@ -680,7 +688,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file * file, unsigne
680 688
681 dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __func__, port->number, result); 689 dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __func__, port->number, result);
682 kfree(transfer_buffer); 690 kfree(transfer_buffer);
683 return (result < 0) ? -EFAULT : 0; 691 return (result < 0) ? -EIO: 0;
684 default: 692 default:
685 return -ENOIOCTLCMD; 693 return -ENOIOCTLCMD;
686 } 694 }