OSDN Git Service

Merge 5.6-rc3 into usb-next
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 24 Feb 2020 07:48:49 +0000 (08:48 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 24 Feb 2020 07:48:49 +0000 (08:48 +0100)
We need the USB fixes in here as well.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
75 files changed:
Documentation/ABI/testing/sysfs-class-typec
Documentation/driver-api/usb/typec_bus.rst
MAINTAINERS
drivers/thunderbolt/usb4.c
drivers/usb/atm/ueagle-atm.c
drivers/usb/atm/usbatm.h
drivers/usb/cdns3/gadget.c
drivers/usb/core/driver.c
drivers/usb/core/generic.c
drivers/usb/core/sysfs.c
drivers/usb/core/usb-acpi.c
drivers/usb/core/usb.h
drivers/usb/dwc2/hcd.h
drivers/usb/dwc3/dwc3-qcom.c
drivers/usb/gadget/function/f_phonet.c
drivers/usb/gadget/function/f_uac1_legacy.c
drivers/usb/gadget/legacy/gmidi.c
drivers/usb/gadget/legacy/inode.c
drivers/usb/gadget/udc/amd5536udc.h
drivers/usb/gadget/udc/amd5536udc_pci.c
drivers/usb/gadget/udc/at91_udc.c
drivers/usb/gadget/udc/dummy_hcd.c
drivers/usb/gadget/udc/fotg210-udc.c
drivers/usb/gadget/udc/fusb300_udc.c
drivers/usb/gadget/udc/goku_udc.c
drivers/usb/gadget/udc/lpc32xx_udc.c
drivers/usb/gadget/udc/m66592-udc.c
drivers/usb/gadget/udc/net2280.c
drivers/usb/gadget/udc/omap_udc.c
drivers/usb/gadget/udc/r8a66597-udc.c
drivers/usb/gadget/udc/renesas_usb3.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-platform.c
drivers/usb/host/ehci-tegra.c
drivers/usb/host/ehci.h
drivers/usb/host/fhci-hcd.c
drivers/usb/host/fotg210.h
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci.h
drivers/usb/host/sl811-hcd.c
drivers/usb/host/uhci-pci.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mtk.h
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-trace.h
drivers/usb/host/xhci.h
drivers/usb/misc/Kconfig
drivers/usb/misc/Makefile
drivers/usb/misc/apple-mfi-fastcharge.c [new file with mode: 0644]
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_host.c
drivers/usb/roles/class.c
drivers/usb/serial/io_usbvend.h
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/storage/usb.c
drivers/usb/storage/usb.h
drivers/usb/storage/usual-tables.c
drivers/usb/typec/bus.c
drivers/usb/typec/bus.h
drivers/usb/typec/class.c
drivers/usb/typec/mux.c
drivers/usb/typec/tcpm/tcpm.c
drivers/usb/typec/ucsi/ucsi.c
drivers/usb/typec/ucsi/ucsi.h
drivers/usb/typec/ucsi/ucsi_ccg.c
include/linux/usb.h
include/linux/usb/audio-v2.h
include/linux/usb/audio-v3.h
include/linux/usb/ehci_def.h
include/linux/usb/gadget.h
include/linux/usb/hcd.h
include/linux/usb/typec.h
include/linux/usb/typec_altmode.h
include/linux/usb_usual.h
include/linux/usbdevice_fs.h

index d7647b2..0c2eb26 100644 (file)
@@ -20,13 +20,13 @@ Date:               April 2017
 Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
 Description:
                The supported power roles. This attribute can be used to request
-               power role swap on the port when the port supports USB Power
-               Delivery. Swapping is supported as synchronous operation, so
-               write(2) to the attribute will not return until the operation
-               has finished. The attribute is notified about role changes so
-               that poll(2) on the attribute wakes up. Change on the role will
-               also generate uevent KOBJ_CHANGE. The current role is show in
-               brackets, for example "[source] sink" when in source mode.
+               power role swap on the port. Swapping is supported as
+               synchronous operation, so write(2) to the attribute will not
+               return until the operation has finished. The attribute is
+               notified about role changes so that poll(2) on the attribute
+               wakes up. Change on the role will also generate uevent
+               KOBJ_CHANGE. The current role is show in brackets, for example
+               "[source] sink" when in source mode.
 
                Valid values: source, sink
 
index f47a69b..03dfa9c 100644 (file)
@@ -53,9 +53,7 @@ in need to reconfigure the pins on the connector, the alternate mode driver
 needs to notify the bus using :c:func:`typec_altmode_notify()`. The driver
 passes the negotiated SVID specific pin configuration value to the function as
 parameter. The bus driver will then configure the mux behind the connector using
-that value as the state value for the mux, and also call blocking notification
-chain to notify the external drivers about the state of the connector that need
-to know it.
+that value as the state value for the mux.
 
 NOTE: The SVID specific pin configuration values must always start from
 ``TYPEC_STATE_MODAL``. USB Type-C specification defines two default states for
@@ -80,19 +78,6 @@ Helper macro ``TYPEC_MODAL_STATE()`` can also be used::
 #define ALTMODEX_CONF_A = TYPEC_MODAL_STATE(0);
 #define ALTMODEX_CONF_B = TYPEC_MODAL_STATE(1);
 
-Notification chain
-~~~~~~~~~~~~~~~~~~
-
-The drivers for the components that the alternate modes are designed for need to
-get details regarding the results of the negotiation with the partner, and the
-pin configuration of the connector. In case of DisplayPort alternate mode for
-example, the GPU drivers will need to know those details. In case of
-Thunderbolt alternate mode, the thunderbolt drivers will need to know them, and
-so on.
-
-The notification chain is designed for this purpose. The drivers can register
-notifiers with :c:func:`typec_altmode_register_notifier()`.
-
 Cable plug alternate modes
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -129,8 +114,3 @@ Cable Plug operations
 
 .. kernel-doc:: drivers/usb/typec/bus.c
    :functions: typec_altmode_get_plug typec_altmode_put_plug
-
-Notifications
-~~~~~~~~~~~~~
-.. kernel-doc:: drivers/usb/typec/class.c
-   :functions: typec_altmode_register_notifier typec_altmode_unregister_notifier
index fcd79fc..e54866c 100644 (file)
@@ -17183,6 +17183,12 @@ S:     Maintained
 F:     Documentation/usb/acm.rst
 F:     drivers/usb/class/cdc-acm.*
 
+USB APPLE MFI FASTCHARGE DRIVER
+M:     Bastien Nocera <hadess@hadess.net>
+L:     linux-usb@vger.kernel.org
+S:     Maintained
+F:     drivers/usb/misc/apple-mfi-fastcharge.c
+
 USB AR5523 WIRELESS DRIVER
 M:     Pontus Fuchs <pontus.fuchs@gmail.com>
 L:     linux-wireless@vger.kernel.org
index b341fc6..3d084ce 100644 (file)
@@ -259,6 +259,7 @@ int usb4_switch_setup(struct tb_switch *sw)
 /**
  * usb4_switch_read_uid() - Read UID from USB4 router
  * @sw: USB4 router
+ * @uid: UID is stored here
  *
  * Reads 64-bit UID from USB4 router config space.
  */
@@ -296,6 +297,9 @@ static int usb4_switch_drom_read_block(struct tb_switch *sw,
 /**
  * usb4_switch_drom_read() - Read arbitrary bytes from USB4 router DROM
  * @sw: USB4 router
+ * @address: Byte address inside DROM to start reading
+ * @buf: Buffer where the DROM content is stored
+ * @size: Number of bytes to read from DROM
  *
  * Uses USB4 router operations to read router DROM. For devices this
  * should always work but for hosts it may return %-EOPNOTSUPP in which
index 635cf04..e9fed9a 100644 (file)
@@ -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 */
index d3bdc4c..8725755 100644 (file)
@@ -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)
index 736b0c6..3c05080 100644 (file)
@@ -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;
index 2b27d23..f81606c 100644 (file)
@@ -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);
index 38f8b3e..4626227 100644 (file)
@@ -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,
 };
index f19694e..9f4320b 100644 (file)
@@ -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)
index 9043d72..50b2fc7 100644 (file)
@@ -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);
index 3ad0ee5..64ed402 100644 (file)
@@ -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 struct usb_device_id *usb_device_match_id(struct usb_device *udev,
+                               const struct usb_device_id *id);
 extern void usb_forced_unbind_intf(struct usb_interface *intf);
 extern void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev);
 
index 8ca6d12..1224fa9 100644 (file)
@@ -199,7 +199,7 @@ struct dwc2_hcd_urb {
        u32 flags;
        u16 interval;
        struct dwc2_hcd_pipe_info pipe_info;
-       struct dwc2_hcd_iso_packet_desc iso_descs[0];
+       struct dwc2_hcd_iso_packet_desc iso_descs[];
 };
 
 /* Phases for control transfers */
