Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6cb9ee7 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Linus Torvalds
Browse files

PCI: Retry BARs restoration for Type 0 headers only



Some shortcomings introduced into pci_restore_state() by commit
26f41062 ("PCI: check for pci bar restore completion and retry")
have been fixed by recent commit ebfc5b80 ("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 commit 26f41062 for all header types except for Type 0.

Tested-by: default avatarMikko Vinni <mmvinni@yahoo.com>
Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 5191d566
Loading
Loading
Loading
Loading
+15 −9
Original line number Original line Diff line number Diff line
@@ -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);