Merge 6.2-rc7 into usb-next
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Feb 2023 07:33:30 +0000 (08:33 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Feb 2023 07:33:30 +0000 (08:33 +0100)
We need the USB fixes in here, and this resolves a merge conflict with
the i915 driver as reported in linux-next

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1  2 
MAINTAINERS
drivers/gpu/drm/i915/gt/intel_execlists_submission.c
drivers/usb/fotg210/fotg210-udc.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/udc/bcm63xx_udc.c
drivers/usb/gadget/udc/fusb300_udc.c
drivers/usb/typec/ucsi/ucsi.c

diff --combined MAINTAINERS
@@@ -1097,7 -1097,6 +1097,6 @@@ S:      Maintaine
  F:    drivers/dma/ptdma/
  
  AMD SEATTLE DEVICE TREE SUPPORT
- M:    Brijesh Singh <brijeshkumar.singh@amd.com>
  M:    Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
  M:    Tom Lendacky <thomas.lendacky@amd.com>
  S:    Supported
@@@ -2212,6 -2211,9 +2211,9 @@@ L:      linux-arm-kernel@lists.infradead.or
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
  X:    drivers/media/i2c/
+ F:    arch/arm64/boot/dts/freescale/
+ X:    arch/arm64/boot/dts/freescale/fsl-*
+ X:    arch/arm64/boot/dts/freescale/qoriq-*
  N:    imx
  N:    mxs
  
@@@ -2450,11 -2452,14 +2452,14 @@@ F:   drivers/rtc/rtc-mt7622.
  
  ARM/Mediatek SoC support
  M:    Matthias Brugger <matthias.bgg@gmail.com>
+ R:    AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ L:    linux-kernel@vger.kernel.org
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  L:    linux-mediatek@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
  W:    https://mtk.wiki.kernel.org/
- C:    irc://chat.freenode.net/linux-mediatek
+ C:    irc://irc.libera.chat/linux-mediatek
+ F:    arch/arm/boot/dts/mt2*
  F:    arch/arm/boot/dts/mt6*
  F:    arch/arm/boot/dts/mt7*
  F:    arch/arm/boot/dts/mt8*
@@@ -2462,7 -2467,7 +2467,7 @@@ F:      arch/arm/mach-mediatek
  F:    arch/arm64/boot/dts/mediatek/
  F:    drivers/soc/mediatek/
  N:    mtk
- N:    mt[678]
+ N:    mt[2678]
  K:    mediatek
  
  ARM/Mediatek USB3 PHY DRIVER
@@@ -3766,7 -3771,6 +3771,6 @@@ F:      net/bluetooth
  
  BONDING DRIVER
  M:    Jay Vosburgh <j.vosburgh@gmail.com>
- M:    Veaceslav Falico <vfalico@gmail.com>
  M:    Andy Gospodarek <andy@greyhouse.net>
  L:    netdev@vger.kernel.org
  S:    Supported
@@@ -7615,7 -7619,6 +7619,6 @@@ S:      Maintaine
  F:    drivers/firmware/efi/test/
  
  EFI VARIABLE FILESYSTEM
- M:    Matthew Garrett <matthew.garrett@nebula.com>
  M:    Jeremy Kerr <jk@ozlabs.org>
  M:    Ard Biesheuvel <ardb@kernel.org>
  L:    linux-efi@vger.kernel.org
@@@ -7894,7 -7897,11 +7897,11 @@@ F:    include/linux/extcon
  
  EXTRA BOOT CONFIG
  M:    Masami Hiramatsu <mhiramat@kernel.org>
+ L:    linux-kernel@vger.kernel.org
+ L:    linux-trace-kernel@vger.kernel.org
+ Q:    https://patchwork.kernel.org/project/linux-trace-kernel/list/
  S:    Maintained
+ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git
  F:    Documentation/admin-guide/bootconfig.rst
  F:    fs/proc/bootconfig.c
  F:    include/linux/bootconfig.h
@@@ -8467,16 -8474,16 +8474,16 @@@ F:   fs/fscache
  F:    include/linux/fscache*.h
  
  FSCRYPT: FILE SYSTEM LEVEL ENCRYPTION SUPPORT
+ M:    Eric Biggers <ebiggers@kernel.org>
  M:    Theodore Y. Ts'o <tytso@mit.edu>
  M:    Jaegeuk Kim <jaegeuk@kernel.org>
- M:    Eric Biggers <ebiggers@kernel.org>
  L:    linux-fscrypt@vger.kernel.org
  S:    Supported
  Q:    https://patchwork.kernel.org/project/linux-fscrypt/list/
- T:    git git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt.git
+ T:    git https://git.kernel.org/pub/scm/fs/fscrypt/linux.git
  F:    Documentation/filesystems/fscrypt.rst
  F:    fs/crypto/
- F:    include/linux/fscrypt*.h
+ F:    include/linux/fscrypt.h
  F:    include/uapi/linux/fscrypt.h
  
  FSI SUBSYSTEM
@@@ -8519,10 -8526,10 +8526,10 @@@ F:   include/linux/fsnotify*.
  FSVERITY: READ-ONLY FILE-BASED AUTHENTICITY PROTECTION
  M:    Eric Biggers <ebiggers@kernel.org>
  M:    Theodore Y. Ts'o <tytso@mit.edu>
- L:    linux-fscrypt@vger.kernel.org
+ L:    fsverity@lists.linux.dev
  S:    Supported
- Q:    https://patchwork.kernel.org/project/linux-fscrypt/list/
- T:    git git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt.git fsverity
+ Q:    https://patchwork.kernel.org/project/fsverity/list/
+ T:    git https://git.kernel.org/pub/scm/fs/fsverity/linux.git
  F:    Documentation/filesystems/fsverity.rst
  F:    fs/verity/
  F:    include/linux/fsverity.h
@@@ -8570,6 -8577,7 +8577,7 @@@ F:      kernel/trace/fgraph.
  F:    arch/*/*/*/*ftrace*
  F:    arch/*/*/*ftrace*
  F:    include/*/ftrace.h
+ F:    samples/ftrace
  
  FUNGIBLE ETHERNET DRIVERS
  M:    Dimitris Michailidis <dmichail@fungible.com>
@@@ -14600,7 -14608,6 +14608,6 @@@ F:   tools/testing/selftests/net/ipsec.
  
  NETWORKING [IPv4/IPv6]
  M:    "David S. Miller" <davem@davemloft.net>
- M:    Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
  M:    David Ahern <dsahern@kernel.org>
  L:    netdev@vger.kernel.org
  S:    Maintained
@@@ -14633,7 -14640,6 +14640,6 @@@ F:   net/netfilter/xt_SECMARK.
  F:    net/netlabel/
  
  NETWORKING [MPTCP]
- M:    Mat Martineau <mathew.j.martineau@linux.intel.com>
  M:    Matthieu Baerts <matthieu.baerts@tessares.net>
  L:    netdev@vger.kernel.org
  L:    mptcp@lists.linux.dev
@@@ -15658,7 -15664,7 +15664,7 @@@ OPENRISC ARCHITECTUR
  M:    Jonas Bonn <jonas@southpole.se>
  M:    Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
  M:    Stafford Horne <shorne@gmail.com>
- L:    openrisc@lists.librecores.org
+ L:    linux-openrisc@vger.kernel.org
  S:    Maintained
  W:    http://openrisc.io
  T:    git https://github.com/openrisc/linux.git
@@@ -17872,14 -17878,6 +17878,14 @@@ S: Maintaine
  F:    Documentation/devicetree/bindings/rtc/renesas,rzn1-rtc.yaml
  F:    drivers/rtc/rtc-rzn1.c
  
 +RENESAS RZ/N1 USBF CONTROLLER DRIVER
 +M:    Herve Codina <herve.codina@bootlin.com>
 +L:    linux-renesas-soc@vger.kernel.org
 +L:    linux-usb@vger.kernel.org
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/usb/renesas,rzn1-usbf.yaml
 +F:    drivers/usb/gadget/udc/renesas_usbf.c
 +
  RENESAS R-CAR GEN3 & RZ/N1 NAND CONTROLLER DRIVER
  M:    Miquel Raynal <miquel.raynal@bootlin.com>
  L:    linux-mtd@lists.infradead.org
@@@ -17970,6 -17968,7 +17976,7 @@@ M:   Albert Ou <aou@eecs.berkeley.edu
  L:    linux-riscv@lists.infradead.org
  S:    Supported
  Q:    https://patchwork.kernel.org/project/linux-riscv/list/
+ C:    irc://irc.libera.chat/riscv
  P:    Documentation/riscv/patch-acceptance.rst
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux.git
  F:    arch/riscv/
@@@ -18691,9 -18690,9 +18698,9 @@@ F:   drivers/target
  F:    include/target/
  
  SCTP PROTOCOL
- M:    Vlad Yasevich <vyasevich@gmail.com>
  M:    Neil Horman <nhorman@tuxdriver.com>
  M:    Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+ M:    Xin Long <lucien.xin@gmail.com>
  L:    linux-sctp@vger.kernel.org
  S:    Maintained
  W:    http://lksctp.sourceforge.net
@@@ -21731,6 -21730,7 +21738,7 @@@ F:   include/uapi/linux/uvcvideo.
  
  USB WEBCAM GADGET
  M:    Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ M:    Daniel Scally <dan.scally@ideasonboard.com>
  L:    linux-usb@vger.kernel.org
  S:    Maintained
  F:    drivers/usb/gadget/function/*uvc*
@@@ -4148,6 -4148,33 +4148,22 @@@ void intel_execlists_show_requests(stru
        spin_unlock_irqrestore(&sched_engine->lock, flags);
  }
  
 -static unsigned long list_count(struct list_head *list)
 -{
 -      struct list_head *pos;
 -      unsigned long count = 0;
 -
 -      list_for_each(pos, list)
 -              count++;
 -
 -      return count;
 -}
 -
+ void intel_execlists_dump_active_requests(struct intel_engine_cs *engine,
+                                         struct i915_request *hung_rq,
+                                         struct drm_printer *m)
+ {
+       unsigned long flags;
+       spin_lock_irqsave(&engine->sched_engine->lock, flags);
+       intel_engine_dump_active_requests(&engine->sched_engine->requests, hung_rq, m);
+       drm_printf(m, "\tOn hold?: %lu\n",
 -                 list_count(&engine->sched_engine->hold));
++                 list_count_nodes(&engine->sched_engine->hold));
+       spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
+ }
  #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
  #include "selftest_execlists.c"
  #endif
@@@ -7,7 -7,6 +7,7 @@@
   * Author : Yuan-Hsin Chen <yhchen@faraday-tech.com>
   */
  
 +#include <linux/delay.h>
  #include <linux/dma-mapping.h>
  #include <linux/err.h>
  #include <linux/interrupt.h>
@@@ -16,6 -15,7 +16,6 @@@
  #include <linux/platform_device.h>
  #include <linux/usb/ch9.h>
  #include <linux/usb/gadget.h>
 -#include <linux/clk.h>
  #include <linux/usb/otg.h>
  #include <linux/usb/phy.h>
  
@@@ -29,14 -29,6 +29,14 @@@ static const char udc_name[] = "fotg210
  static const char * const fotg210_ep_name[] = {
        "ep0", "ep1", "ep2", "ep3", "ep4"};
  
 +static void fotg210_ack_int(struct fotg210_udc *fotg210, u32 offset, u32 mask)
 +{
 +      u32 value = ioread32(fotg210->reg + offset);
 +
 +      value &= ~mask;
 +      iowrite32(value, fotg210->reg + offset);
 +}
 +
  static void fotg210_disable_fifo_int(struct fotg210_ep *ep)
  {
        u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR1);
@@@ -312,7 -304,8 +312,7 @@@ static void fotg210_wait_dma_done(struc
                        goto dma_reset;
        } while (!(value & DISGR2_DMA_CMPLT));
  
 -      value &= ~DISGR2_DMA_CMPLT;
 -      iowrite32(value, ep->fotg210->reg + FOTG210_DISGR2);
 +      fotg210_ack_int(ep->fotg210, FOTG210_DISGR2, DISGR2_DMA_CMPLT);
        return;
  
  dma_reset:
@@@ -717,20 -710,6 +717,20 @@@ static int fotg210_is_epnstall(struct f
        return value & INOUTEPMPSR_STL_EP ? 1 : 0;
  }
  
 +/* For EP0 requests triggered by this driver (currently GET_STATUS response) */
 +static void fotg210_ep0_complete(struct usb_ep *_ep, struct usb_request *req)
 +{
 +      struct fotg210_ep *ep;
 +      struct fotg210_udc *fotg210;
 +
 +      ep = container_of(_ep, struct fotg210_ep, ep);
 +      fotg210 = ep->fotg210;
 +
 +      if (req->status || req->actual != req->length) {
 +              dev_warn(&fotg210->gadget.dev, "EP0 request failed: %d\n", req->status);
 +      }
 +}
 +
  static void fotg210_get_status(struct fotg210_udc *fotg210,
                                struct usb_ctrlrequest *ctrl)
  {
@@@ -852,6 -831,14 +852,6 @@@ static void fotg210_ep0in(struct fotg21
        }
  }
  
 -static void fotg210_clear_comabt_int(struct fotg210_udc *fotg210)
 -{
 -      u32 value = ioread32(fotg210->reg + FOTG210_DISGR0);
 -
 -      value &= ~DISGR0_CX_COMABT_INT;
 -      iowrite32(value, fotg210->reg + FOTG210_DISGR0);
 -}
 -
  static void fotg210_in_fifo_handler(struct fotg210_ep *ep)
  {
        struct fotg210_request *req = list_entry(ep->queue.next,
@@@ -893,43 -880,60 +893,43 @@@ static irqreturn_t fotg210_irq(int irq
                void __iomem *reg = fotg210->reg + FOTG210_DISGR2;
                u32 int_grp2 = ioread32(reg);
                u32 int_msk2 = ioread32(fotg210->reg + FOTG210_DMISGR2);
 -              u32 value;
  
                int_grp2 &= ~int_msk2;
  
                if (int_grp2 & DISGR2_USBRST_INT) {
                        usb_gadget_udc_reset(&fotg210->gadget,
                                             fotg210->driver);
 -                      value = ioread32(reg);
 -                      value &= ~DISGR2_USBRST_INT;
 -                      iowrite32(value, reg);
 +                      fotg210_ack_int(fotg210, FOTG210_DISGR2, DISGR2_USBRST_INT);
                        pr_info("fotg210 udc reset\n");
                }
                if (int_grp2 & DISGR2_SUSP_INT) {
 -                      value = ioread32(reg);
 -                      value &= ~DISGR2_SUSP_INT;
 -                      iowrite32(value, reg);
 +                      fotg210_ack_int(fotg210, FOTG210_DISGR2, DISGR2_SUSP_INT);
                        pr_info("fotg210 udc suspend\n");
                }
                if (int_grp2 & DISGR2_RESM_INT) {
 -                      value = ioread32(reg);
 -                      value &= ~DISGR2_RESM_INT;
 -                      iowrite32(value, reg);
 +                      fotg210_ack_int(fotg210, FOTG210_DISGR2, DISGR2_RESM_INT);
                        pr_info("fotg210 udc resume\n");
                }
                if (int_grp2 & DISGR2_ISO_SEQ_ERR_INT) {
 -                      value = ioread32(reg);
 -                      value &= ~DISGR2_ISO_SEQ_ERR_INT;
 -                      iowrite32(value, reg);
 +                      fotg210_ack_int(fotg210, FOTG210_DISGR2, DISGR2_ISO_SEQ_ERR_INT);
                        pr_info("fotg210 iso sequence error\n");
                }
                if (int_grp2 & DISGR2_ISO_SEQ_ABORT_INT) {
 -                      value = ioread32(reg);
 -                      value &= ~DISGR2_ISO_SEQ_ABORT_INT;
 -                      iowrite32(value, reg);
 +                      fotg210_ack_int(fotg210, FOTG210_DISGR2, DISGR2_ISO_SEQ_ABORT_INT);
                        pr_info("fotg210 iso sequence abort\n");
                }
                if (int_grp2 & DISGR2_TX0BYTE_INT) {
                        fotg210_clear_tx0byte(fotg210);
 -                      value = ioread32(reg);
 -                      value &= ~DISGR2_TX0BYTE_INT;
 -                      iowrite32(value, reg);
 +                      fotg210_ack_int(fotg210, FOTG210_DISGR2, DISGR2_TX0BYTE_INT);
                        pr_info("fotg210 transferred 0 byte\n");
                }
                if (int_grp2 & DISGR2_RX0BYTE_INT) {
                        fotg210_clear_rx0byte(fotg210);
 -                      value = ioread32(reg);
 -                      value &= ~DISGR2_RX0BYTE_INT;
 -                      iowrite32(value, reg);
 +                      fotg210_ack_int(fotg210, FOTG210_DISGR2, DISGR2_RX0BYTE_INT);
                        pr_info("fotg210 received 0 byte\n");
                }
                if (int_grp2 & DISGR2_DMA_ERROR) {
 -                      value = ioread32(reg);
 -                      value &= ~DISGR2_DMA_ERROR;
 -                      iowrite32(value, reg);
 +                      fotg210_ack_int(fotg210, FOTG210_DISGR2, DISGR2_DMA_ERROR);
                }
        }
  
  
                /* the highest priority in this source register */
                if (int_grp0 & DISGR0_CX_COMABT_INT) {
 -                      fotg210_clear_comabt_int(fotg210);
 +                      fotg210_ack_int(fotg210, FOTG210_DISGR0, DISGR0_CX_COMABT_INT);
                        pr_info("fotg210 CX command abort\n");
                }
  
@@@ -1010,12 -1014,7 +1010,11 @@@ static int fotg210_udc_start(struct usb
        int ret;
  
        /* hook up the driver */
-       driver->driver.bus = NULL;
        fotg210->driver = driver;
 +      fotg210->gadget.dev.of_node = fotg210->dev->of_node;
 +      fotg210->gadget.speed = USB_SPEED_UNKNOWN;
 +
 +      dev_info(fotg210->dev, "bound driver %s\n", driver->driver.name);
  
        if (!IS_ERR_OR_NULL(fotg210->phy)) {
                ret = otg_set_peripheral(fotg210->phy->otg,
                        dev_err(fotg210->dev, "can't bind to phy\n");
        }
  
 +      /* chip enable */
 +      value = ioread32(fotg210->reg + FOTG210_DMCR);
 +      value |= DMCR_CHIP_EN;
 +      iowrite32(value, fotg210->reg + FOTG210_DMCR);
 +
        /* enable device global interrupt */
        value = ioread32(fotg210->reg + FOTG210_DMCR);
        value |= DMCR_GLINT_EN;
@@@ -1045,15 -1039,6 +1044,15 @@@ static void fotg210_init(struct fotg210
        iowrite32(GMIR_MHC_INT | GMIR_MOTG_INT | GMIR_INT_POLARITY,
                  fotg210->reg + FOTG210_GMIR);
  
 +      /* mask interrupts for groups other than 0-2 */
 +      iowrite32(~(DMIGR_MINT_G0 | DMIGR_MINT_G1 | DMIGR_MINT_G2),
 +                fotg210->reg + FOTG210_DMIGR);
 +
 +      /* udc software reset */
 +      iowrite32(DMCR_SFRST, fotg210->reg + FOTG210_DMCR);
 +      /* Better wait a bit, but without a datasheet, no idea how long. */
 +      usleep_range(100, 200);
 +
        /* disable device global interrupt */
        value = ioread32(fotg210->reg + FOTG210_DMCR);
        value &= ~DMCR_GLINT_EN;
@@@ -1086,33 -1071,15 +1085,33 @@@ static int fotg210_udc_stop(struct usb_
  
        fotg210_init(fotg210);
        fotg210->driver = NULL;
 +      fotg210->gadget.speed = USB_SPEED_UNKNOWN;
  
        spin_unlock_irqrestore(&fotg210->lock, flags);
  
        return 0;
  }
  
 +/**
 + * fotg210_vbus_session - Called by external transceiver to enable/disable udc
 + * @_gadget: usb gadget
 + * @is_active: 0 if should disable UDC VBUS, 1 if should enable
 + *
 + * Returns 0
 + */
 +static int fotg210_vbus_session(struct usb_gadget *g, int is_active)
 +{
 +      struct fotg210_udc *fotg210 = gadget_to_fotg210(g);
 +
 +      /* Call down to core integration layer to drive or disable VBUS */
 +      fotg210_vbus(fotg210->fotg, is_active);
 +      return 0;
 +}
 +
  static const struct usb_gadget_ops fotg210_gadget_ops = {
        .udc_start              = fotg210_udc_start,
        .udc_stop               = fotg210_udc_stop,
 +      .vbus_session           = fotg210_vbus_session,
  };
  
  /**
@@@ -1166,22 -1133,34 +1165,22 @@@ int fotg210_udc_remove(struct platform_
        for (i = 0; i < FOTG210_MAX_NUM_EP; i++)
                kfree(fotg210->ep[i]);
  
 -      if (!IS_ERR(fotg210->pclk))
 -              clk_disable_unprepare(fotg210->pclk);
 -
        kfree(fotg210);
  
        return 0;
  }
  
 -int fotg210_udc_probe(struct platform_device *pdev)
 +int fotg210_udc_probe(struct platform_device *pdev, struct fotg210 *fotg)
  {
 -      struct resource *res;
        struct fotg210_udc *fotg210 = NULL;
        struct device *dev = &pdev->dev;
        int irq;
        int ret = 0;
        int i;
  
 -      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 -      if (!res) {
 -              pr_err("platform_get_resource error.\n");
 -              return -ENODEV;
 -      }
 -
        irq = platform_get_irq(pdev, 0);
 -      if (irq < 0) {
 -              pr_err("could not get irq\n");
 -              return -ENODEV;
 -      }
 +      if (irq < 0)
 +              return irq;
  
        /* initialize udc */
        fotg210 = kzalloc(sizeof(struct fotg210_udc), GFP_KERNEL);
                return -ENOMEM;
  
        fotg210->dev = dev;
 -
 -      /* It's OK not to supply this clock */
 -      fotg210->pclk = devm_clk_get(dev, "PCLK");
 -      if (!IS_ERR(fotg210->pclk)) {
 -              ret = clk_prepare_enable(fotg210->pclk);
 -              if (ret) {
 -                      dev_err(dev, "failed to enable PCLK\n");
 -                      goto err;
 -              }
 -      } else if (PTR_ERR(fotg210->pclk) == -EPROBE_DEFER) {
 -              /*
 -               * Percolate deferrals, for anything else,
 -               * just live without the clocking.
 -               */
 -              ret = -EPROBE_DEFER;
 -              goto err;
 -      }
 +      fotg210->fotg = fotg;
  
        fotg210->phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
        if (IS_ERR(fotg210->phy)) {
                ret = PTR_ERR(fotg210->phy);
                if (ret == -EPROBE_DEFER)
 -                      goto err_pclk;
 +                      goto err_free;
                dev_info(dev, "no PHY found\n");
                fotg210->phy = NULL;
        } else {
                ret = usb_phy_init(fotg210->phy);
                if (ret)
 -                      goto err_pclk;
 +                      goto err_free;
                dev_info(dev, "found and initialized PHY\n");
        }
  
                        goto err_alloc;
        }
  
 -      fotg210->reg = ioremap(res->start, resource_size(res));
 -      if (fotg210->reg == NULL) {
 -              dev_err(dev, "ioremap error\n");
 -              goto err_alloc;
 -      }
 +      fotg210->reg = fotg->base;
  
        spin_lock_init(&fotg210->lock);
  
        if (fotg210->ep0_req == NULL)
                goto err_map;
  
 +      fotg210->ep0_req->complete = fotg210_ep0_complete;
 +
        fotg210_init(fotg210);
  
        fotg210_disable_unplug(fotg210);
        ret = request_irq(irq, fotg210_irq, IRQF_SHARED,
                          udc_name, fotg210);
        if (ret < 0) {
 -              dev_err(dev, "request_irq error (%d)\n", ret);
 +              dev_err_probe(dev, ret, "request_irq error\n");
                goto err_req;
        }
  
@@@ -1300,8 -1297,11 +1299,8 @@@ err_map
  err_alloc:
        for (i = 0; i < FOTG210_MAX_NUM_EP; i++)
                kfree(fotg210->ep[i]);
 -err_pclk:
 -      if (!IS_ERR(fotg210->pclk))
 -              clk_disable_unprepare(fotg210->pclk);
  
 -err:
 +err_free:
        kfree(fotg210);
        return ret;
  }
@@@ -279,8 -279,10 +279,10 @@@ static int __ffs_ep0_queue_wait(struct 
        struct usb_request *req = ffs->ep0req;
        int ret;
  
-       if (!req)
+       if (!req) {
+               spin_unlock_irq(&ffs->ev.waitq.lock);
                return -EINVAL;
+       }
  
        req->zero     = len < le16_to_cpu(ffs->ev.setup.wLength);
  
@@@ -828,7 -830,8 +830,7 @@@ static void ffs_user_copy_worker(struc
  {
        struct ffs_io_data *io_data = container_of(work, struct ffs_io_data,
                                                   work);
 -      int ret = io_data->req->status ? io_data->req->status :
 -                                       io_data->req->actual;
 +      int ret = io_data->status;
        bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
  
        if (io_data->read && ret > 0) {
        if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd)
                eventfd_signal(io_data->ffs->ffs_eventfd, 1);
  
 -      usb_ep_free_request(io_data->ep, io_data->req);
 -
        if (io_data->read)
                kfree(io_data->to_free);
        ffs_free_buffer(io_data);
@@@ -856,9 -861,6 +858,9 @@@ static void ffs_epfile_async_io_complet
  
        ENTER();
  
 +      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);
  }
@@@ -1830,7 -1830,6 +1830,6 @@@ static int bcm63xx_udc_start(struct usb
        bcm63xx_select_phy_mode(udc, true);
  
        udc->driver = driver;
-       driver->driver.bus = NULL;
        udc->gadget.dev.of_node = udc->dev->of_node;
  
        spin_unlock_irqrestore(&udc->lock, flags);
@@@ -2172,6 -2171,7 +2171,6 @@@ static int bcm63xx_iudma_dbg_show(struc
  
        for (ch_idx = 0; ch_idx < BCM63XX_NUM_IUDMA; ch_idx++) {
                struct iudma_ch *iudma = &udc->iudma[ch_idx];
 -              struct list_head *pos;
  
                seq_printf(s, "IUDMA channel %d -- ", ch_idx);
                switch (iudma_defaults[ch_idx].ep_type) {
                seq_printf(s, "  desc: %d/%d used", iudma->n_bds_used,
                           iudma->n_bds);
  
 -              if (iudma->bep) {
 -                      i = 0;
 -                      list_for_each(pos, &iudma->bep->queue)
 -                              i++;
 -                      seq_printf(s, "; %d queued\n", i);
 -              } else {
 +              if (iudma->bep)
 +                      seq_printf(s, "; %zu queued\n", list_count_nodes(&iudma->bep->queue));
 +              else
                        seq_printf(s, "\n");
 -              }
  
                for (i = 0; i < iudma->n_bds; i++) {
                        struct bcm_enet_desc *d = &iudma->bd_ring[i];
@@@ -1311,7 -1311,6 +1311,6 @@@ static int fusb300_udc_start(struct usb
        struct fusb300 *fusb300 = to_fusb300(g);
  
        /* hook up the driver */
-       driver->driver.bus = NULL;
        fusb300->driver = driver;
  
        return 0;
@@@ -1347,7 -1346,6 +1346,7 @@@ static int fusb300_remove(struct platfo
        usb_del_gadget_udc(&fusb300->gadget);
        iounmap(fusb300->reg);
        free_irq(platform_get_irq(pdev, 0), fusb300);
 +      free_irq(platform_get_irq(pdev, 1), fusb300);
  
        fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
        for (i = 0; i < FUSB300_MAX_NUM_EP; i++)
@@@ -1433,7 -1431,7 +1432,7 @@@ static int fusb300_probe(struct platfor
                        IRQF_SHARED, udc_name, fusb300);
        if (ret < 0) {
                pr_err("request_irq1 error (%d)\n", ret);
 -              goto clean_up;
 +              goto err_request_irq1;
        }
  
        INIT_LIST_HEAD(&fusb300->gadget.ep_list);
                                GFP_KERNEL);
        if (fusb300->ep0_req == NULL) {
                ret = -ENOMEM;
 -              goto clean_up3;
 +              goto err_alloc_request;
        }
  
        init_controller(fusb300);
  err_add_udc:
        fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
  
 -clean_up3:
 +err_alloc_request:
 +      free_irq(ires1->start, fusb300);
 +
 +err_request_irq1:
        free_irq(ires->start, fusb300);
  
  clean_up:
@@@ -567,9 -567,8 +567,9 @@@ static void ucsi_unregister_altmodes(st
        }
  }
  
 -static int ucsi_get_pdos(struct ucsi_connector *con, int is_partner,
 -                       u32 *pdos, int offset, int num_pdos)
 +static int ucsi_read_pdos(struct ucsi_connector *con,
 +                        enum typec_role role, int is_partner,
 +                        u32 *pdos, int offset, int num_pdos)
  {
        struct ucsi *ucsi = con->ucsi;
        u64 command;
        command |= UCSI_GET_PDOS_PARTNER_PDO(is_partner);
        command |= UCSI_GET_PDOS_PDO_OFFSET(offset);
        command |= UCSI_GET_PDOS_NUM_PDOS(num_pdos - 1);
 -      command |= UCSI_GET_PDOS_SRC_PDOS;
 +      command |= is_source(role) ? UCSI_GET_PDOS_SRC_PDOS : 0;
        ret = ucsi_send_command(ucsi, command, pdos + offset,
                                num_pdos * sizeof(u32));
        if (ret < 0 && ret != -ETIMEDOUT)
        return ret;
  }
  
 -static int ucsi_get_src_pdos(struct ucsi_connector *con)
 +static int ucsi_get_pdos(struct ucsi_connector *con, enum typec_role role,
 +                       int is_partner, u32 *pdos)
  {
 +      u8 num_pdos;
        int ret;
  
        /* UCSI max payload means only getting at most 4 PDOs at a time */
 -      ret = ucsi_get_pdos(con, 1, con->src_pdos, 0, UCSI_MAX_PDOS);
 +      ret = ucsi_read_pdos(con, role, is_partner, pdos, 0, UCSI_MAX_PDOS);
        if (ret < 0)
                return ret;
  
 -      con->num_pdos = ret / sizeof(u32); /* number of bytes to 32-bit PDOs */
 -      if (con->num_pdos < UCSI_MAX_PDOS)
 -              return 0;
 +      num_pdos = ret / sizeof(u32); /* number of bytes to 32-bit PDOs */
 +      if (num_pdos < UCSI_MAX_PDOS)
 +              return num_pdos;
  
        /* get the remaining PDOs, if any */
 -      ret = ucsi_get_pdos(con, 1, con->src_pdos, UCSI_MAX_PDOS,
 -                          PDO_MAX_OBJECTS - UCSI_MAX_PDOS);
 +      ret = ucsi_read_pdos(con, role, is_partner, pdos, UCSI_MAX_PDOS,
 +                           PDO_MAX_OBJECTS - UCSI_MAX_PDOS);
        if (ret < 0)
                return ret;
  
 -      con->num_pdos += ret / sizeof(u32);
 +      return ret / sizeof(u32) + num_pdos;
 +}
 +
 +static int ucsi_get_src_pdos(struct ucsi_connector *con)
 +{
 +      int ret;
 +
 +      ret = ucsi_get_pdos(con, TYPEC_SOURCE, 1, con->src_pdos);
 +      if (ret < 0)
 +              return ret;
 +
 +      con->num_pdos = ret;
  
        ucsi_port_psy_changed(con);
  
 -      return 0;
 +      return ret;
  }
  
  static int ucsi_check_altmodes(struct ucsi_connector *con)
        return ret;
  }
  
 +static int ucsi_register_partner_pdos(struct ucsi_connector *con)
 +{
 +      struct usb_power_delivery_desc desc = { con->ucsi->cap.pd_version };
 +      struct usb_power_delivery_capabilities_desc caps;
 +      struct usb_power_delivery_capabilities *cap;
 +      int ret;
 +
 +      if (con->partner_pd)
 +              return 0;
 +
 +      con->partner_pd = usb_power_delivery_register(NULL, &desc);
 +      if (IS_ERR(con->partner_pd))
 +              return PTR_ERR(con->partner_pd);
 +
 +      ret = ucsi_get_pdos(con, TYPEC_SOURCE, 1, caps.pdo);
 +      if (ret > 0) {
 +              if (ret < PDO_MAX_OBJECTS)
 +                      caps.pdo[ret] = 0;
 +
 +              caps.role = TYPEC_SOURCE;
 +              cap = usb_power_delivery_register_capabilities(con->partner_pd, &caps);
 +              if (IS_ERR(cap))
 +                      return PTR_ERR(cap);
 +
 +              con->partner_source_caps = cap;
 +
 +              ret = typec_partner_set_usb_power_delivery(con->partner, con->partner_pd);
 +              if (ret) {
 +                      usb_power_delivery_unregister_capabilities(con->partner_source_caps);
 +                      return ret;
 +              }
 +      }
 +
 +      ret = ucsi_get_pdos(con, TYPEC_SINK, 1, caps.pdo);
 +      if (ret > 0) {
 +              if (ret < PDO_MAX_OBJECTS)
 +                      caps.pdo[ret] = 0;
 +
 +              caps.role = TYPEC_SINK;
 +
 +              cap = usb_power_delivery_register_capabilities(con->partner_pd, &caps);
 +              if (IS_ERR(cap))
 +                      return PTR_ERR(cap);
 +
 +              con->partner_sink_caps = cap;
 +
 +              ret = typec_partner_set_usb_power_delivery(con->partner, con->partner_pd);
 +              if (ret) {
 +                      usb_power_delivery_unregister_capabilities(con->partner_sink_caps);
 +                      return ret;
 +              }
 +      }
 +
 +      return 0;
 +}
 +
 +static void ucsi_unregister_partner_pdos(struct ucsi_connector *con)
 +{
 +      usb_power_delivery_unregister_capabilities(con->partner_sink_caps);
 +      con->partner_sink_caps = NULL;
 +      usb_power_delivery_unregister_capabilities(con->partner_source_caps);
 +      con->partner_source_caps = NULL;
 +      usb_power_delivery_unregister(con->partner_pd);
 +      con->partner_pd = NULL;
 +}
 +
  static void ucsi_pwr_opmode_change(struct ucsi_connector *con)
  {
        switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
                typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_PD);
                ucsi_partner_task(con, ucsi_get_src_pdos, 30, 0);
                ucsi_partner_task(con, ucsi_check_altmodes, 30, 0);
 +              ucsi_partner_task(con, ucsi_register_partner_pdos, 1, HZ);
                break;
        case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5:
                con->rdo = 0;
@@@ -782,7 -701,6 +782,7 @@@ static void ucsi_unregister_partner(str
        if (!con->partner)
                return;
  
 +      ucsi_unregister_partner_pdos(con);
        ucsi_unregister_altmodes(con, UCSI_RECIPIENT_SOP);
        typec_unregister_partner(con->partner);
        con->partner = NULL;
@@@ -887,10 -805,6 +887,10 @@@ static void ucsi_handle_connector_chang
                if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
                        ucsi_register_partner(con);
                        ucsi_partner_task(con, ucsi_check_connection, 1, HZ);
 +
 +                      if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
 +                          UCSI_CONSTAT_PWR_OPMODE_PD)
 +                              ucsi_partner_task(con, ucsi_register_partner_pdos, 1, HZ);
                } else {
                        ucsi_unregister_partner(con);
                }
@@@ -1127,9 -1041,6 +1127,9 @@@ static struct fwnode_handle *ucsi_find_
  
  static int ucsi_register_port(struct ucsi *ucsi, int index)
  {
 +      struct usb_power_delivery_desc desc = { ucsi->cap.pd_version};
 +      struct usb_power_delivery_capabilities_desc pd_caps;
 +      struct usb_power_delivery_capabilities *pd_cap;
        struct ucsi_connector *con = &ucsi->connector[index];
        struct typec_capability *cap = &con->typec_cap;
        enum typec_accessory *accessory = cap->accessory;
                goto out;
        }
  
 +      con->pd = usb_power_delivery_register(ucsi->dev, &desc);
 +
 +      ret = ucsi_get_pdos(con, TYPEC_SOURCE, 0, pd_caps.pdo);
 +      if (ret > 0) {
 +              if (ret < PDO_MAX_OBJECTS)
 +                      pd_caps.pdo[ret] = 0;
 +
 +              pd_caps.role = TYPEC_SOURCE;
 +              pd_cap = usb_power_delivery_register_capabilities(con->pd, &pd_caps);
 +              if (IS_ERR(pd_cap)) {
 +                      ret = PTR_ERR(pd_cap);
 +                      goto out;
 +              }
 +
 +              con->port_source_caps = pd_cap;
 +              typec_port_set_usb_power_delivery(con->port, con->pd);
 +      }
 +
 +      memset(&pd_caps, 0, sizeof(pd_caps));
 +      ret = ucsi_get_pdos(con, TYPEC_SINK, 0, pd_caps.pdo);
 +      if (ret > 0) {
 +              if (ret < PDO_MAX_OBJECTS)
 +                      pd_caps.pdo[ret] = 0;
 +
 +              pd_caps.role = TYPEC_SINK;
 +              pd_cap = usb_power_delivery_register_capabilities(con->pd, &pd_caps);
 +              if (IS_ERR(pd_cap)) {
 +                      ret = PTR_ERR(pd_cap);
 +                      goto out;
 +              }
 +
 +              con->port_sink_caps = pd_cap;
 +              typec_port_set_usb_power_delivery(con->port, con->pd);
 +      }
 +
        /* Alternate modes */
        ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_CON);
        if (ret) {
        if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
                typec_set_pwr_role(con->port,
                                  !!(con->status.flags & UCSI_CONSTAT_PWR_DIR));
 -              ucsi_pwr_opmode_change(con);
                ucsi_register_partner(con);
 +              ucsi_pwr_opmode_change(con);
                ucsi_port_psy_changed(con);
        }
  
@@@ -1389,17 -1265,13 +1389,20 @@@ err_unregister
                ucsi_unregister_port_psy(con);
                if (con->wq)
                        destroy_workqueue(con->wq);
 +
 +              usb_power_delivery_unregister_capabilities(con->port_sink_caps);
 +              con->port_sink_caps = NULL;
 +              usb_power_delivery_unregister_capabilities(con->port_source_caps);
 +              con->port_source_caps = NULL;
 +              usb_power_delivery_unregister(con->pd);
 +              con->pd = NULL;
                typec_unregister_port(con->port);
                con->port = NULL;
        }
  
+       kfree(ucsi->connector);
+       ucsi->connector = NULL;
  err_reset:
        memset(&ucsi->cap, 0, sizeof(ucsi->cap));
        ucsi_reset_ppm(ucsi);
@@@ -1431,7 -1303,8 +1434,8 @@@ static void ucsi_resume_work(struct wor
  
  int ucsi_resume(struct ucsi *ucsi)
  {
-       queue_work(system_long_wq, &ucsi->resume_work);
+       if (ucsi->connector)
+               queue_work(system_long_wq, &ucsi->resume_work);
        return 0;
  }
  EXPORT_SYMBOL_GPL(ucsi_resume);
@@@ -1551,6 -1424,9 +1555,9 @@@ void ucsi_unregister(struct ucsi *ucsi
        /* Disable notifications */
        ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd));
  
+       if (!ucsi->connector)
+               return;
        for (i = 0; i < ucsi->cap.num_connectors; i++) {
                cancel_work_sync(&ucsi->connector[i].work);
                ucsi_unregister_partner(&ucsi->connector[i]);
                        mutex_unlock(&ucsi->connector[i].lock);
                        destroy_workqueue(ucsi->connector[i].wq);
                }
 +
 +              usb_power_delivery_unregister_capabilities(ucsi->connector[i].port_sink_caps);
 +              ucsi->connector[i].port_sink_caps = NULL;
 +              usb_power_delivery_unregister_capabilities(ucsi->connector[i].port_source_caps);
 +              ucsi->connector[i].port_source_caps = NULL;
 +              usb_power_delivery_unregister(ucsi->connector[i].pd);
 +              ucsi->connector[i].pd = NULL;
                typec_unregister_port(ucsi->connector[i].port);
        }