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);
next 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).