Commit bd877e48 authored by Bjørn Mork's avatar Bjørn Mork Committed by David S. Miller

net: qmi_wwan: use a single bind function for all device types

Refactoring the bind code lets us use a common driver_info struct
for all supported devices, simplifying the code a bit.  The
real advantage is that devices using the CDC ECM interface
layout now also can be added dynamically using the new_id sysfs
interface.  This simplifies testing of new devices.
Signed-off-by: default avatarBjørn Mork <bjorn@mork.no>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3ee24037
...@@ -139,10 +139,18 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) ...@@ -139,10 +139,18 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state))); BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state)));
/* require a single interrupt status endpoint for subdriver */ /* control and data is shared? */
if (intf->cur_altsetting->desc.bNumEndpoints == 3) {
info->control = intf;
info->data = intf;
goto shared;
}
/* else require a single interrupt status endpoint on control intf */
if (intf->cur_altsetting->desc.bNumEndpoints != 1) if (intf->cur_altsetting->desc.bNumEndpoints != 1)
goto err; goto err;
/* and a number of CDC descriptors */
while (len > 3) { while (len > 3) {
struct usb_descriptor_header *h = (void *)buf; struct usb_descriptor_header *h = (void *)buf;
...@@ -231,8 +239,9 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) ...@@ -231,8 +239,9 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
if (status < 0) if (status < 0)
goto err; goto err;
shared:
status = qmi_wwan_register_subdriver(dev); status = qmi_wwan_register_subdriver(dev);
if (status < 0) { if (status < 0 && info->control != info->data) {
usb_set_intfdata(info->data, NULL); usb_set_intfdata(info->data, NULL);
usb_driver_release_interface(driver, info->data); usb_driver_release_interface(driver, info->data);
} }
...@@ -241,20 +250,6 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) ...@@ -241,20 +250,6 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
return status; return status;
} }
/* Some devices combine the "control" and "data" functions into a
* single interface with all three endpoints: interrupt + bulk in and
* out
*/
static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf)
{
struct qmi_wwan_state *info = (void *)&dev->data;
/* control and data is shared */
info->control = intf;
info->data = intf;
return qmi_wwan_register_subdriver(dev);
}
static void qmi_wwan_unbind(struct usbnet *dev, struct usb_interface *intf) static void qmi_wwan_unbind(struct usbnet *dev, struct usb_interface *intf)
{ {
struct qmi_wwan_state *info = (void *)&dev->data; struct qmi_wwan_state *info = (void *)&dev->data;
...@@ -330,20 +325,12 @@ static const struct driver_info qmi_wwan_info = { ...@@ -330,20 +325,12 @@ static const struct driver_info qmi_wwan_info = {
.manage_power = qmi_wwan_manage_power, .manage_power = qmi_wwan_manage_power,
}; };
static const struct driver_info qmi_wwan_shared = {
.description = "WWAN/QMI device",
.flags = FLAG_WWAN,
.bind = qmi_wwan_bind_shared,
.unbind = qmi_wwan_unbind,
.manage_power = qmi_wwan_manage_power,
};
#define HUAWEI_VENDOR_ID 0x12D1 #define HUAWEI_VENDOR_ID 0x12D1
/* map QMI/wwan function by a fixed interface number */ /* map QMI/wwan function by a fixed interface number */
#define QMI_FIXED_INTF(vend, prod, num) \ #define QMI_FIXED_INTF(vend, prod, num) \
USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \ USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \
.driver_info = (unsigned long)&qmi_wwan_shared .driver_info = (unsigned long)&qmi_wwan_info
/* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */ /* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */
#define QMI_GOBI1K_DEVICE(vend, prod) \ #define QMI_GOBI1K_DEVICE(vend, prod) \
...@@ -367,15 +354,15 @@ static const struct usb_device_id products[] = { ...@@ -367,15 +354,15 @@ static const struct usb_device_id products[] = {
/* 2. Combined interface devices matching on class+protocol */ /* 2. Combined interface devices matching on class+protocol */
{ /* Huawei E392, E398 and possibly others in "Windows mode" */ { /* Huawei E392, E398 and possibly others in "Windows mode" */
USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17), USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17),
.driver_info = (unsigned long)&qmi_wwan_shared, .driver_info = (unsigned long)&qmi_wwan_info,
}, },
{ /* Pantech UML290 */ { /* Pantech UML290 */
USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff), USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff),
.driver_info = (unsigned long)&qmi_wwan_shared, .driver_info = (unsigned long)&qmi_wwan_info,
}, },
{ /* Pantech UML290 - newer firmware */ { /* Pantech UML290 - newer firmware */
USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff), USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff),
.driver_info = (unsigned long)&qmi_wwan_shared, .driver_info = (unsigned long)&qmi_wwan_info,
}, },
/* 3. Combined interface devices matching on interface number */ /* 3. Combined interface devices matching on interface number */
...@@ -457,7 +444,7 @@ static int qmi_wwan_probe(struct usb_interface *intf, const struct usb_device_id ...@@ -457,7 +444,7 @@ static int qmi_wwan_probe(struct usb_interface *intf, const struct usb_device_id
*/ */
if (!id->driver_info) { if (!id->driver_info) {
dev_dbg(&intf->dev, "setting defaults for dynamic device id\n"); dev_dbg(&intf->dev, "setting defaults for dynamic device id\n");
id->driver_info = (unsigned long)&qmi_wwan_shared; id->driver_info = (unsigned long)&qmi_wwan_info;
} }
return usbnet_probe(intf, id); return usbnet_probe(intf, id);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment