Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 304e474e authored by Andy Shevchenko's avatar Andy Shevchenko Committed by Greg Kroah-Hartman
Browse files

usb: gadget: pch_udc: Revert d3cb25a1 completely



commit 50a318cc9b54a36f00beadf77e578a50f3620477 upstream.

The commit d3cb25a1 ("usb: gadget: udc: fix spin_lock in pch_udc")
obviously was not thought through and had made the situation even worse
than it was before. Two changes after almost reverted it. but a few
leftovers have been left as it. With this revert d3cb25a1 completely.

While at it, narrow down the scope of unlocked section to prevent
potential race when prot_stall is assigned.

Fixes: d3cb25a1 ("usb: gadget: udc: fix spin_lock in pch_udc")
Fixes: 9903b6be ("usb: gadget: pch-udc: fix lock")
Fixes: 1d23d16a88e6 ("usb: gadget: pch_udc: reorder spin_[un]lock to avoid deadlock")
Cc: Iago Abal <mail@iagoabal.eu>
Signed-off-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20210323153626.54908-5-andriy.shevchenko@linux.intel.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d9199089
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -615,18 +615,22 @@ static void pch_udc_reconnect(struct pch_udc_dev *dev)
static inline void pch_udc_vbus_session(struct pch_udc_dev *dev,
					  int is_active)
{
	unsigned long		iflags;

	spin_lock_irqsave(&dev->lock, iflags);
	if (is_active) {
		pch_udc_reconnect(dev);
		dev->vbus_session = 1;
	} else {
		if (dev->driver && dev->driver->disconnect) {
			spin_lock(&dev->lock);
			spin_unlock_irqrestore(&dev->lock, iflags);
			dev->driver->disconnect(&dev->gadget);
			spin_unlock(&dev->lock);
			spin_lock_irqsave(&dev->lock, iflags);
		}
		pch_udc_set_disconnect(dev);
		dev->vbus_session = 0;
	}
	spin_unlock_irqrestore(&dev->lock, iflags);
}

/**
@@ -1183,20 +1187,25 @@ static int pch_udc_pcd_selfpowered(struct usb_gadget *gadget, int value)
static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on)
{
	struct pch_udc_dev	*dev;
	unsigned long		iflags;

	if (!gadget)
		return -EINVAL;

	dev = container_of(gadget, struct pch_udc_dev, gadget);

	spin_lock_irqsave(&dev->lock, iflags);
	if (is_on) {
		pch_udc_reconnect(dev);
	} else {
		if (dev->driver && dev->driver->disconnect) {
			spin_lock(&dev->lock);
			spin_unlock_irqrestore(&dev->lock, iflags);
			dev->driver->disconnect(&dev->gadget);
			spin_unlock(&dev->lock);
			spin_lock_irqsave(&dev->lock, iflags);
		}
		pch_udc_set_disconnect(dev);
	}
	spin_unlock_irqrestore(&dev->lock, iflags);

	return 0;
}