Add a helper routine to conditionally modify the start address of a
resource allocation from an x86 Host-PCI bridge driver so that it can be reused by the ACPI Host-PCI bridge driver (and eventually the MPTable Host-PCI bridge driver) instead of duplicating the same logic. Note that this means that hw.acpi.host_mem_start is now replaced with the hw.pci.host_mem_start tunable that was already used in the non-ACPI case. This also removes hw.acpi.host_mem_start on ia64 where it was not applicable (the implementation was very x86-specific). While here, adjust the logic to apply the new start address on any "wildcard" allocation even if that allocation comes from a subset of the allowable address range. Reviewed by: imp (1)
This commit is contained in:
parent
62b6e03adf
commit
38d7a61ba4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=223424
@ -302,35 +302,45 @@ legacy_pcib_write_ivar(device_t dev, device_t child, int which,
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper routine for x86 Host-PCI bridge driver resource allocation.
|
||||
* This is used to adjust the start address of wildcard allocation
|
||||
* requests to avoid low addresses that are known to be problematic.
|
||||
*
|
||||
* If no memory preference is given, use upper 32MB slot most BIOSes
|
||||
* use for their memory window. This is typically only used on older
|
||||
* laptops that don't have PCI busses behind a PCI bridge, so assuming
|
||||
* > 32MB is likely OK.
|
||||
*
|
||||
* However, this can cause problems for other chipsets, so we make
|
||||
* this tunable by hw.pci.host_mem_start.
|
||||
*/
|
||||
SYSCTL_DECL(_hw_pci);
|
||||
|
||||
static unsigned long legacy_host_mem_start = 0x80000000;
|
||||
TUNABLE_ULONG("hw.pci.host_mem_start", &legacy_host_mem_start);
|
||||
SYSCTL_ULONG(_hw_pci, OID_AUTO, host_mem_start, CTLFLAG_RDTUN,
|
||||
&legacy_host_mem_start, 0x80000000,
|
||||
"Limit the host bridge memory to being above this address. Must be\n\
|
||||
set at boot via a tunable.");
|
||||
static unsigned long host_mem_start = 0x80000000;
|
||||
TUNABLE_ULONG("hw.pci.host_mem_start", &host_mem_start);
|
||||
SYSCTL_ULONG(_hw_pci, OID_AUTO, host_mem_start, CTLFLAG_RDTUN, &host_mem_start,
|
||||
0, "Limit the host bridge memory to being above this address.");
|
||||
|
||||
u_long
|
||||
hostb_alloc_start(int type, u_long start, u_long end, u_long count)
|
||||
{
|
||||
|
||||
if (start + count - 1 != end) {
|
||||
if (type == SYS_RES_MEMORY && start < host_mem_start)
|
||||
start = host_mem_start;
|
||||
if (type == SYS_RES_IOPORT && start < 0x1000)
|
||||
start = 0x1000;
|
||||
}
|
||||
return (start);
|
||||
}
|
||||
|
||||
struct resource *
|
||||
legacy_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||
u_long start, u_long end, u_long count, u_int flags)
|
||||
{
|
||||
/*
|
||||
* If no memory preference is given, use upper 32MB slot most
|
||||
* bioses use for their memory window. Typically other bridges
|
||||
* before us get in the way to assert their preferences on memory.
|
||||
* Hardcoding like this sucks, so a more MD/MI way needs to be
|
||||
* found to do it. This is typically only used on older laptops
|
||||
* that don't have pci busses behind pci bridge, so assuming > 32MB
|
||||
* is liekly OK.
|
||||
*
|
||||
* However, this can cause problems for other chipsets, so we make
|
||||
* this tunable by hw.pci.host_mem_start.
|
||||
*/
|
||||
if (type == SYS_RES_MEMORY && start == 0UL && end == ~0UL)
|
||||
start = legacy_host_mem_start;
|
||||
if (type == SYS_RES_IOPORT && start == 0UL && end == ~0UL)
|
||||
start = 0x1000;
|
||||
|
||||
start = hostb_alloc_start(type, start, end, count);
|
||||
return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
|
||||
count, flags));
|
||||
}
|
||||
|
@ -357,32 +357,14 @@ acpi_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
|
||||
return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
|
||||
}
|
||||
|
||||
static u_long acpi_host_mem_start = 0x80000000;
|
||||
TUNABLE_ULONG("hw.acpi.host_mem_start", &acpi_host_mem_start);
|
||||
|
||||
struct resource *
|
||||
acpi_pcib_acpi_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||
u_long start, u_long end, u_long count, u_int flags)
|
||||
{
|
||||
/*
|
||||
* If no memory preference is given, use upper 32MB slot most
|
||||
* bioses use for their memory window. Typically other bridges
|
||||
* before us get in the way to assert their preferences on memory.
|
||||
* Hardcoding like this sucks, so a more MD/MI way needs to be
|
||||
* found to do it. This is typically only used on older laptops
|
||||
* that don't have pci busses behind pci bridge, so assuming > 32MB
|
||||
* is likely OK.
|
||||
*
|
||||
* PCI-PCI bridges may allocate smaller ranges for their windows,
|
||||
* but the heuristics here should apply to those, so we allow
|
||||
* several different end addresses.
|
||||
*/
|
||||
if (type == SYS_RES_MEMORY && start == 0UL && (end == ~0UL ||
|
||||
end == 0xffffffff))
|
||||
start = acpi_host_mem_start;
|
||||
if (type == SYS_RES_IOPORT && start == 0UL && (end == ~0UL ||
|
||||
end == 0xffff || end == 0xffffffff))
|
||||
start = 0x1000;
|
||||
|
||||
#if defined(__i386__) || defined(__amd64__)
|
||||
start = hostb_alloc_start(type, start, end, count);
|
||||
#endif
|
||||
return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
|
||||
count, flags));
|
||||
}
|
||||
|
@ -519,35 +519,45 @@ legacy_pcib_write_ivar(device_t dev, device_t child, int which,
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper routine for x86 Host-PCI bridge driver resource allocation.
|
||||
* This is used to adjust the start address of wildcard allocation
|
||||
* requests to avoid low addresses that are known to be problematic.
|
||||
*
|
||||
* If no memory preference is given, use upper 32MB slot most BIOSes
|
||||
* use for their memory window. This is typically only used on older
|
||||
* laptops that don't have PCI busses behind a PCI bridge, so assuming
|
||||
* > 32MB is likely OK.
|
||||
*
|
||||
* However, this can cause problems for other chipsets, so we make
|
||||
* this tunable by hw.pci.host_mem_start.
|
||||
*/
|
||||
SYSCTL_DECL(_hw_pci);
|
||||
|
||||
static unsigned long legacy_host_mem_start = 0x80000000;
|
||||
TUNABLE_ULONG("hw.pci.host_mem_start", &legacy_host_mem_start);
|
||||
SYSCTL_ULONG(_hw_pci, OID_AUTO, host_mem_start, CTLFLAG_RDTUN,
|
||||
&legacy_host_mem_start, 0x80000000,
|
||||
"Limit the host bridge memory to being above this address. Must be\n\
|
||||
set at boot via a tunable.");
|
||||
static unsigned long host_mem_start = 0x80000000;
|
||||
TUNABLE_ULONG("hw.pci.host_mem_start", &host_mem_start);
|
||||
SYSCTL_ULONG(_hw_pci, OID_AUTO, host_mem_start, CTLFLAG_RDTUN, &host_mem_start,
|
||||
0, "Limit the host bridge memory to being above this address.");
|
||||
|
||||
u_long
|
||||
hostb_alloc_start(int type, u_long start, u_long end, u_long count)
|
||||
{
|
||||
|
||||
if (start + count - 1 != end) {
|
||||
if (type == SYS_RES_MEMORY && start < host_mem_start)
|
||||
start = host_mem_start;
|
||||
if (type == SYS_RES_IOPORT && start < 0x1000)
|
||||
start = 0x1000;
|
||||
}
|
||||
return (start);
|
||||
}
|
||||
|
||||
struct resource *
|
||||
legacy_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||
u_long start, u_long end, u_long count, u_int flags)
|
||||
{
|
||||
/*
|
||||
* If no memory preference is given, use upper 32MB slot most
|
||||
* bioses use for their memory window. Typically other bridges
|
||||
* before us get in the way to assert their preferences on memory.
|
||||
* Hardcoding like this sucks, so a more MD/MI way needs to be
|
||||
* found to do it. This is typically only used on older laptops
|
||||
* that don't have pci busses behind pci bridge, so assuming > 32MB
|
||||
* is liekly OK.
|
||||
*
|
||||
* However, this can cause problems for other chipsets, so we make
|
||||
* this tunable by hw.pci.host_mem_start.
|
||||
*/
|
||||
if (type == SYS_RES_MEMORY && start == 0UL && end == ~0UL)
|
||||
start = legacy_host_mem_start;
|
||||
if (type == SYS_RES_IOPORT && start == 0UL && end == ~0UL)
|
||||
start = 0x1000;
|
||||
|
||||
start = hostb_alloc_start(type, start, end, count);
|
||||
return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
|
||||
count, flags));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user