* [PATCH V3] usb: gadget: storage: Remove warning message @ 2019-05-10 11:02 EJ Hsu 2019-05-10 14:29 ` Alan Stern 0 siblings, 1 reply; 16+ messages in thread From: EJ Hsu @ 2019-05-10 11:02 UTC (permalink / raw) To: balbi; +Cc: linux-usb, ejh This change is to fix below warning message in following scenario: usb_composite_setup_continue: Unexpected call When system tried to enter suspend, the fsg_disable() will be called to disable fsg driver and send a signal to fsg_main_thread. However, at this point, the fsg_main_thread has already been frozen and can not respond to this signal. So, this signal will be pended until fsg_main_thread wakes up. Once system resumes from suspend, fsg_main_thread will detect a signal pended and do some corresponding action (in handle_exception()). Then, host will send some setup requests (get descriptor, set configuration...) to UDC driver trying to enumerate this device. During the handling of "set configuration" request, it will try to sync up with fsg_main_thread by sending a signal (which is the same as the signal sent by fsg_disable) to it. In a similar manner, once the fsg_main_thread receives this signal, it will call handle_exception() to handle the request. However, if the fsg_main_thread wakes up from suspend a little late and "set configuration" request from Host arrives a little earlier, fsg_main_thread might come across the request from "set configuration" when it handles the signal from fsg_disable(). In this case, it will handle this request as well. So, when fsg_main_thread tries to handle the signal sent from "set configuration" later, there will nothing left to do and warning message "Unexpected call" is printed. Signed-off-by: EJ Hsu <ejh@nvidia.com> --- v2: remove the copyright info v3: change fsg_unbind() to use FSG_STATE_DISCONNECT --- drivers/usb/gadget/function/f_mass_storage.c | 21 +++++++++++++++------ drivers/usb/gadget/function/storage_common.h | 1 + 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 043f97a..982c3e8 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -2293,8 +2293,7 @@ static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) static void fsg_disable(struct usb_function *f) { struct fsg_dev *fsg = fsg_from_func(f); - fsg->common->new_fsg = NULL; - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); + raise_exception(fsg->common, FSG_STATE_DISCONNECT); } @@ -2307,6 +2306,7 @@ static void handle_exception(struct fsg_common *common) enum fsg_state old_state; struct fsg_lun *curlun; unsigned int exception_req_tag; + struct fsg_dev *fsg; /* * Clear the existing signals. Anything but SIGUSR1 is converted @@ -2413,9 +2413,19 @@ static void handle_exception(struct fsg_common *common) break; case FSG_STATE_CONFIG_CHANGE: - do_set_interface(common, common->new_fsg); - if (common->new_fsg) + fsg = common->new_fsg; + /* + * Add a check here to double confirm if a disconnect event + * occurs and common->new_fsg has been cleared. + */ + if (fsg) { + do_set_interface(common, fsg); usb_composite_setup_continue(common->cdev); + } + break; + + case FSG_STATE_DISCONNECT: + do_set_interface(common, NULL); break; case FSG_STATE_EXIT: @@ -2989,8 +2999,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) DBG(fsg, "unbind\n"); if (fsg->common->fsg == fsg) { - fsg->common->new_fsg = NULL; - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); + raise_exception(fsg->common, FSG_STATE_DISCONNECT); /* FIXME: make interruptible or killable somehow? */ wait_event(common->fsg_wait, common->fsg != fsg); } diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h index e5e3a25..12687f7 100644 --- a/drivers/usb/gadget/function/storage_common.h +++ b/drivers/usb/gadget/function/storage_common.h @@ -161,6 +161,7 @@ enum fsg_state { FSG_STATE_ABORT_BULK_OUT, FSG_STATE_PROTOCOL_RESET, FSG_STATE_CONFIG_CHANGE, + FSG_STATE_DISCONNECT, FSG_STATE_EXIT, FSG_STATE_TERMINATED }; -- 2.1.4 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH V3] usb: gadget: storage: Remove warning message 2019-05-10 11:02 [PATCH V3] usb: gadget: storage: Remove warning message EJ Hsu @ 2019-05-10 14:29 ` Alan Stern 2019-07-02 1:58 ` Thinh Nguyen 0 siblings, 1 reply; 16+ messages in thread From: Alan Stern @ 2019-05-10 14:29 UTC (permalink / raw) To: EJ Hsu; +Cc: balbi, linux-usb On Fri, 10 May 2019, EJ Hsu wrote: > This change is to fix below warning message in following scenario: > usb_composite_setup_continue: Unexpected call > > When system tried to enter suspend, the fsg_disable() will be called to > disable fsg driver and send a signal to fsg_main_thread. However, at > this point, the fsg_main_thread has already been frozen and can not > respond to this signal. So, this signal will be pended until > fsg_main_thread wakes up. > > Once system resumes from suspend, fsg_main_thread will detect a signal > pended and do some corresponding action (in handle_exception()). Then, > host will send some setup requests (get descriptor, set configuration...) > to UDC driver trying to enumerate this device. During the handling of "set > configuration" request, it will try to sync up with fsg_main_thread by > sending a signal (which is the same as the signal sent by fsg_disable) > to it. In a similar manner, once the fsg_main_thread receives this > signal, it will call handle_exception() to handle the request. > > However, if the fsg_main_thread wakes up from suspend a little late and > "set configuration" request from Host arrives a little earlier, > fsg_main_thread might come across the request from "set configuration" > when it handles the signal from fsg_disable(). In this case, it will > handle this request as well. So, when fsg_main_thread tries to handle > the signal sent from "set configuration" later, there will nothing left > to do and warning message "Unexpected call" is printed. > > Signed-off-by: EJ Hsu <ejh@nvidia.com> > --- > v2: remove the copyright info > v3: change fsg_unbind() to use FSG_STATE_DISCONNECT > --- > drivers/usb/gadget/function/f_mass_storage.c | 21 +++++++++++++++------ > drivers/usb/gadget/function/storage_common.h | 1 + > 2 files changed, 16 insertions(+), 6 deletions(-) > > diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c > index 043f97a..982c3e8 100644 > --- a/drivers/usb/gadget/function/f_mass_storage.c > +++ b/drivers/usb/gadget/function/f_mass_storage.c > @@ -2293,8 +2293,7 @@ static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) > static void fsg_disable(struct usb_function *f) > { > struct fsg_dev *fsg = fsg_from_func(f); > - fsg->common->new_fsg = NULL; > - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); > + raise_exception(fsg->common, FSG_STATE_DISCONNECT); > } > > > @@ -2307,6 +2306,7 @@ static void handle_exception(struct fsg_common *common) > enum fsg_state old_state; > struct fsg_lun *curlun; > unsigned int exception_req_tag; > + struct fsg_dev *fsg; > > /* > * Clear the existing signals. Anything but SIGUSR1 is converted > @@ -2413,9 +2413,19 @@ static void handle_exception(struct fsg_common *common) > break; > > case FSG_STATE_CONFIG_CHANGE: > - do_set_interface(common, common->new_fsg); > - if (common->new_fsg) > + fsg = common->new_fsg; > + /* > + * Add a check here to double confirm if a disconnect event > + * occurs and common->new_fsg has been cleared. > + */ > + if (fsg) { > + do_set_interface(common, fsg); > usb_composite_setup_continue(common->cdev); > + } > + break; > + > + case FSG_STATE_DISCONNECT: > + do_set_interface(common, NULL); > break; > > case FSG_STATE_EXIT: > @@ -2989,8 +2999,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) > > DBG(fsg, "unbind\n"); > if (fsg->common->fsg == fsg) { > - fsg->common->new_fsg = NULL; > - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); > + raise_exception(fsg->common, FSG_STATE_DISCONNECT); > /* FIXME: make interruptible or killable somehow? */ > wait_event(common->fsg_wait, common->fsg != fsg); > } > diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h > index e5e3a25..12687f7 100644 > --- a/drivers/usb/gadget/function/storage_common.h > +++ b/drivers/usb/gadget/function/storage_common.h > @@ -161,6 +161,7 @@ enum fsg_state { > FSG_STATE_ABORT_BULK_OUT, > FSG_STATE_PROTOCOL_RESET, > FSG_STATE_CONFIG_CHANGE, > + FSG_STATE_DISCONNECT, > FSG_STATE_EXIT, > FSG_STATE_TERMINATED > }; Acked-by: Alan Stern <stern@rowland.harvard.edu> Although at this point the comment you have added to the CONFIG_CHANGE case and the following test are useless. Since common->new_fsg doesn't get cleared any more, it will never be NULL at this point. What really matters is that the FSG_STATE_DISCONNECT case doesn't call usb_composite_setup_continue(). Alan Stern ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V3] usb: gadget: storage: Remove warning message 2019-05-10 14:29 ` Alan Stern @ 2019-07-02 1:58 ` Thinh Nguyen 2019-07-02 14:10 ` Alan Stern 0 siblings, 1 reply; 16+ messages in thread From: Thinh Nguyen @ 2019-07-02 1:58 UTC (permalink / raw) To: Alan Stern, EJ Hsu; +Cc: balbi@kernel.org, linux-usb@vger.kernel.org Hi, Alan Stern wrote: > On Fri, 10 May 2019, EJ Hsu wrote: > >> This change is to fix below warning message in following scenario: >> usb_composite_setup_continue: Unexpected call >> >> When system tried to enter suspend, the fsg_disable() will be called to >> disable fsg driver and send a signal to fsg_main_thread. However, at >> this point, the fsg_main_thread has already been frozen and can not >> respond to this signal. So, this signal will be pended until >> fsg_main_thread wakes up. >> >> Once system resumes from suspend, fsg_main_thread will detect a signal >> pended and do some corresponding action (in handle_exception()). Then, >> host will send some setup requests (get descriptor, set configuration...) >> to UDC driver trying to enumerate this device. During the handling of "set >> configuration" request, it will try to sync up with fsg_main_thread by >> sending a signal (which is the same as the signal sent by fsg_disable) >> to it. In a similar manner, once the fsg_main_thread receives this >> signal, it will call handle_exception() to handle the request. >> >> However, if the fsg_main_thread wakes up from suspend a little late and >> "set configuration" request from Host arrives a little earlier, >> fsg_main_thread might come across the request from "set configuration" >> when it handles the signal from fsg_disable(). In this case, it will >> handle this request as well. So, when fsg_main_thread tries to handle >> the signal sent from "set configuration" later, there will nothing left >> to do and warning message "Unexpected call" is printed. >> >> Signed-off-by: EJ Hsu <ejh@nvidia.com> >> --- >> v2: remove the copyright info >> v3: change fsg_unbind() to use FSG_STATE_DISCONNECT >> --- >> drivers/usb/gadget/function/f_mass_storage.c | 21 +++++++++++++++------ >> drivers/usb/gadget/function/storage_common.h | 1 + >> 2 files changed, 16 insertions(+), 6 deletions(-) >> >> diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c >> index 043f97a..982c3e8 100644 >> --- a/drivers/usb/gadget/function/f_mass_storage.c >> +++ b/drivers/usb/gadget/function/f_mass_storage.c >> @@ -2293,8 +2293,7 @@ static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) >> static void fsg_disable(struct usb_function *f) >> { >> struct fsg_dev *fsg = fsg_from_func(f); >> - fsg->common->new_fsg = NULL; >> - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); >> + raise_exception(fsg->common, FSG_STATE_DISCONNECT); >> } >> >> >> @@ -2307,6 +2306,7 @@ static void handle_exception(struct fsg_common *common) >> enum fsg_state old_state; >> struct fsg_lun *curlun; >> unsigned int exception_req_tag; >> + struct fsg_dev *fsg; >> >> /* >> * Clear the existing signals. Anything but SIGUSR1 is converted >> @@ -2413,9 +2413,19 @@ static void handle_exception(struct fsg_common *common) >> break; >> >> case FSG_STATE_CONFIG_CHANGE: >> - do_set_interface(common, common->new_fsg); >> - if (common->new_fsg) >> + fsg = common->new_fsg; >> + /* >> + * Add a check here to double confirm if a disconnect event >> + * occurs and common->new_fsg has been cleared. >> + */ >> + if (fsg) { >> + do_set_interface(common, fsg); >> usb_composite_setup_continue(common->cdev); >> + } >> + break; >> + >> + case FSG_STATE_DISCONNECT: >> + do_set_interface(common, NULL); >> break; >> >> case FSG_STATE_EXIT: >> @@ -2989,8 +2999,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) >> >> DBG(fsg, "unbind\n"); >> if (fsg->common->fsg == fsg) { >> - fsg->common->new_fsg = NULL; >> - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); >> + raise_exception(fsg->common, FSG_STATE_DISCONNECT); >> /* FIXME: make interruptible or killable somehow? */ >> wait_event(common->fsg_wait, common->fsg != fsg); >> } >> diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h >> index e5e3a25..12687f7 100644 >> --- a/drivers/usb/gadget/function/storage_common.h >> +++ b/drivers/usb/gadget/function/storage_common.h >> @@ -161,6 +161,7 @@ enum fsg_state { >> FSG_STATE_ABORT_BULK_OUT, >> FSG_STATE_PROTOCOL_RESET, >> FSG_STATE_CONFIG_CHANGE, >> + FSG_STATE_DISCONNECT, >> FSG_STATE_EXIT, >> FSG_STATE_TERMINATED >> }; > Acked-by: Alan Stern <stern@rowland.harvard.edu> > > Although at this point the comment you have added to the CONFIG_CHANGE > case and the following test are useless. Since common->new_fsg doesn't > get cleared any more, it will never be NULL at this point. > > What really matters is that the FSG_STATE_DISCONNECT case doesn't call > usb_composite_setup_continue(). > > Alan Stern This patch causes a failure in USB CV TD 9.13 Set Configuration Test. Please review and help resolve it. Apologize for the short report description. I'll try to capture more info if you cannot reproduce it. Thanks, Thinh ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V3] usb: gadget: storage: Remove warning message 2019-07-02 1:58 ` Thinh Nguyen @ 2019-07-02 14:10 ` Alan Stern [not found] ` <CY4PR1201MB0037C93EC7F81A394008C4CCAAF80@CY4PR1201MB0037.namprd12.prod.outlook.com> 0 siblings, 1 reply; 16+ messages in thread From: Alan Stern @ 2019-07-02 14:10 UTC (permalink / raw) To: Thinh Nguyen; +Cc: EJ Hsu, balbi@kernel.org, linux-usb@vger.kernel.org On Tue, 2 Jul 2019, Thinh Nguyen wrote: > Hi, > > Alan Stern wrote: > > On Fri, 10 May 2019, EJ Hsu wrote: > > > >> This change is to fix below warning message in following scenario: > >> usb_composite_setup_continue: Unexpected call > >> > >> When system tried to enter suspend, the fsg_disable() will be called to > >> disable fsg driver and send a signal to fsg_main_thread. However, at > >> this point, the fsg_main_thread has already been frozen and can not > >> respond to this signal. So, this signal will be pended until > >> fsg_main_thread wakes up. > >> > >> Once system resumes from suspend, fsg_main_thread will detect a signal > >> pended and do some corresponding action (in handle_exception()). Then, > >> host will send some setup requests (get descriptor, set configuration...) > >> to UDC driver trying to enumerate this device. During the handling of "set > >> configuration" request, it will try to sync up with fsg_main_thread by > >> sending a signal (which is the same as the signal sent by fsg_disable) > >> to it. In a similar manner, once the fsg_main_thread receives this > >> signal, it will call handle_exception() to handle the request. > >> > >> However, if the fsg_main_thread wakes up from suspend a little late and > >> "set configuration" request from Host arrives a little earlier, > >> fsg_main_thread might come across the request from "set configuration" > >> when it handles the signal from fsg_disable(). In this case, it will > >> handle this request as well. So, when fsg_main_thread tries to handle > >> the signal sent from "set configuration" later, there will nothing left > >> to do and warning message "Unexpected call" is printed. > >> > >> Signed-off-by: EJ Hsu <ejh@nvidia.com> > >> --- > >> v2: remove the copyright info > >> v3: change fsg_unbind() to use FSG_STATE_DISCONNECT > >> --- > This patch causes a failure in USB CV TD 9.13 Set Configuration Test. > Please review and help resolve it. > Apologize for the short report description. I'll try to capture more > info if you cannot reproduce it. Yes, please provide the complete log and information from the failing USB CV test. Alan Stern ^ permalink raw reply [flat|nested] 16+ messages in thread
[parent not found: <CY4PR1201MB0037C93EC7F81A394008C4CCAAF80@CY4PR1201MB0037.namprd12.prod.outlook.com>]
* Re: [PATCH V3] usb: gadget: storage: Remove warning message [not found] ` <CY4PR1201MB0037C93EC7F81A394008C4CCAAF80@CY4PR1201MB0037.namprd12.prod.outlook.com> @ 2019-07-02 18:06 ` Thinh Nguyen 2019-07-03 11:20 ` EJ Hsu 0 siblings, 1 reply; 16+ messages in thread From: Thinh Nguyen @ 2019-07-02 18:06 UTC (permalink / raw) To: Alan Stern, Thinh Nguyen Cc: EJ Hsu, balbi@kernel.org, linux-usb@vger.kernel.org Thinh Nguyen wrote: > Alan Stern wrote: >> On Tue, 2 Jul 2019, Thinh Nguyen wrote: >> >>> Hi, >>> >>> Alan Stern wrote: >>>> On Fri, 10 May 2019, EJ Hsu wrote: >>>> >>>>> This change is to fix below warning message in following scenario: >>>>> usb_composite_setup_continue: Unexpected call >>>>> >>>>> When system tried to enter suspend, the fsg_disable() will be called to >>>>> disable fsg driver and send a signal to fsg_main_thread. However, at >>>>> this point, the fsg_main_thread has already been frozen and can not >>>>> respond to this signal. So, this signal will be pended until >>>>> fsg_main_thread wakes up. >>>>> >>>>> Once system resumes from suspend, fsg_main_thread will detect a signal >>>>> pended and do some corresponding action (in handle_exception()). Then, >>>>> host will send some setup requests (get descriptor, set configuration...) >>>>> to UDC driver trying to enumerate this device. During the handling of "set >>>>> configuration" request, it will try to sync up with fsg_main_thread by >>>>> sending a signal (which is the same as the signal sent by fsg_disable) >>>>> to it. In a similar manner, once the fsg_main_thread receives this >>>>> signal, it will call handle_exception() to handle the request. >>>>> >>>>> However, if the fsg_main_thread wakes up from suspend a little late and >>>>> "set configuration" request from Host arrives a little earlier, >>>>> fsg_main_thread might come across the request from "set configuration" >>>>> when it handles the signal from fsg_disable(). In this case, it will >>>>> handle this request as well. So, when fsg_main_thread tries to handle >>>>> the signal sent from "set configuration" later, there will nothing left >>>>> to do and warning message "Unexpected call" is printed. >>>>> >>>>> Signed-off-by: EJ Hsu <ejh@nvidia.com> >>>>> --- >>>>> v2: remove the copyright info >>>>> v3: change fsg_unbind() to use FSG_STATE_DISCONNECT >>>>> --- >>> This patch causes a failure in USB CV TD 9.13 Set Configuration Test. >>> Please review and help resolve it. >>> Apologize for the short report description. I'll try to capture more >>> info if you cannot reproduce it. >> Yes, please provide the complete log and information from the failing >> USB CV test. >> > I attached the CV test log. I hope that's sufficient. > We may have issue sending attched HTML file. Here's a text format of it: TEST SUITE: Chapter 9 Tests [USB 3 Gen X devices].cvtests REVISION: 10866 REVISION DATE: 2018-02-28 16:30:43 -0800 (Wed, 28 Feb 2018) OPERATING SYSTEM: Windows 10 Home (Build 18894.1000.amd64fre.rs_prerelease.190503-1728) WORKSTATION: USB-AUTOMATION DATE: Tuesday, July 02, 2019 TIME: 01:52:01 AM OPERATOR: Lab_auto NUMBER OF TESTS: 1 LOG NAME: Chapter 9 Tests - USB 3 Gen X - 2019-07-02 01-51-36 RESULT: failed InitializeTestSuite INFOTest log initialized. INFOLog Level: Normal INFOUser Input module initialized INFOWindows 10 Home (Build 18894.1000.amd64fre.rs_prerelease.190503-1728) INFOCVExe.exe ver 3.0.0.0 INFOBaseUtilities.dll ver 3.0.0.0 INFOCommandVerifierLog.dll ver 3.0.0.0 INFOTSMFCGuiDialogHelperDLL.dll ver 3.0.0.0 INFOTestUtilities.dll ver 3.0.0.0 INFOTestSuiteEngine.dll ver 3.0.0.0 INFOVIFReader.dll ver 3.0.0.0 INFOxhci_DevIOCTL.dll ver 2.1.10.3 INFOxhci_TestServices.dll ver 2.1.10.3 INFOUSBUtilities.dll ver 1.4.5.1 INFOStackSwitcher.dll ver 1.4.5.1 INFOxhci_USBCommandVerifier.dll ver 2.1.10.3 INFOHost selected: xHCI Host: VID=0x8086, PID=0xa36d (PCI bus 0, device 20, function 0) INFODUT selected: SSP Device (MSC/BOT) addr=1: VID=053f, PID=8bd8 INFOTopology: XHCI HC -- DUT INFOSuperSpeedPlus Device. GetNumberOfConfigurations INFOUSB Version number of device: 3.20 INFONumber of configurations: 1 TD 9.13 Set Configuration Test - Device State AddressedFailed (Aborted) INFOStart time: Tue Jul 2 01:51:39 2019 INFO In Address state: INFONow doing a Set Configuration with Configuration Value 0 INFOSet Configuration with Configuration Value 0 succeeded INFONow doing a Get Configuration INFOGet Configuration for the device returned the correct Configuration Value of 0 INFONow doing a Get Descriptor with Configuration Index 0 INFOGet Descriptor succeeded and returned Configuration Value : 1 INFONow doing a Set Configuration with Configuration Value 1 INFOSet Configuration succeeded with Configuration Value : 1 INFO In Configured state: INFONow doing a Get Descriptor with Configuration Index 0 INFOGet Descriptor succeeded and returned Configuration Value : 1 INFONow doing a Set Configuration with Configuration Value 1 ERRORSet Configuration failed for Configuration Value : 1 ERRORSet Configuration failed with Configuration Value : 1 FAIL(9.4.7.1) Devices must support a valid SetConfiguration() request INFONow doing a Set Configuration with Configuration Value 0 ERRORSet Configuration failed for Configuration Value : 0 ERRORCould not unconfigure the device FAIL(9.4.7.4) In the Configured state in response to the SetConfiguration() request, the device must enter the Address state, if the specified configuration is zero. INFONow doing a Get Configuration ERRORGet configuration failed ERRORCould not Get Configuration for the device ERRORGet device descriptor failed ERRORCouldn't get USB Version of Device Under Test ERRORGet number of configurations failed ABORTCould not find an invalid Configuration Value, FindInvalidConfigValue() returned 0 - Internal error INFOPutting device back in Configured state ERRORSet Configuration failed for Configuration Value : 1 ERRORSet Configuration failed with Configuration Value : 1 FAIL(9.4.7.1) Devices must support a valid SetConfiguration() request INFONow doing a Get Configuration ERRORGet configuration failed ERRORCould not Get Configuration for the device FAIL(9.4.2.2) Devices should return the non-zero bConfigurationValue of the current configuration for the GetConfiguration() request in the Configured state. INFONow doing a Get Configuration ERRORGet configuration failed ERRORCould not Get Configuration for the device FAIL(9.4.2.2) Devices should return the non-zero bConfigurationValue of the current configuration for the GetConfiguration() request in the Configured state. INFONow doing a Set Configuration with Configuration Value 0 ERRORSet Configuration failed for Configuration Value : 0 ERRORCould not unconfigure the device FAIL(9.4.7.4) In the Configured state in response to the SetConfiguration() request, the device must enter the Address state, if the specified configuration is zero. FAILTest did not execute all required steps. INFO Stop time: Tue Jul 2 01:52:01 2019 INFODuration: 22 seconds. INFOStopping Test [ TD 9.13 Set Configuration Test - Device State Addressed: Number of: Fails (7); Aborts (1); Warnings (0) ] Summary INFOTEST SUITE SUMMARY: [ Fails (7); Aborts (1); Warnings (0) ] INFOTEST RESULTS: [ Passed (0); Failed (1) ] BR, Thinh ^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [PATCH V3] usb: gadget: storage: Remove warning message 2019-07-02 18:06 ` Thinh Nguyen @ 2019-07-03 11:20 ` EJ Hsu 2019-07-04 8:39 ` EJ Hsu 0 siblings, 1 reply; 16+ messages in thread From: EJ Hsu @ 2019-07-03 11:20 UTC (permalink / raw) To: Thinh Nguyen, Alan Stern; +Cc: balbi@kernel.org, linux-usb@vger.kernel.org EJ Hsu wrote: > Thinh Nguyen wrote: > > Alan Stern wrote: > >> On Tue, 2 Jul 2019, Thinh Nguyen wrote: > >> > >>> Hi, > >>> > >>> Alan Stern wrote: > >>>> On Fri, 10 May 2019, EJ Hsu wrote: > >>>> > >>>>> This change is to fix below warning message in following scenario: > >>>>> usb_composite_setup_continue: Unexpected call > >>>>> > >>>>> When system tried to enter suspend, the fsg_disable() will be > >>>>> called to disable fsg driver and send a signal to fsg_main_thread. > >>>>> However, at this point, the fsg_main_thread has already been > >>>>> frozen and can not respond to this signal. So, this signal will be > >>>>> pended until fsg_main_thread wakes up. > >>>>> > >>>>> Once system resumes from suspend, fsg_main_thread will detect a > >>>>> signal pended and do some corresponding action (in > >>>>> handle_exception()). Then, host will send some setup requests (get > >>>>> descriptor, set configuration...) to UDC driver trying to > >>>>> enumerate this device. During the handling of "set configuration" > >>>>> request, it will try to sync up with fsg_main_thread by sending a > >>>>> signal (which is the same as the signal sent by fsg_disable) to > >>>>> it. In a similar manner, once the fsg_main_thread receives this signal, it > will call handle_exception() to handle the request. > >>>>> > >>>>> However, if the fsg_main_thread wakes up from suspend a little > >>>>> late and "set configuration" request from Host arrives a little > >>>>> earlier, fsg_main_thread might come across the request from "set > configuration" > >>>>> when it handles the signal from fsg_disable(). In this case, it > >>>>> will handle this request as well. So, when fsg_main_thread tries > >>>>> to handle the signal sent from "set configuration" later, there > >>>>> will nothing left to do and warning message "Unexpected call" is printed. > >>>>> > >>>>> Signed-off-by: EJ Hsu <ejh@nvidia.com> > >>>>> --- > >>>>> v2: remove the copyright info > >>>>> v3: change fsg_unbind() to use FSG_STATE_DISCONNECT > >>>>> --- > >>> This patch causes a failure in USB CV TD 9.13 Set Configuration Test. > >>> Please review and help resolve it. > >>> Apologize for the short report description. I'll try to capture more > >>> info if you cannot reproduce it. > >> Yes, please provide the complete log and information from the failing > >> USB CV test. > >> > > I attached the CV test log. I hope that's sufficient. > > > > We may have issue sending attched HTML file. Here's a text format of it: > > > TEST SUITE: Chapter 9 Tests [USB 3 Gen X devices].cvtests > REVISION: 10866 > REVISION DATE: 2018-02-28 16:30:43 -0800 (Wed, 28 Feb 2018) > OPERATING SYSTEM: Windows 10 Home (Build > 18894.1000.amd64fre.rs_prerelease.190503-1728) > WORKSTATION: USB-AUTOMATION > DATE: Tuesday, July 02, 2019 > TIME: 01:52:01 AM > OPERATOR: Lab_auto > NUMBER OF TESTS: 1 > LOG NAME: Chapter 9 Tests - USB 3 Gen X - 2019-07-02 01-51-36 > RESULT: failed > > InitializeTestSuite > > INFOTest log initialized. > INFOLog Level: Normal > INFOUser Input module initialized > INFOWindows 10 Home (Build 18894.1000.amd64fre.rs_prerelease.190503- > 1728) > INFOCVExe.exe ver 3.0.0.0 > INFOBaseUtilities.dll ver 3.0.0.0 > INFOCommandVerifierLog.dll ver 3.0.0.0 > INFOTSMFCGuiDialogHelperDLL.dll ver 3.0.0.0 INFOTestUtilities.dll ver 3.0.0.0 > INFOTestSuiteEngine.dll ver 3.0.0.0 INFOVIFReader.dll ver 3.0.0.0 > INFOxhci_DevIOCTL.dll ver 2.1.10.3 INFOxhci_TestServices.dll ver 2.1.10.3 > INFOUSBUtilities.dll ver 1.4.5.1 INFOStackSwitcher.dll ver 1.4.5.1 > INFOxhci_USBCommandVerifier.dll ver 2.1.10.3 INFOHost selected: xHCI Host: > VID=0x8086, PID=0xa36d (PCI bus 0, device 20, function 0) > INFODUT selected: SSP Device (MSC/BOT) addr=1: VID=053f, PID=8bd8 > INFOTopology: XHCI HC -- DUT > INFOSuperSpeedPlus Device. > > GetNumberOfConfigurations > > INFOUSB Version number of device: 3.20 > INFONumber of configurations: 1 > > TD 9.13 Set Configuration Test - Device State AddressedFailed (Aborted) > > INFOStart time: Tue Jul 2 01:51:39 2019 > > INFO In Address state: > INFONow doing a Set Configuration with Configuration Value 0 INFOSet > Configuration with Configuration Value 0 succeeded INFONow doing a Get > Configuration INFOGet Configuration for the device returned the correct > Configuration Value of 0 INFONow doing a Get Descriptor with Configuration > Index 0 INFOGet Descriptor succeeded and returned Configuration Value : 1 > INFONow doing a Set Configuration with Configuration Value 1 INFOSet > Configuration succeeded with Configuration Value : 1 > INFO In Configured state: > INFONow doing a Get Descriptor with Configuration Index 0 INFOGet > Descriptor succeeded and returned Configuration Value : 1 INFONow doing a > Set Configuration with Configuration Value 1 ERRORSet Configuration failed for > Configuration Value : 1 ERRORSet Configuration failed with Configuration > Value : 1 > FAIL(9.4.7.1) Devices must support a valid SetConfiguration() request INFONow > doing a Set Configuration with Configuration Value 0 ERRORSet Configuration > failed for Configuration Value : 0 ERRORCould not unconfigure the device > FAIL(9.4.7.4) In the Configured state in response to the > SetConfiguration() request, the device must enter the Address state, if the > specified configuration is zero. > INFONow doing a Get Configuration > ERRORGet configuration failed > ERRORCould not Get Configuration for the device ERRORGet device descriptor > failed ERRORCouldn't get USB Version of Device Under Test ERRORGet number > of configurations failed ABORTCould not find an invalid Configuration Value, > FindInvalidConfigValue() returned 0 - Internal error INFOPutting device back in > Configured state ERRORSet Configuration failed for Configuration Value : 1 > ERRORSet Configuration failed with Configuration Value : 1 > FAIL(9.4.7.1) Devices must support a valid SetConfiguration() request INFONow > doing a Get Configuration ERRORGet configuration failed ERRORCould not Get > Configuration for the device > FAIL(9.4.2.2) Devices should return the non-zero bConfigurationValue of the > current configuration for the GetConfiguration() request in the Configured > state. > INFONow doing a Get Configuration > ERRORGet configuration failed > ERRORCould not Get Configuration for the device > FAIL(9.4.2.2) Devices should return the non-zero bConfigurationValue of the > current configuration for the GetConfiguration() request in the Configured > state. > INFONow doing a Set Configuration with Configuration Value 0 ERRORSet > Configuration failed for Configuration Value : 0 ERRORCould not unconfigure > the device > FAIL(9.4.7.4) In the Configured state in response to the > SetConfiguration() request, the device must enter the Address state, if the > specified configuration is zero. > FAILTest did not execute all required steps. > INFO > Stop time: Tue Jul 2 01:52:01 2019 > INFODuration: 22 seconds. > INFOStopping Test [ TD 9.13 Set Configuration Test - Device State Addressed: > Number of: Fails (7); Aborts (1); Warnings (0) ] > > Summary > > INFOTEST SUITE SUMMARY: > [ Fails (7); Aborts (1); Warnings (0) ] INFOTEST RESULTS: > [ Passed (0); Failed (1) ] > > > > > BR, > Thinh I can reproduce this issue locally. The reproducing rate is about 1 out of 10. Will look into this issue. Thanks ----------------------------------------------------------------------------------- This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. ----------------------------------------------------------------------------------- ^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [PATCH V3] usb: gadget: storage: Remove warning message 2019-07-03 11:20 ` EJ Hsu @ 2019-07-04 8:39 ` EJ Hsu 2019-07-04 16:06 ` Alan Stern 0 siblings, 1 reply; 16+ messages in thread From: EJ Hsu @ 2019-07-04 8:39 UTC (permalink / raw) To: Thinh Nguyen, Alan Stern Cc: balbi@kernel.org, linux-usb@vger.kernel.org, WK Tsai Based on my initial debugging, USB CV TD 9.13 will consecutively set device to configuration #1 by sending "Set Configuration" transfer. So, in set_config() function, it will try to disable each interface first and then set up each interface. That is, the fsg_disable() will be called first and then fsg_set_alt(). There might be a chance that the request (FSG_STATE_DISCONNECT) from fsg_disabled() has not been handled by fsg_main_thread before fsg_set_alt() is called. In this case, fsg_set_alt() will try to queue its request (FSG_STATE_CONFIG_CHANGE) to fsg_main_thread, but find that FSG_STATE_DISCONNECT has not been handled. Because the priority of FSG_STATE_DISCONNECT is higher than FSG_STATE_CONFIG_CHANGE, FSG_STATE_CONFIG_CHANGE will be discarded accordingly. This might lead to the missing of usb_composite_setup_continue() which result in the failure of "Set Configuration" transfer. Will push a new patch to fix this issue. --nvpublic ^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [PATCH V3] usb: gadget: storage: Remove warning message 2019-07-04 8:39 ` EJ Hsu @ 2019-07-04 16:06 ` Alan Stern 2019-07-05 10:49 ` EJ Hsu 0 siblings, 1 reply; 16+ messages in thread From: Alan Stern @ 2019-07-04 16:06 UTC (permalink / raw) To: EJ Hsu; +Cc: Thinh Nguyen, balbi@kernel.org, linux-usb@vger.kernel.org, WK Tsai On Thu, 4 Jul 2019, EJ Hsu wrote: > Based on my initial debugging, USB CV TD 9.13 will consecutively set device to configuration #1 by sending "Set Configuration" transfer. > So, in set_config() function, it will try to disable each interface first and then set up each interface. That is, the fsg_disable() will be called first and then fsg_set_alt(). > There might be a chance that the request (FSG_STATE_DISCONNECT) from fsg_disabled() has not been handled by fsg_main_thread before fsg_set_alt() is called. > In this case, fsg_set_alt() will try to queue its request (FSG_STATE_CONFIG_CHANGE) to fsg_main_thread, but find that FSG_STATE_DISCONNECT has not been handled. > Because the priority of FSG_STATE_DISCONNECT is higher than FSG_STATE_CONFIG_CHANGE, FSG_STATE_CONFIG_CHANGE will be discarded accordingly. > This might lead to the missing of usb_composite_setup_continue() which result in the failure of "Set Configuration" transfer. > > Will push a new patch to fix this issue. Have you seen these emails? https://marc.info/?l=linux-usb&m=156222739324546&w=2 https://marc.info/?l=linux-usb&m=156222747024558&w=2 They are probably related to this same issue. Alan Stern ^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [PATCH V3] usb: gadget: storage: Remove warning message 2019-07-04 16:06 ` Alan Stern @ 2019-07-05 10:49 ` EJ Hsu 2019-07-05 12:28 ` Benjamin Herrenschmidt 2019-07-05 12:34 ` Benjamin Herrenschmidt 0 siblings, 2 replies; 16+ messages in thread From: EJ Hsu @ 2019-07-05 10:49 UTC (permalink / raw) To: Alan Stern Cc: Thinh Nguyen, balbi@kernel.org, linux-usb@vger.kernel.org, WK Tsai, benh@kernel.crashing.org Alan Stern wrote: > On Thu, 4 Jul 2019, EJ Hsu wrote: > > > Based on my initial debugging, USB CV TD 9.13 will consecutively set device > to configuration #1 by sending "Set Configuration" transfer. > > So, in set_config() function, it will try to disable each interface first and then > set up each interface. That is, the fsg_disable() will be called first and then > fsg_set_alt(). > > There might be a chance that the request (FSG_STATE_DISCONNECT) from > fsg_disabled() has not been handled by fsg_main_thread before fsg_set_alt() is > called. > > In this case, fsg_set_alt() will try to queue its request > (FSG_STATE_CONFIG_CHANGE) to fsg_main_thread, but find that > FSG_STATE_DISCONNECT has not been handled. > > Because the priority of FSG_STATE_DISCONNECT is higher than > FSG_STATE_CONFIG_CHANGE, FSG_STATE_CONFIG_CHANGE will be discarded > accordingly. > > This might lead to the missing of usb_composite_setup_continue() which > result in the failure of "Set Configuration" transfer. > > > > Will push a new patch to fix this issue. > > Have you seen these emails? > > https://marc.info/?l=linux-usb&m=156222739324546&w=2 > https://marc.info/?l=linux-usb&m=156222747024558&w=2 > > They are probably related to this same issue. > > Alan Stern Yes, looks like we are facing the same issue. The change of Ben is similar to mine, but the priority of FSG_STATE_CONFIG_CHANGE in his patch is higher than FSG_STATE_CONFIG_CLEAR. So, it will not hit the USB CV TD 9.13 failure as above. However, in my opinion, I think we should keep the handling of FSG_STATE_CONFIG_CHANGE as it was. FSG_STATE_CONFIG_CHANGE should take care of handling FSG_STATE_CONFIG_CLEAR because of its higher priority. Think about below case: When fsg_main_thread tries to handle the FSG_STATE_CONFIG_CHANGE, a disconnect event arise at the same time and fsg_disable() is called accordingly. In this case, FSG_STATE_CONFIG_CLEAR might not be queued. (depending on if FSG_STATE_CONFIG_CHANGE is cleared in handle_exception() ) If we still call usb_composite_setup_continue() without checking common->new_fsg, the " Unexpected call" message might still be printed (if delayed_status has been cleared in reset_config() ). Please correct me if I have any misunderstanding. The change for my previous patch is as follows, and it works well on my local test. Thanks, EJ diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 982c3e8..b5f1e1e 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -2306,7 +2306,6 @@ static void handle_exception(struct fsg_common *common) enum fsg_state old_state; struct fsg_lun *curlun; unsigned int exception_req_tag; - struct fsg_dev *fsg; /* * Clear the existing signals. Anything but SIGUSR1 is converted @@ -2413,15 +2412,9 @@ static void handle_exception(struct fsg_common *common) break; case FSG_STATE_CONFIG_CHANGE: - fsg = common->new_fsg; - /* - * Add a check here to double confirm if a disconnect event - * occurs and common->new_fsg has been cleared. - */ - if (fsg) { - do_set_interface(common, fsg); + do_set_interface(common, common->new_fsg); + if (common->new_fsg) usb_composite_setup_continue(common->cdev); - } break; case FSG_STATE_DISCONNECT: diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h index 12687f7..fc13921 100644 --- a/drivers/usb/gadget/function/storage_common.h +++ b/drivers/usb/gadget/function/storage_common.h @@ -160,8 +160,8 @@ enum fsg_state { FSG_STATE_NORMAL, FSG_STATE_ABORT_BULK_OUT, FSG_STATE_PROTOCOL_RESET, - FSG_STATE_CONFIG_CHANGE, FSG_STATE_DISCONNECT, + FSG_STATE_CONFIG_CHANGE, FSG_STATE_EXIT, FSG_STATE_TERMINATED }; ----------------------------------------------------------------------------------- This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. ----------------------------------------------------------------------------------- ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH V3] usb: gadget: storage: Remove warning message 2019-07-05 10:49 ` EJ Hsu @ 2019-07-05 12:28 ` Benjamin Herrenschmidt 2019-07-05 14:30 ` Alan Stern 2019-07-05 12:34 ` Benjamin Herrenschmidt 1 sibling, 1 reply; 16+ messages in thread From: Benjamin Herrenschmidt @ 2019-07-05 12:28 UTC (permalink / raw) To: EJ Hsu, Alan Stern Cc: Thinh Nguyen, balbi@kernel.org, linux-usb@vger.kernel.org, WK Tsai On Fri, 2019-07-05 at 10:49 +0000, EJ Hsu wrote: > > Yes, looks like we are facing the same issue. > > The change of Ben is similar to mine, but the priority of FSG_STATE_CONFIG_CHANGE in his patch is higher than FSG_STATE_CONFIG_CLEAR. > So, it will not hit the USB CV TD 9.13 failure as above. Correct. This is on purpose. A CONFIG_CHANGE will wipe out the previous config, so if the queued state was CONFIG_CLEAR, and we haven't dequeued it yet, we can skip it. > However, in my opinion, I think we should keep the handling of > FSG_STATE_CONFIG_CHANGE as it was. FSG_STATE_CONFIG_CHANGE should > take care of handling FSG_STATE_CONFIG_CLEAR because of its higher > priority. My patch does just that. If you get a clear and a change fast enough (ie, the clear hasn't been dequeued), then the change will override, which is what we want, since that will cleanup the previous config regardless. The entire point of my patch is to make sure that new_fsg is only ever set in that one place, the config change, and there is no possible confusion with the async continuation. > Think about below case: > When fsg_main_thread tries to handle the FSG_STATE_CONFIG_CHANGE, a disconnect event arise at the same time and fsg_disable() is called accordingly. > In this case, FSG_STATE_CONFIG_CLEAR might not be queued. (depending on if FSG_STATE_CONFIG_CHANGE is cleared in handle_exception() ) > If we still call usb_composite_setup_continue() without checking common->new_fsg, the " Unexpected call" message might still be printed (if delayed_status has been cleared in reset_config() ). > Please correct me if I have any misunderstanding. new_fsg will never be clear if we do FSG_STATE_CONFIG_CHANGE, that's the whole point of my patch. Otherwise we keep having the problem that I described in my cset comment where two parties stomp on that one variable and confusion ensures. Now, there's indeed one remaining issue as you pointed out. If we disconnect before we've dequeued FSG_STATE_CONFIG_CHANGE. Is that an issue in practice however ? There are several ways we could handle that one: - We can do a fully ordered queue of events. But that's more complex and somewhat suboptimal, but would be the most robust I suppose. - Or we could be a bit smarter here, and have additional state information protected by the lock set while queuing FSG_STATE_CONFIG_CHANGE. This would include the fact that we have a pending set_alt and thus a delayed status to complete. Then we could have a flag indicating a disable/disconnect. fsg_disable would set it, fsg_set_alt would clear it. Those would need to be established with the same lock that queues the state and *retreived* in the same lock as well, otherwise we go back to having them change on the fly leading to inconsistent state. But in any case, having more than one agent stomping on new_fsg locklessly from interrupts is going to be a problem and I don't want to get back down that path. As it is, my patch makes things work for me. Does it work for you ? We can look at polishing more later. Cheers, Ben. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V3] usb: gadget: storage: Remove warning message 2019-07-05 12:28 ` Benjamin Herrenschmidt @ 2019-07-05 14:30 ` Alan Stern 2019-07-05 22:09 ` Benjamin Herrenschmidt 0 siblings, 1 reply; 16+ messages in thread From: Alan Stern @ 2019-07-05 14:30 UTC (permalink / raw) To: Benjamin Herrenschmidt Cc: EJ Hsu, Thinh Nguyen, balbi@kernel.org, linux-usb@vger.kernel.org, WK Tsai On Fri, 5 Jul 2019, Benjamin Herrenschmidt wrote: > On Fri, 2019-07-05 at 10:49 +0000, EJ Hsu wrote: > > > > Yes, looks like we are facing the same issue. > > > > The change of Ben is similar to mine, but the priority of FSG_STATE_CONFIG_CHANGE in his patch is higher than FSG_STATE_CONFIG_CLEAR. > > So, it will not hit the USB CV TD 9.13 failure as above. > > Correct. This is on purpose. A CONFIG_CHANGE will wipe out the previous > config, so if the queued state was CONFIG_CLEAR, and we haven't > dequeued it yet, we can skip it. > > > However, in my opinion, I think we should keep the handling of > > FSG_STATE_CONFIG_CHANGE as it was. FSG_STATE_CONFIG_CHANGE should > > take care of handling FSG_STATE_CONFIG_CLEAR because of its higher > > priority. > > My patch does just that. If you get a clear and a change fast enough > (ie, the clear hasn't been dequeued), then the change will override, > which is what we want, since that will cleanup the previous config > regardless. > > The entire point of my patch is to make sure that new_fsg is only ever > set in that one place, the config change, and there is no possible > confusion with the async continuation. > > > Think about below case: > > When fsg_main_thread tries to handle the FSG_STATE_CONFIG_CHANGE, a disconnect event arise at the same time and fsg_disable() is called accordingly. > > In this case, FSG_STATE_CONFIG_CLEAR might not be queued. (depending on if FSG_STATE_CONFIG_CHANGE is cleared in handle_exception() ) > > If we still call usb_composite_setup_continue() without checking common->new_fsg, the " Unexpected call" message might still be printed (if delayed_status has been cleared in reset_config() ). > > Please correct me if I have any misunderstanding. > > new_fsg will never be clear if we do FSG_STATE_CONFIG_CHANGE, that's > the whole point of my patch. > > Otherwise we keep having the problem that I described in my cset > comment where two parties stomp on that one variable and confusion > ensures. > > Now, there's indeed one remaining issue as you pointed out. If we > disconnect before we've dequeued FSG_STATE_CONFIG_CHANGE. > > Is that an issue in practice however ? There are several ways we could > handle that one: > > - We can do a fully ordered queue of events. But that's more complex > and somewhat suboptimal, but would be the most robust I suppose. > > - Or we could be a bit smarter here, and have additional state > information protected by the lock set while queuing > FSG_STATE_CONFIG_CHANGE. This would include the fact that we have a > pending set_alt and thus a delayed status to complete. Then we could > have a flag indicating a disable/disconnect. fsg_disable would set it, > fsg_set_alt would clear it. Those would need to be established with the > same lock that queues the state and *retreived* in the same lock as > well, otherwise we go back to having them change on the fly leading to > inconsistent state. > > But in any case, having more than one agent stomping on new_fsg > locklessly from interrupts is going to be a problem and I don't want to > get back down that path. > > As it is, my patch makes things work for me. Does it work for you ? We > can look at polishing more later. I haven't looked at the new patches yet. Still, what I originally had in mind for this situation was that the _last_ event should always take precedence. This goes against the idea of having separate FSG_STATE_* levels for disconnect and config-change, because the driver assumes that higher levels should override lower levels. Also, if the thread has already started processing one of these events when another one occurs, the new exception should cause the thread to restart the handler and thus take care of the new event. And yes, there should be enough locking to ensure that nothing gets stomped on except in situations where it won't matter. That's how I think this should all work, and it doesn't look like we really need a queue to do it properly. Alan Stern ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V3] usb: gadget: storage: Remove warning message 2019-07-05 14:30 ` Alan Stern @ 2019-07-05 22:09 ` Benjamin Herrenschmidt 0 siblings, 0 replies; 16+ messages in thread From: Benjamin Herrenschmidt @ 2019-07-05 22:09 UTC (permalink / raw) To: Alan Stern Cc: EJ Hsu, Thinh Nguyen, balbi@kernel.org, linux-usb@vger.kernel.org, WK Tsai On Fri, 2019-07-05 at 10:30 -0400, Alan Stern wrote: > I haven't looked at the new patches yet. > > Still, what I originally had in mind for this situation was that the > _last_ event should always take precedence. This goes against the idea > of having separate FSG_STATE_* levels for disconnect and config-change, > because the driver assumes that higher levels should override lower > levels. Right, this is what my new tentative patch does. The main caveat is to ensure that if that last event arrives after the previous one was "dequeued" by the thread but before it was *processed*, then we don't clobber it's argument (new_fsg) and thus end up processing both events each with the appropriate corresponding value of new_fsg. This is the root of the bug in fact: When the second event occurs in that window, we end up processing twice, as expected, but potentially using twice the *new* new_fsg value. > Also, if the thread has already started processing one of these events > when another one occurs, the new exception should cause the thread to > restart the handler and thus take care of the new event. And yes, > there should be enough locking to ensure that nothing gets stomped on > except in situations where it won't matter. > > That's how I think this should all work, and it doesn't look like we > really need a queue to do it properly. Yes, I agree. That's what the patch I posted last night aims at, I need to test it today. Cheers, Ben. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V3] usb: gadget: storage: Remove warning message 2019-07-05 10:49 ` EJ Hsu 2019-07-05 12:28 ` Benjamin Herrenschmidt @ 2019-07-05 12:34 ` Benjamin Herrenschmidt 2019-07-05 13:13 ` Benjamin Herrenschmidt 1 sibling, 1 reply; 16+ messages in thread From: Benjamin Herrenschmidt @ 2019-07-05 12:34 UTC (permalink / raw) To: EJ Hsu, Alan Stern Cc: Thinh Nguyen, balbi@kernel.org, linux-usb@vger.kernel.org, WK Tsai On Fri, 2019-07-05 at 10:49 +0000, EJ Hsu wrote: > The change for my previous patch is as follows, and it works well on my local test. > > Thanks, > EJ > > diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c > index 982c3e8..b5f1e1e 100644 > --- a/drivers/usb/gadget/function/f_mass_storage.c > +++ b/drivers/usb/gadget/function/f_mass_storage.c > @@ -2306,7 +2306,6 @@ static void handle_exception(struct fsg_common *common) > enum fsg_state old_state; > struct fsg_lun *curlun; > unsigned int exception_req_tag; > - struct fsg_dev *fsg; > > /* > * Clear the existing signals. Anything but SIGUSR1 is converted > @@ -2413,15 +2412,9 @@ static void handle_exception(struct fsg_common *common) > break; > > case FSG_STATE_CONFIG_CHANGE: > - fsg = common->new_fsg; > - /* > - * Add a check here to double confirm if a disconnect event > - * occurs and common->new_fsg has been cleared. > - */ > - if (fsg) { > - do_set_interface(common, fsg); > + do_set_interface(common, common->new_fsg); > + if (common->new_fsg) > usb_composite_setup_continue(common->cdev); > - } > break; > > case FSG_STATE_DISCONNECT: > diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h > index 12687f7..fc13921 100644 > --- a/drivers/usb/gadget/function/storage_common.h > +++ b/drivers/usb/gadget/function/storage_common.h > @@ -160,8 +160,8 @@ enum fsg_state { > FSG_STATE_NORMAL, > FSG_STATE_ABORT_BULK_OUT, > FSG_STATE_PROTOCOL_RESET, > - FSG_STATE_CONFIG_CHANGE, > FSG_STATE_DISCONNECT, > + FSG_STATE_CONFIG_CHANGE, > FSG_STATE_EXIT, > FSG_STATE_TERMINATED > }; Is this patch against some other patch ? Please send the whole thing so people don't have to go digging in archives to figure what the code looks like. The above by itself doesn't make sense and can't be reviewed. However, I have a strong suspicion that if you still need to test new_fsg before calling usb_composite_setup_continue(). Then you haven't fixed the bug that I describe. Cheers, Ben. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V3] usb: gadget: storage: Remove warning message 2019-07-05 12:34 ` Benjamin Herrenschmidt @ 2019-07-05 13:13 ` Benjamin Herrenschmidt 2019-07-05 18:28 ` Alan Stern 0 siblings, 1 reply; 16+ messages in thread From: Benjamin Herrenschmidt @ 2019-07-05 13:13 UTC (permalink / raw) To: EJ Hsu, Alan Stern Cc: Thinh Nguyen, balbi@kernel.org, linux-usb@vger.kernel.org, WK Tsai (following our conversation) Here's a completely untested alternative patch (it replaces my previous one) that fixes it a bit differently. This time it should handle the case of a disconnect happening before we have dequeued a config change. This assumes that it's correct to never call usb_composite_setup_continue() if an fsg_disable() happens after a fsg_set_alt() and before we have processed the latter. I will try to test it tomorrow if time permits, otherwise some time next week: --- [PATCH] usb: gadget: mass_storage: Fix races between fsg_disable and fsg_set_alt If fsg_disable() and fsg_set_alt() are called too closely to each other (for example due to a quick reset/reconnect), what can happen is that fsg_set_alt sets common->new_fsg from an interrupt while handle_exception is trying to process the config change caused by fsg_disable(): fsg_disable() ... handle_exception() sets state back to FSG_STATE_NORMAL hasn't yet called do_set_interface() or is inside it. ---> interrupt fsg_set_alt sets common->new_fsg queues a new FSG_STATE_CONFIG_CHANGE <--- Now, the first handle_exception can "see" the updated new_fsg, treats it as if it was a fsg_set_alt() response, call usb_composite_setup_continue() etc... But then, the thread sees the second FSG_STATE_CONFIG_CHANGE, and goes back down the same path, wipes and reattaches a now active fsg, and .. calls usb_composite_setup_continue() which at this point is wrong. Not only we get a backtrace, but I suspect the second set_interface wrecks some state causing the host to get upset in my case. This fixes it by replacing "new_fsg" by a "state argument" (same principle) which is set in the same lock section as the state update, and retrieved similarly. That way, there is never any discrepancy between the dequeued state and the observed value of it. We keep the ability to have the latest reconfig operation take precedence, but we guarantee that once "dequeued" the argument (new_fsg) will not be clobbered by any new event. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- drivers/usb/gadget/function/f_mass_storage.c | 26 ++++++++++++-------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 043f97ad8f22..2ef029413b01 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -261,7 +261,7 @@ struct fsg_common; struct fsg_common { struct usb_gadget *gadget; struct usb_composite_dev *cdev; - struct fsg_dev *fsg, *new_fsg; + struct fsg_dev *fsg; wait_queue_head_t io_wait; wait_queue_head_t fsg_wait; @@ -290,6 +290,7 @@ struct fsg_common { unsigned int bulk_out_maxpacket; enum fsg_state state; /* For exception handling */ unsigned int exception_req_tag; + void *exception_arg; enum data_direction data_dir; u32 data_size; @@ -391,7 +392,8 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) /* These routines may be called in process context or in_irq */ -static void raise_exception(struct fsg_common *common, enum fsg_state new_state) +static void __raise_exception(struct fsg_common *common, enum fsg_state new_state, + void *arg) { unsigned long flags; @@ -404,6 +406,7 @@ static void raise_exception(struct fsg_common *common, enum fsg_state new_state) if (common->state <= new_state) { common->exception_req_tag = common->ep0_req_tag; common->state = new_state; + common->exception_arg = arg; if (common->thread_task) send_sig_info(SIGUSR1, SEND_SIG_PRIV, common->thread_task); @@ -411,6 +414,10 @@ static void raise_exception(struct fsg_common *common, enum fsg_state new_state) spin_unlock_irqrestore(&common->lock, flags); } +static void raise_exception(struct fsg_common *common, enum fsg_state new_state) +{ + __raise_exception(common, new_state, NULL); +} /*-------------------------------------------------------------------------*/ @@ -2285,16 +2292,14 @@ static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg) static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct fsg_dev *fsg = fsg_from_func(f); - fsg->common->new_fsg = fsg; - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); + __raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE, fsg); return USB_GADGET_DELAYED_STATUS; } static void fsg_disable(struct usb_function *f) { struct fsg_dev *fsg = fsg_from_func(f); - fsg->common->new_fsg = NULL; - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); + __raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE, NULL); } @@ -2307,6 +2312,7 @@ static void handle_exception(struct fsg_common *common) enum fsg_state old_state; struct fsg_lun *curlun; unsigned int exception_req_tag; + struct fsg_dev *new_fsg; /* * Clear the existing signals. Anything but SIGUSR1 is converted @@ -2360,6 +2366,7 @@ static void handle_exception(struct fsg_common *common) common->next_buffhd_to_fill = &common->buffhds[0]; common->next_buffhd_to_drain = &common->buffhds[0]; exception_req_tag = common->exception_req_tag; + new_fsg = common->exception_arg; old_state = common->state; common->state = FSG_STATE_NORMAL; @@ -2413,8 +2420,8 @@ static void handle_exception(struct fsg_common *common) break; case FSG_STATE_CONFIG_CHANGE: - do_set_interface(common, common->new_fsg); - if (common->new_fsg) + do_set_interface(common, new_fsg); + if (new_fsg) usb_composite_setup_continue(common->cdev); break; @@ -2989,8 +2996,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) DBG(fsg, "unbind\n"); if (fsg->common->fsg == fsg) { - fsg->common->new_fsg = NULL; - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); + __raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE, NULL); /* FIXME: make interruptible or killable somehow? */ wait_event(common->fsg_wait, common->fsg != fsg); } ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH V3] usb: gadget: storage: Remove warning message 2019-07-05 13:13 ` Benjamin Herrenschmidt @ 2019-07-05 18:28 ` Alan Stern 2019-07-05 22:11 ` Benjamin Herrenschmidt 0 siblings, 1 reply; 16+ messages in thread From: Alan Stern @ 2019-07-05 18:28 UTC (permalink / raw) To: Benjamin Herrenschmidt Cc: EJ Hsu, Thinh Nguyen, balbi@kernel.org, linux-usb@vger.kernel.org, WK Tsai On Fri, 5 Jul 2019, Benjamin Herrenschmidt wrote: > (following our conversation) > > Here's a completely untested alternative patch (it replaces my previous > one) that fixes it a bit differently. > > This time it should handle the case of a disconnect happening > before we have dequeued a config change. > > This assumes that it's correct to never call > usb_composite_setup_continue() if an fsg_disable() happens after a > fsg_set_alt() and before we have processed the latter. That should be handled okay. If it isn't, the composite core needs to be fixed. > I will try to test it tomorrow if time permits, otherwise some time > next week: > --- > > [PATCH] usb: gadget: mass_storage: Fix races between fsg_disable and fsg_set_alt > > If fsg_disable() and fsg_set_alt() are called too closely to each > other (for example due to a quick reset/reconnect), what can happen > is that fsg_set_alt sets common->new_fsg from an interrupt while > handle_exception is trying to process the config change caused by > fsg_disable(): > > fsg_disable() > ... > handle_exception() > sets state back to FSG_STATE_NORMAL > hasn't yet called do_set_interface() > or is inside it. > > ---> interrupt > fsg_set_alt > sets common->new_fsg > queues a new FSG_STATE_CONFIG_CHANGE > <--- > > Now, the first handle_exception can "see" the updated > new_fsg, treats it as if it was a fsg_set_alt() response, > call usb_composite_setup_continue() etc... > > But then, the thread sees the second FSG_STATE_CONFIG_CHANGE, > and goes back down the same path, wipes and reattaches a now > active fsg, and .. calls usb_composite_setup_continue() which > at this point is wrong. > > Not only we get a backtrace, but I suspect the second set_interface > wrecks some state causing the host to get upset in my case. > > This fixes it by replacing "new_fsg" by a "state argument" (same > principle) which is set in the same lock section as the state > update, and retrieved similarly. > > That way, there is never any discrepancy between the dequeued > state and the observed value of it. We keep the ability to have > the latest reconfig operation take precedence, but we guarantee > that once "dequeued" the argument (new_fsg) will not be clobbered > by any new event. > > Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Yes, this looks just right. If I had thought about this a little more deeply earlier on, I would have come up with a patch very much like this. My only comments are cosmetic. > --- > drivers/usb/gadget/function/f_mass_storage.c | 26 ++++++++++++-------- > 1 file changed, 16 insertions(+), 10 deletions(-) > > diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c > index 043f97ad8f22..2ef029413b01 100644 > --- a/drivers/usb/gadget/function/f_mass_storage.c > +++ b/drivers/usb/gadget/function/f_mass_storage.c > @@ -2285,16 +2292,14 @@ static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg) > static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) > { > struct fsg_dev *fsg = fsg_from_func(f); While you're changing this, it would be nice to add the customary blank line here. > - fsg->common->new_fsg = fsg; > - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); > + __raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE, fsg); > return USB_GADGET_DELAYED_STATUS; > } > > static void fsg_disable(struct usb_function *f) > { > struct fsg_dev *fsg = fsg_from_func(f); And here. Otherwise: Acked-by: Alan Stern <stern@rowland.harvard.edu> Alan Stern ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V3] usb: gadget: storage: Remove warning message 2019-07-05 18:28 ` Alan Stern @ 2019-07-05 22:11 ` Benjamin Herrenschmidt 0 siblings, 0 replies; 16+ messages in thread From: Benjamin Herrenschmidt @ 2019-07-05 22:11 UTC (permalink / raw) To: Alan Stern Cc: EJ Hsu, Thinh Nguyen, balbi@kernel.org, linux-usb@vger.kernel.org, WK Tsai On Fri, 2019-07-05 at 14:28 -0400, Alan Stern wrote: > On Fri, 5 Jul 2019, Benjamin Herrenschmidt wrote: > > > (following our conversation) > > > > Here's a completely untested alternative patch (it replaces my previous > > one) that fixes it a bit differently. > > > > This time it should handle the case of a disconnect happening > > before we have dequeued a config change. > > > > This assumes that it's correct to never call > > usb_composite_setup_continue() if an fsg_disable() happens after a > > fsg_set_alt() and before we have processed the latter. > > That should be handled okay. If it isn't, the composite core needs to > be fixed. Ok. I'll have a quick look to make sure. .../... > Yes, this looks just right. If I had thought about this a little more > deeply earlier on, I would have come up with a patch very much like > this. Right, so as I grow more familiar with that code and its intent, I agree, I'm much happier with this. Hopefully it passes my tests. I'll tidy up as per your comments and repost properly if all goes well along with some other things I piled up. Cheers, Ben. > My only comments are cosmetic. > > > --- > > drivers/usb/gadget/function/f_mass_storage.c | 26 ++++++++++++-------- > > 1 file changed, 16 insertions(+), 10 deletions(-) > > > > diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c > > index 043f97ad8f22..2ef029413b01 100644 > > --- a/drivers/usb/gadget/function/f_mass_storage.c > > +++ b/drivers/usb/gadget/function/f_mass_storage.c > > > @@ -2285,16 +2292,14 @@ static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg) > > static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) > > { > > struct fsg_dev *fsg = fsg_from_func(f); > > While you're changing this, it would be nice to add the customary blank > line here. > > > - fsg->common->new_fsg = fsg; > > - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); > > + __raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE, fsg); > > return USB_GADGET_DELAYED_STATUS; > > } > > > > static void fsg_disable(struct usb_function *f) > > { > > struct fsg_dev *fsg = fsg_from_func(f); > > And here. Otherwise: > > Acked-by: Alan Stern <stern@rowland.harvard.edu> > > Alan Stern ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2019-07-05 22:12 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-05-10 11:02 [PATCH V3] usb: gadget: storage: Remove warning message EJ Hsu
2019-05-10 14:29 ` Alan Stern
2019-07-02 1:58 ` Thinh Nguyen
2019-07-02 14:10 ` Alan Stern
[not found] ` <CY4PR1201MB0037C93EC7F81A394008C4CCAAF80@CY4PR1201MB0037.namprd12.prod.outlook.com>
2019-07-02 18:06 ` Thinh Nguyen
2019-07-03 11:20 ` EJ Hsu
2019-07-04 8:39 ` EJ Hsu
2019-07-04 16:06 ` Alan Stern
2019-07-05 10:49 ` EJ Hsu
2019-07-05 12:28 ` Benjamin Herrenschmidt
2019-07-05 14:30 ` Alan Stern
2019-07-05 22:09 ` Benjamin Herrenschmidt
2019-07-05 12:34 ` Benjamin Herrenschmidt
2019-07-05 13:13 ` Benjamin Herrenschmidt
2019-07-05 18:28 ` Alan Stern
2019-07-05 22:11 ` Benjamin Herrenschmidt
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox