diff mbox series

option: Improve Quectel EP06 detection

Message ID 20180908125754.1947-1-kristian.evensen@gmail.com (mailing list archive)
State New, archived
Headers show
Series option: Improve Quectel EP06 detection | expand

Commit Message

Kristian Evensen Sept. 8, 2018, 12:57 p.m. UTC
The Quectel EP06 (and EM06/EG06) LTE modem supports updating the USB
configuration, without the VID/PID or configuration number changing.
When the configuration is updated and interfaces are added/removed, the
interface numbers are updated. This causes our current code for matching
EP06 not to work as intended, as the assumption about reserved
interfaces no longer holds. If for example the diagnostic (first)
interface is removed, option will (try to) bind to the QMI interface.

This patch improves EP06 detection by replacing the current match with
two matches, and those matches check class, subclass and protocol as
well as VID and PID. The diag interface exports class, subclass and
protocol as 0xff. For the other serial interfaces, class is 0xff and
subclass and protocol are both 0x0.

The modem can export the following devices and always in this order:
diag, nmea, at, ppp. qmi and adb. This means that diag can only ever be
interface 0, and interface numbers 1-5 should be marked as reserved. The
three other serial devices can have interface numbers 0-3, but I have
not marked any interfaces as reserved. The reason is that the serial
devices are the only interfaces exported by the device where subclass
and protocol is 0x0.

QMI exports the same class, subclass and protocol values as the diag
interface. However, the two interfaces have different number of
endpoints, QMI has three and diag two. I have added a check for number
of interfaces if VID/PID matches the EP06, and we ignore the device if
number of interfaces equals three (and subclass is set).

Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
---
 drivers/usb/serial/option.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

Comments

Johan Hovold Sept. 10, 2018, 10:30 a.m. UTC | #1
On Sat, Sep 08, 2018 at 02:57:54PM +0200, Kristian Evensen wrote:
> The Quectel EP06 (and EM06/EG06) LTE modem supports updating the USB
> configuration, without the VID/PID or configuration number changing.
> When the configuration is updated and interfaces are added/removed, the
> interface numbers are updated. This causes our current code for matching
> EP06 not to work as intended, as the assumption about reserved
> interfaces no longer holds. If for example the diagnostic (first)
> interface is removed, option will (try to) bind to the QMI interface.
> 
> This patch improves EP06 detection by replacing the current match with
> two matches, and those matches check class, subclass and protocol as
> well as VID and PID. The diag interface exports class, subclass and
> protocol as 0xff. For the other serial interfaces, class is 0xff and
> subclass and protocol are both 0x0.
> 
> The modem can export the following devices and always in this order:
> diag, nmea, at, ppp. qmi and adb. This means that diag can only ever be
> interface 0, and interface numbers 1-5 should be marked as reserved. The
> three other serial devices can have interface numbers 0-3, but I have
> not marked any interfaces as reserved. The reason is that the serial
> devices are the only interfaces exported by the device where subclass
> and protocol is 0x0.
> 
> QMI exports the same class, subclass and protocol values as the diag
> interface. However, the two interfaces have different number of
> endpoints, QMI has three and diag two. I have added a check for number
> of interfaces if VID/PID matches the EP06, and we ignore the device if
> number of interfaces equals three (and subclass is set).
> 
> Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>

What a mess.

Please provide the output of usb-devices (or lsusb -v) for both
"configurations". How do you update the configuration by the way?

Thanks,
Johan
Kristian Evensen Sept. 10, 2018, 11:39 a.m. UTC | #2
Hi,

On Mon, Sep 10, 2018 at 12:30 PM Johan Hovold <johan@kernel.org> wrote:
> Please provide the output of usb-devices (or lsusb -v) for both
> "configurations". How do you update the configuration by the way?

The configuration is updated using a proprietary AT-command
(AT+QCFG="usbcfg"). The format of the command is as follows:
AT+QCFG="usbcfg",<vid>,<pid>,<diag>,<nmea>,<at_port>,<modem>,<rmnet>,<adb>.
In other words, you set which interfaces to enable/disable. Based on
my testing, it is only possible to enable/disable diag, rmnet (QMI)
and adb, as well as nmea, at_port and modem together. I.e., it is not
possible to only disable for example nmea.

