From: David Jander <david@protonic.nl>
To: Marc Kleine-Budde <mkl@pengutronix.de>
Cc: Wolfgang Grandegger <wg@grandegger.com>, linux-can@vger.kernel.org
Subject: Re: [PATCH v4] can: flexcan: Re-write receive path to use MB queue instead of FIFO
Date: Mon, 29 Sep 2014 15:24:19 +0200 [thread overview]
Message-ID: <20140929152419.46c3b185@archvile> (raw)
In-Reply-To: <54253373.7000201@pengutronix.de>
Dear Marc,
On Fri, 26 Sep 2014 11:35:47 +0200
Marc Kleine-Budde <mkl@pengutronix.de> wrote:
> On 09/23/2014 03:53 PM, David Jander wrote:
>
> >> On 09/18/2014 03:48 PM, David Jander wrote:
> >>> The FlexCAN controller has a RX FIFO that is only 6 messages deep, and a
> >>> mailbox space capable of holding up to 63 messages.
> >>> This space was largely unused, limiting the permissible latency from
> >>> interrupt to NAPI to only 6 messages. This patch uses all available MBs
> >>> for message reception and frees the MBs in the IRQ handler to greatly
> >>> decrease the likelihood of receive overruns.
> >>>
> >>> Signed-off-by: David Jander <david@protonic.nl>
> >>
> >> I think we can improve the algorithm a bit.
> >>
> >> I see a problem when you receive 4 CAN frames:
> >>
> >> 0-1-2-3
> >>
> >> then the irq handler starts, 0 gets processed and is empty (E)
> >>
> >> E-1-2-3
> >
> > No. It will not be empty. It will be marked inactive immediately in
> > flexcan_copy_one_rxmb().
> >
> >> while in the interrupt handler another two frames come in:
> >>
> >> 4-1-2-3-5
> >
> > That can't happen ;-)
> >
> >> I suggest add a variable to the priv which indicates the next MB to read
> >> from. Further, don't clear the mailbox direclty after it's been read,
> >> wait until a certain amount of read mailboxes accumulate, .e.g. when the
> >> rx_next point to 32. I have a work-in-progress code which to abstract
> >
> > More or less exactly what I do. Please read the comment to
> > flexcan_copy_rxmbs()
>
> Yes you're right, I missed the:
>
> > if (i >= 32) {
> > /* Re-enable all disabled MBs */
>
> in the code.
>
> [...]
>
> >>> @@ -741,10 +743,16 @@ static int flexcan_read_frame(struct net_device
> >>> *dev) static int flexcan_poll(struct napi_struct *napi, int quota)
> >>> {
> >>> struct net_device *dev = napi->dev;
> >>> - const struct flexcan_priv *priv = netdev_priv(dev);
> >>> + struct flexcan_priv *priv = netdev_priv(dev);
> >>> struct flexcan_regs __iomem *regs = priv->base;
> >>> - u32 reg_iflag1, reg_esr;
> >>> + u32 reg_esr;
> >>> int work_done = 0;
> >>> + int n;
> >>> + int ret;
> >>> +
> >>> + /* disable RX IRQs */
> >>> + flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->imask1);
> >>> + flexcan_write(0, ®s->imask2);
> >>
> >> Please use defines here. BTW: the RX IRQ has to disabled in the IRQ
> >> handler.
> >
> > Ok, will use #defines.... but why should I disable interrupts in the IRQ
> > handler? I am copying all mailboxes in the IRQ, so no need to disable
> > interrupts there...
> > What I do here is avoid the IRQ from messing with my copy while pushing it
> > up NAPI.
>
> As you don't access the hardware in the NAPI handler, why do you disable
> the interrupts? AFAIK there is no guarantee that the interrupt handler
> is not running on a different CPU when you enter the NAPI handler. You
> have to lock the shared resource rx_idx.
>
> I suggest to turn cantxfg_copy[] into a cyclic buffer, with a head and a
> tail pointer. This way you can access them lockless.
Good idea. I just did this. Please see V5 of the patch that just hit the list.
I just noticed that I left over an unnecessary piece from a previous version:
A write barrier on reg_ctrl in flexcan_copy_one_rxmb() and corresponding read
barrier in flexcan_poll() :-(
It should not be necessary anymore, since the ring-buffer's head/tail barriers
should take care of synchronization. So please ignore the smp_wmb()/smp_rmb()
pair... it does no harm, but I will remove it in the next version *sigh*.
> >
> >>>
> >>> /*
> >>> * The error bits are cleared on read,
> >>> @@ -755,12 +763,13 @@ static int flexcan_poll(struct napi_struct *napi,
> >>> int quota) /* handle state changes */
> >>> work_done += flexcan_poll_state(dev, reg_esr);
> >>>
> >>> - /* handle RX-FIFO */
> >>> - reg_iflag1 = flexcan_read(®s->iflag1);
> >>> - while (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE &&
> >>> - work_done < quota) {
> >>> - work_done += flexcan_read_frame(dev);
> >>> - reg_iflag1 = flexcan_read(®s->iflag1);
> >>> + /* handle mailboxes */
> >>> + for (n = 0; (n < ARRAY_SIZE(priv->cantxfg_copy)) &&
> >>> + (work_done < quota); n++) {
> >>> + ret = flexcan_read_frame(dev, n);
> >>> + if (!ret)
> >>> + break;
> >>> + work_done += ret;
> >>> }
>[...]
Best regards,
--
David Jander
Protonic Holland.
prev parent reply other threads:[~2014-09-29 13:24 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-18 13:48 [PATCH v4] can: flexcan: Re-write receive path to use MB queue instead of FIFO David Jander
2014-09-23 12:58 ` Marc Kleine-Budde
2014-09-23 13:34 ` Marc Kleine-Budde
2014-09-23 13:53 ` David Jander
2014-09-26 9:35 ` Marc Kleine-Budde
2014-09-29 13:24 ` David Jander [this message]
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=20140929152419.46c3b185@archvile \
--to=david@protonic.nl \
--cc=linux-can@vger.kernel.org \
--cc=mkl@pengutronix.de \
--cc=wg@grandegger.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