RE: usb: gadget: ffs: Fix BUG when userland exits with submitted AIO transfers

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

 



Hi, Vincent:
	We tried my patch doesn't fix the issue totally, we still see the kernel panic.
	currently solution in our test is: Rvert "usb: gadget: ffs: Fix BUG when userland exits with submitted AIO transfers"
	and only add the below patch to use the in_interrupt() to avoid the wait_event_lock_irq() is called in interrupt context.

Subject: [PATCH] fix the wait_event_lock_irq run in interrupt context

the patch is to fix the below bug:
BUG: scheduling while atomic: SettingsProvide/3433/0x00000104
Preemption disabled at:
[<ffffffff81e00053>] __do_softirq+0x53/0x31b
CPU: 1 PID: 3433 Comm: SettingsProvide Tainted: P     U
ilt-2e5dc0ac-g3f662bf-dirty #8
Call Trace:
 <IRQ>
 dump_stack+0x70/0x9e
 ? __do_softirq+0x53/0x31b
 __schedule_bug+0x7f/0xd0
 __schedule+0x61d/0x860
 ? _raw_spin_unlock_irqrestore+0x28/0x50
 ? prepare_to_wait_event+0x87/0x170
 schedule+0x36/0x90
 dwc3_gadget_ep_dequeue+0x27a/0x2e0 [dwc3]
 ? finish_wait+0x90/0x90
 usb_ep_dequeue+0x23/0x90
 ffs_aio_cancel+0x4c/0x70
 kiocb_cancel+0x40/0x50
 free_ioctx_users+0x6e/0x100
 percpu_ref_switch_to_atomic_rcu+0x159/0x160
 rcu_process_callbacks+0x1a7/0x520
 __do_softirq+0x11a/0x31b
 irq_exit+0xb5/0xc0
 smp_apic_timer_interrupt+0x7c/0x160

the BUG is introduced form the patch:
commit: cf3113d89
usb: dwc3: gadget: properly increment dequeue pointer on ep_dequeue

Signed-off-by: he, bo <bo.he@xxxxxxxxx>
---
 drivers/usb/dwc3/gadget.c | 112 +++++++++++++++++++++++-----------------------
 1 file changed, 57 insertions(+), 55 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 7120678..386fd82 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1413,65 +1413,67 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
 			/* wait until it is processed */
 			dwc3_stop_active_transfer(dwc, dep->number, true);
 
