diff options
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/cdc_mbim.c | 1 | ||||
-rw-r--r-- | drivers/net/usb/ipheth.c | 60 | ||||
-rw-r--r-- | drivers/net/usb/qmi_wwan.c | 65 | ||||
-rw-r--r-- | drivers/net/usb/r8152.c | 53 | ||||
-rw-r--r-- | drivers/net/usb/smsc75xx.c | 4 | ||||
-rw-r--r-- | drivers/net/usb/smsc95xx.c | 4 |
6 files changed, 76 insertions, 111 deletions
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index 0362acd5cdca..28321aca48fe 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c @@ -23,6 +23,7 @@ #include <linux/usb/cdc_ncm.h> #include <net/ipv6.h> #include <net/addrconf.h> +#include <net/ipv6_stubs.h> /* alternative VLAN for IP session 0 if not untagged */ #define MBIM_IPS0_VID 4094 diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 3d8a70d3ea9b..c247aed2dceb 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -54,17 +54,6 @@ #include <linux/workqueue.h> #define USB_VENDOR_APPLE 0x05ac -#define USB_PRODUCT_IPHONE 0x1290 -#define USB_PRODUCT_IPHONE_3G 0x1292 -#define USB_PRODUCT_IPHONE_3GS 0x1294 -#define USB_PRODUCT_IPHONE_4 0x1297 -#define USB_PRODUCT_IPAD 0x129a -#define USB_PRODUCT_IPAD_2 0x12a2 -#define USB_PRODUCT_IPAD_3 0x12a6 -#define USB_PRODUCT_IPAD_MINI 0x12ab -#define USB_PRODUCT_IPHONE_4_VZW 0x129c -#define USB_PRODUCT_IPHONE_4S 0x12a0 -#define USB_PRODUCT_IPHONE_5 0x12a8 #define IPHETH_USBINTF_CLASS 255 #define IPHETH_USBINTF_SUBCLASS 253 @@ -88,50 +77,9 @@ #define IPHETH_CARRIER_ON 0x04 static const struct usb_device_id ipheth_table[] = { - { USB_DEVICE_AND_INTERFACE_INFO( - USB_VENDOR_APPLE, USB_PRODUCT_IPHONE, - IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, - IPHETH_USBINTF_PROTO) }, - { USB_DEVICE_AND_INTERFACE_INFO( - USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_3G, - IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, - IPHETH_USBINTF_PROTO) }, - { USB_DEVICE_AND_INTERFACE_INFO( - USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_3GS, - IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, - IPHETH_USBINTF_PROTO) }, - { USB_DEVICE_AND_INTERFACE_INFO( - USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4, - IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, - IPHETH_USBINTF_PROTO) }, - { USB_DEVICE_AND_INTERFACE_INFO( - USB_VENDOR_APPLE, USB_PRODUCT_IPAD, - IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, - IPHETH_USBINTF_PROTO) }, - { USB_DEVICE_AND_INTERFACE_INFO( - USB_VENDOR_APPLE, USB_PRODUCT_IPAD_2, - IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, - IPHETH_USBINTF_PROTO) }, - { USB_DEVICE_AND_INTERFACE_INFO( - USB_VENDOR_APPLE, USB_PRODUCT_IPAD_3, - IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, - IPHETH_USBINTF_PROTO) }, - { USB_DEVICE_AND_INTERFACE_INFO( - USB_VENDOR_APPLE, USB_PRODUCT_IPAD_MINI, - IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, - IPHETH_USBINTF_PROTO) }, - { USB_DEVICE_AND_INTERFACE_INFO( - USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4_VZW, - IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, - IPHETH_USBINTF_PROTO) }, - { USB_DEVICE_AND_INTERFACE_INFO( - USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S, - IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, - IPHETH_USBINTF_PROTO) }, - { USB_DEVICE_AND_INTERFACE_INFO( - USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5, - IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, - IPHETH_USBINTF_PROTO) }, + { USB_VENDOR_AND_INTERFACE_INFO(USB_VENDOR_APPLE, IPHETH_USBINTF_CLASS, + IPHETH_USBINTF_SUBCLASS, + IPHETH_USBINTF_PROTO) }, { } }; MODULE_DEVICE_TABLE(usb, ipheth_table); @@ -293,8 +241,6 @@ static int ipheth_carrier_set(struct ipheth_device *dev) struct usb_device *udev; int retval; - if (!dev) - return 0; if (!dev->confirmed_pairing) return 0; diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 679e404a5224..5c3ac97519b7 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -63,6 +63,7 @@ enum qmi_wwan_flags { enum qmi_wwan_quirks { QMI_WWAN_QUIRK_DTR = 1 << 0, /* needs "set DTR" request */ + QMI_WWAN_QUIRK_QUECTEL_DYNCFG = 1 << 1, /* check num. endpoints */ }; struct qmimux_hdr { @@ -845,6 +846,16 @@ static const struct driver_info qmi_wwan_info_quirk_dtr = { .data = QMI_WWAN_QUIRK_DTR, }; +static const struct driver_info qmi_wwan_info_quirk_quectel_dyncfg = { + .description = "WWAN/QMI device", + .flags = FLAG_WWAN | FLAG_SEND_ZLP, + .bind = qmi_wwan_bind, + .unbind = qmi_wwan_unbind, + .manage_power = qmi_wwan_manage_power, + .rx_fixup = qmi_wwan_rx_fixup, + .data = QMI_WWAN_QUIRK_DTR | QMI_WWAN_QUIRK_QUECTEL_DYNCFG, +}; + #define HUAWEI_VENDOR_ID 0x12D1 /* map QMI/wwan function by a fixed interface number */ @@ -865,6 +876,15 @@ static const struct driver_info qmi_wwan_info_quirk_dtr = { #define QMI_GOBI_DEVICE(vend, prod) \ QMI_FIXED_INTF(vend, prod, 0) +/* Quectel does not use fixed interface numbers on at least some of their + * devices. We need to check the number of endpoints to ensure that we bind to + * the correct interface. + */ +#define QMI_QUIRK_QUECTEL_DYNCFG(vend, prod) \ + USB_DEVICE_AND_INTERFACE_INFO(vend, prod, USB_CLASS_VENDOR_SPEC, \ + USB_SUBCLASS_VENDOR_SPEC, 0xff), \ + .driver_info = (unsigned long)&qmi_wwan_info_quirk_quectel_dyncfg + static const struct usb_device_id products[] = { /* 1. CDC ECM like devices match on the control interface */ { /* Huawei E392, E398 and possibly others sharing both device id and more... */ @@ -969,20 +989,9 @@ static const struct usb_device_id products[] = { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x581d, USB_CLASS_VENDOR_SPEC, 1, 7), .driver_info = (unsigned long)&qmi_wwan_info, }, - { /* Quectel EP06/EG06/EM06 */ - USB_DEVICE_AND_INTERFACE_INFO(0x2c7c, 0x0306, - USB_CLASS_VENDOR_SPEC, - USB_SUBCLASS_VENDOR_SPEC, - 0xff), - .driver_info = (unsigned long)&qmi_wwan_info_quirk_dtr, - }, - { /* Quectel EG12/EM12 */ - USB_DEVICE_AND_INTERFACE_INFO(0x2c7c, 0x0512, - USB_CLASS_VENDOR_SPEC, - USB_SUBCLASS_VENDOR_SPEC, - 0xff), - .driver_info = (unsigned long)&qmi_wwan_info_quirk_dtr, - }, + {QMI_QUIRK_QUECTEL_DYNCFG(0x2c7c, 0x0125)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */ + {QMI_QUIRK_QUECTEL_DYNCFG(0x2c7c, 0x0306)}, /* Quectel EP06/EG06/EM06 */ + {QMI_QUIRK_QUECTEL_DYNCFG(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */ /* 3. Combined interface devices matching on interface number */ {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ @@ -1281,7 +1290,6 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)}, /* HP lt4120 Snapdragon X5 LTE */ {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */ {QMI_QUIRK_SET_DTR(0x1e0e, 0x9001, 5)}, /* SIMCom 7100E, 7230E, 7600E ++ */ - {QMI_QUIRK_SET_DTR(0x2c7c, 0x0125, 4)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */ {QMI_QUIRK_SET_DTR(0x2c7c, 0x0121, 4)}, /* Quectel EC21 Mini PCIe */ {QMI_QUIRK_SET_DTR(0x2c7c, 0x0191, 4)}, /* Quectel EG91 */ {QMI_FIXED_INTF(0x2c7c, 0x0296, 4)}, /* Quectel BG96 */ @@ -1361,27 +1369,12 @@ static bool quectel_ec20_detected(struct usb_interface *intf) return false; } -static bool quectel_diag_detected(struct usb_interface *intf) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_interface_descriptor intf_desc = intf->cur_altsetting->desc; - u16 id_vendor = le16_to_cpu(dev->descriptor.idVendor); - u16 id_product = le16_to_cpu(dev->descriptor.idProduct); - - if (id_vendor != 0x2c7c || intf_desc.bNumEndpoints != 2) - return false; - - if (id_product == 0x0306 || id_product == 0x0512) - return true; - else - return false; -} - static int qmi_wwan_probe(struct usb_interface *intf, const struct usb_device_id *prod) { struct usb_device_id *id = (struct usb_device_id *)prod; struct usb_interface_descriptor *desc = &intf->cur_altsetting->desc; + const struct driver_info *info; /* Workaround to enable dynamic IDs. This disables usbnet * blacklisting functionality. Which, if required, can be @@ -1415,10 +1408,14 @@ static int qmi_wwan_probe(struct usb_interface *intf, * we need to match on class/subclass/protocol. These values are * identical for the diagnostic- and QMI-interface, but bNumEndpoints is * different. Ignore the current interface if the number of endpoints - * the number for the diag interface (two). + * equals the number for the diag interface (two). */ - if (quectel_diag_detected(intf)) - return -ENODEV; + info = (void *)&id->driver_info; + + if (info->data & QMI_WWAN_QUIRK_QUECTEL_DYNCFG) { + if (desc->bNumEndpoints == 2) + return -ENODEV; + } return usbnet_probe(intf, id); } diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 86c8c64fbb0f..b01bfa63860d 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -1212,7 +1212,6 @@ static int vendor_mac_passthru_addr_read(struct r8152 *tp, struct sockaddr *sa) goto amacout; } memcpy(sa->sa_data, buf, 6); - ether_addr_copy(tp->netdev->dev_addr, sa->sa_data); netif_info(tp, probe, tp->netdev, "Using pass-thru MAC addr %pM\n", sa->sa_data); @@ -1221,43 +1220,57 @@ amacout: return ret; } -static int set_ethernet_addr(struct r8152 *tp) +static int determine_ethernet_addr(struct r8152 *tp, struct sockaddr *sa) { struct net_device *dev = tp->netdev; - struct sockaddr sa; int ret; + sa->sa_family = dev->type; + if (tp->version == RTL_VER_01) { - ret = pla_ocp_read(tp, PLA_IDR, 8, sa.sa_data); + ret = pla_ocp_read(tp, PLA_IDR, 8, sa->sa_data); } else { /* if device doesn't support MAC pass through this will * be expected to be non-zero */ - ret = vendor_mac_passthru_addr_read(tp, &sa); + ret = vendor_mac_passthru_addr_read(tp, sa); if (ret < 0) - ret = pla_ocp_read(tp, PLA_BACKUP, 8, sa.sa_data); + ret = pla_ocp_read(tp, PLA_BACKUP, 8, sa->sa_data); } if (ret < 0) { netif_err(tp, probe, dev, "Get ether addr fail\n"); - } else if (!is_valid_ether_addr(sa.sa_data)) { + } else if (!is_valid_ether_addr(sa->sa_data)) { netif_err(tp, probe, dev, "Invalid ether addr %pM\n", - sa.sa_data); + sa->sa_data); eth_hw_addr_random(dev); - ether_addr_copy(sa.sa_data, dev->dev_addr); - ret = rtl8152_set_mac_address(dev, &sa); + ether_addr_copy(sa->sa_data, dev->dev_addr); netif_info(tp, probe, dev, "Random ether addr %pM\n", - sa.sa_data); - } else { - if (tp->version == RTL_VER_01) - ether_addr_copy(dev->dev_addr, sa.sa_data); - else - ret = rtl8152_set_mac_address(dev, &sa); + sa->sa_data); + return 0; } return ret; } +static int set_ethernet_addr(struct r8152 *tp) +{ + struct net_device *dev = tp->netdev; + struct sockaddr sa; + int ret; + + ret = determine_ethernet_addr(tp, &sa); + if (ret < 0) + return ret; + + if (tp->version == RTL_VER_01) + ether_addr_copy(dev->dev_addr, sa.sa_data); + else + ret = rtl8152_set_mac_address(dev, &sa); + + return ret; +} + static void read_bulk_callback(struct urb *urb) { struct net_device *netdev; @@ -4264,10 +4277,18 @@ static int rtl8152_post_reset(struct usb_interface *intf) { struct r8152 *tp = usb_get_intfdata(intf); struct net_device *netdev; + struct sockaddr sa; if (!tp) return 0; + /* reset the MAC adddress in case of policy change */ + if (determine_ethernet_addr(tp, &sa) >= 0) { + rtnl_lock(); + dev_set_mac_address (tp->netdev, &sa, NULL); + rtnl_unlock(); + } + netdev = tp->netdev; if (!netif_running(netdev)) return 0; diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index ec287c9741e8..e4c2f3afce60 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -774,8 +774,8 @@ static void smsc75xx_init_mac_address(struct usbnet *dev) /* maybe the boot loader passed the MAC address in devicetree */ mac_addr = of_get_mac_address(dev->udev->dev.of_node); - if (mac_addr) { - memcpy(dev->net->dev_addr, mac_addr, ETH_ALEN); + if (!IS_ERR(mac_addr)) { + ether_addr_copy(dev->net->dev_addr, mac_addr); return; } diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index e3d08626828e..a0e119907c84 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -917,8 +917,8 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) /* maybe the boot loader passed the MAC address in devicetree */ mac_addr = of_get_mac_address(dev->udev->dev.of_node); - if (mac_addr) { - memcpy(dev->net->dev_addr, mac_addr, ETH_ALEN); + if (!IS_ERR(mac_addr)) { + ether_addr_copy(dev->net->dev_addr, mac_addr); return; } |