Re: Possible race condition in f_mass_storage gadget during deinitialization. Kernel warning issued

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Adrian,

On 8/20/2018 4:34 PM, Adrian Ambrożewicz wrote:
> In my current workspace the kernel used is 4.17.7 .
> 
> Unfortunately I don't have the resources now to verify with newer
> version but I might look into that later if it's necessary. I've only
> compared source code between my worktree and mainline sources and
> verified that code around this area still looks almost exactly the
> same (with minor changes like renames of API calls here and there).
> 
> Looking forward for Minas opinion.
> pon., 20 sie 2018 o 13:20 Felipe Balbi <felipe.balbi@xxxxxxxxxxxxxxx>
> napisał(a):
>>
>>
>> Hi,
>>
>> Adrian Ambrożewicz <adrian.ambrozewicz@xxxxxxxxx> writes:
>>> Hello,
>>>
>>> I'm consistently observing kernel warnings related to Mass Storage USB
>>> Gadget de-initialization flow. After investigation I believe that I've
>>> found root cause of these warnings, however I'm unable to estimate the
>>> impact. I would like to put the issue into discussion about possible
>>> side-effects.
>>>
>>> My usage model is to emulate file system using f_mass_storage gadget.
>>> Whenever I pull the USB cable out I see warning related to
>>> "dwc2_hsotg_init_fifo" which is commented in the following way: "/*
>>> Reset fifo map if not correctly cleared during previous session */".
>>
>> which kernel are you using? Have you tried latest mainline? (currently
>> at v4.18).
>>
>>> Assumption I've made were the following:
>>> 1) disconnect handler notifies all gadgets with call_gadget(.., disconnect)
>>> 2) gadgets are then responsible to clear the ep fifos with usb_ep_disable()
>>> 3) disconnect handler initializes the fifo maps to clear state
>>>
>>> Unfortunately in my case the warning occurs every time when using
>>> f_mass_storage gadget. By comparison with f_hid gadget I've come up
>>> with conclusion that it's caused by race condition in the way the
>>> "disable" flow is implemented in mass storage.
>>>
>>> "Correct" flow implemented by HID gadget is the following:
>>> * dwc2_hsotg_irq (USBRst)
>>> ** dwc2_hsotg_disconnect
>>> *** call_gadget(disconnect)
>>> **** hidg_disable
>>> ***** usb_ep_disable // fifos utilized by device are cleared in fifo_map
>>> ** dwc_hsotg_core_init_disconnected
>>> *** dwc2_hsotg_init_fifo // fifo_map is empty - no warning here
>>>
>>> By comparison here is flow observed in Mass Storage gadget. Race
>>> condition is introduced by utilizing separate worker thread to handle
>>> events:
>>> THREAD #1
>>> * dwc2_hsotg_irq (USBRst)
>>> ** dwc2_hsotg_disconnect
>>> *** call_gadget(disconnect)
>>> **** fsg_disable()
>>> ***** raise_exception(FSG_STATE_CONFIG_CHANGE) // Race between Thread
>>> #1 and Thread #2 starts here.
>>> ** dwc_hsotg_core_init_disconnected
>>> *** dwc2_hsotg_init_fifo // fifo_map is object of the race between
>>> this function, and call to usb_ep_disable()
>>>
>>> THREAD #2
>>> * handle_exception(FSG_STATE_CONFIG_CHANGE)
>>> ** do_set_interface(NULL)
>>> *** usb_ep_disable()
>>>
>>> My questions are the following:
>>> - is this known issue?
>>> - is it risky? What are possible outcomes?
>>> - If this race condition is dangerous what would be proper fix ?
>>> Should fsg_disable() call be blocked until handle_exception() finishes
>>> the cleanup? I know that it's just a WA for "misaligned" Mass Storage
>>> gadget architecture, but are there alternatives?
>>>
>>> I would really appreciate professional insight on that matter,
>>
>> Let's see if Minas has anything to say about this.
>>
>> --
>> balbi
> 

Could you please apply this patch and test again.

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 403e99026c52..2bc924c55488 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3171,6 +3171,8 @@ 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
@@ -3184,13 +3186,27 @@ void dwc2_hsotg_core_init_disconnected(struct 
dwc2_hsotg *hsotg,
  	u32 val;
  	u32 usbcfg;
  	u32 dcfg = 0;
+	unsigned long flags;
+	int ep;

  	/* Kill any ep0 requests as controller will be reinitialized */
  	kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);

-	if (!is_usb_reset)
+	if (!is_usb_reset) {
  		if (dwc2_core_reset(hsotg, true))
  			return;
+	}
+	else {
+		/* all endpoints should be shutdown */
+		spin_unlock_irqrestore(&hsotg->lock, flags);
+		for (ep = 1; ep < hsotg->num_of_eps; ep++) {
+			if (hsotg->eps_in[ep])
+				dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
+			if (hsotg->eps_out[ep])
+				dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
+		}
+		spin_lock_irqsave(&hsotg->lock, flags);
+	}

  	/*
  	 * we must now enable ep0 ready for host detection and then




Thanks,
Minas




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux