]> Git Repo - J-linux.git/commitdiff
Merge 6.9-rc7 into usb-next
authorGreg Kroah-Hartman <[email protected]>
Fri, 10 May 2024 08:38:01 +0000 (09:38 +0100)
committerGreg Kroah-Hartman <[email protected]>
Fri, 10 May 2024 08:38:01 +0000 (09:38 +0100)
We want the USB fixes in here as well, and resolve a merge conflict in
drivers/usb/dwc3/core.c

Signed-off-by: Greg Kroah-Hartman <[email protected]>
1  2 
MAINTAINERS
drivers/usb/core/hub.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/uvc_configfs.c

diff --combined MAINTAINERS
index 7d1f4b1fb4c2bcf2b8fec7ea89cf263a3a7692dc,ec0284125e8f706cf4a6f6da241493ce8150e5fe..622ab3209d90a9042cff19f773c6a38cf83ef78c
@@@ -553,7 -553,7 +553,7 @@@ F: Documentation/devicetree/bindings/ii
  F:    drivers/input/misc/adxl34x.c
  
  ADXL355 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
- M:    Puranjay Mohan <puranjay[email protected]>
+ M:    Puranjay Mohan <puranjay@kernel.org>
  L:    [email protected]
  S:    Supported
  F:    Documentation/devicetree/bindings/iio/accel/adi,adxl355.yaml
@@@ -3022,6 -3022,8 +3022,6 @@@ F:      drivers/mmc/host/wmt-sdmmc.
  F:    drivers/pwm/pwm-vt8500.c
  F:    drivers/rtc/rtc-vt8500.c
  F:    drivers/tty/serial/vt8500_serial.c
 -F:    drivers/usb/host/ehci-platform.c
 -F:    drivers/usb/host/uhci-platform.c
  F:    drivers/video/fbdev/vt8500lcdfb.*
  F:    drivers/video/fbdev/wm8505fb*
  F:    drivers/video/fbdev/wmt_ge_rops.*
@@@ -3712,7 -3714,7 +3712,7 @@@ F:      drivers/iio/imu/bmi323
  
  BPF JIT for ARM
  M:    Russell King <[email protected]>
- M:    Puranjay Mohan <puranjay[email protected]>
+ M:    Puranjay Mohan <puranjay@kernel.org>
  L:    [email protected]
  S:    Maintained
  F:    arch/arm/net/
@@@ -3762,6 -3764,8 +3762,8 @@@ X:      arch/riscv/net/bpf_jit_comp64.
  
  BPF JIT for RISC-V (64-bit)
  M:    Björn Töpel <[email protected]>
+ R:    Pu Lehui <[email protected]>
+ R:    Puranjay Mohan <[email protected]>
  L:    [email protected]
  S:    Maintained
  F:    arch/riscv/net/
@@@ -4189,7 -4193,6 +4191,6 @@@ S:      Supporte
  F:    drivers/scsi/bnx2i/
  
  BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
- M:    Ariel Elior <[email protected]>
  M:    Sudarsana Kalluru <[email protected]>
  M:    Manish Chopra <[email protected]>
  L:    [email protected]
@@@ -7827,9 -7830,8 +7828,8 @@@ W:      http://aeschi.ch.eu.org/efs
  F:    fs/efs/
  
  EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER
- M:    Douglas Miller <[email protected]>
  L:    [email protected]
- S:    Maintained
+ S:    Orphan
  F:    drivers/net/ethernet/ibm/ehea/
  
  ELM327 CAN NETWORK DRIVER
@@@ -9574,7 -9576,7 +9574,7 @@@ F:      kernel/power
  
  HID CORE LAYER
  M:    Jiri Kosina <[email protected]>
- M:    Benjamin Tissoires <ben[email protected]>
+ M:    Benjamin Tissoires <ben[email protected]>
  L:    [email protected]
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git
@@@ -15159,9 -15161,8 +15159,8 @@@ F:   drivers/scsi/myrb.
  F:    drivers/scsi/myrs.*
  
  MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
- M:    Chris Lee <[email protected]>
  L:    [email protected]
- S:    Supported
+ S:    Orphan
  W:    https://www.cspi.com/ethernet-products/support/downloads/
  F:    drivers/net/ethernet/myricom/myri10ge/
  
@@@ -16438,8 -16439,8 +16437,8 @@@ ONBOARD USB HUB DRIVE
  M:    Matthias Kaehlcke <[email protected]>
  L:    [email protected]
  S:    Maintained
 -F:    Documentation/ABI/testing/sysfs-bus-platform-onboard-usb-hub
 -F:    drivers/usb/misc/onboard_usb_hub.c
 +F:    Documentation/ABI/testing/sysfs-bus-platform-onboard-usb-dev
 +F:    drivers/usb/misc/onboard_usb_dev.c
  
  ONENAND FLASH DRIVER
  M:    Kyungmin Park <[email protected]>
@@@ -16797,12 -16798,6 +16796,6 @@@ S:  Maintaine
  F:    drivers/leds/leds-pca9532.c
  F:    include/linux/leds-pca9532.h
  
- PCA9541 I2C BUS MASTER SELECTOR DRIVER
- M:    Guenter Roeck <[email protected]>
- L:    [email protected]
- S:    Maintained
- F:    drivers/i2c/muxes/i2c-mux-pca9541.c
  PCI DRIVER FOR AARDVARK (Marvell Armada 3700)
  M:    Thomas Petazzoni <[email protected]>
  M:    Pali Rohár <[email protected]>
@@@ -17871,7 -17866,7 +17864,7 @@@ F:   Documentation/devicetree/bindings/le
  F:    drivers/media/rc/pwm-ir-tx.c
  
  PWM SUBSYSTEM
- M:    Uwe Kleine-König <u[email protected]>
+ M:    Uwe Kleine-König <u[email protected]>
  L:    [email protected]
  S:    Maintained
  Q:    https://patchwork.ozlabs.org/project/linux-pwm/list/
