lkml.org 
[lkml]   [2013]   [Nov]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [PATCH] usb: gadget: Add UDC driver for Aeroflex Gaisler GRUSBDC
On Mon, Oct 28, 2013 at 01:59:02PM +0100, Andreas Larsson wrote:
> On 2013-10-01 16:19, Felipe Balbi wrote:
> >>>>+static void gr_finish_request(struct gr_ep *ep, struct gr_request *req,
> >>>>+ int status)
> >>>>+{
> >>>>+ struct gr_udc *dev;
> >>>>+
> >>>>+ list_del_init(&req->queue);
> >>>>+
> >>>>+ if (likely(req->req.status == -EINPROGRESS))
> >>>>+ req->req.status = status;
> >>>>+ else
> >>>>+ status = req->req.status;
> >>>>+
> >>>>+ dev = ep->dev;
> >>>>+ usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
> >>>>+ gr_free_dma_desc_chain(dev, req);
> >>>>+
> >>>>+ if (ep->is_in) /* For OUT, actual gets updated by the work handler */
> >>>>+ req->req.actual = req->req.length;
> >>>>+
> >>>>+ if (!status) {
> >>>>+ if (ep->is_in)
> >>>>+ gr_dbgprint_request("SENT", ep, req);
> >>>>+ else
> >>>>+ gr_dbgprint_request("RECV", ep, req);
> >>>>+ }
> >>>>+
> >>>>+ /* Prevent changes to ep->queue during callback */
> >>>>+ ep->callback = 1;
> >>>>+ if (req == dev->ep0reqo && !status) {
> >>>>+ if (req->setup)
> >>>>+ gr_ep0_setup(dev, req);
> >>>>+ else
> >>>>+ dev_err(dev->dev,
> >>>>+ "Unexpected non setup packet on ep0in\n");
> >>>>+ } else if (req->req.complete) {
> >>>>+ unsigned long flags;
> >>>>+
> >>>>+ /* Complete should be called with irqs disabled */
> >>>>+ local_irq_save(flags);
> >>>
> >>>I guess it'd be better if you called this with spin_lock_irqsave()
> >>>called before, then you can remove local_irq_save from here.
> >>
> >>That would increase the amount of time interrupts are disabled quite a
> >>lot, so I would prefer not to.
> >
> >that's what every other UDC driver is doing. I don't think you need to
> >worry about that. Can you run some benchmarks with both constructs just
> >so I can have peace of mind ?
>
> Hi!
>
> My benchmark shows 20%+ performance loss both for mass storage running
> on this driver and for concurrent ethernet traffic and cpu bound tasks
> running with this change. In addition the code becomes messier as some
> spin locks disables interrupts and some do not depending on wich paths
> might lead to a call to complete. So I'll stick to not disabling
> interrupts until disabled interrupts are actually needed.
>
> >>>>+static irqreturn_t gr_irq(int irq, void *_dev)
> >>>>+{
> >>>>+ struct gr_udc *dev = _dev;
> >>>>+
> >>>>+ if (!dev->irq_enabled)
> >>>>+ return IRQ_NONE;
> >>>>+
> >>>>+ schedule_work(&dev->work);
> >>>
> >>>why do you need this ? We have threaded IRQ handlers. Why a workqueue ?
> >>
> >>As mentioned above, to to be able to schedule work after pausing
> >>endpoint handling during a completion callback call or during an
> >>endpoint halt.
> >
> >doesn't look like you need that work_struct at all. Handle your IRQ
> >directly and for the pieces you need to do after ClearHalt, re-factor
> >that to a separate function which you call conditionally on
> >->set_halt().
>
> For some reason, the performance suffers massively when switching to
> using threaded interrupts instead of the current solution using the work
> queue. The times to complete large file transfers to the mass_storage
> gadget running on top of the udc are regularly around seven times longer
> using threaded interrupts complared to using the work queue
> solution. Unless you have any ideas here, I hope you can let the driver
> keep the work queue solution.

sorry for the long delay. That would point to a bug in threaded IRQ
handling and I believe Sebastian has looked over that in past,
Sebastian ? To answer your question, sorry, we don't want unnecessary
workqueues to be added :-s

cheers

--
balbi
[unhandled content-type:application/pgp-signature]
\
 
 \ /
  Last update: 2013-11-26 19:01    [W:0.596 / U:0.316 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site