Skip to content

Commit

Permalink
drm/i915: Type safe register read/write
Browse files Browse the repository at this point in the history
Make I915_READ and I915_WRITE more type safe by wrapping the register
offset in a struct. This should eliminate most of the fumbles we've had
with misplaced parens.

This only takes care of normal mmio registers. We could extend the idea
to other register types and define each with its own struct. That way
you wouldn't be able to accidentally pass the wrong thing to a specific
register access function.

The gpio_reg setup is probably the ugliest thing left. But I figure I'd
just leave it for now, and wait for some divine inspiration to strike
before making it nice.

As for the generated code, it's actually a bit better sometimes. Eg.
looking at i915_irq_handler(), we can see the following change:
  lea    0x70024(%rdx,%rax,1),%r9d
  mov    $0x1,%edx
- movslq %r9d,%r9
- mov    %r9,%rsi
- mov    %r9,-0x58(%rbp)
- callq  *0xd8(%rbx)
+ mov    %r9d,%esi
+ mov    %r9d,-0x48(%rbp)
 callq  *0xd8(%rbx)

So previously gcc thought the register offset might be signed and
decided to sign extend it, just in case. The rest appears to be
mostly just minor shuffling of instructions.

v2: i915_mmio_reg_{offset,equal,valid}() helpers added
    s/_REG/_MMIO/ in the register defines
    mo more switch statements left to worry about
    ring_emit stuff got sorted in a prep patch
    cmd parser, lrc context and w/a batch buildup also in prep patch
    vgpu stuff cleaned up and moved to a prep patch
    all other unrelated changes split out
v3: Rebased due to BXT DSI/BLC, MOCS, etc.
v4: Rebased due to churn, s/i915_mmio_reg_t/i915_reg_t/

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1447853606-2751-1-git-send-email-ville.syrjala@linux.intel.com
  • Loading branch information
