aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/qmi_wwan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/usb/qmi_wwan.c')
-rw-r--r--drivers/net/usb/qmi_wwan.c49
1 files changed, 16 insertions, 33 deletions
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index efb5c7c33a28..968d5d50751d 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -139,16 +139,9 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
139 139
140 BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state))); 140 BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state)));
141 141
142 /* control and data is shared? */ 142 /* set up initial state */
143 if (intf->cur_altsetting->desc.bNumEndpoints == 3) { 143 info->control = intf;
144 info->control = intf; 144 info->data = intf;
145 info->data = intf;
146 goto shared;
147 }
148
149 /* else require a single interrupt status endpoint on control intf */
150 if (intf->cur_altsetting->desc.bNumEndpoints != 1)
151 goto err;
152 145
153 /* and a number of CDC descriptors */ 146 /* and a number of CDC descriptors */
154 while (len > 3) { 147 while (len > 3) {
@@ -207,25 +200,14 @@ next_desc:
207 buf += h->bLength; 200 buf += h->bLength;
208 } 201 }
209 202
210 /* did we find all the required ones? */ 203 /* Use separate control and data interfaces if we found a CDC Union */
211 if (!(found & (1 << USB_CDC_HEADER_TYPE)) || 204 if (cdc_union) {
212 !(found & (1 << USB_CDC_UNION_TYPE))) { 205 info->data = usb_ifnum_to_if(dev->udev, cdc_union->bSlaveInterface0);
213 dev_err(&intf->dev, "CDC functional descriptors missing\n"); 206 if (desc->bInterfaceNumber != cdc_union->bMasterInterface0 || !info->data) {
214 goto err; 207 dev_err(&intf->dev, "bogus CDC Union: master=%u, slave=%u\n",
215 } 208 cdc_union->bMasterInterface0, cdc_union->bSlaveInterface0);
216 209 goto err;
217 /* verify CDC Union */ 210 }
218 if (desc->bInterfaceNumber != cdc_union->bMasterInterface0) {
219 dev_err(&intf->dev, "bogus CDC Union: master=%u\n", cdc_union->bMasterInterface0);
220 goto err;
221 }
222
223 /* need to save these for unbind */
224 info->control = intf;
225 info->data = usb_ifnum_to_if(dev->udev, cdc_union->bSlaveInterface0);
226 if (!info->data) {
227 dev_err(&intf->dev, "bogus CDC Union: slave=%u\n", cdc_union->bSlaveInterface0);
228 goto err;
229 } 211 }
230 212
231 /* errors aren't fatal - we can live with the dynamic address */ 213 /* errors aren't fatal - we can live with the dynamic address */
@@ -235,11 +217,12 @@ next_desc:
235 } 217 }
236 218
237 /* claim data interface and set it up */ 219 /* claim data interface and set it up */
238 status = usb_driver_claim_interface(driver, info->data, dev); 220 if (info->control != info->data) {
239 if (status < 0) 221 status = usb_driver_claim_interface(driver, info->data, dev);
240 goto err; 222 if (status < 0)
223 goto err;
224 }
241 225
242shared:
243 status = qmi_wwan_register_subdriver(dev); 226 status = qmi_wwan_register_subdriver(dev);
244 if (status < 0 && info->control != info->data) { 227 if (status < 0 && info->control != info->data) {
245 usb_set_intfdata(info->data, NULL); 228 usb_set_intfdata(info->data, NULL);