mirror of
https://github.com/fail0verflow/switch-coreboot.git
synced 2025-05-04 01:39:18 -04:00
mtrr: only add prefetchable resources as WRCOMB for VGA devices
Be more conservative and only add VGA devices' prefetchable resources as write-combining in the address space. Previously all prefetchable memory was added as a write-combining memory type. Some hardware incorrectly advertises its BAR as prefetchable when it shouldn't be. A new memranges_add_resources_filter() function is added to provide additional filtering on device and resource. Change-Id: I3fc55b90d8c5b694c5aa9e2f34db1b4ef845ce10 Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/5169 Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com> Tested-by: build bot (Jenkins)
This commit is contained in:
parent
892728c65f
commit
ca4f4b8c9e
3 changed files with 45 additions and 6 deletions
|
@ -30,6 +30,7 @@
|
|||
#include <bootstate.h>
|
||||
#include <console/console.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <cpu/cpu.h>
|
||||
#include <cpu/x86/msr.h>
|
||||
#include <cpu/x86/mtrr.h>
|
||||
|
@ -154,6 +155,20 @@ static inline int range_entry_mtrr_type(struct range_entry *r)
|
|||
return range_entry_tag(r) & MTRR_TAG_MASK;
|
||||
}
|
||||
|
||||
static int filter_vga_wrcomb(struct device *dev, struct resource *res)
|
||||
{
|
||||
/* Only handle PCI devices. */
|
||||
if (dev->path.type != DEVICE_PATH_PCI)
|
||||
return 0;
|
||||
|
||||
/* Only handle VGA class devices. */
|
||||
if (((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA))
|
||||
return 0;
|
||||
|
||||
/* Add resource as write-combining in the address space. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct memranges *get_physical_address_space(void)
|
||||
{
|
||||
static struct memranges *addr_space;
|
||||
|
@ -181,8 +196,8 @@ static struct memranges *get_physical_address_space(void)
|
|||
* resources are appropriate for this MTRR type. */
|
||||
match = IORESOURCE_PREFETCH;
|
||||
mask |= match;
|
||||
memranges_add_resources(addr_space, mask, match,
|
||||
MTRR_TYPE_WRCOMB);
|
||||
memranges_add_resources_filter(addr_space, mask, match, MTRR_TYPE_WRCOMB,
|
||||
filter_vga_wrcomb);
|
||||
|
||||
#if CONFIG_CACHE_ROM
|
||||
/* Add a write-protect region covering the ROM size
|
||||
|
|
|
@ -94,6 +94,19 @@ void memranges_add_resources(struct memranges *ranges,
|
|||
unsigned long mask, unsigned long match,
|
||||
unsigned long tag);
|
||||
|
||||
/* Add memory resources that match with the corresponding mask and match but
|
||||
* also provide filter as additional check. The filter will return non-zero
|
||||
* to add the resource or zero to not add the resource. Each entry will be
|
||||
* tagged with the provided tag. e.g. To populate all cacheable memory
|
||||
* resources in the range with a filter:
|
||||
* memranges_add_resources_filter(range, IORESOURCE_CACHEABLE,
|
||||
* IORESROUCE_CACHEABLE, my_cacheable_tag, filter); */
|
||||
typedef int (*memrange_filter_t)(struct device *dev, struct resource *res);
|
||||
void memranges_add_resources_filter(struct memranges *ranges,
|
||||
unsigned long mask, unsigned long match,
|
||||
unsigned long tag,
|
||||
memrange_filter_t filter);
|
||||
|
||||
/* Fill all address ranges up to limit (exclusive) not covered by an entry by
|
||||
* inserting new entries with the provided tag. */
|
||||
void memranges_fill_holes_up_to(struct memranges *ranges,
|
||||
|
|
|
@ -252,6 +252,7 @@ void memranges_insert(struct memranges *ranges,
|
|||
struct collect_context {
|
||||
struct memranges *ranges;
|
||||
unsigned long tag;
|
||||
memrange_filter_t filter;
|
||||
};
|
||||
|
||||
static void collect_ranges(void *gp, struct device *dev, struct resource *res)
|
||||
|
@ -261,12 +262,14 @@ static void collect_ranges(void *gp, struct device *dev, struct resource *res)
|
|||
if (res->size == 0)
|
||||
return;
|
||||
|
||||
if (ctx->filter == NULL || ctx->filter(dev, res))
|
||||
memranges_insert(ctx->ranges, res->base, res->size, ctx->tag);
|
||||
}
|
||||
|
||||
void memranges_add_resources(struct memranges *ranges,
|
||||
void memranges_add_resources_filter(struct memranges *ranges,
|
||||
unsigned long mask, unsigned long match,
|
||||
unsigned long tag)
|
||||
unsigned long tag,
|
||||
memrange_filter_t filter)
|
||||
{
|
||||
struct collect_context context;
|
||||
|
||||
|
@ -276,9 +279,17 @@ void memranges_add_resources(struct memranges *ranges,
|
|||
|
||||
context.ranges = ranges;
|
||||
context.tag = tag;
|
||||
context.filter = filter;
|
||||
search_global_resources(mask, match, collect_ranges, &context);
|
||||
}
|
||||
|
||||
void memranges_add_resources(struct memranges *ranges,
|
||||
unsigned long mask, unsigned long match,
|
||||
unsigned long tag)
|
||||
{
|
||||
memranges_add_resources_filter(ranges, mask, match, tag, NULL);
|
||||
}
|
||||
|
||||
void memranges_init(struct memranges *ranges,
|
||||
unsigned long mask, unsigned long match,
|
||||
unsigned long tag)
|
||||
|
|
Loading…
Add table
Reference in a new issue