From 9992c2e2fbb72ffc63d4587c4aa94dfcd8229e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 21 Jan 2013 05:50:38 +0000 Subject: [PATCH 1/3] net: cdc_ncm: workaround for missing CDC Union MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding support for the MBIM mode in some Sierra Wireless devices. Some Sierra Wireless firmwares support CDC MBIM but have no CDC Union funtional descriptor. This violates the MBIM specification, but we can easily work around the bug by looking at the Interface Association Descriptor instead. This is most likely what Windows uses too, which explains how the firmware bug has gone unnoticed until now. This change will not affect any currently supported device conforming to the NCM or MBIM specifications, as they must have the CDC Union descriptor. Cc: Greg Suarez Cc: Alexey Orishko Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ncm.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 71b6e92b8e9b..4041159f6c98 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -344,6 +344,23 @@ static const struct ethtool_ops cdc_ncm_ethtool_ops = { .nway_reset = usbnet_nway_reset, }; +/* return first slave interface if an IAD matches the given master */ +static struct usb_interface *get_iad_slave(struct usb_device *udev, + struct usb_interface *master) { + int i; + struct usb_interface_assoc_descriptor *iad; + u8 mnum = master->cur_altsetting->desc.bInterfaceNumber; + + for (i = 0; i < USB_MAXIADS; i++) { + iad = udev->actconfig->intf_assoc[i]; + if (!iad) + break; + if (iad->bFirstInterface == mnum && iad->bInterfaceCount == 2) + return usb_ifnum_to_if(udev, mnum + 1); + } + return NULL; +} + int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting) { struct cdc_ncm_ctx *ctx; @@ -435,6 +452,16 @@ advance: len -= temp; } + /* some buggy devices have an IAD but no CDC Union */ + if (!ctx->union_desc) { + dev_dbg(&intf->dev, "missing CDC Union descriptor\n"); + ctx->data = get_iad_slave(dev->udev, intf); + if (ctx->data) { + ctx->control = intf; + dev_dbg(&intf->dev, "got slave from IAD\n"); + } + } + /* check if we got everything */ if ((ctx->control == NULL) || (ctx->data == NULL) || ((!ctx->mbim_desc) && ((ctx->ether_desc == NULL) || (ctx->control != intf)))) From 328d7b8a4ab045484e1cc09579abf13c8c6223e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 21 Jan 2013 05:50:39 +0000 Subject: [PATCH 2/3] net: cdc_mbim: send ZLP after max sized NTBs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We normally avoid sending ZLPs by padding NTBs with a zero byte if the NTB is shorter than dwNtbOutMaxSize, resulting in a short USB packet instead of a ZLP. But in the case where the NTB length is exactly dwNtbOutMaxSize and this is an exact multiplum of wMaxPacketSize, then we must send a ZLP. This fixes an issue seen on a Sierra Wireless MC7710 device where the transmission would fail whenever we ended up padding the NTBs to max size. Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/cdc_mbim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index 42f51c71ec1f..3a5673aa1c37 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c @@ -366,7 +366,7 @@ err: static const struct driver_info cdc_mbim_info = { .description = "CDC MBIM", - .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN, + .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN | FLAG_SEND_ZLP, .bind = cdc_mbim_bind, .unbind = cdc_mbim_unbind, .manage_power = cdc_mbim_manage_power, From 6b4ef60299e30daa8643218fde6152d8a01e2d4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 21 Jan 2013 05:50:40 +0000 Subject: [PATCH 3/3] net: cdc_ncm: fix error path for single interface probing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit bbc8d92 (net: cdc_ncm: add Huawei devices) implemented support for devices with a single combined control and data interface. Fix up the error path so that we do not double release such interfaces in case of probing failures. Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ncm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 4041159f6c98..2c4b41ffddb6 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -524,7 +524,8 @@ advance: error2: usb_set_intfdata(ctx->control, NULL); usb_set_intfdata(ctx->data, NULL); - usb_driver_release_interface(driver, ctx->data); + if (ctx->data != ctx->control) + usb_driver_release_interface(driver, ctx->data); error: cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]); dev->data[0] = 0;