diff options
Diffstat (limited to 'drivers/net/usb/cdc_ncm.c')
| -rw-r--r-- | drivers/net/usb/cdc_ncm.c | 57 | 
1 files changed, 40 insertions, 17 deletions
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 4a8c25a2229..4709fa3497c 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -55,6 +55,14 @@  #define	DRIVER_VERSION				"14-Mar-2012" +#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM) +static bool prefer_mbim = true; +#else +static bool prefer_mbim; +#endif +module_param(prefer_mbim, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(prefer_mbim, "Prefer MBIM setting on dual NCM/MBIM functions"); +  static void cdc_ncm_txpath_bh(unsigned long param);  static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx);  static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer); @@ -550,9 +558,12 @@ void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)  }  EXPORT_SYMBOL_GPL(cdc_ncm_unbind); -static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf) +/* Select the MBIM altsetting iff it is preferred and available, + * returning the number of the corresponding data interface altsetting + */ +u8 cdc_ncm_select_altsetting(struct usbnet *dev, struct usb_interface *intf)  { -	int ret; +	struct usb_host_interface *alt;  	/* The MBIM spec defines a NCM compatible default altsetting,  	 * which we may have matched: @@ -568,23 +579,27 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)  	 *   endpoint descriptors, shall be constructed according to  	 *   the rules given in section 6 (USB Device Model) of this  	 *   specification." -	 * -	 * Do not bind to such interfaces, allowing cdc_mbim to handle -	 * them  	 */ -#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM) -	if ((intf->num_altsetting == 2) && -	    !usb_set_interface(dev->udev, -			       intf->cur_altsetting->desc.bInterfaceNumber, -			       CDC_NCM_COMM_ALTSETTING_MBIM)) { -		if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) -			return -ENODEV; -		else -			usb_set_interface(dev->udev, -					  intf->cur_altsetting->desc.bInterfaceNumber, -					  CDC_NCM_COMM_ALTSETTING_NCM); +	if (prefer_mbim && intf->num_altsetting == 2) { +		alt = usb_altnum_to_altsetting(intf, CDC_NCM_COMM_ALTSETTING_MBIM); +		if (alt && cdc_ncm_comm_intf_is_mbim(alt) && +		    !usb_set_interface(dev->udev, +				       intf->cur_altsetting->desc.bInterfaceNumber, +				       CDC_NCM_COMM_ALTSETTING_MBIM)) +			return CDC_NCM_DATA_ALTSETTING_MBIM;  	} -#endif +	return CDC_NCM_DATA_ALTSETTING_NCM; +} +EXPORT_SYMBOL_GPL(cdc_ncm_select_altsetting); + +static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf) +{ +	int ret; + +	/* MBIM backwards compatible function? */ +	cdc_ncm_select_altsetting(dev, intf); +	if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) +		return -ENODEV;  	/* NCM data altsetting is always 1 */  	ret = cdc_ncm_bind_common(dev, intf, 1); @@ -1213,6 +1228,14 @@ static const struct usb_device_id cdc_devs[] = {  	  .driver_info = (unsigned long) &wwan_info,  	}, +	/* tag Huawei devices as wwan */ +	{ USB_VENDOR_AND_INTERFACE_INFO(0x12d1, +					USB_CLASS_COMM, +					USB_CDC_SUBCLASS_NCM, +					USB_CDC_PROTO_NONE), +	  .driver_info = (unsigned long)&wwan_info, +	}, +  	/* Huawei NCM devices disguised as vendor specific */  	{ USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16),  	  .driver_info = (unsigned long)&wwan_info,  |