@@@ -17995,7 -17990,6 +17988,6 @@@ S:   Supporte
  F:    drivers/scsi/qedi/
  
  QLOGIC QL4xxx ETHERNET DRIVER
- M:    Ariel Elior <[email protected]>
  M:    Manish Chopra <[email protected]>
  L:    [email protected]
  S:    Supported
@@@ -18005,7 -17999,6 +17997,6 @@@ F:   include/linux/qed
  
  QLOGIC QL4xxx RDMA DRIVER
  M:    Michal Kalderon <[email protected]>
- M:    Ariel Elior <[email protected]>
  L:    [email protected]
  S:    Supported
  F:    drivers/infiniband/hw/qedr/
@@@ -20175,7 -20168,6 +20166,6 @@@ F:   include/linux/platform_data/simplefb
  
  SIOX
  M:    Thorsten Scherer <[email protected]>
- M:    Uwe Kleine-König <[email protected]>
  R:    Pengutronix Kernel Team <[email protected]>
  S:    Supported
  F:    drivers/gpio/gpio-siox.c
@@@ -21924,7 -21916,7 +21914,7 @@@ F:   include/linux/soc/ti/ti_sci_inta_msi
  F:    include/linux/soc/ti/ti_sci_protocol.h
  
  TEXAS INSTRUMENTS' TMP117 TEMPERATURE SENSOR DRIVER
- M:    Puranjay Mohan <puranjay[email protected]>
+ M:    Puranjay Mohan <puranjay@kernel.org>
  L:    [email protected]
  S:    Supported
  F:    Documentation/devicetree/bindings/iio/temperature/ti,tmp117.yaml
@@@ -22837,7 -22829,7 +22827,7 @@@ F:   drivers/usb/host/ehci
  
  USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...)
  M:    Jiri Kosina <[email protected]>
- M:    Benjamin Tissoires <ben[email protected]>
+ M:    Benjamin Tissoires <ben[email protected]>
  L:    [email protected]
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git
@@@ -24465,6 -24457,14 +24455,14 @@@ T: git git://git.kernel.org/pub/scm/lin
  F:    Documentation/admin-guide/LSM/Yama.rst
  F:    security/yama/
  
+ YAML NETLINK (YNL)
+ M:    Donald Hunter <[email protected]>
+ M:    Jakub Kicinski <[email protected]>
+ F:    Documentation/netlink/
+ F:    Documentation/userspace-api/netlink/intro-specs.rst
+ F:    Documentation/userspace-api/netlink/specs.rst
+ F:    tools/net/ynl/
  YEALINK PHONE DRIVER
  M:    Henk Vergonet <[email protected]>
  L:    [email protected]
diff --combined drivers/usb/core/hub.c
index bd2e57f90e71361bc8d94ca6d5bb8e5b61eef9df,008053039875a4c6d3fc9b8822491c97eadd0abe..4b93c0bd1d4bcc8141ca34c490f67e2a368c1902
@@@ -23,7 -23,7 +23,7 @@@
  #include <linux/usb.h>
  #include <linux/usbdevice_fs.h>
  #include <linux/usb/hcd.h>
 -#include <linux/usb/onboard_hub.h>
 +#include <linux/usb/onboard_dev.h>
  #include <linux/usb/otg.h>
  #include <linux/usb/quirks.h>
  #include <linux/workqueue.h>
@@@ -1814,7 -1814,7 +1814,7 @@@ static void hub_disconnect(struct usb_i
        if (hub->quirk_disable_autosuspend)
                usb_autopm_put_interface(intf);
  
 -      onboard_hub_destroy_pdevs(&hub->onboard_hub_devs);
 +      onboard_dev_destroy_pdevs(&hub->onboard_devs);
  
        hub_put(hub);
  }
@@@ -1933,7 -1933,7 +1933,7 @@@ static int hub_probe(struct usb_interfa
        INIT_DELAYED_WORK(&hub->leds, led_work);
        INIT_DELAYED_WORK(&hub->init_work, NULL);
        INIT_WORK(&hub->events, hub_event);
 -      INIT_LIST_HEAD(&hub->onboard_hub_devs);
 +      INIT_LIST_HEAD(&hub->onboard_devs);
        spin_lock_init(&hub->irq_urb_lock);
        timer_setup(&hub->irq_urb_retry, hub_retry_irq_urb, 0);
        usb_get_intf(intf);
        }
  
        if (hub_configure(hub, &desc->endpoint[0].desc) >= 0) {
 -              onboard_hub_create_pdevs(hdev, &hub->onboard_hub_devs);
 +              onboard_dev_create_pdevs(hdev, &hub->onboard_devs);
  
                return 0;
        }
