linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: linux@arm.linux.org.uk (Russell King - ARM Linux)
To: linux-arm-kernel@lists.infradead.org
Subject: PL310 errata workarounds
Date: Fri, 21 Mar 2014 17:12:17 +0000	[thread overview]
Message-ID: <20140321171217.GK7528@n2100.arm.linux.org.uk> (raw)
In-Reply-To: <CAHrpEqSaV951SGctNdHGtbX-ksv=OEv2KSY_QBpZ_Qu2c_Ka-Q@mail.gmail.com>

On Fri, Mar 21, 2014 at 10:50:41AM -0500, Frank Li wrote:
> On Wed, Mar 19, 2014 at 5:51 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > 2. The ARM can re-order writes.  The writes it can re-order are:
> >
> >         bdp->cbd_bufaddr
> >         ebdp->cbd_bdu
> >         ebdp->cbd_esc
> >         ebdp->cbd_sc
> >
> > Hence, it's entirely possible for the FEC to see the updated descriptor
> > status before the rest of the descriptor has been written.  What's missing
> > is a barrier between the descriptor writes, and the final write to
> > bdp->cbd_sc.
> 
> Possible. I also consider this when debug the other issues.
> Just bdp->bufaddr and bdp->buflen is important.
> bdu, hardware don't care it.
> esc is the same for each BD.  When software go though BD ring once,
> esc will be not changed again, even though we write.

If you assume that all you're sending is traffic which needs the headers
checksummed (in other words, only IP traffic and nothing else) then you're
correct.  Reality is that other traffic gets included, such as ARPs which
have skb->ip_summed = CHECKSUM_NONE.

In any case, you are wrong about cbd_esc.  For this code:

			ebdp->cbd_esc = BD_ENET_TX_INT;
 
			/* Enable protocol checksum flags
			 * We do not bother with the IP Checksum bits as they
			 * are done by the kernel
			 */
			if (skb->ip_summed == CHECKSUM_PARTIAL)
				ebdp->cbd_esc |= BD_ENET_TX_PINS;

this is the assembly which the compiler will generate:

     820:       e3a03101        mov     r3, #1073741824 ; 0x40000000
     824:       e5863008        str     r3, [r6, #8]
     828:       e5d53064        ldrb    r3, [r5, #100]  ; 0x64
     82c:       e203300c        and     r3, r3, #12
     830:       e353000c        cmp     r3, #12
     834:       03a03205        moveq   r3, #1342177280 ; 0x50000000
     838:       05863008        streq   r3, [r6, #8]

That's a write to cbd_esc with BD_ENET_TX_INT set and BD_ENET_TX_PINS
clear, followed by another write with both set if the packet has been
partially checksummed.

Depending on the CPU and timing, that could be visible to the device.
Thankfully, fb8ef788680 fixed it for CPUs which are strongly ordered.
However, with a weakly ordered CPU, all it would take is an interrupt
between those two writes to make them visible as separate writes, and
without the following barrier, the order of cbd_esc and cbd_sc
becoming visible is uncertain.

> but if sc write before buffaddr and bullen, there will be issue.
> Add memory barre here is better before  ebdp->cbd_sc.
> 
> I also want to add it before, But I have not found a test case to
> verify it is necessary.

In these situations, knowledge and theory is better than test-and-verify,
especially when we're talking about trying to hit a small window with
timings.

We know ARMv6 and ARMv7 are weakly ordered.  We know we see problems
with transmit on these devices.  We know that the specification calls
for the TX ready bit to be set last.  We know on these CPUs that
writes can be reordered.  Therefore... a barrier is definitely
required.

> > The result is the handler is entered, FEC_IEVENT contains TXF and MII
> > events.  Both these events are cleared down, (and thus no longer exist
> > as interrupt-causing events.)  napi_schedule_prep() returns false as
> > the NAPI rx function is still running, and doesn't mark it for a re-run.
> > We then do the MII interrupt.  Loop again, and int_events is zero,
> > we exit.
> >
> > Meanwhile, the NAPI rx function calls napi_complete() and re-enables
> > the receive interrupt.  If you're unlucky enough that the RX ring is
> > also full... no RXF interrupt.  So no further interrupts except maybe
> > MII interrupts.
> >
> > NAPI never gets scheduled.  RX ring never gets emptied.  TX ring never
> > gets reaped.  The result is a timeout with a completely full TX ring.
> 
> Do you see RX ring full?

I haven't added any debug for the RX ring, so I don't know for certain.
What I do know is that I've had the situation where the TX ring is
completely full of packets which have been sent and the TX ring hasn't
been reaped, which leads to the timeout, and that is down to the NAPI
functions not being scheduled.

When that happens, the three sets of flood pings thumping away at the
iMX6Q don't get any response until the timeout occurs.

In that scenario, if a packet were to be received (and there's many
packets hitting the interface) then it _would_ trigger reaping of the
TX ring.

> > +       do {
> > +               index = (index + 1) & (fep->tx_ring_size - 1);
> > +               bdp = fec_enet_tx_get(index, fep);
> >
> > -       while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
> > +               status = bdp->bd.cbd_sc;
> > +               if (status & BD_ENET_TX_READY)
> > +                       break;

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In answer to your question below, here.

> >
> >                 /* current queue is empty */
> > -               if (bdp == fep->cur_tx)
> > +               if (index == fep->tx_next)
> >                         break;

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
and here.

> >
> > -               if (fep->bufdesc_ex)
> > -                       index = (struct bufdesc_ex *)bdp -
> > -                               (struct bufdesc_ex *)fep->tx_bd_base;
> > -               else
> > -                       index = bdp - fep->tx_bd_base;
> > +               fec_enet_tx_unmap(&bdp->bd, fep);
> >
> >                 skb = fep->tx_skbuff[index];
> > -               dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, skb->len,
> > -                               DMA_TO_DEVICE);
> > -               bdp->cbd_bufaddr = 0;
> > +               fep->tx_skbuff[index] = NULL;
> >
> >                 /* Check for errors. */
> >                 if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
> > @@ -797,19 +826,18 @@ fec_enet_tx(struct net_device *ndev)
> >                                 ndev->stats.tx_carrier_errors++;
> >                 } else {
> >                         ndev->stats.tx_packets++;
> > -                       ndev->stats.tx_bytes += bdp->cbd_datlen;
> > +                       ndev->stats.tx_bytes += bdp->bd.cbd_datlen;
> >                 }
> >
> >                 if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) &&
> >                         fep->bufdesc_ex) {
> >                         struct skb_shared_hwtstamps shhwtstamps;
> >                         unsigned long flags;
> > -                       struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
> >
> >                         memset(&shhwtstamps, 0, sizeof(shhwtstamps));
> >                         spin_lock_irqsave(&fep->tmreg_lock, flags);
> >                         shhwtstamps.hwtstamp = ns_to_ktime(
> > -                               timecounter_cyc2time(&fep->tc, ebdp->ts));
> > +                               timecounter_cyc2time(&fep->tc, bdp->ebd.ts));
> >                         spin_unlock_irqrestore(&fep->tmreg_lock, flags);
> >                         skb_tstamp_tx(skb, &shhwtstamps);
> >                 }
> > @@ -825,45 +853,252 @@ fec_enet_tx(struct net_device *ndev)
> >
> >                 /* Free the sk buffer associated with this last transmit */
> >                 dev_kfree_skb_any(skb);
> > -               fep->tx_skbuff[index] = NULL;
> > -
> > -               fep->dirty_tx = bdp;
> > -
> > -               /* Update pointer to next buffer descriptor to be transmitted */
> > -               bdp = fec_enet_get_nextdesc(bdp, fep);
> >
> >                 /* Since we have freed up a buffer, the ring is no longer full
> >                  */
> > -               if (fep->dirty_tx != fep->cur_tx) {
> > -                       if (netif_queue_stopped(ndev))
> > -                               netif_wake_queue(ndev);
> > +               if (netif_queue_stopped(ndev)) {
> > +
> > +
> > +
> > +
> > +
> > +                       netif_wake_queue(ndev);
> > +
> >                 }
> > -       }
> > +
> > +               fep->tx_dirty = index;
> > +       } while (1);
> 
> where break this while(1);

-- 
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.

  reply	other threads:[~2014-03-21 17:12 UTC|newest]

