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

Commit b544a685 authored by Minas Harutyunyan's avatar Minas Harutyunyan Committed by Greg Kroah-Hartman
Browse files

usb: dwc2: Fix disable all EP's on disconnect



commit 4fe4f9fecc36956fd53c8edf96dd0c691ef98ff9 upstream.

Disabling all EP's allow to reset EP's to initial state.
Introduced new function dwc2_hsotg_ep_disable_lock() which
before calling dwc2_hsotg_ep_disable() function acquire
hsotg->lock and release on exiting.
From dwc2_hsotg_ep_disable() function removed acquiring
hsotg->lock.
In dwc2_hsotg_core_init_disconnected() function when USB
reset interrupt asserted disabling all ep’s by
dwc2_hsotg_ep_disable() function.
This updates eliminating sparse imbalance warnings.

Reverted changes in dwc2_hostg_disconnect() function.
Introduced new function dwc2_hsotg_ep_disable_lock().
Changed dwc2_hsotg_ep_ops. Now disable point to
dwc2_hsotg_ep_disable_lock() function.
In functions dwc2_hsotg_udc_stop() and dwc2_hsotg_suspend()
dwc2_hsotg_ep_disable() function replaced by
dwc2_hsotg_ep_disable_lock() function.
In dwc2_hsotg_ep_disable() function removed acquiring
of hsotg->lock.

Fixes: dccf1bad4be7 ("usb: dwc2: Disable all EP's on disconnect")
Signed-off-by: default avatarMinas Harutyunyan <hminas@synopsys.com>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
Signed-off-by: default avatarAmit Pundir <amit.pundir@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent ec58bfa2
Loading
Loading
Loading
Loading
+23 −18
Original line number Diff line number Diff line
@@ -3107,8 +3107,6 @@ static void kill_all_requests(struct dwc2_hsotg *hsotg,
		dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index);
}

static int dwc2_hsotg_ep_disable(struct usb_ep *ep);

/**
 * dwc2_hsotg_disconnect - disconnect service
 * @hsotg: The device state.
@@ -3130,9 +3128,11 @@ void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg)
	/* all endpoints should be shutdown */
	for (ep = 0; ep < hsotg->num_of_eps; ep++) {
		if (hsotg->eps_in[ep])
			dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
			kill_all_requests(hsotg, hsotg->eps_in[ep],
					  -ESHUTDOWN);
		if (hsotg->eps_out[ep])
			dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
			kill_all_requests(hsotg, hsotg->eps_out[ep],
					  -ESHUTDOWN);
	}

	call_gadget(hsotg, disconnect);
@@ -3176,6 +3176,7 @@ static void dwc2_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic)
			GINTSTS_PTXFEMP |  \
			GINTSTS_RXFLVL)

static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
/**
 * dwc2_hsotg_core_init - issue softreset to the core
 * @hsotg: The device state
@@ -4004,10 +4005,8 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
	struct dwc2_hsotg *hsotg = hs_ep->parent;
	int dir_in = hs_ep->dir_in;
	int index = hs_ep->index;
	unsigned long flags;
	u32 epctrl_reg;
	u32 ctrl;
	int locked;

	dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep);

@@ -4023,10 +4022,6 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)

	epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);

	locked = spin_is_locked(&hsotg->lock);
	if (!locked)
		spin_lock_irqsave(&hsotg->lock, flags);

	ctrl = dwc2_readl(hsotg, epctrl_reg);

	if (ctrl & DXEPCTL_EPENA)
@@ -4049,12 +4044,22 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
	hs_ep->fifo_index = 0;
	hs_ep->fifo_size = 0;

	if (!locked)
		spin_unlock_irqrestore(&hsotg->lock, flags);

	return 0;
}

static int dwc2_hsotg_ep_disable_lock(struct usb_ep *ep)
{
	struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
	struct dwc2_hsotg *hsotg = hs_ep->parent;
	unsigned long flags;
	int ret;

	spin_lock_irqsave(&hsotg->lock, flags);
	ret = dwc2_hsotg_ep_disable(ep);
	spin_unlock_irqrestore(&hsotg->lock, flags);
	return ret;
}

/**
 * on_list - check request is on the given endpoint
 * @ep: The endpoint to check.
@@ -4202,7 +4207,7 @@ static int dwc2_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value)

static const struct usb_ep_ops dwc2_hsotg_ep_ops = {
	.enable		= dwc2_hsotg_ep_enable,
	.disable	= dwc2_hsotg_ep_disable,
	.disable	= dwc2_hsotg_ep_disable_lock,
	.alloc_request	= dwc2_hsotg_ep_alloc_request,
	.free_request	= dwc2_hsotg_ep_free_request,
	.queue		= dwc2_hsotg_ep_queue_lock,
@@ -4342,9 +4347,9 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
	/* all endpoints should be shutdown */
	for (ep = 1; ep < hsotg->num_of_eps; ep++) {
		if (hsotg->eps_in[ep])
			dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
			dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep);
		if (hsotg->eps_out[ep])
			dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
			dwc2_hsotg_ep_disable_lock(&hsotg->eps_out[ep]->ep);
	}

	spin_lock_irqsave(&hsotg->lock, flags);
@@ -4792,9 +4797,9 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg)

		for (ep = 0; ep < hsotg->num_of_eps; ep++) {
			if (hsotg->eps_in[ep])
				dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
				dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep);
			if (hsotg->eps_out[ep])
				dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
				dwc2_hsotg_ep_disable_lock(&hsotg->eps_out[ep]->ep);
		}
	}