Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / usb / class / cdc-acm.c
index cb8ef3ef5c94012de4bb1ebb0b5cb595df97e99d..9b1cbcf8fb7fcfbd0f3b576d207a90dd4421c62f 100644 (file)
@@ -292,7 +292,6 @@ static void acm_ctrl_irq(struct urb *urb)
 {
        struct acm *acm = urb->context;
        struct usb_cdc_notification *dr = urb->transfer_buffer;
-       struct tty_struct *tty;
        unsigned char *data;
        int newctrl;
        int retval;
@@ -327,17 +326,12 @@ static void acm_ctrl_irq(struct urb *urb)
                break;
 
        case USB_CDC_NOTIFY_SERIAL_STATE:
-               tty = tty_port_tty_get(&acm->port);
                newctrl = get_unaligned_le16(data);
 
-               if (tty) {
-                       if (!acm->clocal &&
-                               (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
-                               dev_dbg(&acm->control->dev,
-                                       "%s - calling hangup\n", __func__);
-                               tty_hangup(tty);
-                       }
-                       tty_kref_put(tty);
+               if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
+                       dev_dbg(&acm->control->dev, "%s - calling hangup\n",
+                                       __func__);
+                       tty_port_tty_hangup(&acm->port, false);
                }
 
                acm->ctrlin = newctrl;
@@ -475,15 +469,10 @@ static void acm_write_bulk(struct urb *urb)
 static void acm_softint(struct work_struct *work)
 {
        struct acm *acm = container_of(work, struct acm, work);
-       struct tty_struct *tty;
 
        dev_vdbg(&acm->data->dev, "%s\n", __func__);
 
-       tty = tty_port_tty_get(&acm->port);
-       if (!tty)
-               return;
-       tty_wakeup(tty);
-       tty_kref_put(tty);
+       tty_port_tty_wakeup(&acm->port);
 }
 
 /*
@@ -593,7 +582,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);
@@ -840,14 +828,6 @@ static int acm_tty_ioctl(struct tty_struct *tty,
        return rv;
 }
 
-static const __u32 acm_tty_speed[] = {
-       0, 50, 75, 110, 134, 150, 200, 300, 600,
-       1200, 1800, 2400, 4800, 9600, 19200, 38400,
-       57600, 115200, 230400, 460800, 500000, 576000,
-       921600, 1000000, 1152000, 1500000, 2000000,
-       2500000, 3000000, 3500000, 4000000
-};
-
 static void acm_tty_set_termios(struct tty_struct *tty,
                                                struct ktermios *termios_old)
 {
@@ -977,6 +957,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;
@@ -1343,11 +1325,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:
@@ -1363,7 +1358,7 @@ alloc_fail2:
        acm_release_minor(acm);
        kfree(acm);
 alloc_fail:
-       return -ENOMEM;
+       return rv;
 }
 
 static void stop_data_traffic(struct acm *acm)
@@ -1415,6 +1410,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);
@@ -1507,15 +1504,9 @@ err_out:
 static int acm_reset_resume(struct usb_interface *intf)
 {
        struct acm *acm = usb_get_intfdata(intf);
-       struct tty_struct *tty;
 
-       if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) {
-               tty = tty_port_tty_get(&acm->port);
-               if (tty) {
-                       tty_hangup(tty);
-                       tty_kref_put(tty);
-               }
-       }
+       if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags))
+               tty_port_tty_hangup(&acm->port, false);
 
        return acm_resume(intf);
 }