@@@ -2207,12 -2207,13 +2207,12 @@@ static void choose_devnum(struct usb_de
        mutex_lock(&bus->devnum_next_mutex);
  
        /* Try to allocate the next devnum beginning at bus->devnum_next. */
 -      devnum = find_next_zero_bit(bus->devmap.devicemap, 128,
 -                      bus->devnum_next);
 +      devnum = find_next_zero_bit(bus->devmap, 128, bus->devnum_next);
        if (devnum >= 128)
 -              devnum = find_next_zero_bit(bus->devmap.devicemap, 128, 1);
 +              devnum = find_next_zero_bit(bus->devmap, 128, 1);
        bus->devnum_next = (devnum >= 127 ? 1 : devnum + 1);
        if (devnum < 128) {
 -              set_bit(devnum, bus->devmap.devicemap);
 +              set_bit(devnum, bus->devmap);
                udev->devnum = devnum;
        }
        mutex_unlock(&bus->devnum_next_mutex);
  static void release_devnum(struct usb_device *udev)
  {
        if (udev->devnum > 0) {
 -              clear_bit(udev->devnum, udev->bus->devmap.devicemap);
 +              clear_bit(udev->devnum, udev->bus->devmap);
                udev->devnum = -1;
        }
  }
@@@ -5109,9 -5110,10 +5109,10 @@@ hub_port_init(struct usb_hub *hub, stru
        }
        if (usb_endpoint_maxp(&udev->ep0.desc) == i) {
                ;       /* Initial ep0 maxpacket guess is right */
-       } else if ((udev->speed == USB_SPEED_FULL ||
+       } else if (((udev->speed == USB_SPEED_FULL ||
                                udev->speed == USB_SPEED_HIGH) &&
-                       (i == 8 || i == 16 || i == 32 || i == 64)) {
+                       (i == 8 || i == 16 || i == 32 || i == 64)) ||
+                       (udev->speed >= USB_SPEED_SUPER && i > 0)) {
                /* Initial guess is wrong; use the descriptor's value */
                if (udev->speed == USB_SPEED_FULL)
                        dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
diff --combined drivers/usb/dwc3/core.c
index 719305ab86c0b0f3413199a75647f4dcdef2f4a7,100041320e8dd2e80488b7dfdc372d373ea0d251..5c6a7e99a4b9e25c60d3efbc2020a0d1bc9a359c
@@@ -39,7 -39,6 +39,7 @@@
  #include "io.h"
  
  #include "debug.h"
 +#include "../host/xhci-ext-caps.h"
  
  #define DWC3_DEFAULT_AUTOSUSPEND_DELAY        5000 /* ms */
  
@@@ -105,6 -104,27 +105,27 @@@ static int dwc3_get_dr_mode(struct dwc
        return 0;
  }
  
+ void dwc3_enable_susphy(struct dwc3 *dwc, bool enable)
+ {
+       u32 reg;
+       reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
+       if (enable && !dwc->dis_u3_susphy_quirk)
+               reg |= DWC3_GUSB3PIPECTL_SUSPHY;
+       else
+               reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
+       dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
+       reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+       if (enable && !dwc->dis_u2_susphy_quirk)
+               reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+       else
+               reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+       dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+ }
  void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
  {
        u32 reg;
@@@ -124,7 -144,6 +145,7 @@@ static void __dwc3_set_mode(struct work
        int ret;
        u32 reg;
        u32 desired_dr_role;
 +      int i;
  
        mutex_lock(&dwc->mutex);
        spin_lock_irqsave(&dwc->lock, flags);
                } else {
                        if (dwc->usb2_phy)
                                otg_set_vbus(dwc->usb2_phy->otg, true);
 -                      phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
 -                      phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);
 +
 +                      for (i = 0; i < dwc->num_usb2_ports; i++)
 +                              phy_set_mode(dwc->usb2_generic_phy[i], PHY_MODE_USB_HOST);
 +                      for (i = 0; i < dwc->num_usb3_ports; i++)
 +                              phy_set_mode(dwc->usb3_generic_phy[i], PHY_MODE_USB_HOST);
 +
                        if (dwc->dis_split_quirk) {
                                reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);
                                reg |= DWC3_GUCTL3_SPLITDISABLE;
  
                if (dwc->usb2_phy)
                        otg_set_vbus(dwc->usb2_phy->otg, false);
 -              phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);
 -              phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE);
 +              phy_set_mode(dwc->usb2_generic_phy[0], PHY_MODE_USB_DEVICE);
 +              phy_set_mode(dwc->usb3_generic_phy[0], PHY_MODE_USB_DEVICE);
  
                ret = dwc3_gadget_init(dwc);
                if (ret)
@@@ -491,13 -506,6 +512,13 @@@ static void dwc3_free_event_buffers(str
  static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned int length)
  {
        struct dwc3_event_buffer *evt;
 +      unsigned int hw_mode;
 +
 +      hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
 +      if (hw_mode == DWC3_GHWPARAMS0_MODE_HOST) {
 +              dwc->ev_buf = NULL;
 +              return 0;
 +      }
  
        evt = dwc3_alloc_one_event_buffer(dwc, length);
        if (IS_ERR(evt)) {
@@@ -519,9 -527,6 +540,9 @@@ int dwc3_event_buffers_setup(struct dwc
  {
        struct dwc3_event_buffer        *evt;
  
 +      if (!dwc->ev_buf)
 +              return 0;
 +
        evt = dwc->ev_buf;
        evt->lpos = 0;
        dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0),
@@@ -539,9 -544,6 +560,9 @@@ void dwc3_event_buffers_cleanup(struct 
  {
        struct dwc3_event_buffer        *evt;
  
 +      if (!dwc->ev_buf)
 +              return;
 +
        evt = dwc->ev_buf;
  
        evt->lpos = 0;
@@@ -594,14 -596,19 +615,11 @@@ static int dwc3_core_ulpi_init(struct d
        return ret;
  }
  
 -/**
 - * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
 - * @dwc: Pointer to our controller context structure
 - *
 - * Returns 0 on success. The USB PHY interfaces are configured but not
 - * initialized. The PHY interfaces and the PHYs get initialized together with
 - * the core in dwc3_core_init.
 - */
 -static int dwc3_phy_setup(struct dwc3 *dwc)
 +static int dwc3_ss_phy_setup(struct dwc3 *dwc, int index)
  {
-       unsigned int hw_mode;
        u32 reg;
  
-       hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
 -      reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
 +      reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(index));
  
        /*
         * Make sure UX_EXIT_PX is cleared as that causes issues with some
        reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX;
  
        /*
-        * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
-        * to '0' during coreConsultant configuration. So default value
-        * will be '0' when the core is reset. Application needs to set it
-        * to '1' after the core initialization is completed.
-        */
-       if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A))
-               reg |= DWC3_GUSB3PIPECTL_SUSPHY;
-       /*
-        * For DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be cleared after
-        * power-on reset, and it can be set after core initialization, which is
-        * after device soft-reset during initialization.
+        * Above DWC_usb3.0 1.94a, it is recommended to set
+        * DWC3_GUSB3PIPECTL_SUSPHY to '0' during coreConsultant configuration.
+        * So default value will be '0' when the core is reset. Application
+        * needs to set it to '1' after the core initialization is completed.
+        *
+        * Similarly for DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be
+        * cleared after power-on reset, and it can be set after core
+        * initialization.
         */
-       if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
-               reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
+       reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
  
        if (dwc->u2ss_inp3_quirk)
                reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
        if (dwc->tx_de_emphasis_quirk)
                reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
  
-       if (dwc->dis_u3_susphy_quirk)
-               reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
        if (dwc->dis_del_phy_power_chg_quirk)
                reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE;
  
 -      dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
 +      dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(index), reg);
  
 -      reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
 +      return 0;
 +}
 +
 +static int dwc3_hs_phy_setup(struct dwc3 *dwc, int index)
 +{
 +      unsigned int hw_mode;
 +      u32 reg;
 +
 +      hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
 +
 +      reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(index));
  
        /* Select the HS PHY interface */
        switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) {
                } else if (dwc->hsphy_interface &&
                                !strncmp(dwc->hsphy_interface, "ulpi", 4)) {
                        reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI;
 -                      dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 +                      dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(index), reg);
                } else {
                        /* Relying on default value. */
                        if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI))
        }
  
        /*
-        * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
-        * '0' during coreConsultant configuration. So default value will
-        * be '0' when the core is reset. Application needs to set it to
-        * '1' after the core initialization is completed.
-        */
-       if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A))
-               reg |= DWC3_GUSB2PHYCFG_SUSPHY;
-       /*
-        * For DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared after
-        * power-on reset, and it can be set after core initialization, which is
-        * after device soft-reset during initialization.
+        * Above DWC_usb3.0 1.94a, it is recommended to set
+        * DWC3_GUSB2PHYCFG_SUSPHY to '0' during coreConsultant configuration.
+        * So default value will be '0' when the core is reset. Application
+        * needs to set it to '1' after the core initialization is completed.
+        *
+        * Similarly for DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared
+        * after power-on reset, and it can be set after core initialization.
         */