With all interfaces are enabled, the output of lsusb -v looks as follows:

Bus 002 Device 008: ID 2c7c:0306 Quectel Wireless Solutions Co., Ltd.
EG06/EP06/EM06 LTE-A modem
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               3.00
  bDeviceClass          239 Miscellaneous Device
  bDeviceSubClass         2 ?
  bDeviceProtocol         1 Interface Association
  bMaxPacketSize0         9
  idVendor           0x2c7c Quectel Wireless Solutions Co., Ltd.
  idProduct          0x0306 EG06/EP06/EM06 LTE-A modem
  bcdDevice            3.10
  iManufacturer           1 Quectel
  iProduct                2 LTE-A Module
  iSerial                 3 c1494706
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength          328
    bNumInterfaces          6
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              126mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass    255 Vendor Specific Subclass
      bInterfaceProtocol    255 Vendor Specific Protocol
      iInterface              0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               0
        bMaxBurst               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               0
        bMaxBurst               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           3
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
      ** UNRECOGNIZED:  05 24 00 10 01
      ** UNRECOGNIZED:  05 24 01 00 00
      ** UNRECOGNIZED:  04 24 02 02
      ** UNRECOGNIZED:  05 24 06 00 00
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x000a  1x 10 bytes
        bInterval               9
        bMaxBurst               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               0
        bMaxBurst               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               0
        bMaxBurst               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           3
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
      ** UNRECOGNIZED:  05 24 00 10 01
      ** UNRECOGNIZED:  05 24 01 00 00
      ** UNRECOGNIZED:  04 24 02 02
      ** UNRECOGNIZED:  05 24 06 00 00
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x85  EP 5 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x000a  1x 10 bytes
        bInterval               9
        bMaxBurst               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x84  EP 4 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               0
        bMaxBurst               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               0
        bMaxBurst               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           3
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
      ** UNRECOGNIZED:  05 24 00 10 01
      ** UNRECOGNIZED:  05 24 01 00 00
      ** UNRECOGNIZED:  04 24 02 02
      ** UNRECOGNIZED:  05 24 06 00 00
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x87  EP 7 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x000a  1x 10 bytes
        bInterval               9
        bMaxBurst               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x86  EP 6 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               0
        bMaxBurst               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               0
        bMaxBurst               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        4
      bAlternateSetting       0
      bNumEndpoints           3
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass    255 Vendor Specific Subclass
      bInterfaceProtocol    255 Vendor Specific Protocol
      iInterface              0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x89  EP 9 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval               9
        bMaxBurst               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x88  EP 8 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               0
        bMaxBurst               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x05  EP 5 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               0
        bMaxBurst               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        5
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass     66
      bInterfaceProtocol      1
      iInterface              4 ADB Interface
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x06  EP 6 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               0
        bMaxBurst               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x8a  EP 10 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               0
        bMaxBurst               0
Binary Object Store Descriptor:
  bLength                 5
  bDescriptorType        15
  wTotalLength           22
  bNumDeviceCaps          2
  USB 2.0 Extension Device Capability:
    bLength                 7
    bDescriptorType        16
    bDevCapabilityType      2
    bmAttributes   0x00000002
      Link Power Management (LPM) Supported
  SuperSpeed USB Device Capability:
    bLength                10
    bDescriptorType        16
    bDevCapabilityType      3
    bmAttributes         0x00
    wSpeedsSupported   0x000f
      Device can operate at Low Speed (1Mbps)
      Device can operate at Full Speed (12Mbps)
      Device can operate at High Speed (480Mbps)
      Device can operate at SuperSpeed (5Gbps)
    bFunctionalitySupport   1
      Lowest fully-functional device speed is Full Speed (12Mbps)
    bU1DevExitLat           1 micro seconds
    bU2DevExitLat         500 micro seconds
Device Status:     0x0000
  (Bus Powered)

If I for example disable diag, then the bInterfaceNumber of nmea
changes from 1 to 0, at from 2 to 1, etc., etc.

