Commit 8697600b authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915: Make the high dword offset more explicit in i915_reg_read_ioctl

Store the upper dword of the register offset in the whitelist as well.
This would allow it to read register where the two halves aren't sitting
right next to each other, and it'll make it easier to make register
access type safe.

While at it change the register offsets to u32 from u64. Our register
space isn't quite that big, yet :)

v2: Use ldw/udw as the suffixes, and add a note about
    64bit wide split regs (Chris)

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1446839021-18599-1-git-send-email-ville.syrjala@linux.intel.comReviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent 3613cf1d
...@@ -1574,6 +1574,7 @@ enum skl_disp_power_wells { ...@@ -1574,6 +1574,7 @@ enum skl_disp_power_wells {
#define RING_IMR(base) ((base)+0xa8) #define RING_IMR(base) ((base)+0xa8)
#define RING_HWSTAM(base) ((base)+0x98) #define RING_HWSTAM(base) ((base)+0x98)
#define RING_TIMESTAMP(base) ((base)+0x358) #define RING_TIMESTAMP(base) ((base)+0x358)
#define RING_TIMESTAMP_UDW(base) ((base)+0x358 + 4)
#define TAIL_ADDR 0x001FFFF8 #define TAIL_ADDR 0x001FFFF8
#define HEAD_WRAP_COUNT 0xFFE00000 #define HEAD_WRAP_COUNT 0xFFE00000
#define HEAD_WRAP_ONE 0x00200000 #define HEAD_WRAP_ONE 0x00200000
......
...@@ -1261,12 +1261,14 @@ void intel_uncore_fini(struct drm_device *dev) ...@@ -1261,12 +1261,14 @@ void intel_uncore_fini(struct drm_device *dev)
#define GEN_RANGE(l, h) GENMASK(h, l) #define GEN_RANGE(l, h) GENMASK(h, l)
static const struct register_whitelist { static const struct register_whitelist {
uint64_t offset; uint32_t offset_ldw, offset_udw;
uint32_t size; uint32_t size;
/* supported gens, 0x10 for 4, 0x30 for 4 and 5, etc. */ /* supported gens, 0x10 for 4, 0x30 for 4 and 5, etc. */
uint32_t gen_bitmask; uint32_t gen_bitmask;
} whitelist[] = { } whitelist[] = {
{ RING_TIMESTAMP(RENDER_RING_BASE), 8, GEN_RANGE(4, 9) }, { .offset_ldw = RING_TIMESTAMP(RENDER_RING_BASE),
.offset_udw = RING_TIMESTAMP_UDW(RENDER_RING_BASE),
.size = 8, .gen_bitmask = GEN_RANGE(4, 9) },
}; };
int i915_reg_read_ioctl(struct drm_device *dev, int i915_reg_read_ioctl(struct drm_device *dev,
...@@ -1276,11 +1278,11 @@ int i915_reg_read_ioctl(struct drm_device *dev, ...@@ -1276,11 +1278,11 @@ int i915_reg_read_ioctl(struct drm_device *dev,
struct drm_i915_reg_read *reg = data; struct drm_i915_reg_read *reg = data;
struct register_whitelist const *entry = whitelist; struct register_whitelist const *entry = whitelist;
unsigned size; unsigned size;
u64 offset; uint32_t offset_ldw, offset_udw;
int i, ret = 0; int i, ret = 0;
for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) { for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) {
if (entry->offset == (reg->offset & -entry->size) && if (entry->offset_ldw == (reg->offset & -entry->size) &&
(1 << INTEL_INFO(dev)->gen & entry->gen_bitmask)) (1 << INTEL_INFO(dev)->gen & entry->gen_bitmask))
break; break;
} }
...@@ -1292,27 +1294,28 @@ int i915_reg_read_ioctl(struct drm_device *dev, ...@@ -1292,27 +1294,28 @@ int i915_reg_read_ioctl(struct drm_device *dev,
* be naturally aligned (and those that are not so aligned merely * be naturally aligned (and those that are not so aligned merely
* limit the available flags for that register). * limit the available flags for that register).
*/ */
offset = entry->offset; offset_ldw = entry->offset_ldw;
offset_udw = entry->offset_udw;
size = entry->size; size = entry->size;
size |= reg->offset ^ offset; size |= reg->offset ^ offset_ldw;
intel_runtime_pm_get(dev_priv); intel_runtime_pm_get(dev_priv);
switch (size) { switch (size) {
case 8 | 1: case 8 | 1:
reg->val = I915_READ64_2x32(offset, offset+4); reg->val = I915_READ64_2x32(offset_ldw, offset_udw);
break; break;
case 8: case 8:
reg->val = I915_READ64(offset); reg->val = I915_READ64(offset_ldw);
break; break;
case 4: case 4:
reg->val = I915_READ(offset); reg->val = I915_READ(offset_ldw);
break; break;
case 2: case 2:
reg->val = I915_READ16(offset); reg->val = I915_READ16(offset_ldw);
break; break;
case 1: case 1:
reg->val = I915_READ8(offset); reg->val = I915_READ8(offset_ldw);
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
......
...@@ -1079,6 +1079,12 @@ struct drm_i915_gem_context_destroy { ...@@ -1079,6 +1079,12 @@ struct drm_i915_gem_context_destroy {
}; };
struct drm_i915_reg_read { struct drm_i915_reg_read {
/*
* Register offset.
* For 64bit wide registers where the upper 32bits don't immediately
* follow the lower 32bits, the offset of the lower 32bits must
* be specified
*/
__u64 offset; __u64 offset;
__u64 val; /* Return value */ __u64 val; /* Return value */
}; };
......
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