Linux PCI subsystem development
 help / color / mirror / Atom feed
From: Marek Vasut <marex@denx.de>
To: linux-pci@vger.kernel.org
Cc: Bjorn Helgaas <bhelgaas@google.com>,
	"Rafael J . Wysocki" <rafael.j.wysocki@intel.com>
Subject: Re: [PATCH] [RFC] PCI/PM: Do not RPM suspend devices without drivers
Date: Sat, 12 Oct 2024 02:59:44 +0200	[thread overview]
Message-ID: <a1cdad18-369e-4b12-afed-8b6b60f4d86f@denx.de> (raw)
In-Reply-To: <20241012004857.218874-1-marex@denx.de>

On 10/12/24 2:48 AM, Marek Vasut wrote:
> I am sending this as RFC, because I can only trigger it sporadically on
> Linux 6.6.54 , but I believe this was around for a while. The rationale
> might also be far from perfect. This is NOT a proper fix for the issue.
> 
> The pci_host_probe() and pci_bus_type RPM suspend seem to race against each
> other at least in Linux kernel up to 6.6.54 . The problem occurs when the
> PCIe host controller driver, in this case DWC i.MX6, is sufficiently delayed
> by EPROBE_DEFER from one if its clocks, in this case the PCIe bus clock
> provided by RS9 clock synthesizer driver which is compiled as a module and
> loaded about a minute after boot. Once the RS9 module is loaded and the
> bus clock become available, the probe of DWC iMX6 controller driver can
> proceed.
> 
> At that point, imx6_pcie_probe() triggers pci_host_probe(), while at the
> same time, devices instantiated with pci_bus_type can already enter RPM
> suspend via pci_bus_type pci_pm_runtime_idle() / pci_pm_runtime_suspend()
> callbacks.
> 
> The pci_host_probe() does reallocate BARs for devices which start up with
> uninitialized BAR addresses set to 0 by calling pci_bus_assign_resources(),
> which updates the device config space content.
> 
> At the same time, pci_pm_runtime_suspend() triggers pci_save_state() for
> all devices which do not have drivers assigned to them to store current
> content of their config space registers.
> 
> This leads to a race condition between pci_bus_assign_resources() and
> pci_save_state(). In case pci_save_state() wins and gets called before
> pci_bus_assign_resources(), the content stored by pci_save_state() is
> the incorrect pre-pci_bus_assign_resources() content, which is usually
> one with BARs set to invalid addresses and possibly other invalid
> configuration.
> 
> Once either a driver or manual RPM control attempts to start the device
> up, that invalid content is restored into the device config space and
> the device becomes inoperable. If the BARs are restored to zeroes, then
> the device stops responding to BAR memory accesses, while it still does
> respond to config space accesses.
> 
> Work around the issue by not suspending pci_bus_type devices which do
> not have driver assigned to them, keep those devices active to prevent
> pci_save_state() from being called. Once a proper driver takes over, it
> can RPM manage the device correctly.
> 
> Invalid ordering and backtrace is below, visualized with this extra print
> added to drivers/pci/setup-res.c :
> 
> "
> @@ -108,6 +108,8 @@ static void pci_std_update_resource(struct pci_dev *dev, int resno)
>                          resno, new, check);
>          }
> 
> +       pci_err(dev, "BAR %d: updated (%#010x != %#010x)\n", resno, new, check);
> +
>          if (res->flags & IORESOURCE_MEM_64) {
>                  new = region.start >> 16 >> 16;
>                  pci_write_config_dword(dev, reg + 4, new);
> "
> 
> "
> [   47.042906] pci 0000:01:00.0: save config 0x10: 0x00000004
> ...
> [   47.079863] pci 0000:01:00.0: BAR 0: updated (0x18100004 != 0x18100004)
> ...
> "
> 
> "
> [   47.274095]  pci_update_resource+0x1f0/0x260
> [   47.278370]  pci_assign_resource+0x22c/0x234
> [   47.282643]  assign_requested_resources_sorted+0x6c/0xac
> [   47.287959]  __assign_resources_sorted+0xfc/0x424
> [   47.292669]  __pci_bus_assign_resources+0x68/0x1f4
> [   47.297463]  __pci_bus_assign_resources+0xec/0x1f4
> [   47.302258]  pci_bus_assign_resources+0x1c/0x24
> [   47.306792]  pci_host_probe+0x88/0xa4
> [   47.310457]  dw_pcie_host_init+0x17c/0x530
> [   47.314560]  imx6_pcie_probe+0x698/0x708
> [   47.318487]  platform_probe+0x6c/0xb8
> [   47.322153]  really_probe+0x140/0x278
> [   47.325818]  __driver_probe_device+0xf4/0x10c
> [   47.330177]  driver_probe_device+0x40/0xf8
> [   47.334277]  __device_attach_driver+0x60/0xd4
> [   47.338638]  bus_for_each_drv+0xb4/0xdc
> [   47.342476]  __device_attach_async_helper+0x78/0xcc
> [   47.347357]  async_run_entry_fn+0x38/0xe0
> [   47.351369]  process_scheduled_works+0x1cc/0x2b8
> [   47.355991]  worker_thread+0x214/0x25c
> [   47.359744]  kthread+0xec/0xfc
> [   47.362804]  ret_from_fork+0x10/0x20
> "
> "
> [   47.575814]  pci_save_state+0xcc/0x224
> [   47.579567]  pci_pm_runtime_suspend+0x44/0x16c
> [   47.584013]  __rpm_callback+0x48/0x124
> [   47.587764]  rpm_callback+0x70/0x74
> [   47.591254]  rpm_suspend+0x26c/0x424
> [   47.594831]  rpm_idle+0x190/0x1c0
> [   47.598149]  pm_runtime_work+0x8c/0x9c
> [   47.601900]  process_scheduled_works+0x1cc/0x2b8
> [   47.606524]  worker_thread+0x214/0x25c
> [   47.610278]  kthread+0xec/0xfc
> [   47.613338]  ret_from_fork+0x10/0x20
The backtraces are collected at the very end of pci_update_resource() 
and pci_save_state() using WARN_ON(), so the timestamps do not match, 
but at least they include the call stack how those functions were 
reached when this problem occurred .

  reply	other threads:[~2024-10-12  0:59 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-12  0:48 [PATCH] [RFC] PCI/PM: Do not RPM suspend devices without drivers Marek Vasut
2024-10-12  0:59 ` Marek Vasut [this message]
2024-10-13 11:03 ` Lukas Wunner
2024-10-26  0:19   ` Marek Vasut
2024-10-28 17:52     ` Wysocki, Rafael J
2024-10-28 18:25       ` Marek Vasut
2024-10-29 18:57         ` Rafael J. Wysocki

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=a1cdad18-369e-4b12-afed-8b6b60f4d86f@denx.de \
    --to=marex@denx.de \
    --cc=bhelgaas@google.com \
    --cc=linux-pci@vger.kernel.org \
    --cc=rafael.j.wysocki@intel.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