return rv;
  }
  
- /* Gobi devices uses identical class/protocol codes for all interfaces regardless
-  * of function. Some of these are CDC ACM like and have the exact same endpoints
-  * we are looking for. This leaves two possible strategies for identifying the
-  * correct interface:
-  *   a) hardcoding interface number, or
-  *   b) use the fact that the wwan interface is the only one lacking additional
-  *      (CDC functional) descriptors
-  *
-  * Let's see if we can get away with the generic b) solution.
-  */
- static int qmi_wwan_bind_gobi(struct usbnet *dev, struct usb_interface *intf)
- {
-       int rv = -EINVAL;
- 
-       /* ignore any interface with additional descriptors */
-       if (intf->cur_altsetting->extralen)
-               goto err;
- 
-       rv = qmi_wwan_bind_shared(dev, intf);
- err:
-       return rv;
- }
- 
 -static void qmi_wwan_unbind_shared(struct usbnet *dev, struct usb_interface *intf)
 +static void qmi_wwan_unbind(struct usbnet *dev, struct usb_interface *intf)
  {
 -      struct usb_driver *subdriver = (void *)dev->data[0];
 -
 -      if (subdriver && subdriver->disconnect)
 -              subdriver->disconnect(intf);
 +      struct qmi_wwan_state *info = (void *)&dev->data;
 +      struct usb_driver *driver = driver_of(intf);
 +      struct usb_interface *other;
 +
 +      if (info->subdriver && info->subdriver->disconnect)
 +              info->subdriver->disconnect(info->control);
 +
 +      /* allow user to unbind using either control or data */
 +      if (intf == info->control)
 +              other = info->data;
 +      else
 +              other = info->control;
 +
 +      /* only if not shared */
 +      if (other && intf != other) {
 +              usb_set_intfdata(other, NULL);
 +              usb_driver_release_interface(driver, other);
 +      }
  
 -      dev->data[0] = (unsigned long)NULL;
 +      info->subdriver = NULL;
 +      info->data = NULL;
 +      info->control = NULL;
  }
  
  /* suspend/resume wrappers calling both usbnet and the cdc-wdm
        .manage_power   = qmi_wwan_manage_power,
  };
  
- static const struct driver_info       qmi_wwan_gobi = {
-       .description    = "Qualcomm Gobi wwan/QMI device",
+ static const struct driver_info       qmi_wwan_force_int0 = {
+       .description    = "Qualcomm WWAN/QMI device",
        .flags          = FLAG_WWAN,
-       .bind           = qmi_wwan_bind_gobi,
+       .bind           = qmi_wwan_bind_shared,
 -      .unbind         = qmi_wwan_unbind_shared,
 +      .unbind         = qmi_wwan_unbind,
        .manage_power   = qmi_wwan_manage_power,
+       .data           = BIT(0), /* interface whitelist bitmap */
  };
  
- /* ZTE suck at making USB descriptors */
  static const struct driver_info       qmi_wwan_force_int1 = {
        .description    = "Qualcomm WWAN/QMI device",
        .flags          = FLAG_WWAN,
        .data           = BIT(1), /* interface whitelist bitmap */
  };
  
 -      .unbind         = qmi_wwan_unbind_shared,
+ static const struct driver_info       qmi_wwan_force_int3 = {
+       .description    = "Qualcomm WWAN/QMI device",
+       .flags          = FLAG_WWAN,
+       .bind           = qmi_wwan_bind_shared,
++      .unbind         = qmi_wwan_unbind,
+       .manage_power   = qmi_wwan_manage_power,
+       .data           = BIT(3), /* interface whitelist bitmap */
+ };
+ 
  static const struct driver_info       qmi_wwan_force_int4 = {
        .description    = "Qualcomm WWAN/QMI device",
        .flags          = FLAG_WWAN,
  static const struct driver_info       qmi_wwan_sierra = {
        .description    = "Sierra Wireless wwan/QMI device",
        .flags          = FLAG_WWAN,
-       .bind           = qmi_wwan_bind_gobi,
+       .bind           = qmi_wwan_bind_shared,
 -      .unbind         = qmi_wwan_unbind_shared,
 +      .unbind         = qmi_wwan_unbind,
        .manage_power   = qmi_wwan_manage_power,
        .data           = BIT(8) | BIT(19), /* interface whitelist bitmap */
  };
 
        .exit = ip6_route_net_exit,
  };
  
 +static int __net_init ipv6_inetpeer_init(struct net *net)
 +{
 +      struct inet_peer_base *bp = kmalloc(sizeof(*bp), GFP_KERNEL);
 +
 +      if (!bp)
 +              return -ENOMEM;
 +      inet_peer_base_init(bp);
 +      net->ipv6.peers = bp;
 +      return 0;
 +}
 +
 +static void __net_exit ipv6_inetpeer_exit(struct net *net)
 +{
 +      struct inet_peer_base *bp = net->ipv6.peers;
 +
 +      net->ipv6.peers = NULL;
 +      inetpeer_invalidate_tree(bp);
 +      kfree(bp);
 +}
 +
 +static struct pernet_operations ipv6_inetpeer_ops = {
 +      .init   =       ipv6_inetpeer_init,
 +      .exit   =       ipv6_inetpeer_exit,
 +};
 +
+ static struct pernet_operations ip6_route_net_late_ops = {
+       .init = ip6_route_net_init_late,
+       .exit = ip6_route_net_exit_late,
+ };
+ 
  static struct notifier_block ip6_route_dev_notifier = {
        .notifier_call = ip6_route_dev_notify,
        .priority = 0,