diff options
Diffstat (limited to 'drivers/usb/serial/mos7840.c')
-rw-r--r-- | drivers/usb/serial/mos7840.c | 495 |
1 files changed, 207 insertions, 288 deletions
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index d6d4eeca8c68..1cf3375ec1af 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
@@ -218,12 +218,10 @@ struct moschip_port { | |||
218 | int port_num; /*Actual port number in the device(1,2,etc) */ | 218 | int port_num; /*Actual port number in the device(1,2,etc) */ |
219 | struct urb *write_urb; /* write URB for this port */ | 219 | struct urb *write_urb; /* write URB for this port */ |
220 | struct urb *read_urb; /* read URB for this port */ | 220 | struct urb *read_urb; /* read URB for this port */ |
221 | struct urb *int_urb; | ||
222 | __u8 shadowLCR; /* last LCR value received */ | 221 | __u8 shadowLCR; /* last LCR value received */ |
223 | __u8 shadowMCR; /* last MCR value received */ | 222 | __u8 shadowMCR; /* last MCR value received */ |
224 | char open; | 223 | char open; |
225 | char open_ports; | 224 | char open_ports; |
226 | char zombie; | ||
227 | wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ | 225 | wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ |
228 | wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ | 226 | wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ |
229 | int delta_msr_cond; | 227 | int delta_msr_cond; |
@@ -478,7 +476,6 @@ static void mos7840_control_callback(struct urb *urb) | |||
478 | struct moschip_port *mos7840_port; | 476 | struct moschip_port *mos7840_port; |
479 | struct device *dev = &urb->dev->dev; | 477 | struct device *dev = &urb->dev->dev; |
480 | __u8 regval = 0x0; | 478 | __u8 regval = 0x0; |
481 | int result = 0; | ||
482 | int status = urb->status; | 479 | int status = urb->status; |
483 | 480 | ||
484 | mos7840_port = urb->context; | 481 | mos7840_port = urb->context; |
@@ -495,7 +492,7 @@ static void mos7840_control_callback(struct urb *urb) | |||
495 | return; | 492 | return; |
496 | default: | 493 | default: |
497 | dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status); | 494 | dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status); |
498 | goto exit; | 495 | return; |
499 | } | 496 | } |
500 | 497 | ||
501 | dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length); | 498 | dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length); |
@@ -508,16 +505,6 @@ static void mos7840_control_callback(struct urb *urb) | |||
508 | mos7840_handle_new_msr(mos7840_port, regval); | 505 | mos7840_handle_new_msr(mos7840_port, regval); |
509 | else if (mos7840_port->MsrLsr == 1) | 506 | else if (mos7840_port->MsrLsr == 1) |
510 | mos7840_handle_new_lsr(mos7840_port, regval); | 507 | mos7840_handle_new_lsr(mos7840_port, regval); |
511 | |||
512 | exit: | ||
513 | spin_lock(&mos7840_port->pool_lock); | ||
514 | if (!mos7840_port->zombie) | ||
515 | result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC); | ||
516 | spin_unlock(&mos7840_port->pool_lock); | ||
517 | if (result) { | ||
518 | dev_err(dev, "%s - Error %d submitting interrupt urb\n", | ||
519 | __func__, result); | ||
520 | } | ||
521 | } | 508 | } |
522 | 509 | ||
523 | static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, | 510 | static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, |
@@ -686,14 +673,7 @@ static void mos7840_interrupt_callback(struct urb *urb) | |||
686 | wreg = MODEM_STATUS_REGISTER; | 673 | wreg = MODEM_STATUS_REGISTER; |
687 | break; | 674 | break; |
688 | } | 675 | } |
689 | spin_lock(&mos7840_port->pool_lock); | 676 | rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); |
690 | if (!mos7840_port->zombie) { | ||
691 | rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); | ||
692 | } else { | ||
693 | spin_unlock(&mos7840_port->pool_lock); | ||
694 | return; | ||
695 | } | ||
696 | spin_unlock(&mos7840_port->pool_lock); | ||
697 | } | 677 | } |
698 | } | 678 | } |
699 | } | 679 | } |
@@ -2347,309 +2327,249 @@ static int mos7840_calc_num_ports(struct usb_serial *serial) | |||
2347 | return mos7840_num_ports; | 2327 | return mos7840_num_ports; |
2348 | } | 2328 | } |
2349 | 2329 | ||
2350 | /**************************************************************************** | 2330 | static int mos7840_port_probe(struct usb_serial_port *port) |
2351 | * mos7840_startup | ||
2352 | ****************************************************************************/ | ||
2353 | |||
2354 | static int mos7840_startup(struct usb_serial *serial) | ||
2355 | { | 2331 | { |
2332 | struct usb_serial *serial = port->serial; | ||
2356 | struct moschip_port *mos7840_port; | 2333 | struct moschip_port *mos7840_port; |
2357 | struct usb_device *dev; | 2334 | int status; |
2358 | int i, status; | 2335 | int pnum; |
2359 | __u16 Data; | 2336 | __u16 Data; |
2360 | 2337 | ||
2361 | dev = serial->dev; | ||
2362 | |||
2363 | /* we set up the pointers to the endpoints in the mos7840_open * | 2338 | /* we set up the pointers to the endpoints in the mos7840_open * |
2364 | * function, as the structures aren't created yet. */ | 2339 | * function, as the structures aren't created yet. */ |
2365 | 2340 | ||
2366 | /* set up port private structures */ | 2341 | pnum = port->number - serial->minor; |
2367 | for (i = 0; i < serial->num_ports; ++i) { | ||
2368 | dev_dbg(&dev->dev, "mos7840_startup: configuring port %d............\n", i); | ||
2369 | mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); | ||
2370 | if (mos7840_port == NULL) { | ||
2371 | dev_err(&dev->dev, "%s - Out of memory\n", __func__); | ||
2372 | status = -ENOMEM; | ||
2373 | i--; /* don't follow NULL pointer cleaning up */ | ||
2374 | goto error; | ||
2375 | } | ||
2376 | |||
2377 | /* Initialize all port interrupt end point to port 0 int | ||
2378 | * endpoint. Our device has only one interrupt end point | ||
2379 | * common to all port */ | ||
2380 | |||
2381 | mos7840_port->port = serial->port[i]; | ||
2382 | mos7840_set_port_private(serial->port[i], mos7840_port); | ||
2383 | spin_lock_init(&mos7840_port->pool_lock); | ||
2384 | |||
2385 | /* minor is not initialised until later by | ||
2386 | * usb-serial.c:get_free_serial() and cannot therefore be used | ||
2387 | * to index device instances */ | ||
2388 | mos7840_port->port_num = i + 1; | ||
2389 | dev_dbg(&dev->dev, "serial->port[i]->number = %d\n", serial->port[i]->number); | ||
2390 | dev_dbg(&dev->dev, "serial->port[i]->serial->minor = %d\n", serial->port[i]->serial->minor); | ||
2391 | dev_dbg(&dev->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); | ||
2392 | dev_dbg(&dev->dev, "serial->minor = %d\n", serial->minor); | ||
2393 | |||
2394 | if (mos7840_port->port_num == 1) { | ||
2395 | mos7840_port->SpRegOffset = 0x0; | ||
2396 | mos7840_port->ControlRegOffset = 0x1; | ||
2397 | mos7840_port->DcrRegOffset = 0x4; | ||
2398 | } else if ((mos7840_port->port_num == 2) | ||
2399 | && (serial->num_ports == 4)) { | ||
2400 | mos7840_port->SpRegOffset = 0x8; | ||
2401 | mos7840_port->ControlRegOffset = 0x9; | ||
2402 | mos7840_port->DcrRegOffset = 0x16; | ||
2403 | } else if ((mos7840_port->port_num == 2) | ||
2404 | && (serial->num_ports == 2)) { | ||
2405 | mos7840_port->SpRegOffset = 0xa; | ||
2406 | mos7840_port->ControlRegOffset = 0xb; | ||
2407 | mos7840_port->DcrRegOffset = 0x19; | ||
2408 | } else if ((mos7840_port->port_num == 3) | ||
2409 | && (serial->num_ports == 4)) { | ||
2410 | mos7840_port->SpRegOffset = 0xa; | ||
2411 | mos7840_port->ControlRegOffset = 0xb; | ||
2412 | mos7840_port->DcrRegOffset = 0x19; | ||
2413 | } else if ((mos7840_port->port_num == 4) | ||
2414 | && (serial->num_ports == 4)) { | ||
2415 | mos7840_port->SpRegOffset = 0xc; | ||
2416 | mos7840_port->ControlRegOffset = 0xd; | ||
2417 | mos7840_port->DcrRegOffset = 0x1c; | ||
2418 | } | ||
2419 | mos7840_dump_serial_port(serial->port[i], mos7840_port); | ||
2420 | mos7840_set_port_private(serial->port[i], mos7840_port); | ||
2421 | 2342 | ||
2422 | /* enable rx_disable bit in control register */ | 2343 | dev_dbg(&port->dev, "mos7840_startup: configuring port %d\n", pnum); |
2423 | status = mos7840_get_reg_sync(serial->port[i], | 2344 | mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); |
2424 | mos7840_port->ControlRegOffset, &Data); | 2345 | if (mos7840_port == NULL) { |
2425 | if (status < 0) { | 2346 | dev_err(&port->dev, "%s - Out of memory\n", __func__); |
2426 | dev_dbg(&dev->dev, "Reading ControlReg failed status-0x%x\n", status); | 2347 | return -ENOMEM; |
2427 | break; | 2348 | } |
2428 | } else | ||
2429 | dev_dbg(&dev->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); | ||
2430 | Data |= 0x08; /* setting driver done bit */ | ||
2431 | Data |= 0x04; /* sp1_bit to have cts change reflect in | ||
2432 | modem status reg */ | ||
2433 | |||
2434 | /* Data |= 0x20; //rx_disable bit */ | ||
2435 | status = mos7840_set_reg_sync(serial->port[i], | ||
2436 | mos7840_port->ControlRegOffset, Data); | ||
2437 | if (status < 0) { | ||
2438 | dev_dbg(&dev->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); | ||
2439 | break; | ||
2440 | } else | ||
2441 | dev_dbg(&dev->dev, "ControlReg Writing success(rx_disable) status%d\n", status); | ||
2442 | 2349 | ||
2443 | /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 | 2350 | /* Initialize all port interrupt end point to port 0 int |
2444 | and 0x24 in DCR3 */ | 2351 | * endpoint. Our device has only one interrupt end point |
2445 | Data = 0x01; | 2352 | * common to all port */ |
2446 | status = mos7840_set_reg_sync(serial->port[i], | 2353 | |
2447 | (__u16) (mos7840_port->DcrRegOffset + 0), Data); | 2354 | mos7840_port->port = port; |
2448 | if (status < 0) { | 2355 | mos7840_set_port_private(port, mos7840_port); |
2449 | dev_dbg(&dev->dev, "Writing DCR0 failed status-0x%x\n", status); | 2356 | spin_lock_init(&mos7840_port->pool_lock); |
2450 | break; | 2357 | |
2451 | } else | 2358 | /* minor is not initialised until later by |
2452 | dev_dbg(&dev->dev, "DCR0 Writing success status%d\n", status); | 2359 | * usb-serial.c:get_free_serial() and cannot therefore be used |
2360 | * to index device instances */ | ||
2361 | mos7840_port->port_num = pnum + 1; | ||
2362 | dev_dbg(&port->dev, "port->number = %d\n", port->number); | ||
2363 | dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor); | ||
2364 | dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); | ||
2365 | dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor); | ||
2366 | |||
2367 | if (mos7840_port->port_num == 1) { | ||
2368 | mos7840_port->SpRegOffset = 0x0; | ||
2369 | mos7840_port->ControlRegOffset = 0x1; | ||
2370 | mos7840_port->DcrRegOffset = 0x4; | ||
2371 | } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 4)) { | ||
2372 | mos7840_port->SpRegOffset = 0x8; | ||
2373 | mos7840_port->ControlRegOffset = 0x9; | ||
2374 | mos7840_port->DcrRegOffset = 0x16; | ||
2375 | } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 2)) { | ||
2376 | mos7840_port->SpRegOffset = 0xa; | ||
2377 | mos7840_port->ControlRegOffset = 0xb; | ||
2378 | mos7840_port->DcrRegOffset = 0x19; | ||
2379 | } else if ((mos7840_port->port_num == 3) && (serial->num_ports == 4)) { | ||
2380 | mos7840_port->SpRegOffset = 0xa; | ||
2381 | mos7840_port->ControlRegOffset = 0xb; | ||
2382 | mos7840_port->DcrRegOffset = 0x19; | ||
2383 | } else if ((mos7840_port->port_num == 4) && (serial->num_ports == 4)) { | ||
2384 | mos7840_port->SpRegOffset = 0xc; | ||
2385 | mos7840_port->ControlRegOffset = 0xd; | ||
2386 | mos7840_port->DcrRegOffset = 0x1c; | ||
2387 | } | ||
2388 | mos7840_dump_serial_port(port, mos7840_port); | ||
2389 | mos7840_set_port_private(port, mos7840_port); | ||
2390 | |||
2391 | /* enable rx_disable bit in control register */ | ||
2392 | status = mos7840_get_reg_sync(port, | ||
2393 | mos7840_port->ControlRegOffset, &Data); | ||
2394 | if (status < 0) { | ||
2395 | dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status); | ||
2396 | goto out; | ||
2397 | } else | ||
2398 | dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); | ||
2399 | Data |= 0x08; /* setting driver done bit */ | ||
2400 | Data |= 0x04; /* sp1_bit to have cts change reflect in | ||
2401 | modem status reg */ | ||
2453 | 2402 | ||
2454 | Data = 0x05; | 2403 | /* Data |= 0x20; //rx_disable bit */ |
2455 | status = mos7840_set_reg_sync(serial->port[i], | 2404 | status = mos7840_set_reg_sync(port, |
2456 | (__u16) (mos7840_port->DcrRegOffset + 1), Data); | 2405 | mos7840_port->ControlRegOffset, Data); |
2457 | if (status < 0) { | 2406 | if (status < 0) { |
2458 | dev_dbg(&dev->dev, "Writing DCR1 failed status-0x%x\n", status); | 2407 | dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); |
2459 | break; | 2408 | goto out; |
2460 | } else | 2409 | } else |
2461 | dev_dbg(&dev->dev, "DCR1 Writing success status%d\n", status); | 2410 | dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status); |
2462 | 2411 | ||
2463 | Data = 0x24; | 2412 | /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 |
2464 | status = mos7840_set_reg_sync(serial->port[i], | 2413 | and 0x24 in DCR3 */ |
2465 | (__u16) (mos7840_port->DcrRegOffset + 2), Data); | 2414 | Data = 0x01; |
2466 | if (status < 0) { | 2415 | status = mos7840_set_reg_sync(port, |
2467 | dev_dbg(&dev->dev, "Writing DCR2 failed status-0x%x\n", status); | 2416 | (__u16) (mos7840_port->DcrRegOffset + 0), Data); |
2468 | break; | 2417 | if (status < 0) { |
2469 | } else | 2418 | dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status); |
2470 | dev_dbg(&dev->dev, "DCR2 Writing success status%d\n", status); | 2419 | goto out; |
2420 | } else | ||
2421 | dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status); | ||
2471 | 2422 | ||
2472 | /* write values in clkstart0x0 and clkmulti 0x20 */ | 2423 | Data = 0x05; |
2473 | Data = 0x0; | 2424 | status = mos7840_set_reg_sync(port, |
2474 | status = mos7840_set_reg_sync(serial->port[i], | 2425 | (__u16) (mos7840_port->DcrRegOffset + 1), Data); |
2475 | CLK_START_VALUE_REGISTER, Data); | 2426 | if (status < 0) { |
2476 | if (status < 0) { | 2427 | dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status); |
2477 | dev_dbg(&dev->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); | 2428 | goto out; |
2478 | break; | 2429 | } else |
2479 | } else | 2430 | dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status); |
2480 | dev_dbg(&dev->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); | ||
2481 | 2431 | ||
2482 | Data = 0x20; | 2432 | Data = 0x24; |
2483 | status = mos7840_set_reg_sync(serial->port[i], | 2433 | status = mos7840_set_reg_sync(port, |
2484 | CLK_MULTI_REGISTER, Data); | 2434 | (__u16) (mos7840_port->DcrRegOffset + 2), Data); |
2485 | if (status < 0) { | 2435 | if (status < 0) { |
2486 | dev_dbg(&dev->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); | 2436 | dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status); |
2487 | goto error; | 2437 | goto out; |
2488 | } else | 2438 | } else |
2489 | dev_dbg(&dev->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); | 2439 | dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status); |
2490 | 2440 | ||
2491 | /* write value 0x0 to scratchpad register */ | 2441 | /* write values in clkstart0x0 and clkmulti 0x20 */ |
2492 | Data = 0x00; | 2442 | Data = 0x0; |
2493 | status = mos7840_set_uart_reg(serial->port[i], | 2443 | status = mos7840_set_reg_sync(port, CLK_START_VALUE_REGISTER, Data); |
2494 | SCRATCH_PAD_REGISTER, Data); | 2444 | if (status < 0) { |
2495 | if (status < 0) { | 2445 | dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); |
2496 | dev_dbg(&dev->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); | 2446 | goto out; |
2497 | break; | 2447 | } else |
2498 | } else | 2448 | dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); |
2499 | dev_dbg(&dev->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); | ||
2500 | 2449 | ||
2501 | /* Zero Length flag register */ | 2450 | Data = 0x20; |
2502 | if ((mos7840_port->port_num != 1) | 2451 | status = mos7840_set_reg_sync(port, CLK_MULTI_REGISTER, Data); |
2503 | && (serial->num_ports == 2)) { | 2452 | if (status < 0) { |
2453 | dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); | ||
2454 | goto error; | ||
2455 | } else | ||
2456 | dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); | ||
2504 | 2457 | ||
2505 | Data = 0xff; | 2458 | /* write value 0x0 to scratchpad register */ |
2506 | status = mos7840_set_reg_sync(serial->port[i], | 2459 | Data = 0x00; |
2507 | (__u16) (ZLP_REG1 + | 2460 | status = mos7840_set_uart_reg(port, SCRATCH_PAD_REGISTER, Data); |
2508 | ((__u16)mos7840_port->port_num)), Data); | 2461 | if (status < 0) { |
2509 | dev_dbg(&dev->dev, "ZLIP offset %x\n", | 2462 | dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); |
2463 | goto out; | ||
2464 | } else | ||
2465 | dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); | ||
2466 | |||
2467 | /* Zero Length flag register */ | ||
2468 | if ((mos7840_port->port_num != 1) && (serial->num_ports == 2)) { | ||
2469 | Data = 0xff; | ||
2470 | status = mos7840_set_reg_sync(port, | ||
2471 | (__u16) (ZLP_REG1 + | ||
2472 | ((__u16)mos7840_port->port_num)), Data); | ||
2473 | dev_dbg(&port->dev, "ZLIP offset %x\n", | ||
2510 | (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num))); | 2474 | (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num))); |
2511 | if (status < 0) { | 2475 | if (status < 0) { |
2512 | dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 2, status); | 2476 | dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status); |
2513 | break; | 2477 | goto out; |
2514 | } else | 2478 | } else |
2515 | dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 2, status); | 2479 | dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status); |
2516 | } else { | 2480 | } else { |
2517 | Data = 0xff; | 2481 | Data = 0xff; |
2518 | status = mos7840_set_reg_sync(serial->port[i], | 2482 | status = mos7840_set_reg_sync(port, |
2519 | (__u16) (ZLP_REG1 + | 2483 | (__u16) (ZLP_REG1 + |
2520 | ((__u16)mos7840_port->port_num) - 0x1), Data); | 2484 | ((__u16)mos7840_port->port_num) - 0x1), Data); |
2521 | dev_dbg(&dev->dev, "ZLIP offset %x\n", | 2485 | dev_dbg(&port->dev, "ZLIP offset %x\n", |
2522 | (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1)); | 2486 | (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1)); |
2523 | if (status < 0) { | 2487 | if (status < 0) { |
2524 | dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 1, status); | 2488 | dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status); |
2525 | break; | 2489 | goto out; |
2526 | } else | 2490 | } else |
2527 | dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 1, status); | 2491 | dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status); |
2528 | 2492 | ||
2529 | } | 2493 | } |
2530 | mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); | 2494 | mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); |
2531 | mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); | 2495 | mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); |
2532 | mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), | 2496 | mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), |
2533 | GFP_KERNEL); | 2497 | GFP_KERNEL); |
2534 | if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || | 2498 | if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || |
2535 | !mos7840_port->dr) { | 2499 | !mos7840_port->dr) { |
2536 | status = -ENOMEM; | 2500 | status = -ENOMEM; |
2537 | goto error; | 2501 | goto error; |
2538 | } | 2502 | } |
2539 | 2503 | ||
2540 | mos7840_port->has_led = false; | 2504 | mos7840_port->has_led = false; |
2541 | 2505 | ||
2542 | /* Initialize LED timers */ | 2506 | /* Initialize LED timers */ |
2543 | if (device_type == MOSCHIP_DEVICE_ID_7810) { | 2507 | if (device_type == MOSCHIP_DEVICE_ID_7810) { |
2544 | mos7840_port->has_led = true; | 2508 | mos7840_port->has_led = true; |
2545 | 2509 | ||
2546 | init_timer(&mos7840_port->led_timer1); | 2510 | init_timer(&mos7840_port->led_timer1); |
2547 | mos7840_port->led_timer1.function = mos7840_led_off; | 2511 | mos7840_port->led_timer1.function = mos7840_led_off; |
2548 | mos7840_port->led_timer1.expires = | 2512 | mos7840_port->led_timer1.expires = |
2549 | jiffies + msecs_to_jiffies(LED_ON_MS); | 2513 | jiffies + msecs_to_jiffies(LED_ON_MS); |
2550 | mos7840_port->led_timer1.data = | 2514 | mos7840_port->led_timer1.data = (unsigned long)mos7840_port; |
2551 | (unsigned long)mos7840_port; | ||
2552 | 2515 | ||
2553 | init_timer(&mos7840_port->led_timer2); | 2516 | init_timer(&mos7840_port->led_timer2); |
2554 | mos7840_port->led_timer2.function = | 2517 | mos7840_port->led_timer2.function = mos7840_led_flag_off; |
2555 | mos7840_led_flag_off; | 2518 | mos7840_port->led_timer2.expires = |
2556 | mos7840_port->led_timer2.expires = | 2519 | jiffies + msecs_to_jiffies(LED_OFF_MS); |
2557 | jiffies + msecs_to_jiffies(LED_OFF_MS); | 2520 | mos7840_port->led_timer2.data = (unsigned long)mos7840_port; |
2558 | mos7840_port->led_timer2.data = | ||
2559 | (unsigned long)mos7840_port; | ||
2560 | 2521 | ||
2561 | mos7840_port->led_flag = false; | 2522 | mos7840_port->led_flag = false; |
2562 | 2523 | ||
2563 | /* Turn off LED */ | 2524 | /* Turn off LED */ |
2564 | mos7840_set_led_sync(serial->port[i], | 2525 | mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); |
2565 | MODEM_CONTROL_REGISTER, 0x0300); | ||
2566 | } | ||
2567 | } | 2526 | } |
2527 | out: | ||
2528 | if (pnum == serial->num_ports - 1) { | ||
2529 | /* Zero Length flag enable */ | ||
2530 | Data = 0x0f; | ||
2531 | status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); | ||
2532 | if (status < 0) { | ||
2533 | dev_dbg(&port->dev, "Writing ZLP_REG5 failed status-0x%x\n", status); | ||
2534 | goto error; | ||
2535 | } else | ||
2536 | dev_dbg(&port->dev, "ZLP_REG5 Writing success status%d\n", status); | ||
2568 | 2537 | ||
2569 | /* Zero Length flag enable */ | 2538 | /* setting configuration feature to one */ |
2570 | Data = 0x0f; | 2539 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
2571 | status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); | 2540 | 0x03, 0x00, 0x01, 0x00, NULL, 0x00, |
2572 | if (status < 0) { | 2541 | MOS_WDR_TIMEOUT); |
2573 | dev_dbg(&dev->dev, "Writing ZLP_REG5 failed status-0x%x\n", status); | 2542 | } |
2574 | goto error; | ||
2575 | } else | ||
2576 | dev_dbg(&dev->dev, "ZLP_REG5 Writing success status%d\n", status); | ||
2577 | |||
2578 | /* setting configuration feature to one */ | ||
2579 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
2580 | (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT); | ||
2581 | return 0; | 2543 | return 0; |
2582 | error: | 2544 | error: |
2583 | for (/* nothing */; i >= 0; i--) { | 2545 | kfree(mos7840_port->dr); |
2584 | mos7840_port = mos7840_get_port_private(serial->port[i]); | 2546 | kfree(mos7840_port->ctrl_buf); |
2547 | usb_free_urb(mos7840_port->control_urb); | ||
2548 | kfree(mos7840_port); | ||
2585 | 2549 | ||
2586 | kfree(mos7840_port->dr); | ||
2587 | kfree(mos7840_port->ctrl_buf); | ||
2588 | usb_free_urb(mos7840_port->control_urb); | ||
2589 | kfree(mos7840_port); | ||
2590 | serial->port[i] = NULL; | ||
2591 | } | ||
2592 | return status; | 2550 | return status; |
2593 | } | 2551 | } |
2594 | 2552 | ||
2595 | /**************************************************************************** | 2553 | static int mos7840_port_remove(struct usb_serial_port *port) |
2596 | * mos7840_disconnect | ||
2597 | * This function is called whenever the device is removed from the usb bus. | ||
2598 | ****************************************************************************/ | ||
2599 | |||
2600 | static void mos7840_disconnect(struct usb_serial *serial) | ||
2601 | { | 2554 | { |
2602 | int i; | ||
2603 | unsigned long flags; | ||
2604 | struct moschip_port *mos7840_port; | 2555 | struct moschip_port *mos7840_port; |
2605 | 2556 | ||
2606 | /* check for the ports to be closed,close the ports and disconnect */ | 2557 | mos7840_port = mos7840_get_port_private(port); |
2607 | 2558 | ||
2608 | /* free private structure allocated for serial port * | 2559 | if (mos7840_port->has_led) { |
2609 | * stop reads and writes on all ports */ | 2560 | /* Turn off LED */ |
2561 | mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); | ||
2610 | 2562 | ||
2611 | for (i = 0; i < serial->num_ports; ++i) { | 2563 | del_timer_sync(&mos7840_port->led_timer1); |
2612 | mos7840_port = mos7840_get_port_private(serial->port[i]); | 2564 | del_timer_sync(&mos7840_port->led_timer2); |
2613 | if (mos7840_port) { | ||
2614 | spin_lock_irqsave(&mos7840_port->pool_lock, flags); | ||
2615 | mos7840_port->zombie = 1; | ||
2616 | spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); | ||
2617 | usb_kill_urb(mos7840_port->control_urb); | ||
2618 | } | ||
2619 | } | 2565 | } |
2620 | } | 2566 | usb_kill_urb(mos7840_port->control_urb); |
2621 | 2567 | usb_free_urb(mos7840_port->control_urb); | |
2622 | /**************************************************************************** | 2568 | kfree(mos7840_port->ctrl_buf); |
2623 | * mos7840_release | 2569 | kfree(mos7840_port->dr); |
2624 | * This function is called when the usb_serial structure is freed. | 2570 | kfree(mos7840_port); |
2625 | ****************************************************************************/ | ||
2626 | |||
2627 | static void mos7840_release(struct usb_serial *serial) | ||
2628 | { | ||
2629 | int i; | ||
2630 | struct moschip_port *mos7840_port; | ||
2631 | |||
2632 | /* check for the ports to be closed,close the ports and disconnect */ | ||
2633 | 2571 | ||
2634 | /* free private structure allocated for serial port * | 2572 | return 0; |
2635 | * stop reads and writes on all ports */ | ||
2636 | |||
2637 | for (i = 0; i < serial->num_ports; ++i) { | ||
2638 | mos7840_port = mos7840_get_port_private(serial->port[i]); | ||
2639 | if (mos7840_port) { | ||
2640 | if (mos7840_port->has_led) { | ||
2641 | /* Turn off LED */ | ||
2642 | mos7840_set_led_sync(mos7840_port->port, | ||
2643 | MODEM_CONTROL_REGISTER, 0x0300); | ||
2644 | |||
2645 | del_timer_sync(&mos7840_port->led_timer1); | ||
2646 | del_timer_sync(&mos7840_port->led_timer2); | ||
2647 | } | ||
2648 | kfree(mos7840_port->ctrl_buf); | ||
2649 | kfree(mos7840_port->dr); | ||
2650 | kfree(mos7840_port); | ||
2651 | } | ||
2652 | } | ||
2653 | } | 2573 | } |
2654 | 2574 | ||
2655 | static struct usb_serial_driver moschip7840_4port_device = { | 2575 | static struct usb_serial_driver moschip7840_4port_device = { |
@@ -2677,9 +2597,8 @@ static struct usb_serial_driver moschip7840_4port_device = { | |||
2677 | .tiocmget = mos7840_tiocmget, | 2597 | .tiocmget = mos7840_tiocmget, |
2678 | .tiocmset = mos7840_tiocmset, | 2598 | .tiocmset = mos7840_tiocmset, |
2679 | .get_icount = mos7840_get_icount, | 2599 | .get_icount = mos7840_get_icount, |
2680 | .attach = mos7840_startup, | 2600 | .port_probe = mos7840_port_probe, |
2681 | .disconnect = mos7840_disconnect, | 2601 | .port_remove = mos7840_port_remove, |
2682 | .release = mos7840_release, | ||
2683 | .read_bulk_callback = mos7840_bulk_in_callback, | 2602 | .read_bulk_callback = mos7840_bulk_in_callback, |
2684 | .read_int_callback = mos7840_interrupt_callback, | 2603 | .read_int_callback = mos7840_interrupt_callback, |
2685 | }; | 2604 | }; |