[+cc Thorsten, thanks for the reminder!]

On Wed, Apr 15, 2026 at 05:56:06PM +0200, Lukas Wunner wrote:
> Bernd reports passthrough failure of a Digital Devices Cine S2 V6 DVB
> adapter plugged into an ASRock X570S PG Riptide board with BIOS version
> P5.41 (09/07/2023):
> 
>   ddbridge 0000:05:00.0: detected Digital Devices Cine S2 V6 DVB adapter
>   ddbridge 0000:05:00.0: cannot read registers
>   ddbridge 0000:05:00.0: fail
> 
> BIOS assigns an incorrect BAR to the DVB adapter which doesn't fit into
> the upstream bridge window.  The kernel corrects the BAR assignment:
> 
>   pci 0000:07:00.0: BAR 0 [mem 0xfffffffffc500000-0xfffffffffc50ffff 64bit]: 
> can't claim; no compatible bridge window
>   pci 0000:07:00.0: BAR 0 [mem 0xfc500000-0xfc50ffff 64bit]: assigned
> 
> Correction of the BAR assignment happens in an x86-specific fs_initcall,
> pcibios_assign_resources(), after device enumeration in a subsys_initcall.
> This order was introduced at the behest of Linus in 2004:
> 
>     https://git.kernel.org/tglx/history/c/a06a30144bbc
> 
> No other architecture performs such a late BAR correction.
> 
> Bernd bisected the issue to commit a2f1e22390ac ("PCI/ERR: Ensure error
> recoverability at all times"), but it only occurs in the absence of commit
> 4d4c10f763d7 ("PCI: Explicitly put devices into D0 when initializing").
> This combination exists in stable kernel v6.12.70, but not in mainline,
> hence Bernd cannot reproduce the issue with mainline.
> 
> Since a2f1e22390ac, config space is saved on enumeration, prior to BAR
> correction.  Upon passthrough, the corrected BAR is overwritten with the
> incorrect saved value by:
> 
>   vfio_pci_core_register_device()
>     vfio_pci_set_power_state()
>       pci_restore_state()
> 
> But only if the device's current_state is PCI_UNKNOWN, as it was prior to
> commit 4d4c10f763d7.  Since the commit, it is PCI_D0, which changes the
> behavior of vfio_pci_set_power_state() to no longer restore the state
> without saving it first.
> 
> Alexandre is reporting the same issue as Bernd, but in his case, mainline
> is affected as well.  The difference is that on Alexandre's system, the
> host kernel binds a driver to the device which is unbound prior to
> passthrough, whereas on Bernd's system no driver gets bound by the host
> kernel.
> 
> Unbinding sets current_state to PCI_UNKNOWN in pci_device_remove(), so
> when vfio-pci is subsequently bound to the device, pci_restore_state() is
> once again called without invoking pci_save_state() first.
> 
> To robustly fix the issue, always update saved_config_space upon resource
> assignment.
> 
> Reported-by: Bernd Schumacher <[email protected]>
> Tested-by: Bernd Schumacher <[email protected]>
> Closes: https://lore.kernel.org/r/[email protected]/
> Reported-by: Alexandre N. <[email protected]>
> Tested-by: Alexandre N. <[email protected]>
> Closes: 
> https://lore.kernel.org/r/[email protected]/
> Fixes: a2f1e22390ac ("PCI/ERR: Ensure error recoverability at all times")
> Signed-off-by: Lukas Wunner <[email protected]>
> Cc: [email protected] # v6.12+

a2f1e22390ac appeared in v6.19.  Applied this fix to pci/for-linus for
v7.1, thanks!

> ---
>  drivers/pci/setup-res.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
> index e5fcadf..1769ba9 100644
> --- a/drivers/pci/setup-res.c
> +++ b/drivers/pci/setup-res.c
> @@ -102,6 +102,7 @@ static void pci_std_update_resource(struct pci_dev *dev, 
> int resno)
>       }
>  
>       pci_write_config_dword(dev, reg, new);
> +     dev->saved_config_space[reg / 4] = new;
>       pci_read_config_dword(dev, reg, &check);
>  
>       if ((new ^ check) & mask) {
> @@ -112,6 +113,7 @@ static void pci_std_update_resource(struct pci_dev *dev, 
> int resno)
>       if (res->flags & IORESOURCE_MEM_64) {
>               new = region.start >> 16 >> 16;
>               pci_write_config_dword(dev, reg + 4, new);
> +             dev->saved_config_space[(reg + 4) / 4] = new;
>               pci_read_config_dword(dev, reg + 4, &check);
>               if (check != new) {
>                       pci_err(dev, "%s: error updating (high %#010x != 
> %#010x)\n",
> -- 
> 2.51.0
> 

Reply via email to