summaryrefslogtreecommitdiff
path: root/drivers/usb/class/cdc-acm.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2013-04-30 09:00:33 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-04-30 09:00:33 -0300
commitaad797c89903d570c17f6affc770eb98afd74e62 (patch)
treebddefd4242b0efba1068b5260f831c2697ba4037 /drivers/usb/class/cdc-acm.c
parentc95789ecd5a979fd718ae09763df3fa50dd97a91 (diff)
parentc1be5a5b1b355d40e6cf79cc979eb66dafa24ad1 (diff)
Merge tag 'v3.9' into v4l_for_linus
Linux 3.9 * tag 'v3.9': (1099 commits) Linux 3.9 vm: add no-mmu vm_iomap_memory() stub efivars: only check for duplicates on the registered list TTY: fix atime/mtime regression aio: fix possible invalid memory access when DEBUG is enabled parisc: use spin_lock_irqsave/spin_unlock_irqrestore for PTE updates parisc: disable -mlong-calls compiler option for kernel modules parisc: uaccess: fix compiler warnings caused by __put_user casting parisc: Change kunmap macro to static inline function parisc: Provide __ucmpdi2 to resolve undefined references in 32 bit builds. sparc64: Fix missing put_cpu_var() in tlb_batch_add_one() when not batching. Revert "gpio: pxa: set initcall level to module init" efi: Check EFI revision in setup_efi_vars x86, efi: Fix a build warning Revert "MIPS: page.h: Provide more readable definition for PAGE_MASK." kernel/hz.bc: ignore. Linux 3.9-rc8 events: Protect access via task_subsys_state_check() net: fix incorrect credentials passing x86, microcode: Verify the family before dispatching microcode patching ...
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
-rw-r--r--drivers/usb/class/cdc-acm.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 8ac25adf31b4..387dc6c8ad25 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -593,7 +593,6 @@ static void acm_port_destruct(struct tty_port *port)
dev_dbg(&acm->control->dev, "%s\n", __func__);
- tty_unregister_device(acm_tty_driver, acm->minor);
acm_release_minor(acm);
usb_put_intf(acm->control);
kfree(acm->country_codes);
@@ -977,6 +976,8 @@ static int acm_probe(struct usb_interface *intf,
int num_rx_buf;
int i;
int combined_interfaces = 0;
+ struct device *tty_dev;
+ int rv = -ENOMEM;
/* normal quirks */
quirks = (unsigned long)id->driver_info;
@@ -1339,11 +1340,24 @@ skip_countries:
usb_set_intfdata(data_interface, acm);
usb_get_intf(control_interface);
- tty_port_register_device(&acm->port, acm_tty_driver, minor,
+ tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor,
&control_interface->dev);
+ if (IS_ERR(tty_dev)) {
+ rv = PTR_ERR(tty_dev);
+ goto alloc_fail8;
+ }
return 0;
+alloc_fail8:
+ if (acm->country_codes) {
+ device_remove_file(&acm->control->dev,
+ &dev_attr_wCountryCodes);
+ device_remove_file(&acm->control->dev,
+ &dev_attr_iCountryCodeRelDate);
+ }
+ device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities);
alloc_fail7:
+ usb_set_intfdata(intf, NULL);
for (i = 0; i < ACM_NW; i++)
usb_free_urb(acm->wb[i].urb);
alloc_fail6:
@@ -1359,7 +1373,7 @@ alloc_fail2:
acm_release_minor(acm);
kfree(acm);
alloc_fail:
- return -ENOMEM;
+ return rv;
}
static void stop_data_traffic(struct acm *acm)
@@ -1411,6 +1425,8 @@ static void acm_disconnect(struct usb_interface *intf)
stop_data_traffic(acm);
+ tty_unregister_device(acm_tty_driver, acm->minor);
+
usb_free_urb(acm->ctrlurb);
for (i = 0; i < ACM_NW; i++)
usb_free_urb(acm->wb[i].urb);