PCI: disable mmio during bar sizing
It is a known issue that mmio decoding shall be disabled while doing PCI bar sizing. Host bridge and other devices (PCI PIC) shall be excluded for certain platforms. This patch mainly comes from Mathew Willcox's patch in http://kerneltrap.org/mailarchive/linux-kernel/2007/9/13/258969. A new flag bit "mmio_alway_on" is added to pci_dev with the intention that devices with their mmio decoding cannot be disabled during BAR sizing shall have this bit set, preferrablly in their quirks. Without this patch, Intel Moorestown platform graphics unit will be corrupted during bar sizing activities. Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
parent
fcd097f31a
commit
253d2e5498
@ -163,9 +163,16 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
||||
struct resource *res, unsigned int pos)
|
||||
{
|
||||
u32 l, sz, mask;
|
||||
u16 orig_cmd;
|
||||
|
||||
mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
|
||||
|
||||
if (!dev->mmio_always_on) {
|
||||
pci_read_config_word(dev, PCI_COMMAND, &orig_cmd);
|
||||
pci_write_config_word(dev, PCI_COMMAND,
|
||||
orig_cmd & ~(PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
|
||||
}
|
||||
|
||||
res->name = pci_name(dev);
|
||||
|
||||
pci_read_config_dword(dev, pos, &l);
|
||||
@ -173,6 +180,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
||||
pci_read_config_dword(dev, pos, &sz);
|
||||
pci_write_config_dword(dev, pos, l);
|
||||
|
||||
if (!dev->mmio_always_on)
|
||||
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
|
||||
|
||||
/*
|
||||
* All bits set in sz means the device isn't working properly.
|
||||
* If the BAR isn't implemented, all bits must be 0. If it's a
|
||||
|
@ -91,6 +91,19 @@ static void __devinit quirk_resource_alignment(struct pci_dev *dev)
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_resource_alignment);
|
||||
|
||||
/*
|
||||
* Decoding should be disabled for a PCI device during BAR sizing to avoid
|
||||
* conflict. But doing so may cause problems on host bridge and perhaps other
|
||||
* key system devices. For devices that need to have mmio decoding always-on,
|
||||
* we need to set the dev->mmio_always_on bit.
|
||||
*/
|
||||
static void __devinit quirk_mmio_always_on(struct pci_dev *dev)
|
||||
{
|
||||
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
|
||||
dev->mmio_always_on = 1;
|
||||
}
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, quirk_mmio_always_on);
|
||||
|
||||
/* The Mellanox Tavor device gives false positive parity errors
|
||||
* Mark this device with a broken_parity_status, to allow
|
||||
* PCI scanning code to "skip" this now blacklisted device.
|
||||
|
@ -270,6 +270,8 @@ struct pci_dev {
|
||||
unsigned int d1_support:1; /* Low power state D1 is supported */
|
||||
unsigned int d2_support:1; /* Low power state D2 is supported */
|
||||
unsigned int no_d1d2:1; /* Only allow D0 and D3 */
|
||||
unsigned int mmio_always_on:1; /* disallow turning off io/mem
|
||||
decoding during bar sizing */
|
||||
unsigned int wakeup_prepared:1;
|
||||
unsigned int d3_delay; /* D3->D0 transition time in ms */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user