linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: Niklas Cassel <cassel@kernel.org>
To: Shawn Lin <shawn.lin@rock-chips.com>
Cc: "FUKAUMI Naoki" <naoki@radxa.com>,
	"Damien Le Moal" <dlemoal@kernel.org>,
	"Anand Moon" <linux.amoon@gmail.com>,
	linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org,
	"Dragan Simic" <dsimic@manjaro.org>,
	"Lorenzo Pieralisi" <lpieralisi@kernel.org>,
	"Krzysztof Wilczyński" <kw@linux.com>,
	"Rob Herring" <robh@kernel.org>,
	"Bjorn Helgaas" <bhelgaas@google.com>,
	"Heiko Stuebner" <heiko@sntech.de>,
	mani@kernel.org
Subject: Re: [RESEND] Re: [PATCH] PCI: dw-rockchip: Skip waiting for link up
Date: Mon, 10 Nov 2025 13:34:41 +0100	[thread overview]
Message-ID: <aRHb4S40a7ZUDop1@ryzen> (raw)
In-Reply-To: <dc932773-af5b-4af7-a0d0-8cc72dfbd3c7@rock-chips.com>

On Mon, Nov 10, 2025 at 06:15:33PM +0800, Shawn Lin wrote:
> > 
> > Could you try PCIe 2.0 slot on your board?
> 
> I did, it doesn't work on PCIe 2.0 slot. From the PA, I could see
> the link is still in training during pci_host_probe() is called.
> Add some delay before pci_rescan_bus() in pcie-dw-rockchip doesn't
> help. But the below change should work as we delayed pci_host_probe().
> 
> --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> @@ -236,6 +236,8 @@ static int rockchip_pcie_start_link(struct dw_pcie *pci)
>         msleep(PCIE_T_PVPERL_MS);
>         gpiod_set_value_cansleep(rockchip->rst_gpio, 1);
> 
> +       msleep(50);
> +
>         return 0;
> 
> Otherwise we got:
> 
> [    0.841518] pci_bus 0003:33: busn_res: can not insert [bus 33-31] under
> [bus 32-31] (conflicts with (null) [bus 32-31])
> [    0.842596] pci_bus 0003:33: busn_res: [bus 33-31] end is updated to 33
> [    0.843184] pci_bus 0003:33: busn_res: can not insert [bus 33] under [bus
> 32-31] (conflicts with (null) [bus 32-31])
> [    0.844120] pci 0003:32:00.0: devices behind bridge are unusable because
> [bus 33] cannot be assigned for them
> [    0.845229] pci_bus 0003:34: busn_res: can not insert [bus 34-31] under
> [bus 32-31] (conflicts with (null) [bus 32-31])
> [    0.846309] pci_bus 0003:34: busn_res: [bus 34-31] end is updated to 34
> [    0.846898] pci_bus 0003:34: busn_res: can not insert [bus 34] under [bus
> 32-31] (conflicts with (null) [bus 32-31])
> [    0.847833] pci 0003:32:06.0: devices behind bridge are unusable because
> [bus 34] cannot be assigned for them
> [    0.848923] pci_bus 0003:35: busn_res: can not insert [bus 35-31] under
> [bus 32-31] (conflicts with (null) [bus 32-31])
> [    0.850014] pci_bus 0003:35: busn_res: [bus 35-31] end is updated to 35
> [    0.850605] pci_bus 0003:35: busn_res: can not insert [bus 35] under [bus
> 32-31] (conflicts with (null) [bus 32-31])
> [    0.851540] pci 0003:32:0e.0: devices behind bridge are unusable because
> [bus 35] cannot be assigned for them
> [    0.852424] pci_bus 0003:32: busn_res: [bus 32-31] end is updated to 35
> [    0.853028] pci_bus 0003:32: busn_res: can not insert [bus 32-35] under
> [bus 31] (conflicts with (null) [bus 31])
> [    0.853184] hub 3-0:1.0: USB hub found
> [    0.853931] pci 0003:31:00.0: devices behind bridge are unusable because
> [bus 32-35] cannot be assigned for them
> [    0.854262] hub 3-0:1.0: 1 port detected
> [    0.855144] pcieport 0003:30:00.0: bridge has subordinate 31 but max busn
> 35
> [    0.855722] hub 4-0:1.0: USB hub found
> [    0.856109] pci 0003:32:00.0: PCI bridge to [bus 33]
> [    0.856939] pci 0003:32:06.0: PCI bridge to [bus 34]
> [    0.857133] hub 4-0:1.0: 1 port detected
> [    0.857430] pci 0003:32:0e.0: PCI bridge to [bus 35]
> [    0.858236] pci 0003:31:00.0: PCI bridge to [bus 32-35]