-       if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
-               reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
-       if (dwc->dis_u2_susphy_quirk)
-               reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+       reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
  
        if (dwc->dis_enblslpm_quirk)
                reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
        if (dwc->ulpi_ext_vbus_drv)
                reg |= DWC3_GUSB2PHYCFG_ULPIEXTVBUSDRV;
  
 -      dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 +      dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(index), reg);
 +
 +      return 0;
 +}
 +
 +/**
 + * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
 + * @dwc: Pointer to our controller context structure
 + *
 + * Returns 0 on success. The USB PHY interfaces are configured but not
 + * initialized. The PHY interfaces and the PHYs get initialized together with
 + * the core in dwc3_core_init.
 + */
 +static int dwc3_phy_setup(struct dwc3 *dwc)
 +{
 +      int i;
 +      int ret;
 +
 +      for (i = 0; i < dwc->num_usb3_ports; i++) {
 +              ret = dwc3_ss_phy_setup(dwc, i);
 +              if (ret)
 +                      return ret;
 +      }
 +
 +      for (i = 0; i < dwc->num_usb2_ports; i++) {
 +              ret = dwc3_hs_phy_setup(dwc, i);
 +              if (ret)
 +                      return ret;
 +      }
  
        return 0;
  }
  static int dwc3_phy_init(struct dwc3 *dwc)
  {
        int ret;
 +      int i;
 +      int j;
  
        usb_phy_init(dwc->usb2_phy);
        usb_phy_init(dwc->usb3_phy);
  
 -      ret = phy_init(dwc->usb2_generic_phy);
 -      if (ret < 0)
 -              goto err_shutdown_usb3_phy;
 +      for (i = 0; i < dwc->num_usb2_ports; i++) {
 +              ret = phy_init(dwc->usb2_generic_phy[i]);
 +              if (ret < 0)
 +                      goto err_exit_usb2_phy;
 +      }
  
 -      ret = phy_init(dwc->usb3_generic_phy);
 -      if (ret < 0)
 -              goto err_exit_usb2_phy;
 +      for (j = 0; j < dwc->num_usb3_ports; j++) {
 +              ret = phy_init(dwc->usb3_generic_phy[j]);
 +              if (ret < 0)
 +                      goto err_exit_usb3_phy;
 +      }
  
        return 0;
  
 +err_exit_usb3_phy:
 +      while (--j >= 0)
 +              phy_exit(dwc->usb3_generic_phy[j]);
 +
  err_exit_usb2_phy:
 -      phy_exit(dwc->usb2_generic_phy);
 -err_shutdown_usb3_phy:
 +      while (--i >= 0)
 +              phy_exit(dwc->usb2_generic_phy[i]);
 +
        usb_phy_shutdown(dwc->usb3_phy);
        usb_phy_shutdown(dwc->usb2_phy);
  
  
  static void dwc3_phy_exit(struct dwc3 *dwc)
  {
 -      phy_exit(dwc->usb3_generic_phy);
 -      phy_exit(dwc->usb2_generic_phy);
 +      int i;
 +
 +      for (i = 0; i < dwc->num_usb3_ports; i++)
 +              phy_exit(dwc->usb3_generic_phy[i]);
 +
 +      for (i = 0; i < dwc->num_usb2_ports; i++)
 +              phy_exit(dwc->usb2_generic_phy[i]);
  
        usb_phy_shutdown(dwc->usb3_phy);
        usb_phy_shutdown(dwc->usb2_phy);
  static int dwc3_phy_power_on(struct dwc3 *dwc)
  {
        int ret;
 +      int i;
 +      int j;
  
        usb_phy_set_suspend(dwc->usb2_phy, 0);
        usb_phy_set_suspend(dwc->usb3_phy, 0);
  
 -      ret = phy_power_on(dwc->usb2_generic_phy);
 -      if (ret < 0)
 -              goto err_suspend_usb3_phy;
 +      for (i = 0; i < dwc->num_usb2_ports; i++) {
 +              ret = phy_power_on(dwc->usb2_generic_phy[i]);
 +              if (ret < 0)
 +                      goto err_power_off_usb2_phy;
 +      }
  
 -      ret = phy_power_on(dwc->usb3_generic_phy);
 -      if (ret < 0)
 -              goto err_power_off_usb2_phy;
 +      for (j = 0; j < dwc->num_usb3_ports; j++) {
 +              ret = phy_power_on(dwc->usb3_generic_phy[j]);
 +              if (ret < 0)
 +                      goto err_power_off_usb3_phy;
 +      }
  
        return 0;
  
 +err_power_off_usb3_phy:
 +      while (--j >= 0)
 +              phy_power_off(dwc->usb3_generic_phy[j]);
 +
  err_power_off_usb2_phy:
 -      phy_power_off(dwc->usb2_generic_phy);
 -err_suspend_usb3_phy:
 +      while (--i >= 0)
 +              phy_power_off(dwc->usb2_generic_phy[i]);
 +
        usb_phy_set_suspend(dwc->usb3_phy, 1);
        usb_phy_set_suspend(dwc->usb2_phy, 1);
  
  
  static void dwc3_phy_power_off(struct dwc3 *dwc)
  {
 -      phy_power_off(dwc->usb3_generic_phy);
 -      phy_power_off(dwc->usb2_generic_phy);
 +      int i;
 +
 +      for (i = 0; i < dwc->num_usb3_ports; i++)
 +              phy_power_off(dwc->usb3_generic_phy[i]);
 +
 +      for (i = 0; i < dwc->num_usb2_ports; i++)
 +              phy_power_off(dwc->usb2_generic_phy[i]);
  
        usb_phy_set_suspend(dwc->usb3_phy, 1);
        usb_phy_set_suspend(dwc->usb2_phy, 1);
@@@ -1268,7 -1188,6 +1269,6 @@@ static int dwc3_core_init(struct dwc3 *
        unsigned int            hw_mode;
        u32                     reg;
        int                     ret;
-       int                     i;
  
        hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
  
        if (ret)
                goto err_exit_phy;
  
-       if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD &&
-           !DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) {
-               if (!dwc->dis_u3_susphy_quirk) {
-                       for (i = 0; i < dwc->num_usb3_ports; i++) {
-                               reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(i));
-                               reg |= DWC3_GUSB3PIPECTL_SUSPHY;
-                               dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(i), reg);
-                       }
-               }
-               if (!dwc->dis_u2_susphy_quirk) {
-                       for (i = 0; i < dwc->num_usb2_ports; i++) {
-                               reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(i));
-                               reg |= DWC3_GUSB2PHYCFG_SUSPHY;
-                               dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(i), reg);
-                       }
-               }
-       }
        dwc3_core_setup_global_control(dwc);
        dwc3_core_num_eps(dwc);
  
                if (dwc->parkmode_disable_hs_quirk)
                        reg |= DWC3_GUCTL1_PARKMODE_DISABLE_HS;
  
 -              if (DWC3_VER_IS_WITHIN(DWC3, 290A, ANY) &&
 -                  (dwc->maximum_speed == USB_SPEED_HIGH ||
 -                   dwc->maximum_speed == USB_SPEED_FULL))
 -                      reg |= DWC3_GUCTL1_DEV_FORCE_20_CLK_FOR_30_CLK;
 +              if (DWC3_VER_IS_WITHIN(DWC3, 290A, ANY)) {
 +                      if (dwc->maximum_speed == USB_SPEED_FULL ||
 +                          dwc->maximum_speed == USB_SPEED_HIGH)
 +                              reg |= DWC3_GUCTL1_DEV_FORCE_20_CLK_FOR_30_CLK;
 +                      else
 +                              reg &= ~DWC3_GUCTL1_DEV_FORCE_20_CLK_FOR_30_CLK;
 +              }
  
                dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
        }