Ville Syrjälä committed Nov 18, 2015
1 parent 9bca5d0 commit f0f59a0
Show file tree
Hide file tree
Showing 35 changed files with 1,540 additions and 1,573 deletions.
4 changes: 2 additions & 2 deletions drivers/gpu/drm/i915/dvo.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ struct intel_dvo_device {
const char *name;
int type;
/* DVOA/B/C output register */
u32 dvo_reg;
u32 dvo_srcdim_reg;
i915_reg_t dvo_reg;
i915_reg_t dvo_srcdim_reg;
/* GPIO register used for i2c bus to control this device */
u32 gpio;
int slave_addr;
Expand Down
8 changes: 4 additions & 4 deletions drivers/gpu/drm/i915/i915_cmd_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ static const struct drm_i915_cmd_table hsw_blt_ring_cmds[] = {
* LRI.
*/
struct drm_i915_reg_descriptor {
u32 addr;
i915_reg_t addr;
u32 mask;
u32 value;
};
Expand Down Expand Up @@ -597,7 +597,7 @@ static bool check_sorted(int ring_id,
bool ret = true;

for (i = 0; i < reg_count; i++) {
u32 curr = reg_table[i].addr;
u32 curr = i915_mmio_reg_offset(reg_table[i].addr);

if (curr < previous) {
DRM_ERROR("CMD: table not sorted ring=%d entry=%d reg=0x%08X prev=0x%08X\n",
Expand Down Expand Up @@ -852,7 +852,7 @@ find_reg(const struct drm_i915_reg_descriptor *table,
int i;

for (i = 0; i < count; i++) {
if (table[i].addr == addr)
if (i915_mmio_reg_offset(table[i].addr) == addr)
return &table[i];
}
}
Expand Down Expand Up @@ -1028,7 +1028,7 @@ static bool check_cmd(const struct intel_engine_cs *ring,
* to the register. Hence, limit OACONTROL writes to
* only MI_LOAD_REGISTER_IMM commands.
*/
if (reg_addr == OACONTROL) {
if (reg_addr == i915_mmio_reg_offset(OACONTROL)) {
if (desc->cmd.value == MI_LOAD_REGISTER_MEM) {
DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n");
return false;
Expand Down
5 changes: 3 additions & 2 deletions drivers/gpu/drm/i915/i915_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -3267,7 +3267,8 @@ static int i915_wa_registers(struct seq_file *m, void *unused)

seq_printf(m, "Workarounds applied: %d\n", dev_priv->workarounds.count);
for (i = 0; i < dev_priv->workarounds.count; ++i) {
u32 addr, mask, value, read;
i915_reg_t addr;
u32 mask, value, read;
bool ok;

addr = dev_priv->workarounds.reg[i].addr;
Expand All @@ -3276,7 +3277,7 @@ static int i915_wa_registers(struct seq_file *m, void *unused)
read = I915_READ(addr);
ok = (value & mask) == (read & mask);
seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X, read: 0x%08x, status: %s\n",
addr, value, mask, read, ok ? "OK" : "FAIL");
i915_mmio_reg_offset(addr), value, mask, read, ok ? "OK" : "FAIL");
}

intel_runtime_pm_put(dev_priv);
Expand Down
38 changes: 19 additions & 19 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -685,18 +685,18 @@ struct intel_uncore_funcs {
void (*force_wake_put)(struct drm_i915_private *dev_priv,
enum forcewake_domains domains);

uint8_t (*mmio_readb)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
uint16_t (*mmio_readw)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
uint32_t (*mmio_readl)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
uint64_t (*mmio_readq)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
uint8_t (*mmio_readb)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace);
uint16_t (*mmio_readw)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace);
uint32_t (*mmio_readl)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace);
uint64_t (*mmio_readq)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace);

void (*mmio_writeb)(struct drm_i915_private *dev_priv, off_t offset,
void (*mmio_writeb)(struct drm_i915_private *dev_priv, i915_reg_t r,
uint8_t val, bool trace);
void (*mmio_writew)(struct drm_i915_private *dev_priv, off_t offset,
void (*mmio_writew)(struct drm_i915_private *dev_priv, i915_reg_t r,
uint16_t val, bool trace);
void (*mmio_writel)(struct drm_i915_private *dev_priv, off_t offset,
void (*mmio_writel)(struct drm_i915_private *dev_priv, i915_reg_t r,
uint32_t val, bool trace);
void (*mmio_writeq)(struct drm_i915_private *dev_priv, off_t offset,
void (*mmio_writeq)(struct drm_i915_private *dev_priv, i915_reg_t r,
uint64_t val, bool trace);
};

Expand All @@ -713,11 +713,11 @@ struct intel_uncore {
enum forcewake_domain_id id;
unsigned wake_count;
struct timer_list timer;
u32 reg_set;
i915_reg_t reg_set;
u32 val_set;
u32 val_clear;
u32 reg_ack;
u32 reg_post;
i915_reg_t reg_ack;
i915_reg_t reg_post;
u32 val_reset;
} fw_domain[FW_DOMAIN_ID_COUNT];
};
Expand All @@ -743,7 +743,7 @@ struct intel_csr {
uint32_t dmc_fw_size;
uint32_t version;
uint32_t mmio_count;
uint32_t mmioaddr[8];
i915_reg_t mmioaddr[8];
uint32_t mmiodata[8];
};

Expand Down Expand Up @@ -996,7 +996,7 @@ struct intel_gmbus {
struct i2c_adapter adapter;
u32 force_bit;
u32 reg0;
u32 gpio_reg;
i915_reg_t gpio_reg;
struct i2c_algo_bit_data bit_algo;
struct drm_i915_private *dev_priv;
};
Expand Down Expand Up @@ -1645,7 +1645,7 @@ struct i915_frontbuffer_tracking {
};

struct i915_wa_reg {
u32 addr;
i915_reg_t addr;
u32 value;
/* bitmask representing WA bits */
u32 mask;
Expand Down Expand Up @@ -3434,16 +3434,16 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val);

#define __raw_read(x, s) \
static inline uint##x##_t __raw_i915_read##x(struct drm_i915_private *dev_priv, \
uint32_t reg) \
i915_reg_t reg) \
{ \
return read##s(dev_priv->regs + reg); \
return read##s(dev_priv->regs + i915_mmio_reg_offset(reg)); \
}

#define __raw_write(x, s) \
static inline void __raw_i915_write##x(struct drm_i915_private *dev_priv, \
uint32_t reg, uint##x##_t val) \
i915_reg_t reg, uint##x##_t val) \
{ \
write##s(val, dev_priv->regs + reg); \
write##s(val, dev_priv->regs + i915_mmio_reg_offset(reg)); \
}
__raw_read(8, b)
__raw_read(16, w)
Expand Down Expand Up @@ -3474,7 +3474,7 @@ __raw_write(64, q)
#define INTEL_BROADCAST_RGB_FULL 1
#define INTEL_BROADCAST_RGB_LIMITED 2

static inline uint32_t i915_vgacntrl_reg(struct drm_device *dev)
static inline i915_reg_t i915_vgacntrl_reg(struct drm_device *dev)
{
if (IS_VALLEYVIEW(dev))
return VLV_VGACNTRL;
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/i915_gem_fence.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
struct drm_i915_gem_object *obj)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int fence_reg_lo, fence_reg_hi;
i915_reg_t fence_reg_lo, fence_reg_hi;
int fence_pitch_shift;

if (INTEL_INFO(dev)->gen >= 6) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/i915_gpu_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -910,7 +910,7 @@ static void i915_record_ring_state(struct drm_device *dev,
ering->ctl = I915_READ_CTL(ring);

if (I915_NEED_GFX_HWS(dev)) {
int mmio;
i915_reg_t mmio;

if (IS_GEN7(dev)) {
switch (ring->id) {
Expand Down
52 changes: 26 additions & 26 deletions drivers/gpu/drm/i915/i915_guc_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

/* Definitions of GuC H/W registers, bits, etc */

#define GUC_STATUS 0xc000
#define GUC_STATUS _MMIO(0xc000)
#define GS_BOOTROM_SHIFT 1
#define GS_BOOTROM_MASK (0x7F << GS_BOOTROM_SHIFT)
#define GS_BOOTROM_RSA_FAILED (0x50 << GS_BOOTROM_SHIFT)
Expand All @@ -39,41 +39,41 @@
#define GS_MIA_MASK (0x07 << GS_MIA_SHIFT)
#define GS_MIA_CORE_STATE (1 << GS_MIA_SHIFT)

#define SOFT_SCRATCH(n) (0xc180 + ((n) * 4))
#define SOFT_SCRATCH(n) _MMIO(0xc180 + (n) * 4)

#define UOS_RSA_SCRATCH(i) (0xc200 + (i) * 4)
#define UOS_RSA_SCRATCH(i) _MMIO(0xc200 + (i) * 4)
#define UOS_RSA_SCRATCH_MAX_COUNT 64
#define DMA_ADDR_0_LOW 0xc300
#define DMA_ADDR_0_HIGH 0xc304
#define DMA_ADDR_1_LOW 0xc308
#define DMA_ADDR_1_HIGH 0xc30c
#define DMA_ADDR_0_LOW _MMIO(0xc300)
#define DMA_ADDR_0_HIGH _MMIO(0xc304)
#define DMA_ADDR_1_LOW _MMIO(0xc308)
#define DMA_ADDR_1_HIGH _MMIO(0xc30c)
#define DMA_ADDRESS_SPACE_WOPCM (7 << 16)
#define DMA_ADDRESS_SPACE_GTT (8 << 16)
#define DMA_COPY_SIZE 0xc310
#define DMA_CTRL 0xc314
#define DMA_COPY_SIZE _MMIO(0xc310)
#define DMA_CTRL _MMIO(0xc314)
#define UOS_MOVE (1<<4)
#define START_DMA (1<<0)
#define DMA_GUC_WOPCM_OFFSET 0xc340
#define DMA_GUC_WOPCM_OFFSET _MMIO(0xc340)
#define GUC_WOPCM_OFFSET_VALUE 0x80000 /* 512KB */
#define GUC_MAX_IDLE_COUNT 0xC3E4
#define GUC_MAX_IDLE_COUNT _MMIO(0xC3E4)

#define GUC_WOPCM_SIZE 0xc050
#define GUC_WOPCM_SIZE _MMIO(0xc050)
#define GUC_WOPCM_SIZE_VALUE (0x80 << 12) /* 512KB */

/* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */
#define GUC_WOPCM_TOP (GUC_WOPCM_SIZE_VALUE)

#define GEN8_GT_PM_CONFIG 0x138140
#define GEN9LP_GT_PM_CONFIG 0x138140
#define GEN9_GT_PM_CONFIG 0x13816c
#define GEN8_GT_PM_CONFIG _MMIO(0x138140)
#define GEN9LP_GT_PM_CONFIG _MMIO(0x138140)
#define GEN9_GT_PM_CONFIG _MMIO(0x13816c)
#define GT_DOORBELL_ENABLE (1<<0)

#define GEN8_GTCR 0x4274
#define GEN8_GTCR _MMIO(0x4274)
#define GEN8_GTCR_INVALIDATE (1<<0)

#define GUC_ARAT_C6DIS 0xA178
#define GUC_ARAT_C6DIS _MMIO(0xA178)

#define GUC_SHIM_CONTROL 0xc064
#define GUC_SHIM_CONTROL _MMIO(0xc064)
#define GUC_DISABLE_SRAM_INIT_TO_ZEROES (1<<0)
#define GUC_ENABLE_READ_CACHE_LOGIC (1<<1)
#define GUC_ENABLE_MIA_CACHING (1<<2)
Expand All @@ -90,21 +90,21 @@
GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA | \
GUC_ENABLE_MIA_CLOCK_GATING)

#define HOST2GUC_INTERRUPT 0xc4c8
#define HOST2GUC_INTERRUPT _MMIO(0xc4c8)
#define HOST2GUC_TRIGGER (1<<0)

#define DRBMISC1 0x1984
#define DOORBELL_ENABLE (1<<0)

#define GEN8_DRBREGL(x) (0x1000 + (x) * 8)
#define GEN8_DRBREGL(x) _MMIO(0x1000 + (x) * 8)
#define GEN8_DRB_VALID (1<<0)
#define GEN8_DRBREGU(x) (GEN8_DRBREGL(x) + 4)
#define GEN8_DRBREGU(x) _MMIO(0x1000 + (x) * 8 + 4)

#define DE_GUCRMR 0x44054
#define DE_GUCRMR _MMIO(0x44054)

#define GUC_BCS_RCS_IER 0xC550
#define GUC_VCS2_VCS1_IER 0xC554
#define GUC_WD_VECS_IER 0xC558
#define GUC_PM_P24C_IER 0xC55C
#define GUC_BCS_RCS_IER _MMIO(0xC550)
#define GUC_VCS2_VCS1_IER _MMIO(0xC554)
#define GUC_WD_VECS_IER _MMIO(0xC558)
#define GUC_PM_P24C_IER _MMIO(0xC55C)

#endif
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/i915_guc_submission.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ static void guc_disable_doorbell(struct intel_guc *guc,
struct drm_i915_private *dev_priv = guc_to_i915(guc);
struct guc_doorbell_info *doorbell;
void *base;
int drbreg = GEN8_DRBREGL(client->doorbell_id);
i915_reg_t drbreg = GEN8_DRBREGL(client->doorbell_id);
int value;

base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0));
Expand Down
Loading

0 comments on commit f0f59a0

Please sign in to comment.