Mani,

while I see the idea behind your suggested hack:
 
+       if (pdev->vendor == 0x1d87 && pdev->device == 0x3588) {
+               pdev->is_hotplug_bridge = pdev->is_pciehp = 1;
+               return;
+       }


Considering what Shawn says, that the switch gets enumerated properly
if we simply add a msleep() in ->start_link(), which will be called
by dw_pcie_host_init() before pci_host_probe() is called...

...we already have a delay in the link up IRQ handler, before calling
pci_rescan_bus().

So, I think that the problem is that we are unconditionally calling
pci_host_probe() in dw_pcie_host_init(), even for platforms that have
a link-up IRQ.


I think a better solution would be something like:

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index e92513c5bda5..42d987ddab7d 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -565,6 +565,39 @@ static int dw_pcie_host_get_resources(struct dw_pcie_rp *pp)
 	return 0;
 }
 
+static int dw_pcie_host_initial_scan(struct dw_pcie_rp *pp)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+	struct pci_host_bridge *bridge = pp->bridge;
+	int ret;
+
+	ret = pci_host_probe(bridge);
+	if (ret)
+		return ret;
+
+	if (pp->ops->post_init)
+		pp->ops->post_init(pp);
+
+	dwc_pcie_debugfs_init(pci, DW_PCIE_RC_TYPE);
+
+	return 0;
+}
+
+void dw_pcie_handle_link_up_irq(struct dw_pcie_rp *pp)
+{
+	if (!pp->initial_linkup_irq_done) {
+		if (dw_pcie_host_initial_scan(pp)) {
+			//TODO: cleanup
+		}
+		pp->initial_linkup_irq_done = true;
+	} else {
+		/* Rescan the bus to enumerate endpoint devices */
+		pci_lock_rescan_remove();
+		pci_rescan_bus(pp->bridge->bus);
+		pci_unlock_rescan_remove();
+	}
+}
+
 int dw_pcie_host_init(struct dw_pcie_rp *pp)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -672,15 +705,13 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
 	if (!pp->use_linkup_irq)
 		/* Ignore errors, the link may come up later */
 		dw_pcie_wait_for_link(pci);
-
-	ret = pci_host_probe(bridge);
-	if (ret)
-		goto err_stop_link;
-
-	if (pp->ops->post_init)
-		pp->ops->post_init(pp);
-
-	dwc_pcie_debugfs_init(pci, DW_PCIE_RC_TYPE);
+	else
+		/*
+		 * For platforms with Link Up IRQ, initial scan will be done
+		 * on first Link Up IRQ.
+		 */
+		if (dw_pcie_host_initial_scan(pp))
+			goto err_stop_link;
 
 	return 0;
 
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index e995f692a1ec..a31bd93490dc 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -427,6 +427,7 @@ struct dw_pcie_rp {
 	int			msg_atu_index;
 	struct resource		*msg_res;
 	bool			use_linkup_irq;
+	bool			initial_linkup_irq_done;
 	struct pci_eq_presets	presets;
 	struct pci_config_window *cfg;
 	bool			ecam_enabled;
@@ -807,6 +808,7 @@ void dw_pcie_msi_init(struct dw_pcie_rp *pp);
 int dw_pcie_msi_host_init(struct dw_pcie_rp *pp);
 void dw_pcie_free_msi(struct dw_pcie_rp *pp);
 int dw_pcie_setup_rc(struct dw_pcie_rp *pp);
+void dw_pcie_handle_link_up_irq(struct dw_pcie_rp *pp);
 int dw_pcie_host_init(struct dw_pcie_rp *pp);
 void dw_pcie_host_deinit(struct dw_pcie_rp *pp);
 int dw_pcie_allocate_domains(struct dw_pcie_rp *pp);
@@ -844,6 +846,9 @@ static inline int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
 	return 0;
 }
 
