Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pullx86 core platform updates from Peter Anvin: "This is the x86/platform branch with the objectionable IOSF patches removed. What is left is proper memory handling for Intel GPUs, and a change to the Calgary IOMMU code which will be required to make kexec work sanely on those platforms after some upcoming kexec changes" * 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86, calgary: Use 8M TCE table size by default x86/gpu: Print the Intel graphics stolen memory range x86/gpu: Add Intel graphics stolen memory quirk for gen2 platforms x86/gpu: Add vfunc for Intel graphics stolen memory base address
This commit is contained in:
commit
40e9963e62
|
@ -225,7 +225,7 @@ static void __init intel_remapping_check(int num, int slot, int func)
|
|||
*
|
||||
* And yes, so far on current devices the base addr is always under 4G.
|
||||
*/
|
||||
static u32 __init intel_stolen_base(int num, int slot, int func)
|
||||
static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_size)
|
||||
{
|
||||
u32 base;
|
||||
|
||||
|
@ -244,6 +244,114 @@ static u32 __init intel_stolen_base(int num, int slot, int func)
|
|||
#define MB(x) (KB (KB (x)))
|
||||
#define GB(x) (MB (KB (x)))
|
||||
|
||||
static size_t __init i830_tseg_size(void)
|
||||
{
|
||||
u8 tmp = read_pci_config_byte(0, 0, 0, I830_ESMRAMC);
|
||||
|
||||
if (!(tmp & TSEG_ENABLE))
|
||||
return 0;
|
||||
|
||||
if (tmp & I830_TSEG_SIZE_1M)
|
||||
return MB(1);
|
||||
else
|
||||
return KB(512);
|
||||
}
|
||||
|
||||
static size_t __init i845_tseg_size(void)
|
||||
{
|
||||
u8 tmp = read_pci_config_byte(0, 0, 0, I845_ESMRAMC);
|
||||
|
||||
if (!(tmp & TSEG_ENABLE))
|
||||
return 0;
|
||||
|
||||
switch (tmp & I845_TSEG_SIZE_MASK) {
|
||||
case I845_TSEG_SIZE_512K:
|
||||
return KB(512);
|
||||
case I845_TSEG_SIZE_1M:
|
||||
return MB(1);
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t __init i85x_tseg_size(void)
|
||||
{
|
||||
u8 tmp = read_pci_config_byte(0, 0, 0, I85X_ESMRAMC);
|
||||
|
||||
if (!(tmp & TSEG_ENABLE))
|
||||
return 0;
|
||||
|
||||
return MB(1);
|
||||
}
|
||||
|
||||
static size_t __init i830_mem_size(void)
|
||||
{
|
||||
return read_pci_config_byte(0, 0, 0, I830_DRB3) * MB(32);
|
||||
}
|
||||
|
||||
static size_t __init i85x_mem_size(void)
|
||||
{
|
||||
return read_pci_config_byte(0, 0, 1, I85X_DRB3) * MB(32);
|
||||
}
|
||||
|
||||
/*
|
||||
* On 830/845/85x the stolen memory base isn't available in any
|
||||
* register. We need to calculate it as TOM-TSEG_SIZE-stolen_size.
|
||||
*/
|
||||
static u32 __init i830_stolen_base(int num, int slot, int func, size_t stolen_size)
|
||||
{
|
||||
return i830_mem_size() - i830_tseg_size() - stolen_size;
|
||||
}
|
||||
|
||||
static u32 __init i845_stolen_base(int num, int slot, int func, size_t stolen_size)
|
||||
{
|
||||
return i830_mem_size() - i845_tseg_size() - stolen_size;
|
||||
}
|
||||
|
||||
static u32 __init i85x_stolen_base(int num, int slot, int func, size_t stolen_size)
|
||||
{
|
||||
return i85x_mem_size() - i85x_tseg_size() - stolen_size;
|
||||
}
|
||||
|
||||
static u32 __init i865_stolen_base(int num, int slot, int func, size_t stolen_size)
|
||||
{
|
||||
/*
|
||||
* FIXME is the graphics stolen memory region
|
||||
* always at TOUD? Ie. is it always the last
|
||||
* one to be allocated by the BIOS?
|
||||
*/
|
||||
return read_pci_config_16(0, 0, 0, I865_TOUD) << 16;
|
||||
}
|
||||
|
||||
static size_t __init i830_stolen_size(int num, int slot, int func)
|
||||
{
|
||||
size_t stolen_size;
|
||||
u16 gmch_ctrl;
|
||||
|
||||
gmch_ctrl = read_pci_config_16(0, 0, 0, I830_GMCH_CTRL);
|
||||
|
||||
switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
|
||||
case I830_GMCH_GMS_STOLEN_512:
|
||||
stolen_size = KB(512);
|
||||
break;
|
||||
case I830_GMCH_GMS_STOLEN_1024:
|
||||
stolen_size = MB(1);
|
||||
break;
|
||||
case I830_GMCH_GMS_STOLEN_8192:
|
||||
stolen_size = MB(8);
|
||||
break;
|
||||
case I830_GMCH_GMS_LOCAL:
|
||||
/* local memory isn't part of the normal address space */
|
||||
stolen_size = 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return stolen_size;
|
||||
}
|
||||
|
||||
static size_t __init gen3_stolen_size(int num, int slot, int func)
|
||||
{
|
||||
size_t stolen_size;
|
||||
|
@ -310,7 +418,7 @@ static size_t __init gen6_stolen_size(int num, int slot, int func)
|
|||
return gmch_ctrl << 25; /* 32 MB units */
|
||||
}
|
||||
|
||||
static inline size_t gen8_stolen_size(int num, int slot, int func)
|
||||
static size_t gen8_stolen_size(int num, int slot, int func)
|
||||
{
|
||||
u16 gmch_ctrl;
|
||||
|
||||
|
@ -320,31 +428,74 @@ static inline size_t gen8_stolen_size(int num, int slot, int func)
|
|||
return gmch_ctrl << 25; /* 32 MB units */
|
||||
}
|
||||
|
||||
typedef size_t (*stolen_size_fn)(int num, int slot, int func);
|
||||
|
||||
struct intel_stolen_funcs {
|
||||
size_t (*size)(int num, int slot, int func);
|
||||
u32 (*base)(int num, int slot, int func, size_t size);
|
||||
};
|
||||
|
||||
static const struct intel_stolen_funcs i830_stolen_funcs = {
|
||||
.base = i830_stolen_base,
|
||||
.size = i830_stolen_size,
|
||||
};
|
||||
|
||||
static const struct intel_stolen_funcs i845_stolen_funcs = {
|
||||
.base = i845_stolen_base,
|
||||
.size = i830_stolen_size,
|
||||
};
|
||||
|
||||
static const struct intel_stolen_funcs i85x_stolen_funcs = {
|
||||
.base = i85x_stolen_base,
|
||||
.size = gen3_stolen_size,
|
||||
};
|
||||
|
||||
static const struct intel_stolen_funcs i865_stolen_funcs = {
|
||||
.base = i865_stolen_base,
|
||||
.size = gen3_stolen_size,
|
||||
};
|
||||
|
||||
static const struct intel_stolen_funcs gen3_stolen_funcs = {
|
||||
.base = intel_stolen_base,
|
||||
.size = gen3_stolen_size,
|
||||
};
|
||||
|
||||
static const struct intel_stolen_funcs gen6_stolen_funcs = {
|
||||
.base = intel_stolen_base,
|
||||
.size = gen6_stolen_size,
|
||||
};
|
||||
|
||||
static const struct intel_stolen_funcs gen8_stolen_funcs = {
|
||||
.base = intel_stolen_base,
|
||||
.size = gen8_stolen_size,
|
||||
};
|
||||
|
||||
static struct pci_device_id intel_stolen_ids[] __initdata = {
|
||||
INTEL_I915G_IDS(gen3_stolen_size),
|
||||
INTEL_I915GM_IDS(gen3_stolen_size),
|
||||
INTEL_I945G_IDS(gen3_stolen_size),
|
||||
INTEL_I945GM_IDS(gen3_stolen_size),
|
||||
INTEL_VLV_M_IDS(gen6_stolen_size),
|
||||
INTEL_VLV_D_IDS(gen6_stolen_size),
|
||||
INTEL_PINEVIEW_IDS(gen3_stolen_size),
|
||||
INTEL_I965G_IDS(gen3_stolen_size),
|
||||
INTEL_G33_IDS(gen3_stolen_size),
|
||||
INTEL_I965GM_IDS(gen3_stolen_size),
|
||||
INTEL_GM45_IDS(gen3_stolen_size),
|
||||
INTEL_G45_IDS(gen3_stolen_size),
|
||||
INTEL_IRONLAKE_D_IDS(gen3_stolen_size),
|
||||
INTEL_IRONLAKE_M_IDS(gen3_stolen_size),
|
||||
INTEL_SNB_D_IDS(gen6_stolen_size),
|
||||
INTEL_SNB_M_IDS(gen6_stolen_size),
|
||||
INTEL_IVB_M_IDS(gen6_stolen_size),
|
||||
INTEL_IVB_D_IDS(gen6_stolen_size),
|
||||
INTEL_HSW_D_IDS(gen6_stolen_size),
|
||||
INTEL_HSW_M_IDS(gen6_stolen_size),
|
||||
INTEL_BDW_M_IDS(gen8_stolen_size),
|
||||
INTEL_BDW_D_IDS(gen8_stolen_size)
|
||||
INTEL_I830_IDS(&i830_stolen_funcs),
|
||||
INTEL_I845G_IDS(&i845_stolen_funcs),
|
||||
INTEL_I85X_IDS(&i85x_stolen_funcs),
|
||||
INTEL_I865G_IDS(&i865_stolen_funcs),
|
||||
INTEL_I915G_IDS(&gen3_stolen_funcs),
|
||||
INTEL_I915GM_IDS(&gen3_stolen_funcs),
|
||||
INTEL_I945G_IDS(&gen3_stolen_funcs),
|
||||
INTEL_I945GM_IDS(&gen3_stolen_funcs),
|
||||
INTEL_VLV_M_IDS(&gen6_stolen_funcs),
|
||||
INTEL_VLV_D_IDS(&gen6_stolen_funcs),
|
||||
INTEL_PINEVIEW_IDS(&gen3_stolen_funcs),
|
||||
INTEL_I965G_IDS(&gen3_stolen_funcs),
|
||||
INTEL_G33_IDS(&gen3_stolen_funcs),
|
||||
INTEL_I965GM_IDS(&gen3_stolen_funcs),
|
||||
INTEL_GM45_IDS(&gen3_stolen_funcs),
|
||||
INTEL_G45_IDS(&gen3_stolen_funcs),
|
||||
INTEL_IRONLAKE_D_IDS(&gen3_stolen_funcs),
|
||||
INTEL_IRONLAKE_M_IDS(&gen3_stolen_funcs),
|
||||
INTEL_SNB_D_IDS(&gen6_stolen_funcs),
|
||||
INTEL_SNB_M_IDS(&gen6_stolen_funcs),
|
||||
INTEL_IVB_M_IDS(&gen6_stolen_funcs),
|
||||
INTEL_IVB_D_IDS(&gen6_stolen_funcs),
|
||||
INTEL_HSW_D_IDS(&gen6_stolen_funcs),
|
||||
INTEL_HSW_M_IDS(&gen6_stolen_funcs),
|
||||
INTEL_BDW_M_IDS(&gen8_stolen_funcs),
|
||||
INTEL_BDW_D_IDS(&gen8_stolen_funcs)
|
||||
};
|
||||
|
||||
static void __init intel_graphics_stolen(int num, int slot, int func)
|
||||
|
@ -361,11 +512,13 @@ static void __init intel_graphics_stolen(int num, int slot, int func)
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(intel_stolen_ids); i++) {
|
||||
if (intel_stolen_ids[i].device == device) {
|
||||
stolen_size_fn stolen_size =
|
||||
(stolen_size_fn)intel_stolen_ids[i].driver_data;
|
||||
size = stolen_size(num, slot, func);
|
||||
start = intel_stolen_base(num, slot, func);
|
||||
const struct intel_stolen_funcs *stolen_funcs =
|
||||
(const struct intel_stolen_funcs *)intel_stolen_ids[i].driver_data;
|
||||
size = stolen_funcs->size(num, slot, func);
|
||||
start = stolen_funcs->base(num, slot, func, size);
|
||||
if (size && start) {
|
||||
printk(KERN_INFO "Reserving Intel graphics stolen memory at 0x%x-0x%x\n",
|
||||
start, start + (u32)size - 1);
|
||||
/* Mark this space as reserved */
|
||||
e820_add_region(start, size, E820_RESERVED);
|
||||
sanitize_e820_map(e820.map,
|
||||
|
|
|
@ -1207,23 +1207,31 @@ error:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline int __init determine_tce_table_size(u64 ram)
|
||||
static inline int __init determine_tce_table_size(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (specified_table_size != TCE_TABLE_SIZE_UNSPECIFIED)
|
||||
return specified_table_size;
|
||||
|
||||
/*
|
||||
* Table sizes are from 0 to 7 (TCE_TABLE_SIZE_64K to
|
||||
* TCE_TABLE_SIZE_8M). Table size 0 has 8K entries and each
|
||||
* larger table size has twice as many entries, so shift the
|
||||
* max ram address by 13 to divide by 8K and then look at the
|
||||
* order of the result to choose between 0-7.
|
||||
*/
|
||||
ret = get_order(ram >> 13);
|
||||
if (ret > TCE_TABLE_SIZE_8M)
|
||||
if (is_kdump_kernel() && saved_max_pfn) {
|
||||
/*
|
||||
* Table sizes are from 0 to 7 (TCE_TABLE_SIZE_64K to
|
||||
* TCE_TABLE_SIZE_8M). Table size 0 has 8K entries and each
|
||||
* larger table size has twice as many entries, so shift the
|
||||
* max ram address by 13 to divide by 8K and then look at the
|
||||
* order of the result to choose between 0-7.
|
||||
*/
|
||||
ret = get_order((saved_max_pfn * PAGE_SIZE) >> 13);
|
||||
if (ret > TCE_TABLE_SIZE_8M)
|
||||
ret = TCE_TABLE_SIZE_8M;
|
||||
} else {
|
||||
/*
|
||||
* Use 8M by default (suggested by Muli) if it's not
|
||||
* kdump kernel and saved_max_pfn isn't set.
|
||||
*/
|
||||
ret = TCE_TABLE_SIZE_8M;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1418,8 +1426,7 @@ int __init detect_calgary(void)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
specified_table_size = determine_tce_table_size((is_kdump_kernel() ?
|
||||
saved_max_pfn : max_pfn) * PAGE_SIZE);
|
||||
specified_table_size = determine_tce_table_size();
|
||||
|
||||
for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
|
||||
struct calgary_bus_info *info = &bus_info[bus];
|
||||
|
|
|
@ -56,6 +56,12 @@ extern bool i915_gpu_turbo_disable(void);
|
|||
|
||||
#define I830_GMCH_CTRL 0x52
|
||||
|
||||
#define I830_GMCH_GMS_MASK 0x70
|
||||
#define I830_GMCH_GMS_LOCAL 0x10
|
||||
#define I830_GMCH_GMS_STOLEN_512 0x20
|
||||
#define I830_GMCH_GMS_STOLEN_1024 0x30
|
||||
#define I830_GMCH_GMS_STOLEN_8192 0x40
|
||||
|
||||
#define I855_GMCH_GMS_MASK 0xF0
|
||||
#define I855_GMCH_GMS_STOLEN_0M 0x0
|
||||
#define I855_GMCH_GMS_STOLEN_1M (0x1 << 4)
|
||||
|
@ -72,4 +78,18 @@ extern bool i915_gpu_turbo_disable(void);
|
|||
#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4)
|
||||
#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4)
|
||||
|
||||
#define I830_DRB3 0x63
|
||||
#define I85X_DRB3 0x43
|
||||
#define I865_TOUD 0xc4
|
||||
|
||||
#define I830_ESMRAMC 0x91
|
||||
#define I845_ESMRAMC 0x9e
|
||||
#define I85X_ESMRAMC 0x61
|
||||
#define TSEG_ENABLE (1 << 0)
|
||||
#define I830_TSEG_SIZE_512K (0 << 1)
|
||||
#define I830_TSEG_SIZE_1M (1 << 1)
|
||||
#define I845_TSEG_SIZE_MASK (3 << 1)
|
||||
#define I845_TSEG_SIZE_512K (2 << 1)
|
||||
#define I845_TSEG_SIZE_1M (3 << 1)
|
||||
|
||||
#endif /* _I915_DRM_H_ */
|
||||
|
|
Loading…
Reference in New Issue