aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristian Evensen <kristian.evensen@gmail.com>2016-07-21 05:10:06 -0400
committerDavid S. Miller <davem@davemloft.net>2016-07-25 01:16:03 -0400
commitbfe9b9d2df669a57a95d641ed46eb018e204c6ce (patch)
treeee04711e21bff5aa230f32e2491f522516949021
parentc42d7121fbee1ee30fd9221d594e9c5a4bc1fed6 (diff)
cdc_ether: Improve ZTE MF823/831/910 handling
The firmware in several ZTE devices (at least the MF823/831/910 modems/mifis) use OS fingerprinting to determine which type of device to export. In addition, these devices export a REST API which can be used to control the type of device. So far, on Linux, the devices have been seen as RNDIS or CDC Ether. When CDC Ether is used, devices of the same type are, as with RNDIS, exported with the same, bogus random MAC address. In addition, the devices (at least on all firmware revisions I have found) use the bogus MAC when sending traffic routed from external networks. And as a final feature, the devices sometimes export the link state incorrectly. There are also references online to several other ZTE devices displaying this behavior, with several different PIDs and MAC addresses. This patch tries to improve the handling of ZTE devices by doing the following: * Create a new driver_info-struct that is used by ZTE devices that do not have an explicit entry in the product table. This struct is the same as the default cdc_ether driver info, but a new bind- and an rx_fixup-function have been added. * In the new bind function, we check if we have read a random MAC from the device. If we have, then we generate a new random MAC address. This will ensure that all devices get a unique MAC. * The rx_fixup-function replaces the destination MAC address in the skb with that of the device. I have not seen a revision of these devices that behaves correctly (i.e., sets the right destination MAC), so I chose not to do any comparison with for example the known, bogus addresses. * The MF823/MF832/MF910 sometimes export cdc carrier on twice on connect (the correct behavior is off then on). Work around this by manually setting carrier to off if an on-notification is received and the NOCARRIER-bit is not set. This change will affect all devices, but it should take care of similar mistakes made by other manufacturers. I tried to think of/look/test for problems/regressions that could be introduced by this behavior, but could not find any. However, my familiarity with this code path is not that great, so there could be something I have overlooked. I have tested this patch with multiple revisions of all three devices, and they behave as expected. In other words, they all got a valid, random MAC, the correct operational state and I can receive/sent traffic without problems. I also tested with some other cdc_ether devices I have and did not find any problems/regressions caused by the two general changes. v3->v4: * Forgot to remove unused variables, sorry about that (thanks David Miller). v2->v3: * I had forgot to remove the random MAC generation from usbnet_cdc_bind() (thanks Oliver). * Rework logic in the ZTE bind-function a bit. v1->v2: * Only generate random MAC for ZTE devices (thanks Oliver Neukum). * Set random MAC and do RX fixup for all ZTE devices that do not have a product-entry, as the bogus MAC have been seen on devices with several different PIDs/MAC addresses. In other words, it seems to be the default behavior of ZTE CDC Ether devices (thanks Lars Melin). Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com> Acked-by: Oliver Neukum <oneukum@suse.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/usb/cdc_ether.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 7cba2c3759df..c47ec0a04c8e 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -388,6 +388,12 @@ void usbnet_cdc_status(struct usbnet *dev, struct urb *urb)
388 case USB_CDC_NOTIFY_NETWORK_CONNECTION: 388 case USB_CDC_NOTIFY_NETWORK_CONNECTION:
389 netif_dbg(dev, timer, dev->net, "CDC: carrier %s\n", 389 netif_dbg(dev, timer, dev->net, "CDC: carrier %s\n",
390 event->wValue ? "on" : "off"); 390 event->wValue ? "on" : "off");
391
392 /* Work-around for devices with broken off-notifications */
393 if (event->wValue &&
394 !test_bit(__LINK_STATE_NOCARRIER, &dev->net->state))
395 usbnet_link_change(dev, 0, 0);
396
391 usbnet_link_change(dev, !!event->wValue, 0); 397 usbnet_link_change(dev, !!event->wValue, 0);
392 break; 398 break;
393 case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */ 399 case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */
@@ -432,6 +438,34 @@ int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
432} 438}
433EXPORT_SYMBOL_GPL(usbnet_cdc_bind); 439EXPORT_SYMBOL_GPL(usbnet_cdc_bind);
434 440
441static int usbnet_cdc_zte_bind(struct usbnet *dev, struct usb_interface *intf)
442{
443 int status = usbnet_cdc_bind(dev, intf);
444
445 if (!status && (dev->net->dev_addr[0] & 0x02))
446 eth_hw_addr_random(dev->net);
447
448 return status;
449}
450
451/* Make sure packets have correct destination MAC address
452 *
453 * A firmware bug observed on some devices (ZTE MF823/831/910) is that the
454 * device sends packets with a static, bogus, random MAC address (event if
455 * device MAC address has been updated). Always set MAC address to that of the
456 * device.
457 */
458static int usbnet_cdc_zte_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
459{
460 if (skb->len < ETH_HLEN || !(skb->data[0] & 0x02))
461 return 1;
462
463 skb_reset_mac_header(skb);
464 ether_addr_copy(eth_hdr(skb)->h_dest, dev->net->dev_addr);
465
466 return 1;
467}
468
435static const struct driver_info cdc_info = { 469static const struct driver_info cdc_info = {
436 .description = "CDC Ethernet Device", 470 .description = "CDC Ethernet Device",
437 .flags = FLAG_ETHER | FLAG_POINTTOPOINT, 471 .flags = FLAG_ETHER | FLAG_POINTTOPOINT,
@@ -442,6 +476,17 @@ static const struct driver_info cdc_info = {
442 .manage_power = usbnet_manage_power, 476 .manage_power = usbnet_manage_power,
443}; 477};
444 478
479static const struct driver_info zte_cdc_info = {
480 .description = "ZTE CDC Ethernet Device",
481 .flags = FLAG_ETHER | FLAG_POINTTOPOINT,
482 .bind = usbnet_cdc_zte_bind,
483 .unbind = usbnet_cdc_unbind,
484 .status = usbnet_cdc_status,
485 .set_rx_mode = usbnet_cdc_update_filter,
486 .manage_power = usbnet_manage_power,
487 .rx_fixup = usbnet_cdc_zte_rx_fixup,
488};
489
445static const struct driver_info wwan_info = { 490static const struct driver_info wwan_info = {
446 .description = "Mobile Broadband Network Device", 491 .description = "Mobile Broadband Network Device",
447 .flags = FLAG_WWAN, 492 .flags = FLAG_WWAN,
@@ -707,6 +752,12 @@ static const struct usb_device_id products[] = {
707 USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 752 USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
708 .driver_info = (kernel_ulong_t)&wwan_info, 753 .driver_info = (kernel_ulong_t)&wwan_info,
709}, { 754}, {
755 /* ZTE modules */
756 USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, USB_CLASS_COMM,
757 USB_CDC_SUBCLASS_ETHERNET,
758 USB_CDC_PROTO_NONE),
759 .driver_info = (unsigned long)&zte_cdc_info,
760}, {
710 USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, 761 USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
711 USB_CDC_PROTO_NONE), 762 USB_CDC_PROTO_NONE),
712 .driver_info = (unsigned long) &cdc_info, 763 .driver_info = (unsigned long) &cdc_info,