aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/mos7840.c
diff options
context:
space:
mode:
authorOliver Neukum <oneukum@suse.de>2007-03-16 15:28:28 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-04-27 16:28:36 -0400
commit0de9a7024e7ae62512d080c7e2beb59d82958cd5 (patch)
tree7327913df59f5c5575b1513122ee404666731b4a /drivers/usb/serial/mos7840.c
parent96c706ed1c46470598d785124b2a7fb233b27dab (diff)
USB: overhaul of mos7840 driver
This fixes: - breaking DMA rules about buffers - usage of _global_ variables to save a single device's attributes - racy access to urb->status - smp monotonity issue with statistics - use of one buffer for many simultaneous URBs - error handling introduced - several instances of following NULL pointers - use after free - unnecessary GFP_ATOMIC - GFP_KERNEL in interrupt - various cleanups - write room granularity issue that bit cdc-acm - race in shutdown Signed-off-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/mos7840.c')
-rw-r--r--drivers/usb/serial/mos7840.c233
1 files changed, 145 insertions, 88 deletions
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index c6cca859af45..2366e7b63ece 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -176,9 +176,12 @@ struct moschip_port {
176 int port_num; /*Actual port number in the device(1,2,etc) */ 176 int port_num; /*Actual port number in the device(1,2,etc) */
177 struct urb *write_urb; /* write URB for this port */ 177 struct urb *write_urb; /* write URB for this port */
178 struct urb *read_urb; /* read URB for this port */ 178 struct urb *read_urb; /* read URB for this port */
179 struct urb *int_urb;
179 __u8 shadowLCR; /* last LCR value received */ 180 __u8 shadowLCR; /* last LCR value received */
180 __u8 shadowMCR; /* last MCR value received */ 181 __u8 shadowMCR; /* last MCR value received */
181 char open; 182 char open;
183 char open_ports;
184 char zombie;
182 wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ 185 wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */
183 wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ 186 wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */
184 int delta_msr_cond; 187 int delta_msr_cond;
@@ -191,17 +194,17 @@ struct moschip_port {
191 __u8 DcrRegOffset; 194 __u8 DcrRegOffset;
192 //for processing control URBS in interrupt context 195 //for processing control URBS in interrupt context
193 struct urb *control_urb; 196 struct urb *control_urb;
197 struct usb_ctrlrequest *dr;
194 char *ctrl_buf; 198 char *ctrl_buf;
195 int MsrLsr; 199 int MsrLsr;
196 200
201 spinlock_t pool_lock;
197 struct urb *write_urb_pool[NUM_URBS]; 202 struct urb *write_urb_pool[NUM_URBS];
203 char busy[NUM_URBS];
198}; 204};
199 205
200 206
201static int debug; 207static int debug;
202static int mos7840_num_ports; //this says the number of ports in the device
203static int mos7840_num_open_ports;
204
205 208
206/* 209/*
207 * mos7840_set_reg_sync 210 * mos7840_set_reg_sync
@@ -254,7 +257,7 @@ static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg,
254 struct usb_device *dev = port->serial->dev; 257 struct usb_device *dev = port->serial->dev;
255 val = val & 0x00ff; 258 val = val & 0x00ff;
256 // For the UART control registers, the application number need to be Or'ed 259 // For the UART control registers, the application number need to be Or'ed
257 if (mos7840_num_ports == 4) { 260 if (port->serial->num_ports == 4) {
258 val |= 261 val |=
259 (((__u16) port->number - (__u16) (port->serial->minor)) + 262 (((__u16) port->number - (__u16) (port->serial->minor)) +
260 1) << 8; 263 1) << 8;
@@ -294,7 +297,7 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg,
294 297
295 //dbg("application number is %4x \n",(((__u16)port->number - (__u16)(port->serial->minor))+1)<<8); 298 //dbg("application number is %4x \n",(((__u16)port->number - (__u16)(port->serial->minor))+1)<<8);
296 /*Wval is same as application number */ 299 /*Wval is same as application number */
297 if (mos7840_num_ports == 4) { 300 if (port->serial->num_ports == 4) {
298 Wval = 301 Wval =
299 (((__u16) port->number - (__u16) (port->serial->minor)) + 302 (((__u16) port->number - (__u16) (port->serial->minor)) +
300 1) << 8; 303 1) << 8;
@@ -352,7 +355,7 @@ static inline struct moschip_port *mos7840_get_port_private(struct
352 return (struct moschip_port *)usb_get_serial_port_data(port); 355 return (struct moschip_port *)usb_get_serial_port_data(port);
353} 356}
354 357
355static int mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr) 358static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
356{ 359{
357 struct moschip_port *mos7840_port; 360 struct moschip_port *mos7840_port;
358 struct async_icount *icount; 361 struct async_icount *icount;
@@ -366,22 +369,24 @@ static int mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
366 /* update input line counters */ 369 /* update input line counters */
367 if (new_msr & MOS_MSR_DELTA_CTS) { 370 if (new_msr & MOS_MSR_DELTA_CTS) {
368 icount->cts++; 371 icount->cts++;
372 smp_wmb();
369 } 373 }
370 if (new_msr & MOS_MSR_DELTA_DSR) { 374 if (new_msr & MOS_MSR_DELTA_DSR) {
371 icount->dsr++; 375 icount->dsr++;
376 smp_wmb();
372 } 377 }
373 if (new_msr & MOS_MSR_DELTA_CD) { 378 if (new_msr & MOS_MSR_DELTA_CD) {
374 icount->dcd++; 379 icount->dcd++;
380 smp_wmb();
375 } 381 }
376 if (new_msr & MOS_MSR_DELTA_RI) { 382 if (new_msr & MOS_MSR_DELTA_RI) {
377 icount->rng++; 383 icount->rng++;
384 smp_wmb();
378 } 385 }
379 } 386 }
380
381 return 0;
382} 387}
383 388
384static int mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr) 389static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
385{ 390{
386 struct async_icount *icount; 391 struct async_icount *icount;
387 392
@@ -400,18 +405,20 @@ static int mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
400 icount = &port->icount; 405 icount = &port->icount;
401 if (new_lsr & SERIAL_LSR_BI) { 406 if (new_lsr & SERIAL_LSR_BI) {
402 icount->brk++; 407 icount->brk++;
408 smp_wmb();
403 } 409 }
404 if (new_lsr & SERIAL_LSR_OE) { 410 if (new_lsr & SERIAL_LSR_OE) {
405 icount->overrun++; 411 icount->overrun++;
412 smp_wmb();
406 } 413 }
407 if (new_lsr & SERIAL_LSR_PE) { 414 if (new_lsr & SERIAL_LSR_PE) {
408 icount->parity++; 415 icount->parity++;
416 smp_wmb();
409 } 417 }
410 if (new_lsr & SERIAL_LSR_FE) { 418 if (new_lsr & SERIAL_LSR_FE) {
411 icount->frame++; 419 icount->frame++;
420 smp_wmb();
412 } 421 }
413
414 return 0;
415} 422}
416 423
417/************************************************************************/ 424/************************************************************************/
@@ -426,12 +433,15 @@ static void mos7840_control_callback(struct urb *urb)
426 unsigned char *data; 433 unsigned char *data;
427 struct moschip_port *mos7840_port; 434 struct moschip_port *mos7840_port;
428 __u8 regval = 0x0; 435 __u8 regval = 0x0;
436 int result = 0;
429 437
430 if (!urb) { 438 if (!urb) {
431 dbg("%s", "Invalid Pointer !!!!:\n"); 439 dbg("%s", "Invalid Pointer !!!!:\n");
432 return; 440 return;
433 } 441 }
434 442
443 mos7840_port = (struct moschip_port *)urb->context;
444
435 switch (urb->status) { 445 switch (urb->status) {
436 case 0: 446 case 0:
437 /* success */ 447 /* success */
@@ -449,8 +459,6 @@ static void mos7840_control_callback(struct urb *urb)
449 goto exit; 459 goto exit;
450 } 460 }
451 461
452 mos7840_port = (struct moschip_port *)urb->context;
453
454 dbg("%s urb buffer size is %d\n", __FUNCTION__, urb->actual_length); 462 dbg("%s urb buffer size is %d\n", __FUNCTION__, urb->actual_length);
455 dbg("%s mos7840_port->MsrLsr is %d port %d\n", __FUNCTION__, 463 dbg("%s mos7840_port->MsrLsr is %d port %d\n", __FUNCTION__,
456 mos7840_port->MsrLsr, mos7840_port->port_num); 464 mos7840_port->MsrLsr, mos7840_port->port_num);
@@ -462,21 +470,26 @@ static void mos7840_control_callback(struct urb *urb)
462 else if (mos7840_port->MsrLsr == 1) 470 else if (mos7840_port->MsrLsr == 1)
463 mos7840_handle_new_lsr(mos7840_port, regval); 471 mos7840_handle_new_lsr(mos7840_port, regval);
464 472
465 exit: 473exit:
466 return; 474 spin_lock(&mos7840_port->pool_lock);
475 if (!mos7840_port->zombie)
476 result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC);
477 spin_unlock(&mos7840_port->pool_lock);
478 if (result) {
479 dev_err(&urb->dev->dev,
480 "%s - Error %d submitting interrupt urb\n",
481 __FUNCTION__, result);
482 }
467} 483}
468 484
469static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, 485static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
470 __u16 * val) 486 __u16 * val)
471{ 487{
472 struct usb_device *dev = mcs->port->serial->dev; 488 struct usb_device *dev = mcs->port->serial->dev;
473 struct usb_ctrlrequest *dr = NULL; 489 struct usb_ctrlrequest *dr = mcs->dr;
474 unsigned char *buffer = NULL; 490 unsigned char *buffer = mcs->ctrl_buf;
475 int ret = 0; 491 int ret;
476 buffer = (__u8 *) mcs->ctrl_buf;
477 492
478// dr=(struct usb_ctrlrequest *)(buffer);
479 dr = (void *)(buffer + 2);
480 dr->bRequestType = MCS_RD_RTYPE; 493 dr->bRequestType = MCS_RD_RTYPE;
481 dr->bRequest = MCS_RDREQ; 494 dr->bRequest = MCS_RDREQ;
482 dr->wValue = cpu_to_le16(Wval); //0; 495 dr->wValue = cpu_to_le16(Wval); //0;
@@ -506,8 +519,8 @@ static void mos7840_interrupt_callback(struct urb *urb)
506 __u16 Data; 519 __u16 Data;
507 unsigned char *data; 520 unsigned char *data;
508 __u8 sp[5], st; 521 __u8 sp[5], st;
509 int i; 522 int i, rv = 0;
510 __u16 wval; 523 __u16 wval, wreg = 0;
511 524
512 dbg("%s", " : Entering\n"); 525 dbg("%s", " : Entering\n");
513 if (!urb) { 526 if (!urb) {
@@ -569,31 +582,34 @@ static void mos7840_interrupt_callback(struct urb *urb)
569 dbg("Serial Port %d: Receiver status error or ", i); 582 dbg("Serial Port %d: Receiver status error or ", i);
570 dbg("address bit detected in 9-bit mode\n"); 583 dbg("address bit detected in 9-bit mode\n");
571 mos7840_port->MsrLsr = 1; 584 mos7840_port->MsrLsr = 1;
572 mos7840_get_reg(mos7840_port, wval, 585 wreg = LINE_STATUS_REGISTER;
573 LINE_STATUS_REGISTER,
574 &Data);
575 break; 586 break;
576 case SERIAL_IIR_MS: 587 case SERIAL_IIR_MS:
577 dbg("Serial Port %d: Modem status change\n", i); 588 dbg("Serial Port %d: Modem status change\n", i);
578 mos7840_port->MsrLsr = 0; 589 mos7840_port->MsrLsr = 0;
579 mos7840_get_reg(mos7840_port, wval, 590 wreg = MODEM_STATUS_REGISTER;
580 MODEM_STATUS_REGISTER,
581 &Data);
582 break; 591 break;
583 } 592 }
593 spin_lock(&mos7840_port->pool_lock);
594 if (!mos7840_port->zombie) {
595 rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
596 } else {
597 spin_unlock(&mos7840_port->pool_lock);
598 return;
599 }
600 spin_unlock(&mos7840_port->pool_lock);
584 } 601 }
585 } 602 }
586 } 603 }
587 exit: 604 if (!(rv < 0)) /* the completion handler for the control urb will resubmit */
605 return;
606exit:
588 result = usb_submit_urb(urb, GFP_ATOMIC); 607 result = usb_submit_urb(urb, GFP_ATOMIC);
589 if (result) { 608 if (result) {
590 dev_err(&urb->dev->dev, 609 dev_err(&urb->dev->dev,
591 "%s - Error %d submitting interrupt urb\n", 610 "%s - Error %d submitting interrupt urb\n",
592 __FUNCTION__, result); 611 __FUNCTION__, result);
593 } 612 }
594
595 return;
596
597} 613}
598 614
599static int mos7840_port_paranoia_check(struct usb_serial_port *port, 615static int mos7840_port_paranoia_check(struct usb_serial_port *port,
@@ -634,7 +650,8 @@ static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port,
634 if (!port || 650 if (!port ||
635 mos7840_port_paranoia_check(port, function) || 651 mos7840_port_paranoia_check(port, function) ||
636 mos7840_serial_paranoia_check(port->serial, function)) { 652 mos7840_serial_paranoia_check(port->serial, function)) {
637 /* then say that we don't have a valid usb_serial thing, which will * end up genrating -ENODEV return values */ 653 /* then say that we don't have a valid usb_serial thing, which will
654 * end up genrating -ENODEV return values */
638 return NULL; 655 return NULL;
639 } 656 }
640 657
@@ -699,6 +716,7 @@ static void mos7840_bulk_in_callback(struct urb *urb)
699 tty_flip_buffer_push(tty); 716 tty_flip_buffer_push(tty);
700 } 717 }
701 mos7840_port->icount.rx += urb->actual_length; 718 mos7840_port->icount.rx += urb->actual_length;
719 smp_wmb();
702 dbg("mos7840_port->icount.rx is %d:\n", 720 dbg("mos7840_port->icount.rx is %d:\n",
703 mos7840_port->icount.rx); 721 mos7840_port->icount.rx);
704 } 722 }
@@ -708,15 +726,14 @@ static void mos7840_bulk_in_callback(struct urb *urb)
708 return; 726 return;
709 } 727 }
710 728
711 if (mos7840_port->read_urb->status != -EINPROGRESS) {
712 mos7840_port->read_urb->dev = serial->dev;
713 729
714 status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); 730 mos7840_port->read_urb->dev = serial->dev;
715 731
716 if (status) { 732 status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
717 dbg(" usb_submit_urb(read bulk) failed, status = %d", 733
718 status); 734 if (status) {
719 } 735 dbg(" usb_submit_urb(read bulk) failed, status = %d",
736 status);
720 } 737 }
721} 738}
722 739
@@ -730,17 +747,28 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
730{ 747{
731 struct moschip_port *mos7840_port; 748 struct moschip_port *mos7840_port;
732 struct tty_struct *tty; 749 struct tty_struct *tty;
750 int i;
751
733 if (!urb) { 752 if (!urb) {
734 dbg("%s", "Invalid Pointer !!!!:\n"); 753 dbg("%s", "Invalid Pointer !!!!:\n");
735 return; 754 return;
736 } 755 }
737 756
757 mos7840_port = (struct moschip_port *)urb->context;
758 spin_lock(&mos7840_port->pool_lock);
759 for (i = 0; i < NUM_URBS; i++) {
760 if (urb == mos7840_port->write_urb_pool[i]) {
761 mos7840_port->busy[i] = 0;
762 break;
763 }
764 }
765 spin_unlock(&mos7840_port->pool_lock);
766
738 if (urb->status) { 767 if (urb->status) {
739 dbg("nonzero write bulk status received:%d\n", urb->status); 768 dbg("nonzero write bulk status received:%d\n", urb->status);
740 return; 769 return;
741 } 770 }
742 771
743 mos7840_port = (struct moschip_port *)urb->context;
744 if (!mos7840_port) { 772 if (!mos7840_port) {
745 dbg("%s", "NULL mos7840_port pointer \n"); 773 dbg("%s", "NULL mos7840_port pointer \n");
746 return; 774 return;
@@ -792,13 +820,13 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
792 __u16 Data; 820 __u16 Data;
793 int status; 821 int status;
794 struct moschip_port *mos7840_port; 822 struct moschip_port *mos7840_port;
823 struct moschip_port *port0;
795 824
796 if (mos7840_port_paranoia_check(port, __FUNCTION__)) { 825 if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
797 dbg("%s", "Port Paranoia failed \n"); 826 dbg("%s", "Port Paranoia failed \n");
798 return -ENODEV; 827 return -ENODEV;
799 } 828 }
800 829
801 mos7840_num_open_ports++;
802 serial = port->serial; 830 serial = port->serial;
803 831
804 if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) { 832 if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
@@ -807,16 +835,18 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
807 } 835 }
808 836
809 mos7840_port = mos7840_get_port_private(port); 837 mos7840_port = mos7840_get_port_private(port);
838 port0 = mos7840_get_port_private(serial->port[0]);
810 839
811 if (mos7840_port == NULL) 840 if (mos7840_port == NULL || port0 == NULL)
812 return -ENODEV; 841 return -ENODEV;
813 842
814 usb_clear_halt(serial->dev, port->write_urb->pipe); 843 usb_clear_halt(serial->dev, port->write_urb->pipe);
815 usb_clear_halt(serial->dev, port->read_urb->pipe); 844 usb_clear_halt(serial->dev, port->read_urb->pipe);
845 port0->open_ports++;
816 846
817 /* Initialising the write urb pool */ 847 /* Initialising the write urb pool */
818 for (j = 0; j < NUM_URBS; ++j) { 848 for (j = 0; j < NUM_URBS; ++j) {
819 urb = usb_alloc_urb(0, GFP_ATOMIC); 849 urb = usb_alloc_urb(0, GFP_KERNEL);
820 mos7840_port->write_urb_pool[j] = urb; 850 mos7840_port->write_urb_pool[j] = urb;
821 851
822 if (urb == NULL) { 852 if (urb == NULL) {
@@ -824,10 +854,10 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
824 continue; 854 continue;
825 } 855 }
826 856
827 urb->transfer_buffer = NULL; 857 urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
828 urb->transfer_buffer =
829 kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
830 if (!urb->transfer_buffer) { 858 if (!urb->transfer_buffer) {
859 usb_free_urb(urb);
860 mos7840_port->write_urb_pool[j] = NULL;
831 err("%s-out of memory for urb buffers.", __FUNCTION__); 861 err("%s-out of memory for urb buffers.", __FUNCTION__);
832 continue; 862 continue;
833 } 863 }
@@ -879,9 +909,7 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
879 } 909 }
880 Data |= 0x08; //Driver done bit 910 Data |= 0x08; //Driver done bit
881 Data |= 0x20; //rx_disable 911 Data |= 0x20; //rx_disable
882 status = 0; 912 status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
883 status =
884 mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
885 if (status < 0) { 913 if (status < 0) {
886 dbg("writing Controlreg failed\n"); 914 dbg("writing Controlreg failed\n");
887 return -1; 915 return -1;
@@ -893,7 +921,6 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
893 //////////////////////////////////// 921 ////////////////////////////////////
894 922
895 Data = 0x00; 923 Data = 0x00;
896 status = 0;
897 status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); 924 status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
898 if (status < 0) { 925 if (status < 0) {
899 dbg("disableing interrupts failed\n"); 926 dbg("disableing interrupts failed\n");
@@ -901,7 +928,6 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
901 } 928 }
902 // Set FIFO_CONTROL_REGISTER to the default value 929 // Set FIFO_CONTROL_REGISTER to the default value
903 Data = 0x00; 930 Data = 0x00;
904 status = 0;
905 status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); 931 status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
906 if (status < 0) { 932 if (status < 0) {
907 dbg("Writing FIFO_CONTROL_REGISTER failed\n"); 933 dbg("Writing FIFO_CONTROL_REGISTER failed\n");
@@ -909,7 +935,6 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
909 } 935 }
910 936
911 Data = 0xcf; 937 Data = 0xcf;
912 status = 0;
913 status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); 938 status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
914 if (status < 0) { 939 if (status < 0) {
915 dbg("Writing FIFO_CONTROL_REGISTER failed\n"); 940 dbg("Writing FIFO_CONTROL_REGISTER failed\n");
@@ -917,22 +942,18 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
917 } 942 }
918 943
919 Data = 0x03; 944 Data = 0x03;
920 status = 0;
921 status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); 945 status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
922 mos7840_port->shadowLCR = Data; 946 mos7840_port->shadowLCR = Data;
923 947
924 Data = 0x0b; 948 Data = 0x0b;
925 status = 0;
926 status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); 949 status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
927 mos7840_port->shadowMCR = Data; 950 mos7840_port->shadowMCR = Data;
928 951
929 Data = 0x00; 952 Data = 0x00;
930 status = 0;
931 status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); 953 status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
932 mos7840_port->shadowLCR = Data; 954 mos7840_port->shadowLCR = Data;
933 955
934 Data |= SERIAL_LCR_DLAB; //data latch enable in LCR 0x80 956 Data |= SERIAL_LCR_DLAB; //data latch enable in LCR 0x80
935 status = 0;
936 status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); 957 status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
937 958
938 Data = 0x0c; 959 Data = 0x0c;
@@ -999,7 +1020,7 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
999/* Check to see if we've set up our endpoint info yet * 1020/* Check to see if we've set up our endpoint info yet *
1000 * (can't set it up in mos7840_startup as the structures * 1021 * (can't set it up in mos7840_startup as the structures *
1001 * were not set up at that time.) */ 1022 * were not set up at that time.) */
1002 if (mos7840_num_open_ports == 1) { 1023 if (port0->open_ports == 1) {
1003 if (serial->port[0]->interrupt_in_buffer == NULL) { 1024 if (serial->port[0]->interrupt_in_buffer == NULL) {
1004 1025
1005 /* set up interrupt urb */ 1026 /* set up interrupt urb */
@@ -1097,6 +1118,7 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port)
1097{ 1118{
1098 int i; 1119 int i;
1099 int chars = 0; 1120 int chars = 0;
1121 unsigned long flags;
1100 struct moschip_port *mos7840_port; 1122 struct moschip_port *mos7840_port;
1101 1123
1102 dbg("%s \n", " mos7840_chars_in_buffer:entering ..........."); 1124 dbg("%s \n", " mos7840_chars_in_buffer:entering ...........");
@@ -1112,13 +1134,15 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port)
1112 return -1; 1134 return -1;
1113 } 1135 }
1114 1136
1137 spin_lock_irqsave(&mos7840_port->pool_lock,flags);
1115 for (i = 0; i < NUM_URBS; ++i) { 1138 for (i = 0; i < NUM_URBS; ++i) {
1116 if (mos7840_port->write_urb_pool[i]->status == -EINPROGRESS) { 1139 if (mos7840_port->busy[i]) {
1117 chars += URB_TRANSFER_BUFFER_SIZE; 1140 chars += URB_TRANSFER_BUFFER_SIZE;
1118 } 1141 }
1119 } 1142 }
1143 spin_unlock_irqrestore(&mos7840_port->pool_lock,flags);
1120 dbg("%s - returns %d", __FUNCTION__, chars); 1144 dbg("%s - returns %d", __FUNCTION__, chars);
1121 return (chars); 1145 return chars;
1122 1146
1123} 1147}
1124 1148
@@ -1172,6 +1196,7 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp)
1172{ 1196{
1173 struct usb_serial *serial; 1197 struct usb_serial *serial;
1174 struct moschip_port *mos7840_port; 1198 struct moschip_port *mos7840_port;
1199 struct moschip_port *port0;
1175 int j; 1200 int j;
1176 __u16 Data; 1201 __u16 Data;
1177 1202
@@ -1189,10 +1214,10 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp)
1189 } 1214 }
1190 1215
1191 mos7840_port = mos7840_get_port_private(port); 1216 mos7840_port = mos7840_get_port_private(port);
1217 port0 = mos7840_get_port_private(serial->port[0]);
1192 1218
1193 if (mos7840_port == NULL) { 1219 if (mos7840_port == NULL || port0 == NULL)
1194 return; 1220 return;
1195 }
1196 1221
1197 for (j = 0; j < NUM_URBS; ++j) 1222 for (j = 0; j < NUM_URBS; ++j)
1198 usb_kill_urb(mos7840_port->write_urb_pool[j]); 1223 usb_kill_urb(mos7840_port->write_urb_pool[j]);
@@ -1234,12 +1259,13 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp)
1234 } 1259 }
1235// if(mos7840_port->ctrl_buf != NULL) 1260// if(mos7840_port->ctrl_buf != NULL)
1236// kfree(mos7840_port->ctrl_buf); 1261// kfree(mos7840_port->ctrl_buf);
1237 mos7840_num_open_ports--; 1262 port0->open_ports--;
1238 dbg("mos7840_num_open_ports in close%d:in port%d\n", 1263 dbg("mos7840_num_open_ports in close%d:in port%d\n",
1239 mos7840_num_open_ports, port->number); 1264 port0->open_ports, port->number);
1240 if (mos7840_num_open_ports == 0) { 1265 if (port0->open_ports == 0) {
1241 if (serial->port[0]->interrupt_in_urb) { 1266 if (serial->port[0]->interrupt_in_urb) {
1242 dbg("%s", "Shutdown interrupt_in_urb\n"); 1267 dbg("%s", "Shutdown interrupt_in_urb\n");
1268 usb_kill_urb(serial->port[0]->interrupt_in_urb);
1243 } 1269 }
1244 } 1270 }
1245 1271
@@ -1368,6 +1394,7 @@ static int mos7840_write_room(struct usb_serial_port *port)
1368{ 1394{
1369 int i; 1395 int i;
1370 int room = 0; 1396 int room = 0;
1397 unsigned long flags;
1371 struct moschip_port *mos7840_port; 1398 struct moschip_port *mos7840_port;
1372 1399
1373 dbg("%s \n", " mos7840_write_room:entering ..........."); 1400 dbg("%s \n", " mos7840_write_room:entering ...........");
@@ -1384,14 +1411,17 @@ static int mos7840_write_room(struct usb_serial_port *port)
1384 return -1; 1411 return -1;
1385 } 1412 }
1386 1413
1414 spin_lock_irqsave(&mos7840_port->pool_lock, flags);
1387 for (i = 0; i < NUM_URBS; ++i) { 1415 for (i = 0; i < NUM_URBS; ++i) {
1388 if (mos7840_port->write_urb_pool[i]->status != -EINPROGRESS) { 1416 if (!mos7840_port->busy[i]) {
1389 room += URB_TRANSFER_BUFFER_SIZE; 1417 room += URB_TRANSFER_BUFFER_SIZE;
1390 } 1418 }
1391 } 1419 }
1420 spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
1392 1421
1422 room = (room == 0) ? 0 : room - URB_TRANSFER_BUFFER_SIZE + 1;
1393 dbg("%s - returns %d", __FUNCTION__, room); 1423 dbg("%s - returns %d", __FUNCTION__, room);
1394 return (room); 1424 return room;
1395 1425
1396} 1426}
1397 1427
@@ -1410,6 +1440,7 @@ static int mos7840_write(struct usb_serial_port *port,
1410 int i; 1440 int i;
1411 int bytes_sent = 0; 1441 int bytes_sent = 0;
1412 int transfer_size; 1442 int transfer_size;
1443 unsigned long flags;
1413 1444
1414 struct moschip_port *mos7840_port; 1445 struct moschip_port *mos7840_port;
1415 struct usb_serial *serial; 1446 struct usb_serial *serial;
@@ -1476,13 +1507,16 @@ static int mos7840_write(struct usb_serial_port *port,
1476 /* try to find a free urb in the list */ 1507 /* try to find a free urb in the list */
1477 urb = NULL; 1508 urb = NULL;
1478 1509
1510 spin_lock_irqsave(&mos7840_port->pool_lock, flags);
1479 for (i = 0; i < NUM_URBS; ++i) { 1511 for (i = 0; i < NUM_URBS; ++i) {
1480 if (mos7840_port->write_urb_pool[i]->status != -EINPROGRESS) { 1512 if (!mos7840_port->busy[i]) {
1513 mos7840_port->busy[i] = 1;
1481 urb = mos7840_port->write_urb_pool[i]; 1514 urb = mos7840_port->write_urb_pool[i];
1482 dbg("\nURB:%d", i); 1515 dbg("\nURB:%d", i);
1483 break; 1516 break;
1484 } 1517 }
1485 } 1518 }
1519 spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
1486 1520
1487 if (urb == NULL) { 1521 if (urb == NULL) {
1488 dbg("%s - no more free urbs", __FUNCTION__); 1522 dbg("%s - no more free urbs", __FUNCTION__);
@@ -1518,6 +1552,7 @@ static int mos7840_write(struct usb_serial_port *port,
1518 status = usb_submit_urb(urb, GFP_ATOMIC); 1552 status = usb_submit_urb(urb, GFP_ATOMIC);
1519 1553
1520 if (status) { 1554 if (status) {
1555 mos7840_port->busy[i] = 0;
1521 err("%s - usb_submit_urb(write bulk) failed with status = %d", 1556 err("%s - usb_submit_urb(write bulk) failed with status = %d",
1522 __FUNCTION__, status); 1557 __FUNCTION__, status);
1523 bytes_sent = status; 1558 bytes_sent = status;
@@ -1525,6 +1560,7 @@ static int mos7840_write(struct usb_serial_port *port,
1525 } 1560 }
1526 bytes_sent = transfer_size; 1561 bytes_sent = transfer_size;
1527 mos7840_port->icount.tx += transfer_size; 1562 mos7840_port->icount.tx += transfer_size;
1563 smp_wmb();
1528 dbg("mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx); 1564 dbg("mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx);
1529 exit: 1565 exit:
1530 1566
@@ -2490,6 +2526,7 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
2490 if (signal_pending(current)) 2526 if (signal_pending(current))
2491 return -ERESTARTSYS; 2527 return -ERESTARTSYS;
2492 cnow = mos7840_port->icount; 2528 cnow = mos7840_port->icount;
2529 smp_rmb();
2493 if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && 2530 if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
2494 cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) 2531 cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
2495 return -EIO; /* no change => error */ 2532 return -EIO; /* no change => error */
@@ -2506,6 +2543,7 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
2506 2543
2507 case TIOCGICOUNT: 2544 case TIOCGICOUNT:
2508 cnow = mos7840_port->icount; 2545 cnow = mos7840_port->icount;
2546 smp_rmb();
2509 icount.cts = cnow.cts; 2547 icount.cts = cnow.cts;
2510 icount.dsr = cnow.dsr; 2548 icount.dsr = cnow.dsr;
2511 icount.rng = cnow.rng; 2549 icount.rng = cnow.rng;
@@ -2535,19 +2573,18 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
2535 2573
2536static int mos7840_calc_num_ports(struct usb_serial *serial) 2574static int mos7840_calc_num_ports(struct usb_serial *serial)
2537{ 2575{
2576 int mos7840_num_ports = 0;
2538 2577
2539 dbg("numberofendpoints: %d \n", 2578 dbg("numberofendpoints: %d \n",
2540 (int)serial->interface->cur_altsetting->desc.bNumEndpoints); 2579 (int)serial->interface->cur_altsetting->desc.bNumEndpoints);
2541 dbg("numberofendpoints: %d \n", 2580 dbg("numberofendpoints: %d \n",
2542 (int)serial->interface->altsetting->desc.bNumEndpoints); 2581 (int)serial->interface->altsetting->desc.bNumEndpoints);
2543 if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) { 2582 if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) {
2544 mos7840_num_ports = 2; 2583 mos7840_num_ports = serial->num_ports = 2;
2545 serial->type->num_ports = 2;
2546 } else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) { 2584 } else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) {
2547 mos7840_num_ports = 4; 2585 serial->num_bulk_in = 4;
2548 serial->type->num_bulk_in = 4; 2586 serial->num_bulk_out = 4;
2549 serial->type->num_bulk_out = 4; 2587 mos7840_num_ports = serial->num_ports = 4;
2550 serial->type->num_ports = 4;
2551 } 2588 }
2552 2589
2553 return mos7840_num_ports; 2590 return mos7840_num_ports;
@@ -2583,7 +2620,9 @@ static int mos7840_startup(struct usb_serial *serial)
2583 mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); 2620 mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
2584 if (mos7840_port == NULL) { 2621 if (mos7840_port == NULL) {
2585 err("%s - Out of memory", __FUNCTION__); 2622 err("%s - Out of memory", __FUNCTION__);
2586 return -ENOMEM; 2623 status = -ENOMEM;
2624 i--; /* don't follow NULL pointer cleaning up */
2625 goto error;
2587 } 2626 }
2588 2627
2589 /* Initialize all port interrupt end point to port 0 int endpoint * 2628 /* Initialize all port interrupt end point to port 0 int endpoint *
@@ -2591,6 +2630,7 @@ static int mos7840_startup(struct usb_serial *serial)
2591 2630
2592 mos7840_port->port = serial->port[i]; 2631 mos7840_port->port = serial->port[i];
2593 mos7840_set_port_private(serial->port[i], mos7840_port); 2632 mos7840_set_port_private(serial->port[i], mos7840_port);
2633 spin_lock_init(&mos7840_port->pool_lock);
2594 2634
2595 mos7840_port->port_num = ((serial->port[i]->number - 2635 mos7840_port->port_num = ((serial->port[i]->number -
2596 (serial->port[i]->serial->minor)) + 2636 (serial->port[i]->serial->minor)) +
@@ -2601,22 +2641,22 @@ static int mos7840_startup(struct usb_serial *serial)
2601 mos7840_port->ControlRegOffset = 0x1; 2641 mos7840_port->ControlRegOffset = 0x1;
2602 mos7840_port->DcrRegOffset = 0x4; 2642 mos7840_port->DcrRegOffset = 0x4;
2603 } else if ((mos7840_port->port_num == 2) 2643 } else if ((mos7840_port->port_num == 2)
2604 && (mos7840_num_ports == 4)) { 2644 && (serial->num_ports == 4)) {
2605 mos7840_port->SpRegOffset = 0x8; 2645 mos7840_port->SpRegOffset = 0x8;
2606 mos7840_port->ControlRegOffset = 0x9; 2646 mos7840_port->ControlRegOffset = 0x9;
2607 mos7840_port->DcrRegOffset = 0x16; 2647 mos7840_port->DcrRegOffset = 0x16;
2608 } else if ((mos7840_port->port_num == 2) 2648 } else if ((mos7840_port->port_num == 2)
2609 && (mos7840_num_ports == 2)) { 2649 && (serial->num_ports == 2)) {
2610 mos7840_port->SpRegOffset = 0xa; 2650 mos7840_port->SpRegOffset = 0xa;
2611 mos7840_port->ControlRegOffset = 0xb; 2651 mos7840_port->ControlRegOffset = 0xb;
2612 mos7840_port->DcrRegOffset = 0x19; 2652 mos7840_port->DcrRegOffset = 0x19;
2613 } else if ((mos7840_port->port_num == 3) 2653 } else if ((mos7840_port->port_num == 3)
2614 && (mos7840_num_ports == 4)) { 2654 && (serial->num_ports == 4)) {
2615 mos7840_port->SpRegOffset = 0xa; 2655 mos7840_port->SpRegOffset = 0xa;
2616 mos7840_port->ControlRegOffset = 0xb; 2656 mos7840_port->ControlRegOffset = 0xb;
2617 mos7840_port->DcrRegOffset = 0x19; 2657 mos7840_port->DcrRegOffset = 0x19;
2618 } else if ((mos7840_port->port_num == 4) 2658 } else if ((mos7840_port->port_num == 4)
2619 && (mos7840_num_ports == 4)) { 2659 && (serial->num_ports == 4)) {
2620 mos7840_port->SpRegOffset = 0xc; 2660 mos7840_port->SpRegOffset = 0xc;
2621 mos7840_port->ControlRegOffset = 0xd; 2661 mos7840_port->ControlRegOffset = 0xd;
2622 mos7840_port->DcrRegOffset = 0x1c; 2662 mos7840_port->DcrRegOffset = 0x1c;
@@ -2701,21 +2741,19 @@ static int mos7840_startup(struct usb_serial *serial)
2701 dbg("CLK_START_VALUE_REGISTER Writing success status%d\n", status); 2741 dbg("CLK_START_VALUE_REGISTER Writing success status%d\n", status);
2702 2742
2703 Data = 0x20; 2743 Data = 0x20;
2704 status = 0;
2705 status = 2744 status =
2706 mos7840_set_reg_sync(serial->port[i], CLK_MULTI_REGISTER, 2745 mos7840_set_reg_sync(serial->port[i], CLK_MULTI_REGISTER,
2707 Data); 2746 Data);
2708 if (status < 0) { 2747 if (status < 0) {
2709 dbg("Writing CLK_MULTI_REGISTER failed status-0x%x\n", 2748 dbg("Writing CLK_MULTI_REGISTER failed status-0x%x\n",
2710 status); 2749 status);
2711 break; 2750 goto error;
2712 } else 2751 } else
2713 dbg("CLK_MULTI_REGISTER Writing success status%d\n", 2752 dbg("CLK_MULTI_REGISTER Writing success status%d\n",
2714 status); 2753 status);
2715 2754
2716 //write value 0x0 to scratchpad register 2755 //write value 0x0 to scratchpad register
2717 Data = 0x00; 2756 Data = 0x00;
2718 status = 0;
2719 status = 2757 status =
2720 mos7840_set_uart_reg(serial->port[i], SCRATCH_PAD_REGISTER, 2758 mos7840_set_uart_reg(serial->port[i], SCRATCH_PAD_REGISTER,
2721 Data); 2759 Data);
@@ -2729,7 +2767,7 @@ static int mos7840_startup(struct usb_serial *serial)
2729 2767
2730 //Zero Length flag register 2768 //Zero Length flag register
2731 if ((mos7840_port->port_num != 1) 2769 if ((mos7840_port->port_num != 1)
2732 && (mos7840_num_ports == 2)) { 2770 && (serial->num_ports == 2)) {
2733 2771
2734 Data = 0xff; 2772 Data = 0xff;
2735 status = 0; 2773 status = 0;
@@ -2770,14 +2808,17 @@ static int mos7840_startup(struct usb_serial *serial)
2770 i + 1, status); 2808 i + 1, status);
2771 2809
2772 } 2810 }
2773 mos7840_port->control_urb = usb_alloc_urb(0, GFP_ATOMIC); 2811 mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
2774 mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); 2812 mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
2775 2813 mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
2814 if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || !mos7840_port->dr) {
2815 status = -ENOMEM;
2816 goto error;
2817 }
2776 } 2818 }
2777 2819
2778 //Zero Length flag enable 2820 //Zero Length flag enable
2779 Data = 0x0f; 2821 Data = 0x0f;
2780 status = 0;
2781 status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); 2822 status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
2782 if (status < 0) { 2823 if (status < 0) {
2783 dbg("Writing ZLP_REG5 failed status-0x%x\n", status); 2824 dbg("Writing ZLP_REG5 failed status-0x%x\n", status);
@@ -2789,6 +2830,17 @@ static int mos7840_startup(struct usb_serial *serial)
2789 usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 2830 usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
2790 (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5 * HZ); 2831 (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5 * HZ);
2791 return 0; 2832 return 0;
2833error:
2834 for (/* nothing */; i >= 0; i--) {
2835 mos7840_port = mos7840_get_port_private(serial->port[i]);
2836
2837 kfree(mos7840_port->dr);
2838 kfree(mos7840_port->ctrl_buf);
2839 usb_free_urb(mos7840_port->control_urb);
2840 kfree(mos7840_port);
2841 serial->port[i] = NULL;
2842 }
2843 return status;
2792} 2844}
2793 2845
2794/**************************************************************************** 2846/****************************************************************************
@@ -2799,6 +2851,7 @@ static int mos7840_startup(struct usb_serial *serial)
2799static void mos7840_shutdown(struct usb_serial *serial) 2851static void mos7840_shutdown(struct usb_serial *serial)
2800{ 2852{
2801 int i; 2853 int i;
2854 unsigned long flags;
2802 struct moschip_port *mos7840_port; 2855 struct moschip_port *mos7840_port;
2803 dbg("%s \n", " shutdown :entering.........."); 2856 dbg("%s \n", " shutdown :entering..........");
2804 2857
@@ -2814,8 +2867,12 @@ static void mos7840_shutdown(struct usb_serial *serial)
2814 2867
2815 for (i = 0; i < serial->num_ports; ++i) { 2868 for (i = 0; i < serial->num_ports; ++i) {
2816 mos7840_port = mos7840_get_port_private(serial->port[i]); 2869 mos7840_port = mos7840_get_port_private(serial->port[i]);
2817 kfree(mos7840_port->ctrl_buf); 2870 spin_lock_irqsave(&mos7840_port->pool_lock, flags);
2871 mos7840_port->zombie = 1;
2872 spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
2818 usb_kill_urb(mos7840_port->control_urb); 2873 usb_kill_urb(mos7840_port->control_urb);
2874 kfree(mos7840_port->ctrl_buf);
2875 kfree(mos7840_port->dr);
2819 kfree(mos7840_port); 2876 kfree(mos7840_port);
2820 mos7840_set_port_private(serial->port[i], NULL); 2877 mos7840_set_port_private(serial->port[i], NULL);
2821 } 2878 }