linux-usb.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Felipe Balbi <balbi@kernel.org>
To: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>,
	"linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>,
	"linux-renesas-soc@vger.kernel.org"
	<linux-renesas-soc@vger.kernel.org>
Subject: [PATCH/RFC] usb: gadget: function: printer: avoid wrong list handling in printer_write()
Date: Mon, 21 May 2018 11:04:45 +0300	[thread overview]
Message-ID: <87603h8mea.fsf@linux.intel.com> (raw)

Hi,

Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> writes:

> Hi,
>
>> From: Felipe Balbi, Sent: Monday, May 21, 2018 3:57 PM
>> 
>> Hi,
>> 
>> Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> writes:
>> > The usb_ep_queue() in printer_write() is possible to call req->complete().
>> > In that case, since tx_complete() calls list_add(&req->list, &dev->tx_reqs),
>> > printer_write() should not call list_add(&req->list, &dev->tx_reqs_active)
>> > because the transfer has already finished. So, this patch checks
>> > the condition of req->list before adding the list in printer_write().
>> >
>> > Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
>> > ---
>> >  This issue can be caused by renesas_usbhs udc driver. I'm not sure
>> >  this patch is acceptable or not. So, I marked RFC on this patch.
>> 
>> can you explain this a little more? How do you trigger the problem?
>
> Sure. If printer_write() called usb_ep_queue() with 63 bytes or less data,
> the renesas_usbhs udc driver transfers data as PIO. In this case, the udc
> driver calls usb_gadget_giveback_reuqest() in .queue ops (usbhsg_ep_queue())
> immediately. Then, printer_write() calls list_add(&req->list, &dev->tx_reqs_active); wrongly.
> After that, if we do rmmod g_printer, WARN_ON(!list_empty(&dev->tx_reqs_active); happens in
> printer_func_unbind() because the list entry is not removed.
>
> < Reference: calltrace (very long though...) >
> 	usb_ep_queue(...);		at f_printer.c / printer_write()
> 	1-> usbhsg_ep_queue();		at renesas_usbhs/mod_gadget.c
> 	 2-> usbhsg_queue_push();
> 	  3-> usbhs_pkt_start();		at renesas_usbhs/fifo.c
> 	   4-> usbhsf_pkt_handler();
> 	    5-> func() = usbhsf_dma_prepare_push();
> 	     6-> goto usbhsf_pio_prepare_push; // Because len is 63
> 	      7-> usbhsf_pio_prepare_push();
> 	       8-> usbhsf_pio_try_push();
>             5-> done() = usbhsg_queue_done();	at renesas_usbhs/mod_gadget.c
> 	     6-> __usbsg_queue_pop();
> 	      7-> usb_gadget_giveback_reuqest();
> 	       8-> tx_complete();		at f_printer.c
>                 9-> list_del_init(&req->list);
>                 9-> list_add(&req->list, &dev->tx_reqs);
> 	list_add(&req->list, &dev->tx_reqs_active);	// Even if the transaction already finished, this driver is possible to add the list to "active".

seems like it would be better to just move this like before
usb_ep_queue():

modified   drivers/usb/gadget/function/f_printer.c
@@ -631,19 +631,19 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 			return -EAGAIN;
 		}
 
+		list_add(&req->list, &dev->tx_reqs_active);
+
 		/* here, we unlock, and only unlock, to avoid deadlock. */
 		spin_unlock(&dev->lock);
 		value = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC);
 		spin_lock(&dev->lock);
 		if (value) {
+			list_del(&req->list);
 			list_add(&req->list, &dev->tx_reqs);
 			spin_unlock_irqrestore(&dev->lock, flags);
 			mutex_unlock(&dev->lock_printer_io);
 			return -EAGAIN;
 		}
-
-		list_add(&req->list, &dev->tx_reqs_active);
-
 	}
 
 	spin_unlock_irqrestore(&dev->lock, flags);

             reply	other threads:[~2018-05-21  8:04 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-21  8:04 Felipe Balbi [this message]
  -- strict thread matches above, loose matches on Subject: below --
2018-05-21 11:16 [PATCH/RFC] usb: gadget: function: printer: avoid wrong list handling in printer_write() Yoshihiro Shimoda
2018-05-21 10:18 Felipe Balbi
2018-05-21  8:57 Yoshihiro Shimoda
2018-05-21  7:57 Yoshihiro Shimoda
2018-05-21  6:57 Felipe Balbi
2018-05-18  8:37 Yoshihiro Shimoda

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87603h8mea.fsf@linux.intel.com \
    --to=balbi@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-renesas-soc@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=yoshihiro.shimoda.uh@renesas.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).