Hi Alan,

Felipe Balbi <felipe.ba...@linux.intel.com> writes:
> Hi,
>
> Alan Stern <st...@rowland.harvard.edu> writes:
>> On Sat, 3 Sep 2016, Felipe Balbi wrote:
>>
>>> Hi,
>>> 
>>> Alan Stern <st...@rowland.harvard.edu> writes:
>>> > On Fri, 2 Sep 2016, Felipe Balbi wrote:
>>> >
>>> >> 
>>> >> Hi,
>>> >> 
>>> >> Alan Stern <st...@rowland.harvard.edu> writes:
>>> >> 
>>> >> [...]
>>> >> 
>>> >> > No, that would be too late.  The barrier needs to go between the write 
>>> >> > to common->thead_wakeup_needed and the call to wake_up_process().  
>>> >> 
>>> >> alright, I tested this but it doesn't work. It still hangs :-(
>>> >
>>> > Okay, I was wrong.  But see my recent reply to Paul; maybe the 
>>> > smp_wmb() in wakeup_thread() needs to be smp_mb().
>>> 
>>> okay, this seems to be working so far:
>>> 
>>> modified   drivers/usb/gadget/function/f_mass_storage.c
>>> @@ -395,7 +395,7 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct 
>>> usb_ep *ep)
>>>  /* Caller must hold fsg->lock */
>>>  static void wakeup_thread(struct fsg_common *common)
>>>  {
>>> -   smp_wmb();      /* ensure the write of bh->state is complete */
>>> +   smp_mb();       /* ensure the write of bh->state is complete */
>>>     /* Tell the main thread that something has happened */
>>>     common->thread_wakeup_needed = 1;
>>>     if (common->thread_task)
>>> @@ -626,7 +626,7 @@ static int sleep_thread(struct fsg_common *common, bool 
>>> can_freeze)
>>>     }
>>>     __set_current_state(TASK_RUNNING);
>>>     common->thread_wakeup_needed = 0;
>>> -   smp_rmb();      /* ensure the latest bh->state is visible */
>>> +   smp_mb();       /* ensure the latest bh->state is visible */
>>>     return rc;
>>>  }
>>>  
>>> I'll keep it running over the weekend.
>>
>> Can you also check the question I mentioned earlier?  That is, if you
>> revert to the original code then when the thread hangs, what does the
>> call to received_cbw() in get_next_command() return?  Or does that
>> routine not get called at all because the preceding sleep_thread() is
>> the one that doesn't return?
>
> here are the last few calls
>
>> [   34.122210] ==> bulk_out_complete 484
>
> CBW received
>
>> [   34.122213] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>
> set thread_wakeup_needed to 1 and wakeup fsg_main_thread
>
>> [   34.122255] ==> fsg_main_thread 2587 -> get_next_command() -> 0
>
> get_next_command()
>
>> [   34.122328] ==> fsg_main_thread 2608 -> send_status -> 0
>
> CSW
>
>> [   34.122331] ==> get_next_command 2251 -> state != full
>
> now waiting for CBW:
>
>> [   34.122333] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>
> thread goes to sleep
>
>> [   34.122379] ==> bulk_in_complete 461
>
> We send data to host
>
>> [   34.122381] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.122383] ==> get_next_command 2251 -> state != full
>
> still waiting for CBW
>
>> [   34.122385] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>> [   34.122386] ==> bulk_in_complete 461
>
> send data to host
>
>> [   34.122388] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.122389] ==> get_next_command 2251 -> state != full
>
> still waiting for CBW
>
>> [   34.122391] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>> [   34.122468] ==> bulk_in_complete 461
>> [   34.122469] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.122470] ==> get_next_command 2251 -> state != full
>> [   34.122473] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>> [   34.122473] ==> bulk_in_complete 461
>> [   34.122474] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.122476] ==> get_next_command 2251 -> state != full
>> [   34.122479] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>> [   34.122556] ==> bulk_in_complete 461
>> [   34.122557] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.122559] ==> get_next_command 2251 -> state != full
>> [   34.122561] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>> [   34.122561] ==> bulk_in_complete 461
>> [   34.122563] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.122563] ==> get_next_command 2251 -> state != full
>> [   34.122565] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>> [   34.122647] ==> bulk_in_complete 461
>> [   34.122648] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.122650] ==> get_next_command 2251 -> state != full
>> [   34.122653] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>> [   34.122654] ==> bulk_in_complete 461
>> [   34.122655] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.122656] ==> get_next_command 2251 -> state != full
>> [   34.122658] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>> [   34.122716] ==> bulk_in_complete 461
>> [   34.122717] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>
> yada, yada, yada. All the other transfers. If you count all
> bulk_in_complete prints, you'll see there are 9 of them. 8x 16kiB +
> 13-byte CSW.
>
>> [   34.122719] ==> bulk_out_complete 484
>> [   34.122720] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>
> another CBW
>
>> [   34.122721] ==> fsg_main_thread 2587 -> get_next_command() -> 0
>> [   34.122802] ==> fsg_main_thread 2608 -> send_status -> 0
>> [   34.122805] ==> get_next_command 2251 -> state != full
>> [   34.122807] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>> [   34.122850] ==> bulk_in_complete 461
>> [   34.122851] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.122855] ==> get_next_command 2251 -> state != full
>> [   34.122856] ==> bulk_in_complete 461
>> [   34.122857] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.122858] ==> get_next_command 2251 -> state != full
>> [   34.122860] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>> [   34.122939] ==> bulk_in_complete 461
>> [   34.122940] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.122945] ==> bulk_in_complete 461
>> [   34.122947] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.122988] ==> get_next_command 2251 -> state != full
>> [   34.123008] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>> [   34.123055] ==> bulk_in_complete 461
>> [   34.123070] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.123073] ==> bulk_in_complete 461
>> [   34.123074] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.123105] ==> get_next_command 2251 -> state != full
>> [   34.123125] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>> [   34.123167] ==> bulk_in_complete 461
>> [   34.123169] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.123179] ==> bulk_in_complete 461
>> [   34.123181] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>> [   34.123185] ==> get_next_command 2251 -> state != full
>> [   34.123202] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>> [   34.123279] ==> bulk_in_complete 461
>> [   34.123280] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>
> Another block of 128kiB
>
>> [   34.123281] ==> bulk_out_complete 484
>
> received CBW. Now, bh->state is set to BUF_STATE_FULL, and ...
>
>> [   34.123283] ==> wakeup_thread 403: caller 
>> usb_gadget_giveback_request+0x7/0x10: thread_wakeup_needed = 1
>
> wakeup_thread() is called, however ...
>
>> [   34.123283] ==> get_next_command 2251 -> state != full
>
> get_next_command() still sees bh->state != BUF_STATE_FULL.
>
>> [   34.123286] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>> [   34.123289] ===> sleep_thread 634: caller fsg_main_thread+0xaa1/0xb00 
>> [usb_f_mass_storage]: going to sleep
>
> so it goes to sleep and never wakes up again.

one thing that caught my attention is that not all accesses to bh->state
are locked. Is that an oversight or is there a valid reason for that?

Considering that accessing bh->state would always guarantee a full
barrier (at least on x86, per Peter Z), I'm wondering if we should make
every access to bh->state locked. Or, perhaps, they should all be
preceeded with a call to smp_mb() in order to guarantee that previous
writes to bh->state are seen by current CPU?

I can test that out, but I'll wait for a proper patch from you as I
cannot predict all memory ordering problems that could arise from
current code. Still, f_mass_storage.c looks really odd :-s

cheers

-- 
balbi

Attachment: signature.asc
Description: PGP signature

Reply via email to