PCI: Retry BARs restoration for Type 0 headers only
Some shortcomings introduced into pci_restore_state() by commit26f41062f2
("PCI: check for pci bar restore completion and retry") have been fixed by recent commitebfc5b802f
("PCI: Fix regression in pci_restore_state(), v3"), but that commit treats all PCI devices as those with Type 0 configuration headers. That is not entirely correct, because Type 1 and Type 2 headers have different layouts. In particular, the area occupied by BARs in Type 0 config headers contains the secondary status register in Type 1 ones and it doesn't make sense to retry the restoration of that register even if the value read back from it after a write is not the same as the written one (it very well may be different). For this reason, make pci_restore_state() only retry the restoration of BARs for Type 0 config headers. This effectively makes it behave as before commit26f41062f2
for all header types except for Type 0. Tested-by: Mikko Vinni <mmvinni@yahoo.com> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
5191d566c0
commit
a6cb9ee7ca
1 changed files with 15 additions and 9 deletions
|
@ -991,8 +991,8 @@ static void pci_restore_config_dword(struct pci_dev *pdev, int offset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pci_restore_config_space(struct pci_dev *pdev, int start, int end,
|
static void pci_restore_config_space_range(struct pci_dev *pdev,
|
||||||
int retry)
|
int start, int end, int retry)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
|
@ -1002,6 +1002,18 @@ static void pci_restore_config_space(struct pci_dev *pdev, int start, int end,
|
||||||
retry);
|
retry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pci_restore_config_space(struct pci_dev *pdev)
|
||||||
|
{
|
||||||
|
if (pdev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
|
||||||
|
pci_restore_config_space_range(pdev, 10, 15, 0);
|
||||||
|
/* Restore BARs before the command register. */
|
||||||
|
pci_restore_config_space_range(pdev, 4, 9, 10);
|
||||||
|
pci_restore_config_space_range(pdev, 0, 3, 0);
|
||||||
|
} else {
|
||||||
|
pci_restore_config_space_range(pdev, 0, 15, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pci_restore_state - Restore the saved state of a PCI device
|
* pci_restore_state - Restore the saved state of a PCI device
|
||||||
* @dev: - PCI device that we're dealing with
|
* @dev: - PCI device that we're dealing with
|
||||||
|
@ -1015,13 +1027,7 @@ void pci_restore_state(struct pci_dev *dev)
|
||||||
pci_restore_pcie_state(dev);
|
pci_restore_pcie_state(dev);
|
||||||
pci_restore_ats_state(dev);
|
pci_restore_ats_state(dev);
|
||||||
|
|
||||||
pci_restore_config_space(dev, 10, 15, 0);
|
pci_restore_config_space(dev);
|
||||||
/*
|
|
||||||
* The Base Address register should be programmed before the command
|
|
||||||
* register(s)
|
|
||||||
*/
|
|
||||||
pci_restore_config_space(dev, 4, 9, 10);
|
|
||||||
pci_restore_config_space(dev, 0, 3, 0);
|
|
||||||
|
|
||||||
pci_restore_pcix_state(dev);
|
pci_restore_pcix_state(dev);
|
||||||
pci_restore_msi_state(dev);
|
pci_restore_msi_state(dev);
|
||||||
|
|
Loading…
Reference in a new issue