diff options
Diffstat (limited to 'drivers/usb')
73 files changed, 1295 insertions, 301 deletions
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 635cf0466b59..e9fed9a88737 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -350,7 +350,7 @@ struct l1_code { u8 string_header[E4_L1_STRING_HEADER]; u8 page_number_to_block_index[E4_MAX_PAGE_NUMBER]; struct block_index page_header[E4_NO_SWAPPAGE_HEADERS]; - u8 code[0]; + u8 code[]; } __packed; /* structures describing a block within a DSP page */ diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h index d3bdc4cc47aa..8725755bd53d 100644 --- a/drivers/usb/atm/usbatm.h +++ b/drivers/usb/atm/usbatm.h @@ -164,7 +164,7 @@ struct usbatm_data { unsigned char *cell_buf; /* holds partial rx cell */ unsigned int buf_usage; - struct urb *urbs[0]; + struct urb *urbs[]; }; static inline void *to_usbatm_driver_data(struct usb_interface *intf) diff --git a/drivers/usb/cdns3/core.c b/drivers/usb/cdns3/core.c index c2123ef8d8a3..4aafba20f450 100644 --- a/drivers/usb/cdns3/core.c +++ b/drivers/usb/cdns3/core.c @@ -330,9 +330,9 @@ exit: * * Returns role */ -static enum usb_role cdns3_role_get(struct device *dev) +static enum usb_role cdns3_role_get(struct usb_role_switch *sw) { - struct cdns3 *cdns = dev_get_drvdata(dev); + struct cdns3 *cdns = usb_role_switch_get_drvdata(sw); return cdns->role; } @@ -346,9 +346,9 @@ static enum usb_role cdns3_role_get(struct device *dev) * - Role switch for dual-role devices * - USB_ROLE_GADGET <--> USB_ROLE_NONE for peripheral-only devices */ -static int cdns3_role_set(struct device *dev, enum usb_role role) +static int cdns3_role_set(struct usb_role_switch *sw, enum usb_role role) { - struct cdns3 *cdns = dev_get_drvdata(dev); + struct cdns3 *cdns = usb_role_switch_get_drvdata(sw); int ret = 0; pm_runtime_get_sync(cdns->dev); @@ -423,12 +423,6 @@ pm_put: return ret; } -static const struct usb_role_switch_desc cdns3_switch_desc = { - .set = cdns3_role_set, - .get = cdns3_role_get, - .allow_userspace_control = true, -}; - /** * cdns3_probe - probe for cdns3 core device * @pdev: Pointer to cdns3 core platform device @@ -437,6 +431,7 @@ static const struct usb_role_switch_desc cdns3_switch_desc = { */ static int cdns3_probe(struct platform_device *pdev) { + struct usb_role_switch_desc sw_desc = { }; struct device *dev = &pdev->dev; struct resource *res; struct cdns3 *cdns; @@ -529,7 +524,12 @@ static int cdns3_probe(struct platform_device *pdev) if (ret) goto err3; - cdns->role_sw = usb_role_switch_register(dev, &cdns3_switch_desc); + sw_desc.set = cdns3_role_set; + sw_desc.get = cdns3_role_get; + sw_desc.allow_userspace_control = true; + sw_desc.driver_data = cdns; + + cdns->role_sw = usb_role_switch_register(dev, &sw_desc); if (IS_ERR(cdns->role_sw)) { ret = PTR_ERR(cdns->role_sw); dev_warn(dev, "Unable to register Role Switch\n"); diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c index 3574dbb09366..372460ea4df9 100644 --- a/drivers/usb/cdns3/gadget.c +++ b/drivers/usb/cdns3/gadget.c @@ -1380,7 +1380,7 @@ static bool cdns3_request_handled(struct cdns3_endpoint *priv_ep, struct cdns3_request *priv_req) { struct cdns3_device *priv_dev = priv_ep->cdns3_dev; - struct cdns3_trb *trb = priv_req->trb; + struct cdns3_trb *trb; int current_index = 0; int handled = 0; int doorbell; diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 52139c2a9924..ae0bdc036464 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -600,9 +600,9 @@ static int ci_cable_notifier(struct notifier_block *nb, unsigned long event, return NOTIFY_DONE; } -static enum usb_role ci_usb_role_switch_get(struct device *dev) +static enum usb_role ci_usb_role_switch_get(struct usb_role_switch *sw) { - struct ci_hdrc *ci = dev_get_drvdata(dev); + struct ci_hdrc *ci = usb_role_switch_get_drvdata(sw); enum usb_role role; unsigned long flags; @@ -613,9 +613,10 @@ static enum usb_role ci_usb_role_switch_get(struct device *dev) return role; } -static int ci_usb_role_switch_set(struct device *dev, enum usb_role role) +static int ci_usb_role_switch_set(struct usb_role_switch *sw, + enum usb_role role) { - struct ci_hdrc *ci = dev_get_drvdata(dev); + struct ci_hdrc *ci = usb_role_switch_get_drvdata(sw); struct ci_hdrc_cable *cable = NULL; enum usb_role current_role = ci_role_to_usb_role(ci); enum ci_role ci_role = usb_role_to_ci_role(role); @@ -1118,6 +1119,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) } if (ci_role_switch.fwnode) { + ci_role_switch.driver_data = ci; ci->role_switch = usb_role_switch_register(dev, &ci_role_switch); if (IS_ERR(ci->role_switch)) { diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 2b27d232d7a7..f81606c6a35b 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -261,9 +261,19 @@ static int usb_probe_device(struct device *dev) */ if (!udriver->supports_autosuspend) error = usb_autoresume_device(udev); + if (error) + return error; - if (!error) - error = udriver->probe(udev); + if (udriver->generic_subclass) + error = usb_generic_driver_probe(udev); + if (error) + return error; + + error = udriver->probe(udev); + if (error == -ENODEV && udriver != &usb_generic_driver) { + udev->use_generic_driver = 1; + return -EPROBE_DEFER; + } return error; } @@ -273,7 +283,10 @@ static int usb_unbind_device(struct device *dev) struct usb_device *udev = to_usb_device(dev); struct usb_device_driver *udriver = to_usb_device_driver(dev->driver); - udriver->disconnect(udev); + if (udriver->disconnect) + udriver->disconnect(udev); + if (udriver->generic_subclass) + usb_generic_driver_disconnect(udev); if (!udriver->supports_autosuspend) usb_autosuspend_device(udev); return 0; @@ -790,17 +803,42 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface, } EXPORT_SYMBOL_GPL(usb_match_id); +const struct usb_device_id *usb_device_match_id(struct usb_device *udev, + const struct usb_device_id *id) +{ + if (!id) + return NULL; + + for (; id->idVendor || id->idProduct ; id++) { + if (usb_match_device(udev, id)) + return id; + } + + return NULL; +} + static int usb_device_match(struct device *dev, struct device_driver *drv) { /* devices and interfaces are handled separately */ if (is_usb_device(dev)) { + struct usb_device *udev; + struct usb_device_driver *udrv; /* interface drivers never match devices */ if (!is_usb_device_driver(drv)) return 0; - /* TODO: Add real matching code */ - return 1; + udev = to_usb_device(dev); + udrv = to_usb_device_driver(drv); + + if (udrv->id_table && + usb_device_match_id(udev, udrv->id_table) != NULL) { + return 1; + } + + if (udrv->match) + return udrv->match(udev); + return 0; } else if (is_usb_interface(dev)) { struct usb_interface *intf; @@ -1149,7 +1187,10 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg) udev->do_remote_wakeup = 0; udriver = &usb_generic_driver; } - status = udriver->suspend(udev, msg); + if (udriver->suspend) + status = udriver->suspend(udev, msg); + if (status == 0 && udriver->generic_subclass) + status = usb_generic_driver_suspend(udev, msg); done: dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status); @@ -1181,7 +1222,10 @@ static int usb_resume_device(struct usb_device *udev, pm_message_t msg) udev->reset_resume = 1; udriver = to_usb_device_driver(udev->dev.driver); - status = udriver->resume(udev, msg); + if (udriver->generic_subclass) + status = usb_generic_driver_resume(udev, msg); + if (status == 0 && udriver->resume) + status = udriver->resume(udev, msg); done: dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status); diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 38f8b3e31762..4626227a6dd2 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -195,7 +195,38 @@ int usb_choose_configuration(struct usb_device *udev) } EXPORT_SYMBOL_GPL(usb_choose_configuration); -static int generic_probe(struct usb_device *udev) +static int __check_usb_generic(struct device_driver *drv, void *data) +{ + struct usb_device *udev = data; + struct usb_device_driver *udrv; + + if (!is_usb_device_driver(drv)) + return 0; + udrv = to_usb_device_driver(drv); + if (udrv == &usb_generic_driver) + return 0; + if (!udrv->id_table) + return 0; + + return usb_device_match_id(udev, udrv->id_table) != NULL; +} + +static bool usb_generic_driver_match(struct usb_device *udev) +{ + if (udev->use_generic_driver) + return true; + + /* + * If any other driver wants the device, leave the device to this other + * driver. + */ + if (bus_for_each_drv(&usb_bus_type, NULL, udev, __check_usb_generic)) + return false; + + return true; +} + +int usb_generic_driver_probe(struct usb_device *udev) { int err, c; @@ -222,7 +253,7 @@ static int generic_probe(struct usb_device *udev) return 0; } -static void generic_disconnect(struct usb_device *udev) +void usb_generic_driver_disconnect(struct usb_device *udev) { usb_notify_remove_device(udev); @@ -234,7 +265,7 @@ static void generic_disconnect(struct usb_device *udev) #ifdef CONFIG_PM -static int generic_suspend(struct usb_device *udev, pm_message_t msg) +int usb_generic_driver_suspend(struct usb_device *udev, pm_message_t msg) { int rc; @@ -262,7 +293,7 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg) return rc; } -static int generic_resume(struct usb_device *udev, pm_message_t msg) +int usb_generic_driver_resume(struct usb_device *udev, pm_message_t msg) { int rc; @@ -285,11 +316,12 @@ static int generic_resume(struct usb_device *udev, pm_message_t msg) struct usb_device_driver usb_generic_driver = { .name = "usb", - .probe = generic_probe, - .disconnect = generic_disconnect, + .match = usb_generic_driver_match, + .probe = usb_generic_driver_probe, + .disconnect = usb_generic_driver_disconnect, #ifdef CONFIG_PM - .suspend = generic_suspend, - .resume = generic_resume, + .suspend = usb_generic_driver_suspend, + .resume = usb_generic_driver_resume, #endif .supports_autosuspend = 1, }; diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index f19694e69f5c..9f4320b9d7fc 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -849,7 +849,7 @@ static struct attribute *dev_string_attrs[] = { static umode_t dev_string_attrs_are_visible(struct kobject *kobj, struct attribute *a, int n) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct usb_device *udev = to_usb_device(dev); if (a == &dev_attr_manufacturer.attr) { @@ -883,7 +883,7 @@ read_descriptors(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct usb_device *udev = to_usb_device(dev); size_t nleft = count; size_t srclen, n; @@ -1233,7 +1233,7 @@ static struct attribute *intf_assoc_attrs[] = { static umode_t intf_assoc_attrs_are_visible(struct kobject *kobj, struct attribute *a, int n) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct usb_interface *intf = to_usb_interface(dev); if (intf->intf_assoc == NULL) diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index 9043d7242d67..50b2fc7fcc0e 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -86,7 +86,7 @@ static enum usb_port_connect_type usb_acpi_get_connect_type(acpi_handle handle, { enum usb_port_connect_type connect_type = USB_PORT_CONNECT_TYPE_UNKNOWN; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *upc; + union acpi_object *upc = NULL; acpi_status status; /* @@ -98,11 +98,12 @@ static enum usb_port_connect_type usb_acpi_get_connect_type(acpi_handle handle, * no connectable, the port would be not used. */ status = acpi_evaluate_object(handle, "_UPC", NULL, &buffer); + if (ACPI_FAILURE(status)) + goto out; + upc = buffer.pointer; - if (!upc || (upc->type != ACPI_TYPE_PACKAGE) - || upc->package.count != 4) { + if (!upc || (upc->type != ACPI_TYPE_PACKAGE) || upc->package.count != 4) goto out; - } if (upc->package.elements[0].integer.value) if (pld->user_visible) @@ -186,7 +187,7 @@ usb_acpi_find_companion_for_port(struct usb_port *port_dev) handle = adev->handle; status = acpi_get_physical_device_location(handle, &pld); - if (!ACPI_FAILURE(status) && pld) { + if (ACPI_SUCCESS(status) && pld) { port_dev->location = USB_ACPI_LOCATION_VALID | pld->group_token << 8 | pld->group_position; port_dev->connect_type = usb_acpi_get_connect_type(handle, pld); diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 3ad0ee57e859..64ed4023a8c8 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -50,6 +50,12 @@ extern void usb_release_bos_descriptor(struct usb_device *dev); extern char *usb_cache_string(struct usb_device *udev, int index); extern int usb_set_configuration(struct usb_device *dev, int configuration); extern int usb_choose_configuration(struct usb_device *udev); +extern int usb_generic_driver_probe(struct usb_device *udev); +extern void usb_generic_driver_disconnect(struct usb_device *udev); +extern int usb_generic_driver_suspend(struct usb_device *udev, + pm_message_t msg); +extern int usb_generic_driver_resume(struct usb_device *udev, + pm_message_t msg); static inline unsigned usb_get_max_power(struct usb_device *udev, struct usb_host_config *c) @@ -66,6 +72,8 @@ extern int usb_match_one_id_intf(struct usb_device *dev, const struct usb_device_id *id); extern int usb_match_device(struct usb_device *dev, const struct usb_device_id *id); +extern const stru |