Commit c0dd3460 authored by Joonas Lahtinen's avatar Joonas Lahtinen

drm/i915: Canonicalize stolen memory calculations

Move the better constructs/comments from i915_gem_stolen.c to
early-quirks.c and increase readability in preparation of only
having one set of functions.

- intel_stolen_base -> gen3_stolen_base
- use phys_addr_t instead of u32 for address for future proofing

v2:
- Print the invalid register values (Chris)
  (Omitting the register prefix as it's visible from backtrace.)

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Acked-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
parent 050fc465
...@@ -223,36 +223,19 @@ static void __init intel_remapping_check(int num, int slot, int func) ...@@ -223,36 +223,19 @@ static void __init intel_remapping_check(int num, int slot, int func)
* despite the efforts of the "RAM buffer" approach, which simply rounds * despite the efforts of the "RAM buffer" approach, which simply rounds
* memory boundaries up to 64M to try to catch space that may decode * memory boundaries up to 64M to try to catch space that may decode
* as RAM and so is not suitable for MMIO. * as RAM and so is not suitable for MMIO.
*
* 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, size_t stolen_size)
{
u32 base;
/*
* For the PCI IDs in this quirk, the stolen base is always
* in 0x5c, aka the BDSM register (yes that's really what
* it's called).
*/
base = read_pci_config(num, slot, func, 0x5c);
base &= ~((1<<20) - 1);
return base;
}
#define KB(x) ((x) * 1024UL) #define KB(x) ((x) * 1024UL)
#define MB(x) (KB (KB (x))) #define MB(x) (KB (KB (x)))
#define GB(x) (MB (KB (x)))
static size_t __init i830_tseg_size(void) static size_t __init i830_tseg_size(void)
{ {
u8 tmp = read_pci_config_byte(0, 0, 0, I830_ESMRAMC); u8 esmramc = read_pci_config_byte(0, 0, 0, I830_ESMRAMC);
if (!(tmp & TSEG_ENABLE)) if (!(esmramc & TSEG_ENABLE))
return 0; return 0;
if (tmp & I830_TSEG_SIZE_1M) if (esmramc & I830_TSEG_SIZE_1M)
return MB(1); return MB(1);
else else
return KB(512); return KB(512);
...@@ -260,27 +243,26 @@ static size_t __init i830_tseg_size(void) ...@@ -260,27 +243,26 @@ static size_t __init i830_tseg_size(void)
static size_t __init i845_tseg_size(void) static size_t __init i845_tseg_size(void)
{ {
u8 tmp = read_pci_config_byte(0, 0, 0, I845_ESMRAMC); u8 esmramc = read_pci_config_byte(0, 0, 0, I845_ESMRAMC);
u8 tseg_size = esmramc & I845_TSEG_SIZE_MASK;
if (!(tmp & TSEG_ENABLE)) if (!(esmramc & TSEG_ENABLE))
return 0; return 0;
switch (tmp & I845_TSEG_SIZE_MASK) { switch (tseg_size) {
case I845_TSEG_SIZE_512K: case I845_TSEG_SIZE_512K: return KB(512);
return KB(512); case I845_TSEG_SIZE_1M: return MB(1);
case I845_TSEG_SIZE_1M:
return MB(1);
default: default:
WARN_ON(1); WARN(1, "Unknown ESMRAMC value: %x!\n", esmramc);
return 0;
} }
return 0;
} }
static size_t __init i85x_tseg_size(void) static size_t __init i85x_tseg_size(void)
{ {
u8 tmp = read_pci_config_byte(0, 0, 0, I85X_ESMRAMC); u8 esmramc = read_pci_config_byte(0, 0, 0, I85X_ESMRAMC);
if (!(tmp & TSEG_ENABLE)) if (!(esmramc & TSEG_ENABLE))
return 0; return 0;
return MB(1); return MB(1);
...@@ -300,174 +282,166 @@ static size_t __init i85x_mem_size(void) ...@@ -300,174 +282,166 @@ static size_t __init i85x_mem_size(void)
* On 830/845/85x the stolen memory base isn't available in any * 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. * 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) static phys_addr_t __init i830_stolen_base(int num, int slot, int func,
size_t stolen_size)
{ {
return i830_mem_size() - i830_tseg_size() - stolen_size; return (phys_addr_t)i830_mem_size() - i830_tseg_size() - stolen_size;
} }
static u32 __init i845_stolen_base(int num, int slot, int func, size_t stolen_size) static phys_addr_t __init i845_stolen_base(int num, int slot, int func,
size_t stolen_size)
{ {
return i830_mem_size() - i845_tseg_size() - stolen_size; return (phys_addr_t)i830_mem_size() - i845_tseg_size() - stolen_size;
} }
static u32 __init i85x_stolen_base(int num, int slot, int func, size_t stolen_size) static phys_addr_t __init i85x_stolen_base(int num, int slot, int func,
size_t stolen_size)
{ {
return i85x_mem_size() - i85x_tseg_size() - stolen_size; return (phys_addr_t)i85x_mem_size() - i85x_tseg_size() - stolen_size;
} }
static u32 __init i865_stolen_base(int num, int slot, int func, size_t stolen_size) static phys_addr_t __init i865_stolen_base(int num, int slot, int func,
size_t stolen_size)
{ {
u16 toud;
/* /*
* FIXME is the graphics stolen memory region * FIXME is the graphics stolen memory region
* always at TOUD? Ie. is it always the last * always at TOUD? Ie. is it always the last
* one to be allocated by the BIOS? * one to be allocated by the BIOS?
*/ */
return read_pci_config_16(0, 0, 0, I865_TOUD) << 16; toud = read_pci_config_16(0, 0, 0, I865_TOUD);
return (phys_addr_t)toud << 16;
}
static phys_addr_t __init gen3_stolen_base(int num, int slot, int func,
size_t stolen_size)
{
u32 bsm;
/* Almost universally we can find the Graphics Base of Stolen Memory
* at register BSM (0x5c) in the igfx configuration space. On a few
* (desktop) machines this is also mirrored in the bridge device at
* different locations, or in the MCHBAR.
*/
bsm = read_pci_config(num, slot, func, INTEL_BSM);
return (phys_addr_t)bsm & INTEL_BSM_MASK;
} }
static size_t __init i830_stolen_size(int num, int slot, int func) static size_t __init i830_stolen_size(int num, int slot, int func)
{ {
size_t stolen_size;
u16 gmch_ctrl; u16 gmch_ctrl;
u16 gms;
gmch_ctrl = read_pci_config_16(0, 0, 0, I830_GMCH_CTRL); gmch_ctrl = read_pci_config_16(0, 0, 0, I830_GMCH_CTRL);
gms = gmch_ctrl & I830_GMCH_GMS_MASK;
switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
case I830_GMCH_GMS_STOLEN_512: switch (gms) {
stolen_size = KB(512); case I830_GMCH_GMS_STOLEN_512: return KB(512);
break; case I830_GMCH_GMS_STOLEN_1024: return MB(1);
case I830_GMCH_GMS_STOLEN_1024: case I830_GMCH_GMS_STOLEN_8192: return MB(8);
stolen_size = MB(1); /* local memory isn't part of the normal address space */
break; case I830_GMCH_GMS_LOCAL: return 0;
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: default:
return 0; WARN(1, "Unknown GMCH_CTRL value: %x!\n", gmch_ctrl);
} }
return stolen_size; return 0;
} }
static size_t __init gen3_stolen_size(int num, int slot, int func) static size_t __init gen3_stolen_size(int num, int slot, int func)
{ {
size_t stolen_size;
u16 gmch_ctrl; u16 gmch_ctrl;
u16 gms;
gmch_ctrl = read_pci_config_16(0, 0, 0, I830_GMCH_CTRL); gmch_ctrl = read_pci_config_16(0, 0, 0, I830_GMCH_CTRL);
gms = gmch_ctrl & I855_GMCH_GMS_MASK;
switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
case I855_GMCH_GMS_STOLEN_1M: switch (gms) {
stolen_size = MB(1); case I855_GMCH_GMS_STOLEN_1M: return MB(1);
break; case I855_GMCH_GMS_STOLEN_4M: return MB(4);
case I855_GMCH_GMS_STOLEN_4M: case I855_GMCH_GMS_STOLEN_8M: return MB(8);
stolen_size = MB(4); case I855_GMCH_GMS_STOLEN_16M: return MB(16);
break; case I855_GMCH_GMS_STOLEN_32M: return MB(32);
case I855_GMCH_GMS_STOLEN_8M: case I915_GMCH_GMS_STOLEN_48M: return MB(48);
stolen_size = MB(8); case I915_GMCH_GMS_STOLEN_64M: return MB(64);
break; case G33_GMCH_GMS_STOLEN_128M: return MB(128);
case I855_GMCH_GMS_STOLEN_16M: case G33_GMCH_GMS_STOLEN_256M: return MB(256);
stolen_size = MB(16); case INTEL_GMCH_GMS_STOLEN_96M: return MB(96);
break; case INTEL_GMCH_GMS_STOLEN_160M:return MB(160);
case I855_GMCH_GMS_STOLEN_32M: case INTEL_GMCH_GMS_STOLEN_224M:return MB(224);
stolen_size = MB(32); case INTEL_GMCH_GMS_STOLEN_352M:return MB(352);
break;
case I915_GMCH_GMS_STOLEN_48M:
stolen_size = MB(48);
break;
case I915_GMCH_GMS_STOLEN_64M:
stolen_size = MB(64);
break;
case G33_GMCH_GMS_STOLEN_128M:
stolen_size = MB(128);
break;
case G33_GMCH_GMS_STOLEN_256M:
stolen_size = MB(256);
break;
case INTEL_GMCH_GMS_STOLEN_96M:
stolen_size = MB(96);
break;
case INTEL_GMCH_GMS_STOLEN_160M:
stolen_size = MB(160);
break;
case INTEL_GMCH_GMS_STOLEN_224M:
stolen_size = MB(224);
break;
case INTEL_GMCH_GMS_STOLEN_352M:
stolen_size = MB(352);
break;
default: default:
stolen_size = 0; WARN(1, "Unknown GMCH_CTRL value: %x!\n", gmch_ctrl);
break;
} }
return stolen_size; return 0;
} }
static size_t __init gen6_stolen_size(int num, int slot, int func) static size_t __init gen6_stolen_size(int num, int slot, int func)
{ {
u16 gmch_ctrl; u16 gmch_ctrl;
u16 gms;
gmch_ctrl = read_pci_config_16(num, slot, func, SNB_GMCH_CTRL); gmch_ctrl = read_pci_config_16(num, slot, func, SNB_GMCH_CTRL);
gmch_ctrl >>= SNB_GMCH_GMS_SHIFT; gms = (gmch_ctrl >> SNB_GMCH_GMS_SHIFT) & SNB_GMCH_GMS_MASK;
gmch_ctrl &= SNB_GMCH_GMS_MASK;
return gmch_ctrl << 25; /* 32 MB units */ return (size_t)gms * MB(32);
} }
static size_t __init gen8_stolen_size(int num, int slot, int func) static size_t __init gen8_stolen_size(int num, int slot, int func)
{ {
u16 gmch_ctrl; u16 gmch_ctrl;
u16 gms;
gmch_ctrl = read_pci_config_16(num, slot, func, SNB_GMCH_CTRL); gmch_ctrl = read_pci_config_16(num, slot, func, SNB_GMCH_CTRL);
gmch_ctrl >>= BDW_GMCH_GMS_SHIFT; gms = (gmch_ctrl >> BDW_GMCH_GMS_SHIFT) & BDW_GMCH_GMS_MASK;
gmch_ctrl &= BDW_GMCH_GMS_MASK;
return gmch_ctrl << 25; /* 32 MB units */ return (size_t)gms * MB(32);
} }
static size_t __init chv_stolen_size(int num, int slot, int func) static size_t __init chv_stolen_size(int num, int slot, int func)
{ {
u16 gmch_ctrl; u16 gmch_ctrl;
u16 gms;
gmch_ctrl = read_pci_config_16(num, slot, func, SNB_GMCH_CTRL); gmch_ctrl = read_pci_config_16(num, slot, func, SNB_GMCH_CTRL);
gmch_ctrl >>= SNB_GMCH_GMS_SHIFT; gms = (gmch_ctrl >> SNB_GMCH_GMS_SHIFT) & SNB_GMCH_GMS_MASK;
gmch_ctrl &= SNB_GMCH_GMS_MASK;
/* /*
* 0x0 to 0x10: 32MB increments starting at 0MB * 0x0 to 0x10: 32MB increments starting at 0MB
* 0x11 to 0x16: 4MB increments starting at 8MB * 0x11 to 0x16: 4MB increments starting at 8MB
* 0x17 to 0x1d: 4MB increments start at 36MB * 0x17 to 0x1d: 4MB increments start at 36MB
*/ */
if (gmch_ctrl < 0x11) if (gms < 0x11)
return gmch_ctrl << 25; return (size_t)gms * MB(32);
else if (gmch_ctrl < 0x17) else if (gms < 0x17)
return (gmch_ctrl - 0x11 + 2) << 22; return (size_t)(gms - 0x11 + 2) * MB(4);
else else
return (gmch_ctrl - 0x17 + 9) << 22; return (size_t)(gms - 0x17 + 9) * MB(4);
} }
struct intel_stolen_funcs { struct intel_stolen_funcs {
size_t (*size)(int num, int slot, int func); size_t (*size)(int num, int slot, int func);
u32 (*base)(int num, int slot, int func, size_t size); phys_addr_t (*base)(int num, int slot, int func, size_t size);
}; };
static size_t __init gen9_stolen_size(int num, int slot, int func) static size_t __init gen9_stolen_size(int num, int slot, int func)
{ {
u16 gmch_ctrl; u16 gmch_ctrl;
u16 gms;
gmch_ctrl = read_pci_config_16(num, slot, func, SNB_GMCH_CTRL); gmch_ctrl = read_pci_config_16(num, slot, func, SNB_GMCH_CTRL);
gmch_ctrl >>= BDW_GMCH_GMS_SHIFT; gms = (gmch_ctrl >> BDW_GMCH_GMS_SHIFT) & BDW_GMCH_GMS_MASK;
gmch_ctrl &= BDW_GMCH_GMS_MASK;
if (gmch_ctrl < 0xf0) /* 0x0 to 0xef: 32MB increments starting at 0MB */
return gmch_ctrl << 25; /* 32 MB units */ /* 0xf0 to 0xfe: 4MB increments starting at 4MB */
if (gms < 0xf0)
return (size_t)gms * MB(32);
else else
/* 4MB increments starting at 0xf0 for 4MB */ return (size_t)(gms - 0xf0 + 1) * MB(4);
return (gmch_ctrl - 0xf0 + 1) << 22;
} }
typedef size_t (*stolen_size_fn)(int num, int slot, int func); typedef size_t (*stolen_size_fn)(int num, int slot, int func);
...@@ -493,27 +467,27 @@ static const struct intel_stolen_funcs i865_stolen_funcs __initconst = { ...@@ -493,27 +467,27 @@ static const struct intel_stolen_funcs i865_stolen_funcs __initconst = {
}; };
static const struct intel_stolen_funcs gen3_stolen_funcs __initconst = { static const struct intel_stolen_funcs gen3_stolen_funcs __initconst = {
.base = intel_stolen_base, .base = gen3_stolen_base,
.size = gen3_stolen_size, .size = gen3_stolen_size,
}; };
static const struct intel_stolen_funcs gen6_stolen_funcs __initconst = { static const struct intel_stolen_funcs gen6_stolen_funcs __initconst = {
.base = intel_stolen_base, .base = gen3_stolen_base,
.size = gen6_stolen_size, .size = gen6_stolen_size,
}; };
static const struct intel_stolen_funcs gen8_stolen_funcs __initconst = { static const struct intel_stolen_funcs gen8_stolen_funcs __initconst = {
.base = intel_stolen_base, .base = gen3_stolen_base,
.size = gen8_stolen_size, .size = gen8_stolen_size,
}; };
static const struct intel_stolen_funcs gen9_stolen_funcs __initconst = { static const struct intel_stolen_funcs gen9_stolen_funcs __initconst = {
.base = intel_stolen_base, .base = gen3_stolen_base,
.size = gen9_stolen_size, .size = gen9_stolen_size,
}; };
static const struct intel_stolen_funcs chv_stolen_funcs __initconst = { static const struct intel_stolen_funcs chv_stolen_funcs __initconst = {
.base = intel_stolen_base, .base = gen3_stolen_base,
.size = chv_stolen_size, .size = chv_stolen_size,
}; };
...@@ -554,7 +528,7 @@ static void __init intel_graphics_stolen(int num, int slot, int func) ...@@ -554,7 +528,7 @@ static void __init intel_graphics_stolen(int num, int slot, int func)
{ {
size_t size; size_t size;
int i; int i;
u32 start; phys_addr_t start;
u16 device, subvendor, subdevice; u16 device, subvendor, subdevice;
device = read_pci_config_16(num, slot, func, PCI_DEVICE_ID); device = read_pci_config_16(num, slot, func, PCI_DEVICE_ID);
...@@ -569,8 +543,8 @@ static void __init intel_graphics_stolen(int num, int slot, int func) ...@@ -569,8 +543,8 @@ static void __init intel_graphics_stolen(int num, int slot, int func)
size = stolen_funcs->size(num, slot, func); size = stolen_funcs->size(num, slot, func);
start = stolen_funcs->base(num, slot, func, size); start = stolen_funcs->base(num, slot, func, size);
if (size && start) { if (size && start) {
printk(KERN_INFO "Reserving Intel graphics stolen memory at 0x%x-0x%x\n", printk(KERN_INFO "Reserving Intel graphics stolen memory at 0x%llx-0x%llx\n",
start, start + (u32)size - 1); start, start + size - 1);
/* Mark this space as reserved */ /* Mark this space as reserved */
e820_add_region(start, size, E820_RESERVED); e820_add_region(start, size, E820_RESERVED);
sanitize_e820_map(e820.map, sanitize_e820_map(e820.map,
......
...@@ -109,9 +109,9 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) ...@@ -109,9 +109,9 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
if (INTEL_INFO(dev)->gen >= 3) { if (INTEL_INFO(dev)->gen >= 3) {
u32 bsm; u32 bsm;
pci_read_config_dword(dev->pdev, BSM, &bsm); pci_read_config_dword(dev->pdev, INTEL_BSM, &bsm);
base = bsm & BSM_MASK; base = bsm & INTEL_BSM_MASK;
} else if (IS_I865G(dev)) { } else if (IS_I865G(dev)) {
u16 toud = 0; u16 toud = 0;
......
...@@ -92,4 +92,7 @@ extern bool i915_gpu_turbo_disable(void); ...@@ -92,4 +92,7 @@ extern bool i915_gpu_turbo_disable(void);
#define I845_TSEG_SIZE_512K (2 << 1) #define I845_TSEG_SIZE_512K (2 << 1)
#define I845_TSEG_SIZE_1M (3 << 1) #define I845_TSEG_SIZE_1M (3 << 1)
#define INTEL_BSM 0x5c
#define INTEL_BSM_MASK (0xFFFF << 20)
#endif /* _I915_DRM_H_ */ #endif /* _I915_DRM_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment