RE: [PATCH v2 1/4] usb: renesas_usbhs: fix spinlock suspected in a gadget complete function

2015-03-16 Thread yoshihiro shimoda
Hi,

 Hi,
 
 On Fri, Mar 13, 2015 at 01:14:01AM +, yoshihiro shimoda wrote:
 diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c 
 b/drivers/usb/renesas_usbhs/mod_gadget.c
 index e0384af77e56..e9d75d85be59 100644
 --- a/drivers/usb/renesas_usbhs/mod_gadget.c
 +++ b/drivers/usb/renesas_usbhs/mod_gadget.c
 @@ -119,7 +119,7 @@ struct usbhsg_recip_handle {
  /*
   *   queue push/pop
   */
 -static void usbhsg_queue_pop(struct usbhsg_uep *uep,
 +static void __usbhsg_queue_pop(struct usbhsg_uep *uep,
struct usbhsg_request *ureq,
int status)
  {
 @@ -133,6 +133,15 @@ static void usbhsg_queue_pop(struct usbhsg_uep 
 *uep,
   usb_gadget_giveback_request(uep-ep, ureq-req);
  }

 +static void usbhsg_queue_pop(struct usbhsg_uep *uep,
 +  struct usbhsg_request *ureq,
 +  int status)
 +{
 + usbhs_lock(priv, flags);
 + __usbhsg_queue_pop(uep, ureq, status);
 + usbhs_unlock(priv, flags);
 +}
 +
  static void usbhsg_queue_done(struct usbhs_priv *priv, struct 
 usbhs_pkt *pkt)
  {
   struct usbhs_pipe *pipe = pkt-pipe;


 then, for cases where lock is already held you call 
 __usbhsg_queue_pop()
 and for all other cases, call usbhsg_queue_pop().
   
Thank you for the suggestion. However, we cannot use this
usbhsg_queue_pop() because a gadget driver might call usb_ep_queue()
in the complete function and this driver calls usbhs_lock() in the
usb_ep_queue().
  
   right, in that case just call __usbhs_queue_pop() directly.
 
  Yes. So, my understanding is that this driver always calls 
  __usbhs_queue_pop()
  because this driver cannot know that a gadget driver calls usb_ep_queue() 
  or not
  in the complete function.
 
 but you don't need to know that. All you have to do is spin_unlock()
 before calling usb_gadget_giveback_request(), look at
 drivers/usb/dwc3/gadget.c::dwc3_gadget_giveback()

Thank you for the suggestion. I understood it.

Perhaps my explanation was bad, but this issue was caused by the
following conditions:
 - I use the renesas_usbhs driver as udc.
 - I use an old usb-dmac driver that the callback runs on a kthread.
 - I use the ncm driver. In this environment, the ncm driver might
cause a spinlock suspected.
   
As an old solution, I fixed the renesas_usbhs driver by this patch.
However, if I use a new usb-dmac driver that the callback runs on a
tasklet, I don't need this patch. (This is a new solution.)
  
   then differentiate based on some revision register or something like
   that ?
 
  Sorry for the lack information. I am submitting this usb-dmac driver that
  the callback runs on a tasklet now. This means that the driver is not
  merged yet. So, I think that we don't need to differentiate.
 
 But as soon as your driver gets merged, you will need to differentiate,
 right ?

Right. So, I will submit v3 patch soon.

Best regards,
Yoshihiro Shimoda

 --
 balbi
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/4] usb: renesas_usbhs: fix spinlock suspected in a gadget complete function

2015-03-13 Thread Felipe Balbi
Hi,

On Fri, Mar 13, 2015 at 01:14:01AM +, yoshihiro shimoda wrote:
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c 
b/drivers/usb/renesas_usbhs/mod_gadget.c
index e0384af77e56..e9d75d85be59 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -119,7 +119,7 @@ struct usbhsg_recip_handle {
 /*
  * queue push/pop
  */
-static void usbhsg_queue_pop(struct usbhsg_uep *uep,
+static void __usbhsg_queue_pop(struct usbhsg_uep *uep,
 struct usbhsg_request *ureq,
 int status)
 {
@@ -133,6 +133,15 @@ static void usbhsg_queue_pop(struct usbhsg_uep 
*uep,
usb_gadget_giveback_request(uep-ep, ureq-req);
 }
   
+static void usbhsg_queue_pop(struct usbhsg_uep *uep,
+struct usbhsg_request *ureq,
+int status)
+{
+   usbhs_lock(priv, flags);
+   __usbhsg_queue_pop(uep, ureq, status);
+   usbhs_unlock(priv, flags);
+}
+
 static void usbhsg_queue_done(struct usbhs_priv *priv, struct 
usbhs_pkt *pkt)
 {
struct usbhs_pipe *pipe = pkt-pipe;
   
   
then, for cases where lock is already held you call __usbhsg_queue_pop()
and for all other cases, call usbhsg_queue_pop().
  
   Thank you for the suggestion. However, we cannot use this
   usbhsg_queue_pop() because a gadget driver might call usb_ep_queue()
   in the complete function and this driver calls usbhs_lock() in the
   usb_ep_queue().
  
  right, in that case just call __usbhs_queue_pop() directly.
 
 Yes. So, my understanding is that this driver always calls __usbhs_queue_pop()
 because this driver cannot know that a gadget driver calls usb_ep_queue() or 
 not
 in the complete function.

but you don't need to know that. All you have to do is spin_unlock()
before calling usb_gadget_giveback_request(), look at
drivers/usb/dwc3/gadget.c::dwc3_gadget_giveback()

   Perhaps my explanation was bad, but this issue was caused by the
   following conditions:
- I use the renesas_usbhs driver as udc.
- I use an old usb-dmac driver that the callback runs on a kthread.
- I use the ncm driver. In this environment, the ncm driver might
 cause a spinlock suspected.
  
   As an old solution, I fixed the renesas_usbhs driver by this patch.
   However, if I use a new usb-dmac driver that the callback runs on a
   tasklet, I don't need this patch. (This is a new solution.)
  
  then differentiate based on some revision register or something like
  that ?
 
 Sorry for the lack information. I am submitting this usb-dmac driver that
 the callback runs on a tasklet now. This means that the driver is not
 merged yet. So, I think that we don't need to differentiate.

But as soon as your driver gets merged, you will need to differentiate,
right ?

-- 
balbi


signature.asc
Description: Digital signature


Re: [PATCH v2 1/4] usb: renesas_usbhs: fix spinlock suspected in a gadget complete function

2015-03-12 Thread Felipe Balbi
Hi,

On Thu, Mar 12, 2015 at 05:40:56AM +, yoshihiro shimoda wrote:
 Hi,
 
  On Thu, Mar 12, 2015 at 04:33:41AM +, yoshihiro shimoda wrote:
   Hi Geert-san again,
  
Hi Geert-san,
   
Thank you for the reply again!
   
 Hi Shimoda-san,

 On Mon, Feb 16, 2015 at 2:52 AM, Yoshihiro Shimoda
 yoshihiro.shimoda...@renesas.com wrote:
  According to the gadget.h, a complete function will always be 
  called
  with interrupts disabled. However, sometimes usbhsg_queue_pop() 
  function
  is called with interrupts enabled. So, this function should calls
  local_irq_save() before this calls the 
  usb_gadget_giveback_request().
  Otherwise, there is possible to cause a spinlock suspected in a 
  gadget
  complete function.

 I still feel uneasy about adding the call to local_irq_save(), as the 
 need for
 this is usually an indicator of another locking problem.
   
I also think that I would like to avoid using local_irq_save().
But, I have no idea to resolve this issue for now.
  
   After I modified usb-dmac driver to use a tasklet instead of a kthread,
   this issue disappeared.
  
   My understanding is the followings:
   - According to the backtrace below, during usbhsf_dma_complete() was 
   running,
a softirq happened. After ncm_tx_tasklet() was called, the issue 
   happened.
   http://thread.gmane.org/gmane.linux.usb.general/122023/focus=43729
  
   - This means that usbhsf_dma_complete() ran on a kthread. So, ncm driver 
   is able
 to do the ncm_tx_tasklet().
  
   - After the current usb-dmac driver, since usbhsf_dma_complete() runs on 
   a tasklet,
 ncm driver is not able to do the ncm_tx_tasklet during 
   usbhsf_dma_complete() was running.
  
  
   So, I would like to recall this patch and I will resubmit this patch 
   series as v3.
  
  try something like below:
  
  diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c 
  b/drivers/usb/renesas_usbhs/mod_gadget.c
  index e0384af77e56..e9d75d85be59 100644
  --- a/drivers/usb/renesas_usbhs/mod_gadget.c
  +++ b/drivers/usb/renesas_usbhs/mod_gadget.c
  @@ -119,7 +119,7 @@ struct usbhsg_recip_handle {
   /*
* queue push/pop
*/
  -static void usbhsg_queue_pop(struct usbhsg_uep *uep,
  +static void __usbhsg_queue_pop(struct usbhsg_uep *uep,
   struct usbhsg_request *ureq,
   int status)
   {
  @@ -133,6 +133,15 @@ static void usbhsg_queue_pop(struct usbhsg_uep *uep,
  usb_gadget_giveback_request(uep-ep, ureq-req);
   }
  
  +static void usbhsg_queue_pop(struct usbhsg_uep *uep,
  +struct usbhsg_request *ureq,
  +int status)
  +{
  +   usbhs_lock(priv, flags);
  +   __usbhsg_queue_pop(uep, ureq, status);
  +   usbhs_unlock(priv, flags);
  +}
  +
   static void usbhsg_queue_done(struct usbhs_priv *priv, struct usbhs_pkt 
  *pkt)
   {
  struct usbhs_pipe *pipe = pkt-pipe;
  
  
  then, for cases where lock is already held you call __usbhsg_queue_pop()
  and for all other cases, call usbhsg_queue_pop().
 
 Thank you for the suggestion. However, we cannot use this
 usbhsg_queue_pop() because a gadget driver might call usb_ep_queue()
 in the complete function and this driver calls usbhs_lock() in the
 usb_ep_queue().

right, in that case just call __usbhs_queue_pop() directly.

 Perhaps my explanation was bad, but this issue was caused by the
 following conditions:
  - I use the renesas_usbhs driver as udc.
  - I use an old usb-dmac driver that the callback runs on a kthread.
  - I use the ncm driver. In this environment, the ncm driver might
   cause a spinlock suspected.
 
 As an old solution, I fixed the renesas_usbhs driver by this patch.
 However, if I use a new usb-dmac driver that the callback runs on a
 tasklet, I don't need this patch. (This is a new solution.)

then differentiate based on some revision register or something like
that ?

-- 
balbi


signature.asc
Description: Digital signature


RE: [PATCH v2 1/4] usb: renesas_usbhs: fix spinlock suspected in a gadget complete function

2015-03-12 Thread yoshihiro shimoda
Hi,

 Hi,
 
 On Thu, Mar 12, 2015 at 05:40:56AM +, yoshihiro shimoda wrote:
  Hi,
 
 snip 
  
   try something like below:
  
   diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c 
   b/drivers/usb/renesas_usbhs/mod_gadget.c
   index e0384af77e56..e9d75d85be59 100644
   --- a/drivers/usb/renesas_usbhs/mod_gadget.c
   +++ b/drivers/usb/renesas_usbhs/mod_gadget.c
   @@ -119,7 +119,7 @@ struct usbhsg_recip_handle {
/*
 *   queue push/pop
 */
   -static void usbhsg_queue_pop(struct usbhsg_uep *uep,
   +static void __usbhsg_queue_pop(struct usbhsg_uep *uep,
  struct usbhsg_request *ureq,
  int status)
{
   @@ -133,6 +133,15 @@ static void usbhsg_queue_pop(struct usbhsg_uep *uep,
 usb_gadget_giveback_request(uep-ep, ureq-req);
}
  
   +static void usbhsg_queue_pop(struct usbhsg_uep *uep,
   +  struct usbhsg_request *ureq,
   +  int status)
   +{
   + usbhs_lock(priv, flags);
   + __usbhsg_queue_pop(uep, ureq, status);
   + usbhs_unlock(priv, flags);
   +}
   +
static void usbhsg_queue_done(struct usbhs_priv *priv, struct usbhs_pkt 
   *pkt)
{
 struct usbhs_pipe *pipe = pkt-pipe;
  
  
   then, for cases where lock is already held you call __usbhsg_queue_pop()
   and for all other cases, call usbhsg_queue_pop().
 
  Thank you for the suggestion. However, we cannot use this
  usbhsg_queue_pop() because a gadget driver might call usb_ep_queue()
  in the complete function and this driver calls usbhs_lock() in the
  usb_ep_queue().
 
 right, in that case just call __usbhs_queue_pop() directly.

Yes. So, my understanding is that this driver always calls __usbhs_queue_pop()
because this driver cannot know that a gadget driver calls usb_ep_queue() or not
in the complete function.

  Perhaps my explanation was bad, but this issue was caused by the
  following conditions:
   - I use the renesas_usbhs driver as udc.
   - I use an old usb-dmac driver that the callback runs on a kthread.
   - I use the ncm driver. In this environment, the ncm driver might
  cause a spinlock suspected.
 
  As an old solution, I fixed the renesas_usbhs driver by this patch.
  However, if I use a new usb-dmac driver that the callback runs on a
  tasklet, I don't need this patch. (This is a new solution.)
 
 then differentiate based on some revision register or something like
 that ?

Sorry for the lack information. I am submitting this usb-dmac driver that
the callback runs on a tasklet now. This means that the driver is not
merged yet. So, I think that we don't need to differentiate.

Best regards,
Yoshihiro Shimoda

 --
 balbi
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH v2 1/4] usb: renesas_usbhs: fix spinlock suspected in a gadget complete function

2015-03-11 Thread yoshihiro shimoda
Hi Geert-san again,

 Hi Geert-san,
 
 Thank you for the reply again!
 
  Hi Shimoda-san,
 
  On Mon, Feb 16, 2015 at 2:52 AM, Yoshihiro Shimoda
  yoshihiro.shimoda...@renesas.com wrote:
   According to the gadget.h, a complete function will always be called
   with interrupts disabled. However, sometimes usbhsg_queue_pop() function
   is called with interrupts enabled. So, this function should calls
   local_irq_save() before this calls the usb_gadget_giveback_request().
   Otherwise, there is possible to cause a spinlock suspected in a gadget
   complete function.
 
  I still feel uneasy about adding the call to local_irq_save(), as the need 
  for
  this is usually an indicator of another locking problem.
 
 I also think that I would like to avoid using local_irq_save().
 But, I have no idea to resolve this issue for now.

After I modified usb-dmac driver to use a tasklet instead of a kthread,
this issue disappeared.

My understanding is the followings:
- According to the backtrace below, during usbhsf_dma_complete() was running,
 a softirq happened. After ncm_tx_tasklet() was called, the issue happened.
http://thread.gmane.org/gmane.linux.usb.general/122023/focus=43729

- This means that usbhsf_dma_complete() ran on a kthread. So, ncm driver is able
  to do the ncm_tx_tasklet().

- After the current usb-dmac driver, since usbhsf_dma_complete() runs on a 
tasklet,
  ncm driver is not able to do the ncm_tx_tasklet during usbhsf_dma_complete() 
was running.


So, I would like to recall this patch and I will resubmit this patch series as 
v3.

Best regards,
Yoshihiro Shimoda

N�r��yb�X��ǧv�^�)޺{.n�+{��^n�r���z���h����G���h�(�階�ݢj���m��z�ޖ���f���h���~�m�

Re: [PATCH v2 1/4] usb: renesas_usbhs: fix spinlock suspected in a gadget complete function

2015-03-11 Thread Felipe Balbi
Hi,

On Thu, Mar 12, 2015 at 04:33:41AM +, yoshihiro shimoda wrote:
 Hi Geert-san again,
 
  Hi Geert-san,
  
  Thank you for the reply again!
  
   Hi Shimoda-san,
  
   On Mon, Feb 16, 2015 at 2:52 AM, Yoshihiro Shimoda
   yoshihiro.shimoda...@renesas.com wrote:
According to the gadget.h, a complete function will always be called
with interrupts disabled. However, sometimes usbhsg_queue_pop() function
is called with interrupts enabled. So, this function should calls
local_irq_save() before this calls the usb_gadget_giveback_request().
Otherwise, there is possible to cause a spinlock suspected in a gadget
complete function.
  
   I still feel uneasy about adding the call to local_irq_save(), as the 
   need for
   this is usually an indicator of another locking problem.
  
  I also think that I would like to avoid using local_irq_save().
  But, I have no idea to resolve this issue for now.
 
 After I modified usb-dmac driver to use a tasklet instead of a kthread,
 this issue disappeared.
 
 My understanding is the followings:
 - According to the backtrace below, during usbhsf_dma_complete() was running,
  a softirq happened. After ncm_tx_tasklet() was called, the issue happened.
 http://thread.gmane.org/gmane.linux.usb.general/122023/focus=43729
 
 - This means that usbhsf_dma_complete() ran on a kthread. So, ncm driver is 
 able
   to do the ncm_tx_tasklet().
 
 - After the current usb-dmac driver, since usbhsf_dma_complete() runs on a 
 tasklet,
   ncm driver is not able to do the ncm_tx_tasklet during 
 usbhsf_dma_complete() was running.
 
 
 So, I would like to recall this patch and I will resubmit this patch series 
 as v3.

try something like below:

diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c 
b/drivers/usb/renesas_usbhs/mod_gadget.c
index e0384af77e56..e9d75d85be59 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -119,7 +119,7 @@ struct usbhsg_recip_handle {
 /*
  * queue push/pop
  */
-static void usbhsg_queue_pop(struct usbhsg_uep *uep,
+static void __usbhsg_queue_pop(struct usbhsg_uep *uep,
 struct usbhsg_request *ureq,
 int status)
 {
@@ -133,6 +133,15 @@ static void usbhsg_queue_pop(struct usbhsg_uep *uep,
usb_gadget_giveback_request(uep-ep, ureq-req);
 }
 
+static void usbhsg_queue_pop(struct usbhsg_uep *uep,
+struct usbhsg_request *ureq,
+int status)
+{
+   usbhs_lock(priv, flags);
+   __usbhsg_queue_pop(uep, ureq, status);
+   usbhs_unlock(priv, flags);
+}
+
 static void usbhsg_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt)
 {
struct usbhs_pipe *pipe = pkt-pipe;


then, for cases where lock is already held you call __usbhsg_queue_pop()
and for all other cases, call usbhsg_queue_pop().

-- 
balbi


signature.asc
Description: Digital signature


RE: [PATCH v2 1/4] usb: renesas_usbhs: fix spinlock suspected in a gadget complete function

2015-03-11 Thread yoshihiro shimoda
Hi,

 On Thu, Mar 12, 2015 at 04:33:41AM +, yoshihiro shimoda wrote:
  Hi Geert-san again,
 
   Hi Geert-san,
  
   Thank you for the reply again!
  
Hi Shimoda-san,
   
On Mon, Feb 16, 2015 at 2:52 AM, Yoshihiro Shimoda
yoshihiro.shimoda...@renesas.com wrote:
 According to the gadget.h, a complete function will always be called
 with interrupts disabled. However, sometimes usbhsg_queue_pop() 
 function
 is called with interrupts enabled. So, this function should calls
 local_irq_save() before this calls the usb_gadget_giveback_request().
 Otherwise, there is possible to cause a spinlock suspected in a gadget
 complete function.
   
I still feel uneasy about adding the call to local_irq_save(), as the 
need for
this is usually an indicator of another locking problem.
  
   I also think that I would like to avoid using local_irq_save().
   But, I have no idea to resolve this issue for now.
 
  After I modified usb-dmac driver to use a tasklet instead of a kthread,
  this issue disappeared.
 
  My understanding is the followings:
  - According to the backtrace below, during usbhsf_dma_complete() was 
  running,
   a softirq happened. After ncm_tx_tasklet() was called, the issue happened.
  http://thread.gmane.org/gmane.linux.usb.general/122023/focus=43729
 
  - This means that usbhsf_dma_complete() ran on a kthread. So, ncm driver is 
  able
to do the ncm_tx_tasklet().
 
  - After the current usb-dmac driver, since usbhsf_dma_complete() runs on a 
  tasklet,
ncm driver is not able to do the ncm_tx_tasklet during 
  usbhsf_dma_complete() was running.
 
 
  So, I would like to recall this patch and I will resubmit this patch series 
  as v3.
 
 try something like below:
 
 diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c 
 b/drivers/usb/renesas_usbhs/mod_gadget.c
 index e0384af77e56..e9d75d85be59 100644
 --- a/drivers/usb/renesas_usbhs/mod_gadget.c
 +++ b/drivers/usb/renesas_usbhs/mod_gadget.c
 @@ -119,7 +119,7 @@ struct usbhsg_recip_handle {
  /*
   *   queue push/pop
   */
 -static void usbhsg_queue_pop(struct usbhsg_uep *uep,
 +static void __usbhsg_queue_pop(struct usbhsg_uep *uep,
struct usbhsg_request *ureq,
int status)
  {
 @@ -133,6 +133,15 @@ static void usbhsg_queue_pop(struct usbhsg_uep *uep,
   usb_gadget_giveback_request(uep-ep, ureq-req);
  }
 
 +static void usbhsg_queue_pop(struct usbhsg_uep *uep,
 +  struct usbhsg_request *ureq,
 +  int status)
 +{
 + usbhs_lock(priv, flags);
 + __usbhsg_queue_pop(uep, ureq, status);
 + usbhs_unlock(priv, flags);
 +}
 +
  static void usbhsg_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt)
  {
   struct usbhs_pipe *pipe = pkt-pipe;
 
 
 then, for cases where lock is already held you call __usbhsg_queue_pop()
 and for all other cases, call usbhsg_queue_pop().

Thank you for the suggestion. However, we cannot use this usbhsg_queue_pop() 
because
a gadget driver might call usb_ep_queue() in the complete function and
this driver calls usbhs_lock() in the usb_ep_queue().

Perhaps my explanation was bad, but this issue was caused by the following 
conditions:
 - I use the renesas_usbhs driver as udc.
 - I use an old usb-dmac driver that the callback runs on a kthread.
 - I use the ncm driver. In this environment, the ncm driver might cause a 
spinlock suspected.

As an old solution, I fixed the renesas_usbhs driver by this patch.
However, if I use a new usb-dmac driver that the callback runs on a tasklet,
I don't need this patch. (This is a new solution.)

Best regards,
Yoshihiro Shimoda

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH v2 1/4] usb: renesas_usbhs: fix spinlock suspected in a gadget complete function

2015-02-16 Thread yoshihiro shimoda
Hi Geert-san,

Thank you for the reply again!

 Hi Shimoda-san,
 
 On Mon, Feb 16, 2015 at 2:52 AM, Yoshihiro Shimoda
 yoshihiro.shimoda...@renesas.com wrote:
  According to the gadget.h, a complete function will always be called
  with interrupts disabled. However, sometimes usbhsg_queue_pop() function
  is called with interrupts enabled. So, this function should calls
  local_irq_save() before this calls the usb_gadget_giveback_request().
  Otherwise, there is possible to cause a spinlock suspected in a gadget
  complete function.
 
 I still feel uneasy about adding the call to local_irq_save(), as the need for
 this is usually an indicator of another locking problem.

I also think that I would like to avoid using local_irq_save().
But, I have no idea to resolve this issue for now.

 Unfortunately I know next to nothing about the USB gadget subsystem, so some
 help from the USB gadget experts would be appreciated.
 
 I had a look at other drivers, and it seems most drivers actually release
 and reacquire a spinlock around the call to usb_gadget_giveback_request(),
 i.e. they do:
 
 spin_unlock(...);
 usb_gadget_giveback_request(...);
 spin_lock();
 
 This means they had already acquired the spinlock (and disabled interrupts!)
 before, which looks much healthier to me.
 
 There's only one driver that uses local_irq_save() (pxa27x_udc).

I had a look at the musb driver. It uses a dmaengine driver.
And, in the callback routine of the musb driver, it calls spin_lock_irqsave() 
at first.

cppi41_dma_callback
-- spin_lock_irqsave(musb-lock, flags);
-- cppi41_trans_done
 -- musb_dma_completion
  -- musb_g_tx or musb_g_rx
   -- musb_g_giveback
-- spin_unlock(musb-lock);   # This means unlocked the spin, but 
disabled interrupts.
-- usb_gadget_giveback_request
-- spin_lock(musb-lock);
  snip 
-- spin_unlock_irqrestore(musb-lock, flags);

So, about disabled interrupts before usb_gadget_giveback_request(),
it is similar with this patch.

Best regards,
Yoshihiro Shimoda

N�r��yb�X��ǧv�^�)޺{.n�+{��^n�r���z���h����G���h�(�階�ݢj���m��z�ޖ���f���h���~�m�

Re: [PATCH v2 1/4] usb: renesas_usbhs: fix spinlock suspected in a gadget complete function

2015-02-16 Thread Geert Uytterhoeven
Hi Shimoda-san,

On Mon, Feb 16, 2015 at 2:52 AM, Yoshihiro Shimoda
yoshihiro.shimoda...@renesas.com wrote:
 According to the gadget.h, a complete function will always be called
 with interrupts disabled. However, sometimes usbhsg_queue_pop() function
 is called with interrupts enabled. So, this function should calls
 local_irq_save() before this calls the usb_gadget_giveback_request().
 Otherwise, there is possible to cause a spinlock suspected in a gadget
 complete function.

I still feel uneasy about adding the call to local_irq_save(), as the need for
this is usually an indicator of another locking problem.

Unfortunately I know next to nothing about the USB gadget subsystem, so some
help from the USB gadget experts would be appreciated.

I had a look at other drivers, and it seems most drivers actually release
and reacquire a spinlock around the call to usb_gadget_giveback_request(),
i.e. they do:

spin_unlock(...);
usb_gadget_giveback_request(...);
spin_lock();

This means they had already acquired the spinlock (and disabled interrupts!)
before, which looks much healthier to me.

There's only one driver that uses local_irq_save() (pxa27x_udc).

 Signed-off-by: Yoshihiro Shimoda yoshihiro.shimoda...@renesas.com
 ---
  drivers/usb/renesas_usbhs/mod_gadget.c |   11 +++
  1 file changed, 11 insertions(+)

 diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c 
 b/drivers/usb/renesas_usbhs/mod_gadget.c
 index e0384af..104bddf 100644
 --- a/drivers/usb/renesas_usbhs/mod_gadget.c
 +++ b/drivers/usb/renesas_usbhs/mod_gadget.c
 @@ -126,11 +126,22 @@ static void usbhsg_queue_pop(struct usbhsg_uep *uep,
 struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
 struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
 struct device *dev = usbhsg_gpriv_to_dev(gpriv);
 +   unsigned long flags;

 dev_dbg(dev, pipe %d : queue pop\n, usbhs_pipe_number(pipe));

 ureq-req.status = status;
 +   /*
 +* According to the gadget.h, a complete function will always be
 +* called with interrupts disabled. However, sometimes this function
 +* is called with interrupts enabled. (e.g. complete a DMAC transfer 
 or
 +* write data and done is set immediately when PIO.) So, this function
 +* should calls local_irq_save() before this calls the
 +* usb_gadget_giveback_request().
 +*/
 +   local_irq_save(flags);
 usb_gadget_giveback_request(uep-ep, ureq-req);
 +   local_irq_restore(flags);
  }

  static void usbhsg_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt)

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say programmer or something like that.
-- Linus Torvalds
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 1/4] usb: renesas_usbhs: fix spinlock suspected in a gadget complete function

2015-02-15 Thread Yoshihiro Shimoda
According to the gadget.h, a complete function will always be called
with interrupts disabled. However, sometimes usbhsg_queue_pop() function
is called with interrupts enabled. So, this function should calls
local_irq_save() before this calls the usb_gadget_giveback_request().
Otherwise, there is possible to cause a spinlock suspected in a gadget
complete function.

Signed-off-by: Yoshihiro Shimoda yoshihiro.shimoda...@renesas.com
---
 drivers/usb/renesas_usbhs/mod_gadget.c |   11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c 
b/drivers/usb/renesas_usbhs/mod_gadget.c
index e0384af..104bddf 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -126,11 +126,22 @@ static void usbhsg_queue_pop(struct usbhsg_uep *uep,
struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
struct device *dev = usbhsg_gpriv_to_dev(gpriv);
+   unsigned long flags;
 
dev_dbg(dev, pipe %d : queue pop\n, usbhs_pipe_number(pipe));
 
ureq-req.status = status;
+   /*
+* According to the gadget.h, a complete function will always be
+* called with interrupts disabled. However, sometimes this function
+* is called with interrupts enabled. (e.g. complete a DMAC transfer or
+* write data and done is set immediately when PIO.) So, this function
+* should calls local_irq_save() before this calls the
+* usb_gadget_giveback_request().
+*/
+   local_irq_save(flags);
usb_gadget_giveback_request(uep-ep, ureq-req);
+   local_irq_restore(flags);
 }
 
 static void usbhsg_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt)
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html