diff mbox series

USB: serial: option: support dynamic Quectel USB compositions

Message ID 20200829134250.59118-1-bjorn@mork.no (mailing list archive)
State Accepted
Commit 2bb70f0a4b238323e4e2f392fc3ddeb5b7208c9e
Headers show
Series USB: serial: option: support dynamic Quectel USB compositions | expand

Commit Message

Bjørn Mork Aug. 29, 2020, 1:42 p.m. UTC
The USB composition, defining the set of exported functions, is dynamic
in newer Quectel modems.  Default functions can be disabled and
alternative functions can be enabled instead.  The alternatives
includes class functions using interface pairs, which should be
handled by the respective class drivers.

Active interfaces are numbered consecutively, so static
blacklisting based on interface numbers will fail when the
composition changes.  An example of such an error, where the
option driver has bound to the CDC ECM data interface,
preventing cdc_ether from handling this function:

 T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 0
 D: Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
 P: Vendor=2c7c ProdID=0125 Rev= 3.18
 S: Manufacturer=Quectel
 S: Product=EC25-AF
 C:* #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=500mA
 A: FirstIf#= 4 IfCount= 2 Cls=02(comm.) Sub=06 Prot=00
 I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
 E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
 E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
 E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
 E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
 E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
 E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
 E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 4 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=06 Prot=00 Driver=(none)
 E: Ad=89(I) Atr=03(Int.) MxPS= 16 Ivl=32ms
 I:* If#= 5 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=00 Driver=option
 I: If#= 5 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=option
 E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms

Another device with the same id gets correct drivers, since the
interface of the network function happens to be blacklisted by option:

 T: Bus=01 Lev=02 Prnt=02 Port=01 Cnt=01 Dev#= 3 Spd=480 MxCh= 0
 D: Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
 P: Vendor=2c7c ProdID=0125 Rev= 3.18
 S: Manufacturer=Android
 S: Product=Android
 C:* #Ifs= 5 Cfg#= 1 Atr=a0 MxPwr=500mA
 I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
 E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
 E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
 E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
 E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
 E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
 E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
 E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan
 E: Ad=89(I) Atr=03(Int.) MxPS= 8 Ivl=32ms
 E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms

Change rules for EC21, EC25, BG96 and EG95 to match vendor specific
serial functions only, to prevent binding to class functions. Require
2 endpoints on ff/ff/ff functions, avoiding the 3 endpoint QMI/RMNET
network functions.

Cc: AceLan Kao <acelan.kao@canonical.com>
Cc: Sebastian Sjoholm <ssjoholm@mac.com>
Cc: Dan Williams <dcbw@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Bjørn Mork <bjorn@mork.no>
---
 drivers/usb/serial/option.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

Comments

Sasha Levin Aug. 29, 2020, 9:59 p.m. UTC | #1
Hi

[This is an automated email]

This commit has been processed because it contains a -stable tag.
The stable tag indicates that it's relevant for the following trees: all

The bot has tested the following trees: v5.8.5, v5.4.61, v4.19.142, v4.14.195, v4.9.234, v4.4.234.

v5.8.5: Build OK!
v5.4.61: Build OK!
v4.19.142: Build OK!
v4.14.195: Build OK!
v4.9.234: Failed to apply! Possible dependencies:
    35aecc02b5b6 ("USB: serial: option: add two-endpoints device-id flag")
    36cae568404a ("USB: serial: option: improve Quectel EP06 detection")

v4.4.234: Failed to apply! Possible dependencies:
    35aecc02b5b6 ("USB: serial: option: add two-endpoints device-id flag")
    36cae568404a ("USB: serial: option: improve Quectel EP06 detection")


NOTE: The patch will not be queued to stable trees until it is upstream.

How should we proceed with this patch?
Johan Hovold Aug. 31, 2020, 6:44 a.m. UTC | #2
On Sat, Aug 29, 2020 at 03:42:50PM +0200, Bjørn Mork wrote:
> The USB composition, defining the set of exported functions, is dynamic
> in newer Quectel modems.  Default functions can be disabled and
> alternative functions can be enabled instead.  The alternatives
> includes class functions using interface pairs, which should be
> handled by the respective class drivers.
> 
> Active interfaces are numbered consecutively, so static
> blacklisting based on interface numbers will fail when the
> composition changes.  An example of such an error, where the
> option driver has bound to the CDC ECM data interface,
> preventing cdc_ether from handling this function:
> 
>  T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 0
>  D: Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
>  P: Vendor=2c7c ProdID=0125 Rev= 3.18
>  S: Manufacturer=Quectel
>  S: Product=EC25-AF
>  C:* #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=500mA
>  A: FirstIf#= 4 IfCount= 2 Cls=02(comm.) Sub=06 Prot=00
>  I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
>  E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  I:* If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
>  E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
>  E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
>  E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
>  E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
>  E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
>  E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  I:* If#= 4 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=06 Prot=00 Driver=(none)
>  E: Ad=89(I) Atr=03(Int.) MxPS= 16 Ivl=32ms
>  I:* If#= 5 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=00 Driver=option
>  I: If#= 5 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=option
>  E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
> 
> Another device with the same id gets correct drivers, since the
> interface of the network function happens to be blacklisted by option:
> 
>  T: Bus=01 Lev=02 Prnt=02 Port=01 Cnt=01 Dev#= 3 Spd=480 MxCh= 0
>  D: Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
>  P: Vendor=2c7c ProdID=0125 Rev= 3.18
>  S: Manufacturer=Android
>  S: Product=Android
>  C:* #Ifs= 5 Cfg#= 1 Atr=a0 MxPwr=500mA
>  I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
>  E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  I:* If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
>  E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
>  E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
>  E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
>  E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
>  E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
>  E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan
>  E: Ad=89(I) Atr=03(Int.) MxPS= 8 Ivl=32ms
>  E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
>  E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
> 
> Change rules for EC21, EC25, BG96 and EG95 to match vendor specific
> serial functions only, to prevent binding to class functions. Require
> 2 endpoints on ff/ff/ff functions, avoiding the 3 endpoint QMI/RMNET
> network functions.
> 
> Cc: AceLan Kao <acelan.kao@canonical.com>
> Cc: Sebastian Sjoholm <ssjoholm@mac.com>
> Cc: Dan Williams <dcbw@redhat.com>
> Cc: stable@vger.kernel.org
> Signed-off-by: Bjørn Mork <bjorn@mork.no>

Thanks, Bjørn. Now applied.

Johan
diff mbox series

Patch

diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 89b3192af326..6c3ece5dd9c9 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1094,14 +1094,18 @@  static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, UBLOX_PRODUCT_R410M),
 	  .driver_info = RSVD(1) | RSVD(3) },
 	/* Quectel products using Quectel vendor ID */
-	{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21),
-	  .driver_info = RSVD(4) },
-	{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25),
-	  .driver_info = RSVD(4) },
-	{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95),
-	  .driver_info = RSVD(4) },
-	{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
-	  .driver_info = RSVD(4) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21, 0xff, 0xff, 0xff),
+	  .driver_info = NUMEP2 },
+	{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21, 0xff, 0, 0) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25, 0xff, 0xff, 0xff),
+	  .driver_info = NUMEP2 },
+	{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25, 0xff, 0, 0) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0xff, 0xff),
+	  .driver_info = NUMEP2 },
+	{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0, 0) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96, 0xff, 0xff, 0xff),
+	  .driver_info = NUMEP2 },
+	{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96, 0xff, 0, 0) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
 	  .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
 	{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },