Merge tag 'for-linus-20160801' of git://git.infradead.org/linux-mtd
[deliverable/linux.git] / drivers / net / usb / cdc_ether.c
index 7cba2c3759df76fba3087d0acd654bd9d77896d7..c47ec0a04c8e5f9ff4d77cf8fade7717ca9cdb75 100644 (file)
@@ -388,6 +388,12 @@ void usbnet_cdc_status(struct usbnet *dev, struct urb *urb)
        case USB_CDC_NOTIFY_NETWORK_CONNECTION:
                netif_dbg(dev, timer, dev->net, "CDC: carrier %s\n",
                          event->wValue ? "on" : "off");
+
+               /* Work-around for devices with broken off-notifications */
+               if (event->wValue &&
+                   !test_bit(__LINK_STATE_NOCARRIER, &dev->net->state))
+                       usbnet_link_change(dev, 0, 0);
+
                usbnet_link_change(dev, !!event->wValue, 0);
                break;
        case USB_CDC_NOTIFY_SPEED_CHANGE:       /* tx/rx rates */
@@ -432,6 +438,34 @@ int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
 }
 EXPORT_SYMBOL_GPL(usbnet_cdc_bind);
 
+static int usbnet_cdc_zte_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+       int status = usbnet_cdc_bind(dev, intf);
+
+       if (!status && (dev->net->dev_addr[0] & 0x02))
+               eth_hw_addr_random(dev->net);
+
+       return status;
+}
+
+/* Make sure packets have correct destination MAC address
+ *
+ * A firmware bug observed on some devices (ZTE MF823/831/910) is that the
+ * device sends packets with a static, bogus, random MAC address (event if
+ * device MAC address has been updated). Always set MAC address to that of the
+ * device.
+ */
+static int usbnet_cdc_zte_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+       if (skb->len < ETH_HLEN || !(skb->data[0] & 0x02))
+               return 1;
+
+       skb_reset_mac_header(skb);
+       ether_addr_copy(eth_hdr(skb)->h_dest, dev->net->dev_addr);
+
+       return 1;
+}
+
 static const struct driver_info        cdc_info = {
        .description =  "CDC Ethernet Device",
        .flags =        FLAG_ETHER | FLAG_POINTTOPOINT,
@@ -442,6 +476,17 @@ static const struct driver_info    cdc_info = {
        .manage_power = usbnet_manage_power,
 };
 
+static const struct driver_info        zte_cdc_info = {
+       .description =  "ZTE CDC Ethernet Device",
+       .flags =        FLAG_ETHER | FLAG_POINTTOPOINT,
+       .bind =         usbnet_cdc_zte_bind,
+       .unbind =       usbnet_cdc_unbind,
+       .status =       usbnet_cdc_status,
+       .set_rx_mode =  usbnet_cdc_update_filter,
+       .manage_power = usbnet_manage_power,
+       .rx_fixup = usbnet_cdc_zte_rx_fixup,
+};
+
 static const struct driver_info wwan_info = {
        .description =  "Mobile Broadband Network Device",
        .flags =        FLAG_WWAN,
@@ -706,6 +751,12 @@ static const struct usb_device_id  products[] = {
        USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, 0x81ba, USB_CLASS_COMM,
                        USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
        .driver_info = (kernel_ulong_t)&wwan_info,
+}, {
+       /* ZTE modules */
+       USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, USB_CLASS_COMM,
+                                     USB_CDC_SUBCLASS_ETHERNET,
+                                     USB_CDC_PROTO_NONE),
+       .driver_info = (unsigned long)&zte_cdc_info,
 }, {
        USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
                        USB_CDC_PROTO_NONE),
This page took 0.02658 seconds and 5 git commands to generate.