diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-08-04 20:36:14 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-08-04 20:36:14 -0400 |
commit | 5b146f7e016a8727a98b3d48e4f4e128d3624cd5 (patch) | |
tree | 308acba9e7fdb00ab1458ebacd25dd049e310996 /drivers/usb/serial/mos7840.c | |
parent | 626f090c5cbbe557379978c7a9525011ad7fbbf6 (diff) | |
parent | c095ba7224d8edc71dcef0d655911399a8bd4a3f (diff) |
Merge 3.11-rc4 into usb-next
We want those fixes in here also.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial/mos7840.c')
-rw-r--r-- | drivers/usb/serial/mos7840.c | 150 |
1 files changed, 87 insertions, 63 deletions
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index e31d52aa78c9..dfa678906632 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
@@ -183,7 +183,10 @@ | |||
183 | #define LED_ON_MS 500 | 183 | #define LED_ON_MS 500 |
184 | #define LED_OFF_MS 500 | 184 | #define LED_OFF_MS 500 |
185 | 185 | ||
186 | static int device_type; | 186 | enum mos7840_flag { |
187 | MOS7840_FLAG_CTRL_BUSY, | ||
188 | MOS7840_FLAG_LED_BUSY, | ||
189 | }; | ||
187 | 190 | ||
188 | static const struct usb_device_id id_table[] = { | 191 | static const struct usb_device_id id_table[] = { |
189 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, | 192 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, |
@@ -237,9 +240,12 @@ struct moschip_port { | |||
237 | 240 | ||
238 | /* For device(s) with LED indicator */ | 241 | /* For device(s) with LED indicator */ |
239 | bool has_led; | 242 | bool has_led; |
240 | bool led_flag; | ||
241 | struct timer_list led_timer1; /* Timer for LED on */ | 243 | struct timer_list led_timer1; /* Timer for LED on */ |
242 | struct timer_list led_timer2; /* Timer for LED off */ | 244 | struct timer_list led_timer2; /* Timer for LED off */ |
245 | struct urb *led_urb; | ||
246 | struct usb_ctrlrequest *led_dr; | ||
247 | |||
248 | unsigned long flags; | ||
243 | }; | 249 | }; |
244 | 250 | ||
245 | /* | 251 | /* |
@@ -459,10 +465,10 @@ static void mos7840_control_callback(struct urb *urb) | |||
459 | case -ESHUTDOWN: | 465 | case -ESHUTDOWN: |
460 | /* this urb is terminated, clean up */ | 466 | /* this urb is terminated, clean up */ |
461 | dev_dbg(dev, "%s - urb shutting down with status: %d\n", __func__, status); | 467 | dev_dbg(dev, "%s - urb shutting down with status: %d\n", __func__, status); |
462 | return; | 468 | goto out; |
463 | default: | 469 | default: |
464 | dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status); | 470 | dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status); |
465 | return; | 471 | goto out; |
466 | } | 472 | } |
467 | 473 | ||
468 | dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length); | 474 | dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length); |
@@ -475,6 +481,8 @@ static void mos7840_control_callback(struct urb *urb) | |||
475 | mos7840_handle_new_msr(mos7840_port, regval); | 481 | mos7840_handle_new_msr(mos7840_port, regval); |
476 | else if (mos7840_port->MsrLsr == 1) | 482 | else if (mos7840_port->MsrLsr == 1) |
477 | mos7840_handle_new_lsr(mos7840_port, regval); | 483 | mos7840_handle_new_lsr(mos7840_port, regval); |
484 | out: | ||
485 | clear_bit_unlock(MOS7840_FLAG_CTRL_BUSY, &mos7840_port->flags); | ||
478 | } | 486 | } |
479 | 487 | ||
480 | static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, | 488 | static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, |
@@ -485,6 +493,9 @@ static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, | |||
485 | unsigned char *buffer = mcs->ctrl_buf; | 493 | unsigned char *buffer = mcs->ctrl_buf; |
486 | int ret; | 494 | int ret; |
487 | 495 | ||
496 | if (test_and_set_bit_lock(MOS7840_FLAG_CTRL_BUSY, &mcs->flags)) | ||
497 | return -EBUSY; | ||
498 | |||
488 | dr->bRequestType = MCS_RD_RTYPE; | 499 | dr->bRequestType = MCS_RD_RTYPE; |
489 | dr->bRequest = MCS_RDREQ; | 500 | dr->bRequest = MCS_RDREQ; |
490 | dr->wValue = cpu_to_le16(Wval); /* 0 */ | 501 | dr->wValue = cpu_to_le16(Wval); /* 0 */ |
@@ -496,6 +507,9 @@ static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, | |||
496 | mos7840_control_callback, mcs); | 507 | mos7840_control_callback, mcs); |
497 | mcs->control_urb->transfer_buffer_length = 2; | 508 | mcs->control_urb->transfer_buffer_length = 2; |
498 | ret = usb_submit_urb(mcs->control_urb, GFP_ATOMIC); | 509 | ret = usb_submit_urb(mcs->control_urb, GFP_ATOMIC); |
510 | if (ret) | ||
511 | clear_bit_unlock(MOS7840_FLAG_CTRL_BUSY, &mcs->flags); | ||
512 | |||
499 | return ret; | 513 | return ret; |
500 | } | 514 | } |
501 | 515 | ||
@@ -522,7 +536,7 @@ static void mos7840_set_led_async(struct moschip_port *mcs, __u16 wval, | |||
522 | __u16 reg) | 536 | __u16 reg) |
523 | { | 537 | { |
524 | struct usb_device *dev = mcs->port->serial->dev; | 538 | struct usb_device *dev = mcs->port->serial->dev; |
525 | struct usb_ctrlrequest *dr = mcs->dr; | 539 | struct usb_ctrlrequest *dr = mcs->led_dr; |
526 | 540 | ||
527 | dr->bRequestType = MCS_WR_RTYPE; | 541 | dr->bRequestType = MCS_WR_RTYPE; |
528 | dr->bRequest = MCS_WRREQ; | 542 | dr->bRequest = MCS_WRREQ; |
@@ -530,10 +544,10 @@ static void mos7840_set_led_async(struct moschip_port *mcs, __u16 wval, | |||
530 | dr->wIndex = cpu_to_le16(reg); | 544 | dr->wIndex = cpu_to_le16(reg); |
531 | dr->wLength = cpu_to_le16(0); | 545 | dr->wLength = cpu_to_le16(0); |
532 | 546 | ||
533 | usb_fill_control_urb(mcs->control_urb, dev, usb_sndctrlpipe(dev, 0), | 547 | usb_fill_control_urb(mcs->led_urb, dev, usb_sndctrlpipe(dev, 0), |
534 | (unsigned char *)dr, NULL, 0, mos7840_set_led_callback, NULL); | 548 | (unsigned char *)dr, NULL, 0, mos7840_set_led_callback, NULL); |
535 | 549 | ||
536 | usb_submit_urb(mcs->control_urb, GFP_ATOMIC); | 550 | usb_submit_urb(mcs->led_urb, GFP_ATOMIC); |
537 | } | 551 | } |
538 | 552 | ||
539 | static void mos7840_set_led_sync(struct usb_serial_port *port, __u16 reg, | 553 | static void mos7840_set_led_sync(struct usb_serial_port *port, __u16 reg, |
@@ -559,7 +573,19 @@ static void mos7840_led_flag_off(unsigned long arg) | |||
559 | { | 573 | { |
560 | struct moschip_port *mcs = (struct moschip_port *) arg; | 574 | struct moschip_port *mcs = (struct moschip_port *) arg; |
561 | 575 | ||
562 | mcs->led_flag = false; | 576 | clear_bit_unlock(MOS7840_FLAG_LED_BUSY, &mcs->flags); |
577 | } | ||
578 | |||
579 | static void mos7840_led_activity(struct usb_serial_port *port) | ||
580 | { | ||
581 | struct moschip_port *mos7840_port = usb_get_serial_port_data(port); | ||
582 | |||
583 | if (test_and_set_bit_lock(MOS7840_FLAG_LED_BUSY, &mos7840_port->flags)) | ||
584 | return; | ||
585 | |||
586 | mos7840_set_led_async(mos7840_port, 0x0301, MODEM_CONTROL_REGISTER); | ||
587 | mod_timer(&mos7840_port->led_timer1, | ||
588 | jiffies + msecs_to_jiffies(LED_ON_MS)); | ||
563 | } | 589 | } |
564 | 590 | ||
565 | /***************************************************************************** | 591 | /***************************************************************************** |
@@ -757,14 +783,8 @@ static void mos7840_bulk_in_callback(struct urb *urb) | |||
757 | return; | 783 | return; |
758 | } | 784 | } |
759 | 785 | ||
760 | /* Turn on LED */ | 786 | if (mos7840_port->has_led) |
761 | if (mos7840_port->has_led && !mos7840_port->led_flag) { | 787 | mos7840_led_activity(port); |
762 | mos7840_port->led_flag = true; | ||
763 | mos7840_set_led_async(mos7840_port, 0x0301, | ||
764 | MODEM_CONTROL_REGISTER); | ||
765 | mod_timer(&mos7840_port->led_timer1, | ||
766 | jiffies + msecs_to_jiffies(LED_ON_MS)); | ||
767 | } | ||
768 | 788 | ||
769 | mos7840_port->read_urb_busy = true; | 789 | mos7840_port->read_urb_busy = true; |
770 | retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); | 790 | retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); |
@@ -815,18 +835,6 @@ static void mos7840_bulk_out_data_callback(struct urb *urb) | |||
815 | /************************************************************************/ | 835 | /************************************************************************/ |
816 | /* D R I V E R T T Y I N T E R F A C E F U N C T I O N S */ | 836 | /* D R I V E R T T Y I N T E R F A C E F U N C T I O N S */ |
817 | /************************************************************************/ | 837 | /************************************************************************/ |
818 | #ifdef MCSSerialProbe | ||
819 | static int mos7840_serial_probe(struct usb_serial *serial, | ||
820 | const struct usb_device_id *id) | ||
821 | { | ||
822 | |||
823 | /*need to implement the mode_reg reading and updating\ | ||
824 | structures usb_serial_ device_type\ | ||
825 | (i.e num_ports, num_bulkin,bulkout etc) */ | ||
826 | /* Also we can update the changes attach */ | ||
827 | return 1; | ||
828 | } | ||
829 | #endif | ||
830 | 838 | ||
831 | /***************************************************************************** | 839 | /***************************************************************************** |
832 | * mos7840_open | 840 | * mos7840_open |
@@ -1406,13 +1414,8 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
1406 | data1 = urb->transfer_buffer; | 1414 | data1 = urb->transfer_buffer; |
1407 | dev_dbg(&port->dev, "bulkout endpoint is %d\n", port->bulk_out_endpointAddress); | 1415 | dev_dbg(&port->dev, "bulkout endpoint is %d\n", port->bulk_out_endpointAddress); |
1408 | 1416 | ||
1409 | /* Turn on LED */ | 1417 | if (mos7840_port->has_led) |
1410 | if (mos7840_port->has_led && !mos7840_port->led_flag) { | 1418 | mos7840_led_activity(port); |
1411 | mos7840_port->led_flag = true; | ||
1412 | mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0301); | ||
1413 | mod_timer(&mos7840_port->led_timer1, | ||
1414 | jiffies + msecs_to_jiffies(LED_ON_MS)); | ||
1415 | } | ||
1416 | 1419 | ||
1417 | /* send it down the pipe */ | 1420 | /* send it down the pipe */ |
1418 | status = usb_submit_urb(urb, GFP_ATOMIC); | 1421 | status = usb_submit_urb(urb, GFP_ATOMIC); |
@@ -2139,38 +2142,48 @@ static int mos7810_check(struct usb_serial *serial) | |||
2139 | return 0; | 2142 | return 0; |
2140 | } | 2143 | } |
2141 | 2144 | ||
2142 | static int mos7840_calc_num_ports(struct usb_serial *serial) | 2145 | static int mos7840_probe(struct usb_serial *serial, |
2146 | const struct usb_device_id *id) | ||
2143 | { | 2147 | { |
2144 | __u16 data = 0x00; | 2148 | u16 product = serial->dev->descriptor.idProduct; |
2145 | u8 *buf; | 2149 | u8 *buf; |
2146 | int mos7840_num_ports; | 2150 | int device_type; |
2151 | |||
2152 | if (product == MOSCHIP_DEVICE_ID_7810 || | ||
2153 | product == MOSCHIP_DEVICE_ID_7820) { | ||
2154 | device_type = product; | ||
2155 | goto out; | ||
2156 | } | ||
2147 | 2157 | ||
2148 | buf = kzalloc(VENDOR_READ_LENGTH, GFP_KERNEL); | 2158 | buf = kzalloc(VENDOR_READ_LENGTH, GFP_KERNEL); |
2149 | if (buf) { | 2159 | if (!buf) |
2150 | usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | 2160 | return -ENOMEM; |
2161 | |||
2162 | usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | ||
2151 | MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, buf, | 2163 | MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, buf, |
2152 | VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); | 2164 | VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); |
2153 | data = *buf; | ||
2154 | kfree(buf); | ||
2155 | } | ||
2156 | 2165 | ||
2157 | if (serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7810 || | 2166 | /* For a MCS7840 device GPIO0 must be set to 1 */ |
2158 | serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7820) { | 2167 | if (buf[0] & 0x01) |
2159 | device_type = serial->dev->descriptor.idProduct; | 2168 | device_type = MOSCHIP_DEVICE_ID_7840; |
2160 | } else { | 2169 | else if (mos7810_check(serial)) |
2161 | /* For a MCS7840 device GPIO0 must be set to 1 */ | 2170 | device_type = MOSCHIP_DEVICE_ID_7810; |
2162 | if ((data & 0x01) == 1) | 2171 | else |
2163 | device_type = MOSCHIP_DEVICE_ID_7840; | 2172 | device_type = MOSCHIP_DEVICE_ID_7820; |
2164 | else if (mos7810_check(serial)) | 2173 | |
2165 | device_type = MOSCHIP_DEVICE_ID_7810; | 2174 | kfree(buf); |
2166 | else | 2175 | out: |
2167 | device_type = MOSCHIP_DEVICE_ID_7820; | 2176 | usb_set_serial_data(serial, (void *)(unsigned long)device_type); |
2168 | } | 2177 | |
2178 | return 0; | ||
2179 | } | ||
2180 | |||
2181 | static int mos7840_calc_num_ports(struct usb_serial *serial) | ||
2182 | { | ||
2183 | int device_type = (unsigned long)usb_get_serial_data(serial); | ||
2184 | int mos7840_num_ports; | ||
2169 | 2185 | ||
2170 | mos7840_num_ports = (device_type >> 4) & 0x000F; | 2186 | mos7840_num_ports = (device_type >> 4) & 0x000F; |
2171 | serial->num_bulk_in = mos7840_num_ports; | ||
2172 | serial->num_bulk_out = mos7840_num_ports; | ||
2173 | serial->num_ports = mos7840_num_ports; | ||
2174 | 2187 | ||
2175 | return mos7840_num_ports; | 2188 | return mos7840_num_ports; |
2176 | } | 2189 | } |
@@ -2178,6 +2191,7 @@ static int mos7840_calc_num_ports(struct usb_serial *serial) | |||
2178 | static int mos7840_port_probe(struct usb_serial_port *port) | 2191 | static int mos7840_port_probe(struct usb_serial_port *port) |
2179 | { | 2192 | { |
2180 | struct usb_serial *serial = port->serial; | 2193 | struct usb_serial *serial = port->serial; |
2194 | int device_type = (unsigned long)usb_get_serial_data(serial); | ||
2181 | struct moschip_port *mos7840_port; | 2195 | struct moschip_port *mos7840_port; |
2182 | int status; | 2196 | int status; |
2183 | int pnum; | 2197 | int pnum; |
@@ -2353,6 +2367,14 @@ static int mos7840_port_probe(struct usb_serial_port *port) | |||
2353 | if (device_type == MOSCHIP_DEVICE_ID_7810) { | 2367 | if (device_type == MOSCHIP_DEVICE_ID_7810) { |
2354 | mos7840_port->has_led = true; | 2368 | mos7840_port->has_led = true; |
2355 | 2369 | ||
2370 | mos7840_port->led_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
2371 | mos7840_port->led_dr = kmalloc(sizeof(*mos7840_port->led_dr), | ||
2372 | GFP_KERNEL); | ||
2373 | if (!mos7840_port->led_urb || !mos7840_port->led_dr) { | ||
2374 | status = -ENOMEM; | ||
2375 | goto error; | ||
2376 | } | ||
2377 | |||
2356 | init_timer(&mos7840_port->led_timer1); | 2378 | init_timer(&mos7840_port->led_timer1); |
2357 | mos7840_port->led_timer1.function = mos7840_led_off; | 2379 | mos7840_port->led_timer1.function = mos7840_led_off; |
2358 | mos7840_port->led_timer1.expires = | 2380 | mos7840_port->led_timer1.expires = |
@@ -2365,8 +2387,6 @@ static int mos7840_port_probe(struct usb_serial_port *port) | |||
2365 | jiffies + msecs_to_jiffies(LED_OFF_MS); | 2387 | jiffies + msecs_to_jiffies(LED_OFF_MS); |
2366 | mos7840_port->led_timer2.data = (unsigned long)mos7840_port; | 2388 | mos7840_port->led_timer2.data = (unsigned long)mos7840_port; |
2367 | 2389 | ||
2368 | mos7840_port->led_flag = false; | ||
2369 | |||
2370 | /* Turn off LED */ | 2390 | /* Turn off LED */ |
2371 | mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); | 2391 | mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); |
2372 | } | 2392 | } |
@@ -2388,6 +2408,8 @@ out: | |||
2388 | } | 2408 | } |
2389 | return 0; | 2409 | return 0; |
2390 | error: | 2410 | error: |
2411 | kfree(mos7840_port->led_dr); | ||
2412 | usb_free_urb(mos7840_port->led_urb); | ||
2391 | kfree(mos7840_port->dr); | 2413 | kfree(mos7840_port->dr); |
2392 | kfree(mos7840_port->ctrl_buf); | 2414 | kfree(mos7840_port->ctrl_buf); |
2393 | usb_free_urb(mos7840_port->control_urb); | 2415 | usb_free_urb(mos7840_port->control_urb); |
@@ -2408,6 +2430,10 @@ static int mos7840_port_remove(struct usb_serial_port *port) | |||
2408 | 2430 | ||
2409 | del_timer_sync(&mos7840_port->led_timer1); | 2431 | del_timer_sync(&mos7840_port->led_timer1); |
2410 | del_timer_sync(&mos7840_port->led_timer2); | 2432 | del_timer_sync(&mos7840_port->led_timer2); |
2433 | |||
2434 | usb_kill_urb(mos7840_port->led_urb); | ||
2435 | usb_free_urb(mos7840_port->led_urb); | ||
2436 | kfree(mos7840_port->led_dr); | ||
2411 | } | 2437 | } |
2412 | usb_kill_urb(mos7840_port->control_urb); | 2438 | usb_kill_urb(mos7840_port->control_urb); |
2413 | usb_free_urb(mos7840_port->control_urb); | 2439 | usb_free_urb(mos7840_port->control_urb); |
@@ -2434,9 +2460,7 @@ static struct usb_serial_driver moschip7840_4port_device = { | |||
2434 | .throttle = mos7840_throttle, | 2460 | .throttle = mos7840_throttle, |
2435 | .unthrottle = mos7840_unthrottle, | 2461 | .unthrottle = mos7840_unthrottle, |
2436 | .calc_num_ports = mos7840_calc_num_ports, | 2462 | .calc_num_ports = mos7840_calc_num_ports, |
2437 | #ifdef MCSSerialProbe | 2463 | .probe = mos7840_probe, |
2438 | .probe = mos7840_serial_probe, | ||
2439 | #endif | ||
2440 | .ioctl = mos7840_ioctl, | 2464 | .ioctl = mos7840_ioctl, |
2441 | .set_termios = mos7840_set_termios, | 2465 | .set_termios = mos7840_set_termios, |
2442 | .break_ctl = mos7840_break, | 2466 | .break_ctl = mos7840_break, |