@@@ -1447,9 -1344,7 +1428,9 @@@ static int dwc3_core_get_phy(struct dwc
  {
        struct device           *dev = dwc->dev;
        struct device_node      *node = dev->of_node;
 +      char phy_name[9];
        int ret;
 +      u8 i;
  
        if (node) {
                dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
                        return dev_err_probe(dev, ret, "no usb3 phy configured\n");
        }
  
 -      dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
 -      if (IS_ERR(dwc->usb2_generic_phy)) {
 -              ret = PTR_ERR(dwc->usb2_generic_phy);
 -              if (ret == -ENOSYS || ret == -ENODEV)
 -                      dwc->usb2_generic_phy = NULL;
 +      for (i = 0; i < dwc->num_usb2_ports; i++) {
 +              if (dwc->num_usb2_ports == 1)
 +                      snprintf(phy_name, sizeof(phy_name), "usb2-phy");
                else
 -                      return dev_err_probe(dev, ret, "no usb2 phy configured\n");
 +                      snprintf(phy_name, sizeof(phy_name),  "usb2-%u", i);
 +
 +              dwc->usb2_generic_phy[i] = devm_phy_get(dev, phy_name);
 +              if (IS_ERR(dwc->usb2_generic_phy[i])) {
 +                      ret = PTR_ERR(dwc->usb2_generic_phy[i]);
 +                      if (ret == -ENOSYS || ret == -ENODEV)
 +                              dwc->usb2_generic_phy[i] = NULL;
 +                      else
 +                              return dev_err_probe(dev, ret, "failed to lookup phy %s\n",
 +                                                      phy_name);
 +              }
        }
  
 -      dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
 -      if (IS_ERR(dwc->usb3_generic_phy)) {
 -              ret = PTR_ERR(dwc->usb3_generic_phy);
 -              if (ret == -ENOSYS || ret == -ENODEV)
 -                      dwc->usb3_generic_phy = NULL;
 +      for (i = 0; i < dwc->num_usb3_ports; i++) {
 +              if (dwc->num_usb3_ports == 1)
 +                      snprintf(phy_name, sizeof(phy_name), "usb3-phy");
                else
 -                      return dev_err_probe(dev, ret, "no usb3 phy configured\n");
 +                      snprintf(phy_name, sizeof(phy_name), "usb3-%u", i);
 +
 +              dwc->usb3_generic_phy[i] = devm_phy_get(dev, phy_name);
 +              if (IS_ERR(dwc->usb3_generic_phy[i])) {
 +                      ret = PTR_ERR(dwc->usb3_generic_phy[i]);
 +                      if (ret == -ENOSYS || ret == -ENODEV)
 +                              dwc->usb3_generic_phy[i] = NULL;
 +                      else
 +                              return dev_err_probe(dev, ret, "failed to lookup phy %s\n",
 +                                                      phy_name);
 +              }
        }
  
        return 0;
@@@ -1516,7 -1395,6 +1497,7 @@@ static int dwc3_core_init_mode(struct d
  {
        struct device *dev = dwc->dev;
        int ret;
 +      int i;
  
        switch (dwc->dr_mode) {
        case USB_DR_MODE_PERIPHERAL:
  
                if (dwc->usb2_phy)
                        otg_set_vbus(dwc->usb2_phy->otg, false);
 -              phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);
 -              phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE);
 +              phy_set_mode(dwc->usb2_generic_phy[0], PHY_MODE_USB_DEVICE);
 +              phy_set_mode(dwc->usb3_generic_phy[0], PHY_MODE_USB_DEVICE);
  
                ret = dwc3_gadget_init(dwc);
                if (ret)
  
                if (dwc->usb2_phy)
                        otg_set_vbus(dwc->usb2_phy->otg, true);
 -              phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
 -              phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);
 +              for (i = 0; i < dwc->num_usb2_ports; i++)
 +                      phy_set_mode(dwc->usb2_generic_phy[i], PHY_MODE_USB_HOST);
 +              for (i = 0; i < dwc->num_usb3_ports; i++)
 +                      phy_set_mode(dwc->usb3_generic_phy[i], PHY_MODE_USB_HOST);
  
                ret = dwc3_host_init(dwc);
                if (ret)
@@@ -1991,60 -1867,10 +1972,60 @@@ static int dwc3_get_clocks(struct dwc3 
        return 0;
  }
  
 +static int dwc3_get_num_ports(struct dwc3 *dwc)
 +{
 +      void __iomem *base;
 +      u8 major_revision;
 +      u32 offset;
 +      u32 val;
 +
 +      /*
 +       * Remap xHCI address space to access XHCI ext cap regs since it is
 +       * needed to get information on number of ports present.
 +       */
 +      base = ioremap(dwc->xhci_resources[0].start,
 +                     resource_size(&dwc->xhci_resources[0]));
 +      if (!base)
 +              return -ENOMEM;
 +
 +      offset = 0;
 +      do {
 +              offset = xhci_find_next_ext_cap(base, offset,
 +                                              XHCI_EXT_CAPS_PROTOCOL);
 +              if (!offset)
 +                      break;
 +
 +              val = readl(base + offset);
 +              major_revision = XHCI_EXT_PORT_MAJOR(val);
 +
 +              val = readl(base + offset + 0x08);
 +              if (major_revision == 0x03) {
 +                      dwc->num_usb3_ports += XHCI_EXT_PORT_COUNT(val);
 +              } else if (major_revision <= 0x02) {
 +                      dwc->num_usb2_ports += XHCI_EXT_PORT_COUNT(val);
 +              } else {
 +                      dev_warn(dwc->dev, "unrecognized port major revision %d\n",
 +                               major_revision);
 +              }
 +      } while (1);
 +
 +      dev_dbg(dwc->dev, "hs-ports: %u ss-ports: %u\n",
 +              dwc->num_usb2_ports, dwc->num_usb3_ports);
 +
 +      iounmap(base);
 +
 +      if (dwc->num_usb2_ports > DWC3_USB2_MAX_PORTS ||
 +          dwc->num_usb3_ports > DWC3_USB3_MAX_PORTS)
 +              return -EINVAL;
 +
 +      return 0;
 +}
 +
  static int dwc3_probe(struct platform_device *pdev)
  {
        struct device           *dev = &pdev->dev;
        struct resource         *res, dwc_res;
 +      unsigned int            hw_mode;
        void __iomem            *regs;
        struct dwc3             *dwc;
        int                     ret;
                        goto err_disable_clks;
        }
  
 +      /*
 +       * Currently only DWC3 controllers that are host-only capable
 +       * can have more than one port.
 +       */
 +      hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
 +      if (hw_mode == DWC3_GHWPARAMS0_MODE_HOST) {
 +              ret = dwc3_get_num_ports(dwc);
 +              if (ret)
 +                      goto err_disable_clks;
 +      } else {
 +              dwc->num_usb2_ports = 1;
 +              dwc->num_usb3_ports = 1;
 +      }
 +
        spin_lock_init(&dwc->lock);
        mutex_init(&dwc->mutex);
  
@@@ -2274,7 -2086,6 +2255,7 @@@ static int dwc3_suspend_common(struct d
  {
        unsigned long   flags;
        u32 reg;
 +      int i;
  
        switch (dwc->current_dr_role) {
        case DWC3_GCTL_PRTCAP_DEVICE:
                /* Let controller to suspend HSPHY before PHY driver suspends */
                if (dwc->dis_u2_susphy_quirk ||
                    dwc->dis_enblslpm_quirk) {
 -                      reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
 -                      reg |=  DWC3_GUSB2PHYCFG_ENBLSLPM |
 -                              DWC3_GUSB2PHYCFG_SUSPHY;
 -                      dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 +                      for (i = 0; i < dwc->num_usb2_ports; i++) {
 +                              reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(i));
 +                              reg |=  DWC3_GUSB2PHYCFG_ENBLSLPM |
 +                                      DWC3_GUSB2PHYCFG_SUSPHY;
 +                              dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(i), reg);
 +                      }
  
                        /* Give some time for USB2 PHY to suspend */
                        usleep_range(5000, 6000);
                }
  
 -              phy_pm_runtime_put_sync(dwc->usb2_generic_phy);
 -              phy_pm_runtime_put_sync(dwc->usb3_generic_phy);
 +              for (i = 0; i < dwc->num_usb2_ports; i++)
 +                      phy_pm_runtime_put_sync(dwc->usb2_generic_phy[i]);
 +              for (i = 0; i < dwc->num_usb3_ports; i++)
 +                      phy_pm_runtime_put_sync(dwc->usb3_generic_phy[i]);
                break;
        case DWC3_GCTL_PRTCAP_OTG:
                /* do nothing during runtime_suspend */
@@@ -2337,7 -2144,6 +2318,7 @@@ static int dwc3_resume_common(struct dw
        unsigned long   flags;
        int             ret;
        u32             reg;
 +      int             i;
  
        switch (dwc->current_dr_role) {
        case DWC3_GCTL_PRTCAP_DEVICE:
                        break;
                }
                /* Restore GUSB2PHYCFG bits that were modified in suspend */
 -              reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
 -              if (dwc->dis_u2_susphy_quirk)
 -                      reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
 +              for (i = 0; i < dwc->num_usb2_ports; i++) {
 +                      reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(i));
 +                      if (dwc->dis_u2_susphy_quirk)
 +                              reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
  
 -              if (dwc->dis_enblslpm_quirk)
 -                      reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
 +                      if (dwc->dis_enblslpm_quirk)
 +                              reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
  
 -              dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 +                      dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(i), reg);
 +              }
  
 -              phy_pm_runtime_get_sync(dwc->usb2_generic_phy);
 -              phy_pm_runtime_get_sync(dwc->usb3_generic_phy);
 +              for (i = 0; i < dwc->num_usb2_ports; i++)
 +                      phy_pm_runtime_get_sync(dwc->usb2_generic_phy[i]);
 +              for (i = 0; i < dwc->num_usb3_ports; i++)
 +                      phy_pm_runtime_get_sync(dwc->usb3_generic_phy[i]);
                break;
        case DWC3_GCTL_PRTCAP_OTG:
                /* nothing to do on runtime_resume */
diff --combined drivers/usb/dwc3/core.h
index 5cbc64883dbc9a830d0ffa87723f63880df5ce6b,180dd8d29287c6851581e0a0d194a8c79c0959c2..3781c736c1a17e06fc58060b12ae77da873849b9
  
  #include <linux/power_supply.h>
  
 +/*
 + * DWC3 Multiport controllers support up to 15 High-Speed PHYs
 + * and 4 SuperSpeed PHYs.
 + */
 +#define DWC3_USB2_MAX_PORTS   15
 +#define DWC3_USB3_MAX_PORTS   4
 +
  #define DWC3_MSG_MAX  500
  
  /* Global constants */
@@@ -1044,10 -1037,8 +1044,10 @@@ struct dwc3_scratchpad_array 
   * @usb_psy: pointer to power supply interface.
   * @usb2_phy: pointer to USB2 PHY
   * @usb3_phy: pointer to USB3 PHY
 - * @usb2_generic_phy: pointer to USB2 PHY
 - * @usb3_generic_phy: pointer to USB3 PHY
 + * @usb2_generic_phy: pointer to array of USB2 PHYs
 + * @usb3_generic_phy: pointer to array of USB3 PHYs
 + * @num_usb2_ports: number of USB2 ports
 + * @num_usb3_ports: number of USB3 ports
   * @phys_ready: flag to indicate that PHYs are ready
   * @ulpi: pointer to ulpi interface
   * @ulpi_ready: flag to indicate that ULPI is initialized
@@@ -1193,11 -1184,8 +1193,11 @@@ struct dwc3 
        struct usb_phy          *usb2_phy;
        struct usb_phy          *usb3_phy;
  
 -      struct phy              *usb2_generic_phy;
 -      struct phy              *usb3_generic_phy;
 +      struct phy              *usb2_generic_phy[DWC3_USB2_MAX_PORTS];
 +      struct phy              *usb3_generic_phy[DWC3_USB3_MAX_PORTS];
 +
 +      u8                      num_usb2_ports;
 +      u8                      num_usb3_ports;
  
        bool                    phys_ready;
  
@@@ -1592,6 -1580,7 +1592,7 @@@ int dwc3_event_buffers_setup(struct dwc
  void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
  
  int dwc3_core_soft_reset(struct dwc3 *dwc);
+ void dwc3_enable_susphy(struct dwc3 *dwc, bool enable);
  
  #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
  int dwc3_host_init(struct dwc3 *dwc);
index 8710e32b4949e8a582da8e86f8c6d5596409f249,a057cbedf3c9b30430eeb3a8749975e58cec54da..1f21459b1188c8a6811c0cee3605067656162c6f
@@@ -45,7 -45,6 +45,7 @@@
  #include "configfs.h"
  
  #define FUNCTIONFS_MAGIC      0xa647361 /* Chosen by a honest dice roll ;) */
 +#define MAX_ALT_SETTINGS      2                 /* Allow up to 2 alt settings to be set. */
  
  #define DMABUF_ENQUEUE_TIMEOUT_MS 5000
  
@@@ -83,7 -82,6 +83,7 @@@ struct ffs_function 
        short                           *interfaces_nums;
  
        struct usb_function             function;
 +      int                             cur_alt[MAX_CONFIG_INTERFACES];
  };
  
  
@@@ -107,7 -105,6 +107,7 @@@ static int __must_check ffs_func_eps_en
  static int ffs_func_bind(struct usb_configuration *,
                         struct usb_function *);
  static int ffs_func_set_alt(struct usb_function *, unsigned, unsigned);
 +static int ffs_func_get_alt(struct usb_function *f, unsigned int intf);
  static void ffs_func_disable(struct usb_function *);
  static int ffs_func_setup(struct usb_function *,
                          const struct usb_ctrlrequest *);
@@@ -855,6 -852,7 +855,7 @@@ static void ffs_user_copy_worker(struc
                                                   work);
        int ret = io_data->status;
        bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
+       unsigned long flags;
  
        if (io_data->read && ret > 0) {
                kthread_use_mm(io_data->mm);
        if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd)
                eventfd_signal(io_data->ffs->ffs_eventfd);
  
+       spin_lock_irqsave(&io_data->ffs->eps_lock, flags);
+       usb_ep_free_request(io_data->ep, io_data->req);
+       io_data->req = NULL;
+       spin_unlock_irqrestore(&io_data->ffs->eps_lock, flags);
        if (io_data->read)
                kfree(io_data->to_free);
        ffs_free_buffer(io_data);
@@@ -880,7 -883,6 +886,6 @@@ static void ffs_epfile_async_io_complet
        struct ffs_data *ffs = io_data->ffs;
  
        io_data->status = req->status ? req->status : req->actual;
-       usb_ep_free_request(_ep, req);
  
        INIT_WORK(&io_data->work, ffs_user_copy_worker);
        queue_work(ffs->io_completion_wq, &io_data->work);
@@@ -3710,15 -3712,6 +3715,15 @@@ static void ffs_reset_work(struct work_
        ffs_data_reset(ffs);
  }
  
 +static int ffs_func_get_alt(struct usb_function *f,
 +                          unsigned int interface)
 +{
 +      struct ffs_function *func = ffs_func_from_usb(f);
 +      int intf = ffs_func_revmap_intf(func, interface);
 +
 +      return (intf < 0) ? intf : func->cur_alt[interface];
 +}
 +
  static int ffs_func_set_alt(struct usb_function *f,
                            unsigned interface, unsigned alt)
  {
        struct ffs_data *ffs = func->ffs;
        int ret = 0, intf;
  
 +      if (alt > MAX_ALT_SETTINGS)
 +              return -EINVAL;
 +
        if (alt != (unsigned)-1) {
                intf = ffs_func_revmap_intf(func, interface);
                if (intf < 0)
  
        ffs->func = func;
        ret = ffs_func_eps_enable(func);
 -      if (ret >= 0)
 +      if (ret >= 0) {
                ffs_event_add(ffs, FUNCTIONFS_ENABLE);
 +              func->cur_alt[interface] = alt;
 +      }
        return ret;
  }
  
@@@ -3823,7 -3811,7 +3828,7 @@@ static int ffs_func_setup(struct usb_fu
        __ffs_event_add(ffs, FUNCTIONFS_SETUP);
        spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
  
-       return creq->wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0;
+       return ffs->ev.setup.wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0;
  }
  
  static bool ffs_func_req_match(struct usb_function *f,
@@@ -4086,7 -4074,6 +4091,7 @@@ static struct usb_function *ffs_alloc(s
        func->function.bind    = ffs_func_bind;
        func->function.unbind  = ffs_func_unbind;
        func->function.set_alt = ffs_func_set_alt;
 +      func->function.get_alt = ffs_func_get_alt;
        func->function.disable = ffs_func_disable;
        func->function.setup   = ffs_func_setup;
        func->function.req_match = ffs_func_req_match;
index 6535e5948b2efd2ee72ac0e603b009ba86c14dca,a4377df612f51e12760195cd1fbe89ec9c541fbe..6fac696ea846370416defcb76c809440a7551560
@@@ -13,7 -13,6 +13,7 @@@
  #include "uvc_configfs.h"
  
  #include <linux/sort.h>
 +#include <linux/usb/uvc.h>
  #include <linux/usb/video.h>
  
  /* -----------------------------------------------------------------------------
@@@ -93,10 -92,10 +93,10 @@@ static int __uvcg_iter_item_entries(con
  
        while (pg - page < len) {
                i = 0;
-               while (i < sizeof(buf) && (pg - page < len) &&
+               while (i < bufsize && (pg - page < len) &&
                       *pg != '\0' && *pg != '\n')
                        buf[i++] = *pg++;
-               if (i == sizeof(buf)) {
+               if (i == bufsize) {
                        ret = -EINVAL;
                        goto out_free_buf;
                }
@@@ -2261,8 -2260,6 +2261,8 @@@ static ssize_t uvcg_uncompressed_guid_f
        struct f_uvc_opts *opts;
        struct config_item *opts_item;
        struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
 +      const struct uvc_format_desc *format;
 +      u8 tmpguidFormat[sizeof(ch->desc.guidFormat)];
        int ret;
  
        mutex_lock(su_mutex); /* for navigating configfs hierarchy */
                goto end;
        }
  
 -      memcpy(ch->desc.guidFormat, page,
 +      memcpy(tmpguidFormat, page,
 +             min(sizeof(tmpguidFormat), len));
 +
 +      format = uvc_format_by_guid(tmpguidFormat);
 +      if (!format) {
 +              ret = -EINVAL;
 +              goto end;
 +      }
 +
 +      memcpy(ch->desc.guidFormat, tmpguidFormat,
               min(sizeof(ch->desc.guidFormat), len));
        ret = sizeof(ch->desc.guidFormat);
  
This page took 0.136079 seconds and 4 git commands to generate.