BR,
Kristian
Dan Williams Sept. 10, 2018, 2:43 p.m. UTC | #3
On Sat, 2018-09-08 at 14:57 +0200, Kristian Evensen wrote:
> The Quectel EP06 (and EM06/EG06) LTE modem supports updating the USB
> configuration, without the VID/PID or configuration number changing.
> When the configuration is updated and interfaces are added/removed,
> the
> interface numbers are updated. This causes our current code for
> matching
> EP06 not to work as intended, as the assumption about reserved
> interfaces no longer holds. If for example the diagnostic (first)
> interface is removed, option will (try to) bind to the QMI interface.
> 
> This patch improves EP06 detection by replacing the current match
> with
> two matches, and those matches check class, subclass and protocol as
> well as VID and PID. The diag interface exports class, subclass and
> protocol as 0xff. For the other serial interfaces, class is 0xff and
> subclass and protocol are both 0x0.
> 
> The modem can export the following devices and always in this order:
> diag, nmea, at, ppp. qmi and adb. This means that diag can only ever
> be
> interface 0, and interface numbers 1-5 should be marked as reserved.
> The
> three other serial devices can have interface numbers 0-3, but I have
> not marked any interfaces as reserved. The reason is that the serial
> devices are the only interfaces exported by the device where subclass
> and protocol is 0x0.
> 
> QMI exports the same class, subclass and protocol values as the diag
> interface. However, the two interfaces have different number of
> endpoints, QMI has three and diag two. I have added a check for
> number
> of interfaces if VID/PID matches the EP06, and we ignore the device
> if
> number of interfaces equals three (and subclass is set).

I double-checked the permutations & logic and it makes sense to me.

Acked-by: Dan Williams <dcbw@redhat.com>

> Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
> ---
>  drivers/usb/serial/option.c | 17 +++++++++++++++--
>  1 file changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/serial/option.c
> b/drivers/usb/serial/option.c
> index 0215b70c4efc..835dcd2875a7 100644
> --- a/drivers/usb/serial/option.c
> +++ b/drivers/usb/serial/option.c
> @@ -1081,8 +1081,9 @@ static const struct usb_device_id option_ids[]
> = {
>  	  .driver_info = RSVD(4) },
>  	{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
>  	  .driver_info = RSVD(4) },
> -	{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06),
> -	  .driver_info = RSVD(4) | RSVD(5) },
> +	{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID,
> QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
> +	  .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) |
> RSVD(5) },
> +	{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID,
> QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },
>  	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
>  	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
>  	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
> @@ -1985,6 +1986,7 @@ static int option_probe(struct usb_serial
> *serial,
>  {
>  	struct usb_interface_descriptor *iface_desc =
>  				&serial->interface->cur_altsetting-
> >desc;
> +	struct usb_device_descriptor *dev_desc = &serial->dev-
> >descriptor;
>  	unsigned long device_flags = id->driver_info;
>  
>  	/* Never bind to the CD-Rom emulation interface	*/
> @@ -1999,6 +2001,17 @@ static int option_probe(struct usb_serial
> *serial,
>  	if (device_flags & RSVD(iface_desc->bInterfaceNumber))
>  		return -ENODEV;
>  
> +	/*
> +	 * Don't bind to the QMI device of the Quectel
> EP06/EG06/EM06. Class,
> +	 * subclass and protocol is 0xff for both the diagnostic
> port and the
> +	 * QMI interface, but the diagnostic port only has two
> endpoints (QMI
> +	 * has three).
> +	 */
> +	if (dev_desc->idVendor == cpu_to_le16(QUECTEL_VENDOR_ID) &&
> +	    dev_desc->idProduct == cpu_to_le16(QUECTEL_PRODUCT_EP06)
> &&
> +	    iface_desc->bInterfaceSubClass && iface_desc-
> >bNumEndpoints == 3)
> +		return -ENODEV;
> +
>  	/* Store the device flags so we can use them during attach.
> */
>  	usb_set_serial_data(serial, (void *)device_flags);
>
Lars Melin Sept. 11, 2018, 2 p.m. UTC | #4
On 9/10/2018 18:39, Kristian Evensen wrote:
> Hi,
> 
> On Mon, Sep 10, 2018 at 12:30 PM Johan Hovold <johan@kernel.org> wrote:
>> Please provide the output of usb-devices (or lsusb -v) for both
>> "configurations". How do you update the configuration by the way?
> 
> The configuration is updated using a proprietary AT-command
> (AT+QCFG="usbcfg"). The format of the command is as follows:
> AT+QCFG="usbcfg",<vid>,<pid>,<diag>,<nmea>,<at_port>,<modem>,<rmnet>,<adb>.
> In other words, you set which interfaces to enable/disable. Based on
> my testing, it is only possible to enable/disable diag, rmnet (QMI)
> and adb, as well as nmea, at_port and modem together. I.e., it is not
> possible to only disable for example nmea.
> 

> If I for example disable diag, then the bInterfaceNumber of nmea
> changes from 1 to 0, at from 2 to 1, etc., etc.
> 
> BR,
> Kristian
>

This also becomes a mess for the qmi-wwan driver which has the rmnet/qmi 
interface hardcoded to 4 so that driver will also need a workaround.
Quectel seems to have completely missed the reason why usb id's should 
be unique and not reused  for a different product or a different 
interface layout, there is already a workaround in qmi-wwan for their 
previous EC-20 card...
My opinion is that the option and qmi-wwan drivers should support EP06 
in the factory delivery configuration and not in a configuration the 
user has selected with a Quectel proprietary AT cmd.
Can you give some good reason for disabling an interface instead of 
letting it stay but not use it if you don't need it?


Thanks
/Lars
Kristian Evensen Sept. 11, 2018, 2:34 p.m. UTC | #5
On Tue, Sep 11, 2018 at 4:00 PM Lars Melin <larsm17@gmail.com> wrote:
> This also becomes a mess for the qmi-wwan driver which has the rmnet/qmi
> interface hardcoded to 4 so that driver will also need a workaround.
> Quectel seems to have completely missed the reason why usb id's should
> be unique and not reused  for a different product or a different
> interface layout, there is already a workaround in qmi-wwan for their
> previous EC-20 card...

A patch has already been submitted to work around the issue in qmi driver.

> My opinion is that the option and qmi-wwan drivers should support EP06
> in the factory delivery configuration and not in a configuration the
> user has selected with a Quectel proprietary AT cmd.
> Can you give some good reason for disabling an interface instead of
> letting it stay but not use it if you don't need it?

Yes. I am working with two boards, one based on MT7621 and the other
on MT7623, and I would like to connect two EP06-modems to these
boards. However, the USB-controller used on these SoCs has a (very)
limited number of USB endpoints. With the default configuration, there
are only enough endpoints for one EP06-modem to work properly. By
disabling diag, there are enough endpoints for both modems to work
correctly.

BR,
Kristian
Lars Melin Sept. 12, 2018, 4:32 p.m. UTC | #6
On 9/11/2018 21:34, Kristian Evensen wrote:
> On Tue, Sep 11, 2018 at 4:00 PM Lars Melin <larsm17@gmail.com> wrote:

>> My opinion is that the option and qmi-wwan drivers should support EP06
>> in the factory delivery configuration and not in a configuration the
>> user has selected with a Quectel proprietary AT cmd.
>> Can you give some good reason for disabling an interface instead of
>> letting it stay but not use it if you don't need it?
> 
> Yes. I am working with two boards, one based on MT7621 and the other
> on MT7623, and I would like to connect two EP06-modems to these
> boards. However, the USB-controller used on these SoCs has a (very)
> limited number of USB endpoints. With the default configuration, there
> are only enough endpoints for one EP06-modem to work properly. By
> disabling diag, there are enough endpoints for both modems to work
> correctly.
> 
> BR,
> Kristian
> 

You have chosen a platform which has limited usb resources and want to 
solve that problem by adjusting the device driver?
Why don't you just unbind those interfaces which you are not using and
which are eating up your usb resources?

Thanks
/Lars
Kristian Evensen Sept. 12, 2018, 4:57 p.m. UTC | #7
On Wed, Sep 12, 2018 at 6:32 PM Lars Melin <larsm17@gmail.com> wrote:
> You have chosen a platform which has limited usb resources and want to
> solve that problem by adjusting the device driver?

No, you asked for a good reason for why disabling and not just
ignoring an interface makes sense, and I think that supporting
multiple EP06 on platforms with limited endpoints qualifies as a
reason. My motivation behind this patch and modifying the driver, is
to make the driver work with the different options/combinations
supported by the modem. The platforms I am working on merely triggered
the error and inspired the change.

> Why don't you just unbind those interfaces which you are not using and
> which are eating up your usb resources?

As far as I know, unbinding interfaces from the driver does not free
up the memory allocated to the interface by/on the USB controller. I
also tried, just in case, and the output from lsusb is the same
regardless of bind/unbind.

Btw, the patch for the QMI driver has been accepted, since you
mentioned that driver earlier. So the assumption about interface four
is removed from there.

BR,
Kristian
Lars Melin Sept. 12, 2018, 6:25 p.m. UTC | #8
On 9/12/2018 23:57, Kristian Evensen wrote:
> On Wed, Sep 12, 2018 at 6:32 PM Lars Melin <larsm17@gmail.com> wrote:
>> You have chosen a platform which has limited usb resources and want to
>> solve that problem by adjusting the device driver?
> 
> No, you asked for a good reason for why disabling and not just
> ignoring an interface makes sense, and I think that supporting
> multiple EP06 on platforms with limited endpoints qualifies as a
> reason. My motivation behind this patch and modifying the driver, is
> to make the driver work with the different options/combinations
> supported by the modem. The platforms I am working on merely triggered
> the error and inspired the change.
> 
>> Why don't you just unbind those interfaces which you are not using and
>> which are eating up your usb resources?
> 
> As far as I know, unbinding interfaces from the driver does not free
> up the memory allocated to the interface by/on the USB controller. I
> also tried, just in case, and the output from lsusb is the same
> regardless of bind/unbind.
> 
> Btw, the patch for the QMI driver has been accepted, since you
> mentioned that driver earlier. So the assumption about interface four
> is removed from there.
> 
> BR,
> Kristian
> 

That the patch has qmi-wwan patch has been accepted does not change the 
fact that you are solving your problems in the wrong end.
You are using the OEM re-branding AT cmd to change the interface 
composition without changing the vid and pid at the same time, this is a 
big donut and the whole reason for why you have submitted patches which 
shouldn't be needed.


rgds
/Lars
Dan Williams Sept. 12, 2018, 7:18 p.m. UTC | #9
On Thu, 2018-09-13 at 01:25 +0700, Lars Melin wrote:
> On 9/12/2018 23:57, Kristian Evensen wrote:
> > On Wed, Sep 12, 2018 at 6:32 PM Lars Melin <larsm17@gmail.com>
> > wrote:
> > > You have chosen a platform which has limited usb resources and
> > > want to
> > > solve that problem by adjusting the device driver?
> > 
> > No, you asked for a good reason for why disabling and not just
> > ignoring an interface makes sense, and I think that supporting
> > multiple EP06 on platforms with limited endpoints qualifies as a
> > reason. My motivation behind this patch and modifying the driver,
> > is
> > to make the driver work with the different options/combinations
> > supported by the modem. The platforms I am working on merely
> > triggered
> > the error and inspired the change.
> > 
> > > Why don't you just unbind those interfaces which you are not
> > > using and
> > > which are eating up your usb resources?
> > 
> > As far as I know, unbinding interfaces from the driver does not
> > free
> > up the memory allocated to the interface by/on the USB controller.
> > I
> > also tried, just in case, and the output from lsusb is the same
> > regardless of bind/unbind.
> > 
> > Btw, the patch for the QMI driver has been accepted, since you
> > mentioned that driver earlier. So the assumption about interface
> > four
> > is removed from there.
> > 
> > BR,
> > Kristian
> > 
> 
> That the patch has qmi-wwan patch has been accepted does not change
> the 
> fact that you are solving your problems in the wrong end.
> You are using the OEM re-branding AT cmd to change the interface 
> composition without changing the vid and pid at the same time, this
> is a 
> big donut and the whole reason for why you have submitted patches
> which 
> shouldn't be needed.

The fact that the firmware implementation has the ability to change the
endpoints is unrelated to Kristian's case, and that alone is
justification for this to be quirked in the driver.  People other than
Kristian will undoubtedly use the functionality, on platforms less
limited.

Also most Huawei modems have the ability to change their layout and
configuration just like the EP06 via the U2DIAG and SETPORT commands.

Dan
Bjørn Mork Sept. 12, 2018, 8:34 p.m. UTC | #10
Dan Williams <dcbw@redhat.com> writes:

> The fact that the firmware implementation has the ability to change the
> endpoints is unrelated to Kristian's case, and that alone is
> justification for this to be quirked in the driver.  People other than
> Kristian will undoubtedly use the functionality, on platforms less
> limited.

FWIW, I agree with Dan and Kristian on this. It's a documented feature,
and it will be used. The reasons are irrelevant. The firmware
implementation is inconvenient, but we should still strive to make it
Just Work in Linux.  Kristian's solution does that.

> Also most Huawei modems have the ability to change their layout and
> configuration just like the EP06 via the U2DIAG and SETPORT commands.

Yes, but they are nice enough to use unique class/subclass/protocol
triplets for their functions so it's easy to support the changing
layout.  At least as long as they use their own VID and not some laptop
vendor's..

The Sierra Wireless strategy, using fixed interface numbers leaving
"holes" is another fine solution to the problem.  Or they could have
allocated unique VIDs per function combination, as long as the number of
valid combinations are low.  But they didn't.  It's not like it's the
first bad firmware design we've had to deal with.  Let's just work
around it, like we always do.  No need to make life difficult for end
users just because Quectel makes life difficult for us.


Bjørn
Johan Hovold Sept. 13, 2018, 9:17 a.m. UTC | #11
On Wed, Sep 12, 2018 at 10:34:43PM +0200, Bjørn Mork wrote:
> Dan Williams <dcbw@redhat.com> writes:
> 
> > The fact that the firmware implementation has the ability to change the
> > endpoints is unrelated to Kristian's case, and that alone is
> > justification for this to be quirked in the driver.  People other than
> > Kristian will undoubtedly use the functionality, on platforms less
> > limited.
> 
> FWIW, I agree with Dan and Kristian on this. It's a documented feature,
> and it will be used. The reasons are irrelevant. The firmware
> implementation is inconvenient, but we should still strive to make it
> Just Work in Linux.  Kristian's solution does that.
>
> > Also most Huawei modems have the ability to change their layout and
> > configuration just like the EP06 via the U2DIAG and SETPORT commands.
> 
> Yes, but they are nice enough to use unique class/subclass/protocol
> triplets for their functions so it's easy to support the changing
> layout.  At least as long as they use their own VID and not some laptop
> vendor's..
> 
> The Sierra Wireless strategy, using fixed interface numbers leaving
> "holes" is another fine solution to the problem.  Or they could have
> allocated unique VIDs per function combination, as long as the number of
> valid combinations are low.  But they didn't.  It's not like it's the
> first bad firmware design we've had to deal with.  Let's just work
> around it, like we always do.  No need to make life difficult for end
> users just because Quectel makes life difficult for us.

Ok, thanks for everyone for your input. As Lars I was sceptical about
this, but if this is contained to Quectel and we have a solutions which
hopefully covers all permutations for their other devices, let's go
along with this.

I'd prefer seeing this contained in the device-id table as far as
possible rather than maintaining a second table of product ids in
probe() so I've cooked up a patch (on top of this one) adding a new
device-id match flag.

Kristian would you mind giving it a try? 

Oh, also note that I dropped the RSVD(5) for the ADB interface in your
patch since it uses a different subclass anyway. I'll submit both
patches in a series.

Thanks,
Johan
Kristian Evensen Sept. 13, 2018, 9:44 a.m. UTC | #12
Hi Johan,

On Thu, Sep 13, 2018 at 11:17 AM Johan Hovold <johan@kernel.org> wrote:
> Kristian would you mind giving it a try?

Yes, thank you very much. I will give the patches a go during the day
today and report back.

> Oh, also note that I dropped the RSVD(5) for the ADB interface in your
> patch since it uses a different subclass anyway. I'll submit both
> patches in a series.

Thanks, I completely forgot about that.

BR,
Kristian
Kristian Evensen Sept. 13, 2018, 3:13 p.m. UTC | #13
Hello again,

On Thu, Sep 13, 2018 at 11:17 AM Johan Hovold <johan@kernel.org> wrote:
> Kristian would you mind giving it a try?

I just finished backporting + testing your patch with our 4.14-kernel
(mine is already there) and it works great. The driver correctly
handles different EP06-configurations.

Thanks a lot!

BR,
Kristian
Johan Hovold Sept. 14, 2018, 7:51 a.m. UTC | #14
On Thu, Sep 13, 2018 at 05:13:02PM +0200, Kristian Evensen wrote:

> I just finished backporting + testing your patch with our 4.14-kernel
> (mine is already there) and it works great. The driver correctly
> handles different EP06-configurations.

Great, thanks for testing. Do you mind if I add your tested-by to the
patch?

Johan
Kristian Evensen Sept. 14, 2018, 7:53 a.m. UTC | #15
Hi Johan,
On Fri, Sep 14, 2018 at 9:51 AM Johan Hovold <johan@kernel.org> wrote:
> Great, thanks for testing. Do you mind if I add your tested-by to the
> patch?

Not at all, go right ahead! I should probably have replied to the
patch with a Tested-by. Sorry about forgetting that.

BR,
Kristian
Johan Hovold Sept. 14, 2018, 8:42 a.m. UTC | #16
On Fri, Sep 14, 2018 at 09:53:31AM +0200, Kristian Evensen wrote:
> Hi Johan,
> On Fri, Sep 14, 2018 at 9:51 AM Johan Hovold <johan@kernel.org> wrote:
> > Great, thanks for testing. Do you mind if I add your tested-by to the
> > patch?
> 
> Not at all, go right ahead! I should probably have replied to the
> patch with a Tested-by. Sorry about forgetting that.

No problem at all, I've applied these for 4.19-rc now.

Thanks,
Johan
diff mbox series

Patch

diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 0215b70c4efc..835dcd2875a7 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1081,8 +1081,9 @@  static const struct usb_device_id option_ids[] = {
 	  .driver_info = RSVD(4) },
 	{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
 	  .driver_info = RSVD(4) },
-	{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06),
-	  .driver_info = RSVD(4) | RSVD(5) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
+	  .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | RSVD(5) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },
 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
@@ -1985,6 +1986,7 @@  static int option_probe(struct usb_serial *serial,
 {
 	struct usb_interface_descriptor *iface_desc =
 				&serial->interface->cur_altsetting->desc;
+	struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;
 	unsigned long device_flags = id->driver_info;
 
 	/* Never bind to the CD-Rom emulation interface	*/
@@ -1999,6 +2001,17 @@  static int option_probe(struct usb_serial *serial,
 	if (device_flags & RSVD(iface_desc->bInterfaceNumber))
 		return -ENODEV;
 
+	/*
+	 * Don't bind to the QMI device of the Quectel EP06/EG06/EM06. Class,
+	 * subclass and protocol is 0xff for both the diagnostic port and the
+	 * QMI interface, but the diagnostic port only has two endpoints (QMI
+	 * has three).
+	 */
+	if (dev_desc->idVendor == cpu_to_le16(QUECTEL_VENDOR_ID) &&
+	    dev_desc->idProduct == cpu_to_le16(QUECTEL_PRODUCT_EP06) &&
+	    iface_desc->bInterfaceSubClass && iface_desc->bNumEndpoints == 3)
+		return -ENODEV;
+
 	/* Store the device flags so we can use them during attach. */
 	usb_set_serial_data(serial, (void *)device_flags);