aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/usb/cdc_mbim.c2
-rw-r--r--drivers/net/usb/cdc_ncm.c30
2 files changed, 30 insertions, 2 deletions
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index 42f51c7..3a5673a 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,
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 71b6e92..2c4b41f 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))))
@@ -497,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;