Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: cdc-acm: Decrement tty port's refcount if probe() fail

The cdc-acm driver does not have a refcount of itself, but uses a
tty_port's refcount. That is, if the refcount of tty_port is '0', we
can clean up the cdc-acm driver by calling the .destruct()
callback function of struct tty_port_operations.

The problem is the destruct() callback function is not called if
the probe() fails, because tty_port's refcount is not zero. So,
add tty_port_put() when probe() fails.

Signed-off-by: Jaejoong Kim <climbbb.kim@gmail.com>
Acked-by: Oliver Neukum <oneukum@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Jaejoong Kim and committed by
Greg Kroah-Hartman
cae2bc76 61ef4b90

+17 -18
+17 -18
drivers/usb/class/cdc-acm.c
··· 1378 1378 if (acm == NULL) 1379 1379 goto alloc_fail; 1380 1380 1381 + tty_port_init(&acm->port); 1382 + acm->port.ops = &acm_port_ops; 1383 + 1381 1384 minor = acm_alloc_minor(acm); 1382 1385 if (minor < 0) 1383 1386 goto alloc_fail1; ··· 1416 1413 acm->out = usb_sndintpipe(usb_dev, epwrite->bEndpointAddress); 1417 1414 else 1418 1415 acm->out = usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress); 1419 - tty_port_init(&acm->port); 1420 - acm->port.ops = &acm_port_ops; 1421 1416 init_usb_anchor(&acm->delayed); 1422 1417 acm->quirks = quirks; 1423 1418 1424 1419 buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); 1425 1420 if (!buf) 1426 - goto alloc_fail2; 1421 + goto alloc_fail1; 1427 1422 acm->ctrl_buffer = buf; 1428 1423 1429 1424 if (acm_write_buffers_alloc(acm) < 0) 1430 - goto alloc_fail4; 1425 + goto alloc_fail2; 1431 1426 1432 1427 acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL); 1433 1428 if (!acm->ctrlurb) 1434 - goto alloc_fail5; 1429 + goto alloc_fail3; 1435 1430 1436 1431 for (i = 0; i < num_rx_buf; i++) { 1437 1432 struct acm_rb *rb = &(acm->read_buffers[i]); ··· 1438 1437 rb->base = usb_alloc_coherent(acm->dev, readsize, GFP_KERNEL, 1439 1438 &rb->dma); 1440 1439 if (!rb->base) 1441 - goto alloc_fail6; 1440 + goto alloc_fail4; 1442 1441 rb->index = i; 1443 1442 rb->instance = acm; 1444 1443 1445 1444 urb = usb_alloc_urb(0, GFP_KERNEL); 1446 1445 if (!urb) 1447 - goto alloc_fail6; 1446 + goto alloc_fail4; 1448 1447 1449 1448 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 1450 1449 urb->transfer_dma = rb->dma; ··· 1466 1465 1467 1466 snd->urb = usb_alloc_urb(0, GFP_KERNEL); 1468 1467 if (snd->urb == NULL) 1469 - goto alloc_fail7; 1468 + goto alloc_fail5; 1470 1469 1471 1470 if (usb_endpoint_xfer_int(epwrite)) 1472 1471 usb_fill_int_urb(snd->urb, usb_dev, acm->out, ··· 1484 1483 1485 1484 i = device_create_file(&intf->dev, &dev_attr_bmCapabilities); 1486 1485 if (i < 0) 1487 - goto alloc_fail7; 1486 + goto alloc_fail5; 1488 1487 1489 1488 if (h.usb_cdc_country_functional_desc) { /* export the country data */ 1490 1489 struct usb_cdc_country_functional_desc * cfd = ··· 1543 1542 &control_interface->dev); 1544 1543 if (IS_ERR(tty_dev)) { 1545 1544 rv = PTR_ERR(tty_dev); 1546 - goto alloc_fail8; 1545 + goto alloc_fail6; 1547 1546 } 1548 1547 1549 1548 if (quirks & CLEAR_HALT_CONDITIONS) { ··· 1552 1551 } 1553 1552 1554 1553 return 0; 1555 - alloc_fail8: 1554 + alloc_fail6: 1556 1555 if (acm->country_codes) { 1557 1556 device_remove_file(&acm->control->dev, 1558 1557 &dev_attr_wCountryCodes); ··· 1561 1560 kfree(acm->country_codes); 1562 1561 } 1563 1562 device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); 1564 - alloc_fail7: 1563 + alloc_fail5: 1565 1564 usb_set_intfdata(intf, NULL); 1566 1565 for (i = 0; i < ACM_NW; i++) 1567 1566 usb_free_urb(acm->wb[i].urb); 1568 - alloc_fail6: 1567 + alloc_fail4: 1569 1568 for (i = 0; i < num_rx_buf; i++) 1570 1569 usb_free_urb(acm->read_urbs[i]); 1571 1570 acm_read_buffers_free(acm); 1572 1571 usb_free_urb(acm->ctrlurb); 1573 - alloc_fail5: 1572 + alloc_fail3: 1574 1573 acm_write_buffers_free(acm); 1575 - alloc_fail4: 1576 - usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); 1577 1574 alloc_fail2: 1578 - acm_release_minor(acm); 1575 + usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); 1579 1576 alloc_fail1: 1580 - kfree(acm); 1577 + tty_port_put(&acm->port); 1581 1578 alloc_fail: 1582 1579 return rv; 1583 1580 }