2016-11-26 22:17 GMT+01:00 Bjørn Mork <bj...@mork.no>:
> Bjørn Mork <bj...@mork.no> 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.

Sorry, this does not work :-(

The problem is always in the altsetting toggle: if I comment that
part, your patch is working fine.

I'm now wondering if the safest thing is to add a very simple quirk in
cdc_mbim that makes this toggle not to be applied with the buggy
modems and then unconditionally add the RESET_FUNCTION request in
cdc_mbim_bind after cdc_ncm_bind_common has been executed.

Daniele

>
> 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to