Bjørn Mork <bjorn@xxxxxxx> writes: > Finally, I found my modems (or at least a number of them) again today. > But I'm sorry to say, that the troublesome Huawei E3372h-153 is still > giving us a hard time. It does not work with your patch. The symptom is > the same as earlier: The modem returns MBIM frames with 32bit headers. > > So for now, I have to NAK this patch. > > I am sure we can find a good solution that makes all of these modems > work, but I cannot support a patch that breaks previously working > configurations. Sorry. I'll do a few experiments and see if there is a > simple fix for this. Otherwise we'll probably have to do the quirk > game. This is a proof-of-concept only, but it appears to be working. Please test with your device(s) too. It's still mostly your code, as you can see. If this turns out to work, then I believe we should refactor cdc_ncm_init() and cdc_ncm_bind_common() to make the whole initialisation sequence a bit cleaner. And maybe also include cdc_mbim_bind(). Ideally, the MBIM specific RESET should happen there instead of "polluting" the NCM driver with MBIM specific code. But anyway: The sequence that seems to work for both the E3372h-153 and the EM7455 is USB_CDC_GET_NTB_PARAMETERS USB_CDC_RESET_FUNCTION usb_set_interface(dev->udev, 'data interface no', 0); remaining parts of cdc_ncm_init(), excluding USB_CDC_GET_NTB_PARAMETERS usb_set_interface(dev->udev, 'data interface no', 'data alt setting'); without any additional delay between the two usb_set_interface() calls. So the major difference from your patch is that I moved the two control requests out of cdc_ncm_init() to allow running them _before_ setting the data interface to altsetting 0. But maybe I was just lucky. This was barely proof tested. Needs a lot more testing and cleanups as suggested. I'd appreciate it if you continued that, as I don't really have any time for it... FWIW, I also ran a quick test with a D-Link DWM-156A7 (Mediatek MBIM firmware) and a Huawei E367 (Qualcomm device with early Huawei MBIM firmware, distinctly different from the E3372h-153 and most other MBIM devices I've seen) Bjørn --- drivers/net/usb/cdc_ncm.c | 48 ++++++++++++++++++++++++++++---------------- include/uapi/linux/usb/cdc.h | 1 + 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 877c9516e781..be019cbf1719 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -488,16 +488,6 @@ static int cdc_ncm_init(struct usbnet *dev) u8 iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber; int err; - err = usbnet_read_cmd(dev, USB_CDC_GET_NTB_PARAMETERS, - USB_TYPE_CLASS | USB_DIR_IN - |USB_RECIP_INTERFACE, - 0, iface_no, &ctx->ncm_parm, - sizeof(ctx->ncm_parm)); - if (err < 0) { - dev_err(&dev->intf->dev, "failed GET_NTB_PARAMETERS\n"); - return err; /* GET_NTB_PARAMETERS is required */ - } - /* set CRC Mode */ if (cdc_ncm_flags(dev) & USB_CDC_NCM_NCAP_CRC_MODE) { dev_dbg(&dev->intf->dev, "Setting CRC mode off\n"); @@ -837,12 +827,43 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_ } } + iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber; + temp = usbnet_read_cmd(dev, USB_CDC_GET_NTB_PARAMETERS, + USB_TYPE_CLASS | USB_DIR_IN + | USB_RECIP_INTERFACE, + 0, iface_no, &ctx->ncm_parm, + sizeof(ctx->ncm_parm)); + if (temp < 0) { + dev_err(&dev->intf->dev, "failed GET_NTB_PARAMETERS\n"); + goto error; /* GET_NTB_PARAMETERS is required */ + } + + /* Some modems (e.g. Telit LE922A6) need to reset the MBIM function + * or they will fail to work properly. + * For details on RESET_FUNCTION request see document + * "USB Communication Class Subclass Specification for MBIM" + * RESET_FUNCTION should be harmless for all the other MBIM modems + */ + if (cdc_ncm_comm_intf_is_mbim(ctx->control->cur_altsetting)) { + temp = usbnet_write_cmd(dev, USB_CDC_RESET_FUNCTION, + USB_TYPE_CLASS | USB_DIR_OUT + | USB_RECIP_INTERFACE, + 0, iface_no, NULL, 0); + if (temp < 0) + dev_err(&dev->intf->dev, "failed RESET_FUNCTION\n"); + } + iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber; /* Reset data interface. Some devices will not reset properly * unless they are configured first. Toggle the altsetting to * force a reset + * This is applied only to ncm devices, since it has been verified + * to cause issues with some MBIM modems (e.g. Telit LE922A6). + * MBIM devices reset is achieved using MBIM request RESET_FUNCTION + * in cdc_ncm_init */ + usb_set_interface(dev->udev, iface_no, data_altsetting); temp = usb_set_interface(dev->udev, iface_no, 0); if (temp) { @@ -854,13 +875,6 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_ if (cdc_ncm_init(dev)) goto error2; - /* Some firmwares need a pause here or they will silently fail - * to set up the interface properly. This value was decided - * empirically on a Sierra Wireless MC7455 running 02.08.02.00 - * firmware. - */ - usleep_range(10000, 20000); - /* configure data interface */ temp = usb_set_interface(dev->udev, iface_no, data_altsetting); if (temp) { diff --git a/include/uapi/linux/usb/cdc.h b/include/uapi/linux/usb/cdc.h index e2bc417b243b..30258fb229e6 100644 --- a/include/uapi/linux/usb/cdc.h +++ b/include/uapi/linux/usb/cdc.h @@ -231,6 +231,7 @@ struct usb_cdc_mbim_extended_desc { #define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x00 #define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x01 +#define USB_CDC_RESET_FUNCTION 0x05 #define USB_CDC_REQ_SET_LINE_CODING 0x20 #define USB_CDC_REQ_GET_LINE_CODING 0x21 #define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22 -- 2.10.2 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html