index 261af9e..1dfd024 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/of.h>
 #include <linux/clk.h>
 #include <linux/irq.h>
-#include <linux/clk-provider.h>
+#include <linux/of_clk.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/extcon.h>
index 8b72b19..d7f6cc5 100644 (file)
@@ -48,7 +48,7 @@ struct f_phonet {
        struct usb_ep                   *in_ep, *out_ep;
 
        struct usb_request              *in_req;
-       struct usb_request              *out_reqv[0];
+       struct usb_request              *out_reqv[];
 };
 
 static int phonet_rxq_size = 17;
index 6677ae9..349deae 100644 (file)
@@ -752,8 +752,6 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
        audio->out_ep = ep;
        audio->out_ep->desc = &as_out_ep_desc;
 
-       status = -ENOMEM;
-
        /* copy descriptors, and track endpoint copies */
        status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL,
                                        NULL);
index 9eea2d1..265c392 100644 (file)
@@ -174,7 +174,7 @@ put:
 }
 
 static struct usb_composite_driver midi_driver = {
-       .name           = (char *) longname,
+       .name           = longname,
        .dev            = &device_desc,
        .strings        = dev_strings,
        .max_speed      = USB_SPEED_HIGH,
index b47938d..e3dfc21 100644 (file)
@@ -1736,7 +1736,7 @@ static struct usb_gadget_driver gadgetfs_driver = {
        .suspend        = gadgetfs_suspend,
 
        .driver = {
-               .name           = (char *) shortname,
+               .name           = shortname,
        },
 };
 
index dfdef6a..0262383 100644 (file)
@@ -440,7 +440,7 @@ struct udc_ep_regs {
        /* endpoint data descriptor pointer */
        u32 desptr;
 
-       /* reserverd */
+       /* reserved */
        u32 reserved;
 
        /* write/read confirmation */
index bfd1c9e..80685e4 100644 (file)
@@ -202,7 +202,7 @@ MODULE_DEVICE_TABLE(pci, pci_id);
 
 /* PCI functions */
 static struct pci_driver udc_pci_driver = {
-       .name =         (char *) name,
+       .name =         name,
        .id_table =     pci_id,
        .probe =        udc_pci_probe,
        .remove =       udc_pci_remove,
index 1b2b548..eede5ce 100644 (file)
@@ -2021,7 +2021,7 @@ static struct platform_driver at91_udc_driver = {
        .suspend        = at91udc_suspend,
        .resume         = at91udc_resume,
        .driver         = {
-               .name   = (char *) driver_name,
+               .name   = driver_name,
                .of_match_table = at91_udc_dt_ids,
        },
 };
index 4c9d1e4..6e3e3eb 100644 (file)
@@ -1134,7 +1134,7 @@ static struct platform_driver dummy_udc_driver = {
        .suspend        = dummy_udc_suspend,
        .resume         = dummy_udc_resume,
        .driver         = {
-               .name   = (char *) gadget_name,
+               .name   = gadget_name,
        },
 };
 
@@ -2720,7 +2720,7 @@ static struct platform_driver dummy_hcd_driver = {
        .suspend        = dummy_hcd_suspend,
        .resume         = dummy_hcd_resume,
        .driver         = {
-               .name   = (char *) driver_name,
+               .name   = driver_name,
        },
 };
 
index 21f3e6c..d6ca50f 100644 (file)
@@ -1199,7 +1199,7 @@ err:
 
 static struct platform_driver fotg210_driver = {
        .driver         = {
-               .name = (char *)udc_name,
+               .name = udc_name,
        },
        .probe          = fotg210_udc_probe,
        .remove         = fotg210_udc_remove,
index 00e3f66..9af8b41 100644 (file)
@@ -1507,7 +1507,7 @@ clean_up:
 static struct platform_driver fusb300_driver = {
        .remove =       fusb300_remove,
        .driver         = {
-               .name = (char *) udc_name,
+               .name = udc_name,
        },
 };
 
index 4a46f66..91dcb19 100644 (file)
@@ -1844,7 +1844,7 @@ static const struct pci_device_id pci_ids[] = { {
 MODULE_DEVICE_TABLE (pci, pci_ids);
 
 static struct pci_driver goku_pci_driver = {
-       .name =         (char *) driver_name,
+       .name =         driver_name,
        .id_table =     pci_ids,
 
        .probe =        goku_probe,
index d14b2bb..cb997b8 100644 (file)
@@ -3267,7 +3267,7 @@ static struct platform_driver lpc32xx_udc_driver = {
        .suspend        = lpc32xx_udc_suspend,
        .resume         = lpc32xx_udc_resume,
        .driver         = {
-               .name   = (char *) driver_name,
+               .name   = driver_name,
                .of_match_table = of_match_ptr(lpc32xx_udc_of_match),
        },
 };
index a8288df..75d16a8 100644 (file)
@@ -1691,7 +1691,7 @@ clean_up:
 static struct platform_driver m66592_driver = {
        .remove =       m66592_remove,
        .driver         = {
-               .name = (char *) udc_name,
+               .name = udc_name,
        },
 };
 
index 1fd1b91..4a815aa 100644 (file)
@@ -3857,7 +3857,7 @@ MODULE_DEVICE_TABLE(pci, pci_ids);
 
 /* pci driver glue; this is a "new style" PCI driver module */
 static struct pci_driver net2280_pci_driver = {
-       .name =         (char *) driver_name,
+       .name =         driver_name,
        .id_table =     pci_ids,
 
        .probe =        net2280_probe,
index bd12417..bf87c6c 100644 (file)
@@ -3001,7 +3001,7 @@ static struct platform_driver udc_driver = {
        .suspend        = omap_udc_suspend,
        .resume         = omap_udc_resume,
        .driver         = {
-               .name   = (char *) driver_name,
+               .name   = driver_name,
        },
 };
 
index 582a161..537094b 100644 (file)
@@ -1968,7 +1968,7 @@ clean_up2:
 static struct platform_driver r8a66597_driver = {
        .remove =       r8a66597_remove,
        .driver         = {
-               .name = (char *) udc_name,
+               .name = udc_name,
        },
 };
 
index c5c3c14..42ae99a 100644 (file)
@@ -2906,7 +2906,7 @@ static struct platform_driver renesas_usb3_driver = {
        .probe          = renesas_usb3_probe,
        .remove         = renesas_usb3_remove,
        .driver         = {
-               .name = (char *)udc_name,
+               .name = udc_name,
                .pm             = &renesas_usb3_pm_ops,
                .of_match_table = of_match_ptr(usb3_of_match),
        },
index b0882c1..1a48ab1 100644 (file)
@@ -384,7 +384,7 @@ MODULE_DEVICE_TABLE(pci, pci_ids);
 
 /* pci driver glue; this is a "new style" PCI driver module */
 static struct pci_driver ehci_pci_driver = {
-       .name =         (char *) hcd_name,
+       .name =         hcd_name,
        .id_table =     pci_ids,
 
        .probe =        ehci_pci_probe,
index 769749c..e4fc3f6 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/reset.h>
+#include <linux/sys_soc.h>
+#include <linux/timer.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
 #include <linux/usb/ehci_pdriver.h>
@@ -44,6 +46,9 @@ struct ehci_platform_priv {
        struct clk *clks[EHCI_MAX_CLKS];
        struct reset_control *rsts;
        bool reset_on_resume;
+       bool quirk_poll;
+       struct timer_list poll_timer;
+       struct delayed_work poll_work;
 };
 
 static const char hcd_name[] = "ehci-platform";
@@ -118,6 +123,111 @@ static struct usb_ehci_pdata ehci_platform_defaults = {
        .power_off =            ehci_platform_power_off,
 };
 
+/**
+ * quirk_poll_check_port_status - Poll port_status if the device sticks
+ * @ehci: the ehci hcd pointer
+ *
+ * Since EHCI/OHCI controllers on R-Car Gen3 SoCs are possible to be getting
+ * stuck very rarely after a full/low usb device was disconnected. To
+ * detect such a situation, the controllers require a special way which poll
+ * the EHCI PORTSC register.
+ *
+ * Return: true if the controller's port_status indicated getting stuck
+ */
+static bool quirk_poll_check_port_status(struct ehci_hcd *ehci)
+{
+       u32 port_status = ehci_readl(ehci, &ehci->regs->port_status[0]);
+
+       if (!(port_status & PORT_OWNER) &&
+            (port_status & PORT_POWER) &&
+           !(port_status & PORT_CONNECT) &&
+            (port_status & PORT_LS_MASK))
+               return true;
+
+       return false;
+}
+
+/**
+ * quirk_poll_rebind_companion - rebind comanion device to recover
+ * @ehci: the ehci hcd pointer
+ *
+ * Since EHCI/OHCI controllers on R-Car Gen3 SoCs are possible to be getting
+ * stuck very rarely after a full/low usb device was disconnected. To
+ * recover from such a situation, the controllers require changing the OHCI
+ * functional state.
+ */
+static void quirk_poll_rebind_companion(struct ehci_hcd *ehci)
+{
+       struct device *companion_dev;
+       struct usb_hcd *hcd = ehci_to_hcd(ehci);
+
+       companion_dev = usb_of_get_companion_dev(hcd->self.controller);
+       if (!companion_dev)
+               return;
+
+       device_release_driver(companion_dev);
+       if (device_attach(companion_dev) < 0)
+               ehci_err(ehci, "%s: failed\n", __func__);
+
+       put_device(companion_dev);
+}
+
+static void quirk_poll_work(struct work_struct *work)
+{
+       struct ehci_platform_priv *priv =
+               container_of(to_delayed_work(work), struct ehci_platform_priv,
+                            poll_work);
+       struct ehci_hcd *ehci = container_of((void *)priv, struct ehci_hcd,
+                                            priv);
+
+       /* check the status twice to reduce misdetection rate */
+       if (!quirk_poll_check_port_status(ehci))
+               return;
+       udelay(10);
+       if (!quirk_poll_check_port_status(ehci))
+               return;
+
+       ehci_dbg(ehci, "%s: detected getting stuck. rebind now!\n", __func__);
+       quirk_poll_rebind_companion(ehci);
+}
+
+static void quirk_poll_timer(struct timer_list *t)
+{
+       struct ehci_platform_priv *priv = from_timer(priv, t, poll_timer);
+       struct ehci_hcd *ehci = container_of((void *)priv, struct ehci_hcd,
+                                            priv);
+
+       if (quirk_poll_check_port_status(ehci)) {
+               /*
+                * Now scheduling the work for testing the port more. Note that
+                * updating the status is possible to be delayed when
+                * reconnection. So, this uses delayed work with 5 ms delay
+                * to avoid misdetection.
+                */
+               schedule_delayed_work(&priv->poll_work, msecs_to_jiffies(5));
+       }
+
+       mod_timer(&priv->poll_timer, jiffies + HZ);
+}
+
+static void quirk_poll_init(struct ehci_platform_priv *priv)
+{
+       INIT_DELAYED_WORK(&priv->poll_work, quirk_poll_work);
+       timer_setup(&priv->poll_timer, quirk_poll_timer, 0);
+       mod_timer(&priv->poll_timer, jiffies + HZ);
+}
+
+static void quirk_poll_end(struct ehci_platform_priv *priv)
+{
+       del_timer_sync(&priv->poll_timer);
+       cancel_delayed_work(&priv->poll_work);
+}
+
+static const struct soc_device_attribute quirk_poll_match[] = {
+       { .family = "R-Car Gen3" },
+       { /* sentinel*/ }
+};
+
 static int ehci_platform_probe(struct platform_device *dev)
 {
        struct usb_hcd *hcd;
@@ -176,6 +286,9 @@ static int ehci_platform_probe(struct platform_device *dev)
                                          "has-transaction-translator"))
                        hcd->has_tt = 1;
 
+               if (soc_device_match(quirk_poll_match))
+                       priv->quirk_poll = true;
+
                for (clk = 0; clk < EHCI_MAX_CLKS; clk++) {
                        priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
                        if (IS_ERR(priv->clks[clk])) {
@@ -247,6 +360,9 @@ static int ehci_platform_probe(struct platform_device *dev)
        device_enable_async_suspend(hcd->self.controller);
        platform_set_drvdata(dev, hcd);
 
+       if (priv->quirk_poll)
+               quirk_poll_init(priv);
+
        return err;
 
 err_power:
@@ -273,6 +389,9 @@ static int ehci_platform_remove(struct platform_device *dev)
        struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
        int clk;
 
+       if (priv->quirk_poll)
+               quirk_poll_end(priv);
+
        usb_remove_hcd(hcd);
 
        if (pdata->power_off)
@@ -297,9 +416,13 @@ static int ehci_platform_suspend(struct device *dev)
        struct usb_hcd *hcd = dev_get_drvdata(dev);
        struct usb_ehci_pdata *pdata = dev_get_platdata(dev);
        struct platform_device *pdev = to_platform_device(dev);
+       struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
        bool do_wakeup = device_may_wakeup(dev);
        int ret;
 
+       if (priv->quirk_poll)
+               quirk_poll_end(priv);
+
        ret = ehci_suspend(hcd, do_wakeup);
        if (ret)
                return ret;
@@ -331,6 +454,10 @@ static int ehci_platform_resume(struct device *dev)
        }
 
        ehci_resume(hcd, priv->reset_on_resume);
+
+       if (priv->quirk_poll)
+               quirk_poll_init(priv);
+
        return 0;
 }
 #endif /* CONFIG_PM_SLEEP */
index d6433f2..10d51da 100644 (file)
@@ -282,7 +282,7 @@ done:
 struct dma_aligned_buffer {
        void *kmalloc_ptr;
        void *old_xfer_buffer;
-       u8 data[0];
+       u8 data[];
 };
 
 static void free_dma_aligned_buffer(struct urb *urb)
index ac5e967..229b3de 100644 (file)
@@ -255,7 +255,7 @@ struct ehci_hcd {                   /* one per controller */
        struct list_head        tt_list;
 
        /* platform-specific data -- must come last */
-       unsigned long           priv[0] __aligned(sizeof(s64));
+       unsigned long           priv[] __aligned(sizeof(s64));
 };
 
 /* convert between an HCD pointer and the corresponding EHCI_HCD */
@@ -460,7 +460,7 @@ struct ehci_iso_sched {
        struct list_head        td_list;
        unsigned                span;
        unsigned                first_packet;
-       struct ehci_iso_packet  packet[0];
+       struct ehci_iso_packet  packet[];
 };
 
 /*
index 0473387..a8e1048 100644 (file)
@@ -396,6 +396,7 @@ static int fhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
        case PIPE_CONTROL:
                /* 1 td fro setup,1 for ack */
                size = 2;
+               fallthrough;
        case PIPE_BULK:
                /* one td for every 4096 bytes(can be up to 8k) */
                size += urb->transfer_buffer_length / 4096;
index 1b4db95..6cee40e 100644 (file)
@@ -490,7 +490,7 @@ struct fotg210_iso_packet {
 struct fotg210_iso_sched {
        struct list_head        td_list;
        unsigned                span;
-       struct fotg210_iso_packet       packet[0];
+       struct fotg210_iso_packet       packet[];
 };
 
 /*
index f4e13a3..22117a6 100644 (file)
@@ -288,7 +288,7 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
 
 /* pci driver glue; this is a "new style" PCI driver module */
 static struct pci_driver ohci_pci_driver = {
-       .name =         (char *) hcd_name,
+       .name =         hcd_name,
        .id_table =     pci_ids,
 
        .probe =        usb_hcd_pci_probe,
index b015b00..27c26ca 100644 (file)
@@ -337,7 +337,7 @@ typedef struct urb_priv {
        u16                     length;         // # tds in this request
        u16                     td_cnt;         // tds already serviced
        struct list_head        pending;
-       struct td               *td [0];        // all TDs in this request
+       struct td               *td[];          // all TDs in this request
 
 } urb_priv_t;
 
@@ -435,7 +435,7 @@ struct ohci_hcd {
        struct dentry           *debug_dir;
 
        /* platform-specific data -- must come last */
-       unsigned long           priv[0] __aligned(sizeof(s64));
+       unsigned long           priv[] __aligned(sizeof(s64));
 
 };
 
index 72a34a1..adaf406 100644 (file)
@@ -1792,7 +1792,7 @@ struct platform_driver sl811h_driver = {
        .suspend =      sl811h_suspend,
        .resume =       sl811h_resume,
        .driver = {
-               .name = (char *) hcd_name,
+               .name = hcd_name,
        },
 };
 EXPORT_SYMBOL(sl811h_driver);
index 0fa3d72..957c87e 100644 (file)
@@ -294,7 +294,7 @@ static const struct pci_device_id uhci_pci_ids[] = { {
 MODULE_DEVICE_TABLE(pci, uhci_pci_ids);
 
 static struct pci_driver uhci_pci_driver = {
-       .name =         (char *)hcd_name,
+       .name =         hcd_name,
        .id_table =     uhci_pci_ids,
 
        .probe =        usb_hcd_pci_probe,
index af92b25..2483571 100644 (file)
@@ -567,6 +567,7 @@ struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd)
  */
 static void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd,
                                u16 index, bool on, unsigned long *flags)
+       __must_hold(&xhci->lock)
 {
        struct xhci_hub *rhub;
        struct xhci_port *port;
@@ -617,6 +618,7 @@ static void xhci_port_set_test_mode(struct xhci_hcd *xhci,
 
 static int xhci_enter_test_mode(struct xhci_hcd *xhci,
                                u16 test_mode, u16 wIndex, unsigned long *flags)
+       __must_hold(&xhci->lock)
 {
        int i, retval;
 
index 5ac458b..acd5651 100644 (file)
@@ -95,7 +95,7 @@ struct mu3h_sch_ep_info {
        u32 pkts;
        u32 cs_count;
        u32 burst_mode;
-       u32 bw_budget_table[0];
+       u32 bw_budget_table[];
 };
 
 #define MU3C_U3_PORT_MAX 4
index 5e9b537..0715a2e 100644 (file)
@@ -549,7 +549,7 @@ MODULE_DEVICE_TABLE(pci, pci_ids);
 
 /* pci driver glue; this is a "new style" PCI driver module */
 static struct pci_driver xhci_pci_driver = {
-       .name =         (char *) hcd_name,
+       .name =         hcd_name,
        .id_table =     pci_ids,
 
        .probe =        xhci_pci_probe,
index 56eb867..b19582b 100644 (file)
@@ -289,23 +289,12 @@ DECLARE_EVENT_CLASS(xhci_log_urb,
        ),
        TP_printk("ep%d%s-%s: urb %p pipe %u slot %d length %d/%d sgs %d/%d stream %d flags %08x",
                        __entry->epnum, __entry->dir_in ? "in" : "out",
-                       ({ char *s;
-                       switch (__entry->type) {
-                       case USB_ENDPOINT_XFER_INT:
-                               s = "intr";
-                               break;
-                       case USB_ENDPOINT_XFER_CONTROL:
-                               s = "control";
-                               break;
-                       case USB_ENDPOINT_XFER_BULK:
-                               s = "bulk";
-                               break;
-                       case USB_ENDPOINT_XFER_ISOC:
-                               s = "isoc";
-                               break;
-                       default:
-                               s = "UNKNOWN";
-                       } s; }), __entry->urb, __entry->pipe, __entry->slot_id,
+                       __print_symbolic(__entry->type,
+                                  { USB_ENDPOINT_XFER_INT,     "intr" },
+                                  { USB_ENDPOINT_XFER_CONTROL, "control" },
+                                  { USB_ENDPOINT_XFER_BULK,    "bulk" },
+                                  { USB_ENDPOINT_XFER_ISOC,    "isoc" }),
+                       __entry->urb, __entry->pipe, __entry->slot_id,
                        __entry->actual, __entry->length, __entry->num_mapped_sgs,
                        __entry->num_sgs, __entry->stream, __entry->flags
                )
index 3ecee10..685180e 100644 (file)
@@ -1642,7 +1642,7 @@ struct xhci_scratchpad {
 struct urb_priv {
        int     num_tds;
        int     num_tds_done;
-       struct  xhci_td td[0];
+       struct  xhci_td td[];
 };
 
 /*
@@ -1901,7 +1901,7 @@ struct xhci_hcd {
 
        void                    *dbc;
        /* platform-specific data -- must come last */
-       unsigned long           priv[0] __aligned(sizeof(s64));
+       unsigned long           priv[] __aligned(sizeof(s64));
 };
 
 /* Platform specific overrides to generic XHCI hc_driver ops */
index 834b249..833a460 100644 (file)
@@ -137,6 +137,16 @@ config USB_APPLEDISPLAY
          Say Y here if you want to control the backlight of Apple Cinema
          Displays over USB. This driver provides a sysfs interface.
 
+config APPLE_MFI_FASTCHARGE
+       tristate "Fast charge control for iOS devices"
+       select POWER_SUPPLY
+       help
+         Say Y here if you want to control whether iOS devices will
+         fast charge from the USB interface, as implemented in "MFi"
+         chargers.
+
+         It is safe to say M here.
+
 source "drivers/usb/misc/sisusbvga/Kconfig"
 
 config USB_LD
index 0d416eb..da39bdd 100644 (file)
@@ -11,6 +11,7 @@ obj-$(CONFIG_USB_EMI26)                       += emi26.o
 obj-$(CONFIG_USB_EMI62)                        += emi62.o
 obj-$(CONFIG_USB_EZUSB_FX2)            += ezusb.o
 obj-$(CONFIG_USB_FTDI_ELAN)            += ftdi-elan.o
+obj-$(CONFIG_APPLE_MFI_FASTCHARGE)     += apple-mfi-fastcharge.o
 obj-$(CONFIG_USB_IDMOUSE)              += idmouse.o
 obj-$(CONFIG_USB_IOWARRIOR)            += iowarrior.o
 obj-$(CONFIG_USB_ISIGHTFW)             += isight_firmware.o
diff --git a/drivers/usb/misc/apple-mfi-fastcharge.c b/drivers/usb/misc/apple-mfi-fastcharge.c
new file mode 100644 (file)
index 0000000..b403094
--- /dev/null
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Fast-charge control for Apple "MFi" devices
+ *
+ * Copyright (C) 2019 Bastien Nocera <hadess@hadess.net>
+ */
+
+/* Standard include files */
+#include <linux/module.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
+MODULE_DESCRIPTION("Fast-charge control for Apple \"MFi\" devices");
+MODULE_LICENSE("GPL");
+
+#define TRICKLE_CURRENT_MA             0
+#define FAST_CURRENT_MA                        2500
+
+#define APPLE_VENDOR_ID                        0x05ac  /* Apple */
+
+/* The product ID is defined as starting with 0x12nn, as per the
+ * "Choosing an Apple Device USB Configuration" section in
+ * release R9 (2012) of the "MFi Accessory Hardware Specification"
+ *
+ * To distinguish an Apple device, a USB host can check the device
+ * descriptor of attached USB devices for the following fields:
+ * ■ Vendor ID: 0x05AC
+ * ■ Product ID: 0x12nn
+ *
+ * Those checks will be done in .match() and .probe().
+ */
+
+static const struct usb_device_id mfi_fc_id_table[] = {
+       { .idVendor = APPLE_VENDOR_ID,
+         .match_flags = USB_DEVICE_ID_MATCH_VENDOR },
+       {},
+};
+
+MODULE_DEVICE_TABLE(usb, mfi_fc_id_table);
+
+/* Driver-local specific stuff */
+struct mfi_device {
+       struct usb_device *udev;
+       struct power_supply *battery;
+       int charge_type;
+};
+
+static int apple_mfi_fc_set_charge_type(struct mfi_device *mfi,
+                                       const union power_supply_propval *val)
+{
+       int current_ma;
+       int retval;
+       __u8 request_type;
+
+       if (mfi->charge_type == val->intval) {
+               dev_dbg(&mfi->udev->dev, "charge type %d already set\n",
+                               mfi->charge_type);
+               return 0;
+       }
+
+       switch (val->intval) {
+       case POWER_SUPPLY_CHARGE_TYPE_TRICKLE:
+               current_ma = TRICKLE_CURRENT_MA;
+               break;
+       case POWER_SUPPLY_CHARGE_TYPE_FAST:
+               current_ma = FAST_CURRENT_MA;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       request_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+       retval = usb_control_msg(mfi->udev, usb_sndctrlpipe(mfi->udev, 0),
+                                0x40, /* Vendor‐defined power request */
+                                request_type,
+                                current_ma, /* wValue, current offset */
+                                current_ma, /* wIndex, current offset */
+                                NULL, 0, USB_CTRL_GET_TIMEOUT);
+       if (retval) {
+               dev_dbg(&mfi->udev->dev, "retval = %d\n", retval);
+               return retval;
+       }
+
+       mfi->charge_type = val->intval;
+
+       return 0;
+}
+
+static int apple_mfi_fc_get_property(struct power_supply *psy,
+               enum power_supply_property psp,
+               union power_supply_propval *val)
+{
+       struct mfi_device *mfi = power_supply_get_drvdata(psy);
+
+       dev_dbg(&mfi->udev->dev, "prop: %d\n", psp);
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_CHARGE_TYPE:
+               val->intval = mfi->charge_type;
+               break;
+       case POWER_SUPPLY_PROP_SCOPE:
+               val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+               break;
+       default:
+               return -ENODATA;
+       }
+
+       return 0;
+}
+
+static int apple_mfi_fc_set_property(struct power_supply *psy,
+               enum power_supply_property psp,
+               const union power_supply_propval *val)
+{
+       struct mfi_device *mfi = power_supply_get_drvdata(psy);
+       int ret;
+
+       dev_dbg(&mfi->udev->dev, "prop: %d\n", psp);
+
+       ret = pm_runtime_get_sync(&mfi->udev->dev);
+       if (ret < 0)
+               return ret;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_CHARGE_TYPE:
+               ret = apple_mfi_fc_set_charge_type(mfi, val);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       pm_runtime_mark_last_busy(&mfi->udev->dev);
+       pm_runtime_put_autosuspend(&mfi->udev->dev);
+
+       return ret;
+}
+
+static int apple_mfi_fc_property_is_writeable(struct power_supply *psy,
+                                             enum power_supply_property psp)
+{
+       switch (psp) {
+       case POWER_SUPPLY_PROP_CHARGE_TYPE:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static enum power_supply_property apple_mfi_fc_properties[] = {
+       POWER_SUPPLY_PROP_CHARGE_TYPE,
+       POWER_SUPPLY_PROP_SCOPE
+};
+
+static const struct power_supply_desc apple_mfi_fc_desc = {
+       .name                   = "apple_mfi_fastcharge",
+       .type                   = POWER_SUPPLY_TYPE_BATTERY,
+       .properties             = apple_mfi_fc_properties,
+       .num_properties         = ARRAY_SIZE(apple_mfi_fc_properties),
+       .get_property           = apple_mfi_fc_get_property,
+       .set_property           = apple_mfi_fc_set_property,
+       .property_is_writeable  = apple_mfi_fc_property_is_writeable
+};
+
+static int mfi_fc_probe(struct usb_device *udev)
+{
+       struct power_supply_config battery_cfg = {};
+       struct mfi_device *mfi = NULL;
+       int err, idProduct;
+
+       idProduct = le16_to_cpu(udev->descriptor.idProduct);
+       /* See comment above mfi_fc_id_table[] */
+       if (idProduct < 0x1200 || idProduct > 0x12ff) {
+               return -ENODEV;
+       }
+
+       mfi = kzalloc(sizeof(struct mfi_device), GFP_KERNEL);
+       if (!mfi) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       battery_cfg.drv_data = mfi;
+
+       mfi->charge_type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+       mfi->battery = power_supply_register(&udev->dev,
+                                               &apple_mfi_fc_desc,
+                                               &battery_cfg);
+       if (IS_ERR(mfi->battery)) {
+               dev_err(&udev->dev, "Can't register battery\n");
+               err = PTR_ERR(mfi->battery);
+               goto error;
+       }
+
+       mfi->udev = usb_get_dev(udev);
+       dev_set_drvdata(&udev->dev, mfi);
+
+       return 0;
+
+error:
+       kfree(mfi);
+       return err;
+}
+
+static void mfi_fc_disconnect(struct usb_device *udev)
+{
+       struct mfi_device *mfi;
+
+       mfi = dev_get_drvdata(&udev->dev);
+       if (mfi->battery)
+               power_supply_unregister(mfi->battery);
+       dev_set_drvdata(&udev->dev, NULL);
+       usb_put_dev(mfi->udev);
+       kfree(mfi);
+}
+
+static struct usb_device_driver mfi_fc_driver = {
+       .name =         "apple-mfi-fastcharge",
+       .probe =        mfi_fc_probe,
+       .disconnect =   mfi_fc_disconnect,
+       .id_table =     mfi_fc_id_table,
+       .generic_subclass = 1,
+};
+
+static int __init mfi_fc_driver_init(void)
+{
+       return usb_register_device_driver(&mfi_fc_driver, THIS_MODULE);
+}
+
+static void __exit mfi_fc_driver_exit(void)
+{
+       usb_deregister_device_driver(&mfi_fc_driver);
+}
+
+module_init(mfi_fc_driver_init);
+module_exit(mfi_fc_driver_exit);
index f616fb4..d590110 100644 (file)
@@ -2945,7 +2945,7 @@ static const struct dev_pm_ops musb_dev_pm_ops = {
 
 static struct platform_driver musb_driver = {
        .driver = {
-               .name           = (char *)musb_driver_name,
+               .name           = musb_driver_name,
                .bus            = &platform_bus_type,
                .pm             = MUSB_DEV_PM_OPS,
                .dev_groups     = musb_groups,
index 886c9b6..1c813c3 100644 (file)
@@ -2550,7 +2550,7 @@ static int musb_bus_resume(struct usb_hcd *hcd)
 struct musb_temp_buffer {
        void *kmalloc_ptr;
        void *old_xfer_buffer;
-       u8 data[0];
+       u8 data[];
 };
 
 static void musb_free_temp_buffer(struct urb *urb)
index 63a00ff..486b0b1 100644 (file)
@@ -199,7 +199,7 @@ EXPORT_SYMBOL_GPL(usb_role_switch_find_by_fwnode);
 static umode_t
 usb_role_switch_is_visible(struct kobject *kobj, struct attribute *attr, int n)
 {
-       struct device *dev = container_of(kobj, typeof(*dev), kobj);
+       struct device *dev = kobj_to_dev(kobj);
        struct usb_role_switch *sw = to_role_switch(dev);
 
        if (sw->allow_userspace_control)
index c38e87a..0d1a5bb 100644 (file)
@@ -593,7 +593,7 @@ struct ti_i2c_desc {
        __u8    Type;                   // Type of descriptor
        __le16  Size;                   // Size of data only not including header
        __u8    CheckSum;               // Checksum (8 bit sum of data only)
-       __u8    Data[0];                // Data starts here
+       __u8    Data[];         // Data starts here
 } __attribute__((packed));
 
 // for 5152 devices only (type 2 record)
@@ -601,7 +601,7 @@ struct ti_i2c_desc {
 struct ti_i2c_firmware_rec {
        __u8    Ver_Major;              // Firmware Major version number
        __u8    Ver_Minor;              // Firmware Minor version number
-       __u8    Data[0];                // Download starts here
+       __u8    Data[];         // Download starts here
 } __attribute__((packed));
 
 
index ef23acc..73075b9 100644 (file)
@@ -219,7 +219,7 @@ struct ti_write_data_bytes {
        u8      bDataCounter;
        __be16  wBaseAddrHi;
        __be16  wBaseAddrLo;
-       u8      bData[0];
+       u8      bData[];
 } __packed;
 
 struct ti_read_data_request {
@@ -234,7 +234,7 @@ struct ti_read_data_bytes {
        __u8    bCmdCode;
        __u8    bModuleId;
        __u8    bErrorCode;
-       __u8    bData[0];
+       __u8    bData[];
 } __packed;
 
 /* Interrupt struct */
index 9a79cd9..94a6472 100644 (file)
@@ -121,12 +121,12 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks");
        .initFunction = init_function,  \
 }
 
-static struct us_unusual_dev us_unusual_dev_list[] = {
+static const struct us_unusual_dev us_unusual_dev_list[] = {
 #      include "unusual_devs.h"
        { }             /* Terminating entry */
 };
 
-static struct us_unusual_dev for_dynamic_ids =
+static const struct us_unusual_dev for_dynamic_ids =
                USUAL_DEV(USB_SC_SCSI, USB_PR_BULK);
 
 #undef UNUSUAL_DEV
@@ -583,7 +583,7 @@ EXPORT_SYMBOL_GPL(usb_stor_adjust_quirks);
 
 /* Get the unusual_devs entries and the string descriptors */
 static int get_device_info(struct us_data *us, const struct usb_device_id *id,
-               struct us_unusual_dev *unusual_dev)
+               const struct us_unusual_dev *unusual_dev)
 {
        struct usb_device *dev = us->pusb_dev;
        struct usb_interface_descriptor *idesc =
@@ -933,7 +933,7 @@ static unsigned int usb_stor_sg_tablesize(struct usb_interface *intf)
 int usb_stor_probe1(struct us_data **pus,
                struct usb_interface *intf,
                const struct usb_device_id *id,
-               struct us_unusual_dev *unusual_dev,
+               const struct us_unusual_dev *unusual_dev,
                struct scsi_host_template *sht)
 {
        struct Scsi_Host *host;
@@ -1092,7 +1092,7 @@ static struct scsi_host_template usb_stor_host_template;
 static int storage_probe(struct usb_interface *intf,
                         const struct usb_device_id *id)
 {
-       struct us_unusual_dev *unusual_dev;
+       const struct us_unusual_dev *unusual_dev;
        struct us_data *us;
        int result;
        int size;
index 85052cd..5850d62 100644 (file)
@@ -93,7 +93,8 @@ struct us_data {
        struct mutex            dev_mutex;       /* protect pusb_dev */
        struct usb_device       *pusb_dev;       /* this usb_device */
        struct usb_interface    *pusb_intf;      /* this interface */
-       struct us_unusual_dev   *unusual_dev;    /* device-filter entry     */
+       const struct us_unusual_dev   *unusual_dev;
+                                               /* device-filter entry     */
        unsigned long           fflags;          /* fixed flags from filter */
        unsigned long           dflags;          /* dynamic atomic bitflags */
        unsigned int            send_bulk_pipe;  /* cached pipe values */
@@ -185,7 +186,7 @@ extern int usb_stor_post_reset(struct usb_interface *iface);
 extern int usb_stor_probe1(struct us_data **pus,
                struct usb_interface *intf,
                const struct usb_device_id *id,
-               struct us_unusual_dev *unusual_dev,
+               const struct us_unusual_dev *unusual_dev,
                struct scsi_host_template *sht);
 extern int usb_stor_probe2(struct us_data *us);
 extern void usb_stor_disconnect(struct usb_interface *intf);
index cfd12e5..5295128 100644 (file)
@@ -40,7 +40,7 @@
        .driver_info = (flags) \
 }
 
-struct usb_device_id usb_storage_usb_ids[] = {
+const struct usb_device_id usb_storage_usb_ids[] = {
 #      include "unusual_devs.h"
        { }             /* Terminating entry */
 };
@@ -68,7 +68,7 @@ struct ignore_entry {
        .bcdmax = bcdDeviceMax,         \
 }
 
-static struct ignore_entry ignore_ids[] = {
+static const struct ignore_entry ignore_ids[] = {
 #      include "unusual_alauda.h"
 #      include "unusual_cypress.h"
 #      include "unusual_datafab.h"
@@ -92,7 +92,7 @@ int usb_usual_ignore_device(struct usb_interface *intf)
 {
        struct usb_device *udev;
        unsigned vid, pid, bcd;
-       struct ignore_entry *p;
+       const struct ignore_entry *p;
 
        udev = interface_to_usbdev(intf);
        vid = le16_to_cpu(udev->descriptor.idVendor);
index 2e45eb4..c823122 100644 (file)
@@ -30,17 +30,10 @@ static int typec_altmode_set_state(struct typec_altmode *adev,
 {
        bool is_port = is_typec_port(adev->dev.parent);
        struct altmode *port_altmode;
-       int ret;
 
        port_altmode = is_port ? to_altmode(adev) : to_altmode(adev)->partner;
 
-       ret = typec_altmode_set_mux(port_altmode, conf, data);
-       if (ret)
-               return ret;
-
-       blocking_notifier_call_chain(&port_altmode->nh, conf, NULL);
-
-       return 0;
+       return typec_altmode_set_mux(port_altmode, conf, data);
 }
 
 /* -------------------------------------------------------------------------- */
@@ -82,9 +75,6 @@ int typec_altmode_notify(struct typec_altmode *adev,
        if (ret)
                return ret;
 
-       blocking_notifier_call_chain(is_port ? &altmode->nh : &partner->nh,
-                                    conf, data);
-
        if (partner->adev.ops && partner->adev.ops->notify)
                return partner->adev.ops->notify(&partner->adev, conf, data);
 
index 0c9661c..8ba8112 100644 (file)
@@ -22,8 +22,6 @@ struct altmode {
 
        struct altmode                  *partner;
        struct altmode                  *plug[2];
-
-       struct blocking_notifier_head   nh;
 };
 
 #define to_altmode(d) container_of(d, struct altmode, adev)
index 7c44e93..12be5bb 100644 (file)
@@ -206,69 +206,6 @@ static void typec_altmode_put_partner(struct altmode *altmode)
        put_device(&adev->dev);
 }
 
-static void *typec_port_match(struct device_connection *con, int ep, void *data)
-{
-       struct device *dev;
-
-       /*
-        * FIXME: Check does the fwnode supports the requested SVID. If it does
-        * we need to return ERR_PTR(-PROBE_DEFER) when there is no device.
-        */
-       if (con->fwnode)
-               return class_find_device_by_fwnode(typec_class, con->fwnode);
-
-       dev = class_find_device_by_name(typec_class, con->endpoint[ep]);
-
-       return dev ? dev : ERR_PTR(-EPROBE_DEFER);
-}
-
-struct typec_altmode *
-typec_altmode_register_notifier(struct device *dev, u16 svid, u8 mode,
-                               struct notifier_block *nb)
-{
-       struct typec_device_id id = { svid, mode, };
-       struct device *altmode_dev;
-       struct device *port_dev;
-       struct altmode *altmode;
-       int ret;
-
-       /* Find the port linked to the caller */
-       port_dev = device_connection_find_match(dev, NULL, NULL,
-                                               typec_port_match);
-       if (IS_ERR_OR_NULL(port_dev))
-               return port_dev ? ERR_CAST(port_dev) : ERR_PTR(-ENODEV);
-
-       /* Find the altmode with matching svid */
-       altmode_dev = device_find_child(port_dev, &id, altmode_match);
-
-       put_device(port_dev);
-
-       if (!altmode_dev)
-               return ERR_PTR(-ENODEV);
-
-       altmode = to_altmode(to_typec_altmode(altmode_dev));
-
-       /* Register notifier */
-       ret = blocking_notifier_chain_register(&altmode->nh, nb);
-       if (ret) {
-               put_device(altmode_dev);
-               return ERR_PTR(ret);
-       }
-
-       return &altmode->adev;
-}
-EXPORT_SYMBOL_GPL(typec_altmode_register_notifier);
-
-void typec_altmode_unregister_notifier(struct typec_altmode *adev,
-                                      struct notifier_block *nb)
-{
-       struct altmode *altmode = to_altmode(adev);
-
-       blocking_notifier_chain_unregister(&altmode->nh, nb);
-       put_device(&adev->dev);
-}
-EXPORT_SYMBOL_GPL(typec_altmode_unregister_notifier);
-
 /**
  * typec_altmode_update_active - Report Enter/Exit mode
  * @adev: Handle to the alternate mode
@@ -432,7 +369,28 @@ static struct attribute *typec_altmode_attrs[] = {
        &dev_attr_vdo.attr,
        NULL
 };
-ATTRIBUTE_GROUPS(typec_altmode);
+
+static umode_t typec_altmode_attr_is_visible(struct kobject *kobj,
+                                            struct attribute *attr, int n)
+{
+       struct typec_altmode *adev = to_typec_altmode(kobj_to_dev(kobj));
+
+       if (attr == &dev_attr_active.attr)
+               if (!adev->ops || !adev->ops->activate)
+                       return 0444;
+
+       return attr->mode;
+}
+
+static struct attribute_group typec_altmode_group = {
+       .is_visible = typec_altmode_attr_is_visible,
+       .attrs = typec_altmode_attrs,
+};
+
+static const struct attribute_group *typec_altmode_groups[] = {
+       &typec_altmode_group,
+       NULL
+};
 
 static int altmode_id_get(struct device *dev)
 {
@@ -517,9 +475,7 @@ typec_register_altmode(struct device *parent,
        dev_set_name(&alt->adev.dev, "%s.%u", dev_name(parent), id);
 
        /* Link partners and plugs with the ports */
-       if (is_port)
-               BLOCKING_INIT_NOTIFIER_HEAD(&alt->nh);
-       else
+       if (!is_port)
                typec_altmode_set_partner(alt);
 
        /* The partners are bind to drivers */
@@ -1091,11 +1047,6 @@ static ssize_t power_role_store(struct device *dev,
        struct typec_port *port = to_typec_port(dev);
        int ret;
 
-       if (!port->cap->pd_revision) {
-               dev_dbg(dev, "USB Power Delivery not supported\n");
-               return -EOPNOTSUPP;
-       }
-
        if (!port->ops || !port->ops->pr_set) {
                dev_dbg(dev, "power role swapping not supported\n");
                return -EOPNOTSUPP;
@@ -1305,7 +1256,47 @@ static struct attribute *typec_attrs[] = {
        &dev_attr_port_type.attr,
        NULL,
 };
-ATTRIBUTE_GROUPS(typec);
+
+static umode_t typec_attr_is_visible(struct kobject *kobj,
+                                    struct attribute *attr, int n)
+{
+       struct typec_port *port = to_typec_port(kobj_to_dev(kobj));
+
+       if (attr == &dev_attr_data_role.attr) {
+               if (port->cap->data != TYPEC_PORT_DRD ||
+                   !port->ops || !port->ops->dr_set)
+                       return 0444;
+       } else if (attr == &dev_attr_power_role.attr) {
+               if (port->cap->type != TYPEC_PORT_DRP ||
+                   !port->ops || !port->ops->pr_set)
+                       return 0444;
+       } else if (attr == &dev_attr_vconn_source.attr) {
+               if (!port->cap->pd_revision ||
+                   !port->ops || !port->ops->vconn_set)
+                       return 0444;
+       } else if (attr == &dev_attr_preferred_role.attr) {
+               if (port->cap->type != TYPEC_PORT_DRP ||
+                   !port->ops || !port->ops->try_role)
+                       return 0444;
+       } else if (attr == &dev_attr_port_type.attr) {
+               if (!port->ops || !port->ops->port_type_set)
+                       return 0;
+               if (port->cap->type != TYPEC_PORT_DRP)
+                       return 0444;
+       }
+
+       return attr->mode;
+}
+
+static struct attribute_group typec_group = {
+       .is_visible = typec_attr_is_visible,
+       .attrs = typec_attrs,
+};
+
+static const struct attribute_group *typec_groups[] = {
+       &typec_group,
+       NULL
+};
 
 static int typec_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
index 5baf0f4..b952fa2 100644 (file)
 
 #include "bus.h"
 
-static int name_match(struct device *dev, const void *name)
-{
-       return !strcmp((const char *)name, dev_name(dev));
-}
-
 static bool dev_name_ends_with(struct device *dev, const char *suffix)
 {
        const char *name = dev_name(dev);
@@ -44,16 +39,11 @@ static void *typec_switch_match(struct device_connection *con, int ep,
 {
        struct device *dev;
 
-       if (con->fwnode) {
-               if (con->id && !fwnode_property_present(con->fwnode, con->id))
-                       return NULL;
+       if (con->id && !fwnode_property_present(con->fwnode, con->id))
+               return NULL;
 
-               dev = class_find_device(&typec_mux_class, NULL, con->fwnode,
-                                       switch_fwnode_match);
-       } else {
-               dev = class_find_device(&typec_mux_class, NULL,
-                                       con->endpoint[ep], name_match);
-       }
+       dev = class_find_device(&typec_mux_class, NULL, con->fwnode,
+                               switch_fwnode_match);
 
        return dev ? to_typec_switch(dev) : ERR_PTR(-EPROBE_DEFER);
 }
@@ -191,13 +181,6 @@ static void *typec_mux_match(struct device_connection *con, int ep, void *data)
        u16 *val;
        int i;
 
-       if (!con->fwnode) {
-               dev = class_find_device(&typec_mux_class, NULL,
-                                       con->endpoint[ep], name_match);
-
-               return dev ? to_typec_switch(dev) : ERR_PTR(-EPROBE_DEFER);
-       }
-
        /*
         * Check has the identifier already been "consumed". If it
         * has, no need to do any extra connection identification.
index f3087ef..78077c2 100644 (file)
@@ -373,6 +373,14 @@ struct pd_rx_event {
        ((port)->try_src_count == 0 && (port)->try_role == TYPEC_SOURCE && \
        (port)->port_type == TYPEC_PORT_DRP)
 
+#define tcpm_data_role_for_source(port) \
+       ((port)->typec_caps.data == TYPEC_PORT_UFP ? \
+       TYPEC_DEVICE : TYPEC_HOST)
+
+#define tcpm_data_role_for_sink(port) \
+       ((port)->typec_caps.data == TYPEC_PORT_DFP ? \
+       TYPEC_HOST : TYPEC_DEVICE)
+
 static enum tcpm_state tcpm_default_state(struct tcpm_port *port)
 {
        if (port->port_type == TYPEC_PORT_DRP) {
@@ -788,10 +796,30 @@ static int tcpm_set_roles(struct tcpm_port *port, bool attached,
        else
                orientation = TYPEC_ORIENTATION_REVERSE;
 
-       if (data == TYPEC_HOST)
-               usb_role = USB_ROLE_HOST;
-       else
-               usb_role = USB_ROLE_DEVICE;
+       if (port->typec_caps.data == TYPEC_PORT_DRD) {
+               if (data == TYPEC_HOST)
+                       usb_role = USB_ROLE_HOST;
+               else
+                       usb_role = USB_ROLE_DEVICE;
+       } else if (port->typec_caps.data == TYPEC_PORT_DFP) {
+               if (data == TYPEC_HOST) {
+                       if (role == TYPEC_SOURCE)
+                               usb_role = USB_ROLE_HOST;
+                       else
+                               usb_role = USB_ROLE_NONE;
+               } else {
+                       return -ENOTSUPP;
+               }
+       } else {
+               if (data == TYPEC_DEVICE) {
+                       if (role == TYPEC_SINK)
+                               usb_role = USB_ROLE_DEVICE;
+                       else
+                               usb_role = USB_ROLE_NONE;
+               } else {
+                       return -ENOTSUPP;
+               }
+       }
 
        ret = tcpm_mux_set(port, TYPEC_STATE_USB, usb_role, orientation);
        if (ret < 0)
@@ -1817,7 +1845,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
                tcpm_set_state(port, SOFT_RESET, 0);
                break;
        case PD_CTRL_DR_SWAP:
-               if (port->port_type != TYPEC_PORT_DRP) {
+               if (port->typec_caps.data != TYPEC_PORT_DRD) {
                        tcpm_queue_message(port, PD_MSG_CTRL_REJECT);
                        break;
                }
@@ -2618,7 +2646,8 @@ static int tcpm_src_attach(struct tcpm_port *port)
        if (ret < 0)
                return ret;
 
-       ret = tcpm_set_roles(port, true, TYPEC_SOURCE, TYPEC_HOST);
+       ret = tcpm_set_roles(port, true, TYPEC_SOURCE,
+                            tcpm_data_role_for_source(port));
        if (ret < 0)
                return ret;
 
@@ -2740,7 +2769,8 @@ static int tcpm_snk_attach(struct tcpm_port *port)
        if (ret < 0)
                return ret;
 
-       ret = tcpm_set_roles(port, true, TYPEC_SINK, TYPEC_DEVICE);
+       ret = tcpm_set_roles(port, true, TYPEC_SINK,
+                            tcpm_data_role_for_sink(port));
        if (ret < 0)
                return ret;
 
@@ -2766,7 +2796,8 @@ static int tcpm_acc_attach(struct tcpm_port *port)
        if (port->attached)
                return 0;
 
-       ret = tcpm_set_roles(port, true, TYPEC_SOURCE, TYPEC_HOST);
+       ret = tcpm_set_roles(port, true, TYPEC_SOURCE,
+                            tcpm_data_role_for_source(port));
        if (ret < 0)
                return ret;
 
@@ -3293,7 +3324,7 @@ static void run_state_machine(struct tcpm_port *port)
                tcpm_set_vconn(port, true);
                tcpm_set_vbus(port, false);
                tcpm_set_roles(port, port->self_powered, TYPEC_SOURCE,
-                              TYPEC_HOST);
+                              tcpm_data_role_for_source(port));
                tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SRC_RECOVER);
                break;
        case SRC_HARD_RESET_VBUS_ON:
@@ -3308,7 +3339,7 @@ static void run_state_machine(struct tcpm_port *port)
                if (port->pd_capable)
                        tcpm_set_charge(port, false);
                tcpm_set_roles(port, port->self_powered, TYPEC_SINK,
-                              TYPEC_DEVICE);
+                              tcpm_data_role_for_sink(port));
                /*
                 * VBUS may or may not toggle, depending on the adapter.
                 * If it doesn't toggle, transition to SNK_HARD_RESET_SINK_ON
@@ -3969,7 +4000,7 @@ static int tcpm_dr_set(struct typec_port *p, enum typec_data_role data)
        mutex_lock(&port->swap_lock);
        mutex_lock(&port->lock);
 
-       if (port->port_type != TYPEC_PORT_DRP) {
+       if (port->typec_caps.data != TYPEC_PORT_DRD) {
                ret = -EINVAL;
                goto port_unlock;
        }
index d5a6aac..ddf2ad3 100644 (file)
@@ -270,9 +270,16 @@ static int ucsi_register_altmode(struct ucsi_connector *con,
 
                switch (desc->svid) {
                case USB_TYPEC_DP_SID:
-               case USB_TYPEC_NVIDIA_VLINK_SID:
                        alt = ucsi_register_displayport(con, override, i, desc);
                        break;
+               case USB_TYPEC_NVIDIA_VLINK_SID:
+                       if (desc->vdo == USB_TYPEC_NVIDIA_VLINK_DBG_VDO)
+                               alt = typec_port_register_altmode(con->port,
+                                                                 desc);
+                       else
+                               alt = ucsi_register_displayport(con, override,
+                                                               i, desc);
+                       break;
                default:
                        alt = typec_port_register_altmode(con->port, desc);
                        break;
@@ -400,7 +407,7 @@ static int ucsi_register_altmodes(struct ucsi_connector *con, u8 recipient)
        struct typec_altmode_desc desc;
        struct ucsi_altmode alt[2];
        u64 command;
-       int num = 1;
+       int num;
        int ret;
        int len;
        int j;
@@ -475,7 +482,8 @@ static void ucsi_unregister_altmodes(struct ucsi_connector *con, u8 recipient)
        while (adev[i]) {
                if (recipient == UCSI_RECIPIENT_SOP &&
                    (adev[i]->svid == USB_TYPEC_DP_SID ||
-                       adev[i]->svid == USB_TYPEC_NVIDIA_VLINK_SID)) {
+                       (adev[i]->svid == USB_TYPEC_NVIDIA_VLINK_SID &&
+                       adev[i]->vdo != USB_TYPEC_NVIDIA_VLINK_DBG_VDO))) {
                        pdev = typec_altmode_get_partner(adev[i]);
                        ucsi_displayport_remove_partner((void *)pdev);
                }
index e434b9c..a89112b 100644 (file)
@@ -340,4 +340,11 @@ static inline void
 ucsi_displayport_remove_partner(struct typec_altmode *adev) { }
 #endif /* CONFIG_TYPEC_DP_ALTMODE */
 
+/*
+ * NVIDIA VirtualLink (svid 0x955) has two altmode. VirtualLink
+ * DP mode with vdo=0x1 and NVIDIA test mode with vdo=0x3
+ */
+#define USB_TYPEC_NVIDIA_VLINK_DP_VDO  0x1
+#define USB_TYPEC_NVIDIA_VLINK_DBG_VDO 0x3
+
 #endif /* __DRIVER_USB_TYPEC_UCSI_H */
index a5b8530..2658cda 100644 (file)
@@ -1219,6 +1219,7 @@ static int ccg_restart(struct ucsi_ccg *uc)
                return status;
        }
 
+       pm_runtime_enable(uc->dev);
        return 0;
 }
 
@@ -1234,6 +1235,7 @@ static void ccg_update_firmware(struct work_struct *work)
 
        if (flash_mode != FLASH_NOT_NEEDED) {
                ucsi_unregister(uc->ucsi);
+               pm_runtime_disable(uc->dev);
                free_irq(uc->irq, uc);
 
                ccg_fw_update(uc, flash_mode);
index e656e7b..9f3c721 100644 (file)
@@ -325,7 +325,7 @@ struct usb_interface_cache {
 
        /* variable-length array of alternate settings for this interface,
         * stored in no particular order */
-       struct usb_host_interface altsetting[0];
+       struct usb_host_interface altsetting[];
 };
 #define        ref_to_usb_interface_cache(r) \
                container_of(r, struct usb_interface_cache, ref)
@@ -708,6 +708,7 @@ struct usb_device {
        unsigned lpm_disable_count;
 
        u16 hub_delay;
+       unsigned use_generic_driver:1;
 };
 #define        to_usb_device(d) container_of(d, struct usb_device, dev)
 
@@ -1228,12 +1229,16 @@ struct usb_driver {
  * @drvwrap: Driver-model core structure wrapper.
  * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend
  *     for devices bound to this driver.
+ * @generic_subclass: if set to 1, the generic USB driver's probe, disconnect,
+ *     resume and suspend functions will be called in addition to the driver's
+ *     own, so this part of the setup does not need to be replicated.
  *
  * USB drivers must provide all the fields listed above except drvwrap.
  */
 struct usb_device_driver {
        const char *name;
 
+       bool (*match) (struct usb_device *udev);
        int (*probe) (struct usb_device *udev);
        void (*disconnect) (struct usb_device *udev);
 
@@ -1241,7 +1246,9 @@ struct usb_device_driver {
        int (*resume) (struct usb_device *udev, pm_message_t message);
        const struct attribute_group **dev_groups;
        struct usbdrv_wrap drvwrap;
+       const struct usb_device_id *id_table;
        unsigned int supports_autosuspend:1;
+       unsigned int generic_subclass:1;
 };
 #define        to_usb_device_driver(d) container_of(d, struct usb_device_driver, \
                drvwrap.driver)
@@ -1582,7 +1589,7 @@ struct urb {
        int error_count;                /* (return) number of ISO errors */
        void *context;                  /* (in) context for completion */
        usb_complete_t complete;        /* (in) completion routine */
-       struct usb_iso_packet_descriptor iso_frame_desc[0];
+       struct usb_iso_packet_descriptor iso_frame_desc[];
                                        /* (in) ISO ONLY */
 };
 
index ba4b3e3..5e31740 100644 (file)
@@ -153,7 +153,7 @@ struct uac2_feature_unit_descriptor {
        __u8 bSourceID;
        /* bmaControls is actually u32,
         * but u8 is needed for the hybrid parser */
-       __u8 bmaControls[0]; /* variable length */
+       __u8 bmaControls[]; /* variable length */
 } __attribute__((packed));
 
 /* 4.9.2 Class-Specific AS Interface Descriptor */
index 6b70843..c69a6f2 100644 (file)
@@ -109,7 +109,7 @@ struct uac3_feature_unit_descriptor {
        __u8 bSourceID;
        /* bmaControls is actually u32,
         * but u8 is needed for the hybrid parser */
-       __u8 bmaControls[0]; /* variable length */
+       __u8 bmaControls[]; /* variable length */
        /* wFeatureDescrStr omitted */
 } __attribute__((packed));
 
index a15ce99..78e0063 100644 (file)
@@ -151,7 +151,7 @@ struct ehci_regs {
 #define PORT_OWNER     (1<<13)         /* true: companion hc owns this port */
 #define PORT_POWER     (1<<12)         /* true: has power (see PPC) */
 #define PORT_USB11(x) (((x)&(3<<10)) == (1<<10))       /* USB 1.1 device */
-/* 11:10 for detecting lowspeed devices (reset vs release ownership) */
+#define PORT_LS_MASK   (3<<10)         /* Link status (SE0, K or J */
 /* 9 reserved */
 #define PORT_LPM       (1<<9)          /* LPM transaction */
 #define PORT_RESET     (1<<8)          /* reset port */
index 124462d..9411c08 100644 (file)
@@ -767,7 +767,7 @@ struct usb_gadget_strings {
 
 struct usb_gadget_string_container {
        struct list_head        list;
-       u8                      *stash[0];
+       u8                      *stash[];
 };
 
 /* put descriptor for string with that id into buf (buflen >= 256) */
index 712b2a6..e12105e 100644 (file)
@@ -228,7 +228,7 @@ struct usb_hcd {
        /* The HC driver's private data is stored at the end of
         * this structure.
         */
-       unsigned long hcd_priv[0]
+       unsigned long hcd_priv[]
                        __attribute__ ((aligned(sizeof(s64))));
 };
 
index c358b3f..44d2838 100644 (file)
@@ -198,8 +198,6 @@ struct typec_operations {
  * @pd_revision: USB Power Delivery Specification revision if supported
  * @prefer_role: Initial role preference (DRP ports).
  * @accessory: Supported Accessory Modes
- * @sw: Cable plug orientation switch
- * @mux: Multiplexer switch for Alternate/Accessory Modes
  * @fwnode: Optional fwnode of the port
  * @driver_data: Private pointer for driver specific info
  * @ops: Port operations vector
index 923ff3a..d834e23 100644 (file)
@@ -126,13 +126,6 @@ void typec_altmode_put_plug(struct typec_altmode *plug);
 struct typec_altmode *typec_match_altmode(struct typec_altmode **altmodes,
                                          size_t n, u16 svid, u8 mode);
 
-struct typec_altmode *
-typec_altmode_register_notifier(struct device *dev, u16 svid, u8 mode,
-                               struct notifier_block *nb);
-
-void typec_altmode_unregister_notifier(struct typec_altmode *adev,
-                                      struct notifier_block *nb);
-
 /**
  * typec_altmode_get_orientation - Get cable plug orientation
  * altmode: Handle to the alternate mode
index 000a595..4a19ac3 100644 (file)
@@ -92,6 +92,6 @@ enum { US_DO_ALL_FLAGS };
 #include <linux/usb/storage.h>
 
 extern int usb_usual_ignore_device(struct usb_interface *intf);
-extern struct usb_device_id usb_storage_usb_ids[];
+extern const struct usb_device_id usb_storage_usb_ids[];
 
 #endif /* __LINUX_USB_USUAL_H */
index 79aab00..14ea197 100644 (file)
@@ -69,7 +69,7 @@ struct usbdevfs_urb32 {
        compat_int_t error_count;
        compat_uint_t signr;
        compat_caddr_t usercontext; /* unused */
-       struct usbdevfs_iso_packet_desc iso_frame_desc[0];
+       struct usbdevfs_iso_packet_desc iso_frame_desc[];
 };
 
 struct usbdevfs_ioctl32 {