return 0;
 }
 
-
-/* Determine type of FTDI chip based on USB config and descriptor. */
-static void ftdi_determine_type(struct usb_serial_port *port)
+static int ftdi_determine_type(struct usb_serial_port *port)
 {
        struct ftdi_private *priv = usb_get_serial_port_data(port);
        struct usb_serial *serial = port->serial;
        struct usb_device *udev = serial->dev;
-       unsigned version;
-       unsigned interfaces;
+       unsigned int version, ifnum;
+
+       version = le16_to_cpu(udev->descriptor.bcdDevice);
+       ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
 
-       /* Assume it is not the original SIO device for now. */
        priv->baud_base = 48000000 / 2;
+       priv->channel = 0;
 
-       version = le16_to_cpu(udev->descriptor.bcdDevice);
-       interfaces = udev->actconfig->desc.bNumInterfaces;
-       dev_dbg(&port->dev, "%s: bcdDevice = 0x%x, bNumInterfaces = %u\n", __func__,
-               version, interfaces);
-       if (interfaces > 1) {
-               struct usb_interface *intf = serial->interface;
-               int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
-
-               /* Multiple interfaces.*/
-               if (version == 0x0800) {
-                       priv->chip_type = FT4232H;
-                       /* Hi-speed - baud clock runs at 120MHz */
-                       priv->baud_base = 120000000 / 2;
-               } else if (version == 0x0700) {
-                       priv->chip_type = FT2232H;
-                       /* Hi-speed - baud clock runs at 120MHz */
-                       priv->baud_base = 120000000 / 2;
-               } else
-                       priv->chip_type = FT2232C;
-
-               if (ifnum == 0)
-                       priv->channel = CHANNEL_A;
-               else if (ifnum == 1)
-                       priv->channel = CHANNEL_B;
-               else if (ifnum == 2)
-                       priv->channel = CHANNEL_C;
-               else if (ifnum == 3)
-                       priv->channel = CHANNEL_D;
-
-               /* BM-type devices have a bug where bcdDevice gets set
-                * to 0x200 when iSerialNumber is 0.  */
-               if (version < 0x500) {
-                       dev_dbg(&port->dev,
-                               "%s: something fishy - bcdDevice too low for multi-interface device\n",
-                               __func__);
-               }
-       } else if (version < 0x200) {
-               /* Old device.  Assume it's the original SIO. */
-               priv->chip_type = SIO;
-               priv->baud_base = 12000000 / 16;
-       } else if (version < 0x400) {
-               /* Assume it's an FT8U232AM (or FT8U245AM) */
+       switch (version) {
+       case 0x200:
                priv->chip_type = FT232A;
+
                /*
-                * It might be a BM type because of the iSerialNumber bug.
-                * If iSerialNumber==0 and the latency timer is readable,
-                * assume it is BM type.
+                * FT232B devices have a bug where bcdDevice gets set to 0x200
+                * when iSerialNumber is 0. Assume it is an FT232B in case the
+                * latency timer is readable.
                 */
                if (udev->descriptor.iSerialNumber == 0 &&
                                _read_latency_timer(port) >= 0) {
-                       dev_dbg(&port->dev,
-                               "%s: has latency timer so not an AM type\n",
-                               __func__);
                        priv->chip_type = FT232B;
                }
-       } else if (version < 0x600) {
-               /* Assume it's an FT232BM (or FT245BM) */
+               break;
+       case 0x400:
                priv->chip_type = FT232B;
-       } else if (version < 0x900) {
-               /* Assume it's an FT232RL */
+               break;
+       case 0x500:
+               priv->chip_type = FT2232C;
+               priv->channel = CHANNEL_A + ifnum;
+               break;
+       case 0x600:
                priv->chip_type = FT232R;
-       } else if (version < 0x1000) {
-               /* Assume it's an FT232H */
+               break;
+       case 0x700:
+               priv->chip_type = FT2232H;
+               priv->channel = CHANNEL_A + ifnum;
+               priv->baud_base = 120000000 / 2;
+               break;
+       case 0x800:
+               priv->chip_type = FT4232H;
+               priv->channel = CHANNEL_A + ifnum;
+               priv->baud_base = 120000000 / 2;
+               break;
+       case 0x900:
                priv->chip_type = FT232H;
-       } else {
-               /* Assume it's an FT-X series device */
+               priv->baud_base = 120000000 / 2;
+               break;
+       case 0x1000:
                priv->chip_type = FTX;
+               break;
+       default:
+               if (version < 0x200) {
+                       priv->chip_type = SIO;
+                       priv->baud_base = 12000000 / 16;
+               } else {
+                       dev_err(&port->dev, "unknown device type: 0x%02x\n", version);
+                       return -ENODEV;
+               }
        }
 
        dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]);
+
+       return 0;
 }
 
 
 
        usb_set_serial_port_data(port, priv);
 
-       ftdi_determine_type(port);
+       result = ftdi_determine_type(port);
+       if (result)
+               goto err_free;
+
        ftdi_set_max_packet_size(port);
        if (read_latency_timer(port) < 0)
                priv->latency = 16;
        }
 
        return 0;
+
+err_free:
+       kfree(priv);
+
+       return result;
 }
 
 /* Setup for the USB-UIRT device, which requires hardwired