Thread overview: 76+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-14 14:48 PL310 errata workarounds Russell King - ARM Linux
2014-03-14 15:01 ` Russell King - ARM Linux
2014-03-14 16:02   ` Rob Herring
2014-03-14 17:57     ` Russell King - ARM Linux
2014-03-14 19:14       ` Rob Herring
2014-03-14 20:32         ` Russell King - ARM Linux
2014-03-19 21:22         ` Marek Vasut
2014-03-19 21:35           ` Rob Herring
2014-03-19 21:46             ` Russell King - ARM Linux
2014-03-19 21:54               ` Marek Vasut
2014-03-16 11:52     ` Russell King - ARM Linux
2014-03-17 15:04       ` Rob Herring
2014-03-17 15:37         ` Russell King - ARM Linux
2014-03-17 17:29           ` Catalin Marinas
2014-03-17 19:44             ` Russell King - ARM Linux
2014-03-17 21:09               ` Nicolas Pitre
2014-03-17 21:14                 ` Russell King - ARM Linux
2014-03-17 21:54                   ` Nicolas Pitre
2014-03-16 15:29 ` Russell King - ARM Linux
2014-03-17 14:00   ` Rob Herring
2014-03-17 14:40     ` Russell King - ARM Linux
2014-03-18 11:22     ` *READ THIS IF YOUR SOC HAS A L2 CACHE* PL310 auxctrl settings Russell King - ARM Linux
2014-03-28 12:51       ` Maxime Coquelin
2014-03-28 13:02         ` Russell King - ARM Linux
2014-03-28 13:32           ` Maxime Coquelin
2014-03-18 17:26     ` PL310 errata workarounds Russell King - ARM Linux
2014-03-19 21:52       ` Marek Vasut
2014-03-19 22:51         ` Russell King - ARM Linux
2014-03-19 23:05           ` FEC ethernet issues [Was: PL310 errata workarounds] Marek Vasut
2014-03-20  4:01             ` Marek Vasut
2014-03-20 22:27               ` Fabio Estevam
2014-03-20 23:06                 ` Russell King - ARM Linux
2014-03-21  0:24                   ` Troy Kisky
2014-03-21  1:18                     ` Russell King - ARM Linux
2014-03-21  1:36                       ` Fabio Estevam
2014-03-21  1:43                         ` Fabio Estevam
2014-03-21 16:37                           ` Bernd Faust
     [not found]                           ` <CANBf9eNZB+BVBDkgWNxxGs-ndQ-mYCc6+bfVdS-8T-QLpSZ3GA@mail.gmail.com>
2014-03-21 17:32                             ` Russell King - ARM Linux
2014-03-23 11:38                               ` Bernd Faust
2014-03-23 13:44                                 ` Russell King - ARM Linux
2014-03-24 17:57                               ` robert.daniels at vantagecontrols.com
2014-03-24 20:21                                 ` Marek Vasut
2014-03-24 22:37                                   ` robert.daniels at vantagecontrols.com
2014-03-24 23:44                                     ` Russell King - ARM Linux
2014-03-25  1:02                                       ` Marek Vasut
2014-03-25 23:10                                         ` Russell King - ARM Linux
2014-03-26  0:11                                       ` Russell King - ARM Linux
2014-04-01  9:26                                         ` Russell King - ARM Linux
2014-04-01 14:00                                           ` Eric Nelson
2014-04-01 17:29                                             ` Russell King - ARM Linux
2014-04-01 18:11                                               ` Eric Nelson
2014-04-02  2:26                                               ` fugang.duan at freescale.com
2014-04-01 19:38                                           ` robert.daniels at vantagecontrols.com
2014-04-01 22:51                                             ` Russell King - ARM Linux
2014-04-02  0:37                                               ` robert.daniels at vantagecontrols.com
2014-04-02  3:19                                               ` fugang.duan at freescale.com
2014-04-02  8:59                                                 ` Russell King - ARM Linux
2014-04-02  9:40                                                   ` fugang.duan at freescale.com
2014-04-02 10:46                                                     ` Russell King - ARM Linux
2014-04-02 11:33                                                       ` fugang.duan at freescale.com
2014-04-02 16:51                                                         ` Russell King - ARM Linux
2014-04-03  2:41                                                           ` fugang.duan at freescale.com
2014-04-03  8:56                                                             ` Russell King - ARM Linux
2014-04-03  9:55                                                               ` fugang.duan at freescale.com
2014-04-03 10:32                                                                 ` Russell King - ARM Linux
2014-04-03 13:36                                                                   ` Shawn Guo
2014-04-03 13:45                                                                     ` Russell King - ARM Linux
2014-04-03 14:00                                                                       ` Shawn Guo
2014-04-04 20:21                                               ` robert.daniels at vantagecontrols.com
2014-04-29  9:26                                                 ` Jaccon Bastiaansen
     [not found]                                                 ` <CAGzjT4d8H6YE6P6A1E4aHiPAenJFvZH01LHXaNzVwhF2MRBvWQ@mail.gmail.com>
2014-05-02 11:41                                                   ` Russell King - ARM Linux
2014-05-08  9:23                                                     ` Jaccon Bastiaansen
2014-03-21 15:50           ` PL310 errata workarounds Frank Li
2014-03-21 17:12             ` Russell King - ARM Linux [this message]
2014-03-17 16:32   ` Russell King - ARM Linux
2014-03-17 16:51     ` Russell King - ARM Linux

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=20140321171217.GK7528@n2100.arm.linux.org.uk \
    --to=linux@arm.linux.org.uk \
    --cc=linux-arm-kernel@lists.infradead.org \
    /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).