diff options
Diffstat (limited to 'drivers/usb/serial/mos7840.c')
-rw-r--r-- | drivers/usb/serial/mos7840.c | 233 |
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 | ||
201 | static int debug; | 207 | static int debug; |
202 | static int mos7840_num_ports; //this says the number of ports in the device | ||
203 | static 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 | ||
355 | static int mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr) | 358 | static 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 | ||
384 | static int mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr) | 389 | static 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: | 473 | exit: |
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 | ||
469 | static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, | 485 | static 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; | ||
606 | exit: | ||
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 | ||
599 | static int mos7840_port_paranoia_check(struct usb_serial_port *port, | 615 | static 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 | ||
2536 | static int mos7840_calc_num_ports(struct usb_serial *serial) | 2574 | static 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; |
2833 | error: | ||
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) | |||
2799 | static void mos7840_shutdown(struct usb_serial *serial) | 2851 | static 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 | } |