diff options
| author | Johan Hovold <jhovold@gmail.com> | 2012-10-25 12:56:34 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-25 14:11:19 -0400 |
| commit | 80c00750f0c9867a65b30a17880939b6bc660a77 (patch) | |
| tree | b8bc2072f4df67ad5889b95fc19957b4af466ee0 | |
| parent | e681b66f2e19fadbe8a7e2a17900978cb6bc921f (diff) | |
USB: mos7840: fix port-data memory leak
Fix port-data memory leak by moving port data allocation and
deallocation to port_probe and port_remove.
Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no
driver is bound) the port private data is no longer freed at release as
it is no longer accessible.
Note that the indentation was kept intact using a do-while(0) in order
to facilitate review. A follow-up patch will remove it.
Compile-only tested.
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rw-r--r-- | drivers/usb/serial/mos7840.c | 219 |
1 files changed, 89 insertions, 130 deletions
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 84f8c106e5e9..bc3df86134fe 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
| @@ -2327,49 +2327,45 @@ static int mos7840_calc_num_ports(struct usb_serial *serial) | |||
| 2327 | return mos7840_num_ports; | 2327 | return mos7840_num_ports; |
| 2328 | } | 2328 | } |
| 2329 | 2329 | ||
| 2330 | /**************************************************************************** | 2330 | static int mos7840_port_probe(struct usb_serial_port *port) |
| 2331 | * mos7840_startup | ||
| 2332 | ****************************************************************************/ | ||
| 2333 | |||
| 2334 | static int mos7840_startup(struct usb_serial *serial) | ||
| 2335 | { | 2331 | { |
| 2332 | struct usb_serial *serial = port->serial; | ||
| 2336 | struct moschip_port *mos7840_port; | 2333 | struct moschip_port *mos7840_port; |
| 2337 | struct usb_device *dev; | 2334 | int status; |
| 2338 | int i, status; | 2335 | int pnum; |
| 2339 | __u16 Data; | 2336 | __u16 Data; |
| 2340 | 2337 | ||
| 2341 | dev = serial->dev; | ||
| 2342 | |||
| 2343 | /* 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 * |
| 2344 | * function, as the structures aren't created yet. */ | 2339 | * function, as the structures aren't created yet. */ |
| 2345 | 2340 | ||
| 2346 | /* set up port private structures */ | 2341 | pnum = port->number - serial->minor; |
| 2347 | for (i = 0; i < serial->num_ports; ++i) { | 2342 | |
| 2348 | dev_dbg(&dev->dev, "mos7840_startup: configuring port %d............\n", i); | 2343 | /* FIXME: remove do-while(0) loop used to keep stable patch minimal. |
| 2344 | */ | ||
| 2345 | do { | ||
| 2346 | dev_dbg(&port->dev, "mos7840_startup: configuring port %d............\n", pnum); | ||
| 2349 | mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); | 2347 | mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); |
| 2350 | if (mos7840_port == NULL) { | 2348 | if (mos7840_port == NULL) { |
| 2351 | dev_err(&dev->dev, "%s - Out of memory\n", __func__); | 2349 | dev_err(&port->dev, "%s - Out of memory\n", __func__); |
| 2352 | status = -ENOMEM; | 2350 | return -ENOMEM; |
| 2353 | i--; /* don't follow NULL pointer cleaning up */ | ||
| 2354 | goto error; | ||
| 2355 | } | 2351 | } |
| 2356 | 2352 | ||
| 2357 | /* Initialize all port interrupt end point to port 0 int | 2353 | /* Initialize all port interrupt end point to port 0 int |
| 2358 | * endpoint. Our device has only one interrupt end point | 2354 | * endpoint. Our device has only one interrupt end point |
| 2359 | * common to all port */ | 2355 | * common to all port */ |
| 2360 | 2356 | ||
| 2361 | mos7840_port->port = serial->port[i]; | 2357 | mos7840_port->port = port; |
| 2362 | mos7840_set_port_private(serial->port[i], mos7840_port); | 2358 | mos7840_set_port_private(port, mos7840_port); |
| 2363 | spin_lock_init(&mos7840_port->pool_lock); | 2359 | spin_lock_init(&mos7840_port->pool_lock); |
| 2364 | 2360 | ||
| 2365 | /* minor is not initialised until later by | 2361 | /* minor is not initialised until later by |
| 2366 | * usb-serial.c:get_free_serial() and cannot therefore be used | 2362 | * usb-serial.c:get_free_serial() and cannot therefore be used |
| 2367 | * to index device instances */ | 2363 | * to index device instances */ |
| 2368 | mos7840_port->port_num = i + 1; | 2364 | mos7840_port->port_num = pnum + 1; |
| 2369 | dev_dbg(&dev->dev, "serial->port[i]->number = %d\n", serial->port[i]->number); | 2365 | dev_dbg(&port->dev, "port->number = %d\n", port->number); |
| 2370 | dev_dbg(&dev->dev, "serial->port[i]->serial->minor = %d\n", serial->port[i]->serial->minor); | 2366 | dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor); |
| 2371 | dev_dbg(&dev->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); | 2367 | dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); |
| 2372 | dev_dbg(&dev->dev, "serial->minor = %d\n", serial->minor); | 2368 | dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor); |
| 2373 | 2369 | ||
| 2374 | if (mos7840_port->port_num == 1) { | 2370 | if (mos7840_port->port_num == 1) { |
| 2375 | mos7840_port->SpRegOffset = 0x0; | 2371 | mos7840_port->SpRegOffset = 0x0; |
| @@ -2396,115 +2392,115 @@ static int mos7840_startup(struct usb_serial *serial) | |||
| 2396 | mos7840_port->ControlRegOffset = 0xd; | 2392 | mos7840_port->ControlRegOffset = 0xd; |
| 2397 | mos7840_port->DcrRegOffset = 0x1c; | 2393 | mos7840_port->DcrRegOffset = 0x1c; |
| 2398 | } | 2394 | } |
| 2399 | mos7840_dump_serial_port(serial->port[i], mos7840_port); | 2395 | mos7840_dump_serial_port(port, mos7840_port); |
| 2400 | mos7840_set_port_private(serial->port[i], mos7840_port); | 2396 | mos7840_set_port_private(port, mos7840_port); |
| 2401 | 2397 | ||
| 2402 | /* enable rx_disable bit in control register */ | 2398 | /* enable rx_disable bit in control register */ |
| 2403 | status = mos7840_get_reg_sync(serial->port[i], | 2399 | status = mos7840_get_reg_sync(port, |
| 2404 | mos7840_port->ControlRegOffset, &Data); | 2400 | mos7840_port->ControlRegOffset, &Data); |
| 2405 | if (status < 0) { | 2401 | if (status < 0) { |
| 2406 | dev_dbg(&dev->dev, "Reading ControlReg failed status-0x%x\n", status); | 2402 | dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status); |
| 2407 | break; | 2403 | break; |
| 2408 | } else | 2404 | } else |
| 2409 | dev_dbg(&dev->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); | 2405 | dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); |
| 2410 | Data |= 0x08; /* setting driver done bit */ | 2406 | Data |= 0x08; /* setting driver done bit */ |
| 2411 | Data |= 0x04; /* sp1_bit to have cts change reflect in | 2407 | Data |= 0x04; /* sp1_bit to have cts change reflect in |
| 2412 | modem status reg */ | 2408 | modem status reg */ |
| 2413 | 2409 | ||
| 2414 | /* Data |= 0x20; //rx_disable bit */ | 2410 | /* Data |= 0x20; //rx_disable bit */ |
| 2415 | status = mos7840_set_reg_sync(serial->port[i], | 2411 | status = mos7840_set_reg_sync(port, |
| 2416 | mos7840_port->ControlRegOffset, Data); | 2412 | mos7840_port->ControlRegOffset, Data); |
| 2417 | if (status < 0) { | 2413 | if (status < 0) { |
| 2418 | dev_dbg(&dev->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); | 2414 | dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); |
| 2419 | break; | 2415 | break; |
| 2420 | } else | 2416 | } else |
| 2421 | dev_dbg(&dev->dev, "ControlReg Writing success(rx_disable) status%d\n", status); | 2417 | dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status); |
| 2422 | 2418 | ||
| 2423 | /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 | 2419 | /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 |
| 2424 | and 0x24 in DCR3 */ | 2420 | and 0x24 in DCR3 */ |
| 2425 | Data = 0x01; | 2421 | Data = 0x01; |
| 2426 | status = mos7840_set_reg_sync(serial->port[i], | 2422 | status = mos7840_set_reg_sync(port, |
| 2427 | (__u16) (mos7840_port->DcrRegOffset + 0), Data); | 2423 | (__u16) (mos7840_port->DcrRegOffset + 0), Data); |
| 2428 | if (status < 0) { | 2424 | if (status < 0) { |
| 2429 | dev_dbg(&dev->dev, "Writing DCR0 failed status-0x%x\n", status); | 2425 | dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status); |
| 2430 | break; | 2426 | break; |
| 2431 | } else | 2427 | } else |
| 2432 | dev_dbg(&dev->dev, "DCR0 Writing success status%d\n", status); | 2428 | dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status); |
| 2433 | 2429 | ||
| 2434 | Data = 0x05; | 2430 | Data = 0x05; |
| 2435 | status = mos7840_set_reg_sync(serial->port[i], | 2431 | status = mos7840_set_reg_sync(port, |
| 2436 | (__u16) (mos7840_port->DcrRegOffset + 1), Data); | 2432 | (__u16) (mos7840_port->DcrRegOffset + 1), Data); |
| 2437 | if (status < 0) { | 2433 | if (status < 0) { |
| 2438 | dev_dbg(&dev->dev, "Writing DCR1 failed status-0x%x\n", status); | 2434 | dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status); |
| 2439 | break; | 2435 | break; |
| 2440 | } else | 2436 | } else |
| 2441 | dev_dbg(&dev->dev, "DCR1 Writing success status%d\n", status); | 2437 | dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status); |
| 2442 | 2438 | ||
| 2443 | Data = 0x24; | 2439 | Data = 0x24; |
| 2444 | status = mos7840_set_reg_sync(serial->port[i], | 2440 | status = mos7840_set_reg_sync(port, |
| 2445 | (__u16) (mos7840_port->DcrRegOffset + 2), Data); | 2441 | (__u16) (mos7840_port->DcrRegOffset + 2), Data); |
| 2446 | if (status < 0) { | 2442 | if (status < 0) { |
| 2447 | dev_dbg(&dev->dev, "Writing DCR2 failed status-0x%x\n", status); | 2443 | dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status); |
| 2448 | break; | 2444 | break; |
| 2449 | } else | 2445 | } else |
| 2450 | dev_dbg(&dev->dev, "DCR2 Writing success status%d\n", status); | 2446 | dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status); |
| 2451 | 2447 | ||
| 2452 | /* write values in clkstart0x0 and clkmulti 0x20 */ | 2448 | /* write values in clkstart0x0 and clkmulti 0x20 */ |
| 2453 | Data = 0x0; | 2449 | Data = 0x0; |
| 2454 | status = mos7840_set_reg_sync(serial->port[i], | 2450 | status = mos7840_set_reg_sync(port, |
| 2455 | CLK_START_VALUE_REGISTER, Data); | 2451 | CLK_START_VALUE_REGISTER, Data); |
| 2456 | if (status < 0) { | 2452 | if (status < 0) { |
| 2457 | dev_dbg(&dev->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); | 2453 | dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); |
| 2458 | break; | 2454 | break; |
| 2459 | } else | 2455 | } else |
| 2460 | dev_dbg(&dev->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); | 2456 | dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); |
| 2461 | 2457 | ||
| 2462 | Data = 0x20; | 2458 | Data = 0x20; |
| 2463 | status = mos7840_set_reg_sync(serial->port[i], | 2459 | status = mos7840_set_reg_sync(port, |
| 2464 | CLK_MULTI_REGISTER, Data); | 2460 | CLK_MULTI_REGISTER, Data); |
| 2465 | if (status < 0) { | 2461 | if (status < 0) { |
| 2466 | dev_dbg(&dev->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); | 2462 | dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); |
| 2467 | goto error; | 2463 | goto error; |
| 2468 | } else | 2464 | } else |
| 2469 | dev_dbg(&dev->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); | 2465 | dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); |
| 2470 | 2466 | ||
| 2471 | /* write value 0x0 to scratchpad register */ | 2467 | /* write value 0x0 to scratchpad register */ |
| 2472 | Data = 0x00; | 2468 | Data = 0x00; |
| 2473 | status = mos7840_set_uart_reg(serial->port[i], | 2469 | status = mos7840_set_uart_reg(port, |
| 2474 | SCRATCH_PAD_REGISTER, Data); | 2470 | SCRATCH_PAD_REGISTER, Data); |
| 2475 | if (status < 0) { | 2471 | if (status < 0) { |
| 2476 | dev_dbg(&dev->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); | 2472 | dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); |
| 2477 | break; | 2473 | break; |
| 2478 | } else | 2474 | } else |
| 2479 | dev_dbg(&dev->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); | 2475 | dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); |
| 2480 | 2476 | ||
| 2481 | /* Zero Length flag register */ | 2477 | /* Zero Length flag register */ |
| 2482 | if ((mos7840_port->port_num != 1) | 2478 | if ((mos7840_port->port_num != 1) |
| 2483 | && (serial->num_ports == 2)) { | 2479 | && (serial->num_ports == 2)) { |
| 2484 | 2480 | ||
| 2485 | Data = 0xff; | 2481 | Data = 0xff; |
| 2486 | status = mos7840_set_reg_sync(serial->port[i], | 2482 | status = mos7840_set_reg_sync(port, |
| 2487 | (__u16) (ZLP_REG1 + | 2483 | (__u16) (ZLP_REG1 + |
| 2488 | ((__u16)mos7840_port->port_num)), Data); | 2484 | ((__u16)mos7840_port->port_num)), Data); |
| 2489 | dev_dbg(&dev->dev, "ZLIP offset %x\n", | 2485 | dev_dbg(&port->dev, "ZLIP offset %x\n", |
| 2490 | (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num))); | 2486 | (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num))); |
| 2491 | if (status < 0) { | 2487 | if (status < 0) { |
| 2492 | dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 2, status); | 2488 | dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status); |
| 2493 | break; | 2489 | break; |
| 2494 | } else | 2490 | } else |
| 2495 | dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 2, status); | 2491 | dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status); |
| 2496 | } else { | 2492 | } else { |
| 2497 | Data = 0xff; | 2493 | Data = 0xff; |
| 2498 | status = mos7840_set_reg_sync(serial->port[i], | 2494 | status = mos7840_set_reg_sync(port, |
| 2499 | (__u16) (ZLP_REG1 + | 2495 | (__u16) (ZLP_REG1 + |
| 2500 | ((__u16)mos7840_port->port_num) - 0x1), Data); | 2496 | ((__u16)mos7840_port->port_num) - 0x1), Data); |
| 2501 | dev_dbg(&dev->dev, "ZLIP offset %x\n", | 2497 | dev_dbg(&port->dev, "ZLIP offset %x\n", |
| 2502 | (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1)); | 2498 | (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1)); |
| 2503 | if (status < 0) { | 2499 | if (status < 0) { |
| 2504 | dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 1, status); | 2500 | dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status); |
| 2505 | break; | 2501 | break; |
| 2506 | } else | 2502 | } else |
| 2507 | dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 1, status); | 2503 | dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status); |
| 2508 | 2504 | ||
| 2509 | } | 2505 | } |
| 2510 | mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); | 2506 | mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); |
| @@ -2541,92 +2537,56 @@ static int mos7840_startup(struct usb_serial *serial) | |||
| 2541 | mos7840_port->led_flag = false; | 2537 | mos7840_port->led_flag = false; |
| 2542 | 2538 | ||
| 2543 | /* Turn off LED */ | 2539 | /* Turn off LED */ |
| 2544 | mos7840_set_led_sync(serial->port[i], | 2540 | mos7840_set_led_sync(port, |
| 2545 | MODEM_CONTROL_REGISTER, 0x0300); | 2541 | MODEM_CONTROL_REGISTER, 0x0300); |
| 2546 | } | 2542 | } |
| 2547 | } | 2543 | } while (0); |
| 2548 | 2544 | ||
| 2549 | /* Zero Length flag enable */ | 2545 | if (pnum == serial->num_ports - 1) { |
| 2550 | Data = 0x0f; | 2546 | /* Zero Length flag enable */ |
| 2551 | status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); | 2547 | Data = 0x0f; |
| 2552 | if (status < 0) { | 2548 | status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); |
| 2553 | dev_dbg(&dev->dev, "Writing ZLP_REG5 failed status-0x%x\n", status); | 2549 | if (status < 0) { |
| 2554 | goto error; | 2550 | dev_dbg(&port->dev, "Writing ZLP_REG5 failed status-0x%x\n", status); |
| 2555 | } else | 2551 | goto error; |
| 2556 | dev_dbg(&dev->dev, "ZLP_REG5 Writing success status%d\n", status); | 2552 | } else |
| 2557 | 2553 | dev_dbg(&port->dev, "ZLP_REG5 Writing success status%d\n", status); | |
| 2558 | /* setting configuration feature to one */ | 2554 | |
| 2559 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | 2555 | /* setting configuration feature to one */ |
| 2560 | (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT); | 2556 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
| 2557 | 0x03, 0x00, 0x01, 0x00, NULL, 0x00, | ||
| 2558 | MOS_WDR_TIMEOUT); | ||
| 2559 | } | ||
| 2561 | return 0; | 2560 | return 0; |
| 2562 | error: | 2561 | error: |
| 2563 | for (/* nothing */; i >= 0; i--) { | 2562 | kfree(mos7840_port->dr); |
| 2564 | mos7840_port = mos7840_get_port_private(serial->port[i]); | 2563 | kfree(mos7840_port->ctrl_buf); |
| 2564 | usb_free_urb(mos7840_port->control_urb); | ||
| 2565 | kfree(mos7840_port); | ||
| 2565 | 2566 | ||
| 2566 | kfree(mos7840_port->dr); | ||
| 2567 | kfree(mos7840_port->ctrl_buf); | ||
| 2568 | usb_free_urb(mos7840_port->control_urb); | ||
| 2569 | kfree(mos7840_port); | ||
| 2570 | } | ||
| 2571 | return status; | 2567 | return status; |
| 2572 | } | 2568 | } |
| 2573 | 2569 | ||
| 2574 | /**************************************************************************** | 2570 | static int mos7840_port_remove(struct usb_serial_port *port) |
| 2575 | * mos7840_disconnect | ||
| 2576 | * This function is called whenever the device is removed from the usb bus. | ||
| 2577 | ****************************************************************************/ | ||
| 2578 | |||
| 2579 | static void mos7840_disconnect(struct usb_serial *serial) | ||
| 2580 | { | 2571 | { |
| 2581 | int i; | ||
| 2582 | unsigned long flags; | ||
| 2583 | struct moschip_port *mos7840_port; | 2572 | struct moschip_port *mos7840_port; |
| 2584 | 2573 | ||
| 2585 | /* check for the ports to be closed,close the ports and disconnect */ | 2574 | mos7840_port = mos7840_get_port_private(port); |
| 2586 | 2575 | ||
| 2587 | /* free private structure allocated for serial port * | 2576 | if (mos7840_port->has_led) { |
| 2588 | * stop reads and writes on all ports */ | 2577 | /* Turn off LED */ |
| 2578 | mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); | ||
| 2589 | 2579 | ||
| 2590 | for (i = 0; i < serial->num_ports; ++i) { | 2580 | del_timer_sync(&mos7840_port->led_timer1); |
| 2591 | mos7840_port = mos7840_get_port_private(serial->port[i]); | 2581 | del_timer_sync(&mos7840_port->led_timer2); |
| 2592 | if (mos7840_port) { | ||
| 2593 | usb_kill_urb(mos7840_port->control_urb); | ||
| 2594 | } | ||
| 2595 | } | 2582 | } |
| 2596 | } | 2583 | usb_kill_urb(mos7840_port->control_urb); |
| 2597 | 2584 | usb_free_urb(mos7840_port->control_urb); | |
| 2598 | /**************************************************************************** | 2585 | kfree(mos7840_port->ctrl_buf); |
| 2599 | * mos7840_release | 2586 | kfree(mos7840_port->dr); |
| 2600 | * This function is called when the usb_serial structure is freed. | 2587 | kfree(mos7840_port); |
| 2601 | ****************************************************************************/ | ||
| 2602 | |||
| 2603 | static void mos7840_release(struct usb_serial *serial) | ||
| 2604 | { | ||
| 2605 | int i; | ||
| 2606 | struct moschip_port *mos7840_port; | ||
| 2607 | 2588 | ||
| 2608 | /* check for the ports to be closed,close the ports and disconnect */ | 2589 | return 0; |
| 2609 | |||
| 2610 | /* free private structure allocated for serial port * | ||
| 2611 | * stop reads and writes on all ports */ | ||
| 2612 | |||
| 2613 | for (i = 0; i < serial->num_ports; ++i) { | ||
| 2614 | mos7840_port = mos7840_get_port_private(serial->port[i]); | ||
| 2615 | if (mos7840_port) { | ||
| 2616 | if (mos7840_port->has_led) { | ||
| 2617 | /* Turn off LED */ | ||
| 2618 | mos7840_set_led_sync(mos7840_port->port, | ||
| 2619 | MODEM_CONTROL_REGISTER, 0x0300); | ||
| 2620 | |||
| 2621 | del_timer_sync(&mos7840_port->led_timer1); | ||
| 2622 | del_timer_sync(&mos7840_port->led_timer2); | ||
| 2623 | } | ||
| 2624 | usb_free_urb(mos7840_port->control_urb); | ||
| 2625 | kfree(mos7840_port->ctrl_buf); | ||
| 2626 | kfree(mos7840_port->dr); | ||
| 2627 | kfree(mos7840_port); | ||
| 2628 | } | ||
| 2629 | } | ||
| 2630 | } | 2590 | } |
| 2631 | 2591 | ||
| 2632 | static struct usb_serial_driver moschip7840_4port_device = { | 2592 | static struct usb_serial_driver moschip7840_4port_device = { |
| @@ -2654,9 +2614,8 @@ static struct usb_serial_driver moschip7840_4port_device = { | |||
| 2654 | .tiocmget = mos7840_tiocmget, | 2614 | .tiocmget = mos7840_tiocmget, |
| 2655 | .tiocmset = mos7840_tiocmset, | 2615 | .tiocmset = mos7840_tiocmset, |
| 2656 | .get_icount = mos7840_get_icount, | 2616 | .get_icount = mos7840_get_icount, |
| 2657 | .attach = mos7840_startup, | 2617 | .port_probe = mos7840_port_probe, |
| 2658 | .disconnect = mos7840_disconnect, | 2618 | .port_remove = mos7840_port_remove, |
| 2659 | .release = mos7840_release, | ||
| 2660 | .read_bulk_callback = mos7840_bulk_in_callback, | 2619 | .read_bulk_callback = mos7840_bulk_in_callback, |
| 2661 | .read_int_callback = mos7840_interrupt_callback, | 2620 | .read_int_callback = mos7840_interrupt_callback, |
| 2662 | }; | 2621 | }; |
