[PATCH 2/4] usb: gadget: pch_udc: initialize DMA before registering interrupt sources
From: Myeonghun Pak
Date: Wed Oct 14 2026 - 23:49:57 EST
VBUS GPIO work can reconnect the controller before probe has
allocated its EP0 descriptors. Initialize the lock, endpoint state
and DMA resources before registering either interrupt source.
Keep PCI bus mastering disabled until the PCI IRQ is registered.
This issue was identified as part of our ongoing research while
reviewing kernel code.
Fixes: 637b78eb31e0 ("usb: gadget: pch_udc: Detecting VBUS through GPIO with interrupt")
Assisted-by: LLM
Co-developed-by: Ijae Kim <ae878000@xxxxxxxxx>
Signed-off-by: Ijae Kim <ae878000@xxxxxxxxx>
Signed-off-by: Myeonghun Pak <mhun512@xxxxxxxxx>
---
Compile-tested only.
drivers/usb/gadget/udc/pch_udc.c | 28 +++++++++-------------------
1 file changed, 9 insertions(+), 19 deletions(-)
diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c
index 3b5c5c41c38c..c360bc556cdc 100644
--- a/drivers/usb/gadget/udc/pch_udc.c
+++ b/drivers/usb/gadget/udc/pch_udc.c
@@ -2819,25 +2819,14 @@ static void pch_udc_pcd_reinit(struct pch_udc_dev *dev)
/**
* pch_udc_pcd_init() - This API initializes the driver structure
* @dev: Reference to the driver structure
- *
- * Return codes:
- * 0: Success
- * -ERRNO: All kind of errors when retrieving VBUS GPIO
*/
-static int pch_udc_pcd_init(struct pch_udc_dev *dev)
+static void pch_udc_pcd_init(struct pch_udc_dev *dev)
{
- int ret;
-
pch_udc_init(dev);
pch_udc_pcd_reinit(dev);
INIT_WORK(&dev->vbus_gpio.irq_work_fall, pch_vbus_gpio_work_fall);
INIT_WORK(&dev->vbus_gpio.irq_work_rise, pch_vbus_gpio_work_rise);
-
- ret = pch_vbus_gpio_init(dev);
- if (ret)
- pch_udc_exit(dev);
- return ret;
}
/**
@@ -3082,10 +3071,15 @@ static int pch_udc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dev->base_addr = pcim_iomap_table(pdev)[dev->bar];
+ spin_lock_init(&dev->lock);
+ dev->gadget.ops = &pch_udc_ops;
+
/* initialize the hardware */
- retval = pch_udc_pcd_init(dev);
+ pch_udc_pcd_init(dev);
+
+ retval = init_dma_pools(dev);
if (retval)
- return retval;
+ goto finished;
pci_enable_msi(pdev);
@@ -3102,11 +3096,7 @@ static int pch_udc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_master(pdev);
pci_try_set_mwi(pdev);
- /* device struct setup */
- spin_lock_init(&dev->lock);
- dev->gadget.ops = &pch_udc_ops;
-
- retval = init_dma_pools(dev);
+ retval = pch_vbus_gpio_init(dev);
if (retval)
goto finished;