linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Brian Norris <briannorris@chromium.org>
To: Shawn Lin <shawn.lin@rock-chips.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>,
	devicetree@vger.kernel.org, Heiko Stuebner <heiko@sntech.de>,
	Arnd Bergmann <arnd@arndb.de>,
	Marc Zyngier <marc.zyngier@arm.com>,
	linux-pci@vger.kernel.org, Wenrui Li <wenrui.li@rock-chips.com>,
	linux-kernel@vger.kernel.org,
	Doug Anderson <dianders@chromium.org>,
	linux-rockchip@lists.infradead.org,
	Rob Herring <robh+dt@kernel.org>
Subject: Re: [PATCH v3 2/2] PCI: Rockchip: Add Rockchip PCIe controller support
Date: Wed, 22 Jun 2016 18:35:27 -0700	[thread overview]
Message-ID: <20160623013527.GA46876@google.com> (raw)
In-Reply-To: <dcdc3402-22d9-473a-d9ae-b9bd994c24a6@rock-chips.com>

Hi,

On Thu, Jun 23, 2016 at 09:09:46AM +0800, Shawn Lin wrote:
> 在 2016/6/23 8:29, Brian Norris 写道:
> >On Thu, Jun 16, 2016 at 09:50:35AM +0800, Shawn Lin wrote:

[...]

> >>+	/* 500ms timeout value should be enough for gen1/2 taining */
> >>+	timeout = jiffies + msecs_to_jiffies(500);
> >>+
> >>+	err = -ETIMEDOUT;
> >>+	while (time_before(jiffies, timeout)) {
> >>+		status = pcie_read(port, PCIE_CLIENT_BASIC_STATUS1);
> >>+		if (((status >> PCIE_CLIENT_LINK_STATUS_SHIFT) &
> >>+		      PCIE_CLIENT_LINK_STATUS_MASK) ==
> >>+		      PCIE_CLIENT_LINK_STATUS_UP) {
> >>+			dev_dbg(port->dev, "pcie link training gen1 pass!\n");
> >>+			err = 0;
> >>+			break;
> >>+		}
> >>+		msleep(20);
> >>+	}
> >
> >Technically, the above timeout loop is not quite correct. Possible error
> >case: we can fail with a timeout after 500 ms if the training completes
> >between the 480-500 ms time window. This can happen because you're
> >doing:
> >
> >(1) read register: if complete, then terminate successfully
> >(2) delay
> >(3) check for timeout: if time is up, return error
> >
> >You actually need:
> >
> >(1) read register: if complete, then terminate successfully
> >(2) delay
> >(3) check for timeout: if time is up, repeat (1), and then report error
> >
> >You can examine the logic for readx_poll_timeout() in
> >include/linux/iopoll.h to see an example of a proper timeout loop. You
> >could even try to use one of the helpers there, except that your
> >pcie_read() takes 2 args.
> 
> I see, thanks.
> 
> >
> >>+	if (err) {
> >>+		dev_err(port->dev, "pcie link training gen1 timeout!\n");
> >>+		return err;
> >>+	}
> >>+
> >>+	/*
> >>+	 * Enable retrain for gen2. This should be configured only after
> >>+	 * gen1 finished.
> >>+	 */
> >>+	status = pcie_read(port,
> >>+			   PCIR_RC_CONFIG_LCS + PCIE_RC_CONFIG_BASE);
> >>+	status |= PCIE_CORE_LCSR_RETAIN_LINK;
> >>+	pcie_write(port, status,
> >>+		   PCIR_RC_CONFIG_LCS + PCIE_RC_CONFIG_BASE);
> >
> >I'm not really an expert on this, but how are you actually "retraining
> >for gen2"? Is that just the behavior of the core, that it retries at the
> >higher rate on the 2nd training attempt? I'm just confused, since you
> >set PCIE_CLIENT_GEN_SEL_2 above, so you've already allowed either gen1
> >or gen2 negotiation AFAICT, and so seemingly you might already have
> >negotiated at gen2.
> 
> 
> Not really. I allow the core to enable gen2, but it needs a extra
> setting of retrain after finishing gen1. It's not so strange as it
> depends on the vendor's design. So I have to say it fits the
> designer's expectation.

OK.

> >>+	err = -ETIMEDOUT;
> >>+
> >>+	while (time_before(jiffies, timeout)) {
> >
> >You never reset 'timeout' when starting this loop. So you only have a
> >cumulative 500 ms to do both the gen1 and gen2 loops. Is that
> >intentional? (I feel like this comment was made on an earlier revision
> >of this driver, though I haven't read everything thoroughly.)
> 
> yes, I don't have any docs to let me know how long should I wait for
> gen1/2 to be finished. Maybe someday it will be augmented to a larger
> value if finding a device actually need a longer time. But the only
> thing I can say is that it's from my test for many pcie devices
> currently.
> 
> 
> Do you agree?

I'm not suggesting increasing the timeout, exactly; I'm suggesting that
you should set some minimum timeout for each training loop, instead of
reusing the same deadline. i.e., something like this before the second
loop:

	/* Reset the deadline for gen2 */
	timeout = jiffies + msecs_to_jiffies(500);

As it stands, if the first loop takes 490 ms, that leaves you only 10 ms
for the second loop. And I think it'd be confusing if we ever see the
first loop take a "long" time, and then we time out on the second --
we'd be blaming the gen2 training for gen1's slowness.

> >>+		status = pcie_read(port, PCIE_CORE_CTRL_MGMT_BASE);
> >>+		if (((status >> PCIE_CORE_PL_CONF_SPEED_SHIFT) &
> >>+		      PCIE_CORE_PL_CONF_SPEED_MASK) ==
> >>+		      PCIE_CORE_PL_CONF_SPEED_50G) {
> >>+			dev_dbg(port->dev, "pcie link training gen2 pass!\n");
> >>+			err = 0;
> >>+			break;
> >>+		}
> >>+		msleep(20);
> >>+	}
> >
> >Similar problem with your timeout loop, as mentioned above. Although I
> >confused about what you do in the error case here...
> >
> >>+	if (err)
> >>+		dev_dbg(port->dev, "pcie link training gen2 timeout, force to gen1!\n");
> >
> >... how are you forcing gen1? I don't see any code that indicates this.
> >Should you at least be checking that there aren't some kind of training
> >errors, and that we settled back on gen1/2.5G?
> 
> yes, when failing gen2,  my pcie controller will fallback to gen1
> automatically.

OK. Well maybe the text should say something like "falling back" instead
of "force"?

> if we pass the gen1 then fail to train gen2, a dbg msg here is enough
> here to let we know that we should check the HW signal. Of course we
> should make sure that this device supports gen2.

OK.

[...]

Brian

  reply	other threads:[~2016-06-23  1:35 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-16  1:50 [PATCH v3 2/2] PCI: Rockchip: Add Rockchip PCIe controller support Shawn Lin
2016-06-16 13:08 ` kbuild test robot
2016-06-23  0:29 ` Brian Norris
2016-06-23  1:09   ` Shawn Lin
2016-06-23  1:35     ` Brian Norris [this message]
2016-06-23  2:15       ` Shawn Lin

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=20160623013527.GA46876@google.com \
    --to=briannorris@chromium.org \
    --cc=arnd@arndb.de \
    --cc=bhelgaas@google.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dianders@chromium.org \
    --cc=heiko@sntech.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-rockchip@lists.infradead.org \
    --cc=marc.zyngier@arm.com \
    --cc=robh+dt@kernel.org \
    --cc=shawn.lin@rock-chips.com \
    --cc=wenrui.li@rock-chips.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).