-			/*
-			 * If request was already started, this means we had to
-			 * stop the transfer. With that we also need to ignore
-			 * all TRBs used by the request, however TRBs can only
-			 * be modified after completion of END_TRANSFER
-			 * command. So what we do here is that we wait for
-			 * END_TRANSFER completion and only after that, we jump
-			 * over TRBs by clearing HWO and incrementing dequeue
-			 * pointer.
-			 *
-			 * Note that we have 2 possible types of transfers here:
-			 *
-			 * i) Linear buffer request
-			 * ii) SG-list based request
-			 *
-			 * SG-list based requests will have r->num_pending_sgs
-			 * set to a valid number (> 0). Linear requests,
-			 * normally use a single TRB.
-			 *
-			 * For each of these two cases, if r->unaligned flag is
-			 * set, one extra TRB has been used to align transfer
-			 * size to wMaxPacketSize.
-			 *
-			 * All of these cases need to be taken into
-			 * consideration so we don't mess up our TRB ring
-			 * pointers.
-			 */
-			wait_event_lock_irq(dep->wait_end_transfer,
-					!(dep->flags & DWC3_EP_END_TRANSFER_PENDING),
-					dwc->lock);
-
-			if (!r->trb)
-				goto out0;
-
-			if (r->num_pending_sgs) {
-				struct dwc3_trb *trb;
-				int i = 0;
-
-				for (i = 0; i < r->num_pending_sgs; i++) {
-					trb = r->trb + i;
-					trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
-					dwc3_ep_inc_deq(dep);
-				}
+			if(likely(!in_interrupt())) {
+				/*
+				 * If request was already started, this means we had to
+				 * stop the transfer. With that we also need to ignore
+				 * all TRBs used by the request, however TRBs can only
+				 * be modified after completion of END_TRANSFER
+				 * command. So what we do here is that we wait for
+				 * END_TRANSFER completion and only after that, we jump
+				 * over TRBs by clearing HWO and incrementing dequeue
+				 * pointer.
+				 *
+				 * Note that we have 2 possible types of transfers here:
+				 *
+				 * i) Linear buffer request
+				 * ii) SG-list based request
+				 *
+				 * SG-list based requests will have r->num_pending_sgs
+				 * set to a valid number (> 0). Linear requests,
+				 * normally use a single TRB.
+				 *
+				 * For each of these two cases, if r->unaligned flag is
+				 * set, one extra TRB has been used to align transfer
+				 * size to wMaxPacketSize.
+				 *
+				 * All of these cases need to be taken into
+				 * consideration so we don't mess up our TRB ring
+				 * pointers.
+				 */
+				wait_event_lock_irq(dep->wait_end_transfer,
+						!(dep->flags & DWC3_EP_END_TRANSFER_PENDING),
+						dwc->lock);
+
+				if (!r->trb)
+					goto out0;
+
+				if (r->num_pending_sgs) {
+					struct dwc3_trb *trb;
+					int i = 0;
+
+					for (i = 0; i < r->num_pending_sgs; i++) {
+						trb = r->trb + i;
+						trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
+						dwc3_ep_inc_deq(dep);
+					}
+
+					if (r->unaligned || r->zero) {
+						trb = r->trb + r->num_pending_sgs + 1;
+						trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
+						dwc3_ep_inc_deq(dep);
+					}
+				} else {
+					struct dwc3_trb *trb = r->trb;
 
-				if (r->unaligned || r->zero) {
-					trb = r->trb + r->num_pending_sgs + 1;
 					trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
 					dwc3_ep_inc_deq(dep);
-				}
-			} else {
-				struct dwc3_trb *trb = r->trb;
 
-				trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
-				dwc3_ep_inc_deq(dep);
-
-				if (r->unaligned || r->zero) {
-					trb = r->trb + 1;
-					trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
-					dwc3_ep_inc_deq(dep);
+					if (r->unaligned || r->zero) {
+						trb = r->trb + 1;
+						trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
+						dwc3_ep_inc_deq(dep);
+					}
 				}
 			}
 			goto out1;
-- 
2.7.4





-----Original Message-----
From: Vincent Pelletier <plr.vincent@xxxxxxxxx> 
Sent: Tuesday, September 25, 2018 8:46 PM
To: He, Bo <bo.he@xxxxxxxxx>
Cc: Felipe Balbi <felipe.balbi@xxxxxxxxxxxxxxx>; Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>; Roger Quadros <rogerq@xxxxxx>; Lars-Peter Clausen <lars@xxxxxxxxxx>; Sam Protsenko <semen.protsenko@xxxxxxxxxx>; linux-usb@xxxxxxxxxxxxxxx; Praneeth Bajjuri <praneeth@xxxxxx>; Bai, Jie A <jie.a.bai@xxxxxxxxx>
Subject: Re: usb: gadget: ffs: Fix BUG when userland exits with submitted AIO transfers

Hello,

On Thu, 2 Aug 2018 14:23:51 +0000, Vincent Pelletier <plr.vincent@xxxxxxxxx> wrote:
> On Thu, 2 Aug 2018 00:45:14 +0000, "He, Bo" <bo.he@xxxxxxxxx> wrote:
> > Your patch fix the issue BUG: scheduling while atomic:  
> 
> Yes, although from my understanding of Felipe's answer, the actual bug 
> is the "scheduling" part (sleeping in dwc3 UDC) rather than the 
> "atomic" part.
> 
> So my patch addresses, still if my understanding is correct, the wrong 
> half of the problem, and even introduced the regression you identified.
> Hence my uncertainty...

I notice that neither He's patch, nor a dwc3 change to prevent it from scheduling inside usb_ep_dequeue are in Linus' master. Please correct me if I missed something.

Just in case my previous emails were not clear:
- I have no objection to He's patch on its own (and I do not know the
  code nearly enough to provide a meaningful reviewed-by).
- I do not intend to work on making changes to dwc3 gadget to stop it
  from scheduling in usb_ep_dequeue in the foreseeable future.

So if there is no ongoing work on dwc3 cancel behaviour (Felipe ?), please do resume/carry on with reviewing and integrating He's patch.

It is only *if* dwc3 cancel stops scheduling that I believe my patch should be reverted (here is the hash as of Linus' master):
  commit d52e4d0c0c428bf2ba35074a7495cdb28e2efbae
  Author: Vincent Pelletier <plr.vincent@xxxxxxxxx>
  Date:   Wed Jun 13 11:05:06 2018 +0000

      usb: gadget: ffs: Fix BUG when userland exits with submitted AIO transfers

      This bug happens only when the UDC needs to sleep during usb_ep_dequeue,
      as is the case for (at least) dwc3.
and, in my understanding, a consequence is that He's fix would not be needed anymore - the bug my patch introduced disappearing in the revert.

Regards,
--
Vincent Pelletier



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

  Powered by Linux