+static inline void dw_pcie_handle_link_up_irq(struct dw_pcie_rp *pp)
+{ }
+
 static inline int dw_pcie_host_init(struct dw_pcie_rp *pp)
 {
 	return 0;
diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
index 8a882dcd1e4e..042e5845bdd6 100644
--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
@@ -468,10 +468,7 @@ static irqreturn_t rockchip_pcie_rc_sys_irq_thread(int irq, void *arg)
 		if (rockchip_pcie_link_up(pci)) {
 			msleep(PCIE_RESET_CONFIG_WAIT_MS);
 			dev_dbg(dev, "Received Link up event. Starting enumeration!\n");
-			/* Rescan the bus to enumerate endpoint devices */
-			pci_lock_rescan_remove();
-			pci_rescan_bus(pp->bridge->bus);
-			pci_unlock_rescan_remove();
+			dw_pcie_handle_link_up_irq(pp);
 		}
 	}
 




What do you think?



Kind regards,
Niklas


  reply	other threads:[~2025-11-10 12:34 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-13 10:59 [PATCH] PCI: dw-rockchip: Skip waiting for link up Niklas Cassel
2025-01-13 19:27 ` Bjorn Helgaas
2025-01-13 21:14   ` Niklas Cassel
2025-01-13 20:22 ` Bjorn Helgaas
2025-10-21  4:26 ` FUKAUMI Naoki
2025-10-21  7:10   ` Shawn Lin
2025-11-08 12:34     ` Niklas Cassel
2025-11-08 13:27       ` Niklas Cassel
2025-11-08 14:21         ` Diederik de Haas
2025-11-09  4:42         ` FUKAUMI Naoki
2025-11-09 12:28           ` Niklas Cassel
2025-11-09 23:16             ` FUKAUMI Naoki
2025-11-09 23:26             ` [RESEND] " FUKAUMI Naoki
2025-11-10  2:30               ` Shawn Lin
2025-11-10  4:56                 ` FUKAUMI Naoki
2025-11-10  7:12                   ` Shawn Lin
2025-11-10  7:52                     ` FUKAUMI Naoki
2025-11-10 10:15                       ` Shawn Lin
2025-11-10 12:34                         ` Niklas Cassel [this message]
2025-11-10 12:41                           ` Niklas Cassel
2025-11-10 15:21                             ` FUKAUMI Naoki
2025-11-10 15:37                               ` Manivannan Sadhasivam
2025-11-10 15:53                           ` Manivannan Sadhasivam
2025-11-10 19:59                             ` Niklas Cassel
2025-11-10 22:14                               ` FUKAUMI Naoki
2025-11-11  2:09                               ` FUKAUMI Naoki
2025-11-11  3:17                                 ` Shawn Lin
2025-11-11 14:00                                   ` Niklas Cassel
2025-11-11  1:11                             ` Shawn Lin
2025-11-10 11:24               ` Manivannan Sadhasivam

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=aRHb4S40a7ZUDop1@ryzen \
    --to=cassel@kernel.org \
    --cc=bhelgaas@google.com \
    --cc=dlemoal@kernel.org \
    --cc=dsimic@manjaro.org \
    --cc=heiko@sntech.de \
    --cc=kw@linux.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-rockchip@lists.infradead.org \
    --cc=linux.amoon@gmail.com \
    --cc=lpieralisi@kernel.org \
    --cc=mani@kernel.org \
    --cc=naoki@radxa.com \
    --cc=robh@kernel.org \
    --cc=shawn.lin@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).