Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1712116
| From | Danilo Krummrich <danilokrummrich@dk-develop.de> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | Re: [PATCH] usb: gadget: udc: udc_stop before gadget unbind |
| Date | 2017-08-15 14:00 +0200 |
| Message-ID | <ueIFQ-RA-13@gated-at.bofh.it> (permalink) |
| References | <ueqzh-6tX-37@gated-at.bofh.it> <ueGXo-8q6-25@gated-at.bofh.it> |
| Organization | linux.* mail to news gateway |
Hi, thanks for reviewing. On 2017-08-15 12:03, Felipe Balbi wrote: > Hi, > > Danilo Krummrich <danilokrummrich@dk-develop.de> writes: >> udc_stop needs to be called before gadget driver unbind. Otherwise it >> might happen that udc drivers still call into the gadget driver (e.g. >> to reset gadget after OTG event). If this happens it is likely to get >> panics from gadget driver dereferencing NULL ptr, as gadget's drvdata >> is set to NULL on unbind. > > seems like the problem here is with the OTG layer, not UDC core. > I mentioned this just as example, it can happen whenever a UDC driver calls the gadget driver (e.g. by calling usb_gadget_udc_reset() in ISR) after gadget drivers unbind() was called already (e.g. by gadget configfs). If this happens gadget drivers drvdata was already set to NULL by unbind() and reset() could result into a NULL ptr exception. Therefore my assumption was that it needs to be prevented that the gadget driver is getting called after unbind. >> Signed-off-by: Danilo Krummrich <danilokrummrich@dk-develop.de> >> --- >> Actually there could still be a race: >> (CPU1 code taken from dwc3 drivers dwc3_disconnect_gadget() as >> exsample) >> >> CPU0 CPU1 >> ---- ---- >> usb_gadget_disconnect(udc->gadget); >> udc->driver->disconnect(udc->gadget); >> if (dwc->gadget_driver && dwc->gadget_driver->disconnect) >> usb_gadget_udc_stop(udc); >> udc->driver->unbind(udc->gadget); >> dwc->gadget_driver->disconnect(&dwc->gadget); >> >> UDC drivers typically set their gadget driver pointer to NULL in >> udc_stop >> and check for it before calling into the gadget driver. To fix the >> issue >> above every udc driver could apply a lock around this. >> >> If you see the need for having this or another solutions I can provide >> further patches. This patch could also just serve as a base for >> discussion >> if someone knows a smarter solution. >> >> I saw this problem causing a panic on hikey960 board and provided a >> quick >> workaround for the same problem here: >> https://android-review.googlesource.com/#/c/kernel/common/+/457476/ >> (panic log in the commit message of the linked patch) >> --- >> drivers/usb/gadget/udc/core.c | 6 +++++- >> 1 file changed, 5 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/usb/gadget/udc/core.c >> b/drivers/usb/gadget/udc/core.c >> index efce68e9a8e0..8155468afc0d 100644 >> --- a/drivers/usb/gadget/udc/core.c >> +++ b/drivers/usb/gadget/udc/core.c >> @@ -1234,8 +1234,12 @@ static void usb_gadget_remove_driver(struct >> usb_udc *udc) >> >> usb_gadget_disconnect(udc->gadget); >> udc->driver->disconnect(udc->gadget); >> - udc->driver->unbind(udc->gadget); >> + /* udc_stop needs to be called before gadget driver unbind to >> prevent >> + * udc driver calls into gadget driver after unbind which could >> cause >> + * a nullptr exception. >> + */ >> usb_gadget_udc_stop(udc); >> + udc->driver->unbind(udc->gadget); > > This patch is incorrect, it will prevent us from giving back requests > to > gadget driver properly. ->unbind() has to happen before ->udc_stop(). Do you mean after udc_stop the udc driver can not call the gadget driver anymore? If not, I did not got your point, sorry for that. Can you please help me out? Would the changed order raise another issue I'm not aware of? If I understood you correctly, without this patch udc driver can not call the gadget driver back as well, because this would result in a NULL ptr dereference, as unbind() sets drvdata to NULL. In any case the race described in my original message can still happen, regardless of the order of udc_stop and unbind. But with this patch the needed locking could easily done within the udc driver only. Without, the lock needs to be acquired before udc->driver->unbind(udc->gadget) and released after usb_gadget_udc_stop(). Otherwise an ISR of the udc driver trying to call into the gadget driver could do this after gadget driver already unbound. Regards, Danilo
Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
[PATCH] usb: gadget: udc: udc_stop before gadget unbind Danilo Krummrich <danilokrummrich@dk-develop.de> - 2017-08-14 18:40 +0200
Re: [PATCH] usb: gadget: udc: udc_stop before gadget unbind Felipe Balbi <balbi@kernel.org> - 2017-08-15 12:10 +0200
Re: [PATCH] usb: gadget: udc: udc_stop before gadget unbind Danilo Krummrich <danilokrummrich@dk-develop.de> - 2017-08-15 14:00 +0200
Re: [PATCH] usb: gadget: udc: udc_stop before gadget unbind Felipe Balbi <balbi@kernel.org> - 2017-08-15 14:10 +0200
Re: [PATCH] usb: gadget: udc: udc_stop before gadget unbind Danilo Krummrich <danilokrummrich@dk-develop.de> - 2017-08-15 15:00 +0200
csiph-web