Merge branch 'pci/enumeration'
- Probe bridge window attributes only once at enumeration-time to fix device accesses during rescan (Bjorn Helgaas) - Return BAR size (not "size -1 ") from pci_size() to simplify code (Du Changbin) - Use config header type (not class code) identify bridges more reliably (Honghui Zhang) - Work around Intel Denverton incorrect Trace Hub BAR size reporting (Alexander Shishkin) * pci/enumeration: x86/PCI: Fixup RTIT_BAR of Intel Denverton Trace Hub PCI: Rely on config space header type, not class code PCI: Make pci_size() return real BAR size PCI: Probe bridge window attributes once at enumeration-time
This commit is contained in:
commit
5d130e3dd8
|
@ -635,6 +635,22 @@ static void quirk_no_aersid(struct pci_dev *pdev)
|
|||
DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
|
||||
PCI_CLASS_BRIDGE_PCI, 8, quirk_no_aersid);
|
||||
|
||||
static void quirk_intel_th_dnv(struct pci_dev *dev)
|
||||
{
|
||||
struct resource *r = &dev->resource[4];
|
||||
|
||||
/*
|
||||
* Denverton reports 2k of RTIT_BAR (intel_th resource 4), which
|
||||
* appears to be 4 MB in reality.
|
||||
*/
|
||||
if (r->end == r->start + 0x7ff) {
|
||||
r->start = 0;
|
||||
r->end = 0x3fffff;
|
||||
r->flags |= IORESOURCE_UNSET;
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x19e1, quirk_intel_th_dnv);
|
||||
|
||||
#ifdef CONFIG_PHYS_ADDR_T_64BIT
|
||||
|
||||
#define AMD_141b_MMIO_BASE(x) (0x80 + (x) * 0x8)
|
||||
|
|
|
@ -6049,8 +6049,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
|
|||
* to enable the kernel to reassign new resource
|
||||
* window later on.
|
||||
*/
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
|
||||
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) {
|
||||
r = &dev->resource[i];
|
||||
if (!(r->flags & IORESOURCE_MEM))
|
||||
|
|
|
@ -121,13 +121,13 @@ static u64 pci_size(u64 base, u64 maxbase, u64 mask)
|
|||
* Get the lowest of them to find the decode size, and from that
|
||||
* the extent.
|
||||
*/
|
||||
size = (size & ~(size-1)) - 1;
|
||||
size = size & ~(size-1);
|
||||
|
||||
/*
|
||||
* base == maxbase can be valid only if the BAR has already been
|
||||
* programmed with all 1s.
|
||||
*/
|
||||
if (base == maxbase && ((base | size) & mask) != mask)
|
||||
if (base == maxbase && ((base | (size - 1)) & mask) != mask)
|
||||
return 0;
|
||||
|
||||
return size;
|
||||
|
@ -278,7 +278,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
|||
/* Above 32-bit boundary; try to reallocate */
|
||||
res->flags |= IORESOURCE_UNSET;
|
||||
res->start = 0;
|
||||
res->end = sz64;
|
||||
res->end = sz64 - 1;
|
||||
pci_info(dev, "reg 0x%x: can't handle BAR above 4GB (bus address %#010llx)\n",
|
||||
pos, (unsigned long long)l64);
|
||||
goto out;
|
||||
|
@ -286,7 +286,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
|||
}
|
||||
|
||||
region.start = l64;
|
||||
region.end = l64 + sz64;
|
||||
region.end = l64 + sz64 - 1;
|
||||
|
||||
pcibios_bus_to_resource(dev->bus, res, ®ion);
|
||||
pcibios_resource_to_bus(dev->bus, &inverted_region, res);
|
||||
|
@ -348,6 +348,57 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
|
|||
}
|
||||
}
|
||||
|
||||
static void pci_read_bridge_windows(struct pci_dev *bridge)
|
||||
{
|
||||
u16 io;
|
||||
u32 pmem, tmp;
|
||||
|
||||
pci_read_config_word(bridge, PCI_IO_BASE, &io);
|
||||
if (!io) {
|
||||
pci_write_config_word(bridge, PCI_IO_BASE, 0xe0f0);
|
||||
pci_read_config_word(bridge, PCI_IO_BASE, &io);
|
||||
pci_write_config_word(bridge, PCI_IO_BASE, 0x0);
|
||||
}
|
||||
if (io)
|
||||
bridge->io_window = 1;
|
||||
|
||||
/*
|
||||
* DECchip 21050 pass 2 errata: the bridge may miss an address
|
||||
* disconnect boundary by one PCI data phase. Workaround: do not
|
||||
* use prefetching on this device.
|
||||
*/
|
||||
if (bridge->vendor == PCI_VENDOR_ID_DEC && bridge->device == 0x0001)
|
||||
return;
|
||||
|
||||
pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
|
||||
if (!pmem) {
|
||||
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE,
|
||||
0xffe0fff0);
|
||||
pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
|
||||
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0);
|
||||
}
|
||||
if (!pmem)
|
||||
return;
|
||||
|
||||
bridge->pref_window = 1;
|
||||
|
||||
if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
|
||||
|
||||
/*
|
||||
* Bridge claims to have a 64-bit prefetchable memory
|
||||
* window; verify that the upper bits are actually
|
||||
* writable.
|
||||
*/
|
||||
pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &pmem);
|
||||
pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32,
|
||||
0xffffffff);
|
||||
pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &tmp);
|
||||
pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, pmem);
|
||||
if (tmp)
|
||||
bridge->pref_64_window = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void pci_read_bridge_io(struct pci_bus *child)
|
||||
{
|
||||
struct pci_dev *dev = child->self;
|
||||
|
@ -1728,9 +1779,6 @@ int pci_setup_device(struct pci_dev *dev)
|
|||
break;
|
||||
|
||||
case PCI_HEADER_TYPE_BRIDGE: /* bridge header */
|
||||
if (class != PCI_CLASS_BRIDGE_PCI)
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* The PCI-to-PCI bridge spec requires that subtractive
|
||||
* decoding (i.e. transparent) bridge must have programming
|
||||
|
@ -1739,6 +1787,7 @@ int pci_setup_device(struct pci_dev *dev)
|
|||
pci_read_irq(dev);
|
||||
dev->transparent = ((dev->class & 0xff) == 1);
|
||||
pci_read_bases(dev, 2, PCI_ROM_ADDRESS1);
|
||||
pci_read_bridge_windows(dev);
|
||||
set_pcie_hotplug_bridge(dev);
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_SSVID);
|
||||
if (pos) {
|
||||
|
|
|
@ -735,58 +735,21 @@ int pci_claim_bridge_resource(struct pci_dev *bridge, int i)
|
|||
base/limit registers must be read-only and read as 0. */
|
||||
static void pci_bridge_check_ranges(struct pci_bus *bus)
|
||||
{
|
||||
u16 io;
|
||||
u32 pmem;
|
||||
struct pci_dev *bridge = bus->self;
|
||||
struct resource *b_res;
|
||||
struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
|
||||
|
||||
b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
|
||||
b_res[1].flags |= IORESOURCE_MEM;
|
||||
|
||||
pci_read_config_word(bridge, PCI_IO_BASE, &io);
|
||||
if (!io) {
|
||||
pci_write_config_word(bridge, PCI_IO_BASE, 0xe0f0);
|
||||
pci_read_config_word(bridge, PCI_IO_BASE, &io);
|
||||
pci_write_config_word(bridge, PCI_IO_BASE, 0x0);
|
||||
}
|
||||
if (io)
|
||||
if (bridge->io_window)
|
||||
b_res[0].flags |= IORESOURCE_IO;
|
||||
|
||||
/* DECchip 21050 pass 2 errata: the bridge may miss an address
|
||||
disconnect boundary by one PCI data phase.
|
||||
Workaround: do not use prefetching on this device. */
|
||||
if (bridge->vendor == PCI_VENDOR_ID_DEC && bridge->device == 0x0001)
|
||||
return;
|
||||
|
||||
pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
|
||||
if (!pmem) {
|
||||
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE,
|
||||
0xffe0fff0);
|
||||
pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
|
||||
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0);
|
||||
}
|
||||
if (pmem) {
|
||||
if (bridge->pref_window) {
|
||||
b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
|
||||
if ((pmem & PCI_PREF_RANGE_TYPE_MASK) ==
|
||||
PCI_PREF_RANGE_TYPE_64) {
|
||||
if (bridge->pref_64_window) {
|
||||
b_res[2].flags |= IORESOURCE_MEM_64;
|
||||
b_res[2].flags |= PCI_PREF_RANGE_TYPE_64;
|
||||
}
|
||||
}
|
||||
|
||||
/* double check if bridge does support 64 bit pref */
|
||||
if (b_res[2].flags & IORESOURCE_MEM_64) {
|
||||
u32 mem_base_hi, tmp;
|
||||
pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32,
|
||||
&mem_base_hi);
|
||||
pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32,
|
||||
0xffffffff);
|
||||
pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &tmp);
|
||||
if (!tmp)
|
||||
b_res[2].flags &= ~IORESOURCE_MEM_64;
|
||||
pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32,
|
||||
mem_base_hi);
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper function for sizing routines: find first available
|
||||
|
@ -1223,12 +1186,12 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
|
|||
if (!b)
|
||||
continue;
|
||||
|
||||
switch (dev->class >> 8) {
|
||||
case PCI_CLASS_BRIDGE_CARDBUS:
|
||||
switch (dev->hdr_type) {
|
||||
case PCI_HEADER_TYPE_CARDBUS:
|
||||
pci_bus_size_cardbus(b, realloc_head);
|
||||
break;
|
||||
|
||||
case PCI_CLASS_BRIDGE_PCI:
|
||||
case PCI_HEADER_TYPE_BRIDGE:
|
||||
default:
|
||||
__pci_bus_size_bridges(b, realloc_head);
|
||||
break;
|
||||
|
@ -1239,12 +1202,12 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
|
|||
if (pci_is_root_bus(bus))
|
||||
return;
|
||||
|
||||
switch (bus->self->class >> 8) {
|
||||
case PCI_CLASS_BRIDGE_CARDBUS:
|
||||
switch (bus->self->hdr_type) {
|
||||
case PCI_HEADER_TYPE_CARDBUS:
|
||||
/* don't size cardbuses yet. */
|
||||
break;
|
||||
|
||||
case PCI_CLASS_BRIDGE_PCI:
|
||||
case PCI_HEADER_TYPE_BRIDGE:
|
||||
pci_bridge_check_ranges(bus);
|
||||
if (bus->self->is_hotplug_bridge) {
|
||||
additional_io_size = pci_hotplug_io_size;
|
||||
|
@ -1393,13 +1356,13 @@ void __pci_bus_assign_resources(const struct pci_bus *bus,
|
|||
|
||||
__pci_bus_assign_resources(b, realloc_head, fail_head);
|
||||
|
||||
switch (dev->class >> 8) {
|
||||
case PCI_CLASS_BRIDGE_PCI:
|
||||
switch (dev->hdr_type) {
|
||||
case PCI_HEADER_TYPE_BRIDGE:
|
||||
if (!pci_is_enabled(dev))
|
||||
pci_setup_bridge(b);
|
||||
break;
|
||||
|
||||
case PCI_CLASS_BRIDGE_CARDBUS:
|
||||
case PCI_HEADER_TYPE_CARDBUS:
|
||||
pci_setup_cardbus(b);
|
||||
break;
|
||||
|
||||
|
|
|
@ -373,6 +373,9 @@ struct pci_dev {
|
|||
bool match_driver; /* Skip attaching driver */
|
||||
|
||||
unsigned int transparent:1; /* Subtractive decode bridge */
|
||||
unsigned int io_window:1; /* Bridge has I/O window */
|
||||
unsigned int pref_window:1; /* Bridge has pref mem window */
|
||||
unsigned int pref_64_window:1; /* Pref mem window is 64-bit */
|
||||
unsigned int multifunction:1; /* Multi-function device */
|
||||
|
||||
unsigned int is_busmaster:1; /* Is busmaster */
|
||||
|
|
Loading…
Reference in New Issue