From: <ma...@ke...> - 2007-02-03 04:59:44
|
linux-core/Makefile.kernel | 4 linux-core/nv04_graph.c | 1 shared-core/nouveau_drv.h | 2 shared-core/nouveau_fifo.c | 293 +++++++++++++------------ shared-core/nouveau_irq.c | 116 +++++----- shared-core/nouveau_reg.h | 509 ++++++++++++++++++++++++-------------------- shared-core/nouveau_state.c | 4 shared-core/nv04_graph.c | 237 ++++++++++++++++++++ shared-core/nv10_graph.c | 454 +++++++++++++++++++-------------------- shared-core/nv20_graph.c | 34 +- shared-core/nv30_graph.c | 2 shared-core/nv40_graph.c | 16 - 12 files changed, 991 insertions(+), 681 deletions(-) New commits: diff-tree ebf22aed9aa56e8ba00b5d3d1d2ca4600e5f1ec5 (from 0c13657c33f282233b9f4bb397acb99c4cd65919) Author: Stephane Marchesin <mar...@ic...> Date: Sat Feb 3 06:02:12 2007 +0100 nouveau: add missing nv04_graph.c symlink. diff --git a/linux-core/nv04_graph.c b/linux-core/nv04_graph.c new file mode 120000 index 0000000..0d7a0b3 --- /dev/null +++ b/linux-core/nv04_graph.c @@ -0,0 +1 @@ +../shared-core/nv04_graph.c \ No newline at end of file diff-tree 0c13657c33f282233b9f4bb397acb99c4cd65919 (from 7ab9e7f36f5fb58652f915a0839a167c6206743a) Author: Stephane Marchesin <mar...@ic...> Date: Sat Feb 3 06:00:29 2007 +0100 nouveau: plugin the nv04 graph init function. diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index a45c48e..f1f272e 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -108,6 +108,8 @@ int nouveau_firstopen(struct drm_device nv20_graph_init(dev); else if (dev_priv->card_type >= NV_10) nv10_graph_init(dev); + else if (dev_priv->card_type >= NV_04) + nv04_graph_init(dev); return 0; } diff-tree 7ab9e7f36f5fb58652f915a0839a167c6206743a (from d69902db3b1f82dd35f5bbb3327bdf836961850c) Author: Stephane Marchesin <mar...@ic...> Date: Sat Feb 3 05:56:42 2007 +0100 nouveau: cleanup the nv04 pgraph save/restore mechanism. diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index c45ca87..542e7ec 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -170,6 +170,7 @@ #define NV04_PGRAPH_BPIXEL 0x00400724 #define NV10_PGRAPH_RDI_INDEX 0x00400750 +#define NV04_PGRAPH_FFINTFC_ST2 0x00400754 #define NV10_PGRAPH_RDI_DATA 0x00400754 #define NV04_PGRAPH_DMA_PITCH 0x00400760 #define NV10_PGRAPH_FFINTFC_ST2 0x00400764 diff --git a/shared-core/nv04_graph.c b/shared-core/nv04_graph.c index 47fb8a1..d7d7800 100644 --- a/shared-core/nv04_graph.c +++ b/shared-core/nv04_graph.c @@ -27,132 +27,133 @@ #include "nouveau_drm.h" #include "nouveau_drv.h" - -// FIXME check if NV10/NV04 names are the same or if we need separate regs -static int nv04_graph_ctx_regs [] = { - NV04_PGRAPH_CTX_SWITCH1, 1, - NV04_PGRAPH_CTX_SWITCH2, 1, - NV04_PGRAPH_CTX_SWITCH3, 1, - NV04_PGRAPH_CTX_SWITCH4, 1, - NV04_PGRAPH_CTX_USER, 1, - NV04_PGRAPH_CTX_CACHE1, 8, - NV04_PGRAPH_CTX_CACHE2, 8, - NV04_PGRAPH_CTX_CACHE3, 8, - NV04_PGRAPH_CTX_CACHE4, 8, - NV03_PGRAPH_ABS_X_RAM, 32, - NV03_PGRAPH_ABS_Y_RAM, 32, - NV03_PGRAPH_X_MISC, 1, - NV03_PGRAPH_Y_MISC, 1, - NV04_PGRAPH_VALID1, 1, - NV04_PGRAPH_SOURCE_COLOR, 1, - NV04_PGRAPH_MISC24_0, 1, - NV03_PGRAPH_XY_LOGIC_MISC0, 1, - NV03_PGRAPH_XY_LOGIC_MISC1, 1, - NV03_PGRAPH_XY_LOGIC_MISC2, 1, - NV03_PGRAPH_XY_LOGIC_MISC3, 1, - NV03_PGRAPH_CLIPX_0, 1, - NV03_PGRAPH_CLIPX_1, 1, - NV03_PGRAPH_CLIPY_0, 1, - NV03_PGRAPH_CLIPY_1, 1, - NV03_PGRAPH_ABS_ICLIP_XMAX, 1, - NV03_PGRAPH_ABS_ICLIP_YMAX, 1, - NV03_PGRAPH_ABS_UCLIP_XMIN, 1, - NV03_PGRAPH_ABS_UCLIP_YMIN, 1, - NV03_PGRAPH_ABS_UCLIP_XMAX, 1, - NV03_PGRAPH_ABS_UCLIP_YMAX, 1, - NV03_PGRAPH_ABS_UCLIPA_XMIN, 1, - NV03_PGRAPH_ABS_UCLIPA_YMIN, 1, - NV03_PGRAPH_ABS_UCLIPA_XMAX, 1, - NV03_PGRAPH_ABS_UCLIPA_YMAX, 1, - NV04_PGRAPH_MISC24_1, 1, - NV04_PGRAPH_MISC24_2, 1, - NV04_PGRAPH_VALID2, 1, - NV04_PGRAPH_PASSTHRU_0, 1, - NV04_PGRAPH_PASSTHRU_1, 1, - NV04_PGRAPH_PASSTHRU_2, 1, - NV04_PGRAPH_COMBINE_0_ALPHA, 1, - NV04_PGRAPH_COMBINE_0_COLOR, 1, - NV04_PGRAPH_COMBINE_1_ALPHA, 1, - NV04_PGRAPH_COMBINE_1_COLOR, 1, +struct reg_interval +{ + int reg; + int number; +} nv04_graph_ctx_regs [] = { + {NV04_PGRAPH_CTX_SWITCH1, 1}, + {NV04_PGRAPH_CTX_SWITCH2, 1}, + {NV04_PGRAPH_CTX_SWITCH3, 1}, + {NV04_PGRAPH_CTX_SWITCH4, 1}, + {NV04_PGRAPH_CTX_USER, 1}, + {NV04_PGRAPH_CTX_CACHE1, 8}, + {NV04_PGRAPH_CTX_CACHE2, 8}, + {NV04_PGRAPH_CTX_CACHE3, 8}, + {NV04_PGRAPH_CTX_CACHE4, 8}, + {NV03_PGRAPH_ABS_X_RAM, 32}, + {NV03_PGRAPH_ABS_Y_RAM, 32}, + {NV03_PGRAPH_X_MISC, 1}, + {NV03_PGRAPH_Y_MISC, 1}, + {NV04_PGRAPH_VALID1, 1}, + {NV04_PGRAPH_SOURCE_COLOR, 1}, + {NV04_PGRAPH_MISC24_0, 1}, + {NV03_PGRAPH_XY_LOGIC_MISC0, 1}, + {NV03_PGRAPH_XY_LOGIC_MISC1, 1}, + {NV03_PGRAPH_XY_LOGIC_MISC2, 1}, + {NV03_PGRAPH_XY_LOGIC_MISC3, 1}, + {NV03_PGRAPH_CLIPX_0, 1}, + {NV03_PGRAPH_CLIPX_1, 1}, + {NV03_PGRAPH_CLIPY_0, 1}, + {NV03_PGRAPH_CLIPY_1, 1}, + {NV03_PGRAPH_ABS_ICLIP_XMAX, 1}, + {NV03_PGRAPH_ABS_ICLIP_YMAX, 1}, + {NV03_PGRAPH_ABS_UCLIP_XMIN, 1}, + {NV03_PGRAPH_ABS_UCLIP_YMIN, 1}, + {NV03_PGRAPH_ABS_UCLIP_XMAX, 1}, + {NV03_PGRAPH_ABS_UCLIP_YMAX, 1}, + {NV03_PGRAPH_ABS_UCLIPA_XMIN, 1}, + {NV03_PGRAPH_ABS_UCLIPA_YMIN, 1}, + {NV03_PGRAPH_ABS_UCLIPA_XMAX, 1}, + {NV03_PGRAPH_ABS_UCLIPA_YMAX, 1}, + {NV04_PGRAPH_MISC24_1, 1}, + {NV04_PGRAPH_MISC24_2, 1}, + {NV04_PGRAPH_VALID2, 1}, + {NV04_PGRAPH_PASSTHRU_0, 1}, + {NV04_PGRAPH_PASSTHRU_1, 1}, + {NV04_PGRAPH_PASSTHRU_2, 1}, + {NV04_PGRAPH_COMBINE_0_ALPHA, 1}, + {NV04_PGRAPH_COMBINE_0_COLOR, 1}, + {NV04_PGRAPH_COMBINE_1_ALPHA, 1}, + {NV04_PGRAPH_COMBINE_1_COLOR, 1}, // texture state - NV04_PGRAPH_FORMAT_0, 1, - NV04_PGRAPH_FORMAT_1, 1, - NV04_PGRAPH_FILTER_0, 1, - NV04_PGRAPH_FILTER_1, 1, + {NV04_PGRAPH_FORMAT_0, 1}, + {NV04_PGRAPH_FORMAT_1, 1}, + {NV04_PGRAPH_FILTER_0, 1}, + {NV04_PGRAPH_FILTER_1, 1}, // vertex state - 0x004005c0, 1, - 0x004005c4, 1, - 0x004005c8, 1, - 0x004005cc, 1, - 0x004005d0, 1, - 0x004005d4, 1, - 0x004005d8, 1, - 0x004005dc, 1, - 0x004005e0, 1, - NV03_PGRAPH_MONO_COLOR0, 1, - NV04_PGRAPH_ROP3, 1, - NV04_PGRAPH_BETA_AND, 1, - NV04_PGRAPH_BETA_PREMULT, 1, - NV04_PGRAPH_FORMATS, 1, - NV04_PGRAPH_BOFFSET0, 6, - NV04_PGRAPH_BBASE0, 6, - NV04_PGRAPH_BPITCH0, 5, - NV04_PGRAPH_BLIMIT0, 6, - NV04_PGRAPH_BSWIZZLE2, 1, - NV04_PGRAPH_BSWIZZLE5, 1, - NV04_PGRAPH_SURFACE, 1, - NV04_PGRAPH_STATE, 1, - NV04_PGRAPH_NOTIFY, 1, - NV04_PGRAPH_BPIXEL, 1, - NV04_PGRAPH_DMA_PITCH, 1, - NV04_PGRAPH_DVD_COLORFMT, 1, - NV04_PGRAPH_SCALED_FORMAT, 1, - NV04_PGRAPH_PATT_COLOR0, 1, - NV04_PGRAPH_PATT_COLOR1, 1, - NV04_PGRAPH_PATTERN, 2, - NV04_PGRAPH_PATTERN_SHAPE, 1, - NV04_PGRAPH_CHROMA, 1, - NV04_PGRAPH_CONTROL0, 1, - NV04_PGRAPH_CONTROL1, 1, - NV04_PGRAPH_CONTROL2, 1, - NV04_PGRAPH_BLEND, 1, - NV04_PGRAPH_STORED_FMT, 1, - NV04_PGRAPH_PATT_COLORRAM, 64, - NV04_PGRAPH_U_RAM, 16, - NV04_PGRAPH_V_RAM, 16, - NV04_PGRAPH_W_RAM, 16, - NV04_PGRAPH_DMA_START_0, 1, - NV04_PGRAPH_DMA_START_1, 1, - NV04_PGRAPH_DMA_LENGTH, 1, - NV04_PGRAPH_DMA_MISC, 1, - NV04_PGRAPH_DMA_DATA_0, 1, - NV04_PGRAPH_DMA_DATA_1, 1, - NV04_PGRAPH_DMA_RM, 1, - NV04_PGRAPH_DMA_A_XLATE_INST, 1, - NV04_PGRAPH_DMA_A_CONTROL, 1, - NV04_PGRAPH_DMA_A_LIMIT, 1, - NV04_PGRAPH_DMA_A_TLB_PTE, 1, - NV04_PGRAPH_DMA_A_TLB_TAG, 1, - NV04_PGRAPH_DMA_A_ADJ_OFFSET, 1, - NV04_PGRAPH_DMA_A_OFFSET, 1, - NV04_PGRAPH_DMA_A_SIZE, 1, - NV04_PGRAPH_DMA_A_Y_SIZE, 1, - NV04_PGRAPH_DMA_B_XLATE_INST, 1, - NV04_PGRAPH_DMA_B_CONTROL, 1, - NV04_PGRAPH_DMA_B_LIMIT, 1, - NV04_PGRAPH_DMA_B_TLB_PTE, 1, - NV04_PGRAPH_DMA_B_TLB_TAG, 1, - NV04_PGRAPH_DMA_B_ADJ_OFFSET, 1, - NV04_PGRAPH_DMA_B_OFFSET, 1, - NV04_PGRAPH_DMA_B_SIZE, 1, - NV04_PGRAPH_DMA_B_Y_SIZE, 1, - 0, 0 + {0x004005c0, 1}, + {0x004005c4, 1}, + {0x004005c8, 1}, + {0x004005cc, 1}, + {0x004005d0, 1}, + {0x004005d4, 1}, + {0x004005d8, 1}, + {0x004005dc, 1}, + {0x004005e0, 1}, + {NV03_PGRAPH_MONO_COLOR0, 1}, + {NV04_PGRAPH_ROP3, 1}, + {NV04_PGRAPH_BETA_AND, 1}, + {NV04_PGRAPH_BETA_PREMULT, 1}, + {NV04_PGRAPH_FORMATS, 1}, + {NV04_PGRAPH_BOFFSET0, 6}, + {NV04_PGRAPH_BBASE0, 6}, + {NV04_PGRAPH_BPITCH0, 5}, + {NV04_PGRAPH_BLIMIT0, 6}, + {NV04_PGRAPH_BSWIZZLE2, 1}, + {NV04_PGRAPH_BSWIZZLE5, 1}, + {NV04_PGRAPH_SURFACE, 1}, + {NV04_PGRAPH_STATE, 1}, + {NV04_PGRAPH_NOTIFY, 1}, + {NV04_PGRAPH_BPIXEL, 1}, + {NV04_PGRAPH_DMA_PITCH, 1}, + {NV04_PGRAPH_DVD_COLORFMT, 1}, + {NV04_PGRAPH_SCALED_FORMAT, 1}, + {NV04_PGRAPH_PATT_COLOR0, 1}, + {NV04_PGRAPH_PATT_COLOR1, 1}, + {NV04_PGRAPH_PATTERN, 2}, + {NV04_PGRAPH_PATTERN_SHAPE, 1}, + {NV04_PGRAPH_CHROMA, 1}, + {NV04_PGRAPH_CONTROL0, 1}, + {NV04_PGRAPH_CONTROL1, 1}, + {NV04_PGRAPH_CONTROL2, 1}, + {NV04_PGRAPH_BLEND, 1}, + {NV04_PGRAPH_STORED_FMT, 1}, + {NV04_PGRAPH_PATT_COLORRAM, 64}, + {NV04_PGRAPH_U_RAM, 16}, + {NV04_PGRAPH_V_RAM, 16}, + {NV04_PGRAPH_W_RAM, 16}, + {NV04_PGRAPH_DMA_START_0, 1}, + {NV04_PGRAPH_DMA_START_1, 1}, + {NV04_PGRAPH_DMA_LENGTH, 1}, + {NV04_PGRAPH_DMA_MISC, 1}, + {NV04_PGRAPH_DMA_DATA_0, 1}, + {NV04_PGRAPH_DMA_DATA_1, 1}, + {NV04_PGRAPH_DMA_RM, 1}, + {NV04_PGRAPH_DMA_A_XLATE_INST, 1}, + {NV04_PGRAPH_DMA_A_CONTROL, 1}, + {NV04_PGRAPH_DMA_A_LIMIT, 1}, + {NV04_PGRAPH_DMA_A_TLB_PTE, 1}, + {NV04_PGRAPH_DMA_A_TLB_TAG, 1}, + {NV04_PGRAPH_DMA_A_ADJ_OFFSET, 1}, + {NV04_PGRAPH_DMA_A_OFFSET, 1}, + {NV04_PGRAPH_DMA_A_SIZE, 1}, + {NV04_PGRAPH_DMA_A_Y_SIZE, 1}, + {NV04_PGRAPH_DMA_B_XLATE_INST, 1}, + {NV04_PGRAPH_DMA_B_CONTROL, 1}, + {NV04_PGRAPH_DMA_B_LIMIT, 1}, + {NV04_PGRAPH_DMA_B_TLB_PTE, 1}, + {NV04_PGRAPH_DMA_B_TLB_TAG, 1}, + {NV04_PGRAPH_DMA_B_ADJ_OFFSET, 1}, + {NV04_PGRAPH_DMA_B_OFFSET, 1}, + {NV04_PGRAPH_DMA_B_SIZE, 1}, + {NV04_PGRAPH_DMA_B_Y_SIZE, 1}, }; void nouveau_nv04_context_switch(drm_device_t *dev) { drm_nouveau_private_t *dev_priv = dev->dev_private; - int channel, channel_old, i; + int channel, channel_old, i, j, index; channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); channel_old = (NV_READ(NV04_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); @@ -167,8 +168,13 @@ void nouveau_nv04_context_switch(drm_dev #endif // save PGRAPH context - for (i = 0; nv04_graph_ctx_regs[i]; i++) - dev_priv->fifos[channel_old].pgraph_ctx[i] = NV_READ(nv04_graph_ctx_regs[i]); + index=0; + for (i = 0; i<sizeof(nv04_graph_ctx_regs)/sizeof(nv04_graph_ctx_regs[0]); i++) + for (j = 0; j<nv04_graph_ctx_regs[i].number; j++) + { + dev_priv->fifos[channel_old].pgraph_ctx[index] = NV_READ(nv04_graph_ctx_regs[i].reg+j*4); + index++; + } nouveau_wait_for_idle(dev); @@ -179,14 +185,19 @@ void nouveau_nv04_context_switch(drm_dev // restore PGRAPH context //XXX not working yet #if 1 - for (i = 0; nv04_graph_ctx_regs[i]; i++) - NV_WRITE(nv04_graph_ctx_regs[i], dev_priv->fifos[channel].pgraph_ctx[i]); + index=0; + for (i = 0; i<sizeof(nv04_graph_ctx_regs)/sizeof(nv04_graph_ctx_regs[0]); i++) + for (j = 0; j<nv04_graph_ctx_regs[i].number; j++) + { + NV_WRITE(nv04_graph_ctx_regs[i].reg+j*4, dev_priv->fifos[channel].pgraph_ctx[index]); + index++; + } nouveau_wait_for_idle(dev); #endif NV_WRITE(NV03_PGRAPH_CTX_CONTROL, 0x10010100); NV_WRITE(NV04_PGRAPH_CTX_USER, channel << 24); - //NV_WRITE(NV_PGRAPH_FFINTFC_ST2, NV_READ(NV_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF); + NV_WRITE(NV04_PGRAPH_FFINTFC_ST2, NV_READ(NV04_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF); #if 0 NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); @@ -213,5 +224,14 @@ int nv04_graph_context_create(drm_device int nv04_graph_init(drm_device_t *dev) { + drm_nouveau_private_t *dev_priv = dev->dev_private; + + // check the context is big enough + int i,sum=0; + for ( i = 0 ; i<sizeof(nv04_graph_ctx_regs)/sizeof(nv04_graph_ctx_regs[0]); i++) + sum+=nv04_graph_ctx_regs[i].number; + if ( sum*4>sizeof(dev_priv->fifos[0].pgraph_ctx) ) + DRM_ERROR(); return 0; } + diff-tree d69902db3b1f82dd35f5bbb3327bdf836961850c (from 5a072f32c8f941d1ef301811881e8c89c8d8a5f1) Author: Stephane Marchesin <mar...@ic...> Date: Sat Feb 3 05:25:36 2007 +0100 nouveau: fix nv04 graph routines for new register names. diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index b531a70..05d6e14 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -22,8 +22,8 @@ i830-objs := i830_drv.o i830_dma.o i83 i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \ i915_buffer.o nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ - nouveau_object.o nouveau_irq.o nv10_graph.o nv30_graph.o nv40_graph.o \ - nv20_graph.o + nouveau_object.o nouveau_irq.o nv04_graph.o nv10_graph.o nv20_graph.o nv30_graph.o \ + nv40_graph.o radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o sis-objs := sis_drv.o sis_mm.o ffb-objs := ffb_drv.o ffb_context.o diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 41ea9a5..39fe131 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -91,7 +91,7 @@ struct nouveau_fifo struct nouveau_object *objs; /* XXX dynamic alloc ? */ - uint32_t nv10_pgraph_ctx [340]; + uint32_t pgraph_ctx [340]; }; struct nouveau_config { diff --git a/shared-core/nv04_graph.c b/shared-core/nv04_graph.c index 750a725..47fb8a1 100644 --- a/shared-core/nv04_graph.c +++ b/shared-core/nv04_graph.c @@ -39,37 +39,37 @@ static int nv04_graph_ctx_regs [] = { NV04_PGRAPH_CTX_CACHE2, 8, NV04_PGRAPH_CTX_CACHE3, 8, NV04_PGRAPH_CTX_CACHE4, 8, - NV_PGRAPH_ABS_X_RAM, 32, - NV_PGRAPH_ABS_Y_RAM, 32, - NV_PGRAPH_X_MISC, 1, - NV_PGRAPH_Y_MISC, 1, - NV_PGRAPH_VALID1, 1, - NV_PGRAPH_SOURCE_COLOR, 1, - NV_PGRAPH_MISC24_0, 1, - NV_PGRAPH_XY_LOGIC_MISC0, 1, - NV_PGRAPH_XY_LOGIC_MISC1, 1, - NV_PGRAPH_XY_LOGIC_MISC2, 1, - NV_PGRAPH_XY_LOGIC_MISC3, 1, - NV_PGRAPH_CLIPX_0, 1, - NV_PGRAPH_CLIPX_1, 1, - NV_PGRAPH_CLIPY_0, 1, - NV_PGRAPH_CLIPY_1, 1, - NV_PGRAPH_ABS_ICLIP_XMAX, 1, - NV_PGRAPH_ABS_ICLIP_YMAX, 1, - NV_PGRAPH_ABS_UCLIP_XMIN, 1, - NV_PGRAPH_ABS_UCLIP_YMIN, 1, - NV_PGRAPH_ABS_UCLIP_XMAX, 1, - NV_PGRAPH_ABS_UCLIP_YMAX, 1, - NV_PGRAPH_ABS_UCLIPA_XMIN, 1, - NV_PGRAPH_ABS_UCLIPA_YMIN, 1, - NV_PGRAPH_ABS_UCLIPA_XMAX, 1, - NV_PGRAPH_ABS_UCLIPA_YMAX, 1, - NV_PGRAPH_MISC24_1, 1, - NV_PGRAPH_MISC24_2, 1, - NV_PGRAPH_VALID2, 1, - NV_PGRAPH_PASSTHRU_0, 1, - NV_PGRAPH_PASSTHRU_1, 1, - NV_PGRAPH_PASSTHRU_2, 1, + NV03_PGRAPH_ABS_X_RAM, 32, + NV03_PGRAPH_ABS_Y_RAM, 32, + NV03_PGRAPH_X_MISC, 1, + NV03_PGRAPH_Y_MISC, 1, + NV04_PGRAPH_VALID1, 1, + NV04_PGRAPH_SOURCE_COLOR, 1, + NV04_PGRAPH_MISC24_0, 1, + NV03_PGRAPH_XY_LOGIC_MISC0, 1, + NV03_PGRAPH_XY_LOGIC_MISC1, 1, + NV03_PGRAPH_XY_LOGIC_MISC2, 1, + NV03_PGRAPH_XY_LOGIC_MISC3, 1, + NV03_PGRAPH_CLIPX_0, 1, + NV03_PGRAPH_CLIPX_1, 1, + NV03_PGRAPH_CLIPY_0, 1, + NV03_PGRAPH_CLIPY_1, 1, + NV03_PGRAPH_ABS_ICLIP_XMAX, 1, + NV03_PGRAPH_ABS_ICLIP_YMAX, 1, + NV03_PGRAPH_ABS_UCLIP_XMIN, 1, + NV03_PGRAPH_ABS_UCLIP_YMIN, 1, + NV03_PGRAPH_ABS_UCLIP_XMAX, 1, + NV03_PGRAPH_ABS_UCLIP_YMAX, 1, + NV03_PGRAPH_ABS_UCLIPA_XMIN, 1, + NV03_PGRAPH_ABS_UCLIPA_YMIN, 1, + NV03_PGRAPH_ABS_UCLIPA_XMAX, 1, + NV03_PGRAPH_ABS_UCLIPA_YMAX, 1, + NV04_PGRAPH_MISC24_1, 1, + NV04_PGRAPH_MISC24_2, 1, + NV04_PGRAPH_VALID2, 1, + NV04_PGRAPH_PASSTHRU_0, 1, + NV04_PGRAPH_PASSTHRU_1, 1, + NV04_PGRAPH_PASSTHRU_2, 1, NV04_PGRAPH_COMBINE_0_ALPHA, 1, NV04_PGRAPH_COMBINE_0_COLOR, 1, NV04_PGRAPH_COMBINE_1_ALPHA, 1, @@ -89,77 +89,77 @@ static int nv04_graph_ctx_regs [] = { 0x004005d8, 1, 0x004005dc, 1, 0x004005e0, 1, - NV_PGRAPH_MONO_COLOR0, 1, - NV_PGRAPH_ROP3, 1, - NV_PGRAPH_BETA_AND, 1, - NV_PGRAPH_BETA_PREMULT, 1, - NV_PGRAPH_FORMATS, 1, - NV_PGRAPH_BOFFSET0, 6, - NV_PGRAPH_BBASE0, 6, - NV_PGRAPH_BPITCH0, 5, - NV_PGRAPH_BLIMIT0, 6, - NV_PGRAPH_BSWIZZLE2, 1, - NV_PGRAPH_BSWIZZLE5, 1, + NV03_PGRAPH_MONO_COLOR0, 1, + NV04_PGRAPH_ROP3, 1, + NV04_PGRAPH_BETA_AND, 1, + NV04_PGRAPH_BETA_PREMULT, 1, + NV04_PGRAPH_FORMATS, 1, + NV04_PGRAPH_BOFFSET0, 6, + NV04_PGRAPH_BBASE0, 6, + NV04_PGRAPH_BPITCH0, 5, + NV04_PGRAPH_BLIMIT0, 6, + NV04_PGRAPH_BSWIZZLE2, 1, + NV04_PGRAPH_BSWIZZLE5, 1, NV04_PGRAPH_SURFACE, 1, - NV_PGRAPH_STATE, 1, - NV_PGRAPH_NOTIFY, 1, - NV_PGRAPH_BPIXEL, 1, + NV04_PGRAPH_STATE, 1, + NV04_PGRAPH_NOTIFY, 1, + NV04_PGRAPH_BPIXEL, 1, NV04_PGRAPH_DMA_PITCH, 1, NV04_PGRAPH_DVD_COLORFMT, 1, NV04_PGRAPH_SCALED_FORMAT, 1, - NV_PGRAPH_PATT_COLOR0, 1, - NV_PGRAPH_PATT_COLOR1, 1, - NV_PGRAPH_PATTERN, 2, - NV_PGRAPH_PATTERN_SHAPE, 1, - NV_PGRAPH_CHROMA, 1, + NV04_PGRAPH_PATT_COLOR0, 1, + NV04_PGRAPH_PATT_COLOR1, 1, + NV04_PGRAPH_PATTERN, 2, + NV04_PGRAPH_PATTERN_SHAPE, 1, + NV04_PGRAPH_CHROMA, 1, NV04_PGRAPH_CONTROL0, 1, NV04_PGRAPH_CONTROL1, 1, NV04_PGRAPH_CONTROL2, 1, NV04_PGRAPH_BLEND, 1, - NV_PGRAPH_STORED_FMT, 1, - NV_PGRAPH_PATT_COLORRAM, 64, + NV04_PGRAPH_STORED_FMT, 1, + NV04_PGRAPH_PATT_COLORRAM, 64, NV04_PGRAPH_U_RAM, 16, NV04_PGRAPH_V_RAM, 16, NV04_PGRAPH_W_RAM, 16, - NV_PGRAPH_DMA_START_0, 1, - NV_PGRAPH_DMA_START_1, 1, - NV_PGRAPH_DMA_LENGTH, 1, - NV_PGRAPH_DMA_MISC, 1, - NV_PGRAPH_DMA_DATA_0, 1, - NV_PGRAPH_DMA_DATA_1, 1, - NV_PGRAPH_DMA_RM, 1, - NV_PGRAPH_DMA_A_XLATE_INST, 1, - NV_PGRAPH_DMA_A_CONTROL, 1, - NV_PGRAPH_DMA_A_LIMIT, 1, - NV_PGRAPH_DMA_A_TLB_PTE, 1, - NV_PGRAPH_DMA_A_TLB_TAG, 1, - NV_PGRAPH_DMA_A_ADJ_OFFSET, 1, - NV_PGRAPH_DMA_A_OFFSET, 1, - NV_PGRAPH_DMA_A_SIZE, 1, - NV_PGRAPH_DMA_A_Y_SIZE, 1, - NV_PGRAPH_DMA_B_XLATE_INST, 1, - NV_PGRAPH_DMA_B_CONTROL, 1, - NV_PGRAPH_DMA_B_LIMIT, 1, - NV_PGRAPH_DMA_B_TLB_PTE, 1, - NV_PGRAPH_DMA_B_TLB_TAG, 1, - NV_PGRAPH_DMA_B_ADJ_OFFSET, 1, - NV_PGRAPH_DMA_B_OFFSET, 1, - NV_PGRAPH_DMA_B_SIZE, 1, - NV_PGRAPH_DMA_B_Y_SIZE, 1, + NV04_PGRAPH_DMA_START_0, 1, + NV04_PGRAPH_DMA_START_1, 1, + NV04_PGRAPH_DMA_LENGTH, 1, + NV04_PGRAPH_DMA_MISC, 1, + NV04_PGRAPH_DMA_DATA_0, 1, + NV04_PGRAPH_DMA_DATA_1, 1, + NV04_PGRAPH_DMA_RM, 1, + NV04_PGRAPH_DMA_A_XLATE_INST, 1, + NV04_PGRAPH_DMA_A_CONTROL, 1, + NV04_PGRAPH_DMA_A_LIMIT, 1, + NV04_PGRAPH_DMA_A_TLB_PTE, 1, + NV04_PGRAPH_DMA_A_TLB_TAG, 1, + NV04_PGRAPH_DMA_A_ADJ_OFFSET, 1, + NV04_PGRAPH_DMA_A_OFFSET, 1, + NV04_PGRAPH_DMA_A_SIZE, 1, + NV04_PGRAPH_DMA_A_Y_SIZE, 1, + NV04_PGRAPH_DMA_B_XLATE_INST, 1, + NV04_PGRAPH_DMA_B_CONTROL, 1, + NV04_PGRAPH_DMA_B_LIMIT, 1, + NV04_PGRAPH_DMA_B_TLB_PTE, 1, + NV04_PGRAPH_DMA_B_TLB_TAG, 1, + NV04_PGRAPH_DMA_B_ADJ_OFFSET, 1, + NV04_PGRAPH_DMA_B_OFFSET, 1, + NV04_PGRAPH_DMA_B_SIZE, 1, + NV04_PGRAPH_DMA_B_Y_SIZE, 1, 0, 0 }; void nouveau_nv04_context_switch(drm_device_t *dev) { drm_nouveau_private_t *dev_priv = dev->dev_private; - int channel, channel_old, i, j, gpu_type; + int channel, channel_old, i; - channel=NV_READ(NV_PFIFO_CACH1_PSH1)&(nouveau_fifo_number(dev)-1); - channel_old = (NV_READ(NV_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); + channel_old = (NV_READ(NV04_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); DRM_INFO("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel); - NV_WRITE(NV_PGRAPH_FIFO,0x0); + NV_WRITE(NV04_PGRAPH_FIFO,0x0); #if 0 NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000000); NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000000); @@ -168,45 +168,45 @@ void nouveau_nv04_context_switch(drm_dev // save PGRAPH context for (i = 0; nv04_graph_ctx_regs[i]; i++) - dev_priv->fifos[channel_old].nv04_pgraph_ctx[i] = NV_READ(nv04_graph_ctx_regs[i]); + dev_priv->fifos[channel_old].pgraph_ctx[i] = NV_READ(nv04_graph_ctx_regs[i]); nouveau_wait_for_idle(dev); - NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10000000); - NV_WRITE(NV_PGRAPH_CTX_USER, (NV_READ(NV_PGRAPH_CTX_USER) & 0xffffff) | (0x1f << 24)); + NV_WRITE(NV03_PGRAPH_CTX_CONTROL, 0x10000000); + NV_WRITE(NV04_PGRAPH_CTX_USER, (NV_READ(NV04_PGRAPH_CTX_USER) & 0xffffff) | (0x1f << 24)); nouveau_wait_for_idle(dev); // restore PGRAPH context //XXX not working yet #if 1 for (i = 0; nv04_graph_ctx_regs[i]; i++) - NV_WRITE(nv04_graph_ctx_regs[i], dev_priv->fifos[channel].nv04_pgraph_ctx[i]); + NV_WRITE(nv04_graph_ctx_regs[i], dev_priv->fifos[channel].pgraph_ctx[i]); nouveau_wait_for_idle(dev); #endif - - NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10010100); - NV_WRITE(NV_PGRAPH_CTX_USER, channel << 24); - NV_WRITE(NV_PGRAPH_FFINTFC_ST2, NV_READ(NV_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF); + + NV_WRITE(NV03_PGRAPH_CTX_CONTROL, 0x10010100); + NV_WRITE(NV04_PGRAPH_CTX_USER, channel << 24); + //NV_WRITE(NV_PGRAPH_FFINTFC_ST2, NV_READ(NV_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF); #if 0 NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000001); NV_WRITE(NV_PFIFO_CACHES, 0x00000001); #endif - NV_WRITE(NV_PGRAPH_FIFO,0x1); + NV_WRITE(NV04_PGRAPH_FIFO,0x1); } int nv04_graph_context_create(drm_device_t *dev, int channel) { drm_nouveau_private_t *dev_priv = dev->dev_private; DRM_DEBUG("nv04_graph_context_create %d\n", channel); - memset(dev_priv->fifos[channel].nv04_pgraph_ctx, 0, sizeof(dev_priv->fifos[channel].nv04_pgraph_ctx)); + memset(dev_priv->fifos[channel].pgraph_ctx, 0, sizeof(dev_priv->fifos[channel].pgraph_ctx)); //dev_priv->fifos[channel].pgraph_ctx_user = channel << 24; - dev_priv->fifos[channel].nv04_pgraph_ctx[0] = 0x0001ffff; + dev_priv->fifos[channel].pgraph_ctx[0] = 0x0001ffff; /* is it really needed ??? */ - dev_priv->fifos[channel].nv04_pgraph_ctx[1] = NV_READ(NV_PGRAPH_DEBUG_4); - dev_priv->fifos[channel].nv04_pgraph_ctx[2] = NV_READ(0x004006b0); + //dev_priv->fifos[channel].pgraph_ctx[1] = NV_READ(NV_PGRAPH_DEBUG_4); + //dev_priv->fifos[channel].pgraph_ctx[2] = NV_READ(0x004006b0); return 0; } diff --git a/shared-core/nv10_graph.c b/shared-core/nv10_graph.c index fe9a6a4..ad74b84 100644 --- a/shared-core/nv10_graph.c +++ b/shared-core/nv10_graph.c @@ -546,10 +546,10 @@ void nouveau_nv10_context_switch(drm_dev // save PGRAPH context for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++) - dev_priv->fifos[channel_old].nv10_pgraph_ctx[i] = NV_READ(nv10_graph_ctx_regs[i]); + dev_priv->fifos[channel_old].pgraph_ctx[i] = NV_READ(nv10_graph_ctx_regs[i]); if (dev_priv->chipset>=0x17) { for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++) - dev_priv->fifos[channel_old].nv10_pgraph_ctx[i] = NV_READ(nv17_graph_ctx_regs[j]); + dev_priv->fifos[channel_old].pgraph_ctx[i] = NV_READ(nv17_graph_ctx_regs[j]); } nouveau_wait_for_idle(dev); @@ -562,10 +562,10 @@ void nouveau_nv10_context_switch(drm_dev //XXX not working yet #if 1 for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++) - NV_WRITE(nv10_graph_ctx_regs[i], dev_priv->fifos[channel].nv10_pgraph_ctx[i]); + NV_WRITE(nv10_graph_ctx_regs[i], dev_priv->fifos[channel].pgraph_ctx[i]); if (dev_priv->chipset>=0x17) { for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++) - NV_WRITE(nv17_graph_ctx_regs[j], dev_priv->fifos[channel].nv10_pgraph_ctx[i]); + NV_WRITE(nv17_graph_ctx_regs[j], dev_priv->fifos[channel].pgraph_ctx[i]); } nouveau_wait_for_idle(dev); #endif @@ -586,14 +586,14 @@ int nv10_graph_context_create(drm_device drm_nouveau_private_t *dev_priv = dev->dev_private; DRM_DEBUG("nv10_graph_context_create %d\n", channel); - memset(dev_priv->fifos[channel].nv10_pgraph_ctx, 0, sizeof(dev_priv->fifos[channel].nv10_pgraph_ctx)); + memset(dev_priv->fifos[channel].pgraph_ctx, 0, sizeof(dev_priv->fifos[channel].pgraph_ctx)); //dev_priv->fifos[channel].pgraph_ctx_user = channel << 24; - dev_priv->fifos[channel].nv10_pgraph_ctx[0] = 0x0001ffff; + dev_priv->fifos[channel].pgraph_ctx[0] = 0x0001ffff; /* is it really needed ??? */ if (dev_priv->chipset>=0x17) { - dev_priv->fifos[channel].nv10_pgraph_ctx[sizeof(nv10_graph_ctx_regs) + 0] = NV_READ(NV10_PGRAPH_DEBUG_4); - dev_priv->fifos[channel].nv10_pgraph_ctx[sizeof(nv10_graph_ctx_regs) + 1] = NV_READ(0x004006b0); + dev_priv->fifos[channel].pgraph_ctx[sizeof(nv10_graph_ctx_regs) + 0] = NV_READ(NV10_PGRAPH_DEBUG_4); + dev_priv->fifos[channel].pgraph_ctx[sizeof(nv10_graph_ctx_regs) + 1] = NV_READ(0x004006b0); } diff-tree 5a072f32c8f941d1ef301811881e8c89c8d8a5f1 (from e64dbef911cd739ba5c4d26493dfef6766ff83fd) Author: Stephane Marchesin <mar...@ic...> Date: Sat Feb 3 04:57:06 2007 +0100 nouveau: rename registers to their proper names. diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index b035ed0..d0312a3 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -82,7 +82,7 @@ static int nouveau_fifo_instmem_configur dev_priv->ramht_offset = 0x10000; dev_priv->ramht_bits = 9; dev_priv->ramht_size = (1 << dev_priv->ramht_bits); - NV_WRITE(NV_PFIFO_RAMHT, + NV_WRITE(NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | ((dev_priv->ramht_bits - 9) << 16) | (dev_priv->ramht_offset >> 8) @@ -94,7 +94,7 @@ static int nouveau_fifo_instmem_configur /* FIFO runout table (RAMRO) - 512k at 0x11200 */ dev_priv->ramro_offset = 0x11200; dev_priv->ramro_size = 512; - NV_WRITE(NV_PFIFO_RAMRO, dev_priv->ramro_offset>>8); + NV_WRITE(NV03_PFIFO_RAMRO, dev_priv->ramro_offset>>8); DRM_DEBUG("RAMRO offset=0x%x, size=%d\n", dev_priv->ramro_offset, dev_priv->ramro_size); @@ -124,14 +124,14 @@ static int nouveau_fifo_instmem_configur case NV_10: dev_priv->ramfc_offset = 0x11400; dev_priv->ramfc_size = nouveau_fifo_number(dev) * nouveau_fifo_ctx_size(dev); - NV_WRITE(NV_PFIFO_RAMFC, (dev_priv->ramfc_offset>>8) | + NV_WRITE(NV03_PFIFO_RAMFC, (dev_priv->ramfc_offset>>8) | (1 << 16) /* 64 Bytes entry*/); break; case NV_04: case NV_03: dev_priv->ramfc_offset = 0x11400; dev_priv->ramfc_size = nouveau_fifo_number(dev) * nouveau_fifo_ctx_size(dev); - NV_WRITE(NV_PFIFO_RAMFC, dev_priv->ramfc_offset>>8); + NV_WRITE(NV03_PFIFO_RAMFC, dev_priv->ramfc_offset>>8); break; } DRM_DEBUG("RAMFC offset=0x%x, size=%d\n", @@ -150,7 +150,7 @@ int nouveau_fifo_init(drm_device_t *dev) drm_nouveau_private_t *dev_priv = dev->dev_private; int ret; - NV_WRITE(NV_PFIFO_CACHES, 0x00000000); + NV_WRITE(NV03_PFIFO_CACHES, 0x00000000); ret = nouveau_fifo_instmem_configure(dev); if (ret) { @@ -163,48 +163,49 @@ int nouveau_fifo_init(drm_device_t *dev) DRM_DEBUG("Setting defaults for remaining PFIFO regs\n"); /* All channels into PIO mode */ - NV_WRITE(NV_PFIFO_MODE, 0x00000000); + NV_WRITE(NV04_PFIFO_MODE, 0x00000000); - NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000000); - NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000000); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000); /* Channel 0 active, PIO mode */ - NV_WRITE(NV_PFIFO_CACH1_PSH1, 0x00000000); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, 0x00000000); /* PUT and GET to 0 */ - NV_WRITE(NV_PFIFO_CACH1_DMAP, 0x00000000); - NV_WRITE(NV_PFIFO_CACH1_DMAP, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT, 0x00000000); /* No cmdbuf object */ - NV_WRITE(NV_PFIFO_CACH1_DMAI, 0x00000000); - NV_WRITE(NV_PFIFO_CACH0_PSH0, 0x00000000); - NV_WRITE(NV_PFIFO_CACH0_PUL0, 0x00000000); - NV_WRITE(NV_PFIFO_SIZE, 0x0000FFFF); - NV_WRITE(NV_PFIFO_CACH1_HASH, 0x0000FFFF); - NV_WRITE(NV_PFIFO_CACH0_PUL1, 0x00000001); - NV_WRITE(NV_PFIFO_CACH1_DMAC, 0x00000000); - NV_WRITE(NV_PFIFO_CACH1_DMAS, 0x00000000); - NV_WRITE(NV_PFIFO_CACH1_ENG, 0x00000000); - - NV_WRITE(NV_PFIFO_CACH1_DMAF, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES | - NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | - NV_PFIFO_CACH1_DMAF_MAX_REQS_4 | + NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, 0x00000000); + NV_WRITE(NV03_PFIFO_CACHE0_PUSH0, 0x00000000); + NV_WRITE(NV03_PFIFO_CACHE0_PULL0, 0x00000000); + NV_WRITE(NV04_PFIFO_SIZE, 0x0000FFFF); + NV_WRITE(NV04_PFIFO_CACHE1_HASH, 0x0000FFFF); + NV_WRITE(NV04_PFIFO_CACHE0_PULL1, 0x00000001); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_ENGINE, 0x00000000); + + NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 | #ifdef __BIG_ENDIAN NV_PFIFO_CACH1_BIG_ENDIAN | #endif 0x00000000); - NV_WRITE(NV_PFIFO_CACH1_DMAPSH, 0x00000001); - NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000001); - NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); - NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000001); - - NV_WRITE(NV_PGRAPH_CTX_USER, 0x0); - NV_WRITE(NV_PFIFO_DELAY_0, 0xff /* retrycount*/ ); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000001); + NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000001); + NV_WRITE(NV04_PFIFO_CACHE1_PULL1, 0x00000001); + + /* FIXME on NV04 */ + NV_WRITE(NV10_PGRAPH_CTX_USER, 0x0); + NV_WRITE(NV04_PFIFO_DELAY_0, 0xff /* retrycount*/ ); if (dev_priv->card_type >= NV_40) - NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x00002001); + NV_WRITE(NV03_PGRAPH_CTX_CONTROL, 0x00002001); else - NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10110000); + NV_WRITE(NV03_PGRAPH_CTX_CONTROL, 0x10110000); - NV_WRITE(NV_PFIFO_DMA_TIMESLICE, 0x001fffff); - NV_WRITE(NV_PFIFO_CACHES, 0x00000001); + NV_WRITE(NV04_PFIFO_DMA_TIMESLICE, 0x001fffff); + NV_WRITE(NV03_PFIFO_CACHES, 0x00000001); return 0; } @@ -283,9 +284,9 @@ static void nouveau_nv04_context_init(dr RAMFC_WR(DMA_GET , init->put_base); RAMFC_WR(DMA_INSTANCE , nouveau_chip_instance_get(dev, cb_obj->instance)); - RAMFC_WR(DMA_FETCH, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES | - NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | - NV_PFIFO_CACH1_DMAF_MAX_REQS_4 | + RAMFC_WR(DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 | #ifdef __BIG_ENDIAN NV_PFIFO_CACH1_BIG_ENDIAN | #endif @@ -316,9 +317,9 @@ static void nouveau_nv10_context_init(dr RAMFC_WR(DMA_INSTANCE , nouveau_chip_instance_get(dev, cb_obj->instance)); - RAMFC_WR(DMA_FETCH, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES | - NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | - NV_PFIFO_CACH1_DMAF_MAX_REQS_4 | + RAMFC_WR(DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 | #ifdef __BIG_ENDIAN NV_PFIFO_CACH1_BIG_ENDIAN | #endif @@ -344,23 +345,23 @@ static void nouveau_nv30_context_init(dr RAMFC_WR(DMA_PUT, init->put_base); RAMFC_WR(DMA_GET, init->put_base); - RAMFC_WR(REF_CNT, NV_READ(NV_PFIFO_CACH1_REF_CNT)); + RAMFC_WR(REF_CNT, NV_READ(NV10_PFIFO_CACHE1_REF_CNT)); RAMFC_WR(DMA_INSTANCE, cb_inst); - RAMFC_WR(DMA_STATE, NV_READ(NV_PFIFO_CACH1_DMAS)); - RAMFC_WR(DMA_FETCH, NV_PFIFO_CACH1_DMAF_TRIG_128_BYTES | - NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | - NV_PFIFO_CACH1_DMAF_MAX_REQS_8 | + RAMFC_WR(DMA_STATE, NV_READ(NV04_PFIFO_CACHE1_DMA_STATE)); + RAMFC_WR(DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | #ifdef __BIG_ENDIAN NV_PFIFO_CACH1_BIG_ENDIAN | #endif 0x00000000); - RAMFC_WR(ENGINE, NV_READ(NV_PFIFO_CACH1_ENG)); - RAMFC_WR(PULL1_ENGINE, NV_READ(NV_PFIFO_CACH1_PUL1)); - RAMFC_WR(ACQUIRE_VALUE, NV_READ(NV_PFIFO_CACH1_ACQUIRE_VALUE)); - RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV_PFIFO_CACH1_ACQUIRE_TIMESTAMP)); - RAMFC_WR(ACQUIRE_TIMEOUT, NV_READ(NV_PFIFO_CACH1_ACQUIRE_TIMEOUT)); - RAMFC_WR(SEMAPHORE, NV_READ(NV_PFIFO_CACH1_SEMAPHORE)); + RAMFC_WR(ENGINE, NV_READ(NV04_PFIFO_CACHE1_ENGINE)); + RAMFC_WR(PULL1_ENGINE, NV_READ(NV04_PFIFO_CACHE1_PULL1)); + RAMFC_WR(ACQUIRE_VALUE, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE)); + RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP)); + RAMFC_WR(ACQUIRE_TIMEOUT, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT)); + RAMFC_WR(SEMAPHORE, NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE)); RAMFC_WR(DMA_SUBROUTINE, init->put_base); } @@ -371,22 +372,22 @@ static void nouveau_nv10_context_save(dr uint32_t fifoctx; int channel; - channel = NV_READ(NV_PFIFO_CACH1_PSH1) & (nouveau_fifo_number(dev)-1); + channel = NV_READ(NV03_PFIFO_CACHE1_PUSH1) & (nouveau_fifo_number(dev)-1); fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel*64; - RAMFC_WR(DMA_PUT , NV_READ(NV_PFIFO_CACH1_DMAP)); - RAMFC_WR(DMA_GET , NV_READ(NV_PFIFO_CACH1_DMAG)); - RAMFC_WR(REF_CNT , NV_READ(NV_PFIFO_CACH1_REF_CNT)); - RAMFC_WR(DMA_INSTANCE , NV_READ(NV_PFIFO_CACH1_DMAI)); - RAMFC_WR(DMA_STATE , NV_READ(NV_PFIFO_CACH1_DMAS)); - RAMFC_WR(DMA_FETCH , NV_READ(NV_PFIFO_CACH1_DMAF)); - RAMFC_WR(ENGINE , NV_READ(NV_PFIFO_CACH1_ENG)); - RAMFC_WR(PULL1_ENGINE , NV_READ(NV_PFIFO_CACH1_PUL1)); - RAMFC_WR(ACQUIRE_VALUE , NV_READ(NV_PFIFO_CACH1_ACQUIRE_VALUE)); - RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV_PFIFO_CACH1_ACQUIRE_TIMESTAMP)); - RAMFC_WR(ACQUIRE_TIMEOUT , NV_READ(NV_PFIFO_CACH1_ACQUIRE_TIMEOUT)); - RAMFC_WR(SEMAPHORE , NV_READ(NV_PFIFO_CACH1_SEMAPHORE)); - RAMFC_WR(DMA_SUBROUTINE , NV_READ(NV_PFIFO_CACH1_DMASR)); + RAMFC_WR(DMA_PUT , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT)); + RAMFC_WR(DMA_GET , NV_READ(NV04_PFIFO_CACHE1_DMA_GET)); + RAMFC_WR(REF_CNT , NV_READ(NV10_PFIFO_CACHE1_REF_CNT)); + RAMFC_WR(DMA_INSTANCE , NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE)); + RAMFC_WR(DMA_STATE , NV_READ(NV04_PFIFO_CACHE1_DMA_STATE)); + RAMFC_WR(DMA_FETCH , NV_READ(NV04_PFIFO_CACHE1_DMA_FETCH)); + RAMFC_WR(ENGINE , NV_READ(NV04_PFIFO_CACHE1_ENGINE)); + RAMFC_WR(PULL1_ENGINE , NV_READ(NV04_PFIFO_CACHE1_PULL1)); + RAMFC_WR(ACQUIRE_VALUE , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE)); + RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP)); + RAMFC_WR(ACQUIRE_TIMEOUT , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT)); + RAMFC_WR(SEMAPHORE , NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE)); + RAMFC_WR(DMA_SUBROUTINE , NV_READ(NV10_PFIFO_CACHE1_DMA_SUBROUTINE)); } #undef RAMFC_WR @@ -411,9 +412,9 @@ static void nouveau_nv40_context_init(dr RAMFC_WR(DMA_PUT , init->put_base); RAMFC_WR(DMA_GET , init->put_base); RAMFC_WR(DMA_INSTANCE , cb_inst); - RAMFC_WR(DMA_FETCH , NV_PFIFO_CACH1_DMAF_TRIG_128_BYTES | - NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | - NV_PFIFO_CACH1_DMAF_MAX_REQS_8 | + RAMFC_WR(DMA_FETCH , NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | #ifdef __BIG_ENDIAN NV_PFIFO_CACH1_BIG_ENDIAN | #endif @@ -429,25 +430,25 @@ static void nouveau_nv40_context_save(dr uint32_t fifoctx; int channel; - channel = NV_READ(NV_PFIFO_CACH1_PSH1) & (nouveau_fifo_number(dev)-1); + channel = NV_READ(NV03_PFIFO_CACHE1_PUSH1) & (nouveau_fifo_number(dev)-1); fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel*128; - RAMFC_WR(DMA_PUT , NV_READ(NV_PFIFO_CACH1_DMAP)); - RAMFC_WR(DMA_GET , NV_READ(NV_PFIFO_CACH1_DMAG)); - RAMFC_WR(REF_CNT , NV_READ(NV_PFIFO_CACH1_REF_CNT)); - RAMFC_WR(DMA_INSTANCE , NV_READ(NV_PFIFO_CACH1_DMAI)); - RAMFC_WR(DMA_DCOUNT , NV_READ(NV_PFIFO_CACH1_DMA_DCOUNT)); - RAMFC_WR(DMA_STATE , NV_READ(NV_PFIFO_CACH1_DMAS)); - RAMFC_WR(DMA_FETCH , NV_READ(NV_PFIFO_CACH1_DMAF)); - RAMFC_WR(ENGINE , NV_READ(NV_PFIFO_CACH1_ENG)); - RAMFC_WR(PULL1_ENGINE , NV_READ(NV_PFIFO_CACH1_PUL1)); - RAMFC_WR(ACQUIRE_VALUE , NV_READ(NV_PFIFO_CACH1_ACQUIRE_VALUE)); - RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV_PFIFO_CACH1_ACQUIRE_TIMESTAMP)); - RAMFC_WR(ACQUIRE_TIMEOUT , NV_READ(NV_PFIFO_CACH1_ACQUIRE_TIMEOUT)); - RAMFC_WR(SEMAPHORE , NV_READ(NV_PFIFO_CACH1_SEMAPHORE)); - RAMFC_WR(DMA_SUBROUTINE , NV_READ(NV_PFIFO_CACH1_DMAG)); + RAMFC_WR(DMA_PUT , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT)); + RAMFC_WR(DMA_GET , NV_READ(NV04_PFIFO_CACHE1_DMA_GET)); + RAMFC_WR(REF_CNT , NV_READ(NV10_PFIFO_CACHE1_REF_CNT)); + RAMFC_WR(DMA_INSTANCE , NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE)); + RAMFC_WR(DMA_DCOUNT , NV_READ(NV10_PFIFO_CACHE1_DMA_DCOUNT)); + RAMFC_WR(DMA_STATE , NV_READ(NV04_PFIFO_CACHE1_DMA_STATE)); + RAMFC_WR(DMA_FETCH , NV_READ(NV04_PFIFO_CACHE1_DMA_FETCH)); + RAMFC_WR(ENGINE , NV_READ(NV04_PFIFO_CACHE1_ENGINE)); + RAMFC_WR(PULL1_ENGINE , NV_READ(NV04_PFIFO_CACHE1_PULL1)); + RAMFC_WR(ACQUIRE_VALUE , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE)); + RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP)); + RAMFC_WR(ACQUIRE_TIMEOUT , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT)); + RAMFC_WR(SEMAPHORE , NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE)); + RAMFC_WR(DMA_SUBROUTINE , NV_READ(NV04_PFIFO_CACHE1_DMA_GET)); RAMFC_WR(GRCTX_INSTANCE , NV_READ(NV40_PFIFO_GRCTX_INSTANCE)); - RAMFC_WR(DMA_TIMESLICE , NV_READ(NV_PFIFO_DMA_TIMESLICE) & 0x1FFFF); + RAMFC_WR(DMA_TIMESLICE , NV_READ(NV04_PFIFO_DMA_TIMESLICE) & 0x1FFFF); RAMFC_WR(UNK_40 , NV_READ(NV40_PFIFO_UNK32E4)); } #undef RAMFC_WR @@ -468,24 +469,24 @@ nouveau_fifo_context_restore(drm_device_ // FIXME check if we need to refill the time quota with something like NV_WRITE(0x204C, 0x0003FFFF); if (dev_priv->card_type >= NV_40) - NV_WRITE(NV_PFIFO_CACH1_PSH1, 0x00010000|channel); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, 0x00010000|channel); else - NV_WRITE(NV_PFIFO_CACH1_PSH1, 0x00000100|channel); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, 0x00000100|channel); - NV_WRITE(NV_PFIFO_CACH1_DMAP, 0 /*RAMFC_DMA_PUT*/); - NV_WRITE(NV_PFIFO_CACH1_DMAG, 0 /*RAMFC_DMA_GET*/); - NV_WRITE(NV_PFIFO_CACH1_DMAI, cb_inst); - NV_WRITE(NV_PFIFO_SIZE , 0x0000FFFF); - NV_WRITE(NV_PFIFO_CACH1_HASH, 0x0000FFFF); - - NV_WRITE(NV_PFIFO_CACH0_PUL1, 0x00000001); - NV_WRITE(NV_PFIFO_CACH1_DMAC, 0x00000000); - NV_WRITE(NV_PFIFO_CACH1_DMAS, 0x00000000); - NV_WRITE(NV_PFIFO_CACH1_ENG, 0x00000000); - - NV_WRITE(NV_PFIFO_CACH1_DMAF, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES | - NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | - NV_PFIFO_CACH1_DMAF_MAX_REQS_4 | + NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT, 0 /*RAMFC_DMA_PUT*/); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, 0 /*RAMFC_DMA_GET*/); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, cb_inst); + NV_WRITE(NV04_PFIFO_SIZE , 0x0000FFFF); + NV_WRITE(NV04_PFIFO_CACHE1_HASH, 0x0000FFFF); + + NV_WRITE(NV04_PFIFO_CACHE0_PULL1, 0x00000001); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_ENGINE, 0x00000000); + + NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 | #ifdef __BIG_ENDIAN NV_PFIFO_CACH1_BIG_ENDIAN | #endif @@ -533,42 +534,52 @@ static int nouveau_fifo_alloc(drm_device nouveau_wait_for_idle(dev); /* disable the fifo caches */ - NV_WRITE(NV_PFIFO_CACHES, 0x00000000); - NV_WRITE(NV_PFIFO_CACH1_DMAPSH, NV_READ(NV_PFIFO_CACH1_DMAPSH)&(~0x1)); - NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000000); - NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000000); + NV_WRITE(NV03_PFIFO_CACHES, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, NV_READ(NV04_PFIFO_CACHE1_DMA_PUSH)&(~0x1)); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000); /* Construct inital RAMFC for new channel */ - if (dev_priv->card_type < NV_10) { - nouveau_nv04_context_init(dev, init); - } else if (dev_priv->card_type < NV_20) { - nv10_graph_context_create(dev, init->channel); - nouveau_nv10_context_init(dev, init); - } else if (dev_priv->card_type < NV_30) { - ret = nv20_graph_context_create(dev, init->channel); - if (ret) { - nouveau_fifo_free(dev, init->channel); - return ret; - } - nouveau_nv10_context_init(dev, init); - } else if (dev_priv->card_type < NV_40) { - ret = nv30_graph_context_create(dev, init->channel); - if (ret) { - nouveau_fifo_free(dev, init->channel); - return ret; - } - nouveau_nv30_context_init(dev, init); - } else { - ret = nv40_graph_context_create(dev, init->channel); - if (ret) { - nouveau_fifo_free(dev, init->channel); - return ret; - } - nouveau_nv40_context_init(dev, init); + switch(dev_priv->card_type) + { + case NV_04: + case NV_05: + nouveau_nv04_context_init(dev, init); + break; + case NV_10: + nv10_graph_context_create(dev, init->channel); + nouveau_nv10_context_init(dev, init); + break; + case NV_20: + ret = nv20_graph_context_create(dev, init->channel); + if (ret) { + nouveau_fifo_free(dev, init->channel); + return ret; + } + nouveau_nv10_context_init(dev, init); + break; + case NV_30: + ret = nv30_graph_context_create(dev, init->channel); + if (ret) { + nouveau_fifo_free(dev, init->channel); + return ret; + } + nouveau_nv30_context_init(dev, init); + break; + case NV_40: + case NV_44: + case NV_50: + ret = nv40_graph_context_create(dev, init->channel); + if (ret) { + nouveau_fifo_free(dev, init->channel); + return ret; + } + nouveau_nv40_context_init(dev, init); + break; } /* enable the fifo dma operation */ - NV_WRITE(NV_PFIFO_MODE,NV_READ(NV_PFIFO_MODE)|(1<<init->channel)); + NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<<init->channel)); /* setup channel's default get/put values */ NV_WRITE(NV03_FIFO_REGS_DMAPUT(init->channel), init->put_base); @@ -588,7 +599,7 @@ static int nouveau_fifo_alloc(drm_device chan->ramin_grctx); /* see comments in nv40_graph_context_restore() */ - NV_WRITE(NV_PGRAPH_CHANNEL_CTX_SIZE, inst); + NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_SIZE, inst); if (dev_priv->card_type >= NV_40) { NV_WRITE(0x40032C, inst | 0x01000000); NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE, inst); @@ -596,13 +607,13 @@ static int nouveau_fifo_alloc(drm_device } } - NV_WRITE(NV_PFIFO_CACH1_DMAPSH, 0x00000001); - NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000001); - NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); - NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000001); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000001); + NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000001); + NV_WRITE(NV04_PFIFO_CACHE1_PULL1, 0x00000001); /* reenable the fifo caches */ - NV_WRITE(NV_PFIFO_CACHES, 0x00000001); + NV_WRITE(NV03_PFIFO_CACHES, 0x00000001); /* make the fifo available to user space */ /* first, the fifo control regs */ @@ -636,9 +647,9 @@ void nouveau_fifo_free(drm_device_t* dev DRM_INFO("%s: freeing fifo %d\n", __func__, n); /* disable the fifo caches */ - NV_WRITE(NV_PFIFO_CACHES, 0x00000000); + NV_WRITE(NV03_PFIFO_CACHES, 0x00000000); - NV_WRITE(NV_PFIFO_MODE,NV_READ(NV_PFIFO_MODE)&~(1<<n)); + NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)&~(1<<n)); // FIXME XXX needs more code /* Clean RAMFC */ @@ -659,7 +670,7 @@ void nouveau_fifo_free(drm_device_t* dev } /* reenable the fifo caches */ - NV_WRITE(NV_PFIFO_CACHES, 0x00000001); + NV_WRITE(NV03_PFIFO_CACHES, 0x00000001); /* Deallocate command buffer, and dma object */ nouveau_mem_free(dev, dev_priv->fifos[n].cmdbuf_mem); diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c index ac88b68..9b3d94f 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -43,14 +43,14 @@ void nouveau_irq_preinstall(drm_device_t DRM_DEBUG("IRQ: preinst\n"); /* Disable/Clear PFIFO interrupts */ - NV_WRITE(NV_PFIFO_INTEN, 0); - NV_WRITE(NV_PFIFO_INTSTAT, 0xFFFFFFFF); + NV_WRITE(NV03_PFIFO_INTR_EN_0, 0); + NV_WRITE(NV03_PMC_INTR_0, 0xFFFFFFFF); /* Disable/Clear PGRAPH interrupts */ if (dev_priv->card_type<NV_40) - NV_WRITE(NV04_PGRAPH_INTEN, 0); + NV_WRITE(NV03_PGRAPH_INTR_EN, 0); else - NV_WRITE(NV40_PGRAPH_INTEN, 0); - NV_WRITE(NV_PGRAPH_INTSTAT, 0xFFFFFFFF); + NV_WRITE(NV40_PGRAPH_INTR_EN, 0); + NV_WRITE(NV03_PGRAPH_INTR, 0xFFFFFFFF); #if 0 /* Disable/Clear CRTC0/1 interrupts */ NV_WRITE(NV_CRTC0_INTEN, 0); @@ -59,7 +59,7 @@ void nouveau_irq_preinstall(drm_device_t NV_WRITE(NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK); #endif /* Master disable */ - NV_WRITE(NV_PMC_INTEN, 0); + NV_WRITE(NV03_PMC_INTR_EN_0, 0); } void nouveau_irq_postinstall(drm_device_t *dev) @@ -69,7 +69,7 @@ void nouveau_irq_postinstall(drm_device_ DRM_DEBUG("IRQ: postinst\n"); /* Enable PFIFO error reporting */ - NV_WRITE(NV_PFIFO_INTEN , + NV_WRITE(NV03_PFIFO_INTR_EN_0 , NV_PFIFO_INTR_CACHE_ERROR | NV_PFIFO_INTR_RUNOUT | NV_PFIFO_INTR_RUNOUT_OVERFLOW | @@ -78,11 +78,11 @@ void nouveau_irq_postinstall(drm_device_ NV_PFIFO_INTR_SEMAPHORE | NV_PFIFO_INTR_ACQUIRE_TIMEOUT ); - NV_WRITE(NV_PFIFO_INTSTAT, 0xFFFFFFFF); + NV_WRITE(NV03_PMC_INTR_0, 0xFFFFFFFF); /* Enable PGRAPH interrupts */ if (dev_priv->card_type<NV_40) - NV_WRITE(NV04_PGRAPH_INTEN, + NV_WRITE(NV03_PGRAPH_INTR_EN, NV_PGRAPH_INTR_NOTIFY | NV_PGRAPH_INTR_MISSING_HW | NV_PGRAPH_INTR_CONTEXT_SWITCH | @@ -90,14 +90,14 @@ void nouveau_irq_postinstall(drm_device_ NV_PGRAPH_INTR_ERROR ); else - NV_WRITE(NV40_PGRAPH_INTEN, + NV_WRITE(NV40_PGRAPH_INTR_EN, NV_PGRAPH_INTR_NOTIFY | NV_PGRAPH_INTR_MISSING_HW | NV_PGRAPH_INTR_CONTEXT_SWITCH | NV_PGRAPH_INTR_BUFFER_NOTIFY | NV_PGRAPH_INTR_ERROR ); - NV_WRITE(NV_PGRAPH_INTSTAT, 0xFFFFFFFF); + NV_WRITE(NV03_PGRAPH_INTR, 0xFFFFFFFF); #if 0 /* Enable CRTC0/1 interrupts */ @@ -106,7 +106,7 @@ void nouveau_irq_postinstall(drm_device_ #endif /* Master enable */ - NV_WRITE(NV_PMC_INTEN, NV_PMC_INTEN_MASTER_ENABLE); + NV_WRITE(NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE); } void nouveau_irq_uninstall(drm_device_t *dev) @@ -116,19 +116,19 @@ void nouveau_irq_uninstall(drm_device_t DRM_DEBUG("IRQ: uninst\n"); /* Disable PFIFO interrupts */ - NV_WRITE(NV_PFIFO_INTEN, 0); + NV_WRITE(NV03_PFIFO_INTR_EN_0, 0); /* Disable PGRAPH interrupts */ if (dev_priv->card_type<NV_40) - NV_WRITE(NV04_PGRAPH_INTEN, 0); + NV_WRITE(NV03_PGRAPH_INTR_EN, 0); else - NV_WRITE(NV40_PGRAPH_INTEN, 0); + NV_WRITE(NV40_PGRAPH_INTR_EN, 0); #if 0 /* Disable CRTC0/1 interrupts */ NV_WRITE(NV_CRTC0_INTEN, 0); NV_WRITE(NV_CRTC1_INTEN, 0); #endif /* Master disable */ - NV_WRITE(NV_PMC_INTEN, 0); + NV_WRITE(NV03_PMC_INTR_EN_0, 0); } static void nouveau_fifo_irq_handler(drm_device_t *dev) @@ -136,12 +136,12 @@ static void nouveau_fifo_irq_handler(drm uint32_t status, chmode, chstat, channel; drm_nouveau_private_t *dev_priv = dev->dev_private; - status = NV_READ(NV_PFIFO_INTSTAT); + status = NV_READ(NV03_PMC_INTR_0); if (!status) return; - chmode = NV_READ(NV_PFIFO_MODE); - chstat = NV_READ(NV_PFIFO_DMA); - channel=NV_READ(NV_PFIFO_CACH1_PSH1)&(nouveau_fifo_number(dev)-1); + chmode = NV_READ(NV04_PFIFO_MODE); + chstat = NV_READ(NV04_PFIFO_DMA); + channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); DRM_DEBUG("NV: PFIFO interrupt! Channel=%d, INTSTAT=0x%08x/MODE=0x%08x/PEND=0x%08x\n", channel, status, chmode, chstat); @@ -150,14 +150,14 @@ static void nouveau_fifo_irq_handler(drm DRM_ERROR("NV: PFIFO error interrupt\n"); - c1get = NV_READ(NV_PFIFO_CACH1_GET) >> 2; + c1get = NV_READ(NV03_PFIFO_CACHE1_GET) >> 2; if (dev_priv->card_type < NV_40) { /* Untested, so it may not work.. */ - c1method = NV_READ(NV_PFIFO_CACH1_METHOD(c1get)); - c1data = NV_READ(NV_PFIFO_CACH1_DATA(c1get)); + c1method = NV_READ(NV04_PFIFO_CACHE1_METHOD(c1get)); + c1data = NV_READ(NV04_PFIFO_CACHE1_DATA(c1get)); } else { - c1method = NV_READ(NV40_PFIFO_CACH1_METHOD(c1get)); - c1data = NV_READ(NV40_PFIFO_CACH1_DATA(c1get)); + c1method = NV_READ(NV40_PFIFO_CACHE1_METHOD(c1get)); + c1data = NV_READ(NV40_PFIFO_CACHE1_DATA(c1get)); } DRM_ERROR("NV: Channel %d/%d - Method 0x%04x, Data 0x%08x\n", @@ -166,30 +166,30 @@ static void nouveau_fifo_irq_handler(drm ); status &= ~NV_PFIFO_INTR_CACHE_ERROR; - NV_WRITE(NV_PFIFO_INTSTAT, NV_PFIFO_INTR_CACHE_ERROR); + NV_WRITE(NV03_PMC_INTR_0, NV_PFIFO_INTR_CACHE_ERROR); } if (status & NV_PFIFO_INTR_DMA_PUSHER) { DRM_INFO("NV: PFIFO DMA pusher interrupt\n"); status &= ~NV_PFIFO_INTR_DMA_PUSHER; - NV_WRITE(NV_PFIFO_INTSTAT, NV_PFIFO_INTR_DMA_PUSHER); + NV_WRITE(NV03_PMC_INTR_0, NV_PFIFO_INTR_DMA_PUSHER); - NV_WRITE(NV_PFIFO_CACH1_DMAS, 0x00000000); - if (NV_READ(NV_PFIFO_CACH1_DMAP)!=NV_READ(NV_PFIFO_CACH1_DMAG)) + NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000); + if (NV_READ(NV04_PFIFO_CACHE1_DMA_PUT)!=NV_READ(NV04_PFIFO_CACHE1_DMA_GET)) { - uint32_t getval=NV_READ(NV_PFIFO_CACH1_DMAG)+4; - NV_WRITE(NV_PFIFO_CACH1_DMAG,getval); + uint32_t getval=NV_READ(NV04_PFIFO_CACHE1_DMA_GET)+4; + NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET,getval); } } if (status) { DRM_INFO("NV: unknown PFIFO interrupt. status=0x%08x\n", status); - NV_WRITE(NV_PFIFO_INTSTAT, status); + NV_WRITE(NV03_PMC_INTR_0, status); } - NV_WRITE(NV_PMC_INTSTAT, NV_PMC_INTSTAT_PFIFO_PENDING); + NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING); } static void nouveau_nv04_context_switch(drm_device_t *dev) @@ -197,9 +197,9 @@ static void nouveau_nv04_context_switch( drm_nouveau_private_t *dev_priv = dev->dev_private; uint32_t channel,i; uint32_t max=0; - NV_WRITE(NV_PGRAPH_FIFO,0x0); - channel=NV_READ(NV_PFIFO_CACH1_PSH1)&(nouveau_fifo_number(dev)-1); - //DRM_INFO("raw PFIFO_CACH1_PHS1 reg is %x\n",NV_READ(NV_PFIFO_CACH1_PSH1)); + NV_WRITE(NV04_PGRAPH_FIFO,0x0); + channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); + //DRM_INFO("raw PFIFO_CACH1_PHS1 reg is %x\n",NV_READ(NV03_PFIFO_CACHE1_PUSH1)); //DRM_INFO("currently on channel %d\n",channel); for (i=0;i<nouveau_fifo_number(dev);i++) if ((dev_priv->fifos[i].used)&&(i!=channel)) { @@ -208,13 +208,13 @@ static void nouveau_nv04_context_switch( //get=NV_READ(dev_priv->ramfc_offset+4+i*32); put=NV_READ(NV03_FIFO_REGS_DMAPUT(i)); get=NV_READ(NV03_FIFO_REGS_DMAGET(i)); - pending=NV_READ(NV_PFIFO_DMA); + pending=NV_READ(NV04_PFIFO_DMA); //DRM_INFO("Channel %d (put/get %x/%x)\n",i,put,get); /* mark all pending channels as such */ if ((put!=get)&!(pending&(1<<i))) { pending|=(1<<i); - NV_WRITE(NV_PFIFO_DMA,pending); + NV_WRITE(NV04_PFIFO_DMA,pending); } max++; } @@ -222,18 +222,18 @@ static void nouveau_nv04_context_switch( #if 1 /* 2-channel commute */ - // NV_WRITE(NV_PFIFO_CACH1_PSH1,channel|0x100); + // NV_WRITE(NV03_PFIFO_CACHE1_PUSH1,channel|0x100); if (channel==0) channel=1; else channel=0; // dev_priv->cur_fifo=channel; - NV_WRITE(0x2050,channel|0x100); + NV_WRITE(NV04_PFIFO_NEXT_CHANNEL,channel|0x100); #endif - //NV_WRITE(NV_PFIFO_CACH1_PSH1,max|0x100); + //NV_WRITE(NV03_PFIFO_CACHE1_PUSH1,max|0x100); //NV_WRITE(0x2050,max|0x100); - NV_WRITE(NV_PGRAPH_FIFO,0x1); + NV_WRITE(NV04_PGRAPH_FIFO,0x1); } @@ -242,7 +242,7 @@ static void nouveau_pgraph_irq_handler(d uint32_t status; drm_nouveau_private_t *dev_priv = dev->dev_private; - status = NV_READ(NV_PGRAPH_INTSTAT); + status = NV_READ(NV03_PGRAPH_INTR); if (!status) return; @@ -259,7 +259,7 @@ static void nouveau_pgraph_irq_handler(d DRM_DEBUG("instance:0x%08x\tnotify:0x%08x\n", nsource, nstatus); status &= ~NV_PGRAPH_INTR_NOTIFY; - NV_WRITE(NV_PGRAPH_INTSTAT, NV_PGRAPH_INTR_NOTIFY); + NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY); } if (status & NV_PGRAPH_INTR_BUFFER_NOTIFY) { @@ -275,14 +275,14 @@ static void nouveau_pgraph_irq_handler(d DRM_DEBUG("instance:0x%08x\tnotify:0x%08x\n", instance, notify); status &= ~NV_PGRAPH_INTR_BUFFER_NOTIFY; - NV_WRITE(NV_PGRAPH_INTSTAT, NV_PGRAPH_INTR_BUFFER_NOTIFY); + NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_BUFFER_NOTIFY); } if (status & NV_PGRAPH_INTR_MISSING_HW) { DRM_ERROR("NV: PGRAPH missing hw interrupt\n"); status &= ~NV_PGRAPH_INTR_MISSING_HW; - NV_WRITE(NV_PGRAPH_INTSTAT, NV_PGRAPH_INTR_MISSING_HW); + NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_MISSING_HW); } if (status & NV_PGRAPH_INTR_ERROR) { @@ -314,11 +314,11 @@ static void nouveau_pgraph_irq_handler(d ); status &= ~NV_PGRAPH_INTR_ERROR; - NV_WRITE(NV_PGRAPH_INTSTAT, NV_PGRAPH_INTR_ERROR); + NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR); } if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) { - uint32_t channel=NV_READ(NV_PFIFO_CACH1_PSH1)&(nouveau_fifo_number(dev)-1); + uint32_t channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); DRM_INFO("NV: PGRAPH context switch interrupt channel %x\n",channel); switch(dev_priv->card_type) { @@ -339,15 +339,15 @@ static void nouveau_pgraph_irq_handler(d } status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; - NV_WRITE(NV_PGRAPH_INTSTAT, NV_PGRAPH_INTR_CONTEXT_SWITCH); + NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); } if (status) { DRM_INFO("NV: Unknown PGRAPH interrupt! STAT=0x%08x\n", status); - NV_WRITE(NV_PGRAPH_INTSTAT, status); + NV_WRITE(NV03_PGRAPH_INTR, status); } - NV_WRITE(NV_PMC_INTSTAT, NV_PMC_INTSTAT_PGRAPH_PENDING); + NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); } static void nouveau_crtc_irq_handler(drm_device_t *dev, int crtc) @@ -368,23 +368,23 @@ irqreturn_t nouveau_irq_handler(DRM_IRQ_ drm_nouveau_private_t *dev_priv = dev->dev_private; uint32_t status; - status = NV_READ(NV_PMC_INTSTAT); + status = NV_READ(NV03_PMC_INTR_0); if (!status) return IRQ_NONE; DRM_DEBUG("PMC INTSTAT: 0x%08x\n", status); - if (status & NV_PMC_INTSTAT_PFIFO_PENDING) { + if (status & NV_PMC_INTR_0_PFIFO_PENDING) { nouveau_fifo_irq_handler(dev); - status &= ~NV_PMC_INTSTAT_PFIFO_PENDING; + status &= ~NV_PMC_INTR_0_PFIFO_PENDING; } - if (status & NV_PMC_INTSTAT_PGRAPH_PENDING) { + if (status & NV_PMC_INTR_0_PGRAPH_PENDING) { nouveau_pgraph_irq_handler(dev); - status &= ~NV_PMC_INTSTAT_PGRAPH_PENDING; + status &= ~NV_PMC_INTR_0_PGRAPH_PENDING; } - if (status & NV_PMC_INTSTAT_CRTCn_PENDING) { + if (status & NV_PMC_INTR_0_CRTCn_PENDING) { nouveau_crtc_irq_handler(dev, (status>>24)&3); - status &= ~NV_PMC_INTSTAT_CRTCn_PENDING; + status &= ~NV_PMC_INTR_0_CRTCn_PENDING; } if (status) diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index 55ba43f..c45ca87 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -45,81 +45,82 @@ # define NV03_FIFO_REGS_DMAPUT(i) (NV03_FIFO_REGS(i)+0x40) # define NV03_FIFO_REGS_DMAGET(i) (NV03_FIFO_REGS(i)+0x44) -#define NV_PMC_BOOT_0 0x00000000 -#define NV_PMC_INTSTAT 0x00000100 -# define NV_PMC_INTSTAT_PFIFO_PENDING (1<< 8) -# define NV_PMC_INTSTAT_PGRAPH_PENDING (1<<12) -# define NV_PMC_INTSTAT_CRTC0_PENDING (1<<24) -# define NV_PMC_INTSTAT_CRTC1_PENDING (1<<25) -# define NV_PMC_INTSTAT_CRTCn_PENDING (3<<24) -#define NV_PMC_INTEN 0x00000140 -# define NV_PMC_INTEN_MASTER_ENABLE (1<< 0) - -#define NV_PGRAPH_DEBUG_4 0x00400090 -#define NV_PGRAPH_INTSTAT 0x00400100 -#define NV04_PGRAPH_INTEN 0x00400140 -#define NV40_PGRAPH_INTEN 0x0040013C +#define NV03_PMC_BOOT_0 0x00000000 +#define NV03_PMC_INTR_0 0x00000100 +# define NV_PMC_INTR_0_PFIFO_PENDING (1<< 8) +# define NV_PMC_INTR_0_PGRAPH_PENDING (1<<12) +# define NV_PMC_INTR_0_CRTC0_PENDING (1<<24) +# define NV_PMC_INTR_0_CRTC1_PENDING (1<<25) +# define NV_PMC_INTR_0_CRTCn_PENDING (3<<24) +#define NV03_PMC_INTR_EN_0 0x00000140 +# define NV_PMC_INTR_EN_0_MASTER_ENABLE (1<< 0) + +#define NV10_PGRAPH_DEBUG_4 0x00400090 +#define NV03_PGRAPH_INTR 0x00400100 +#define NV03_PGRAPH_INTR_EN 0x00400140 +#define NV40_PGRAPH_INTR_EN 0x0040013C # define NV_PGRAPH_INTR_NOTIFY (1<< 0) # define NV_PGRAPH_INTR_MISSING_HW (1<< 4) # define NV_PGRAPH_INTR_CONTEXT_SWITCH (1<<12) # define NV_PGRAPH_INTR_BUFFER_NOTIFY (1<<16) # define NV_PGRAPH_INTR_ERROR (1<<20) -#define NV_PGRAPH_CTX_CONTROL 0x00400144 -#define NV_PGRAPH_NV40_UNK220 0x00400220 -# define NV_PGRAPH_NV40_UNK220_FB_INSTANCE 0xFFFFFFFF -#define NV_PGRAPH_CTX_USER 0x00400148 -#define NV_PGRAPH_CTX_SWITCH1 0x0040014C -#define NV_PGRAPH_CTX_SWITCH2 0x00400150 -#define NV_PGRAPH_CTX_SWITCH3 0x00400154 -#define NV_PGRAPH_CTX_SWITCH4 0x00400158 -#define NV_PGRAPH_CTX_SWITCH5 0x0040015C +#define NV03_PGRAPH_CTX_CONTROL 0x00400144 +#define NV40_PGRAPH_UNK220 0x00400220 +# define NV40_PGRAPH_UNK220_FB_INSTANCE 0xFFFFFFFF +#define NV03_PGRAPH_CTX_USER 0x00400194 +#define NV04_PGRAPH_CTX_USER 0x00400174 +#define NV10_PGRAPH_CTX_USER 0x00400148 +#define NV10_PGRAPH_CTX_SWITCH1 0x0040014C +#define NV10_PGRAPH_CTX_SWITCH2 0x00400150 +#define NV10_PGRAPH_CTX_SWITCH3 0x00400154 +#define NV10_PGRAPH_CTX_SWITCH4 0x00400158 +#define NV10_PGRAPH_CTX_SWITCH5 0x0040015C #define NV04_PGRAPH_CTX_SWITCH1 0x00400160 -#define NV_PGRAPH_CTX_CACHE1 0x00400160 +#define NV10_PGRAPH_CTX_CACHE1 0x00400160 #define NV04_PGRAPH_CTX_SWITCH2 0x00400164 #define NV04_PGRAPH_CTX_SWITCH3 0x00400168 #define NV04_PGRAPH_CTX_SWITCH4 0x0040016C -#define NV04_PGRAPH_CTX_USER 0x00400174 #define NV04_PGRAPH_CTX_CACHE1 0x00400180 -#define NV_PGRAPH_CTX_CACHE2 0x00400180 +#define NV10_PGRAPH_CTX_CACHE2 0x00400180 #define NV04_PGRAPH_CTX_CACHE2 0x004001A0 -#define NV_PGRAPH_CTX_CACHE3 0x004001A0 +#define NV10_PGRAPH_CTX_CACHE3 0x004001A0 #define NV04_PGRAPH_CTX_CACHE3 0x004001C0 -#define NV_PGRAPH_CTX_CACHE4 0x004001C0 +#define NV10_PGRAPH_CTX_CACHE4 0x004001C0 #define NV04_PGRAPH_CTX_CACHE4 0... [truncated message content] |
From: <dar...@ke...> - 2007-08-06 12:17:48
|
linux-core/Makefile.kernel | 2 linux-core/drmP.h | 1 linux-core/drm_bo.c | 10 linux-core/drm_bo_move.c | 1 linux-core/drm_irq.c | 3 linux-core/drm_objects.h | 16 + linux-core/nouveau_sgdma.c | 4 shared-core/nouveau_drm.h | 33 ++- shared-core/nouveau_drv.h | 447 +++++++++++++++++++++++------------------ shared-core/nouveau_fifo.c | 170 +++++++-------- shared-core/nouveau_irq.c | 59 +++++ shared-core/nouveau_mem.c | 8 shared-core/nouveau_notifier.c | 59 +++-- shared-core/nouveau_object.c | 247 +++++++++++++--------- shared-core/nouveau_state.c | 61 +++-- shared-core/nv04_fifo.c | 29 +- shared-core/nv04_graph.c | 15 - shared-core/nv04_instmem.c | 11 - shared-core/nv10_fifo.c | 27 +- shared-core/nv10_graph.c | 49 ++-- shared-core/nv20_graph.c | 68 +++--- shared-core/nv30_graph.c | 35 +-- shared-core/nv40_fifo.c | 24 +- shared-core/nv40_graph.c | 26 -- shared-core/nv50_fifo.c | 41 +-- shared-core/nv50_graph.c | 27 +- 26 files changed, 838 insertions(+), 635 deletions(-) New commits: diff-tree 92084c6e056a738308ff65f3fcd7411fd7d2995a (from 7a0a812ea42d80eed89b7b9993eae42c7c1b1613) Author: Ben Skeggs <sk...@gm...> Date: Mon Aug 6 22:11:18 2007 +1000 Export some useful ttm functions to drivers. diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 467d03f..4c2b154 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -517,7 +517,7 @@ static void drm_bo_base_deref_locked(str drm_bo_usage_deref_locked(&bo); } -static void drm_bo_usage_deref_unlocked(struct drm_buffer_object ** bo) +void drm_bo_usage_deref_unlocked(struct drm_buffer_object ** bo) { struct drm_buffer_object *tmp_bo = *bo; struct drm_device *dev = tmp_bo->dev; @@ -530,6 +530,7 @@ static void drm_bo_usage_deref_unlocked( mutex_unlock(&dev->struct_mutex); } } +EXPORT_SYMBOL(drm_bo_usage_deref_unlocked); /* * Note. The caller has to register (if applicable) @@ -1672,10 +1673,10 @@ int drm_buffer_object_create(struct drm_ drm_bo_usage_deref_unlocked(&bo); return ret; } +EXPORT_SYMBOL(drm_buffer_object_create); -static int drm_bo_add_user_object(struct drm_file *file_priv, - struct drm_buffer_object *bo, - int shareable) +int drm_bo_add_user_object(struct drm_file *file_priv, + struct drm_buffer_object *bo, int shareable) { struct drm_device *dev = file_priv->head->dev; int ret; @@ -1694,6 +1695,7 @@ static int drm_bo_add_user_object(struct mutex_unlock(&dev->struct_mutex); return ret; } +EXPORT_SYMBOL(drm_bo_add_user_object); static int drm_bo_lock_test(struct drm_device * dev, struct drm_file *file_priv) { diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c index 5e21173..1a61391 100644 --- a/linux-core/drm_bo_move.c +++ b/linux-core/drm_bo_move.c @@ -128,6 +128,7 @@ int drm_mem_reg_ioremap(struct drm_devic *virtual = addr; return 0; } +EXPORT_SYMBOL(drm_mem_reg_ioremap); /** * \c Unmap mapping obtained using drm_bo_ioremap diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index e5f2b69..e34fdbc 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -483,6 +483,17 @@ extern int drm_bo_mem_space(struct drm_b struct drm_bo_mem_reg * mem, int no_wait); extern int drm_bo_move_buffer(struct drm_buffer_object * bo, uint32_t new_mem_flags, int no_wait, int move_unfenced); +extern int drm_buffer_object_create(struct drm_device *dev, unsigned long size, + enum drm_bo_type type, uint64_t mask, + uint32_t hint, uint32_t page_alignment, + unsigned long buffer_start, + struct drm_buffer_object **bo); +extern int drm_bo_init_mm(struct drm_device *dev, unsigned type, + unsigned long p_offset, unsigned long p_size); +extern int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type); +extern int drm_bo_add_user_object(struct drm_file *file_priv, + struct drm_buffer_object *bo, int sharable); +extern void drm_bo_usage_deref_unlocked(struct drm_buffer_object **bo); /* * Buffer object memory move helpers. @@ -502,6 +513,11 @@ extern int drm_bo_move_accel_cleanup(str uint32_t fence_flags, struct drm_bo_mem_reg * new_mem); +extern int drm_mem_reg_ioremap(struct drm_device *dev, + struct drm_bo_mem_reg *mem, void **virtual); +extern void drm_mem_reg_iounmap(struct drm_device *dev, + struct drm_bo_mem_reg *mem, void *virtual); + #ifdef CONFIG_DEBUG_MUTEXES #define DRM_ASSERT_LOCKED(_mutex) \ BUG_ON(!mutex_is_locked(_mutex) || \ diff-tree 7a0a812ea42d80eed89b7b9993eae42c7c1b1613 (from cf04641bc61c8bc18101713a8d95ef98e6afae7f) Author: Ben Skeggs <sk...@gm...> Date: Mon Aug 6 22:06:52 2007 +1000 nouveau: Remove PGRAPH_SURFACE hack, it wont work now anyway. Need to find another way of doing this, ideally someone'd hunt down which object/method controls it! The Xv blit adaptor is likely now broken on cards that have pNv->WaitVSyncPossible enabled. diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 823801f..fd21d2f 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -369,19 +369,6 @@ nouveau_fifo_alloc(struct drm_device *de nouveau_fifo_free(chan); return ret; } - - /* Temporary hack, to avoid breaking Xv on cards where the - * initial context value for 0x400710 doesn't have these bits - * set. Proper fix would be to find which object+method is - * responsible for modifying this state. - */ - if (dev_priv->chipset >= 0x10 && dev_priv->chipset < 0x50) { - uint32_t tmp; - tmp = NV_READ(NV10_PGRAPH_SURFACE) & 0x0007ff00; - NV_WRITE(NV10_PGRAPH_SURFACE, tmp); - tmp = NV_READ(NV10_PGRAPH_SURFACE) | 0x00020100; - NV_WRITE(NV10_PGRAPH_SURFACE, tmp); - } } NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, diff-tree cf04641bc61c8bc18101713a8d95ef98e6afae7f (from 51f24be578025e3f1eae859288adf5232afc898d) Author: Ben Skeggs <sk...@gm...> Date: Mon Aug 6 22:05:31 2007 +1000 nouveau: Give DRM its own gpu channel If your card doesn't have working context switching, it is now broken. diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 5aa589c..3d00cbe 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -22,7 +22,7 @@ i915-objs := i915_drv.o i915_dma.o i91 i915_buffer.o nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ nouveau_object.o nouveau_irq.o nouveau_notifier.o \ - nouveau_sgdma.o \ + nouveau_sgdma.o nouveau_dma.o \ nv04_timer.o \ nv04_mc.o nv40_mc.o nv50_mc.o \ nv04_fb.o nv10_fb.o nv40_fb.o \ diff --git a/linux-core/nouveau_sgdma.c b/linux-core/nouveau_sgdma.c index 6393a46..df970d1 100644 --- a/linux-core/nouveau_sgdma.c +++ b/linux-core/nouveau_sgdma.c @@ -69,7 +69,7 @@ nouveau_sgdma_clear(struct drm_ttm_backe if (nvbe->is_bound) be->func->unbind(be); - for (d = 0; d < nvbe->pages_populated; d--) { + for (d = 0; d < nvbe->pages_populated; d++) { pci_unmap_page(nvbe->dev->pdev, nvbe->pagelist[d], NV_CTXDMA_PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 0b173b7..10f9149 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -134,6 +134,22 @@ struct nouveau_channel struct list_head ramht_refs; /* Objects referenced by RAMHT */ }; +struct nouveau_drm_channel { + struct nouveau_channel *chan; + + /* DMA state */ + int max, put, cur, free; + int push_free; + volatile uint32_t *pushbuf; + + /* Notifiers */ + uint32_t notify0_offset; + + /* Buffer moves */ + uint32_t m2mf_dma_source; + uint32_t m2mf_dma_destin; +}; + struct nouveau_config { struct { int location; @@ -222,6 +238,7 @@ struct drm_nouveau_private { struct nouveau_channel *fifos[NV_MAX_FIFO_NUMBER]; struct nouveau_engine Engine; + struct nouveau_drm_channel channel; /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ struct nouveau_gpuobj *ramht; @@ -345,6 +362,10 @@ extern int nouveau_fifo_ctx_size(struct extern void nouveau_fifo_cleanup(struct drm_device *, struct drm_file *); extern int nouveau_fifo_owner(struct drm_device *, struct drm_file *, int channel); +extern int nouveau_fifo_alloc(struct drm_device *dev, + struct nouveau_channel **chan, + struct drm_file *file_priv, + uint32_t fb_ctxdma, uint32_t tt_ctxdma); extern void nouveau_fifo_free(struct nouveau_channel *); /* nouveau_object.c */ @@ -400,6 +421,11 @@ extern struct drm_ttm_backend *nouveau_s extern int nouveau_sgdma_nottm_hack_init(struct drm_device *); extern void nouveau_sgdma_nottm_hack_takedown(struct drm_device *); +/* nouveau_dma.c */ +extern int nouveau_dma_channel_init(struct drm_device *); +extern void nouveau_dma_channel_takedown(struct drm_device *); +extern int nouveau_dma_wait(struct drm_device *, int size); + /* nv04_fb.c */ extern int nv04_fb_init(struct drm_device *); extern void nv04_fb_takedown(struct drm_device *); diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 152b669..823801f 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -261,9 +261,10 @@ nouveau_fifo_cmdbuf_alloc(struct nouveau } /* allocates and initializes a fifo for user space consumption */ -int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret, - struct drm_file *file_priv, - uint32_t vram_handle, uint32_t tt_handle) +int +nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, + struct drm_file *file_priv, + uint32_t vram_handle, uint32_t tt_handle) { int ret; struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -288,7 +289,6 @@ int nouveau_fifo_alloc(struct drm_device /* no more fifos. you lost. */ if (channel==nouveau_fifo_number(dev)) return -EINVAL; - (*chan_ret) = channel; dev_priv->fifos[channel] = drm_calloc(1, sizeof(struct nouveau_channel), DRM_MEM_DRIVER); @@ -394,6 +394,7 @@ int nouveau_fifo_alloc(struct drm_device NV_WRITE(NV03_PFIFO_CACHES, 1); DRM_INFO("%s: initialised FIFO %d\n", __func__, channel); + *chan_ret = chan; return 0; } @@ -482,13 +483,12 @@ static int nouveau_ioctl_fifo_alloc(stru if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) return -EINVAL; - res = nouveau_fifo_alloc(dev, &init->channel, file_priv, + res = nouveau_fifo_alloc(dev, &chan, file_priv, init->fb_ctxdma_handle, init->tt_ctxdma_handle); if (res) return res; - chan = dev_priv->fifos[init->channel]; - + init->channel = chan->id; init->put_base = chan->pushbuf_base; /* make the fifo available to user space */ diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 4fb5329..9dab34c 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -274,6 +274,8 @@ nouveau_card_init(struct drm_device *dev struct nouveau_engine *engine; int ret; + DRM_DEBUG("prev state = %d\n", dev_priv->init_state); + if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE) return 0; @@ -335,6 +337,9 @@ nouveau_card_init(struct drm_device *dev /* what about PVIDEO/PCRTC/PRAMDAC etc? */ + ret = nouveau_dma_channel_init(dev); + if (ret) return ret; + dev_priv->init_state = NOUVEAU_CARD_INIT_DONE; return 0; } @@ -344,7 +349,11 @@ static void nouveau_card_takedown(struct struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->Engine; + DRM_DEBUG("prev state = %d\n", dev_priv->init_state); + if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) { + nouveau_dma_channel_takedown(dev); + engine->fifo.takedown(dev); engine->graph.takedown(dev); engine->fb.takedown(dev); diff --git a/shared-core/nv04_instmem.c b/shared-core/nv04_instmem.c index 36aa620..5e0f6f4 100644 --- a/shared-core/nv04_instmem.c +++ b/shared-core/nv04_instmem.c @@ -129,7 +129,6 @@ nv04_instmem_clear(struct drm_device *de if (gpuobj && gpuobj->im_backing) { if (gpuobj->im_bound) dev_priv->Engine.instmem.unbind(dev, gpuobj); - nouveau_mem_free(dev, gpuobj->im_backing); gpuobj->im_backing = NULL; } } diff-tree 51f24be578025e3f1eae859288adf5232afc898d (from 97770db72040dc032130413e0cdabc1777560a75) Author: Ben Skeggs <sk...@gm...> Date: Mon Aug 6 21:46:55 2007 +1000 nouveau: Determine trapped channel id from active grctx on >=NV40 diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c index f7baf89..2ee77d8 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -301,6 +301,61 @@ nouveau_print_bitfield_names(uint32_t va printk(" (unknown bits 0x%08x)", value); } +static int +nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int channel; + + if (dev_priv->card_type < NV_40) { + channel = (NV_READ(0x400704) >> 20) & 0x1f; + } else + if (dev_priv->card_type < NV_50) { + uint32_t cur_grctx = (NV_READ(0x40032C) & 0xfffff) << 4; + + /* 0x400704 *sometimes* contains a sensible channel ID, but + * mostly not.. for now lookup which channel owns the active + * PGRAPH context. Probably a better way, but this'll do + * for now. + */ + for (channel = 0; channel < 32; channel++) { + if (dev_priv->fifos[channel] == NULL) + continue; + if (cur_grctx == + dev_priv->fifos[channel]->ramin_grctx->instance) + break; + } + if (channel == 32) { + DRM_ERROR("AIII, unable to determine active channel " + "from PGRAPH context 0x%08x\n", cur_grctx); + return -EINVAL; + } + } else { + uint32_t cur_grctx = (NV_READ(0x40032C) & 0xfffff) << 12; + + for (channel = 0; channel < 128; channel++) { + if (dev_priv->fifos[channel] == NULL) + continue; + if (cur_grctx == + dev_priv->fifos[channel]->ramin_grctx->instance) + break; + } + if (channel == 128) { + DRM_ERROR("AIII, unable to determine active channel " + "from PGRAPH context 0x%08x\n", cur_grctx); + return -EINVAL; + } + } + + if (channel > nouveau_fifo_number(dev) || + dev_priv->fifos[channel] == NULL) { + DRM_ERROR("AIII, invalid/inactive channel id %d\n", channel); + return -EINVAL; + } + + return 0; +} + static void nouveau_graph_dump_trap_info(struct drm_device *dev) { @@ -310,8 +365,10 @@ nouveau_graph_dump_trap_info(struct drm_ uint32_t method, subc, data; uint32_t nsource, nstatus; + if (nouveau_graph_trapped_channel(dev, &channel)) + channel = -1; + address = NV_READ(0x400704); - channel = (address >> 20) & 0x1F; subc = (address >> 16) & 0x7; method = address & 0x1FFC; data = NV_READ(0x400708); diff-tree 97770db72040dc032130413e0cdabc1777560a75 (from beaa0c9a28b30a6ba3292184d04875b6a597e433) Author: Ben Skeggs <sk...@gm...> Date: Mon Aug 6 21:45:18 2007 +1000 nouveau: Various internal and external API changes 1. DRM_NOUVEAU_GPUOBJ_FREE Used to free GPU objects. The obvious usage case is for Gr objects, but notifiers can also be destroyed in the same way. GPU objects gain a destructor method and private data fields with this change, so other specialised cases (like notifiers) can be implemented on top of gpuobjs. 2. DRM_NOUVEAU_CHANNEL_FREE 3. DRM_NOUVEAU_CARD_INIT Ideally we'd do init during module load, but this isn't currently possible. Doing init during firstopen() is bad as X has a love of opening/closing the DRM many times during startup. Once the modesetting-101 branch is merged this can go away. IRQs are enabled in nouveau_card_init() now, rather than having the X server call drmCtlInstHandler(). We'll need this for when we give the kernel module its own channel. 4. DRM_NOUVEAU_GETPARAM Add CHIPSET_ID value, which will return the chipset id derived from NV_PMC_BOOT_0. 4. Use list_* in a few places, rather than home-brewed stuff. diff --git a/linux-core/drmP.h b/linux-core/drmP.h index a61efcf..aa56222 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -1075,6 +1075,7 @@ extern void drm_core_reclaim_buffers(str extern int drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv); extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS); +extern int drm_irq_install(struct drm_device *dev); extern int drm_irq_uninstall(struct drm_device *dev); extern void drm_driver_irq_preinstall(struct drm_device *dev); extern void drm_driver_irq_postinstall(struct drm_device *dev); diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index fe4316e..25166b6 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -80,7 +80,7 @@ int drm_irq_by_busid(struct drm_device * * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions * before and after the installation. */ -static int drm_irq_install(struct drm_device * dev) +int drm_irq_install(struct drm_device * dev) { int ret; unsigned long sh_flags = 0; @@ -140,6 +140,7 @@ static int drm_irq_install(struct drm_de return 0; } +EXPORT_SYMBOL(drm_irq_install); /** * Uninstall the IRQ handler. diff --git a/shared-core/nouveau_drm.h b/shared-core/nouveau_drm.h index 4016f00..bfc9bd4 100644 --- a/shared-core/nouveau_drm.h +++ b/shared-core/nouveau_drm.h @@ -25,9 +25,9 @@ #ifndef __NOUVEAU_DRM_H__ #define __NOUVEAU_DRM_H__ -#define NOUVEAU_DRM_HEADER_PATCHLEVEL 9 +#define NOUVEAU_DRM_HEADER_PATCHLEVEL 10 -struct drm_nouveau_fifo_alloc { +struct drm_nouveau_channel_alloc { uint32_t fb_ctxdma_handle; uint32_t tt_ctxdma_handle; @@ -44,6 +44,10 @@ struct drm_nouveau_fifo_alloc { int notifier_size; }; +struct drm_nouveau_channel_free { + int channel; +}; + struct drm_nouveau_grobj_alloc { int channel; uint32_t handle; @@ -53,7 +57,7 @@ struct drm_nouveau_grobj_alloc { #define NOUVEAU_MEM_ACCESS_RO 1 #define NOUVEAU_MEM_ACCESS_WO 2 #define NOUVEAU_MEM_ACCESS_RW 3 -struct drm_nouveau_notifier_alloc { +struct drm_nouveau_notifierobj_alloc { int channel; uint32_t handle; int count; @@ -61,6 +65,11 @@ struct drm_nouveau_notifier_alloc { uint32_t offset; }; +struct drm_nouveau_gpuobj_free { + int channel; + uint32_t handle; +}; + #define NOUVEAU_MEM_FB 0x00000001 #define NOUVEAU_MEM_AGP 0x00000002 #define NOUVEAU_MEM_FB_ACCEPTABLE 0x00000004 @@ -95,6 +104,7 @@ struct drm_nouveau_mem_free { #define NOUVEAU_GETPARAM_FB_SIZE 8 #define NOUVEAU_GETPARAM_AGP_SIZE 9 #define NOUVEAU_GETPARAM_PCI_PHYSICAL 10 +#define NOUVEAU_GETPARAM_CHIPSET_ID 11 struct drm_nouveau_getparam { uint64_t param; uint64_t value; @@ -141,13 +151,16 @@ struct drm_nouveau_sarea { unsigned int nbox; }; -#define DRM_NOUVEAU_FIFO_ALLOC 0x00 -#define DRM_NOUVEAU_GROBJ_ALLOC 0x01 -#define DRM_NOUVEAU_NOTIFIER_ALLOC 0x02 -#define DRM_NOUVEAU_MEM_ALLOC 0x03 -#define DRM_NOUVEAU_MEM_FREE 0x04 -#define DRM_NOUVEAU_GETPARAM 0x05 -#define DRM_NOUVEAU_SETPARAM 0x06 +#define DRM_NOUVEAU_CARD_INIT 0x00 +#define DRM_NOUVEAU_GETPARAM 0x01 +#define DRM_NOUVEAU_SETPARAM 0x02 +#define DRM_NOUVEAU_CHANNEL_ALLOC 0x03 +#define DRM_NOUVEAU_CHANNEL_FREE 0x04 +#define DRM_NOUVEAU_GROBJ_ALLOC 0x05 +#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x06 +#define DRM_NOUVEAU_GPUOBJ_FREE 0x07 +#define DRM_NOUVEAU_MEM_ALLOC 0x08 +#define DRM_NOUVEAU_MEM_FREE 0x09 #endif /* __NOUVEAU_DRM_H__ */ diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 8ec9189..0b173b7 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -34,7 +34,7 @@ #define DRIVER_MAJOR 0 #define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 9 +#define DRIVER_PATCHLEVEL 10 #define NOUVEAU_FAMILY 0x0000FFFF #define NOUVEAU_FLAGS 0xFFFF0000 @@ -67,8 +67,7 @@ enum nouveau_flags { #define NVOBJ_FLAG_ZERO_FREE (1 << 2) #define NVOBJ_FLAG_FAKE (1 << 3) struct nouveau_gpuobj { - struct nouveau_gpuobj *next; - struct nouveau_gpuobj *prev; + struct list_head list; int im_channel; struct mem_block *im_pramin; @@ -80,10 +79,13 @@ struct nouveau_gpuobj { uint32_t engine; uint32_t class; + + void (*dtor)(struct drm_device *, struct nouveau_gpuobj *); + void *priv; }; struct nouveau_gpuobj_ref { - struct nouveau_gpuobj_ref *next; + struct list_head list; struct nouveau_gpuobj *gpuobj; uint32_t instance; @@ -129,7 +131,7 @@ struct nouveau_channel struct nouveau_gpuobj_ref *ramin; /* Private instmem */ struct mem_block *ramin_heap; /* Private PRAMIN heap */ struct nouveau_gpuobj_ref *ramht; /* Hash table */ - struct nouveau_gpuobj_ref *ramht_refs; /* Objects referenced by RAMHT */ + struct list_head ramht_refs; /* Objects referenced by RAMHT */ }; struct nouveau_config { @@ -269,9 +271,17 @@ struct drm_nouveau_private { struct nouveau_config config; - struct nouveau_gpuobj *gpuobj_all; + struct list_head gpuobj_list; }; +#define NOUVEAU_CHECK_INITIALISED_WITH_RETURN do { \ + struct drm_nouveau_private *nv = dev->dev_private; \ + if (nv->init_state != NOUVEAU_CARD_INIT_DONE) { \ + DRM_ERROR("called without init\n"); \ + return -EINVAL; \ + } \ +} while(0) + #define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id,cl,ch) do { \ struct drm_nouveau_private *nv = dev->dev_private; \ if (!nouveau_fifo_owner(dev, (cl), (id))) { \ @@ -293,6 +303,7 @@ extern int nouveau_ioctl_getparam(struc extern int nouveau_ioctl_setparam(struct drm_device *, void *data, struct drm_file *); extern void nouveau_wait_for_idle(struct drm_device *); +extern int nouveau_card_init(struct drm_device *); extern int nouveau_ioctl_card_init(struct drm_device *, void *data, struct drm_file *); @@ -324,6 +335,8 @@ extern int nouveau_notifier_alloc(struc int cout, uint32_t *offset); extern int nouveau_ioctl_notifier_alloc(struct drm_device *, void *data, struct drm_file *); +extern int nouveau_ioctl_notifier_free(struct drm_device *, void *data, + struct drm_file *); /* nouveau_fifo.c */ extern int nouveau_fifo_init(struct drm_device *); @@ -335,6 +348,7 @@ extern int nouveau_fifo_owner(struct dr extern void nouveau_fifo_free(struct nouveau_channel *); /* nouveau_object.c */ +extern int nouveau_gpuobj_init(struct drm_device *); extern void nouveau_gpuobj_takedown(struct drm_device *); extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, uint32_t vram_h, uint32_t tt_h); @@ -348,6 +362,8 @@ extern int nouveau_gpuobj_ref_add(struct struct nouveau_gpuobj_ref **); extern int nouveau_gpuobj_ref_del(struct drm_device *, struct nouveau_gpuobj_ref **); +extern int nouveau_gpuobj_ref_find(struct nouveau_channel *, uint32_t handle, + struct nouveau_gpuobj_ref **ref_ret); extern int nouveau_gpuobj_new_ref(struct drm_device *, struct nouveau_channel *alloc_chan, struct nouveau_channel *ref_chan, @@ -368,6 +384,8 @@ extern int nouveau_gpuobj_gr_new(struct struct nouveau_gpuobj **); extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data, struct drm_file *); +extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data, + struct drm_file *); /* nouveau_irq.c */ extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index c7ce1d8..152b669 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -302,22 +302,22 @@ int nouveau_fifo_alloc(struct drm_device DRM_INFO("Allocating FIFO number %d\n", channel); - /* Setup channel's default objects */ - ret = nouveau_gpuobj_channel_init(chan, vram_handle, tt_handle); + /* Allocate space for per-channel fixed notifier memory */ + ret = nouveau_notifier_init_channel(chan); if (ret) { nouveau_fifo_free(chan); return ret; } - /* allocate a command buffer, and create a dma object for the gpu */ - ret = nouveau_fifo_cmdbuf_alloc(chan); + /* Setup channel's default objects */ + ret = nouveau_gpuobj_channel_init(chan, vram_handle, tt_handle); if (ret) { nouveau_fifo_free(chan); return ret; } - /* Allocate space for per-channel fixed notifier memory */ - ret = nouveau_notifier_init_channel(chan); + /* allocate a command buffer, and create a dma object for the gpu */ + ret = nouveau_fifo_cmdbuf_alloc(chan); if (ret) { nouveau_fifo_free(chan); return ret; @@ -426,11 +426,11 @@ void nouveau_fifo_free(struct nouveau_ch chan->pushbuf_mem = NULL; } - nouveau_notifier_takedown_channel(chan); - /* Destroy objects belonging to the channel */ nouveau_gpuobj_channel_takedown(chan); + nouveau_notifier_takedown_channel(chan); + dev_priv->fifos[chan->id] = NULL; dev_priv->fifo_alloc_count--; drm_free(chan, sizeof(*chan), DRM_MEM_DRIVER); @@ -468,14 +468,17 @@ nouveau_fifo_owner(struct drm_device *de * ioctls wrapping the functions ***********************************/ -static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct drm_nouveau_fifo_alloc *init = data; + struct drm_nouveau_channel_alloc *init = data; struct drm_map_list *entry; struct nouveau_channel *chan; int res; + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) return -EINVAL; @@ -519,18 +522,34 @@ static int nouveau_ioctl_fifo_alloc(stru return 0; } +static int nouveau_ioctl_fifo_free(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_channel_free *cfree = data; + struct nouveau_channel *chan; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan); + + nouveau_fifo_free(chan); + return 0; +} + /*********************************** * finally, the ioctl table ***********************************/ struct drm_ioctl_desc nouveau_ioctls[] = { - DRM_IOCTL_DEF(DRM_NOUVEAU_FIFO_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_CARD_INIT, nouveau_ioctl_card_init, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH), DRM_IOCTL_DEF(DRM_NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_NOTIFIER_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH), DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_ALLOC, nouveau_ioctl_mem_alloc, DRM_AUTH), DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_FREE, nouveau_ioctl_mem_free, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), }; int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls); diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c index a7044c9..981af8a 100644 --- a/shared-core/nouveau_mem.c +++ b/shared-core/nouveau_mem.c @@ -549,14 +549,10 @@ void nouveau_mem_free(struct drm_device* int nouveau_ioctl_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_mem_alloc *alloc = data; struct mem_block *block; - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; - } + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; block=nouveau_mem_alloc(dev, alloc->alignment, alloc->size, alloc->flags, file_priv); @@ -575,6 +571,8 @@ int nouveau_ioctl_mem_free(struct drm_de struct drm_nouveau_mem_free *memfree = data; struct mem_block *block; + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + block=NULL; if (memfree->flags & NOUVEAU_MEM_FB) block = find_block(dev_priv->fb_heap, memfree->offset); diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index b109058..31547aa 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -73,6 +73,16 @@ nouveau_notifier_takedown_channel(struct nouveau_mem_takedown(&chan->notifier_heap); } +static void +nouveau_notifier_gpuobj_dtor(struct drm_device *dev, + struct nouveau_gpuobj *gpuobj) +{ + DRM_DEBUG("\n"); + + if (gpuobj->priv) + nouveau_mem_free_block(gpuobj->priv); +} + int nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, int count, uint32_t *b_offset) @@ -90,7 +100,7 @@ nouveau_notifier_alloc(struct nouveau_ch } mem = nouveau_mem_alloc_block(chan->notifier_heap, 32, 0, - chan->file_priv); + (struct drm_file *)-2); if (!mem) { DRM_ERROR("Channel %d notifier block full\n", chan->id); return -ENOMEM; @@ -117,6 +127,8 @@ nouveau_notifier_alloc(struct nouveau_ch DRM_ERROR("Error creating notifier ctxdma: %d\n", ret); return ret; } + nobj->dtor = nouveau_notifier_gpuobj_dtor; + nobj->priv = mem; if ((ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL))) { nouveau_gpuobj_del(dev, &nobj); @@ -133,10 +145,11 @@ int nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_nouveau_notifier_alloc *na = data; + struct drm_nouveau_notifierobj_alloc *na = data; struct nouveau_channel *chan; int ret; + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan); ret = nouveau_notifier_alloc(chan, na->handle, na->count, &na->offset); diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c index 274bb2a..22ad23c 100644 --- a/shared-core/nouveau_object.c +++ b/shared-core/nouveau_object.c @@ -131,6 +131,8 @@ nouveau_ramht_insert(struct drm_device * ref->channel, co, ref->handle, ctx); INSTANCE_WR(ramht, (co + 0)/4, ref->handle); INSTANCE_WR(ramht, (co + 4)/4, ctx); + + list_add_tail(&ref->list, &chan->ramht_refs); return 0; } DRM_DEBUG("collision ch%d 0x%08x: h=0x%08x\n", @@ -167,6 +169,8 @@ nouveau_ramht_remove(struct drm_device * INSTANCE_RD(ramht, (co + 4))); INSTANCE_WR(ramht, (co + 0)/4, 0x00000000); INSTANCE_WR(ramht, (co + 4)/4, 0x00000000); + + list_del(&ref->list); return; } @@ -203,6 +207,8 @@ nouveau_gpuobj_new(struct drm_device *de gpuobj->flags = flags; gpuobj->im_channel = chan ? chan->id : -1; + list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); + /* Choose between global instmem heap, and per-channel private * instmem heap. On <NV50 allow requests for private instmem * to be satisfied from global heap if no per-channel area @@ -254,24 +260,44 @@ nouveau_gpuobj_new(struct drm_device *de INSTANCE_WR(gpuobj, i/4, 0); } - if (dev_priv->gpuobj_all) { - gpuobj->next = dev_priv->gpuobj_all; - gpuobj->next->prev = gpuobj; + *gpuobj_ret = gpuobj; + return 0; +} + +int +nouveau_gpuobj_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + INIT_LIST_HEAD(&dev_priv->gpuobj_list); + + if (dev_priv->card_type < NV_50) { + if ((ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramht_offset, + dev_priv->ramht_size, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ALLOW_NO_REFS, + &dev_priv->ramht, NULL))) + return ret; } - dev_priv->gpuobj_all = gpuobj; - *gpuobj_ret = gpuobj; return 0; } -void nouveau_gpuobj_takedown(struct drm_device *dev) +void +nouveau_gpuobj_takedown(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *gpuobj = NULL; + struct list_head *entry, *tmp; DRM_DEBUG("\n"); - while ((gpuobj = dev_priv->gpuobj_all)) { + nouveau_gpuobj_del(dev, &dev_priv->ramht); + + list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) { + gpuobj = list_entry(entry, struct nouveau_gpuobj, list); + DRM_ERROR("gpuobj %p still exists at takedown, refs=%d\n", gpuobj, gpuobj->refcount); gpuobj->refcount = 0; @@ -279,7 +305,8 @@ void nouveau_gpuobj_takedown(struct drm_ } } -int nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) +int +nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->Engine; @@ -296,6 +323,9 @@ int nouveau_gpuobj_del(struct drm_device return -EINVAL; } + if (gpuobj->dtor) + gpuobj->dtor(dev, gpuobj); + engine->instmem.clear(dev, gpuobj); if (gpuobj->im_pramin) { @@ -306,12 +336,7 @@ int nouveau_gpuobj_del(struct drm_device nouveau_mem_free_block(gpuobj->im_pramin); } - if (gpuobj->next) - gpuobj->next->prev = gpuobj->prev; - if (gpuobj->prev) - gpuobj->prev->next = gpuobj->next; - else - dev_priv->gpuobj_all = gpuobj->next; + list_del(&gpuobj->list); *pgpuobj = NULL; drm_free(gpuobj, sizeof(*gpuobj), DRM_MEM_DRIVER); @@ -403,9 +428,6 @@ nouveau_gpuobj_ref_add(struct drm_device drm_free(ref, sizeof(*ref), DRM_MEM_DRIVER); return ret; } - - ref->next = chan->ramht_refs; - chan->ramht_refs = ref; } else { ref->handle = ~0; *ref_ret = ref; @@ -462,19 +484,21 @@ nouveau_gpuobj_new_ref(struct drm_device return 0; } -static int +int nouveau_gpuobj_ref_find(struct nouveau_channel *chan, uint32_t handle, struct nouveau_gpuobj_ref **ref_ret) { - struct nouveau_gpuobj_ref *ref = chan->ramht_refs; + struct nouveau_gpuobj_ref *ref; + struct list_head *entry, *tmp; + + list_for_each_safe(entry, tmp, &chan->ramht_refs) { + ref = list_entry(entry, struct nouveau_gpuobj_ref, list); - while (ref) { if (ref->handle == handle) { if (ref_ret) *ref_ret = ref; return 0; } - ref = ref->next; } return -EINVAL; @@ -499,6 +523,8 @@ nouveau_gpuobj_new_fake(struct drm_devic gpuobj->im_channel = -1; gpuobj->flags = flags | NVOBJ_FLAG_FAKE; + list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); + gpuobj->im_pramin = drm_calloc(1, sizeof(struct mem_block), DRM_MEM_DRIVER); if (!gpuobj->im_pramin) { @@ -897,6 +923,8 @@ nouveau_gpuobj_channel_init(struct nouve struct nouveau_gpuobj *vram = NULL, *tt = NULL; int ret, i; + INIT_LIST_HEAD(&chan->ramht_refs); + DRM_DEBUG("ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); /* Reserve a block of PRAMIN for the channel @@ -994,14 +1022,17 @@ void nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; + struct list_head *entry, *tmp; struct nouveau_gpuobj_ref *ref; DRM_DEBUG("ch%d\n", chan->id); - while ((ref = chan->ramht_refs)) { - chan->ramht_refs = ref->next; + list_for_each_safe(entry, tmp, &chan->ramht_refs) { + ref = list_entry(entry, struct nouveau_gpuobj_ref, list); + nouveau_gpuobj_ref_del(dev, &ref); } + nouveau_gpuobj_ref_del(dev, &chan->ramht); nouveau_gpuobj_del(dev, &chan->vm_pd); @@ -1022,6 +1053,7 @@ int nouveau_ioctl_grobj_alloc(struct drm struct nouveau_gpuobj *gr = NULL; int ret; + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan); //FIXME: check args, only allow trusted objects to be created @@ -1029,8 +1061,7 @@ int nouveau_ioctl_grobj_alloc(struct drm if (init->handle == ~0) return -EINVAL; - if (nouveau_gpuobj_ref_find(chan, init->handle, NULL) == - 0) + if (nouveau_gpuobj_ref_find(chan, init->handle, NULL) == 0) return -EEXIST; ret = nouveau_gpuobj_gr_new(chan, init->class, &gr); @@ -1050,3 +1081,21 @@ int nouveau_ioctl_grobj_alloc(struct drm return 0; } +int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_gpuobj_free *objfree = data; + struct nouveau_gpuobj_ref *ref; + struct nouveau_channel *chan; + int ret; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan); + + if ((ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref))) + return ret; + nouveau_gpuobj_ref_del(dev, &ref); + + return 0; +} + diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 26ba8fb..4fb5329 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -267,12 +267,16 @@ static int nouveau_init_engine_ptrs(stru return 0; } -static int nouveau_card_init(struct drm_device *dev) +int +nouveau_card_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine; int ret; + if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE) + return 0; + /* Map any PCI resources we need on the card */ ret = nouveau_init_card_mappings(dev); if (ret) return ret; @@ -290,6 +294,9 @@ static int nouveau_card_init(struct drm_ engine = &dev_priv->Engine; dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED; + ret = drm_irq_install(dev); + if (ret) return ret; + /* Initialise instance memory, must happen before mem_init so we * know exactly how much VRAM we're able to use for "normal" * purposes. @@ -301,6 +308,9 @@ static int nouveau_card_init(struct drm_ ret = nouveau_mem_init(dev); if (ret) return ret; + ret = nouveau_gpuobj_init(dev); + if (ret) return ret; + /* Parse BIOS tables / Run init tables? */ /* PMC */ @@ -349,6 +359,8 @@ static void nouveau_card_takedown(struct nouveau_mem_close(dev); engine->instmem.takedown(dev); + drm_irq_uninstall(dev); + dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; } } @@ -368,14 +380,6 @@ void nouveau_preclose(struct drm_device /* first module load, setup the mmio/fb mapping */ int nouveau_firstopen(struct drm_device *dev) { - int ret; - - ret = nouveau_card_init(dev); - if (ret) { - DRM_ERROR("nouveau_card_init() failed! (%d)\n", ret); - return ret; - } - return 0; } @@ -395,15 +399,6 @@ int nouveau_load(struct drm_device *dev, dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; dev->dev_private = (void *)dev_priv; - -#if 0 - ret = nouveau_card_init(dev); - if (ret) { - DRM_ERROR("nouveau_card_init() failed! (%d)\n", ret); - return ret; - } -#endif - return 0; } @@ -427,12 +422,24 @@ int nouveau_unload(struct drm_device *de return 0; } +int +nouveau_ioctl_card_init(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return nouveau_card_init(dev); +} + int nouveau_ioctl_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_getparam *getparam = data; + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + switch (getparam->param) { + case NOUVEAU_GETPARAM_CHIPSET_ID: + getparam->value = dev_priv->chipset; + break; case NOUVEAU_GETPARAM_PCI_VENDOR: getparam->value=dev->pci_vendor; break; @@ -481,6 +488,8 @@ int nouveau_ioctl_setparam(struct drm_de struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_setparam *setparam = data; + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + switch (setparam->param) { case NOUVEAU_SETPARAM_CMDBUF_LOCATION: switch (setparam->value) { diff --git a/shared-core/nv04_instmem.c b/shared-core/nv04_instmem.c index 35b20ab..36aa620 100644 --- a/shared-core/nv04_instmem.c +++ b/shared-core/nv04_instmem.c @@ -93,13 +93,6 @@ int nv04_instmem_init(struct drm_device nv04_instmem_determine_amount(dev); nv04_instmem_configure_fixed_tables(dev); - if ((ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramht_offset, - dev_priv->ramht_size, - NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ALLOW_NO_REFS, - &dev_priv->ramht, NULL))) - return ret; - /* Create a heap to manage RAMIN allocations, we don't allocate * the space that was reserved for RAMHT/FC/RO. */ @@ -117,9 +110,6 @@ int nv04_instmem_init(struct drm_device void nv04_instmem_takedown(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - - nouveau_gpuobj_del(dev, &dev_priv->ramht); } int diff-tree beaa0c9a28b30a6ba3292184d04875b6a597e433 (from 2453ba19b6f9956ea5d412a66d5d33c8a8b301b2) Author: Ben Skeggs <sk...@gm...> Date: Mon Aug 6 03:40:43 2007 +1000 nouveau: Pass channel struct around instead of channel id. diff --git a/linux-core/nouveau_sgdma.c b/linux-core/nouveau_sgdma.c index 0ddac95..6393a46 100644 --- a/linux-core/nouveau_sgdma.c +++ b/linux-core/nouveau_sgdma.c @@ -211,7 +211,7 @@ nouveau_sgdma_init(struct drm_device *de obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 8; } - if ((ret = nouveau_gpuobj_new(dev, -1, obj_size, 16, + if ((ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, NVOBJ_FLAG_ALLOW_NO_REFS | NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, &gpuobj))) { diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index dd323a0..8ec9189 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -92,8 +92,11 @@ struct nouveau_gpuobj_ref { int handle; }; -struct nouveau_fifo +struct nouveau_channel { + struct drm_device *dev; + int id; + /* owner of this fifo */ struct drm_file *file_priv; /* mapping of the fifo itself */ @@ -136,57 +139,64 @@ struct nouveau_config { } cmdbuf; }; -struct nouveau_engine_func { - struct { - void *priv; +struct nouveau_instmem_engine { + void *priv; - int (*init)(struct drm_device *dev); - void (*takedown)(struct drm_device *dev); + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); - int (*populate)(struct drm_device *, struct nouveau_gpuobj *, - uint32_t *size); - void (*clear)(struct drm_device *, struct nouveau_gpuobj *); - int (*bind)(struct drm_device *, struct nouveau_gpuobj *); - int (*unbind)(struct drm_device *, struct nouveau_gpuobj *); - } instmem; + int (*populate)(struct drm_device *, struct nouveau_gpuobj *, + uint32_t *size); + void (*clear)(struct drm_device *, struct nouveau_gpuobj *); + int (*bind)(struct drm_device *, struct nouveau_gpuobj *); + int (*unbind)(struct drm_device *, struct nouveau_gpuobj *); +}; - struct { - int (*init)(struct drm_device *dev); - void (*takedown)(struct drm_device *dev); - } mc; +struct nouveau_mc_engine { + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); +}; - struct { - int (*init)(struct drm_device *dev); - uint64_t (*read)(struct drm_device *dev); - void (*takedown)(struct drm_device *dev); - } timer; +struct nouveau_timer_engine { + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); + uint64_t (*read)(struct drm_device *dev); +}; - struct { - int (*init)(struct drm_device *dev); - void (*takedown)(struct drm_device *dev); - } fb; +struct nouveau_fb_engine { + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); +}; - struct { - int (*init)(struct drm_device *); - void (*takedown)(struct drm_device *); +struct nouveau_fifo_engine { + void *priv; - int (*create_context)(struct drm_device *, int channel); - void (*destroy_context)(struct drm_device *, int channel); - int (*load_context)(struct drm_device *, int channel); - int (*save_context)(struct drm_device *, int channel); - } graph; + int (*init)(struct drm_device *); + void (*takedown)(struct drm_device *); - struct { - void *priv; + int (*create_context)(struct nouveau_channel *); + void (*destroy_context)(struct nouveau_channel *); + int (*load_context)(struct nouveau_channel *); + int (*save_context)(struct nouveau_channel *); +}; - int (*init)(struct drm_device *); - void (*takedown)(struct drm_device *); +struct nouveau_pgraph_engine { + int (*init)(struct drm_device *); + void (*takedown)(struct drm_device *); + + int (*create_context)(struct nouveau_channel *); + void (*destroy_context)(struct nouveau_channel *); + int (*load_context)(struct nouveau_channel *); + int (*save_context)(struct nouveau_channel *); +}; - int (*create_context)(struct drm_device *, int channel); - void (*destroy_context)(struct drm_device *, int channel); - int (*load_context)(struct drm_device *, int channel); - int (*save_context)(struct drm_device *, int channel); - } fifo; +struct nouveau_engine { + struct nouveau_instmem_engine instmem; + struct nouveau_mc_engine mc; + struct nouveau_timer_engine timer; + struct nouveau_fb_engine fb; + struct nouveau_pgraph_engine graph; + struct nouveau_fifo_engine fifo; }; struct drm_nouveau_private { @@ -207,9 +217,9 @@ struct drm_nouveau_private { drm_local_map_t *ramin; /* NV40 onwards */ int fifo_alloc_count; - struct nouveau_fifo *fifos[NV_MAX_FIFO_NUMBER]; + struct nouveau_channel *fifos[NV_MAX_FIFO_NUMBER]; - struct nouveau_engine_func Engine; + struct nouveau_engine Engine; /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ struct nouveau_gpuobj *ramht; @@ -262,93 +272,108 @@ struct drm_nouveau_private { struct nouveau_gpuobj *gpuobj_all; }; +#define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id,cl,ch) do { \ + struct drm_nouveau_private *nv = dev->dev_private; \ + if (!nouveau_fifo_owner(dev, (cl), (id))) { \ + DRM_ERROR("pid %d doesn't own channel %d\n", \ + DRM_CURRENTPID, (id)); \ + return -EPERM; \ + } \ + (ch) = nv->fifos[(id)]; \ +} while(0) + /* nouveau_state.c */ -extern void nouveau_preclose(struct drm_device * dev, - struct drm_file *file_priv); -extern int nouveau_load(struct drm_device *dev, unsigned long flags); -extern int nouveau_firstopen(struct drm_device *dev); -extern void nouveau_lastclose(struct drm_device *dev); -extern int nouveau_unload(struct drm_device *dev); -extern int nouveau_ioctl_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int nouveau_ioctl_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern void nouveau_wait_for_idle(struct drm_device *dev); -extern int nouveau_ioctl_card_init(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern void nouveau_preclose(struct drm_device *dev, struct drm_file *); +extern int nouveau_load(struct drm_device *, unsigned long flags); +extern int nouveau_firstopen(struct drm_device *); +extern void nouveau_lastclose(struct drm_device *); +extern int nouveau_unload(struct drm_device *); +extern int nouveau_ioctl_getparam(struct drm_device *, void *data, + struct drm_file *); +extern int nouveau_ioctl_setparam(struct drm_device *, void *data, + struct drm_file *); +extern void nouveau_wait_for_idle(struct drm_device *); +extern int nouveau_ioctl_card_init(struct drm_device *, void *data, + struct drm_file *); /* nouveau_mem.c */ -extern int nouveau_mem_init_heap(struct mem_block **, - uint64_t start, uint64_t size); +extern int nouveau_mem_init_heap(struct mem_block **, uint64_t start, + uint64_t size); extern struct mem_block *nouveau_mem_alloc_block(struct mem_block *, uint64_t size, int align2, - struct drm_file *file_priv); -extern void nouveau_mem_takedown(struct mem_block **heap); -extern void nouveau_mem_free_block(struct mem_block *); -extern uint64_t nouveau_mem_fb_amount(struct drm_device *dev); -extern void nouveau_mem_release(struct drm_file *file_priv, - struct mem_block *heap); -extern int nouveau_ioctl_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int nouveau_ioctl_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern struct mem_block* nouveau_mem_alloc(struct drm_device *dev, + struct drm_file *); +extern void nouveau_mem_takedown(struct mem_block **heap); +extern void nouveau_mem_free_block(struct mem_block *); +extern uint64_t nouveau_mem_fb_amount(struct drm_device *); +extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap); +extern int nouveau_ioctl_mem_alloc(struct drm_device *, void *data, + struct drm_file *); +extern int nouveau_ioctl_mem_free(struct drm_device *, void *data, + struct drm_file *); +extern struct mem_block* nouveau_mem_alloc(struct drm_device *, int alignment, uint64_t size, - int flags, - struct drm_file *file_priv); -extern void nouveau_mem_free(struct drm_device* dev, struct mem_block*); -extern int nouveau_mem_init(struct drm_device *dev); -extern void nouveau_mem_close(struct drm_device *dev); + int flags, struct drm_file *); +extern void nouveau_mem_free(struct drm_device *dev, struct mem_block*); +extern int nouveau_mem_init(struct drm_device *); +extern void nouveau_mem_close(struct drm_device *); /* nouveau_notifier.c */ -extern int nouveau_notifier_init_channel(struct drm_device *, int channel, - struct drm_file *file_priv); -extern void nouveau_notifier_takedown_channel(struct drm_device *, int channel); -extern int nouveau_notifier_alloc(struct drm_device *, int channel, - uint32_t handle, int cout, uint32_t *offset); -extern int nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int nouveau_notifier_init_channel(struct nouveau_channel *); +extern void nouveau_notifier_takedown_channel(struct nouveau_channel *); +extern int nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, + int cout, uint32_t *offset); +extern int nouveau_ioctl_notifier_alloc(struct drm_device *, void *data, + struct drm_file *); /* nouveau_fifo.c */ -extern int nouveau_fifo_init(struct drm_device *dev); -extern int nouveau_fifo_number(struct drm_device *dev); -extern int nouveau_fifo_ctx_size(struct drm_device *dev); -extern void nouveau_fifo_cleanup(struct drm_device *dev, - struct drm_file *file_priv); -extern int nouveau_fifo_owner(struct drm_device *dev, - struct drm_file *file_priv, int channel); -extern void nouveau_fifo_free(struct drm_device *dev, int channel); +extern int nouveau_fifo_init(struct drm_device *); +extern int nouveau_fifo_number(struct drm_device *); +extern int nouveau_fifo_ctx_size(struct drm_device *); +extern void nouveau_fifo_cleanup(struct drm_device *, struct drm_file *); +extern int nouveau_fifo_owner(struct drm_device *, struct drm_file *, + int channel); +extern void nouveau_fifo_free(struct nouveau_channel *); /* nouveau_object.c */ -extern void nouveau_gpuobj_takedown(struct drm_device *dev); -extern int nouveau_gpuobj_channel_init(struct drm_device *, int channel, +extern void nouveau_gpuobj_takedown(struct drm_device *); +extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, uint32_t vram_h, uint32_t tt_h); -extern void nouveau_gpuobj_channel_takedown(struct drm_device *, int channel); -extern int nouveau_gpuobj_new(struct drm_device *, int channel, int size, int align, - uint32_t flags, struct nouveau_gpuobj **); +extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *); +extern int nouveau_gpuobj_new(struct drm_device *, struct nouveau_channel *, + int size, int align, uint32_t flags, + struct nouveau_gpuobj **); extern int nouveau_gpuobj_del(struct drm_device *, struct nouveau_gpuobj **); -extern int nouveau_gpuobj_ref_add(struct drm_device *, int channel, uint32_t handle, - struct nouveau_gpuobj *, +extern int nouveau_gpuobj_ref_add(struct drm_device *, struct nouveau_channel *, + uint32_t handle, struct nouveau_gpuobj *, + struct nouveau_gpuobj_ref **); +extern int nouveau_gpuobj_ref_del(struct drm_device *, struct nouveau_gpuobj_ref **); -extern int nouveau_gpuobj_ref_del(struct drm_device *, struct nouveau_gpuobj_ref **); -extern int nouveau_gpuobj_new_ref(struct drm_device *, int chan_obj, int chan_ref, +extern int nouveau_gpuobj_new_ref(struct drm_device *, + struct nouveau_channel *alloc_chan, + struct nouveau_channel *ref_chan, uint32_t handle, int size, int align, uint32_t flags, struct nouveau_gpuobj_ref **); extern int nouveau_gpuobj_new_fake(struct drm_device *, uint32_t offset, uint32_t size, uint32_t flags, - struct nouveau_gpuobj**, + struct nouveau_gpuobj **, struct nouveau_gpuobj_ref**); -extern int nouveau_gpuobj_dma_new(struct drm_device *, int channel, int class, - uint64_t offset, uint64_t size, - int access, int target, - struct nouveau_gpuobj **); -extern int nouveau_gpuobj_gart_dma_new(struct drm_device *, int channel, +extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class, + uint64_t offset, uint64_t size, int access, + int target, struct nouveau_gpuobj **); +extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *, uint64_t offset, uint64_t size, int access, struct nouveau_gpuobj **, uint32_t *o_ret); -extern int nouveau_gpuobj_gr_new(struct drm_device *, int channel, int class, +extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class, struct nouveau_gpuobj **); -extern int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data, + struct drm_file *); /* nouveau_irq.c */ extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); -extern void nouveau_irq_preinstall(struct drm_device*); -extern void nouveau_irq_postinstall(struct drm_device*); -extern void nouveau_irq_uninstall(struct drm_device*); +extern void nouveau_irq_preinstall(struct drm_device *); +extern void nouveau_irq_postinstall(struct drm_device *); +extern void nouveau_irq_uninstall(struct drm_device *); /* nouveau_sgdma.c */ extern int nouveau_sgdma_init(struct drm_device *); @@ -358,131 +383,131 @@ extern int nouveau_sgdma_nottm_hack_init extern void nouveau_sgdma_nottm_hack_takedown(struct drm_device *); /* nv04_fb.c */ -extern int nv04_fb_init(struct drm_device *dev); -extern void nv04_fb_takedown(struct drm_device *dev); +extern int nv04_fb_init(struct drm_device *); +extern void nv04_fb_takedown(struct drm_device *); /* nv10_fb.c */ -extern int nv10_fb_init(struct drm_device *dev); -extern void nv10_fb_takedown(struct drm_device *dev); +extern int nv10_fb_init(struct drm_device *); +extern void nv10_fb_takedown(struct drm_device *); /* nv40_fb.c */ -extern int nv40_fb_init(struct drm_device *dev); -extern void nv40_fb_takedown(struct drm_device *dev); +extern int nv40_fb_init(struct drm_device *); +extern void nv40_fb_takedown(struct drm_device *); /* nv04_fifo.c */ -extern int nv04_fifo_create_context(struct drm_device *dev, int channel); -extern void nv04_fifo_destroy_context(struct drm_device *dev, int channel); -extern int nv04_fifo_load_context(struct drm_device *dev, int channel); -extern int nv04_fifo_save_context(struct drm_device *dev, int channel); +extern int nv04_fifo_create_context(struct nouveau_channel *); +extern void nv04_fifo_destroy_context(struct nouveau_channel *); +extern int nv04_fifo_load_context(struct nouveau_channel *); +extern int nv04_fifo_save_context(struct nouveau_channel *); /* nv10_fifo.c */ -extern int nv10_fifo_create_context(struct drm_device *dev, int channel); -extern void nv10_fifo_destroy_context(struct drm_device *dev, int channel); -extern int nv10_fifo_load_context(struct drm_device *dev, int channel); -extern int nv10_fifo_save_context(struct drm_device *dev, int channel); +extern int nv10_fifo_create_context(struct nouveau_channel *); +extern void nv10_fifo_destroy_context(struct nouveau_channel *); +extern int nv10_fifo_load_context(struct nouveau_channel *); +extern int nv10_fifo_save_context(struct nouveau_channel *); /* nv40_fifo.c */ -extern int nv40_fifo_create_context(struct drm_device *, int channel); -extern void nv40_fifo_destroy_context(struct drm_device *, int channel); -extern int nv40_fifo_load_context(struct drm_device *, int channel); -extern int nv40_fifo_save_context(struct drm_device *, int channel); +extern int nv40_fifo_create_context(struct nouveau_channel *); +extern void nv40_fifo_destroy_context(struct nouveau_channel *); +extern int nv40_fifo_load_context(struct nouveau_channel *); +extern int nv40_fifo_save_context(struct nouveau_channel *); /* nv50_fifo.c */ extern int nv50_fifo_init(struct drm_device *); extern void nv50_fifo_takedown(struct drm_device *); -extern int nv50_fifo_create_context(struct drm_device *, int channel); -extern void nv50_fifo_destroy_context(struct drm_device *, int channel); -extern int nv50_fifo_load_context(struct drm_device *, int channel); -extern int nv50_fifo_save_context(struct drm_device *, int channel); +extern int nv50_fifo_create_context(struct nouveau_channel *); +extern void nv50_fifo_destroy_context(struct nouveau_channel *); +extern int nv50_fifo_load_context(struct nouveau_channel *); +extern int nv50_fifo_save_context(struct nouveau_channel *); /* nv04_graph.c */ -extern void nouveau_nv04_context_switch(struct drm_device *dev); -extern int nv04_graph_init(struct drm_device *dev); -extern void nv04_graph_takedown(struct drm_device *dev); -extern int nv04_graph_create_context(struct drm_device *dev, int channel); -extern void nv04_graph_destroy_context(struct drm_device *dev, int channel); -extern int nv04_graph_load_context(struct drm_device *dev, int channel); -extern int nv04_graph_save_context(struct drm_device *dev, int channel); +extern void nouveau_nv04_context_switch(struct drm_device *); +extern int nv04_graph_init(struct drm_device *); +extern void nv04_graph_takedown(struct drm_device *); +extern int nv04_graph_create_context(struct nouveau_channel *); +extern void nv04_graph_destroy_context(struct nouveau_channel *); +extern int nv04_graph_load_context(struct nouveau_channel *); +extern int nv04_graph_save_context(struct nouveau_channel *); /* nv10_graph.c */ -extern void nouveau_nv10_context_switch(struct drm_device *dev); -extern int nv10_graph_init(struct drm_device *dev); -extern void nv10_graph_takedown(struct drm_device *dev); -extern int nv10_graph_create_context(struct drm_device *dev, int channel); -extern void nv10_graph_destroy_context(struct drm_device *dev, int channel); -extern int nv10_graph_load_context(struct drm_device *dev, int channel); -extern int nv10_graph_save_context(struct drm_device *dev, int channel); +extern void nouveau_nv10_context_switch(struct drm_device *); +extern int nv10_graph_init(struct drm_device *); +extern void nv10_graph_takedown(struct drm_device *); +extern int nv10_graph_create_context(struct nouveau_channel *); +extern void nv10_graph_destroy_context(struct nouveau_channel *); +extern int nv10_graph_load_context(struct nouveau_channel *); +extern int nv10_graph_save_context(struct nouveau_channel *); /* nv20_graph.c */ -extern void nouveau_nv20_context_switch(struct drm_device *dev); -extern int nv20_graph_init(struct drm_device *dev); -extern void nv20_graph_takedown(struct drm_device *dev); -extern int nv20_graph_create_context(struct drm_device *dev, int channel); -extern void nv20_graph_destroy_context(struct drm_device *dev, int channel); -extern int nv20_graph_load_context(struct drm_device *dev, int channel); -extern int nv20_graph_save_context(struct drm_device *dev, int channel); +extern void nouveau_nv20_context_switch(struct drm_device *); +extern int nv20_graph_init(struct drm_device *); +extern void nv20_graph_takedown(struct drm_device *); +extern int nv20_graph_create_context(struct nouveau_ch... [truncated message content] |
From: <dar...@ke...> - 2007-11-13 07:10:00
|
linux-core/Makefile.kernel | 2 linux-core/nouveau_bo.c | 265 ++++++++++++++++++++++++++++++++++++++++++++ linux-core/nouveau_buffer.c | 256 ------------------------------------------ linux-core/nouveau_fence.c | 3 shared-core/nouveau_dma.c | 6 shared-core/nouveau_dma.h | 3 shared-core/nouveau_drm.h | 6 shared-core/nouveau_drv.h | 23 +++ shared-core/nouveau_fifo.c | 109 ++++++++++-------- shared-core/nouveau_irq.c | 11 - shared-core/nouveau_reg.h | 47 ++++++- shared-core/nouveau_state.c | 14 ++ shared-core/nv04_fifo.c | 12 + shared-core/nv04_graph.c | 5 shared-core/nv04_instmem.c | 9 - shared-core/nv10_fifo.c | 12 + shared-core/nv10_graph.c | 11 + shared-core/nv40_fifo.c | 4 shared-core/nv50_fifo.c | 9 + 19 files changed, 468 insertions(+), 339 deletions(-) New commits: commit eb5487b9ca1d7ce60d5ddc784089d91cf176f439 Merge: 2370ded... 7c1e59f... Author: Ben Skeggs <sk...@gm...> Date: Wed Nov 14 05:09:07 2007 +1100 Merge branch 'fifo-cleanup' into upstream-master commit 7c1e59fb0c5043d3d369f5feb8e195a6a3da3457 Author: Ben Skeggs <sk...@gm...> Date: Wed Nov 14 04:24:36 2007 +1100 nouveau: Attempt to wait for channel idle before we destroy it. diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 7e109ad..3c993f3 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -402,9 +402,31 @@ void nouveau_fifo_free(struct nouveau_channel *chan) struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->Engine; + uint64_t t_start; DRM_INFO("%s: freeing fifo %d\n", __func__, chan->id); + /* Disable channel switching, if this channel isn't currenly + * active re-enable it if there's still pending commands. + * We really should do a manual context switch here, but I'm + * not sure I trust our ability to do this reliably yet.. + */ + NV_WRITE(NV03_PFIFO_CACHES, 0); + if (engine->fifo.channel_id(dev) != chan->id && + NV_READ(chan->get) != NV_READ(chan->put)) { + NV_WRITE(NV03_PFIFO_CACHES, 1); + } + + /* Give the channel a chance to idle, wait 2s (hopefully) */ + t_start = engine->timer.read(dev); + while (NV_READ(chan->get) != NV_READ(chan->put)) { + if (engine->timer.read(dev) - t_start > 2000000000ULL) { + DRM_ERROR("Failed to idle channel %d before destroy." + "Prepare for strangeness..\n", chan->id); + break; + } + } + /* disable the fifo caches */ NV_WRITE(NV03_PFIFO_CACHES, 0x00000000); NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, NV_READ(NV04_PFIFO_CACHE1_DMA_PUSH)&(~0x1)); commit 53ab6026cfb20bfdf34b245e41af424be62941a8 Author: Ben Skeggs <sk...@gm...> Date: Wed Nov 14 04:15:13 2007 +1100 nouveau: Use "new" NV40 USER control regs. Probably entirely pointless, but a simple change in any case. diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 45b8211..7e109ad 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -295,12 +295,19 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, DRM_INFO("Allocating FIFO number %d\n", channel); /* Locate channel's user control regs */ - if (dev_priv->card_type < NV_50) { + if (dev_priv->card_type < NV_40) { chan->user = NV03_USER(channel); chan->user_size = NV03_USER_SIZE; chan->put = NV03_USER_DMA_PUT(channel); chan->get = NV03_USER_DMA_GET(channel); chan->ref_cnt = NV03_USER_REF_CNT(channel); + } else + if (dev_priv->card_type < NV_50) { + chan->user = NV40_USER(channel); + chan->user_size = NV40_USER_SIZE; + chan->put = NV40_USER_DMA_PUT(channel); + chan->get = NV40_USER_DMA_GET(channel); + chan->ref_cnt = NV40_USER_REF_CNT(channel); } else { chan->user = NV50_USER(channel); chan->user_size = NV50_USER_SIZE; commit 7246a33dd104903bc9227628270712ea9e6168d8 Author: Ben Skeggs <sk...@gm...> Date: Wed Nov 14 04:05:48 2007 +1100 nouveau: store user control reg offsets in channel struct diff --git a/linux-core/nouveau_fence.c b/linux-core/nouveau_fence.c index b3e81a8..4e624a7 100644 --- a/linux-core/nouveau_fence.c +++ b/linux-core/nouveau_fence.c @@ -79,6 +79,7 @@ nouveau_fence_perform_flush(struct drm_device *dev, uint32_t class) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_fence_class_manager *fc = &dev->fm.fence_class[class]; + struct nouveau_channel *chan = dev_priv->fifos[class]; uint32_t pending_types = 0; DRM_DEBUG("class=%d\n", class); @@ -89,7 +90,7 @@ nouveau_fence_perform_flush(struct drm_device *dev, uint32_t class) fc->pending_flush); if (pending_types) { - uint32_t sequence = NV_READ(NV03_FIFO_REGS(class) + 0x48); + uint32_t sequence = NV_READ(chan->ref_cnt); DRM_DEBUG("got 0x%08x\n", sequence); drm_fence_handler(dev, class, sequence, pending_types, 0); diff --git a/shared-core/nouveau_dma.c b/shared-core/nouveau_dma.c index b406c22..dff786d 100644 --- a/shared-core/nouveau_dma.c +++ b/shared-core/nouveau_dma.c @@ -133,10 +133,10 @@ nouveau_dma_channel_takedown(struct drm_device *dev) #define RING_SKIPS 8 -#define READ_GET() ((NV_READ(NV03_FIFO_REGS_DMAGET(dchan->chan->id)) - \ - dchan->chan->pushbuf_base) >> 2) +#define READ_GET() ((NV_READ(dchan->chan->get) - \ + dchan->chan->pushbuf_base) >> 2) #define WRITE_PUT(val) do { \ - NV_WRITE(NV03_FIFO_REGS_DMAPUT(dchan->chan->id), \ + NV_WRITE(dchan->chan->put, \ ((val) << 2) + dchan->chan->pushbuf_base); \ } while(0) diff --git a/shared-core/nouveau_dma.h b/shared-core/nouveau_dma.h index f8df54e..ce3c58c 100644 --- a/shared-core/nouveau_dma.h +++ b/shared-core/nouveau_dma.h @@ -89,8 +89,7 @@ typedef enum { if (dchan->cur != dchan->put) { \ DRM_MEMORYBARRIER(); \ dchan->put = dchan->cur; \ - NV_WRITE(NV03_FIFO_REGS_DMAPUT(dchan->chan->id), \ - (dchan->put<<2)); \ + NV_WRITE(dchan->chan->put, dchan->put << 2); \ } \ } while(0) diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 07bd88e..85a0d0b 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -114,6 +114,12 @@ struct nouveau_channel struct mem_block *pushbuf_mem; uint32_t pushbuf_base; + /* FIFO user control regs */ + uint32_t user, user_size; + uint32_t put; + uint32_t get; + uint32_t ref_cnt; + /* Notifier memory */ struct mem_block *notifier_block; struct mem_block *notifier_heap; @@ -225,6 +231,7 @@ struct nouveau_engine { struct nouveau_fifo_engine fifo; }; +#define NOUVEAU_MAX_CHANNEL_NR 128 struct drm_nouveau_private { enum { NOUVEAU_CARD_INIT_DOWN, @@ -245,7 +252,7 @@ struct drm_nouveau_private { drm_local_map_t *ramin; /* NV40 onwards */ int fifo_alloc_count; - struct nouveau_channel *fifos[NV_MAX_FIFO_NUMBER]; + struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR]; struct nouveau_engine Engine; struct nouveau_drm_channel channel; diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 7c24ed2..45b8211 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -294,6 +294,21 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, DRM_INFO("Allocating FIFO number %d\n", channel); + /* Locate channel's user control regs */ + if (dev_priv->card_type < NV_50) { + chan->user = NV03_USER(channel); + chan->user_size = NV03_USER_SIZE; + chan->put = NV03_USER_DMA_PUT(channel); + chan->get = NV03_USER_DMA_GET(channel); + chan->ref_cnt = NV03_USER_REF_CNT(channel); + } else { + chan->user = NV50_USER(channel); + chan->user_size = NV50_USER_SIZE; + chan->put = NV50_USER_DMA_PUT(channel); + chan->get = NV50_USER_DMA_GET(channel); + chan->ref_cnt = NV50_USER_REF_CNT(channel); + } + /* Allocate space for per-channel fixed notifier memory */ ret = nouveau_notifier_init_channel(chan); if (ret) { @@ -337,14 +352,11 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, return ret; } - /* setup channel's default get/put values */ - if (dev_priv->card_type < NV_50) { - NV_WRITE(NV03_FIFO_REGS_DMAPUT(channel), chan->pushbuf_base); - NV_WRITE(NV03_FIFO_REGS_DMAGET(channel), chan->pushbuf_base); - } else { - NV_WRITE(NV50_FIFO_REGS_DMAPUT(channel), chan->pushbuf_base); - NV_WRITE(NV50_FIFO_REGS_DMAGET(channel), chan->pushbuf_base); - } + /* setup channel's default get/put values + * XXX: quite possibly extremely pointless.. + */ + NV_WRITE(chan->get, chan->pushbuf_base); + NV_WRITE(chan->put, chan->pushbuf_base); /* If this is the first channel, setup PFIFO ourselves. For any * other case, the GPU will handle this when it switches contexts. @@ -393,14 +405,12 @@ void nouveau_fifo_free(struct nouveau_channel *chan) NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000); /* stop the fifo, otherwise it could be running and - * it will crash when removing gpu objects */ - if (dev_priv->card_type < NV_50) { - NV_WRITE(NV03_FIFO_REGS_DMAPUT(chan->id), chan->pushbuf_base); - NV_WRITE(NV03_FIFO_REGS_DMAGET(chan->id), chan->pushbuf_base); - } else { - NV_WRITE(NV50_FIFO_REGS_DMAPUT(chan->id), chan->pushbuf_base); - NV_WRITE(NV50_FIFO_REGS_DMAGET(chan->id), chan->pushbuf_base); - } + * it will crash when removing gpu objects + *XXX: from real-world evidence, absolutely useless.. + */ + NV_WRITE(chan->get, chan->pushbuf_base); + NV_WRITE(chan->put, chan->pushbuf_base); + // FIXME XXX needs more code engine->fifo.destroy_context(chan); @@ -495,14 +505,8 @@ static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, /* make the fifo available to user space */ /* first, the fifo control regs */ - init->ctrl = dev_priv->mmio->offset; - if (dev_priv->card_type < NV_50) { - init->ctrl += NV03_FIFO_REGS(init->channel); - init->ctrl_size = NV03_FIFO_REGS_SIZE; - } else { - init->ctrl += NV50_FIFO_REGS(init->channel); - init->ctrl_size = NV50_FIFO_REGS_SIZE; - } + init->ctrl = dev_priv->mmio->offset + chan->user; + init->ctrl_size = chan->user_size; res = drm_addmap(dev, init->ctrl, init->ctrl_size, _DRM_REGISTERS, 0, &chan->regs); if (res != 0) diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index e097e01..bc71e5f 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -45,16 +45,40 @@ #define NV_CLASS_NULL 0x00000030 #define NV_CLASS_DMA_IN_MEMORY 0x0000003D +#define NV03_USER(i) (0x00800000+(i*NV03_USER_SIZE)) +#define NV03_USER__SIZE 16 +#define NV10_USER__SIZE 32 +#define NV03_USER_SIZE 0x00010000 +#define NV03_USER_DMA_PUT(i) (0x00800040+(i*NV03_USER_SIZE)) +#define NV03_USER_DMA_PUT__SIZE 16 +#define NV10_USER_DMA_PUT__SIZE 32 +#define NV03_USER_DMA_GET(i) (0x00800044+(i*NV03_USER_SIZE)) +#define NV03_USER_DMA_GET__SIZE 16 +#define NV10_USER_DMA_GET__SIZE 32 +#define NV03_USER_REF_CNT(i) (0x00800048+(i*NV03_USER_SIZE)) +#define NV03_USER_REF_CNT__SIZE 16 +#define NV10_USER_REF_CNT__SIZE 32 + +#define NV40_USER(i) (0x00c00000+(i*NV40_USER_SIZE)) +#define NV40_USER_SIZE 0x00001000 +#define NV40_USER_DMA_PUT(i) (0x00c00040+(i*NV40_USER_SIZE)) +#define NV40_USER_DMA_PUT__SIZE 32 +#define NV40_USER_DMA_GET(i) (0x00c00044+(i*NV40_USER_SIZE)) +#define NV40_USER_DMA_GET__SIZE 32 +#define NV40_USER_REF_CNT(i) (0x00c00048+(i*NV40_USER_SIZE)) +#define NV40_USER_REF_CNT__SIZE 32 + +#define NV50_USER(i) (0x00c00000+(i*NV50_USER_SIZE)) +#define NV50_USER_SIZE 0x00002000 +#define NV50_USER_DMA_PUT(i) (0x00c00040+(i*NV50_USER_SIZE)) +#define NV50_USER_DMA_PUT__SIZE 128 +#define NV50_USER_DMA_GET(i) (0x00c00044+(i*NV50_USER_SIZE)) +#define NV50_USER_DMA_GET__SIZE 128 +/*XXX: I don't think this actually exists.. */ +#define NV50_USER_REF_CNT(i) (0x00c00048+(i*NV50_USER_SIZE)) +#define NV50_USER_REF_CNT__SIZE 128 + #define NV03_FIFO_SIZE 0x8000UL -#define NV_MAX_FIFO_NUMBER 128 -#define NV03_FIFO_REGS_SIZE 0x10000 -#define NV03_FIFO_REGS(i) (0x00800000+i*NV03_FIFO_REGS_SIZE) -# define NV03_FIFO_REGS_DMAPUT(i) (NV03_FIFO_REGS(i)+0x40) -# define NV03_FIFO_REGS_DMAGET(i) (NV03_FIFO_REGS(i)+0x44) -#define NV50_FIFO_REGS_SIZE 0x2000 -#define NV50_FIFO_REGS(i) (0x00c00000+i*NV50_FIFO_REGS_SIZE) -# define NV50_FIFO_REGS_DMAPUT(i) (NV50_FIFO_REGS(i)+0x40) -# define NV50_FIFO_REGS_DMAGET(i) (NV50_FIFO_REGS(i)+0x44) #define NV03_PMC_BOOT_0 0x00000000 #define NV03_PMC_BOOT_1 0x00000004 commit d0904f0f2b87c725d3e67060419c445259bd4a5e Author: Ben Skeggs <sk...@gm...> Date: Wed Nov 14 03:27:37 2007 +1100 nouveau: funcs to determine active channel on PFIFO. diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 8b00726..07bd88e 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -193,9 +193,13 @@ struct nouveau_fb_engine { struct nouveau_fifo_engine { void *priv; + int channels; + int (*init)(struct drm_device *); void (*takedown)(struct drm_device *); + int (*channel_id)(struct drm_device *); + int (*create_context)(struct nouveau_channel *); void (*destroy_context)(struct nouveau_channel *); int (*load_context)(struct nouveau_channel *); @@ -364,7 +368,6 @@ extern int nouveau_ioctl_notifier_free(struct drm_device *, void *data, /* nouveau_fifo.c */ extern int nouveau_fifo_init(struct drm_device *); -extern int nouveau_fifo_number(struct drm_device *); extern int nouveau_fifo_ctx_size(struct drm_device *); extern void nouveau_fifo_cleanup(struct drm_device *, struct drm_file *); extern int nouveau_fifo_owner(struct drm_device *, struct drm_file *, @@ -452,12 +455,14 @@ extern int nv40_fb_init(struct drm_device *); extern void nv40_fb_takedown(struct drm_device *); /* nv04_fifo.c */ +extern int nv04_fifo_channel_id(struct drm_device *); extern int nv04_fifo_create_context(struct nouveau_channel *); extern void nv04_fifo_destroy_context(struct nouveau_channel *); extern int nv04_fifo_load_context(struct nouveau_channel *); extern int nv04_fifo_save_context(struct nouveau_channel *); /* nv10_fifo.c */ +extern int nv10_fifo_channel_id(struct drm_device *); extern int nv10_fifo_create_context(struct nouveau_channel *); extern void nv10_fifo_destroy_context(struct nouveau_channel *); extern int nv10_fifo_load_context(struct nouveau_channel *); @@ -473,6 +478,7 @@ extern int nv40_fifo_save_context(struct nouveau_channel *); /* nv50_fifo.c */ extern int nv50_fifo_init(struct drm_device *); extern void nv50_fifo_takedown(struct drm_device *); +extern int nv50_fifo_channel_id(struct drm_device *); extern int nv50_fifo_create_context(struct nouveau_channel *); extern void nv50_fifo_destroy_context(struct nouveau_channel *); extern int nv50_fifo_load_context(struct nouveau_channel *); diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index e2cb209..7c24ed2 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -28,22 +28,6 @@ #include "nouveau_drm.h" -/* returns the number of hw fifos */ -int nouveau_fifo_number(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv=dev->dev_private; - switch(dev_priv->card_type) - { - case NV_04: - case NV_05: - return 16; - case NV_50: - return 128; - default: - return 32; - } -} - /* returns the size of fifo context */ int nouveau_fifo_ctx_size(struct drm_device *dev) { @@ -288,12 +272,13 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, * (woo, full userspace command submission !) * When there are no more contexts, you lost */ - for(channel=0; channel<nouveau_fifo_number(dev); channel++) { + for (channel = 0; channel < engine->fifo.channels; channel++) { if (dev_priv->fifos[channel] == NULL) break; } + /* no more fifos. you lost. */ - if (channel==nouveau_fifo_number(dev)) + if (channel == engine->fifo.channels) return -EINVAL; dev_priv->fifos[channel] = drm_calloc(1, sizeof(struct nouveau_channel), @@ -451,10 +436,11 @@ void nouveau_fifo_free(struct nouveau_channel *chan) void nouveau_fifo_cleanup(struct drm_device *dev, struct drm_file *file_priv) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; int i; DRM_DEBUG("clearing FIFO enables from file_priv\n"); - for(i = 0; i < nouveau_fifo_number(dev); i++) { + for(i = 0; i < engine->fifo.channels; i++) { struct nouveau_channel *chan = dev_priv->fifos[i]; if (chan && chan->file_priv == file_priv) @@ -467,8 +453,9 @@ nouveau_fifo_owner(struct drm_device *dev, struct drm_file *file_priv, int channel) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; - if (channel >= nouveau_fifo_number(dev)) + if (channel >= engine->fifo.channels) return 0; if (dev_priv->fifos[channel] == NULL) return 0; diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c index 43f37ca..500fda2 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -68,6 +68,7 @@ static void nouveau_fifo_irq_handler(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; uint32_t status; while ((status = NV_READ(NV03_PFIFO_INTR_0))) { @@ -75,8 +76,7 @@ nouveau_fifo_irq_handler(struct drm_device *dev) NV_WRITE(NV03_PFIFO_CACHES, 0); - chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1) & - (nouveau_fifo_number(dev) - 1); + chid = engine->fifo.channel_id(dev); get = NV_READ(NV03_PFIFO_CACHE1_GET); if (status & NV_PFIFO_INTR_CACHE_ERROR) { @@ -190,6 +190,7 @@ static int nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; int channel; if (dev_priv->card_type < NV_10) { @@ -234,8 +235,7 @@ nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret) } } - if (channel > nouveau_fifo_number(dev) || - dev_priv->fifos[channel] == NULL) { + if (channel > engine->fifo.channels || !dev_priv->fifos[channel]) { DRM_ERROR("AIII, invalid/inactive channel id %d\n", channel); return -EINVAL; } @@ -365,9 +365,10 @@ static inline void nouveau_pgraph_intr_context_switch(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; uint32_t chid; - chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1) & (nouveau_fifo_number(dev)-1); + chid = engine->fifo.channel_id(dev); DRM_DEBUG("PGRAPH context switch interrupt channel %x\n", chid); switch(dev_priv->card_type) { diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index 43573f2..e097e01 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -406,6 +406,11 @@ #define NV04_PFIFO_CACHE0_PULL1 0x00003054 #define NV03_PFIFO_CACHE1_PUSH0 0x00003200 #define NV03_PFIFO_CACHE1_PUSH1 0x00003204 +#define NV03_PFIFO_CACHE1_PUSH1_DMA (1<<8) +#define NV40_PFIFO_CACHE1_PUSH1_DMA (1<<16) +#define NV03_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000000f +#define NV10_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000001f +#define NV50_PFIFO_CACHE1_PUSH1_CHID_MASK 0x0000007f #define NV04_PFIFO_CACHE1_DMA_PUSH 0x00003220 #define NV04_PFIFO_CACHE1_DMA_FETCH 0x00003224 # define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_8_BYTES 0x00000000 diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 610d24e..35042cd 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -116,8 +116,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->graph.destroy_context = nv04_graph_destroy_context; engine->graph.load_context = nv04_graph_load_context; engine->graph.save_context = nv04_graph_save_context; + engine->fifo.channels = 16; engine->fifo.init = nouveau_fifo_init; engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.channel_id = nv04_fifo_channel_id; engine->fifo.create_context = nv04_fifo_create_context; engine->fifo.destroy_context = nv04_fifo_destroy_context; engine->fifo.load_context = nv04_fifo_load_context; @@ -143,8 +145,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->graph.destroy_context = nv10_graph_destroy_context; engine->graph.load_context = nv10_graph_load_context; engine->graph.save_context = nv10_graph_save_context; + engine->fifo.channels = 32; engine->fifo.init = nouveau_fifo_init; engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv10_fifo_create_context; engine->fifo.destroy_context = nv10_fifo_destroy_context; engine->fifo.load_context = nv10_fifo_load_context; @@ -170,8 +174,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->graph.destroy_context = nv20_graph_destroy_context; engine->graph.load_context = nv20_graph_load_context; engine->graph.save_context = nv20_graph_save_context; + engine->fifo.channels = 32; engine->fifo.init = nouveau_fifo_init; engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv10_fifo_create_context; engine->fifo.destroy_context = nv10_fifo_destroy_context; engine->fifo.load_context = nv10_fifo_load_context; @@ -197,8 +203,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->graph.destroy_context = nv20_graph_destroy_context; engine->graph.load_context = nv20_graph_load_context; engine->graph.save_context = nv20_graph_save_context; + engine->fifo.channels = 32; engine->fifo.init = nouveau_fifo_init; engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv10_fifo_create_context; engine->fifo.destroy_context = nv10_fifo_destroy_context; engine->fifo.load_context = nv10_fifo_load_context; @@ -224,8 +232,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->graph.destroy_context = nv40_graph_destroy_context; engine->graph.load_context = nv40_graph_load_context; engine->graph.save_context = nv40_graph_save_context; + engine->fifo.channels = 32; engine->fifo.init = nv40_fifo_init; engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv40_fifo_create_context; engine->fifo.destroy_context = nv40_fifo_destroy_context; engine->fifo.load_context = nv40_fifo_load_context; @@ -252,8 +262,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->graph.destroy_context = nv50_graph_destroy_context; engine->graph.load_context = nv50_graph_load_context; engine->graph.save_context = nv50_graph_save_context; + engine->fifo.channels = 128; engine->fifo.init = nv50_fifo_init; engine->fifo.takedown = nv50_fifo_takedown; + engine->fifo.channel_id = nv50_fifo_channel_id; engine->fifo.create_context = nv50_fifo_create_context; engine->fifo.destroy_context = nv50_fifo_destroy_context; engine->fifo.load_context = nv50_fifo_load_context; diff --git a/shared-core/nv04_fifo.c b/shared-core/nv04_fifo.c index d172302..230c8e7 100644 --- a/shared-core/nv04_fifo.c +++ b/shared-core/nv04_fifo.c @@ -36,6 +36,15 @@ #define NV04_RAMFC__SIZE 32 int +nv04_fifo_channel_id(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + return (NV_READ(NV03_PFIFO_CACHE1_PUSH1) & + NV03_PFIFO_CACHE1_PUSH1_CHID_MASK); +} + +int nv04_fifo_create_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; @@ -84,7 +93,8 @@ nv04_fifo_load_context(struct nouveau_channel *chan) struct drm_nouveau_private *dev_priv = dev->dev_private; uint32_t tmp; - NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, (1<<8) | chan->id); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, + NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id); NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, RAMFC_RD(DMA_GET)); NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT, RAMFC_RD(DMA_PUT)); diff --git a/shared-core/nv04_graph.c b/shared-core/nv04_graph.c index 04dbf0e..81a6d5c 100644 --- a/shared-core/nv04_graph.c +++ b/shared-core/nv04_graph.c @@ -353,6 +353,7 @@ struct graph_state { void nouveau_nv04_context_switch(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; struct nouveau_channel *next, *last; int chid; @@ -370,7 +371,7 @@ void nouveau_nv04_context_switch(struct drm_device *dev) return; } - chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); + chid = engine->fifo.channel_id(dev); next = dev_priv->fifos[chid]; if (!next) { @@ -378,7 +379,7 @@ void nouveau_nv04_context_switch(struct drm_device *dev) return; } - chid = (NV_READ(NV04_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + chid = (NV_READ(NV04_PGRAPH_CTX_USER) >> 24) & (engine->fifo.channels - 1); last = dev_priv->fifos[chid]; if (!last) { diff --git a/shared-core/nv04_instmem.c b/shared-core/nv04_instmem.c index 5696818..804f9a7 100644 --- a/shared-core/nv04_instmem.c +++ b/shared-core/nv04_instmem.c @@ -33,6 +33,7 @@ static void nv04_instmem_configure_fixed_tables(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; /* FIFO hash table (RAMHT) * use 4k hash table at RAMIN+0x10000 @@ -61,8 +62,8 @@ nv04_instmem_configure_fixed_tables(struct drm_device *dev) case NV_40: case NV_44: dev_priv->ramfc_offset = 0x20000; - dev_priv->ramfc_size = nouveau_fifo_number(dev) * - nouveau_fifo_ctx_size(dev); + dev_priv->ramfc_size = engine->fifo.channels * + nouveau_fifo_ctx_size(dev); break; case NV_30: case NV_20: @@ -72,8 +73,8 @@ nv04_instmem_configure_fixed_tables(struct drm_device *dev) case NV_04: default: dev_priv->ramfc_offset = 0x11400; - dev_priv->ramfc_size = nouveau_fifo_number(dev) * - nouveau_fifo_ctx_size(dev); + dev_priv->ramfc_size = engine->fifo.channels * + nouveau_fifo_ctx_size(dev); break; } DRM_DEBUG("RAMFC offset=0x%x, size=%d\n", dev_priv->ramfc_offset, diff --git a/shared-core/nv10_fifo.c b/shared-core/nv10_fifo.c index 45d2603..6d50b6c 100644 --- a/shared-core/nv10_fifo.c +++ b/shared-core/nv10_fifo.c @@ -37,6 +37,15 @@ #define NV10_RAMFC__SIZE ((dev_priv->chipset) >= 0x17 ? 64 : 32) int +nv10_fifo_channel_id(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + return (NV_READ(NV03_PFIFO_CACHE1_PUSH1) & + NV10_PFIFO_CACHE1_PUSH1_CHID_MASK); +} + +int nv10_fifo_create_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; @@ -87,7 +96,8 @@ nv10_fifo_load_context(struct nouveau_channel *chan) struct drm_nouveau_private *dev_priv = dev->dev_private; uint32_t tmp; - NV_WRITE(NV03_PFIFO_CACHE1_PUSH1 , 0x00000100 | chan->id); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, + NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id); NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET , RAMFC_RD(DMA_GET)); NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT , RAMFC_RD(DMA_PUT)); diff --git a/shared-core/nv10_graph.c b/shared-core/nv10_graph.c index 606fb43..d0c2285 100644 --- a/shared-core/nv10_graph.c +++ b/shared-core/nv10_graph.c @@ -692,6 +692,7 @@ int nv10_graph_save_context(struct nouveau_channel *chan) void nouveau_nv10_context_switch(struct drm_device *dev) { struct drm_nouveau_private *dev_priv; + struct nouveau_engine *engine; struct nouveau_channel *next, *last; int chid; @@ -708,8 +709,10 @@ void nouveau_nv10_context_switch(struct drm_device *dev) DRM_DEBUG("Invalid drm_nouveau_private->fifos\n"); return; } + engine = &dev_priv->Engine; - chid = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 20)&(nouveau_fifo_number(dev)-1); + chid = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 20) & + (engine->fifo.channels - 1); next = dev_priv->fifos[chid]; if (!next) { @@ -717,7 +720,8 @@ void nouveau_nv10_context_switch(struct drm_device *dev) return; } - chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & + (engine->fifo.channels - 1); last = dev_priv->fifos[chid]; if (!last) { @@ -827,13 +831,14 @@ void nv10_graph_destroy_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; struct graph_state* pgraph_ctx = chan->pgraph_ctx; int chid; drm_free(pgraph_ctx, sizeof(*pgraph_ctx), DRM_MEM_DRIVER); chan->pgraph_ctx = NULL; - chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (engine->fifo.channels - 1); /* This code seems to corrupt the 3D pipe, but blob seems to do similar things ???? */ diff --git a/shared-core/nv40_fifo.c b/shared-core/nv40_fifo.c index 5b3eda0..7f9d5e3 100644 --- a/shared-core/nv40_fifo.c +++ b/shared-core/nv40_fifo.c @@ -135,7 +135,9 @@ nv40_fifo_load_context(struct nouveau_channel *chan) NV_WRITE(NV04_PFIFO_DMA_TIMESLICE, tmp); /* Set channel active, and in DMA mode */ - NV_WRITE(NV03_PFIFO_CACHE1_PUSH1 , 0x00010000 | chan->id); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, + NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id); + /* Reset DMA_CTL_AT_INFO to INVALID */ tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_CTL) & ~(1<<31); NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, tmp); diff --git a/shared-core/nv50_fifo.c b/shared-core/nv50_fifo.c index f77de6e..c5cde91 100644 --- a/shared-core/nv50_fifo.c +++ b/shared-core/nv50_fifo.c @@ -213,6 +213,15 @@ nv50_fifo_takedown(struct drm_device *dev) } int +nv50_fifo_channel_id(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + return (NV_READ(NV03_PFIFO_CACHE1_PUSH1) & + NV50_PFIFO_CACHE1_PUSH1_CHID_MASK); +} + +int nv50_fifo_create_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; commit 2370ded79b4176d76cda1ec5f495fd33c2d566ed Author: Ben Skeggs <sk...@gm...> Date: Fri Nov 9 04:27:23 2007 +1100 nouveau: stub superioctl diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index e7c280d..92e1eb7 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -23,7 +23,7 @@ i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \ i915_buffer.o i915_compat.o nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ nouveau_object.o nouveau_irq.o nouveau_notifier.o nouveau_swmthd.o \ - nouveau_sgdma.o nouveau_dma.o nouveau_buffer.o nouveau_fence.o \ + nouveau_sgdma.o nouveau_dma.o nouveau_bo.o nouveau_fence.o \ nv04_timer.o \ nv04_mc.o nv40_mc.o nv50_mc.o \ nv04_fb.o nv10_fb.o nv40_fb.o \ diff --git a/linux-core/nouveau_bo.c b/linux-core/nouveau_bo.c new file mode 100644 index 0000000..f0b0576 --- /dev/null +++ b/linux-core/nouveau_bo.c @@ -0,0 +1,265 @@ +/* + * Copyright 2007 Dave Airlied + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +/* + * Authors: Dave Airlied <ai...@li...> + * Ben Skeggs <dar...@ii...> + * Jeremy Kolb <jk...@br...> + */ + +#include "drmP.h" +#include "nouveau_drm.h" +#include "nouveau_drv.h" +#include "nouveau_dma.h" + +static struct drm_ttm_backend * +nouveau_bo_create_ttm_backend_entry(struct drm_device * dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + switch (dev_priv->gart_info.type) { + case NOUVEAU_GART_AGP: + return drm_agp_init_ttm(dev); + case NOUVEAU_GART_SGDMA: + return nouveau_sgdma_init_ttm(dev); + default: + DRM_ERROR("Unknown GART type %d\n", dev_priv->gart_info.type); + break; + } + + return NULL; +} + +static int +nouveau_bo_fence_type(struct drm_buffer_object *bo, + uint32_t *fclass, uint32_t *type) +{ + /* When we get called, *fclass is set to the requested fence class */ + + if (bo->mem.mask & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) + *type = 3; + else + *type = 1; + return 0; + +} + +static int +nouveau_bo_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags) +{ + /* We'll do this from user space. */ + return 0; +} + +static int +nouveau_bo_init_mem_type(struct drm_device *dev, uint32_t type, + struct drm_mem_type_manager *man) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + switch (type) { + case DRM_BO_MEM_LOCAL: + man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | + _DRM_FLAG_MEMTYPE_CACHED; + man->drm_bus_maptype = 0; + break; + case DRM_BO_MEM_VRAM: + man->flags = _DRM_FLAG_MEMTYPE_FIXED | + _DRM_FLAG_MEMTYPE_MAPPABLE | + _DRM_FLAG_NEEDS_IOREMAP; + man->io_addr = NULL; + man->drm_bus_maptype = _DRM_FRAME_BUFFER; + man->io_offset = drm_get_resource_start(dev, 1); + man->io_size = drm_get_resource_len(dev, 1); + if (man->io_size > nouveau_mem_fb_amount(dev)) + man->io_size = nouveau_mem_fb_amount(dev); + break; + case DRM_BO_MEM_PRIV0: + /* Unmappable VRAM */ + man->flags = _DRM_FLAG_MEMTYPE_CMA; + man->drm_bus_maptype = 0; + break; + case DRM_BO_MEM_TT: + switch (dev_priv->gart_info.type) { + case NOUVEAU_GART_AGP: + man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | + _DRM_FLAG_MEMTYPE_CSELECT | + _DRM_FLAG_NEEDS_IOREMAP; + man->drm_bus_maptype = _DRM_AGP; + break; + case NOUVEAU_GART_SGDMA: + man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | + _DRM_FLAG_MEMTYPE_CSELECT | + _DRM_FLAG_MEMTYPE_CMA; + man->drm_bus_maptype = _DRM_SCATTER_GATHER; + break; + default: + DRM_ERROR("Unknown GART type: %d\n", + dev_priv->gart_info.type); + return -EINVAL; + } + + man->io_offset = dev_priv->gart_info.aper_base; + man->io_size = dev_priv->gart_info.aper_size; + man->io_addr = NULL; + break; + default: + DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); + return -EINVAL; + } + return 0; +} + +static uint32_t +nouveau_bo_evict_mask(struct drm_buffer_object *bo) +{ + switch (bo->mem.mem_type) { + case DRM_BO_MEM_LOCAL: + case DRM_BO_MEM_TT: + return DRM_BO_FLAG_MEM_LOCAL; + default: + return DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED; + } + return 0; +} + +/* GPU-assisted copy using NV_MEMORY_TO_MEMORY_FORMAT, can access + * DRM_BO_MEM_{VRAM,PRIV0,TT} directly. + */ +static int +nouveau_bo_move_m2mf(struct drm_buffer_object *bo, int evict, int no_wait, + struct drm_bo_mem_reg *new_mem) +{ + struct drm_device *dev = bo->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm_channel *dchan = &dev_priv->channel; + struct drm_bo_mem_reg *old_mem = &bo->mem; + uint32_t srch, dsth, page_count; + + /* Can happen during init/takedown */ + if (!dchan->chan) + return -EINVAL; + + srch = old_mem->mem_type == DRM_BO_MEM_TT ? NvDmaTT : NvDmaFB; + dsth = new_mem->mem_type == DRM_BO_MEM_TT ? NvDmaTT : NvDmaFB; + if (srch != dchan->m2mf_dma_source || dsth != dchan->m2mf_dma_destin) { + dchan->m2mf_dma_source = srch; + dchan->m2mf_dma_destin = dsth; + + BEGIN_RING(NvSubM2MF, + NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_SOURCE, 2); + OUT_RING (dchan->m2mf_dma_source); + OUT_RING (dchan->m2mf_dma_destin); + } + + page_count = new_mem->num_pages; + while (page_count) { + int line_count = (page_count > 2047) ? 2047 : page_count; + + BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + OUT_RING (old_mem->mm_node->start << PAGE_SHIFT); + OUT_RING (new_mem->mm_node->start << PAGE_SHIFT); + OUT_RING (PAGE_SIZE); /* src_pitch */ + OUT_RING (PAGE_SIZE); /* dst_pitch */ + OUT_RING (PAGE_SIZE); /* line_length */ + OUT_RING (line_count); + OUT_RING ((1<<8)|(1<<0)); + OUT_RING (0); + BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1); + OUT_RING (0); + + page_count -= line_count; + } + + return drm_bo_move_accel_cleanup(bo, evict, no_wait, dchan->chan->id, + DRM_FENCE_TYPE_EXE, 0, new_mem); +} + +static int +nouveau_bo_move(struct drm_buffer_object *bo, int evict, int no_wait, + struct drm_bo_mem_reg *new_mem) +{ + struct drm_bo_mem_reg *old_mem = &bo->mem; + + if (new_mem->mem_type == DRM_BO_MEM_LOCAL) { + if (old_mem->mem_type == DRM_BO_MEM_LOCAL) + return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); +#if 0 + if (!nouveau_bo_move_flipd(bo, evict, no_wait, new_mem)) +#endif + return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); + } + else + if (old_mem->mem_type == DRM_BO_MEM_LOCAL) { +#if 0 + if (nouveau_bo_move_flips(bo, evict, no_wait, new_mem)) +#endif + return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); + } + else { +// if (nouveau_bo_move_m2mf(bo, evict, no_wait, new_mem)) + return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); + } + return 0; +} + +static void +nouveau_bo_flush_ttm(struct drm_ttm *ttm) +{ +} + +static uint32_t nouveau_mem_prios[] = { + DRM_BO_MEM_PRIV0, + DRM_BO_MEM_VRAM, + DRM_BO_MEM_TT, + DRM_BO_MEM_LOCAL +}; +static uint32_t nouveau_busy_prios[] = { + DRM_BO_MEM_TT, + DRM_BO_MEM_PRIV0, + DRM_BO_MEM_VRAM, + DRM_BO_MEM_LOCAL +}; + +struct drm_bo_driver nouveau_bo_driver = { + .mem_type_prio = nouveau_mem_prios, + .mem_busy_prio = nouveau_busy_prios, + .num_mem_type_prio = sizeof(nouveau_mem_prios)/sizeof(uint32_t), + .num_mem_busy_prio = sizeof(nouveau_busy_prios)/sizeof(uint32_t), + .create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry, + .fence_type = nouveau_bo_fence_type, + .invalidate_caches = nouveau_bo_invalidate_caches, + .init_mem_type = nouveau_bo_init_mem_type, + .evict_mask = nouveau_bo_evict_mask, + .move = nouveau_bo_move, + .ttm_cache_flush= nouveau_bo_flush_ttm +}; + +int +nouveau_bo_validate(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + DRM_ERROR("unimplemented\n"); + return -EINVAL; +} + diff --git a/linux-core/nouveau_buffer.c b/linux-core/nouveau_buffer.c deleted file mode 100644 index c40dff6..0000000 --- a/linux-core/nouveau_buffer.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright 2007 Dave Airlied - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -/* - * Authors: Dave Airlied <ai...@li...> - * Ben Skeggs <dar...@ii...> - * Jeremy Kolb <jk...@br...> - */ - -#include "drmP.h" -#include "nouveau_drm.h" -#include "nouveau_drv.h" -#include "nouveau_dma.h" - -static struct drm_ttm_backend * -nouveau_bo_create_ttm_backend_entry(struct drm_device * dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - switch (dev_priv->gart_info.type) { - case NOUVEAU_GART_AGP: - return drm_agp_init_ttm(dev); - case NOUVEAU_GART_SGDMA: - return nouveau_sgdma_init_ttm(dev); - default: - DRM_ERROR("Unknown GART type %d\n", dev_priv->gart_info.type); - break; - } - - return NULL; -} - -static int -nouveau_bo_fence_type(struct drm_buffer_object *bo, - uint32_t *fclass, uint32_t *type) -{ - /* When we get called, *fclass is set to the requested fence class */ - - if (bo->mem.mask & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) - *type = 3; - else - *type = 1; - return 0; - -} - -static int -nouveau_bo_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags) -{ - /* We'll do this from user space. */ - return 0; -} - -static int -nouveau_bo_init_mem_type(struct drm_device *dev, uint32_t type, - struct drm_mem_type_manager *man) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - switch (type) { - case DRM_BO_MEM_LOCAL: - man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | - _DRM_FLAG_MEMTYPE_CACHED; - man->drm_bus_maptype = 0; - break; - case DRM_BO_MEM_VRAM: - man->flags = _DRM_FLAG_MEMTYPE_FIXED | - _DRM_FLAG_MEMTYPE_MAPPABLE | - _DRM_FLAG_NEEDS_IOREMAP; - man->io_addr = NULL; - man->drm_bus_maptype = _DRM_FRAME_BUFFER; - man->io_offset = drm_get_resource_start(dev, 1); - man->io_size = drm_get_resource_len(dev, 1); - if (man->io_size > nouveau_mem_fb_amount(dev)) - man->io_size = nouveau_mem_fb_amount(dev); - break; - case DRM_BO_MEM_PRIV0: - /* Unmappable VRAM */ - man->flags = _DRM_FLAG_MEMTYPE_CMA; - man->drm_bus_maptype = 0; - break; - case DRM_BO_MEM_TT: - switch (dev_priv->gart_info.type) { - case NOUVEAU_GART_AGP: - man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | - _DRM_FLAG_MEMTYPE_CSELECT | - _DRM_FLAG_NEEDS_IOREMAP; - man->drm_bus_maptype = _DRM_AGP; - break; - case NOUVEAU_GART_SGDMA: - man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | - _DRM_FLAG_MEMTYPE_CSELECT | - _DRM_FLAG_MEMTYPE_CMA; - man->drm_bus_maptype = _DRM_SCATTER_GATHER; - break; - default: - DRM_ERROR("Unknown GART type: %d\n", - dev_priv->gart_info.type); - return -EINVAL; - } - - man->io_offset = dev_priv->gart_info.aper_base; - man->io_size = dev_priv->gart_info.aper_size; - man->io_addr = NULL; - break; - default: - DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); - return -EINVAL; - } - return 0; -} - -static uint32_t -nouveau_bo_evict_mask(struct drm_buffer_object *bo) -{ - switch (bo->mem.mem_type) { - case DRM_BO_MEM_LOCAL: - case DRM_BO_MEM_TT: - return DRM_BO_FLAG_MEM_LOCAL; - default: - return DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED; - } - return 0; -} - -/* GPU-assisted copy using NV_MEMORY_TO_MEMORY_FORMAT, can access - * DRM_BO_MEM_{VRAM,PRIV0,TT} directly. - */ -static int -nouveau_bo_move_m2mf(struct drm_buffer_object *bo, int evict, int no_wait, - struct drm_bo_mem_reg *new_mem) -{ - struct drm_device *dev = bo->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_drm_channel *dchan = &dev_priv->channel; - struct drm_bo_mem_reg *old_mem = &bo->mem; - uint32_t srch, dsth, page_count; - - /* Can happen during init/takedown */ - if (!dchan->chan) - return -EINVAL; - - srch = old_mem->mem_type == DRM_BO_MEM_TT ? NvDmaTT : NvDmaFB; - dsth = new_mem->mem_type == DRM_BO_MEM_TT ? NvDmaTT : NvDmaFB; - if (srch != dchan->m2mf_dma_source || dsth != dchan->m2mf_dma_destin) { - dchan->m2mf_dma_source = srch; - dchan->m2mf_dma_destin = dsth; - - BEGIN_RING(NvSubM2MF, - NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_SOURCE, 2); - OUT_RING (dchan->m2mf_dma_source); - OUT_RING (dchan->m2mf_dma_destin); - } - - page_count = new_mem->num_pages; - while (page_count) { - int line_count = (page_count > 2047) ? 2047 : page_count; - - BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); - OUT_RING (old_mem->mm_node->start << PAGE_SHIFT); - OUT_RING (new_mem->mm_node->start << PAGE_SHIFT); - OUT_RING (PAGE_SIZE); /* src_pitch */ - OUT_RING (PAGE_SIZE); /* dst_pitch */ - OUT_RING (PAGE_SIZE); /* line_length */ - OUT_RING (line_count); - OUT_RING ((1<<8)|(1<<0)); - OUT_RING (0); - BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1); - OUT_RING (0); - - page_count -= line_count; - } - - return drm_bo_move_accel_cleanup(bo, evict, no_wait, dchan->chan->id, - DRM_FENCE_TYPE_EXE, 0, new_mem); -} - -static int -nouveau_bo_move(struct drm_buffer_object *bo, int evict, int no_wait, - struct drm_bo_mem_reg *new_mem) -{ - struct drm_bo_mem_reg *old_mem = &bo->mem; - - if (new_mem->mem_type == DRM_BO_MEM_LOCAL) { - if (old_mem->mem_type == DRM_BO_MEM_LOCAL) - return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); -#if 0 - if (!nouveau_bo_move_flipd(bo, evict, no_wait, new_mem)) -#endif - return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); - } - else - if (old_mem->mem_type == DRM_BO_MEM_LOCAL) { -#if 0 - if (nouveau_bo_move_flips(bo, evict, no_wait, new_mem)) -#endif - return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); - } - else { -// if (nouveau_bo_move_m2mf(bo, evict, no_wait, new_mem)) - return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); - } - return 0; -} - -static void -nouveau_bo_flush_ttm(struct drm_ttm *ttm) -{ -} - -static uint32_t nouveau_mem_prios[] = { - DRM_BO_MEM_PRIV0, - DRM_BO_MEM_VRAM, - DRM_BO_MEM_TT, - DRM_BO_MEM_LOCAL -}; -static uint32_t nouveau_busy_prios[] = { - DRM_BO_MEM_TT, - DRM_BO_MEM_PRIV0, - DRM_BO_MEM_VRAM, - DRM_BO_MEM_LOCAL -}; - -struct drm_bo_driver nouveau_bo_driver = { - .mem_type_prio = nouveau_mem_prios, - .mem_busy_prio = nouveau_busy_prios, - .num_mem_type_prio = sizeof(nouveau_mem_prios)/sizeof(uint32_t), - .num_mem_busy_prio = sizeof(nouveau_busy_prios)/sizeof(uint32_t), - .create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry, - .fence_type = nouveau_bo_fence_type, - .invalidate_caches = nouveau_bo_invalidate_caches, - .init_mem_type = nouveau_bo_init_mem_type, - .evict_mask = nouveau_bo_evict_mask, - .move = nouveau_bo_move, - .ttm_cache_flush= nouveau_bo_flush_ttm -}; diff --git a/shared-core/nouveau_drm.h b/shared-core/nouveau_drm.h index 3bf4008..3a9a529 100644 --- a/shared-core/nouveau_drm.h +++ b/shared-core/nouveau_drm.h @@ -25,7 +25,7 @@ #ifndef __NOUVEAU_DRM_H__ #define __NOUVEAU_DRM_H__ -#define NOUVEAU_DRM_HEADER_PATCHLEVEL 10 +#define NOUVEAU_DRM_HEADER_PATCHLEVEL 11 struct drm_nouveau_channel_alloc { uint32_t fb_ctxdma_handle; @@ -117,6 +117,9 @@ struct drm_nouveau_setparam { uint64_t value; }; +struct drm_nouveau_bo_validate { +}; + enum nouveau_card_type { NV_UNKNOWN =0, NV_04 =4, @@ -156,5 +159,6 @@ struct drm_nouveau_sarea { #define DRM_NOUVEAU_GPUOBJ_FREE 0x07 #define DRM_NOUVEAU_MEM_ALLOC 0x08 #define DRM_NOUVEAU_MEM_FREE 0x09 +#define DRM_NOUVEAU_BO_VALIDATE 0x0a #endif /* __NOUVEAU_DRM_H__ */ diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 8b00726..c276b69 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -34,7 +34,7 @@ #define DRIVER_MAJOR 0 #define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 10 +#define DRIVER_PATCHLEVEL 11 #define NOUVEAU_FAMILY 0x0000FFFF #define NOUVEAU_FLAGS 0xFFFF0000 @@ -559,8 +559,10 @@ extern void nv04_timer_takedown(struct drm_device *); extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -/* nouveau_buffer.c */ +/* nouveau_bo.c */ extern struct drm_bo_driver nouveau_bo_driver; +extern int nouveau_bo_validate(struct drm_device *, void *data, + struct drm_file *); /* nouveau_fence.c */ extern struct drm_fence_driver nouveau_fence_driver; diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index e2cb209..4b84f9c 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -565,6 +565,7 @@ struct drm_ioctl_desc nouveau_ioctls[] = { DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH), DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_ALLOC, nouveau_ioctl_mem_alloc, DRM_AUTH), DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_FREE, nouveau_ioctl_mem_free, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_BO_VALIDATE, nouveau_bo_validate, DRM_AUTH), }; int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls); diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 610d24e..c19d7bf 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -278,7 +278,7 @@ nouveau_card_init(struct drm_device *dev) if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE) return 0; - dev_priv->ttm = 0; + dev_priv->ttm = 1; /* Map any PCI resources we need on the card */ ret = nouveau_init_card_mappings(dev); |
From: <ke...@ke...> - 2007-12-15 20:11:01
|
linux-core/drm_bo.c | 103 +++++++++++++++++++++++++++++++++++++++++------ linux-core/drm_bo_move.c | 4 - linux-core/drm_objects.h | 10 +--- linux-core/drm_ttm.c | 32 ++++++++++---- shared-core/drm.h | 24 ++++++++++ shared-core/i915_dma.c | 6 -- 6 files changed, 144 insertions(+), 35 deletions(-) New commits: commit 0b031dbd63bbb3e0ba6d39e1e5c4eb4e87985158 Author: Keith Packard <ke...@ke...> Date: Fri Dec 14 13:19:35 2007 -0800 Document drm_ttm_set_user. Add a comment explaining the parameters for this function diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index 4200bc1..4c1b327 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -239,6 +239,22 @@ struct page *drm_ttm_get_page(struct drm_ttm *ttm, int index) } EXPORT_SYMBOL(drm_ttm_get_page); +/** + * drm_ttm_set_user: + * + * @ttm: the ttm to map pages to. This must always be + * a freshly created ttm. + * + * @tsk: a pointer to the address space from which to map + * pages. + * + * @write: a boolean indicating that write access is desired + * + * start: the starting address + * + * Map a range of user addresses to a new ttm object. This + * provides access to user memory from the graphics device. + */ int drm_ttm_set_user(struct drm_ttm *ttm, struct task_struct *tsk, int write, commit 9d17373ffbba3cc4ee5f63ff02ff24d48ab99fe0 Author: Keith Packard <ke...@ke...> Date: Fri Dec 14 13:19:09 2007 -0800 Document drm_buffer_object_validate function. Just add documentation for this function, no code changes. diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 1ce8697..7033a8b 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1372,8 +1372,25 @@ static int drm_bo_mem_compat(struct drm_bo_mem_reg *mem) return 1; } -/* - * bo locked. +/** + * drm_buffer_object_validate: + * + * @bo: the buffer object to modify + * + * @fence_class: the new fence class covering this buffer + * + * @move_unfenced: a boolean indicating whether switching the + * memory space of this buffer should cause the buffer to + * be placed on the unfenced list. + * + * @no_wait: whether this function should return -EBUSY instead + * of waiting. + * + * Change buffer access parameters. This can involve moving + * the buffer to the correct memory type, pinning the buffer + * or changing the class/type of fence covering this buffer + * + * Must be called with bo locked. */ static int drm_buffer_object_validate(struct drm_buffer_object *bo, @@ -1503,7 +1520,7 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo, } /** - * drm_bo_do_validate + * drm_bo_do_validate: * * @bo: the buffer object * commit 7461519fed25f6d63415a9dd4b915c6cc668a69c Author: Keith Packard <ke...@ke...> Date: Fri Dec 14 12:49:22 2007 -0800 Document fence_class mess in drm_bo_setstatus_ioctl drmBOSetStatus does not bother to set the fence_class parameter. Fortunately, drm_bo_setstatus_ioctl doesn't end up using it as it calls drm_bo_handle_validate with use_old_fence_class = 1. diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index aa613d7..1ce8697 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1851,6 +1851,12 @@ int drm_bo_setstatus_ioctl(struct drm_device *dev, if (ret) return ret; + /* + * validate the buffer. note that 'fence_class' will be unused + * as we pass use_old_fence_class=1 here. Note also that + * the libdrm API doesn't pass fence_class to the kernel, + * so it's a good thing it isn't used here. + */ ret = drm_bo_handle_validate(file_priv, req->handle, req->flags, req->mask, commit 5f23519b14e54823c94f5db5ad81e6bd5ffd3877 Author: Keith Packard <ke...@ke...> Date: Fri Dec 14 12:45:55 2007 -0800 Document drm_bo_handle_validate. Match drm_bo_do_validate parameter order. Document parameters and usage for drm_bo_handle_validate. Change parameter order to match drm_bo_do_validate (fence_class has been moved to after flags, hint and mask values). Existing users of this function have been changed, but out-of-tree users must be modified separately. diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index d7a507a..aa613d7 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1502,27 +1502,29 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo, return 0; } -/* +/** * drm_bo_do_validate * - * 'validate' a buffer object. This changes where the buffer is - * located, along with changing access modes. + * @bo: the buffer object * - * flags access rights, mapping parameters and cacheability. See - * the DRM_BO_FLAG_* values in drm.h + * @flags: access rights, mapping parameters and cacheability. See + * the DRM_BO_FLAG_* values in drm.h * - * mask which flag values to change; this allows callers to modify - * things without knowing the current state of other flags. + * @mask: Which flag values to change; this allows callers to modify + * things without knowing the current state of other flags. * - * hint changes the proceedure for this operation, see the DRM_BO_HINT_* - * values in drm.h. + * @hint: changes the proceedure for this operation, see the DRM_BO_HINT_* + * values in drm.h. * - * fence_class a driver-specific way of doing fences. Presumably, this - * would be used if the driver had more than one submission and - * fencing mechanism. At this point, there isn't any use of this - * from the user mode code. + * @fence_class: a driver-specific way of doing fences. Presumably, + * this would be used if the driver had more than one submission and + * fencing mechanism. At this point, there isn't any use of this + * from the user mode code. * - * rep will be stuffed with the reply from validation + * @rep: To be stuffed with the reply from validation + * + * 'validate' a buffer object. This changes where the buffer is + * located, along with changing access modes. */ int drm_bo_do_validate(struct drm_buffer_object *bo, @@ -1558,11 +1560,42 @@ out: } EXPORT_SYMBOL(drm_bo_do_validate); +/** + * drm_bo_handle_validate + * + * @file_priv: the drm file private, used to get a handle to the user context + * + * @handle: the buffer object handle + * + * @flags: access rights, mapping parameters and cacheability. See + * the DRM_BO_FLAG_* values in drm.h + * + * @mask: Which flag values to change; this allows callers to modify + * things without knowing the current state of other flags. + * + * @hint: changes the proceedure for this operation, see the DRM_BO_HINT_* + * values in drm.h. + * + * @fence_class: a driver-specific way of doing fences. Presumably, + * this would be used if the driver had more than one submission and + * fencing mechanism. At this point, there isn't any use of this + * from the user mode code. + * + * @use_old_fence_class: don't change fence class, pull it from the buffer object + * + * @rep: To be stuffed with the reply from validation + * + * @bp_rep: To be stuffed with the buffer object pointer + * + * Perform drm_bo_do_validate on a buffer referenced by a user-space handle. + * Some permissions checking is done on the parameters, otherwise this + * is a thin wrapper. + */ int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle, - uint32_t fence_class, uint64_t flags, uint64_t mask, uint32_t hint, + uint32_t fence_class, int use_old_fence_class, struct drm_bo_info_rep *rep, struct drm_buffer_object **bo_rep) @@ -1818,11 +1851,11 @@ int drm_bo_setstatus_ioctl(struct drm_device *dev, if (ret) return ret; - ret = drm_bo_handle_validate(file_priv, req->handle, req->fence_class, + ret = drm_bo_handle_validate(file_priv, req->handle, req->flags, req->mask, req->hint | DRM_BO_HINT_DONT_FENCE, - 1, + req->fence_class, 1, rep, NULL); (void) drm_bo_read_unlock(&dev->bm.bm_lock); diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 1c6ca79..0926b47 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -535,9 +535,8 @@ extern int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type); extern int drm_bo_init_mm(struct drm_device *dev, unsigned type, unsigned long p_offset, unsigned long p_size); extern int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle, - uint32_t fence_class, uint64_t flags, - uint64_t mask, uint32_t hint, - int use_old_fence_class, + uint64_t flags, uint64_t mask, uint32_t hint, + uint32_t fence_class, int use_old_fence_class, struct drm_bo_info_rep *rep, struct drm_buffer_object **bo_rep); extern struct drm_buffer_object *drm_lookup_buffer_object(struct drm_file *file_priv, diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 8041672..df395ba 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -994,11 +994,9 @@ int i915_validate_buffer_list(struct drm_file *file_priv, } rep.ret = drm_bo_handle_validate(file_priv, req->bo_req.handle, - req->bo_req.fence_class, - req->bo_req.flags, - req->bo_req.mask, + req->bo_req.flags, req->bo_req.mask, req->bo_req.hint, - 0, + req->bo_req.fence_class, 0, &rep.bo_info, &buffers[buf_count].buffer); commit b5181d2506be332db8b07c02cdf37c6e25545c4d Author: Keith Packard <ke...@ke...> Date: Fri Dec 14 12:33:35 2007 -0800 Document drm_bo_do_validate. Remove spurious 'do_wait' parameter. Add comments about the parameters to drm_bo_do_validate, along with comments for the DRM_BO_HINT options. Remove the 'do_wait' parameter as it is duplicated by DRM_BO_HINT_DONT_BLOCK. diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 4845f44..d7a507a 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1502,13 +1502,36 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo, return 0; } +/* + * drm_bo_do_validate + * + * 'validate' a buffer object. This changes where the buffer is + * located, along with changing access modes. + * + * flags access rights, mapping parameters and cacheability. See + * the DRM_BO_FLAG_* values in drm.h + * + * mask which flag values to change; this allows callers to modify + * things without knowing the current state of other flags. + * + * hint changes the proceedure for this operation, see the DRM_BO_HINT_* + * values in drm.h. + * + * fence_class a driver-specific way of doing fences. Presumably, this + * would be used if the driver had more than one submission and + * fencing mechanism. At this point, there isn't any use of this + * from the user mode code. + * + * rep will be stuffed with the reply from validation + */ + int drm_bo_do_validate(struct drm_buffer_object *bo, uint64_t flags, uint64_t mask, uint32_t hint, uint32_t fence_class, - int no_wait, struct drm_bo_info_rep *rep) { int ret; + int no_wait = (hint & DRM_BO_HINT_DONT_BLOCK) != 0; mutex_lock(&bo->mutex); ret = drm_bo_wait_unfenced(bo, no_wait, 0); @@ -1547,7 +1570,6 @@ int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle, struct drm_device *dev = file_priv->head->dev; struct drm_buffer_object *bo; int ret; - int no_wait = hint & DRM_BO_HINT_DONT_BLOCK; mutex_lock(&dev->struct_mutex); bo = drm_lookup_buffer_object(file_priv, handle, 1); @@ -1567,8 +1589,7 @@ int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle, mask &= ~(DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE); - ret = drm_bo_do_validate(bo, flags, mask, hint, fence_class, - no_wait, rep); + ret = drm_bo_do_validate(bo, flags, mask, hint, fence_class, rep); if (!ret && bo_rep) *bo_rep = bo; diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 66611f6..1c6ca79 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -546,7 +546,6 @@ extern struct drm_buffer_object *drm_lookup_buffer_object(struct drm_file *file_ extern int drm_bo_do_validate(struct drm_buffer_object *bo, uint64_t flags, uint64_t mask, uint32_t hint, uint32_t fence_class, - int no_wait, struct drm_bo_info_rep *rep); /* diff --git a/shared-core/drm.h b/shared-core/drm.h index 70a25b2..6f6f238 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -748,11 +748,31 @@ struct drm_fence_arg { /* Driver-private flags */ #define DRM_BO_MASK_DRIVER 0xFFFF000000000000ULL -/* Don't block on validate and map */ +/* + * Don't block on validate and map. Instead, return EBUSY. + */ #define DRM_BO_HINT_DONT_BLOCK 0x00000002 -/* Don't place this buffer on the unfenced list.*/ +/* + * Don't place this buffer on the unfenced list. This means + * that the buffer will not end up having a fence associated + * with it as a result of this operation + */ #define DRM_BO_HINT_DONT_FENCE 0x00000004 +/* + * Sleep while waiting for the operation to complete. + * Without this flag, the kernel will, instead, spin + * until this operation has completed. I'm not sure + * why you would ever want this, so please always + * provide DRM_BO_HINT_WAIT_LAZY to any operation + * which may block + */ #define DRM_BO_HINT_WAIT_LAZY 0x00000008 +/* + * The client has compute relocations refering to this buffer using the + * offset in the presumed_offset field. If that offset ends up matching + * where this buffer lands, the kernel is free to skip executing those + * relocations + */ #define DRM_BO_HINT_PRESUMED_OFFSET 0x00000010 #define DRM_BO_INIT_MAGIC 0xfe769812 commit b0bc5f1ae559c705565e516ebb289bf072559dec Author: Keith Packard <ke...@ke...> Date: Fri Dec 14 11:42:17 2007 -0800 Make ttm create/destroy APIs consistent. Pass page_flags in create. Creating a ttm was done with drm_ttm_init while destruction was done with drm_destroy_ttm. Renaming these to drm_ttm_create and drm_ttm_destroy makes their use clearer. Passing page_flags to the create function will allow that to know whether user or kernel pages are needed, with the goal of allowing kernel ttms to be saved for later reuse. diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index d308dcf..4845f44 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -144,12 +144,12 @@ static int drm_bo_add_ttm(struct drm_buffer_object *bo) switch (bo->type) { case drm_bo_type_dc: case drm_bo_type_kernel: - bo->ttm = drm_ttm_init(dev, bo->num_pages << PAGE_SHIFT); + bo->ttm = drm_ttm_create(dev, bo->num_pages << PAGE_SHIFT, 0); if (!bo->ttm) ret = -ENOMEM; break; case drm_bo_type_user: - bo->ttm = drm_ttm_init(dev, bo->num_pages << PAGE_SHIFT); + bo->ttm = drm_ttm_create(dev, bo->num_pages << PAGE_SHIFT, DRM_TTM_PAGE_USER); if (!bo->ttm) ret = -ENOMEM; @@ -262,7 +262,7 @@ out_err: new_man = &bm->man[bo->mem.mem_type]; if ((new_man->flags & _DRM_FLAG_MEMTYPE_FIXED) && bo->ttm) { drm_ttm_unbind(bo->ttm); - drm_destroy_ttm(bo->ttm); + drm_ttm_destroy(bo->ttm); bo->ttm = NULL; } @@ -419,7 +419,7 @@ static void drm_bo_destroy_locked(struct drm_buffer_object *bo) if (bo->ttm) { drm_ttm_unbind(bo->ttm); - drm_destroy_ttm(bo->ttm); + drm_ttm_destroy(bo->ttm); bo->ttm = NULL; } diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c index 971b4af..00d8d3e 100644 --- a/linux-core/drm_bo_move.c +++ b/linux-core/drm_bo_move.c @@ -260,7 +260,7 @@ out2: if ((man->flags & _DRM_FLAG_MEMTYPE_FIXED) && (ttm != NULL)) { drm_ttm_unbind(ttm); - drm_destroy_ttm(ttm); + drm_ttm_destroy(ttm); bo->ttm = NULL; } @@ -365,7 +365,7 @@ int drm_bo_move_accel_cleanup(struct drm_buffer_object *bo, if ((man->flags & _DRM_FLAG_MEMTYPE_FIXED) && (bo->ttm != NULL)) { drm_ttm_unbind(bo->ttm); - drm_destroy_ttm(bo->ttm); + drm_ttm_destroy(bo->ttm); bo->ttm = NULL; } } else { diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 1dc61fd..66611f6 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -297,7 +297,7 @@ struct drm_ttm { }; -extern struct drm_ttm *drm_ttm_init(struct drm_device *dev, unsigned long size); +extern struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size, uint32_t page_flags); extern int drm_bind_ttm(struct drm_ttm *ttm, struct drm_bo_mem_reg *bo_mem); extern void drm_ttm_unbind(struct drm_ttm *ttm); extern void drm_ttm_evict(struct drm_ttm *ttm); @@ -318,7 +318,7 @@ extern int drm_ttm_set_user(struct drm_ttm *ttm, * Otherwise it is called when the last vma exits. */ -extern int drm_destroy_ttm(struct drm_ttm *ttm); +extern int drm_ttm_destroy(struct drm_ttm *ttm); #define DRM_FLAG_MASKED(_old, _new, _mask) {\ (_old) ^= (((_old) ^ (_new)) & (_mask)); \ diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index 3540571..4200bc1 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -193,7 +193,7 @@ static void drm_ttm_free_alloced_pages(struct drm_ttm *ttm) * Free all resources associated with a ttm. */ -int drm_destroy_ttm(struct drm_ttm *ttm) +int drm_ttm_destroy(struct drm_ttm *ttm) { struct drm_ttm_backend *be; @@ -251,11 +251,11 @@ int drm_ttm_set_user(struct drm_ttm *ttm, int i; BUG_ON(num_pages != ttm->num_pages); + BUG_ON((ttm->page_flags & DRM_TTM_PAGE_USER) == 0); ttm->dummy_read_page = dummy_read_page; - ttm->page_flags |= DRM_TTM_PAGE_USER | - ((write) ? DRM_TTM_PAGE_USER_WRITE : 0); - + if (write) + ttm->page_flags |= DRM_TTM_PAGE_USER_WRITE; down_read(&mm->mmap_sem); ret = get_user_pages(tsk, mm, start, num_pages, @@ -299,7 +299,7 @@ int drm_ttm_populate(struct drm_ttm *ttm) * Initialize a ttm. */ -struct drm_ttm *drm_ttm_init(struct drm_device *dev, unsigned long size) +struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size, uint32_t page_flags) { struct drm_bo_driver *bo_driver = dev->driver->bo_driver; struct drm_ttm *ttm; @@ -317,7 +317,7 @@ struct drm_ttm *drm_ttm_init(struct drm_device *dev, unsigned long size) ttm->destroy = 0; ttm->num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; - ttm->page_flags = 0; + ttm->page_flags = page_flags; /* * Account also for AGP module memory usage. @@ -325,13 +325,13 @@ struct drm_ttm *drm_ttm_init(struct drm_device *dev, unsigned long size) ttm_alloc_pages(ttm); if (!ttm->pages) { - drm_destroy_ttm(ttm); + drm_ttm_destroy(ttm); DRM_ERROR("Failed allocating page table\n"); return NULL; } ttm->be = bo_driver->create_ttm_backend_entry(dev); if (!ttm->be) { - drm_destroy_ttm(ttm); + drm_ttm_destroy(ttm); DRM_ERROR("Failed creating ttm backend entry\n"); return NULL; } |
From: <ic...@ke...> - 2009-12-02 14:30:44
|
intel/intel_bufmgr_gem.c | 111 ++++++++++++++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 39 deletions(-) New commits: commit 57473c7f523f476ffa54c34e0c6312ffa66dcc5c Author: Chris Wilson <ch...@ch...> Date: Wed Dec 2 13:36:22 2009 +0000 intel: Free memory before inserting bo into cache. This has the unfortunate behaviour of releasing our malloc cache, but the alternative is for X to consume a couple of gigabytes of ram and die during testing. Fortunately the extra mallocs have little impact on performance whereas avoiding swap and death, lots. Signed-off-by: Chris Wilson <ch...@ch...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index ac7297b..571ab5c 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -727,9 +727,6 @@ drm_intel_gem_bo_free(drm_intel_bo *bo) if (bo_gem->gtt_virtual) munmap(bo_gem->gtt_virtual, bo_gem->bo.size); - free(bo_gem->reloc_target_bo); - free(bo_gem->relocs); - /* Close this object */ memset(&close, 0, sizeof(close)); close.handle = bo_gem->gem_handle; @@ -788,6 +785,16 @@ drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time) DBG("bo_unreference final: %d (%s)\n", bo_gem->gem_handle, bo_gem->name); + /* release memory associated with this object */ + if (bo_gem->reloc_target_bo) { + free(bo_gem->reloc_target_bo); + bo_gem->reloc_target_bo = NULL; + } + if (bo_gem->relocs) { + free(bo_gem->relocs); + bo_gem->relocs = NULL; + } + bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo->size); /* Put the buffer into our internal cache for reuse if we can. */ tiling_mode = I915_TILING_NONE; commit 792fed1e2460f96459141b5a628dd5ab4fbb87db Author: Chris Wilson <ch...@ch...> Date: Wed Dec 2 13:12:39 2009 +0000 intel: Check and propagate errors from building reloc-tree Instead of forcing the caller to check after every emit_reloc(), we can flag the object as being in error, propagating that error upwards through the relocation tree, and failing the eventual batch buffer execution. Signed-off-by: Chris Wilson <ch...@ch...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index 239f36d..ac7297b 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -154,6 +154,11 @@ struct _drm_intel_bo_gem { char used_as_reloc_target; /** + * Boolean of whether we have encountered an error whilst building the relocation tree. + */ + char has_error; + + /** * Boolean of whether this buffer can be re-used */ char reusable; @@ -396,6 +401,17 @@ drm_intel_setup_reloc_list(drm_intel_bo *bo) bo_gem->relocs = malloc(max_relocs * sizeof(struct drm_i915_gem_relocation_entry)); bo_gem->reloc_target_bo = malloc(max_relocs * sizeof(drm_intel_bo *)); + if (bo_gem->relocs == NULL || bo_gem->reloc_target_bo == NULL) { + bo_gem->has_error = 1; + + free (bo_gem->relocs); + bo_gem->relocs = NULL; + + free (bo_gem->reloc_target_bo); + bo_gem->reloc_target_bo = NULL; + + return 1; + } return 0; } @@ -564,6 +580,7 @@ retry: bo_gem->validate_index = -1; bo_gem->reloc_tree_fences = 0; bo_gem->used_as_reloc_target = 0; + bo_gem->has_error = 0; bo_gem->tiling_mode = I915_TILING_NONE; bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; bo_gem->reusable = 1; @@ -1178,10 +1195,22 @@ drm_intel_gem_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo; pthread_mutex_lock(&bufmgr_gem->lock); + if (bo_gem->has_error) { + pthread_mutex_unlock(&bufmgr_gem->lock); + return -ENOMEM; + } + + if (target_bo_gem->has_error) { + bo_gem->has_error = 1; + pthread_mutex_unlock(&bufmgr_gem->lock); + return -ENOMEM; + } /* Create a new relocation list if needed */ - if (bo_gem->relocs == NULL) - drm_intel_setup_reloc_list(bo); + if (bo_gem->relocs == NULL && drm_intel_setup_reloc_list(bo)) { + pthread_mutex_unlock(&bufmgr_gem->lock); + return -ENOMEM; + } /* Check overflow */ assert(bo_gem->reloc_count < bufmgr_gem->max_relocs); @@ -1268,9 +1297,13 @@ drm_intel_gem_bo_exec(drm_intel_bo *bo, int used, drm_clip_rect_t * cliprects, int num_cliprects, int DR4) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; + drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; struct drm_i915_gem_execbuffer execbuf; int ret, i; + if (bo_gem->has_error) + return -ENOMEM; + pthread_mutex_lock(&bufmgr_gem->lock); /* Update indices and set up the validate list. */ drm_intel_gem_bo_process_reloc(bo); commit b73612e4fd69565aa2c5c2e9677f3e0af1945f7d Author: Chris Wilson <ch...@ch...> Date: Wed Dec 2 12:58:00 2009 +0000 intel: Repeat execbuffer after EINTR EAGAIN cannot be raised by the current code, but the system call maybe interrupted and so return EINTR. Signed-off-by: Chris Wilson <ch...@ch...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index bb20f43..239f36d 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -1293,7 +1293,7 @@ drm_intel_gem_bo_exec(drm_intel_bo *bo, int used, ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER, &execbuf); - } while (ret != 0 && errno == EAGAIN); + } while (ret != 0 && errno == EINTR); if (ret != 0) { ret = -errno; commit acb4aa671507aa181b3ff50ccf26a1c0d705a309 Author: Chris Wilson <ch...@ch...> Date: Wed Dec 2 12:40:26 2009 +0000 intel: Review use of errno. Hitting this error lead to a segfault: intel_bufmgr_gem.c:919: Error mapping buffer 48607 (pixmap): Cannot allocate memory. because the errno was reused as the function return value after being reset by the fprintf(), so caller thought the mapping had succeeded. The convention established by libdrm is that the return value is the negative errno and that uses of libdrm cannot trust the value of errno afterwards, but must use the return code. Signed-off-by: Chris Wilson <ch...@ch...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index e9896e7..bb20f43 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -846,6 +846,7 @@ static int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable) &mmap_arg); } while (ret == -1 && errno == EINTR); if (ret != 0) { + ret = -errno; fprintf(stderr, "%s:%d: Error mapping buffer %d (%s): %s .\n", __FILE__, __LINE__, bo_gem->gem_handle, @@ -871,6 +872,7 @@ static int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable) &set_domain); } while (ret == -1 && errno == EINTR); if (ret != 0) { + ret = -errno; fprintf(stderr, "%s:%d: Error setting to CPU domain %d: %s\n", __FILE__, __LINE__, bo_gem->gem_handle, strerror(errno)); @@ -909,6 +911,7 @@ int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo) &mmap_arg); } while (ret == -1 && errno == EINTR); if (ret != 0) { + ret = -errno; fprintf(stderr, "%s:%d: Error preparing buffer map %d (%s): %s .\n", __FILE__, __LINE__, @@ -923,13 +926,14 @@ int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo) MAP_SHARED, bufmgr_gem->fd, mmap_arg.offset); if (bo_gem->gtt_virtual == MAP_FAILED) { + ret = -errno; fprintf(stderr, "%s:%d: Error mapping buffer %d (%s): %s .\n", __FILE__, __LINE__, bo_gem->gem_handle, bo_gem->name, strerror(errno)); pthread_mutex_unlock(&bufmgr_gem->lock); - return errno; + return ret; } } @@ -949,6 +953,7 @@ int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo) } while (ret == -1 && errno == EINTR); if (ret != 0) { + ret = -errno; fprintf(stderr, "%s:%d: Error setting domain %d: %s\n", __FILE__, __LINE__, bo_gem->gem_handle, strerror(errno)); @@ -1077,12 +1082,13 @@ drm_intel_gem_bo_get_subdata(drm_intel_bo *bo, unsigned long offset, &pread); } while (ret == -1 && errno == EINTR); if (ret != 0) { + ret = -errno; fprintf(stderr, "%s:%d: Error reading data from buffer %d: (%d %d) %s .\n", __FILE__, __LINE__, bo_gem->gem_handle, (int)offset, (int)size, strerror(errno)); } - return 0; + return ret; } /** Waits for all GPU rendering to the object to have completed. */ @@ -1289,17 +1295,20 @@ drm_intel_gem_bo_exec(drm_intel_bo *bo, int used, &execbuf); } while (ret != 0 && errno == EAGAIN); - if (ret != 0 && errno == ENOMEM) { - fprintf(stderr, - "Execbuffer fails to pin. " - "Estimate: %u. Actual: %u. Available: %u\n", - drm_intel_gem_estimate_batch_space(bufmgr_gem->exec_bos, - bufmgr_gem-> - exec_count), - drm_intel_gem_compute_batch_space(bufmgr_gem->exec_bos, - bufmgr_gem-> - exec_count), - (unsigned int)bufmgr_gem->gtt_size); + if (ret != 0) { + ret = -errno; + if (errno == ENOSPC) { + fprintf(stderr, + "Execbuffer fails to pin. " + "Estimate: %u. Actual: %u. Available: %u\n", + drm_intel_gem_estimate_batch_space(bufmgr_gem->exec_bos, + bufmgr_gem-> + exec_count), + drm_intel_gem_compute_batch_space(bufmgr_gem->exec_bos, + bufmgr_gem-> + exec_count), + (unsigned int)bufmgr_gem->gtt_size); + } } drm_intel_update_buffer_offsets(bufmgr_gem); @@ -1317,7 +1326,7 @@ drm_intel_gem_bo_exec(drm_intel_bo *bo, int used, bufmgr_gem->exec_count = 0; pthread_mutex_unlock(&bufmgr_gem->lock); - return 0; + return ret; } static int @@ -1606,7 +1615,7 @@ drm_intel_gem_check_aperture_space(drm_intel_bo **bo_array, int count) if (bufmgr_gem->available_fences) { total_fences = drm_intel_gem_total_fences(bo_array, count); if (total_fences > bufmgr_gem->available_fences) - return -1; + return -ENOSPC; } total = drm_intel_gem_estimate_batch_space(bo_array, count); @@ -1618,7 +1627,7 @@ drm_intel_gem_check_aperture_space(drm_intel_bo **bo_array, int count) DBG("check_space: overflowed available aperture, " "%dkb vs %dkb\n", total / 1024, (int)bufmgr_gem->gtt_size / 1024); - return -1; + return -ENOSPC; } else { DBG("drm_check_space: total %dkb vs bufgr %dkb\n", total / 1024, (int)bufmgr_gem->gtt_size / 1024); commit 9fec2a8cb28d814da4fdd97b25e9cc5c10768c87 Author: Chris Wilson <ch...@ch...> Date: Wed Dec 2 10:42:51 2009 +0000 intel: Make bo_reference() inline for internal use. Signed-off-by: Chris Wilson <ch...@ch...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index cf3943c..e9896e7 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -304,7 +304,7 @@ drm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem) } } -static void +static inline void drm_intel_gem_bo_reference(drm_intel_bo *bo) { drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; commit 9c8ad05e8bb1c954b804e40f2f975fed23c24550 Author: Chris Wilson <ch...@ch...> Date: Wed Dec 2 10:41:39 2009 +0000 intel: Remove the extra reference while validating the reloc tree Buffers on the relocation tree are guarded by the reference to the batch object and so do not need an extra reference whilst constructing the list of execution buffer objects. Signed-off-by: Chris Wilson <ch...@ch...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index 3b4d3cf..cf3943c 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -187,7 +187,6 @@ static int drm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, uint32_t stride); -static void drm_intel_gem_bo_unreference_locked(drm_intel_bo *bo); static void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo, time_t time); @@ -357,7 +356,6 @@ drm_intel_add_validate_buffer(drm_intel_bo *bo) bufmgr_gem->exec_objects[index].alignment = 0; bufmgr_gem->exec_objects[index].offset = 0; bufmgr_gem->exec_bos[index] = bo; - drm_intel_gem_bo_reference(bo); bufmgr_gem->exec_count++; } @@ -793,19 +791,6 @@ drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time) } } -static void drm_intel_gem_bo_unreference_locked(drm_intel_bo *bo) -{ - drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; - - assert(atomic_read(&bo_gem->refcount) > 0); - if (atomic_dec_and_test(&bo_gem->refcount)) { - struct timespec time; - - clock_gettime(CLOCK_MONOTONIC, &time); - drm_intel_gem_bo_unreference_final(bo, time.tv_sec); - } -} - static void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo, time_t time) { @@ -1327,7 +1312,6 @@ drm_intel_gem_bo_exec(drm_intel_bo *bo, int used, /* Disconnect the buffer from the validate list */ bo_gem->validate_index = -1; - drm_intel_gem_bo_unreference_locked(bo); bufmgr_gem->exec_bos[i] = NULL; } bufmgr_gem->exec_count = 0; |
From: <jb...@ke...> - 2009-12-03 22:29:23
|
include/drm/drm.h | 4 + include/drm/drm_mode.h | 11 +++ include/drm/i915_drm.h | 1 tests/modetest/modetest.c | 146 +++++++++++++++++++++++++++++++++++++++++++--- xf86drm.h | 8 ++ xf86drmMode.c | 25 +++++++ xf86drmMode.h | 2 7 files changed, 187 insertions(+), 10 deletions(-) New commits: commit 14f5958f7fd9ebe8a772ea931feb044d2d5d967b Author: Jesse Barnes <jb...@vi...> Date: Thu Dec 3 14:20:51 2009 -0800 Bump event context structure version for page flipping diff --git a/xf86drm.h b/xf86drm.h index 89f1db1..9b89f56 100644 --- a/xf86drm.h +++ b/xf86drm.h @@ -693,7 +693,7 @@ extern void drmMsg(const char *format, ...); extern int drmSetMaster(int fd); extern int drmDropMaster(int fd); -#define DRM_EVENT_CONTEXT_VERSION 1 +#define DRM_EVENT_CONTEXT_VERSION 2 typedef struct _drmEventContext { diff --git a/xf86drmMode.c b/xf86drmMode.c index e951685..317aa47 100644 --- a/xf86drmMode.c +++ b/xf86drmMode.c @@ -701,7 +701,7 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx) U642VOID (vblank->user_data)); break; case DRM_EVENT_FLIP_COMPLETE: - if (evctx->version < 1 || + if (evctx->version < 2 || evctx->page_flip_handler == NULL) break; vblank = (struct drm_event_vblank *) e; commit 53addc5d6ef7406d9fab5ea481cf68fa011870f1 Merge: db50f51... ee746a8... Author: Jesse Barnes <jb...@vi...> Date: Thu Dec 3 14:17:26 2009 -0800 Merge branch 'pageflip' of git://people.freedesktop.org/~jbarnes/drm Conflicts: include/drm/drm.h - RMFB had its signature changed to avoid uint32_t diff --cc include/drm/drm.h index 649c46f,0000000..5408c08 mode 100644,000000..100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h @@@ -1,782 -1,0 +1,786 @@@ +/** + * \file drm.h + * Header for the Direct Rendering Manager + * + * \author Rickard E. (Rik) Faith <fa...@va...> + * + * \par Acknowledgments: + * Dec 1999, Richard Henderson <rt...@tw...>, move to generic \c cmpxchg. + */ + +/* + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DRM_H_ +#define _DRM_H_ + +#if defined(__linux__) + +#include <linux/types.h> +#include <asm/ioctl.h> +typedef unsigned int drm_handle_t; + +#else /* One of the BSDs */ + +#include <sys/ioccom.h> +#include <sys/types.h> +typedef int8_t __s8; +typedef uint8_t __u8; +typedef int16_t __s16; +typedef uint16_t __u16; +typedef int32_t __s32; +typedef uint32_t __u32; +typedef int64_t __s64; +typedef uint64_t __u64; +typedef unsigned long drm_handle_t; + +#endif + +#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */ +#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */ +#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */ +#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */ + +#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */ +#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */ +#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD) +#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT) +#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT)) + +typedef unsigned int drm_context_t; +typedef unsigned int drm_drawable_t; +typedef unsigned int drm_magic_t; + +/** + * Cliprect. + * + * \warning: If you change this structure, make sure you change + * XF86DRIClipRectRec in the server as well + * + * \note KW: Actually it's illegal to change either for + * backwards-compatibility reasons. + */ +struct drm_clip_rect { + unsigned short x1; + unsigned short y1; + unsigned short x2; + unsigned short y2; +}; + +/** + * Drawable information. + */ +struct drm_drawable_info { + unsigned int num_rects; + struct drm_clip_rect *rects; +}; + +/** + * Texture region, + */ +struct drm_tex_region { + unsigned char next; + unsigned char prev; + unsigned char in_use; + unsigned char padding; + unsigned int age; +}; + +/** + * Hardware lock. + * + * The lock structure is a simple cache-line aligned integer. To avoid + * processor bus contention on a multiprocessor system, there should not be any + * other data stored in the same cache line. + */ +struct drm_hw_lock { + __volatile__ unsigned int lock; /**< lock variable */ + char padding[60]; /**< Pad to cache line */ +}; + +/** + * DRM_IOCTL_VERSION ioctl argument type. + * + * \sa drmGetVersion(). + */ +struct drm_version { + int version_major; /**< Major version */ + int version_minor; /**< Minor version */ + int version_patchlevel; /**< Patch level */ + size_t name_len; /**< Length of name buffer */ + char *name; /**< Name of driver */ + size_t date_len; /**< Length of date buffer */ + char *date; /**< User-space buffer to hold date */ + size_t desc_len; /**< Length of desc buffer */ + char *desc; /**< User-space buffer to hold desc */ +}; + +/** + * DRM_IOCTL_GET_UNIQUE ioctl argument type. + * + * \sa drmGetBusid() and drmSetBusId(). + */ +struct drm_unique { + size_t unique_len; /**< Length of unique */ + char *unique; /**< Unique name for driver instantiation */ +}; + +struct drm_list { + int count; /**< Length of user-space structures */ + struct drm_version *version; +}; + +struct drm_block { + int unused; +}; + +/** + * DRM_IOCTL_CONTROL ioctl argument type. + * + * \sa drmCtlInstHandler() and drmCtlUninstHandler(). + */ +struct drm_control { + enum { + DRM_ADD_COMMAND, + DRM_RM_COMMAND, + DRM_INST_HANDLER, + DRM_UNINST_HANDLER + } func; + int irq; +}; + +/** + * Type of memory to map. + */ +enum drm_map_type { + _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */ + _DRM_REGISTERS = 1, /**< no caching, no core dump */ + _DRM_SHM = 2, /**< shared, cached */ + _DRM_AGP = 3, /**< AGP/GART */ + _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */ + _DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */ + _DRM_GEM = 6, /**< GEM object */ +}; + +/** + * Memory mapping flags. + */ +enum drm_map_flags { + _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */ + _DRM_READ_ONLY = 0x02, + _DRM_LOCKED = 0x04, /**< shared, cached, locked */ + _DRM_KERNEL = 0x08, /**< kernel requires access */ + _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */ + _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */ + _DRM_REMOVABLE = 0x40, /**< Removable mapping */ + _DRM_DRIVER = 0x80 /**< Managed by driver */ +}; + +struct drm_ctx_priv_map { + unsigned int ctx_id; /**< Context requesting private mapping */ + void *handle; /**< Handle of map */ +}; + +/** + * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls + * argument type. + * + * \sa drmAddMap(). + */ +struct drm_map { + unsigned long offset; /**< Requested physical address (0 for SAREA)*/ + unsigned long size; /**< Requested physical size (bytes) */ + enum drm_map_type type; /**< Type of memory to map */ + enum drm_map_flags flags; /**< Flags */ + void *handle; /**< User-space: "Handle" to pass to mmap() */ + /**< Kernel-space: kernel-virtual address */ + int mtrr; /**< MTRR slot used */ + /* Private data */ +}; + +/** + * DRM_IOCTL_GET_CLIENT ioctl argument type. + */ +struct drm_client { + int idx; /**< Which client desired? */ + int auth; /**< Is client authenticated? */ + unsigned long pid; /**< Process ID */ + unsigned long uid; /**< User ID */ + unsigned long magic; /**< Magic */ + unsigned long iocs; /**< Ioctl count */ +}; + +enum drm_stat_type { + _DRM_STAT_LOCK, + _DRM_STAT_OPENS, + _DRM_STAT_CLOSES, + _DRM_STAT_IOCTLS, + _DRM_STAT_LOCKS, + _DRM_STAT_UNLOCKS, + _DRM_STAT_VALUE, /**< Generic value */ + _DRM_STAT_BYTE, /**< Generic byte counter (1024bytes/K) */ + _DRM_STAT_COUNT, /**< Generic non-byte counter (1000/k) */ + + _DRM_STAT_IRQ, /**< IRQ */ + _DRM_STAT_PRIMARY, /**< Primary DMA bytes */ + _DRM_STAT_SECONDARY, /**< Secondary DMA bytes */ + _DRM_STAT_DMA, /**< DMA */ + _DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */ + _DRM_STAT_MISSED /**< Missed DMA opportunity */ + /* Add to the *END* of the list */ +}; + +/** + * DRM_IOCTL_GET_STATS ioctl argument type. + */ +struct drm_stats { + unsigned long count; + struct { + unsigned long value; + enum drm_stat_type type; + } data[15]; +}; + +/** + * Hardware locking flags. + */ +enum drm_lock_flags { + _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */ + _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */ + _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */ + _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */ + /* These *HALT* flags aren't supported yet + -- they will be used to support the + full-screen DGA-like mode. */ + _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */ + _DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */ +}; + +/** + * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type. + * + * \sa drmGetLock() and drmUnlock(). + */ +struct drm_lock { + int context; + enum drm_lock_flags flags; +}; + +/** + * DMA flags + * + * \warning + * These values \e must match xf86drm.h. + * + * \sa drm_dma. + */ +enum drm_dma_flags { + /* Flags for DMA buffer dispatch */ + _DRM_DMA_BLOCK = 0x01, /**< + * Block until buffer dispatched. + * + * \note The buffer may not yet have + * been processed by the hardware -- + * getting a hardware lock with the + * hardware quiescent will ensure + * that the buffer has been + * processed. + */ + _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */ + _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */ + + /* Flags for DMA buffer request */ + _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */ + _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */ + _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */ +}; + +/** + * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type. + * + * \sa drmAddBufs(). + */ +struct drm_buf_desc { + int count; /**< Number of buffers of this size */ + int size; /**< Size in bytes */ + int low_mark; /**< Low water mark */ + int high_mark; /**< High water mark */ + enum { + _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */ + _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */ + _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */ + _DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */ + _DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */ + } flags; + unsigned long agp_start; /**< + * Start address of where the AGP buffers are + * in the AGP aperture + */ +}; + +/** + * DRM_IOCTL_INFO_BUFS ioctl argument type. + */ +struct drm_buf_info { + int count; /**< Entries in list */ + struct drm_buf_desc *list; +}; + +/** + * DRM_IOCTL_FREE_BUFS ioctl argument type. + */ +struct drm_buf_free { + int count; + int *list; +}; + +/** + * Buffer information + * + * \sa drm_buf_map. + */ +struct drm_buf_pub { + int idx; /**< Index into the master buffer list */ + int total; /**< Buffer size */ + int used; /**< Amount of buffer in use (for DMA) */ + void *address; /**< Address of buffer */ +}; + +/** + * DRM_IOCTL_MAP_BUFS ioctl argument type. + */ +struct drm_buf_map { + int count; /**< Length of the buffer list */ + void *virtual; /**< Mmap'd area in user-virtual */ + struct drm_buf_pub *list; /**< Buffer information */ +}; + +/** + * DRM_IOCTL_DMA ioctl argument type. + * + * Indices here refer to the offset into the buffer list in drm_buf_get. + * + * \sa drmDMA(). + */ +struct drm_dma { + int context; /**< Context handle */ + int send_count; /**< Number of buffers to send */ + int *send_indices; /**< List of handles to buffers */ + int *send_sizes; /**< Lengths of data to send */ + enum drm_dma_flags flags; /**< Flags */ + int request_count; /**< Number of buffers requested */ + int request_size; /**< Desired size for buffers */ + int *request_indices; /**< Buffer information */ + int *request_sizes; + int granted_count; /**< Number of buffers granted */ +}; + +enum drm_ctx_flags { + _DRM_CONTEXT_PRESERVED = 0x01, + _DRM_CONTEXT_2DONLY = 0x02 +}; + +/** + * DRM_IOCTL_ADD_CTX ioctl argument type. + * + * \sa drmCreateContext() and drmDestroyContext(). + */ +struct drm_ctx { + drm_context_t handle; + enum drm_ctx_flags flags; +}; + +/** + * DRM_IOCTL_RES_CTX ioctl argument type. + */ +struct drm_ctx_res { + int count; + struct drm_ctx *contexts; +}; + +/** + * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type. + */ +struct drm_draw { + drm_drawable_t handle; +}; + +/** + * DRM_IOCTL_UPDATE_DRAW ioctl argument type. + */ +typedef enum { + DRM_DRAWABLE_CLIPRECTS, +} drm_drawable_info_type_t; + +struct drm_update_draw { + drm_drawable_t handle; + unsigned int type; + unsigned int num; + unsigned long long data; +}; + +/** + * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type. + */ +struct drm_auth { + drm_magic_t magic; +}; + +/** + * DRM_IOCTL_IRQ_BUSID ioctl argument type. + * + * \sa drmGetInterruptFromBusID(). + */ +struct drm_irq_busid { + int irq; /**< IRQ number */ + int busnum; /**< bus number */ + int devnum; /**< device number */ + int funcnum; /**< function number */ +}; + +enum drm_vblank_seq_type { + _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ + _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + _DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */ + _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ + _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ + _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ + _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking, unsupported */ +}; + +#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) +#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_EVENT | _DRM_VBLANK_SIGNAL | \ + _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS) + +struct drm_wait_vblank_request { + enum drm_vblank_seq_type type; + unsigned int sequence; + unsigned long signal; +}; + +struct drm_wait_vblank_reply { + enum drm_vblank_seq_type type; + unsigned int sequence; + long tval_sec; + long tval_usec; +}; + +/** + * DRM_IOCTL_WAIT_VBLANK ioctl argument type. + * + * \sa drmWaitVBlank(). + */ +union drm_wait_vblank { + struct drm_wait_vblank_request request; + struct drm_wait_vblank_reply reply; +}; + +#define _DRM_PRE_MODESET 1 +#define _DRM_POST_MODESET 2 + +/** + * DRM_IOCTL_MODESET_CTL ioctl argument type + * + * \sa drmModesetCtl(). + */ +struct drm_modeset_ctl { + __u32 crtc; + __u32 cmd; +}; + +/** + * DRM_IOCTL_AGP_ENABLE ioctl argument type. + * + * \sa drmAgpEnable(). + */ +struct drm_agp_mode { + unsigned long mode; /**< AGP mode */ +}; + +/** + * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type. + * + * \sa drmAgpAlloc() and drmAgpFree(). + */ +struct drm_agp_buffer { + unsigned long size; /**< In bytes -- will round to page boundary */ + unsigned long handle; /**< Used for binding / unbinding */ + unsigned long type; /**< Type of memory to allocate */ + unsigned long physical; /**< Physical used by i810 */ +}; + +/** + * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type. + * + * \sa drmAgpBind() and drmAgpUnbind(). + */ +struct drm_agp_binding { + unsigned long handle; /**< From drm_agp_buffer */ + unsigned long offset; /**< In bytes -- will round to page boundary */ +}; + +/** + * DRM_IOCTL_AGP_INFO ioctl argument type. + * + * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(), + * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(), + * drmAgpVendorId() and drmAgpDeviceId(). + */ +struct drm_agp_info { + int agp_version_major; + int agp_version_minor; + unsigned long mode; + unsigned long aperture_base; /* physical address */ + unsigned long aperture_size; /* bytes */ + unsigned long memory_allowed; /* bytes */ + unsigned long memory_used; + + /* PCI information */ + unsigned short id_vendor; + unsigned short id_device; +}; + +/** + * DRM_IOCTL_SG_ALLOC ioctl argument type. + */ +struct drm_scatter_gather { + unsigned long size; /**< In bytes -- will round to page boundary */ + unsigned long handle; /**< Used for mapping / unmapping */ +}; + +/** + * DRM_IOCTL_SET_VERSION ioctl argument type. + */ +struct drm_set_version { + int drm_di_major; + int drm_di_minor; + int drm_dd_major; + int drm_dd_minor; +}; + +/** DRM_IOCTL_GEM_CLOSE ioctl argument type */ +struct drm_gem_close { + /** Handle of the object to be closed. */ + __u32 handle; + __u32 pad; +}; + +/** DRM_IOCTL_GEM_FLINK ioctl argument type */ +struct drm_gem_flink { + /** Handle for the object being named */ + __u32 handle; + + /** Returned global name */ + __u32 name; +}; + +/** DRM_IOCTL_GEM_OPEN ioctl argument type */ +struct drm_gem_open { + /** Name of object being opened */ + __u32 name; + + /** Returned handle for the object */ + __u32 handle; + + /** Returned size of the object */ + __u64 size; +}; + +#include "drm_mode.h" + +#define DRM_IOCTL_BASE 'd' +#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) +#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type) +#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type) +#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type) + +#define DRM_IOCTL_VERSION DRM_IOWR(0x00, struct drm_version) +#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, struct drm_unique) +#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, struct drm_auth) +#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, struct drm_irq_busid) +#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, struct drm_map) +#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client) +#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) +#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) +#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) +#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close) +#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink) +#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open) + +#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) +#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) +#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, struct drm_block) +#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, struct drm_block) +#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, struct drm_control) +#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, struct drm_map) +#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, struct drm_buf_desc) +#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, struct drm_buf_desc) +#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, struct drm_buf_info) +#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, struct drm_buf_map) +#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, struct drm_buf_free) + +#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, struct drm_map) + +#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map) +#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map) + +#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e) +#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f) + +#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx) +#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx) +#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx) +#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, struct drm_ctx) +#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, struct drm_ctx) +#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, struct drm_ctx) +#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, struct drm_ctx_res) +#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, struct drm_draw) +#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, struct drm_draw) +#define DRM_IOCTL_DMA DRM_IOWR(0x29, struct drm_dma) +#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, struct drm_lock) +#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock) +#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock) + +#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) +#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) +#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, struct drm_agp_mode) +#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, struct drm_agp_info) +#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, struct drm_agp_buffer) +#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, struct drm_agp_buffer) +#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, struct drm_agp_binding) +#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, struct drm_agp_binding) + +#define DRM_IOCTL_SG_ALLOC DRM_IOWR(0x38, struct drm_scatter_gather) +#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, struct drm_scatter_gather) + +#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank) + +#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw) + +#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) +#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc) +#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA2, struct drm_mode_crtc) +#define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xA3, struct drm_mode_cursor) +#define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xA4, struct drm_mode_crtc_lut) +#define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xA5, struct drm_mode_crtc_lut) +#define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xA6, struct drm_mode_get_encoder) +#define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA7, struct drm_mode_get_connector) +#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA8, struct drm_mode_mode_cmd) +#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) + +#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAA, struct drm_mode_get_property) +#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_connector_set_property) +#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob) +#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd) +#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd) +#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int) ++#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip) ++ ++/*@}*/ + +/** + * Device specific ioctls should only be in their respective headers + * The device specific ioctl range is from 0x40 to 0x99. + * Generic IOCTLS restart at 0xA0. + * + * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and + * drmCommandReadWrite(). + */ +#define DRM_COMMAND_BASE 0x40 +#define DRM_COMMAND_END 0xA0 + +/** + * Header for events written back to userspace on the drm fd. The + * type defines the type of event, the length specifies the total + * length of the event (including the header), and user_data is + * typically a 64 bit value passed with the ioctl that triggered the + * event. A read on the drm fd will always only return complete + * events, that is, if for example the read buffer is 100 bytes, and + * there are two 64 byte events pending, only one will be returned. + * + * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and + * up are chipset specific. + */ +struct drm_event { + __u32 type; + __u32 length; +}; + +#define DRM_EVENT_VBLANK 0x01 ++#define DRM_EVENT_FLIP_COMPLETE 0x02 + +struct drm_event_vblank { + struct drm_event base; + __u64 user_data; + __u32 tv_sec; + __u32 tv_usec; + __u32 sequence; + __u32 reserved; +}; + +/* typedef area */ +typedef struct drm_clip_rect drm_clip_rect_t; +typedef struct drm_drawable_info drm_drawable_info_t; +typedef struct drm_tex_region drm_tex_region_t; +typedef struct drm_hw_lock drm_hw_lock_t; +typedef struct drm_version drm_version_t; +typedef struct drm_unique drm_unique_t; +typedef struct drm_list drm_list_t; +typedef struct drm_block drm_block_t; +typedef struct drm_control drm_control_t; +typedef enum drm_map_type drm_map_type_t; +typedef enum drm_map_flags drm_map_flags_t; +typedef struct drm_ctx_priv_map drm_ctx_priv_map_t; +typedef struct drm_map drm_map_t; +typedef struct drm_client drm_client_t; +typedef enum drm_stat_type drm_stat_type_t; +typedef struct drm_stats drm_stats_t; +typedef enum drm_lock_flags drm_lock_flags_t; +typedef struct drm_lock drm_lock_t; +typedef enum drm_dma_flags drm_dma_flags_t; +typedef struct drm_buf_desc drm_buf_desc_t; +typedef struct drm_buf_info drm_buf_info_t; +typedef struct drm_buf_free drm_buf_free_t; +typedef struct drm_buf_pub drm_buf_pub_t; +typedef struct drm_buf_map drm_buf_map_t; +typedef struct drm_dma drm_dma_t; +typedef union drm_wait_vblank drm_wait_vblank_t; +typedef struct drm_agp_mode drm_agp_mode_t; +typedef enum drm_ctx_flags drm_ctx_flags_t; +typedef struct drm_ctx drm_ctx_t; +typedef struct drm_ctx_res drm_ctx_res_t; +typedef struct drm_draw drm_draw_t; +typedef struct drm_update_draw drm_update_draw_t; +typedef struct drm_auth drm_auth_t; +typedef struct drm_irq_busid drm_irq_busid_t; +typedef enum drm_vblank_seq_type drm_vblank_seq_type_t; + +typedef struct drm_agp_buffer drm_agp_buffer_t; +typedef struct drm_agp_binding drm_agp_binding_t; +typedef struct drm_agp_info drm_agp_info_t; +typedef struct drm_scatter_gather drm_scatter_gather_t; +typedef struct drm_set_version drm_set_version_t; + +#endif diff --cc include/drm/drm_mode.h index 852505e,0000000..1fd3026 mode 100644,000000..100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@@ -1,268 -1,0 +1,279 @@@ +/* + * Copyright (c) 2007 Dave Airlie <ai...@li...> + * Copyright (c) 2007 Jakob Bornecrantz <wal...@gm...> + * Copyright (c) 2008 Red Hat Inc. + * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA + * Copyright (c) 2007-2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _DRM_MODE_H +#define _DRM_MODE_H + +#define DRM_DISPLAY_INFO_LEN 32 +#define DRM_CONNECTOR_NAME_LEN 32 +#define DRM_DISPLAY_MODE_LEN 32 +#define DRM_PROP_NAME_LEN 32 + +#define DRM_MODE_TYPE_BUILTIN (1<<0) +#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) +#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) +#define DRM_MODE_TYPE_PREFERRED (1<<3) +#define DRM_MODE_TYPE_DEFAULT (1<<4) +#define DRM_MODE_TYPE_USERDEF (1<<5) +#define DRM_MODE_TYPE_DRIVER (1<<6) + +/* Video mode flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_FLAG_PHSYNC (1<<0) +#define DRM_MODE_FLAG_NHSYNC (1<<1) +#define DRM_MODE_FLAG_PVSYNC (1<<2) +#define DRM_MODE_FLAG_NVSYNC (1<<3) +#define DRM_MODE_FLAG_INTERLACE (1<<4) +#define DRM_MODE_FLAG_DBLSCAN (1<<5) +#define DRM_MODE_FLAG_CSYNC (1<<6) +#define DRM_MODE_FLAG_PCSYNC (1<<7) +#define DRM_MODE_FLAG_NCSYNC (1<<8) +#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ +#define DRM_MODE_FLAG_BCAST (1<<10) +#define DRM_MODE_FLAG_PIXMUX (1<<11) +#define DRM_MODE_FLAG_DBLCLK (1<<12) +#define DRM_MODE_FLAG_CLKDIV2 (1<<13) + +/* DPMS flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_DPMS_ON 0 +#define DRM_MODE_DPMS_STANDBY 1 +#define DRM_MODE_DPMS_SUSPEND 2 +#define DRM_MODE_DPMS_OFF 3 + +/* Scaling mode options */ +#define DRM_MODE_SCALE_NONE 0 /* Unmodified timing (display or + software can still scale) */ +#define DRM_MODE_SCALE_FULLSCREEN 1 /* Full screen, ignore aspect */ +#define DRM_MODE_SCALE_CENTER 2 /* Centered, no scaling */ +#define DRM_MODE_SCALE_ASPECT 3 /* Full screen, preserve aspect */ + +/* Dithering mode options */ +#define DRM_MODE_DITHERING_OFF 0 +#define DRM_MODE_DITHERING_ON 1 + +struct drm_mode_modeinfo { + __u32 clock; + __u16 hdisplay, hsync_start, hsync_end, htotal, hskew; + __u16 vdisplay, vsync_start, vsync_end, vtotal, vscan; + + __u32 vrefresh; /* vertical refresh * 1000 */ + + __u32 flags; + __u32 type; + char name[DRM_DISPLAY_MODE_LEN]; +}; + +struct drm_mode_card_res { + __u64 fb_id_ptr; + __u64 crtc_id_ptr; + __u64 connector_id_ptr; + __u64 encoder_id_ptr; + __u32 count_fbs; + __u32 count_crtcs; + __u32 count_connectors; + __u32 count_encoders; + __u32 min_width, max_width; + __u32 min_height, max_height; +}; + +struct drm_mode_crtc { + __u64 set_connectors_ptr; + __u32 count_connectors; + + __u32 crtc_id; /**< Id */ + __u32 fb_id; /**< Id of framebuffer */ + + __u32 x, y; /**< Position on the frameuffer */ + + __u32 gamma_size; + __u32 mode_valid; + struct drm_mode_modeinfo mode; +}; + +#define DRM_MODE_ENCODER_NONE 0 +#define DRM_MODE_ENCODER_DAC 1 +#define DRM_MODE_ENCODER_TMDS 2 +#define DRM_MODE_ENCODER_LVDS 3 +#define DRM_MODE_ENCODER_TVDAC 4 + +struct drm_mode_get_encoder { + __u32 encoder_id; + __u32 encoder_type; + + __u32 crtc_id; /**< Id of crtc */ + + __u32 possible_crtcs; + __u32 possible_clones; +}; + +/* This is for connectors with multiple signal types. */ +/* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */ +#define DRM_MODE_SUBCONNECTOR_Automatic 0 +#define DRM_MODE_SUBCONNECTOR_Unknown 0 +#define DRM_MODE_SUBCONNECTOR_DVID 3 +#define DRM_MODE_SUBCONNECTOR_DVIA 4 +#define DRM_MODE_SUBCONNECTOR_Composite 5 +#define DRM_MODE_SUBCONNECTOR_SVIDEO 6 +#define DRM_MODE_SUBCONNECTOR_Component 8 +#define DRM_MODE_SUBCONNECTOR_SCART 9 + +#define DRM_MODE_CONNECTOR_Unknown 0 +#define DRM_MODE_CONNECTOR_VGA 1 +#define DRM_MODE_CONNECTOR_DVII 2 +#define DRM_MODE_CONNECTOR_DVID 3 +#define DRM_MODE_CONNECTOR_DVIA 4 +#define DRM_MODE_CONNECTOR_Composite 5 +#define DRM_MODE_CONNECTOR_SVIDEO 6 +#define DRM_MODE_CONNECTOR_LVDS 7 +#define DRM_MODE_CONNECTOR_Component 8 +#define DRM_MODE_CONNECTOR_9PinDIN 9 +#define DRM_MODE_CONNECTOR_DisplayPort 10 +#define DRM_MODE_CONNECTOR_HDMIA 11 +#define DRM_MODE_CONNECTOR_HDMIB 12 +#define DRM_MODE_CONNECTOR_TV 13 + +struct drm_mode_get_connector { + + __u64 encoders_ptr; + __u64 modes_ptr; + __u64 props_ptr; + __u64 prop_values_ptr; + + __u32 count_modes; + __u32 count_props; + __u32 count_encoders; + + __u32 encoder_id; /**< Current Encoder */ + __u32 connector_id; /**< Id */ + __u32 connector_type; + __u32 connector_type_id; + + __u32 connection; + __u32 mm_width, mm_height; /**< HxW in millimeters */ + __u32 subpixel; +}; + +#define DRM_MODE_PROP_PENDING (1<<0) +#define DRM_MODE_PROP_RANGE (1<<1) +#define DRM_MODE_PROP_IMMUTABLE (1<<2) +#define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ +#define DRM_MODE_PROP_BLOB (1<<4) + +struct drm_mode_property_enum { + __u64 value; + char name[DRM_PROP_NAME_LEN]; +}; + +struct drm_mode_get_property { + __u64 values_ptr; /* values and blob lengths */ + __u64 enum_blob_ptr; /* enum and blob id ptrs */ + + __u32 prop_id; + __u32 flags; + char name[DRM_PROP_NAME_LEN]; + + __u32 count_values; + __u32 count_enum_blobs; +}; + +struct drm_mode_connector_set_property { + __u64 value; + __u32 prop_id; + __u32 connector_id; +}; + +struct drm_mode_get_blob { + __u32 blob_id; + __u32 length; + __u64 data; +}; + +struct drm_mode_fb_cmd { + __u32 fb_id; + __u32 width, height; + __u32 pitch; + __u32 bpp; + __u32 depth; + /* driver specific handle */ + __u32 handle; +}; + +struct drm_mode_mode_cmd { + __u32 connector_id; + struct drm_mode_modeinfo mode; +}; + +#define DRM_MODE_CURSOR_BO (1<<0) +#define DRM_MODE_CURSOR_MOVE (1<<1) + +/* + * depending on the value in flags diffrent members are used. + * + * CURSOR_BO uses + * crtc + * width + * height + * handle - if 0 turns the cursor of + * + * CURSOR_MOVE uses + * crtc + * x + * y + */ +struct drm_mode_cursor { + __u32 flags; + __u32 crtc_id; + __s32 x; + __s32 y; + __u32 width; + __u32 height; + /* driver specific handle */ + __u32 handle; +}; + +struct drm_mode_crtc_lut { + __u32 crtc_id; + __u32 gamma_size; + + /* pointers to arrays */ + __u64 red; + __u64 green; + __u64 blue; +}; + ++#define DRM_MODE_PAGE_FLIP_EVENT 0x01 ++#define DRM_MODE_PAGE_FLIP_FLAGS DRM_MODE_PAGE_FLIP_EVENT ++ ++struct drm_mode_crtc_page_flip { ++ uint32_t crtc_id; ++ uint32_t fb_id; ++ uint32_t flags; ++ uint32_t reserved; ++ uint64_t user_data; ++}; ++ +#endif diff --cc include/drm/i915_drm.h index 25ff7b7,0000000..75b0e1d mode 100644,000000..100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@@ -1,760 -1,0 +1,761 @@@ +/* + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _I915_DRM_H_ +#define _I915_DRM_H_ + +#include "drm.h" + +/* Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + */ + +/* Each region is a minimum of 16k, and there are at most 255 of them. + */ +#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use + * of chars for next/prev indices */ +#define I915_LOG_MIN_TEX_REGION_SIZE 14 + +typedef struct _drm_i915_init { + enum { + I915_INIT_DMA = 0x01, + I915_CLEANUP_DMA = 0x02, + I915_RESUME_DMA = 0x03 + } func; + unsigned int mmio_offset; + int sarea_priv_offset; + unsigned int ring_start; + unsigned int ring_end; + unsigned int ring_size; + unsigned int front_offset; + unsigned int back_offset; + unsigned int depth_offset; + unsigned int w; + unsigned int h; + unsigned int pitch; + unsigned int pitch_bits; + unsigned int back_pitch; + unsigned int depth_pitch; + unsigned int cpp; + unsigned int chipset; +} drm_i915_init_t; + +typedef struct _drm_i915_sarea { + struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1]; + int last_upload; /* last time texture was uploaded */ + int last_enqueue; /* last time a buffer was enqueued */ + int last_dispatch; /* age of the most recently dispatched buffer */ + int ctxOwner; /* last context to upload state */ + int texAge; + int pf_enabled; /* is pageflipping allowed? */ + int pf_active; + int pf_current_page; /* which buffer is being displayed? */ + int perf_boxes; /* performance boxes to be displayed */ + int width, height; /* screen size in pixels */ + + drm_handle_t front_handle; + int front_offset; + int front_size; + + drm_handle_t back_handle; + int back_offset; + int back_size; + + drm_handle_t depth_handle; + int depth_offset; + int depth_size; + + drm_handle_t tex_handle; + int tex_offset; + int tex_size; + int log_tex_granularity; + int pitch; + int rotation; /* 0, 90, 180 or 270 */ + int rotated_offset; + int rotated_size; + int rotated_pitch; + int virtualX, virtualY; + + unsigned int front_tiled; + unsigned int back_tiled; + unsigned int depth_tiled; + unsigned int rotated_tiled; + unsigned int rotated2_tiled; + + int pipeA_x; + int pipeA_y; + int pipeA_w; + int pipeA_h; + int pipeB_x; + int pipeB_y; + int pipeB_w; + int pipeB_h; + + /* fill out some space for old userspace triple buffer */ + drm_handle_t unused_handle; + __u32 unused1, unused2, unused3; + + /* buffer object handles for static buffers. May change + * over the lifetime of the client. + */ + __u32 front_bo_handle; + __u32 back_bo_handle; + __u32 unused_bo_handle; + __u32 depth_bo_handle; + +} drm_i915_sarea_t; + +/* due to userspace building against these headers we need some compat here */ +#define planeA_x pipeA_x +#define planeA_y pipeA_y +#define planeA_w pipeA_w +#define planeA_h pipeA_h +#define planeB_x pipeB_x +#define planeB_y pipeB_y +#define planeB_w pipeB_w +#define planeB_h pipeB_h + +/* Flags for perf_boxes + */ +#define I915_BOX_RING_EMPTY 0x1 +#define I915_BOX_FLIP 0x2 +#define I915_BOX_WAIT 0x4 +#define I915_BOX_TEXTURE_LOAD 0x8 +#define I915_BOX_LOST_CONTEXT 0x10 + +/* I915 specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_I915_INIT 0x00 +#define DRM_I915_FLUSH 0x01 +#define DRM_I915_FLIP 0x02 +#define DRM_I915_BATCHBUFFER 0x03 +#define DRM_I915_IRQ_EMIT 0x04 +#define DRM_I915_IRQ_WAIT 0x05 +#define DRM_I915_GETPARAM 0x06 +#define DRM_I915_SETPARAM 0x07 +#define DRM_I915_ALLOC 0x08 +#define DRM_I915_FREE 0x09 +#define DRM_I915_INIT_HEAP 0x0a +#define DRM_I915_CMDBUFFER 0x0b +#define DRM_I915_DESTROY_HEAP 0x0c +#define DRM_I915_SET_VBLANK_PIPE 0x0d +#define DRM_I915_GET_VBLANK_PIPE 0x0e +#define DRM_I915_VBLANK_SWAP 0x0f +#define DRM_I915_HWS_ADDR 0x11 +#define DRM_I915_GEM_INIT 0x13 +#define DRM_I915_GEM_EXECBUFFER 0x14 +#define DRM_I915_GEM_PIN 0x15 +#define DRM_I915_GEM_UNPIN 0x16 +#define DRM_I915_GEM_BUSY 0x17 +#define DRM_I915_GEM_THROTTLE 0x18 +#define DRM_I915_GEM_ENTERVT 0x19 +#define DRM_I915_GEM_LEAVEVT 0x1a +#define DRM_I915_GEM_CREATE 0x1b +#define DRM_I915_GEM_PREAD 0x1c +#define DRM_I915_GEM_PWRITE 0x1d +#define DRM_I915_GEM_MMAP 0x1e +#define DRM_I915_GEM_SET_DOMAIN 0x1f +#define DRM_I915_GEM_SW_FINISH 0x20 +#define DRM_I915_GEM_SET_TILING 0x21 +#define DRM_I915_GEM_GET_TILING 0x22 +#define DRM_I915_GEM_GET_APERTURE 0x23 +#define DRM_I915_GEM_MMAP_GTT 0x24 +#define DRM_I915_GET_PIPE_FROM_CRTC_ID 0x25 +#define DRM_I915_GEM_MADVISE 0x26 +#define DRM_I915_OVERLAY_PUT_IMAGE 0x27 +#define DRM_I915_OVERLAY_ATTRS 0x28 + +#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) +#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) +#define DRM_IOCTL_I915_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP) +#define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t) +#define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t) +#define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t) +#define DRM_IOCTL_I915_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t) +#define DRM_IOCTL_I915_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SETPARAM, drm_i915_setparam_t) +#define DRM_IOCTL_I915_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_ALLOC, drm_i915_mem_alloc_t) +#define DRM_IOCTL_I915_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t) +#define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t) +#define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t) +#define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) +#define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) +#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) +#define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) +#define DRM_IOCTL_I915_GEM_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init) +#define DRM_IOCTL_I915_GEM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer) +#define DRM_IOCTL_I915_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin) +#define DRM_IOCTL_I915_GEM_UNPIN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin) +#define DRM_IOCTL_I915_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy) +#define DRM_IOCTL_I915_GEM_THROTTLE DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE) +#define DRM_IOCTL_I915_GEM_ENTERVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT) +#define DRM_IOCTL_I915_GEM_LEAVEVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT) +#define DRM_IOCTL_I915_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create) +#define DRM_IOCTL_I915_GEM_PREAD DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread) +#define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite) +#define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap) +#define DRM_IOCTL_I915_GEM_MMAP_GTT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt) +#define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain) +#define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish) +#define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling) +#define DRM_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling) +#define DRM_IOCTL_I915_GEM_GET_APERTURE DRM_IOR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture) +#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_i915_get_pipe_from_crtc_id) +#define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise) +#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_IOCTL_I915_OVERLAY_ATTRS, struct drm_intel_overlay_put_image) +#define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) + +/* Allow drivers to submit batchbuffers directly to hardware, relying + * on the security mechanisms provided by hardware. + */ +typedef struct drm_i915_batchbuffer { + int start; /* agp offset */ + int used; /* nr bytes in use */ + int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ + int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */ + int num_cliprects; /* mulitpass with multiple cliprects? */ + struct drm_clip_rect *cliprects; /* pointer to userspace cliprects */ +} drm_i915_batchbuffer_t; + +/* As above, but pass a pointer to userspace buffer which can be + * validated by the kernel prior to sending to hardware. + */ +typedef struct _drm_i915_cmdbuffer { + char *buf; /* pointer to userspace command buffer */ + int sz; /* nr bytes in buf */ + int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ + int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */ + int num_cliprects; /* mulitpass with multiple cliprects? */ + struct drm_clip_rect *cliprects; /* pointer to userspace cliprects */ +} drm_i915_cmdbuffer_t; + +/* Userspace can request & wait on irq's: + */ +typedef struct drm_i915_irq_emit { + int *irq_seq; +} drm_i915_irq_emit_t; + +typedef struct drm_i915_irq_wait { + int irq_seq; +} drm_i915_irq_wait_t; + +/* Ioctl to query kernel params: + */ +#define I915_PARAM_IRQ_ACTIVE 1 +#define I915_PARAM_ALLOW_BATCHBUFFER 2 +#define I915_PARAM_LAST_DISPATCH 3 +#define I915_PARAM_CHIPSET_ID 4 +#define I915_PARAM_HAS_GEM 5 +#define I915_PARAM_NUM_FENCES_AVAIL 6 +#define I915_PARAM_HAS_OVERLAY 7 ++#define I915_PARAM_HAS_PAGEFLIPPING 8 + +typedef struct drm_i915_getparam { + int param; + int *value; +} drm_i915_getparam_t; + +/* Ioctl to set kernel params: + */ +#define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1 +#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2 +#define I915_SETPARAM_ALLOW_BATCHBUFFER 3 +#define I915_SETPARAM_NUM_USED_FENCES 4 + +typedef struct drm_i915_setparam { + int param; + int value; +} drm_i915_setparam_t; + +/* A memory manager for regions of shared memory: + */ +#define I915_MEM_REGION_AGP 1 + +typedef struct drm_i915_mem_alloc { + int region; + int alignment; + int size; + int *region_offset; /* offset from start of fb or agp */ +} drm_i915_mem_alloc_t; + +typedef struct drm_i915_mem_free { + int region; + int region_offset; +} drm_i915_mem_free_t; + +typedef struct drm_i915_mem_init_heap { + int region; + int size; + int start; +} drm_i915_mem_init_heap_t; + +/* Allow memory manager to be torn down and re-initialized (eg on + * rotate): + */ +typedef struct drm_i915_mem_destroy_heap { + int region; +} drm_i915_mem_destroy_heap_t; + +/* Allow X server to configure which pipes to monitor for vblank signals + */ +#define DRM_I915_VBLANK_PIPE_A 1 +#define DRM_I915_VBLANK_PIPE_B 2 + +typedef struct drm_i915_vblank_pipe { + int pipe; +} drm_i915_vblank_pipe_t; + +/* Schedule buffer swap at given vertical blank: + */ +typedef struct drm_i915_vblank_swap { + drm_drawable_t drawable; + enum drm_vblank_seq_type seqtype; + unsigned int sequence; +} drm_i915_vblank_swap_t; + +typedef struct drm_i915_hws_addr { + __u64 addr; +} drm_i915_hws_addr_t; + +struct drm_i915_gem_init { + /** + * Beginning offset in the GTT to be managed by the DRM memory + * manager. + */ + __u64 gtt_start; + /** + * Ending offset in the GTT to be managed by the DRM memory + * manager. + */ + __u64 gtt_end; +}; + +struct drm_i915_gem_create { + /** + * Requested size for the object. + * + * The (page-aligned) allocated size for the object will be returned. + */ + __u64 size; + /** + * Returned handle for the object. + * + * Object handles are nonzero. + */ + __u32 handle; + __u32 pad; +}; + +struct drm_i915_gem_pread { + /** Handle for the object being read. */ + __u32 handle; + __u32 pad; + /** Offset into the object to read from */ + __u64 offset; + /** Length of data to read */ + __u64 size; + /** + * Pointer to write the data into. + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 data_ptr; +}; + +struct drm_i915_gem_pwrite { + /** Handle for the object being written to. */ + __u32 handle; + __u32 pad; + /** Offset into the object to write to */ + __u64 offset; + /** Length of data to write */ + __u64 size; + /** + * Pointer to read the data from. + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 data_ptr; +}; + +struct drm_i915_gem_mmap { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 pad; + /** Offset in the object to map. */ + __u64 offset; + /** + * Length of data to map. + * + * The value will be page-aligned. + */ + __u64 size; + /** + * Returned pointer the data was mapped at. + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 addr_ptr; +}; + +struct drm_i915_gem_mmap_gtt { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 pad; + /** + * Fake offset to use for subsequent mmap call + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 offset; +}; + +struct drm_i915_gem_set_domain { + /** Handle for the object */ + __u32 handle; + + /** New read domains */ + __u32 read_domains; + + /** New write domain */ + __u32 write_domain; +}; + +struct drm_i915_gem_sw_finish { + /** Handle for the object */ + __u32 handle; +}; + +struct drm_i915_gem_relocation_entry { + /** + * Handle of the buffer being pointed to by this relocation entry. + * + * It's appealing to make this be an index into the mm_validate_entry + * list to refer to the buffer, but this allows the driver to create + * a relocation list for state buffers and not re-write it per + * exec using the buffer. + */ + __u32 target_handle; + + /** + * Value to be added to the offset of the target buffer to make up + * the relocation entry. + */ + __u32 delta; + + /** Offset in the buffer the relocation entry will be written into */ + __u64 offset; + + /** + * Offset value of the target buffer that the relocation entry was last + * written as. + * + * If the buffer has the same offset as last time, we can skip syncing + * and writing the relocation. This value is written back out by + * the execbuffer ioctl when the relocation is written. + */ + __u64 presumed_offset; + + /** + * Target memory domains read by this operation. + */ + __u32 read_domains; + + /** + * Target memory domains written by this operation. + * + * Note that only one domain may be written by the whole + * execbuffer operation, so that where there are conflicts, + * the application will get -EINVAL back. + */ + __u32 write_domain; +}; + +/** @{ + * Intel memory domains + * + * Most of these just align with the various caches in + * the system and are used to flush and invalidate as + * objects end up cached in different domains. + */ +/** CPU cache */ +#define I915_GEM_DOMAIN_CPU 0x00000001 +/** Render cache, used by 2D and 3D drawing */ +#define I915_GEM_DOMAIN_RENDER 0x00000002 +/** Sampler cache, used by texture engine */ +#define I915_GEM_DOMAIN_SAMPLER 0x00000004 +/** Command queue, used to load batch buffers */ +#define I915_GEM_DOMAIN_COMMAND 0x00000008 +/** Instruction cache, used by shader programs */ +#define I915_GEM_DOMAIN_INSTRUCTION 0x00000010 +/** Vertex address cache */ +#define I915_GEM_DOMAIN_VERTEX 0x00000020 +/** GTT domain - aperture and scanout */ +#define I915_GEM_DOMAIN_GTT 0x00000040 +/** @} */ + +struct drm_i915_gem_exec_object { + /** + * User's handle for a buffer to be bound into the GTT for this + * operation. + */ + __u32 handle; + + /** Number of relocations to be performed on this buffer */ + __u32 relocation_count; + /** + * Pointer to array of struct drm_i915_gem_relocation_entry containing + * the relocations to be performed in this buffer. + */ + __u64 relocs_ptr; + + /** Required alignment in graphics aperture */ + __u64 alignment; + + /** + * Returned value of the updated offset of the object, for future + * presumed_offset writes. + */ + __u64 offset; +}; + +struct drm_i915_gem_execbuffer { + /** + * List of buffers to be validated with their relocations to be + * performend on them. + * + * This is a pointer to an array of struct drm_i915_gem_validate_entry. + * + * These buffers must be listed in an order such that all relocations + * a buffer is performing refer to buffers that have already appeared + * in the validate list. + */ + __u64 buffers_ptr; + __u32 buffer_count; + + /** Offset in the batchbuffer to start execution from. */ + __u32 batch_start_offset; + /** Bytes used in batchbuffer from batch_start_offset */ + __u32 batch_len; + __u32 DR1; + __u32 DR4; + __u32 num_cliprects; + /** This is a struct drm_clip_rect *cliprects */ + __u64 cliprects_ptr; +}; + +struct drm_i915_gem_pin { + /** Handle of the buffer to be pinned. */ + __u32 handle; + __u32 pad; + + /** alignment required within the aperture */ + __u64 alignment; + + /** Returned GTT offset of the buffer. */ + __u64 offset; +}; + +struct drm_i915_gem_unpin { + /** Handle of the buffer to be unpinned. */ + __u32 handle; + __u32 pad; +}; + +struct drm_i915_gem_busy { + /** Handle of the buffer to check for busy */ + __u32 handle; + + /** Return busy status (1 if busy, 0 if idle) */ + __u32 busy; +}; + +#define I915_TILING_NONE 0 +#define I915_TILING_X 1 +#define I915_TILING_Y 2 + +#define I915_BIT_6_SWIZZLE_NONE 0 +#define I915_BIT_6_SWIZZLE_9 1 +#define I915_BIT_6_SWIZZLE_9_10 2 +#define I915_BIT_6_SWIZZLE_9_11 3 +#define I915_BIT_6_SWIZZLE_9_10_11 4 +/* Not seen by userland */ +#define I915_BIT_6_SWIZZLE_UNKNOWN 5 +/* Seen by userland. */ +#define I915_BIT_6_SWIZZLE_9_17 6 +#define I915_BIT_6_SWIZZLE_9_10_17 7 + +struct drm_i915_gem_set_tiling { + /** Handle of the buffer to have its tiling state updated */ + __u32 handle; + + /** + * Tiling mode for the object (I915_TILING_NONE, I915_TILING_X, + * I915_TILING_Y). + * + * This value is to be set on request, and will be updated by the + * kernel on successful return with the actual chosen tiling layout. + * + * The tiling mode may be demoted to I915_TILING_NONE when the system + * has bit 6 swizzling that can't be managed correctly by GEM. + * + * Buffer contents become undefined when changing tiling_mode. + */ + __u32 tiling_mode; + + /** + * Stride in bytes for the object when in I915_TILING_X or + * I915_TILING_Y. + */ + __u32 stride; + + /** + * Returned address bit 6 swizzling required for CPU access through + * mmap mapping. + */ + __u32 swizzle_mode; +}; + +struct drm_i915_gem_get_tiling { + /** Handle of the buffer to get tiling state for. */ + __u32 handle; + + /** + * Current tiling mode for the object (I915_TILING_NONE, I915_TILING_X, + * I915_TILING_Y). + */ + __u32 tiling_mode; + + /** + * Returned address bit 6 swizzling required for CPU access through + * mmap mapping. + */ + __u32 swizzle_mode; +}; + +struct drm_i915_gem_get_aperture { + /** Total size of the aperture used by i915_gem_execbuffer, in bytes */ + __u64 aper_size; + + /** + * Available space in the aperture used by i915_gem_execbuffer, in + * bytes + */ + __u64 aper_available_size; +}; + +struct drm_i915_get_pipe_from_crtc_id { + /** ID of CRTC being requested **/ + __u32 crtc_id; + + /** pipe of requested CRTC **/ + __u32 pipe; +}; + +#define I915_MADV_WILLNEED 0 +#define I915_MADV_DONTNEED 1 +#define __I915_MADV_PURGED 2 /* internal state */ + +struct drm_i915_gem_madvise { + /** Handle of the buffer to change the backing store advice */ + __u32 handle; + + /* Advice: either the buffer will be needed again in the near future, + * or wont be and could be discarded under memory pressure. + */ + __u32 madv; + + /** Whether the backing store still exists. */ + __u32 retained; +}; + +/* flags */ +#define I915_OVERLAY_TYPE_MASK 0xff +#define I915_OVERLAY_YUV_PLANAR 0x01 +#define I915_OVERLAY_YUV_PACKED 0x02 +#define I915_OVERLAY_RGB 0x03 + +#define I915_OVERLAY_DEPTH_MASK 0xff00 +#define I915_OVERLAY_RGB24 0x1000 +#define I915_OVERLAY_RGB16 0x2000 +#define I915_OVERLAY_RGB15 0x3000 +#define I915_OVERLAY_YUV422 0x0100 +#define I915_OVERLAY_YUV411 0x0200 +#define I915_OVERLAY_YUV420 0x0300 +#define I915_OVERLAY_YUV410 0x0400 + +#define I915_OVERLAY_SWAP_MASK 0xff0000 +#define I915_OVERLAY_NO_SWAP 0x000000 +#define I915_OVERLAY_UV_SWAP 0x010000 +#define I915_OVERLAY_Y_SWAP 0x020000 +#define I915_OVERLAY_Y_AND_UV_SWAP 0x030000 + +#define I915_OVERLAY_FLAGS_MASK 0xff000000 +#define I915_OVERLAY_ENABLE 0x01000000 + +struct drm_intel_overlay_put_image { + /* various flags and src format description */ + __u32 flags; + /* source picture description */ + __u32 bo_handle; + /* stride values and offsets are in bytes, buffer relative */ + __u16 stride_Y; /* stride for packed formats */ + __u16 stride_UV; + __u32 offset_Y; /* offset for packet formats */ + __u32 offset_U; + __u32 offset_V; + /* in pixels */ + __u16 src_width; + __u16 src_height; + /* to compensate the scaling factors for partially covered surfaces */ + __u16 src_scan_width; + __u16 src_scan_height; + /* output crtc description */ + __u32 crtc_id; + __u16 dst_x; + __u16 dst_y; + __u16 dst_width; + __u16 dst_height; +}; + +/* flags */ +#define I915_OVERLAY_UPDATE_ATTRS (1<<0) +#define I915_OVERLAY_UPDATE_GAMMA (1<<1) +struct drm_intel_overlay_attrs { + __u32 flags; + __u32 color_key; + __s32 brightness; + __u32 contrast; + __u32 saturation; + __u32 gamma0; + __u32 gamma1; + __u32 gamma2; + __u32 gamma3; + __u32 gamma4; + __u32 gamma5; +}; + +#endif /* _I915_DRM_H_ */ diff --cc xf86drm.h index 496d95d,0000000..89f1db1 mode 100644,000000..100644 --- a/xf86drm.h +++ b/xf86drm.h @@@ -1,716 -1,0 +1,722 @@@ +/** + * \file xf86drm.h + * OS-independent header for DRM user-level library interface. + * + * \author Rickard E. (Rik) Faith <fa...@va...> + */ + +/* + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to ... [truncated message content] |
From: <wal...@ke...> - 2010-02-28 03:04:16
|
configure.ac | 3 libkms/Makefile.am | 4 libkms/intel.c | 2 libkms/internal.h | 2 libkms/linux.c | 4 libkms/nouveau.c | 220 ++++++++++++++++++++++++++++++++++++++++++++ tests/kmstest/main.c | 1 tests/modeprint/modeprint.c | 4 tests/modetest/modetest.c | 10 +- xf86drmMode.h | 2 10 files changed, 242 insertions(+), 10 deletions(-) New commits: commit 9a37455b35d746d694760cfe8850a8bf856d73c9 Author: Marcin KoÅcielnicki <kor...@0x...> Date: Sat Feb 27 15:04:40 2010 +0000 tests/modetest: Don't get_props on a connector after freeing it. diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index faad0b7..c12699c 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -206,10 +206,10 @@ void dump_connectors(void) for (j = 0; j < connector->count_modes; j++) dump_mode(&connector->modes[j]); - drmModeFreeConnector(connector); - printf(" props:\n"); dump_props(connector); + + drmModeFreeConnector(connector); } printf("\n"); } commit 694ef59532253727176ed0ce9077ae3ec41dd457 Author: Marcin KoÅcielnicki <kor...@0x...> Date: Sat Feb 27 15:04:42 2010 +0000 tests: vrefresh is actually not * 1000. diff --git a/tests/modeprint/modeprint.c b/tests/modeprint/modeprint.c index 8971914..4c612f4 100644 --- a/tests/modeprint/modeprint.c +++ b/tests/modeprint/modeprint.c @@ -81,8 +81,8 @@ int printMode(struct drm_mode_modeinfo *mode) printf("\tvrefresh : %i\n", mode->vrefresh); printf("\tflags : %i\n", mode->flags); } else { - printf("Mode: \"%s\" %ix%i %.0f\n", mode->name, - mode->hdisplay, mode->vdisplay, mode->vrefresh / 1000.0); + printf("Mode: \"%s\" %ix%i %i\n", mode->name, + mode->hdisplay, mode->vdisplay, mode->vrefresh); } return 0; } diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 124bf56..faad0b7 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -143,9 +143,9 @@ void dump_encoders(void) void dump_mode(drmModeModeInfo *mode) { - printf(" %s %.02f %d %d %d %d %d %d %d %d\n", + printf(" %s %d %d %d %d %d %d %d %d %d\n", mode->name, - (float)mode->vrefresh / 1000, + mode->vrefresh, mode->hdisplay, mode->hsync_start, mode->hsync_end, diff --git a/xf86drmMode.h b/xf86drmMode.h index 44d90ed..ee7c454 100644 --- a/xf86drmMode.h +++ b/xf86drmMode.h @@ -181,7 +181,7 @@ typedef struct _drmModeModeInfo { uint16_t hdisplay, hsync_start, hsync_end, htotal, hskew; uint16_t vdisplay, vsync_start, vsync_end, vtotal, vscan; - uint32_t vrefresh; /* vertical refresh * 1000 */ + uint32_t vrefresh; uint32_t flags; uint32_t type; commit ecb668e1efd30512d27f5bfc331e8e754b6e15ca Author: Marcin KoÅcielnicki <kor...@0x...> Date: Sat Feb 27 15:04:41 2010 +0000 tests: Add nouveau to list of supported modules. diff --git a/tests/kmstest/main.c b/tests/kmstest/main.c index 7aaeb75..5df0a38 100644 --- a/tests/kmstest/main.c +++ b/tests/kmstest/main.c @@ -59,6 +59,7 @@ int test_bo(struct kms_driver *kms) char *drivers[] = { "i915", "radeon", + "nouveau", "vmwgfx", NULL }; diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 26405f4..124bf56 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -680,7 +680,7 @@ int main(int argc, char **argv) int c; int encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0; int test_vsync = 0; - char *modules[] = { "i915", "radeon" }; + char *modules[] = { "i915", "radeon", "nouveau" }; char *modeset = NULL; int i, count = 0; struct connector con_args[2]; commit d5a2e776826f7a849f1cf654fde8611f687eb12c Author: Marcin KoÅcielnicki <kor...@0x...> Date: Sat Feb 27 16:02:25 2010 +0000 libkms/nouveau: Add support diff --git a/libkms/Makefile.am b/libkms/Makefile.am index e84deb1..0375ae4 100644 --- a/libkms/Makefile.am +++ b/libkms/Makefile.am @@ -21,6 +21,10 @@ if HAVE_VMWGFX libkms_la_SOURCES += vmwgfx.c endif +if HAVE_NOUVEAU +libkms_la_SOURCES += nouveau.c +endif + libkmsincludedir = ${includedir}/libkms libkmsinclude_HEADERS = libkms.h diff --git a/libkms/internal.h b/libkms/internal.h index 9d1c5f7..63122d1 100644 --- a/libkms/internal.h +++ b/libkms/internal.h @@ -68,4 +68,6 @@ int vmwgfx_create(int fd, struct kms_driver **out); int intel_create(int fd, struct kms_driver **out); +int nouveau_create(int fd, struct kms_driver **out); + #endif diff --git a/libkms/linux.c b/libkms/linux.c index 94e1b52..02182d3 100644 --- a/libkms/linux.c +++ b/libkms/linux.c @@ -107,6 +107,10 @@ linux_from_sysfs(int fd, struct kms_driver **out) else if (!strcmp(name, "vmwgfx")) ret = vmwgfx_create(fd, out); #endif +#ifdef HAVE_NOUVEAU + else if (!strcmp(name, "nouveau")) + ret = nouveau_create(fd, out); +#endif else ret = -ENOSYS; diff --git a/libkms/nouveau.c b/libkms/nouveau.c new file mode 100644 index 0000000..0e24a15 --- /dev/null +++ b/libkms/nouveau.c @@ -0,0 +1,220 @@ +/************************************************************************** + * + * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#define HAVE_STDINT_H +#define _FILE_OFFSET_BITS 64 + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "internal.h" + +#include <sys/mman.h> +#include <sys/ioctl.h> +#include "xf86drm.h" + +#include "nouveau_drm.h" + +struct nouveau_bo +{ + struct kms_bo base; + uint64_t map_handle; + unsigned map_count; +}; + +static int +nouveau_get_prop(struct kms_driver *kms, unsigned key, unsigned *out) +{ + switch (key) { + case KMS_BO_TYPE: + *out = KMS_BO_TYPE_SCANOUT_X8R8G8B8 | KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8; + break; + default: + return -EINVAL; + } + return 0; +} + +static int +nouveau_destroy(struct kms_driver *kms) +{ + free(kms); + return 0; +} + +static int +nouveau_bo_create(struct kms_driver *kms, + const unsigned width, const unsigned height, + const enum kms_bo_type type, const unsigned *attr, + struct kms_bo **out) +{ + struct drm_nouveau_gem_new arg; + unsigned size, pitch; + struct nouveau_bo *bo; + int i, ret; + + for (i = 0; attr[i]; i += 2) { + switch (attr[i]) { + case KMS_WIDTH: + case KMS_HEIGHT: + case KMS_BO_TYPE: + break; + default: + return -EINVAL; + } + } + + bo = calloc(1, sizeof(*bo)); + if (!bo) + return -ENOMEM; + + if (type == KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8) { + pitch = 64 * 4; + size = 64 * 64 * 4; + } else if (type == KMS_BO_TYPE_SCANOUT_X8R8G8B8) { + pitch = width * 4; + pitch = (pitch + 512 - 1) & ~(512 - 1); + size = pitch * height; + } else { + return -EINVAL; + } + + memset(&arg, 0, sizeof(arg)); + arg.info.size = size; + arg.info.domain = NOUVEAU_GEM_DOMAIN_MAPPABLE | NOUVEAU_GEM_DOMAIN_VRAM; + arg.info.tile_mode = 0; + arg.info.tile_flags = 0; + arg.align = 512; + arg.channel_hint = 0; + + ret = drmCommandWriteRead(kms->fd, DRM_NOUVEAU_GEM_NEW, &arg, sizeof(arg)); + if (ret) + goto err_free; + + bo->base.kms = kms; + bo->base.handle = arg.info.handle; + bo->base.size = size; + bo->base.pitch = pitch; + bo->map_handle = arg.info.map_handle; + + *out = &bo->base; + + return 0; + +err_free: + free(bo); + return ret; +} + +static int +nouveau_bo_get_prop(struct kms_bo *bo, unsigned key, unsigned *out) +{ + switch (key) { + default: + return -EINVAL; + } +} + +static int +nouveau_bo_map(struct kms_bo *_bo, void **out) +{ + struct nouveau_bo *bo = (struct nouveau_bo *)_bo; + void *map = NULL; + + if (bo->base.ptr) { + bo->map_count++; + *out = bo->base.ptr; + return 0; + } + + map = mmap(0, bo->base.size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->base.kms->fd, bo->map_handle); + if (map == MAP_FAILED) + return -errno; + + bo->base.ptr = map; + bo->map_count++; + *out = bo->base.ptr; + + return 0; +} + +static int +nouveau_bo_unmap(struct kms_bo *_bo) +{ + struct nouveau_bo *bo = (struct nouveau_bo *)_bo; + bo->map_count--; + return 0; +} + +static int +nouveau_bo_destroy(struct kms_bo *_bo) +{ + struct nouveau_bo *bo = (struct nouveau_bo *)_bo; + struct drm_gem_close arg; + int ret; + + if (bo->base.ptr) { + /* XXX Sanity check map_count */ + munmap(bo->base.ptr, bo->base.size); + bo->base.ptr = NULL; + } + + memset(&arg, 0, sizeof(arg)); + arg.handle = bo->base.handle; + + ret = drmIoctl(bo->base.kms->fd, DRM_IOCTL_GEM_CLOSE, &arg); + if (ret) + return -errno; + + free(bo); + return 0; +} + +int +nouveau_create(int fd, struct kms_driver **out) +{ + struct kms_driver *kms; + + kms = calloc(1, sizeof(*kms)); + if (!kms) + return -ENOMEM; + + kms->fd = fd; + + kms->bo_create = nouveau_bo_create; + kms->bo_map = nouveau_bo_map; + kms->bo_unmap = nouveau_bo_unmap; + kms->bo_get_prop = nouveau_bo_get_prop; + kms->bo_destroy = nouveau_bo_destroy; + kms->get_prop = nouveau_get_prop; + kms->destroy = nouveau_destroy; + *out = kms; + + return 0; +} commit 23f62721b707672816ad3461e11c7453ff75810f Author: Marcin KoÅcielnicki <kor...@0x...> Date: Sat Feb 27 15:04:38 2010 +0000 libkms/intel: Throw out unused intel_bo fields. Acked-by: Jakob Bornecrantz <ja...@vm...> diff --git a/libkms/intel.c b/libkms/intel.c index a1914f8..8b8249b 100644 --- a/libkms/intel.c +++ b/libkms/intel.c @@ -44,9 +44,7 @@ struct intel_bo { struct kms_bo base; - unsigned handle; unsigned map_count; - int mapped; }; static int commit afd74ec555a61d7006db90f0c038ff026e76d303 Author: Marcin KoÅcielnicki <kor...@0x...> Date: Sat Feb 27 15:04:37 2010 +0000 Add config.h macro HAVE_NOUVEAU diff --git a/configure.ac b/configure.ac index ef7700f..40634c5 100644 --- a/configure.ac +++ b/configure.ac @@ -154,6 +154,9 @@ if test "x$VMWGFX" = xyes; then fi AM_CONDITIONAL(HAVE_NOUVEAU, [test "x$NOUVEAU" = xyes]) +if test "x$NOUVEAU" = xyes; then + AC_DEFINE(HAVE_NOUVEAU, 1, [Have nouveau (nvidia) support]) +fi AM_CONDITIONAL(HAVE_RADEON, [test "x$RADEON" = xyes]) |
From: <gl...@ke...> - 2013-04-18 18:56:57
|
tests/modetest/buffers.c | 195 ++++++++++++++++++++++++++++++++++++---------- tests/modetest/modetest.c | 10 +- 2 files changed, 158 insertions(+), 47 deletions(-) New commits: commit 83e77461249d535a77c3ed055d198e26f0c1b390 Author: Ville Syrjälä <vil...@li...> Date: Thu Apr 18 15:26:59 2013 +0000 modetest: Add YUV420 support and fix YVU420 Cb/Cr ordering YUV420 support is trivial to add since the code already supports YVU420. But it looks like the YVU420 support is a bit broken. The chroma planes are passed in the wrong order to the fill functions, so fix that while were at it. Signed-off-by: Ville Syrjälä <vil...@li...> diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c index 2f3adf8..9b2bf72 100644 --- a/tests/modetest/buffers.c +++ b/tests/modetest/buffers.c @@ -100,6 +100,7 @@ static const struct format_info format_info[] = { { DRM_FORMAT_NV16, "NV16", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) }, { DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) }, /* YUV planar */ + { DRM_FORMAT_YUV420, "YU12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 1) }, { DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) }, /* RGB16 */ { DRM_FORMAT_ARGB4444, "AR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 4, 12) }, @@ -600,10 +601,14 @@ fill_smpte(const struct format_info *info, void *planes[3], unsigned int width, return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v, width, height, stride); - case DRM_FORMAT_YVU420: + case DRM_FORMAT_YUV420: return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1], planes[2], width, height, stride); + case DRM_FORMAT_YVU420: + return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2], + planes[1], width, height, stride); + case DRM_FORMAT_ARGB4444: case DRM_FORMAT_XRGB4444: case DRM_FORMAT_ABGR4444: @@ -863,10 +868,14 @@ fill_tiles(const struct format_info *info, void *planes[3], unsigned int width, return fill_tiles_yuv_planar(info, planes[0], u, v, width, height, stride); - case DRM_FORMAT_YVU420: + case DRM_FORMAT_YUV420: return fill_tiles_yuv_planar(info, planes[0], planes[1], planes[2], width, height, stride); + case DRM_FORMAT_YVU420: + return fill_tiles_yuv_planar(info, planes[0], planes[2], + planes[1], width, height, stride); + case DRM_FORMAT_ARGB4444: case DRM_FORMAT_XRGB4444: case DRM_FORMAT_ABGR4444: @@ -1055,6 +1064,7 @@ create_test_buffer(struct kms_driver *kms, unsigned int format, planes[1] = virtual + offsets[1]; break; + case DRM_FORMAT_YUV420: case DRM_FORMAT_YVU420: offsets[0] = 0; kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); commit 3f024f85d816a648473373bccc8ccc915951886a Author: Ville Syrjälä <vil...@li...> Date: Thu Apr 18 15:26:57 2013 +0000 modetest: Pass format_info to fill_tiles functions The fourcc is inside the format_info structure, so if we want to use it inside the various fill_tiles functions, we need to pass down the whole format_info, not just the rgb/yuv infos. Signed-off-by: Ville Syrjälä <vil...@li...> Acked-by: Laurent Pinchart <lau...@id...> diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c index b249f1f..2f3adf8 100644 --- a/tests/modetest/buffers.c +++ b/tests/modetest/buffers.c @@ -702,11 +702,12 @@ make_pwetty(void *data, int width, int height, int stride) } static void -fill_tiles_yuv_planar(const struct yuv_info *yuv, +fill_tiles_yuv_planar(const struct format_info *info, unsigned char *y_mem, unsigned char *u_mem, unsigned char *v_mem, unsigned int width, unsigned int height, unsigned int stride) { + const struct yuv_info *yuv = &info->yuv; unsigned int cs = yuv->chroma_stride; unsigned int xsub = yuv->xsub; unsigned int ysub = yuv->ysub; @@ -736,10 +737,11 @@ fill_tiles_yuv_planar(const struct yuv_info *yuv, } static void -fill_tiles_yuv_packed(const struct yuv_info *yuv, unsigned char *mem, +fill_tiles_yuv_packed(const struct format_info *info, unsigned char *mem, unsigned int width, unsigned int height, unsigned int stride) { + const struct yuv_info *yuv = &info->yuv; unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; @@ -768,9 +770,10 @@ fill_tiles_yuv_packed(const struct yuv_info *yuv, unsigned char *mem, } static void -fill_tiles_rgb16(const struct rgb_info *rgb, unsigned char *mem, +fill_tiles_rgb16(const struct format_info *info, unsigned char *mem, unsigned int width, unsigned int height, unsigned int stride) { + const struct rgb_info *rgb = &info->rgb; unsigned int x, y; for (y = 0; y < height; ++y) { @@ -790,9 +793,10 @@ fill_tiles_rgb16(const struct rgb_info *rgb, unsigned char *mem, } static void -fill_tiles_rgb24(const struct rgb_info *rgb, unsigned char *mem, +fill_tiles_rgb24(const struct format_info *info, unsigned char *mem, unsigned int width, unsigned int height, unsigned int stride) { + const struct rgb_info *rgb = &info->rgb; unsigned int x, y; for (y = 0; y < height; ++y) { @@ -811,9 +815,10 @@ fill_tiles_rgb24(const struct rgb_info *rgb, unsigned char *mem, } static void -fill_tiles_rgb32(const struct rgb_info *rgb, unsigned char *mem, +fill_tiles_rgb32(const struct format_info *info, unsigned char *mem, unsigned int width, unsigned int height, unsigned int stride) { + const struct rgb_info *rgb = &info->rgb; unsigned char *mem_base = mem; unsigned int x, y; @@ -846,7 +851,7 @@ fill_tiles(const struct format_info *info, void *planes[3], unsigned int width, case DRM_FORMAT_VYUY: case DRM_FORMAT_YUYV: case DRM_FORMAT_YVYU: - return fill_tiles_yuv_packed(&info->yuv, planes[0], + return fill_tiles_yuv_packed(info, planes[0], width, height, stride); case DRM_FORMAT_NV12: @@ -855,11 +860,11 @@ fill_tiles(const struct format_info *info, void *planes[3], unsigned int width, case DRM_FORMAT_NV61: u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; - return fill_tiles_yuv_planar(&info->yuv, planes[0], u, v, + return fill_tiles_yuv_planar(info, planes[0], u, v, width, height, stride); case DRM_FORMAT_YVU420: - return fill_tiles_yuv_planar(&info->yuv, planes[0], planes[1], + return fill_tiles_yuv_planar(info, planes[0], planes[1], planes[2], width, height, stride); case DRM_FORMAT_ARGB4444: @@ -880,12 +885,12 @@ fill_tiles(const struct format_info *info, void *planes[3], unsigned int width, case DRM_FORMAT_RGBX5551: case DRM_FORMAT_BGRA5551: case DRM_FORMAT_BGRX5551: - return fill_tiles_rgb16(&info->rgb, planes[0], + return fill_tiles_rgb16(info, planes[0], width, height, stride); case DRM_FORMAT_BGR888: case DRM_FORMAT_RGB888: - return fill_tiles_rgb24(&info->rgb, planes[0], + return fill_tiles_rgb24(info, planes[0], width, height, stride); case DRM_FORMAT_ARGB8888: case DRM_FORMAT_XRGB8888: @@ -903,7 +908,7 @@ fill_tiles(const struct format_info *info, void *planes[3], unsigned int width, case DRM_FORMAT_RGBX1010102: case DRM_FORMAT_BGRA1010102: case DRM_FORMAT_BGRX1010102: - return fill_tiles_rgb32(&info->rgb, planes[0], + return fill_tiles_rgb32(info, planes[0], width, height, stride); } } commit 2c26a106fcfb692badef4c42faaed46508a3d1d3 Author: Ville Syrjälä <vil...@li...> Date: Wed Apr 17 19:18:05 2013 +0000 modetest: Reduce the length of the connector type string Spelling out eDP or DP make for a ridicilously long string which plays havoc with formatting. Just say eDP or DP. Signed-off-by: Ville Syrjälä <vil...@li...> Acked-by: Laurent Pinchart <lau...@id...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 27cd2ce..8afd2b1 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -106,11 +106,11 @@ struct type_name connector_type_names[] = { { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, { DRM_MODE_CONNECTOR_Component, "component" }, { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, - { DRM_MODE_CONNECTOR_DisplayPort, "displayport" }, + { DRM_MODE_CONNECTOR_DisplayPort, "DP" }, { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" }, { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" }, { DRM_MODE_CONNECTOR_TV, "TV" }, - { DRM_MODE_CONNECTOR_eDP, "embedded displayport" }, + { DRM_MODE_CONNECTOR_eDP, "eDP" }, }; type_name_fn(connector_type) commit 8e56579b203a11c718c5e3da6fdb03b4f9b9fe56 Author: Ville Syrjälä <vil...@li...> Date: Wed Apr 17 19:18:04 2013 +0000 modetest: Print possible_crtcs for planes Signed-off-by: Ville Syrjälä <vil...@li...> Acked-by: Laurent Pinchart <lau...@id...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index c91bb9d..27cd2ce 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -429,7 +429,7 @@ static void dump_planes(void) } printf("Planes:\n"); - printf("id\tcrtc\tfb\tCRTC x,y\tx,y\tgamma size\n"); + printf("id\tcrtc\tfb\tCRTC x,y\tx,y\tgamma size\tpossible crtcs\n"); for (i = 0; i < plane_resources->count_planes; i++) { ovr = drmModeGetPlane(fd, plane_resources->planes[i]); if (!ovr) { @@ -438,10 +438,10 @@ static void dump_planes(void) continue; } - printf("%d\t%d\t%d\t%d,%d\t\t%d,%d\t%d\n", + printf("%d\t%d\t%d\t%d,%d\t\t%d,%d\t%-8d\t0x%08x\n", ovr->plane_id, ovr->crtc_id, ovr->fb_id, ovr->crtc_x, ovr->crtc_y, ovr->x, ovr->y, - ovr->gamma_size); + ovr->gamma_size, ovr->possible_crtcs); if (!ovr->count_formats) continue; commit fa2925aa342158037ef972f3ef095442fb1fe430 Author: Ville Syrjälä <vil...@li...> Date: Wed Apr 17 19:18:03 2013 +0000 modetest: Add support for all 16/32 bpp RGB formats Signed-off-by: Ville Syrjälä <vil...@li...> Acked-by: Laurent Pinchart <lau...@id...> diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c index 00269e8..b249f1f 100644 --- a/tests/modetest/buffers.c +++ b/tests/modetest/buffers.c @@ -102,17 +102,44 @@ static const struct format_info format_info[] = { /* YUV planar */ { DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) }, /* RGB16 */ + { DRM_FORMAT_ARGB4444, "AR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 4, 12) }, + { DRM_FORMAT_XRGB4444, "XR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 0, 0) }, + { DRM_FORMAT_ABGR4444, "AB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 4, 12) }, + { DRM_FORMAT_XBGR4444, "XB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 0, 0) }, + { DRM_FORMAT_RGBA4444, "RA12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 4, 0) }, + { DRM_FORMAT_RGBX4444, "RX12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 0, 0) }, + { DRM_FORMAT_BGRA4444, "BA12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 4, 0) }, + { DRM_FORMAT_BGRX4444, "BX12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 0, 0) }, { DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) }, { DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) }, + { DRM_FORMAT_ABGR1555, "AB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 1, 15) }, + { DRM_FORMAT_XBGR1555, "XB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 0, 0) }, + { DRM_FORMAT_RGBA5551, "RA15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 1, 0) }, + { DRM_FORMAT_RGBX5551, "RX15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 0, 0) }, + { DRM_FORMAT_BGRA5551, "BA15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 1, 0) }, + { DRM_FORMAT_BGRX5551, "BX15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 0, 0) }, { DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) }, + { DRM_FORMAT_BGR565, "BG16", MAKE_RGB_INFO(5, 0, 6, 5, 5, 11, 0, 0) }, /* RGB24 */ { DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) }, { DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) }, /* RGB32 */ { DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) }, - { DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) }, { DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) }, + { DRM_FORMAT_ABGR8888, "AB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 8, 24) }, + { DRM_FORMAT_XBGR8888, "XB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) }, + { DRM_FORMAT_RGBA8888, "RA24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 8, 0) }, + { DRM_FORMAT_RGBX8888, "RX24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 0, 0) }, + { DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) }, { DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) }, + { DRM_FORMAT_ARGB2101010, "AR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 2, 30) }, + { DRM_FORMAT_XRGB2101010, "XR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 0, 0) }, + { DRM_FORMAT_ABGR2101010, "AB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 2, 30) }, + { DRM_FORMAT_XBGR2101010, "XB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 0, 0) }, + { DRM_FORMAT_RGBA1010102, "RA30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 2, 0) }, + { DRM_FORMAT_RGBX1010102, "RX30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 0, 0) }, + { DRM_FORMAT_BGRA1010102, "BA30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 2, 0) }, + { DRM_FORMAT_BGRX1010102, "BX30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 0, 0) }, }; unsigned int format_fourcc(const char *name) @@ -577,19 +604,47 @@ fill_smpte(const struct format_info *info, void *planes[3], unsigned int width, return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1], planes[2], width, height, stride); + case DRM_FORMAT_ARGB4444: + case DRM_FORMAT_XRGB4444: + case DRM_FORMAT_ABGR4444: + case DRM_FORMAT_XBGR4444: + case DRM_FORMAT_RGBA4444: + case DRM_FORMAT_RGBX4444: + case DRM_FORMAT_BGRA4444: + case DRM_FORMAT_BGRX4444: case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: case DRM_FORMAT_ARGB1555: case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_XBGR1555: + case DRM_FORMAT_RGBA5551: + case DRM_FORMAT_RGBX5551: + case DRM_FORMAT_BGRA5551: + case DRM_FORMAT_BGRX5551: return fill_smpte_rgb16(&info->rgb, planes[0], width, height, stride); + case DRM_FORMAT_BGR888: case DRM_FORMAT_RGB888: return fill_smpte_rgb24(&info->rgb, planes[0], width, height, stride); case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_BGRA8888: case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRA8888: case DRM_FORMAT_BGRX8888: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_RGBA1010102: + case DRM_FORMAT_RGBX1010102: + case DRM_FORMAT_BGRA1010102: + case DRM_FORMAT_BGRX1010102: return fill_smpte_rgb32(&info->rgb, planes[0], width, height, stride); } @@ -807,19 +862,47 @@ fill_tiles(const struct format_info *info, void *planes[3], unsigned int width, return fill_tiles_yuv_planar(&info->yuv, planes[0], planes[1], planes[2], width, height, stride); + case DRM_FORMAT_ARGB4444: + case DRM_FORMAT_XRGB4444: + case DRM_FORMAT_ABGR4444: + case DRM_FORMAT_XBGR4444: + case DRM_FORMAT_RGBA4444: + case DRM_FORMAT_RGBX4444: + case DRM_FORMAT_BGRA4444: + case DRM_FORMAT_BGRX4444: case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: case DRM_FORMAT_ARGB1555: case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_XBGR1555: + case DRM_FORMAT_RGBA5551: + case DRM_FORMAT_RGBX5551: + case DRM_FORMAT_BGRA5551: + case DRM_FORMAT_BGRX5551: return fill_tiles_rgb16(&info->rgb, planes[0], width, height, stride); + case DRM_FORMAT_BGR888: case DRM_FORMAT_RGB888: return fill_tiles_rgb24(&info->rgb, planes[0], width, height, stride); case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_BGRA8888: case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRA8888: case DRM_FORMAT_BGRX8888: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_RGBA1010102: + case DRM_FORMAT_RGBX1010102: + case DRM_FORMAT_BGRA1010102: + case DRM_FORMAT_BGRX1010102: return fill_tiles_rgb32(&info->rgb, planes[0], width, height, stride); } @@ -983,15 +1066,42 @@ create_test_buffer(struct kms_driver *kms, unsigned int format, planes[2] = virtual + offsets[2]; break; - case DRM_FORMAT_RGB565: + case DRM_FORMAT_ARGB4444: + case DRM_FORMAT_XRGB4444: + case DRM_FORMAT_ABGR4444: + case DRM_FORMAT_XBGR4444: + case DRM_FORMAT_RGBA4444: + case DRM_FORMAT_RGBX4444: + case DRM_FORMAT_BGRA4444: + case DRM_FORMAT_BGRX4444: case DRM_FORMAT_ARGB1555: case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_XBGR1555: + case DRM_FORMAT_RGBA5551: + case DRM_FORMAT_RGBX5551: + case DRM_FORMAT_BGRA5551: + case DRM_FORMAT_BGRX5551: + case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: case DRM_FORMAT_BGR888: case DRM_FORMAT_RGB888: case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_BGRA8888: case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRA8888: case DRM_FORMAT_BGRX8888: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_RGBA1010102: + case DRM_FORMAT_RGBX1010102: + case DRM_FORMAT_BGRA1010102: + case DRM_FORMAT_BGRX1010102: offsets[0] = 0; kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); kms_bo_get_prop(bo, KMS_PITCH, &pitches[0]); commit c2988eb211ecad2db60081f1000cf19b350703db Author: Ville Syrjälä <vil...@li...> Date: Wed Apr 17 19:18:02 2013 +0000 modetest: Fix pitches, somewhat libkms only has the xrgb8888 format, so we're overallocating the bo by quite a lot in some cases. But we still need to get the pitch from the libkms since it's the driver that decides how to align it. Signed-off-by: Ville Syrjälä <vil...@li...> Acked-by: Laurent Pinchart <lau...@id...> diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c index 5086381..00269e8 100644 --- a/tests/modetest/buffers.c +++ b/tests/modetest/buffers.c @@ -945,9 +945,9 @@ create_test_buffer(struct kms_driver *kms, unsigned int format, case DRM_FORMAT_VYUY: case DRM_FORMAT_YUYV: case DRM_FORMAT_YVYU: - pitches[0] = width * 2; offsets[0] = 0; kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); + kms_bo_get_prop(bo, KMS_PITCH, &pitches[0]); planes[0] = virtual; break; @@ -956,11 +956,11 @@ create_test_buffer(struct kms_driver *kms, unsigned int format, case DRM_FORMAT_NV21: case DRM_FORMAT_NV16: case DRM_FORMAT_NV61: - pitches[0] = width; offsets[0] = 0; kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); - pitches[1] = width; - offsets[1] = width * height; + kms_bo_get_prop(bo, KMS_PITCH, &pitches[0]); + pitches[1] = pitches[0]; + offsets[1] = pitches[0] * height; kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]); planes[0] = virtual; @@ -968,14 +968,14 @@ create_test_buffer(struct kms_driver *kms, unsigned int format, break; case DRM_FORMAT_YVU420: - pitches[0] = width; offsets[0] = 0; kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); - pitches[1] = width / 2; - offsets[1] = width * height; + kms_bo_get_prop(bo, KMS_PITCH, &pitches[0]); + pitches[1] = pitches[0] / 2; + offsets[1] = pitches[0] * height; kms_bo_get_prop(bo, KMS_HANDLE, &handles[1]); - pitches[2] = width / 2; - offsets[2] = offsets[1] + (width * height) / 4; + pitches[2] = pitches[1]; + offsets[2] = offsets[1] + pitches[1] * height / 2; kms_bo_get_prop(bo, KMS_HANDLE, &handles[2]); planes[0] = virtual; @@ -986,29 +986,15 @@ create_test_buffer(struct kms_driver *kms, unsigned int format, case DRM_FORMAT_RGB565: case DRM_FORMAT_ARGB1555: case DRM_FORMAT_XRGB1555: - pitches[0] = width * 2; - offsets[0] = 0; - kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); - - planes[0] = virtual; - break; - case DRM_FORMAT_BGR888: case DRM_FORMAT_RGB888: - pitches[0] = width * 3; - offsets[0] = 0; - kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); - - planes[0] = virtual; - break; - case DRM_FORMAT_ARGB8888: case DRM_FORMAT_BGRA8888: case DRM_FORMAT_XRGB8888: case DRM_FORMAT_BGRX8888: - pitches[0] = width * 4; offsets[0] = 0; kms_bo_get_prop(bo, KMS_HANDLE, &handles[0]); + kms_bo_get_prop(bo, KMS_PITCH, &pitches[0]); planes[0] = virtual; break; |
From: <rob...@ke...> - 2013-08-30 19:32:17
|
freedreno/Makefile.am | 2 ++ freedreno/freedreno_priv.h | 2 +- freedreno/msm/msm_drm.h | 2 +- intel/libdrm_intel.pc.in | 4 ++-- tests/getversion.c | 1 + tests/modetest/modetest.c | 8 ++++---- tests/setversion.c | 1 + tests/vbltest/vbltest.c | 2 +- 8 files changed, 13 insertions(+), 9 deletions(-) New commits: commit d18cd0c7ccf88c9f6585aaa3cc57f0f064d7310b Author: Emil Velikov <emi...@gm...> Date: Thu Aug 29 21:31:54 2013 +0100 intel: Update package name and description in libdrm_intel.pc Currently the package name and description duplicate that of the core libdrm. Update those to reflect reality. Cc: Daniel Vetter <dan...@ff...> Signed-off-by: Emil Velikov <emi...@gm...> Reviewed-by: Damien Lespiau <dam...@in...> diff --git a/intel/libdrm_intel.pc.in b/intel/libdrm_intel.pc.in index 3ba6793..670e4fe 100644 --- a/intel/libdrm_intel.pc.in +++ b/intel/libdrm_intel.pc.in @@ -3,8 +3,8 @@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ -Name: libdrm -Description: Userspace interface to kernel DRM services +Name: libdrm_intel +Description: Userspace interface to intel kernel DRM services Version: @PACKAGE_VERSION@ Requires: libdrm Libs: -L${libdir} -ldrm_intel commit db6a1b07d06ad7b663f28291a6be8226bd05d421 Author: Emil Velikov <emi...@gm...> Date: Thu Aug 29 21:31:53 2013 +0100 freedreno: set automake options to include subdir-objects Handles automake complains about lack of forward-compatibility, due to the source files in the kgsl and msm backends/folders. Cc: Rob Clark <rob...@fr...> Signed-off-by: Emil Velikov <emi...@gm...> diff --git a/freedreno/Makefile.am b/freedreno/Makefile.am index ec7e359..7903e5b 100644 --- a/freedreno/Makefile.am +++ b/freedreno/Makefile.am @@ -1,3 +1,5 @@ +AUTOMAKE_OPTIONS=subdir-objects + AM_CFLAGS = \ $(WARN_CFLAGS) \ -I$(top_srcdir) \ commit 126c45828aa3eaf1f404a4fc65a09a93fda76467 Author: Emil Velikov <emi...@gm...> Date: Thu Aug 29 21:31:52 2013 +0100 freedreno: use local drm.h over the system one Otherwise build will fail, as drm/drm.h is not available. Cc: Rob Clark <rob...@fr...> Signed-off-by: Emil Velikov <emi...@gm...> diff --git a/freedreno/freedreno_priv.h b/freedreno/freedreno_priv.h index b10ac90..69256f5 100644 --- a/freedreno/freedreno_priv.h +++ b/freedreno/freedreno_priv.h @@ -48,7 +48,7 @@ #include "freedreno_drmif.h" #include "freedreno_ringbuffer.h" -#include "drm/drm.h" +#include "drm.h" struct fd_device_funcs { int (*bo_new_handle)(struct fd_device *dev, uint32_t size, diff --git a/freedreno/msm/msm_drm.h b/freedreno/msm/msm_drm.h index d3c6207..090c724 100644 --- a/freedreno/msm/msm_drm.h +++ b/freedreno/msm/msm_drm.h @@ -19,7 +19,7 @@ #define __MSM_DRM_H__ #include <stddef.h> -#include <drm/drm.h> +#include "drm.h" /* Please note that modifications to all structs defined here are * subject to backwards-compatibility constraints: commit 4a8da02e524d5d70ec638477e36fcafd2c8152ec Author: Emil Velikov <emi...@gm...> Date: Thu Aug 29 21:31:51 2013 +0100 tests/modetest: silence compiler warning about uninitialised variables The compiler is unaware of that we have at least one crts/connector/plane thus it complains that some of our variables will be used uninitialised. Signed-off-by: Emil Velikov <emi...@gm...> Reviewed-by: Rob Clark <rob...@gm...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 79b4f04..f0ed56b 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -781,7 +781,7 @@ static struct crtc *pipe_find_crtc(struct device *dev, struct pipe_arg *pipe) static int pipe_find_crtc_and_mode(struct device *dev, struct pipe_arg *pipe) { - drmModeModeInfo *mode; + drmModeModeInfo *mode = NULL; int i; pipe->mode = NULL; @@ -838,8 +838,8 @@ struct property_arg { static void set_property(struct device *dev, struct property_arg *p) { - drmModeObjectProperties *props; - drmModePropertyRes **props_info; + drmModeObjectProperties *props = NULL; + drmModePropertyRes **props_info = NULL; const char *obj_type; int ret; int i; commit 0100473de648f29dd5abbd3fabd0f73c0bd5bfd5 Author: Emil Velikov <emi...@gm...> Date: Thu Aug 29 21:31:50 2013 +0100 tests/*version: add missing string.h header Prodives memset() and strlen(), used in tests/setversion tests/getversion respectively. Signed-off-by: Emil Velikov <emi...@gm...> Reviewed-by: Rob Clark <rob...@gm...> diff --git a/tests/getversion.c b/tests/getversion.c index 711d376..53d1d35 100644 --- a/tests/getversion.c +++ b/tests/getversion.c @@ -25,6 +25,7 @@ * */ +#include <string.h> #include "drmtest.h" /** diff --git a/tests/setversion.c b/tests/setversion.c index 3aaf7cc..5a5d01c 100644 --- a/tests/setversion.c +++ b/tests/setversion.c @@ -26,6 +26,7 @@ */ #include <limits.h> +#include <string.h> #include "drmtest.h" /** commit dba6bec3ab5ba966a6ee3527e711c51e47229f32 Author: Rob Clark <rob...@fr...> Date: Fri Aug 30 11:15:30 2013 -0400 tests: add msm Signed-off-by: Rob Clark <rob...@fr...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index f96b930..79b4f04 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -1356,7 +1356,7 @@ int main(int argc, char **argv) int encoders = 0, connectors = 0, crtcs = 0, planes = 0, framebuffers = 0; int drop_master = 0; int test_vsync = 0; - const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", "tilcdc" }; + const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", "tilcdc", "msm" }; char *module = NULL; unsigned int i; int count = 0, plane_count = 0; diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c index cf372d7..2a09d28 100644 --- a/tests/vbltest/vbltest.c +++ b/tests/vbltest/vbltest.c @@ -103,7 +103,7 @@ static void usage(char *name) int main(int argc, char **argv) { int i, c, fd, ret; - char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos", "omapdrm", "tilcdc" }; + char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos", "omapdrm", "tilcdc", "msm" }; drmVBlank vbl; drmEventContext evctx; struct vbl_info handler_info; |
From: <ta...@ke...> - 2014-11-27 16:22:39
|
Makefile.am | 6 Makefile.sources | 1 configure.ac | 14 + include/drm/tegra_drm.h | 200 ++++++++++++++++++++++++++ tegra/.gitignore | 1 tegra/Makefile.am | 23 +++ tegra/libdrm_tegra.pc.in | 11 + tegra/private.h | 51 ++++++ tegra/tegra.c | 345 ++++++++++++++++++++++++++++++++++++++++++++++ tegra/tegra.h | 60 ++++++++ tests/Makefile.am | 4 tests/modetest/modetest.c | 2 tests/tegra/.gitignore | 1 tests/tegra/Makefile.am | 13 + tests/tegra/openclose.c | 71 +++++++++ tests/vbltest/vbltest.c | 2 16 files changed, 802 insertions(+), 3 deletions(-) New commits: commit f99522e678dbbaffeca9462a8edcbe900574dc12 Author: Thierry Reding <tr...@nv...> Date: Thu Nov 27 15:32:43 2014 +0100 tegra: Implement drm_tegra_bo_{get,set}_tiling() These two functions are simple wrappers around the corresponding IOCTLs and operate on drm_tegra_bo objects. Signed-off-by: Thierry Reding <tr...@nv...> diff --git a/tegra/tegra.c b/tegra/tegra.c index 614ab96..f8d4078 100644 --- a/tegra/tegra.c +++ b/tegra/tegra.c @@ -292,3 +292,54 @@ int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags) return 0; } + +drm_public +int drm_tegra_bo_get_tiling(struct drm_tegra_bo *bo, + struct drm_tegra_bo_tiling *tiling) +{ + struct drm_tegra_gem_get_tiling args; + struct drm_tegra *drm = bo->drm; + int err; + + if (!bo) + return -EINVAL; + + memset(&args, 0, sizeof(args)); + args.handle = bo->handle; + + err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_GET_TILING, &args, + sizeof(args)); + if (err < 0) + return -errno; + + if (tiling) { + tiling->mode = args.mode; + tiling->value = args.value; + } + + return 0; +} + +drm_public +int drm_tegra_bo_set_tiling(struct drm_tegra_bo *bo, + const struct drm_tegra_bo_tiling *tiling) +{ + struct drm_tegra_gem_set_tiling args; + struct drm_tegra *drm = bo->drm; + int err; + + if (!bo) + return -EINVAL; + + memset(&args, 0, sizeof(args)); + args.handle = bo->handle; + args.mode = tiling->mode; + args.value = tiling->value; + + err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_TILING, &args, + sizeof(args)); + if (err < 0) + return -errno; + + return 0; +} diff --git a/tegra/tegra.h b/tegra/tegra.h index a862418..31b0995 100644 --- a/tegra/tegra.h +++ b/tegra/tegra.h @@ -47,4 +47,14 @@ int drm_tegra_bo_unmap(struct drm_tegra_bo *bo); int drm_tegra_bo_get_flags(struct drm_tegra_bo *bo, uint32_t *flags); int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags); +struct drm_tegra_bo_tiling { + uint32_t mode; + uint32_t value; +}; + +int drm_tegra_bo_get_tiling(struct drm_tegra_bo *bo, + struct drm_tegra_bo_tiling *tiling); +int drm_tegra_bo_set_tiling(struct drm_tegra_bo *bo, + const struct drm_tegra_bo_tiling *tiling); + #endif /* __DRM_TEGRA_H__ */ commit d3ad65db4215f5fb5419d78a14c12833d5ed150a Author: Thierry Reding <tr...@nv...> Date: Thu Nov 27 15:31:34 2014 +0100 tegra: Implement drm_tegra_bo_{get,set}_flags() These two functions are simple wrappers around the corresponding IOCTLs and operate on drm_tegra_bo objects. Signed-off-by: Thierry Reding <tr...@nv...> diff --git a/tegra/tegra.c b/tegra/tegra.c index ec5bf76..614ab96 100644 --- a/tegra/tegra.c +++ b/tegra/tegra.c @@ -246,3 +246,49 @@ int drm_tegra_bo_unmap(struct drm_tegra_bo *bo) return 0; } + +drm_public +int drm_tegra_bo_get_flags(struct drm_tegra_bo *bo, uint32_t *flags) +{ + struct drm_tegra_gem_get_flags args; + struct drm_tegra *drm = bo->drm; + int err; + + if (!bo) + return -EINVAL; + + memset(&args, 0, sizeof(args)); + args.handle = bo->handle; + + err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_GET_FLAGS, &args, + sizeof(args)); + if (err < 0) + return -errno; + + if (flags) + *flags = args.flags; + + return 0; +} + +drm_public +int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags) +{ + struct drm_tegra_gem_get_flags args; + struct drm_tegra *drm = bo->drm; + int err; + + if (!bo) + return -EINVAL; + + memset(&args, 0, sizeof(args)); + args.handle = bo->handle; + args.flags = flags; + + err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_FLAGS, &args, + sizeof(args)); + if (err < 0) + return -errno; + + return 0; +} diff --git a/tegra/tegra.h b/tegra/tegra.h index ed29505..a862418 100644 --- a/tegra/tegra.h +++ b/tegra/tegra.h @@ -44,4 +44,7 @@ int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle); int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr); int drm_tegra_bo_unmap(struct drm_tegra_bo *bo); +int drm_tegra_bo_get_flags(struct drm_tegra_bo *bo, uint32_t *flags); +int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags); + #endif /* __DRM_TEGRA_H__ */ commit 7b5e65268962d277c4e9e623d284150a715c541c Author: Thierry Reding <tr...@nv...> Date: Tue Jun 10 12:41:58 2014 +0200 tegra: Add SET/GET_FLAGS IOCTLs The DRM_TEGRA_GEM_SET_FLAGS IOCTL can be used to set the flags of a buffer object after it has been allocated or imported. Flags associated with a buffer object can be queried using the DRM_TEGRA_GEM_GET_FLAGS IOCTL. Signed-off-by: Thierry Reding <tr...@nv...> diff --git a/include/drm/tegra_drm.h b/include/drm/tegra_drm.h index 1c29129..8dae8f3 100644 --- a/include/drm/tegra_drm.h +++ b/include/drm/tegra_drm.h @@ -150,6 +150,23 @@ struct drm_tegra_gem_get_tiling { __u32 pad; }; +#define DRM_TEGRA_GEM_BOTTOM_UP (1 << 0) +#define DRM_TEGRA_GEM_FLAGS (DRM_TEGRA_GEM_BOTTOM_UP) + +struct drm_tegra_gem_set_flags { + /* input */ + __u32 handle; + /* output */ + __u32 flags; +}; + +struct drm_tegra_gem_get_flags { + /* input */ + __u32 handle; + /* output */ + __u32 flags; +}; + #define DRM_TEGRA_GEM_CREATE 0x00 #define DRM_TEGRA_GEM_MMAP 0x01 #define DRM_TEGRA_SYNCPT_READ 0x02 @@ -162,6 +179,8 @@ struct drm_tegra_gem_get_tiling { #define DRM_TEGRA_GET_SYNCPT_BASE 0x09 #define DRM_TEGRA_GEM_SET_TILING 0x0a #define DRM_TEGRA_GEM_GET_TILING 0x0b +#define DRM_TEGRA_GEM_SET_FLAGS 0x0c +#define DRM_TEGRA_GEM_GET_FLAGS 0x0d #define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create) #define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap) @@ -175,5 +194,7 @@ struct drm_tegra_gem_get_tiling { #define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base) #define DRM_IOCTL_TEGRA_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_TILING, struct drm_tegra_gem_set_tiling) #define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling) +#define DRM_IOCTL_TEGRA_GEM_SET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_FLAGS, struct drm_tegra_gem_set_flags) +#define DRM_IOCTL_TEGRA_GEM_GET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_FLAGS, struct drm_tegra_gem_get_flags) #endif commit 5ad2eef6eaed4ef90c25341a1c2278a0df5dafcc Author: Thierry Reding <tr...@nv...> Date: Wed Jun 4 10:36:43 2014 +0200 tegra: Add GET/SET_TILING IOCTLs Currently the tiling parameters of buffer objects can only be set at allocation time, and only a single tiled mode is supported. This new DRM_TEGRA_GEM_SET_TILING IOCTL allows more modes to be set and also allows the tiling mode to be changed after the allocation. This will enable the Tegra DRM driver to import buffers from a GPU and directly scan them out by configuring the display controller appropriately. To complement this, the DRM_TEGRA_GEM_GET_TILING IOCTL can query the current tiling mode of a buffer object. This is necessary when importing buffers via handle (as is done in Mesa for example) so that userspace can determine the proper parameters for the 2D or 3D engines. Signed-off-by: Thierry Reding <tr...@nv...> diff --git a/include/drm/tegra_drm.h b/include/drm/tegra_drm.h index be91601..1c29129 100644 --- a/include/drm/tegra_drm.h +++ b/include/drm/tegra_drm.h @@ -129,6 +129,27 @@ struct drm_tegra_submit { __u32 reserved[5]; /* future expansion */ }; +#define DRM_TEGRA_GEM_TILING_MODE_PITCH 0 +#define DRM_TEGRA_GEM_TILING_MODE_TILED 1 +#define DRM_TEGRA_GEM_TILING_MODE_BLOCK 2 + +struct drm_tegra_gem_set_tiling { + /* input */ + __u32 handle; + __u32 mode; + __u32 value; + __u32 pad; +}; + +struct drm_tegra_gem_get_tiling { + /* input */ + __u32 handle; + /* output */ + __u32 mode; + __u32 value; + __u32 pad; +}; + #define DRM_TEGRA_GEM_CREATE 0x00 #define DRM_TEGRA_GEM_MMAP 0x01 #define DRM_TEGRA_SYNCPT_READ 0x02 @@ -139,6 +160,8 @@ struct drm_tegra_submit { #define DRM_TEGRA_GET_SYNCPT 0x07 #define DRM_TEGRA_SUBMIT 0x08 #define DRM_TEGRA_GET_SYNCPT_BASE 0x09 +#define DRM_TEGRA_GEM_SET_TILING 0x0a +#define DRM_TEGRA_GEM_GET_TILING 0x0b #define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create) #define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap) @@ -150,5 +173,7 @@ struct drm_tegra_submit { #define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt) #define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit) #define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base) +#define DRM_IOCTL_TEGRA_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_TILING, struct drm_tegra_gem_set_tiling) +#define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling) #endif commit 93035cfbebf1344a041b70fbf9f3b89f6542805f Author: Thierry Reding <tr...@nv...> Date: Wed Feb 19 14:48:31 2014 +0100 tegra: Add simple test for drm_tegra_open() This test opens a device, dumps the version information and checks that a Tegra DRM context can be opened on it. Signed-off-by: Thierry Reding <tr...@nv...> diff --git a/configure.ac b/configure.ac index 253f48b..c88a1c5 100644 --- a/configure.ac +++ b/configure.ac @@ -423,6 +423,7 @@ AC_CONFIG_FILES([ tests/radeon/Makefile tests/vbltest/Makefile tests/exynos/Makefile + tests/tegra/Makefile man/Makefile libdrm.pc]) AC_OUTPUT diff --git a/tests/Makefile.am b/tests/Makefile.am index 889d265..e7ec4fa 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -24,6 +24,10 @@ if HAVE_EXYNOS SUBDIRS += exynos endif +if HAVE_TEGRA +SUBDIRS += tegra +endif + if HAVE_LIBUDEV check_LTLIBRARIES = libdrmtest.la diff --git a/tests/tegra/.gitignore b/tests/tegra/.gitignore new file mode 100644 index 0000000..5c5216c --- /dev/null +++ b/tests/tegra/.gitignore @@ -0,0 +1 @@ +openclose diff --git a/tests/tegra/Makefile.am b/tests/tegra/Makefile.am new file mode 100644 index 0000000..ca63d92 --- /dev/null +++ b/tests/tegra/Makefile.am @@ -0,0 +1,13 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include/drm \ + -I$(top_srcdir)/tegra \ + -I$(top_srcdir) + +AM_CFLAGS = -Wall -Werror + +LDADD = \ + ../../tegra/libdrm_tegra.la \ + ../../libdrm.la + +noinst_PROGRAMS = \ + openclose diff --git a/tests/tegra/openclose.c b/tests/tegra/openclose.c new file mode 100644 index 0000000..881d8aa --- /dev/null +++ b/tests/tegra/openclose.c @@ -0,0 +1,71 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> + +#include "xf86drm.h" +#include "tegra.h" + +static const char default_device[] = "/dev/dri/card0"; + +int main(int argc, char *argv[]) +{ + struct drm_tegra *tegra; + drmVersionPtr version; + const char *device; + int err, fd; + + if (argc < 2) + device = default_device; + else + device = argv[1]; + + fd = open(device, O_RDWR); + if (fd < 0) + return 1; + + version = drmGetVersion(fd); + if (version) { + printf("Version: %d.%d.%d\n", version->version_major, + version->version_minor, version->version_patchlevel); + printf(" Name: %s\n", version->name); + printf(" Date: %s\n", version->date); + printf(" Description: %s\n", version->desc); + + drmFreeVersion(version); + } + + err = drm_tegra_new(&tegra, fd); + if (err < 0) + return 1; + + drm_tegra_close(tegra); + close(fd); + + return 0; +} commit d6a4c2cbd11e357a9123f6d41f6d40d38e82e7f2 Author: Thierry Reding <thi...@av...> Date: Sat Dec 1 10:30:38 2012 +0100 libdrm: Add NVIDIA Tegra support Add the libdrm_tegra helper library to encapsulate Tegra-specific interfaces to the DRM. Furthermore, Tegra is added to the list of supported chips in the modetest and vbltest programs. Signed-off-by: Thierry Reding <thi...@av...> Signed-off-by: Erik Faye-Lund <kus...@gm...> Signed-off-by: Thierry Reding <tr...@nv...> diff --git a/Makefile.am b/Makefile.am index 3952a88..3cb516c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,7 +53,11 @@ if HAVE_FREEDRENO FREEDRENO_SUBDIR = freedreno endif -SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(FREEDRENO_SUBDIR) tests man +if HAVE_TEGRA +TEGRA_SUBDIR = tegra +endif + +SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(FREEDRENO_SUBDIR) $(TEGRA_SUBDIR) tests man libdrm_la_LTLIBRARIES = libdrm.la libdrm_ladir = $(libdir) diff --git a/Makefile.sources b/Makefile.sources index d86fb2a..566f7b5 100644 --- a/Makefile.sources +++ b/Makefile.sources @@ -26,6 +26,7 @@ LIBDRM_INCLUDE_H_FILES := \ include/drm/radeon_drm.h \ include/drm/savage_drm.h \ include/drm/sis_drm.h \ + include/drm/tegra_drm.h \ include/drm/via_drm.h LIBDRM_INCLUDE_VMWGFX_H_FILES := \ diff --git a/configure.ac b/configure.ac index 3a528f2..253f48b 100644 --- a/configure.ac +++ b/configure.ac @@ -98,6 +98,11 @@ AC_ARG_ENABLE(freedreno-experimental-api, [Enable support for freedreno's experimental API (default: disabled)]), [FREEDRENO=$enableval], [FREEDRENO=no]) +AC_ARG_ENABLE(tegra-experimental-api, + AS_HELP_STRING([--enable-tegra-experimental-api], + [Enable support for Tegra's experimental API (default: disabled)]), + [TEGRA=$enableval], [TEGRA=no]) + AC_ARG_ENABLE(install-test-programs, AS_HELP_STRING([--enable-install-test-programs], [Install test programs (default: no)]), @@ -304,6 +309,11 @@ if test "x$RADEON" = xyes; then AC_DEFINE(HAVE_RADEON, 1, [Have radeon support]) fi +AM_CONDITIONAL(HAVE_TEGRA, [test "x$TEGRA" = xyes]) +if test "x$TEGRA" = xyes; then + AC_DEFINE(HAVE_TEGRA, 1, [Have Tegra support]) +fi + AM_CONDITIONAL(HAVE_INSTALL_TESTS, [test "x$INSTALL_TESTS" = xyes]) if test "x$INSTALL_TESTS" = xyes; then AC_DEFINE(HAVE_INSTALL_TESTS, 1, [Install test programs]) @@ -403,6 +413,8 @@ AC_CONFIG_FILES([ exynos/libdrm_exynos.pc freedreno/Makefile freedreno/libdrm_freedreno.pc + tegra/Makefile + tegra/libdrm_tegra.pc tests/Makefile tests/modeprint/Makefile tests/modetest/Makefile @@ -426,4 +438,5 @@ echo " Nouveau API $NOUVEAU" echo " OMAP API $OMAP" echo " EXYNOS API $EXYNOS" echo " Freedreno API $FREEDRENO" +echo " Tegra API $TEGRA" echo "" diff --git a/include/drm/tegra_drm.h b/include/drm/tegra_drm.h new file mode 100644 index 0000000..be91601 --- /dev/null +++ b/include/drm/tegra_drm.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _UAPI_TEGRA_DRM_H_ +#define _UAPI_TEGRA_DRM_H_ + +#include <drm.h> + +#define DRM_TEGRA_GEM_CREATE_TILED (1 << 0) +#define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1) + +struct drm_tegra_gem_create { + __u64 size; + __u32 flags; + __u32 handle; +}; + +struct drm_tegra_gem_mmap { + __u32 handle; + __u32 offset; +}; + +struct drm_tegra_syncpt_read { + __u32 id; + __u32 value; +}; + +struct drm_tegra_syncpt_incr { + __u32 id; + __u32 pad; +}; + +struct drm_tegra_syncpt_wait { + __u32 id; + __u32 thresh; + __u32 timeout; + __u32 value; +}; + +#define DRM_TEGRA_NO_TIMEOUT (0xffffffff) + +struct drm_tegra_open_channel { + __u32 client; + __u32 pad; + __u64 context; +}; + +struct drm_tegra_close_channel { + __u64 context; +}; + +struct drm_tegra_get_syncpt { + __u64 context; + __u32 index; + __u32 id; +}; + +struct drm_tegra_get_syncpt_base { + __u64 context; + __u32 syncpt; + __u32 id; +}; + +struct drm_tegra_syncpt { + __u32 id; + __u32 incrs; +}; + +struct drm_tegra_cmdbuf { + __u32 handle; + __u32 offset; + __u32 words; + __u32 pad; +}; + +struct drm_tegra_reloc { + struct { + __u32 handle; + __u32 offset; + } cmdbuf; + struct { + __u32 handle; + __u32 offset; + } target; + __u32 shift; + __u32 pad; +}; + +struct drm_tegra_waitchk { + __u32 handle; + __u32 offset; + __u32 syncpt; + __u32 thresh; +}; + +struct drm_tegra_submit { + __u64 context; + __u32 num_syncpts; + __u32 num_cmdbufs; + __u32 num_relocs; + __u32 num_waitchks; + __u32 waitchk_mask; + __u32 timeout; + __u64 syncpts; + __u64 cmdbufs; + __u64 relocs; + __u64 waitchks; + __u32 fence; /* Return value */ + + __u32 reserved[5]; /* future expansion */ +}; + +#define DRM_TEGRA_GEM_CREATE 0x00 +#define DRM_TEGRA_GEM_MMAP 0x01 +#define DRM_TEGRA_SYNCPT_READ 0x02 +#define DRM_TEGRA_SYNCPT_INCR 0x03 +#define DRM_TEGRA_SYNCPT_WAIT 0x04 +#define DRM_TEGRA_OPEN_CHANNEL 0x05 +#define DRM_TEGRA_CLOSE_CHANNEL 0x06 +#define DRM_TEGRA_GET_SYNCPT 0x07 +#define DRM_TEGRA_SUBMIT 0x08 +#define DRM_TEGRA_GET_SYNCPT_BASE 0x09 + +#define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create) +#define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap) +#define DRM_IOCTL_TEGRA_SYNCPT_READ DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_READ, struct drm_tegra_syncpt_read) +#define DRM_IOCTL_TEGRA_SYNCPT_INCR DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_INCR, struct drm_tegra_syncpt_incr) +#define DRM_IOCTL_TEGRA_SYNCPT_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_WAIT, struct drm_tegra_syncpt_wait) +#define DRM_IOCTL_TEGRA_OPEN_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_OPEN_CHANNEL, struct drm_tegra_open_channel) +#define DRM_IOCTL_TEGRA_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_CLOSE_CHANNEL, struct drm_tegra_open_channel) +#define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt) +#define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit) +#define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base) + +#endif diff --git a/tegra/.gitignore b/tegra/.gitignore new file mode 100644 index 0000000..74cfe47 --- /dev/null +++ b/tegra/.gitignore @@ -0,0 +1 @@ +libdrm_tegra.pc diff --git a/tegra/Makefile.am b/tegra/Makefile.am new file mode 100644 index 0000000..a647487 --- /dev/null +++ b/tegra/Makefile.am @@ -0,0 +1,23 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -I$(top_srcdir)/include/drm + +AM_CFLAGS = \ + @PTHREADSTUBS_CFLAGS@ \ + $(VISIBILITY_CFLAGS) \ + $(WARN_CFLAGS) + +libdrm_tegra_ladir = $(libdir) +libdrm_tegra_la_LTLIBRARIES = libdrm_tegra.la +libdrm_tegra_la_LDFLAGS = -version-number 0:0:0 -no-undefined +libdrm_tegra_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@ + +libdrm_tegra_la_SOURCES = \ + private.h \ + tegra.c + +libdrm_tegraincludedir = ${includedir}/libdrm +libdrm_tegrainclude_HEADERS = tegra.h + +pkgconfigdir = @pkgconfigdir@ +pkgconfig_DATA = libdrm_tegra.pc diff --git a/tegra/libdrm_tegra.pc.in b/tegra/libdrm_tegra.pc.in new file mode 100644 index 0000000..2e06f49 --- /dev/null +++ b/tegra/libdrm_tegra.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libdrm_tegra +Description: Userspace interface to Tegra kernel DRM services +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -ldrm_tegra +Cflags: -I${includedir} -I${includedir}/libdrm +Requires.private: libdrm diff --git a/tegra/private.h b/tegra/private.h new file mode 100644 index 0000000..9b6bc93 --- /dev/null +++ b/tegra/private.h @@ -0,0 +1,51 @@ +/* + * Copyright © 2012, 2013 Thierry Reding + * Copyright © 2013 Erik Faye-Lund + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __DRM_TEGRA_PRIVATE_H__ +#define __DRM_TEGRA_PRIVATE_H__ 1 + +#include <stdbool.h> +#include <stdint.h> + +#include <libdrm.h> +#include <xf86atomic.h> + +#include "tegra.h" + +struct drm_tegra { + bool close; + int fd; +}; + +struct drm_tegra_bo { + struct drm_tegra *drm; + uint32_t handle; + uint32_t offset; + uint32_t flags; + uint32_t size; + atomic_t ref; + void *map; +}; + +#endif /* __DRM_TEGRA_PRIVATE_H__ */ diff --git a/tegra/tegra.c b/tegra/tegra.c new file mode 100644 index 0000000..ec5bf76 --- /dev/null +++ b/tegra/tegra.c @@ -0,0 +1,248 @@ +/* + * Copyright © 2012, 2013 Thierry Reding + * Copyright © 2013 Erik Faye-Lund + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <unistd.h> + +#include <sys/mman.h> + +#include <xf86drm.h> + +#include <tegra_drm.h> + +#include "private.h" + +static void drm_tegra_bo_free(struct drm_tegra_bo *bo) +{ + struct drm_tegra *drm = bo->drm; + struct drm_gem_close args; + + if (bo->map) + munmap(bo->map, bo->size); + + memset(&args, 0, sizeof(args)); + args.handle = bo->handle; + + drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &args); + + free(bo); +} + +static int drm_tegra_wrap(struct drm_tegra **drmp, int fd, bool close) +{ + struct drm_tegra *drm; + + if (fd < 0 || !drmp) + return -EINVAL; + + drm = calloc(1, sizeof(*drm)); + if (!drm) + return -ENOMEM; + + drm->close = close; + drm->fd = fd; + + *drmp = drm; + + return 0; +} + +drm_public +int drm_tegra_new(struct drm_tegra **drmp, int fd) +{ + bool supported = false; + drmVersionPtr version; + + version = drmGetVersion(fd); + if (!version) + return -ENOMEM; + + if (!strncmp(version->name, "tegra", version->name_len)) + supported = true; + + drmFreeVersion(version); + + if (!supported) + return -ENOTSUP; + + return drm_tegra_wrap(drmp, fd, false); +} + +drm_public +void drm_tegra_close(struct drm_tegra *drm) +{ + if (!drm) + return; + + if (drm->close) + close(drm->fd); + + free(drm); +} + +drm_public +int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm, + uint32_t flags, uint32_t size) +{ + struct drm_tegra_gem_create args; + struct drm_tegra_bo *bo; + int err; + + if (!drm || size == 0 || !bop) + return -EINVAL; + + bo = calloc(1, sizeof(*bo)); + if (!bo) + return -ENOMEM; + + atomic_set(&bo->ref, 1); + bo->flags = flags; + bo->size = size; + bo->drm = drm; + + memset(&args, 0, sizeof(args)); + args.flags = flags; + args.size = size; + + err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_CREATE, &args, + sizeof(args)); + if (err < 0) { + err = -errno; + free(bo); + return err; + } + + bo->handle = args.handle; + + *bop = bo; + + return 0; +} + +drm_public +int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm, + uint32_t handle, uint32_t flags, uint32_t size) +{ + struct drm_tegra_bo *bo; + + if (!drm || !bop) + return -EINVAL; + + bo = calloc(1, sizeof(*bo)); + if (!bo) + return -ENOMEM; + + atomic_set(&bo->ref, 1); + bo->handle = handle; + bo->flags = flags; + bo->size = size; + bo->drm = drm; + + *bop = bo; + + return 0; +} + +drm_public +struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo) +{ + if (bo) + atomic_inc(&bo->ref); + + return bo; +} + +drm_public +void drm_tegra_bo_unref(struct drm_tegra_bo *bo) +{ + if (bo && atomic_dec_and_test(&bo->ref)) + drm_tegra_bo_free(bo); +} + +drm_public +int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle) +{ + if (!bo || !handle) + return -EINVAL; + + *handle = bo->handle; + + return 0; +} + +drm_public +int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr) +{ + struct drm_tegra *drm = bo->drm; + + if (!bo->map) { + struct drm_tegra_gem_mmap args; + int err; + + memset(&args, 0, sizeof(args)); + args.handle = bo->handle; + + err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_MMAP, &args, + sizeof(args)); + if (err < 0) + return -errno; + + bo->offset = args.offset; + + bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, + drm->fd, bo->offset); + if (bo->map == MAP_FAILED) { + bo->map = NULL; + return -errno; + } + } + + if (ptr) + *ptr = bo->map; + + return 0; +} + +drm_public +int drm_tegra_bo_unmap(struct drm_tegra_bo *bo) +{ + if (!bo) + return -EINVAL; + + if (!bo->map) + return 0; + + if (munmap(bo->map, bo->size)) + return -errno; + + bo->map = NULL; + + return 0; +} diff --git a/tegra/tegra.h b/tegra/tegra.h new file mode 100644 index 0000000..ed29505 --- /dev/null +++ b/tegra/tegra.h @@ -0,0 +1,47 @@ +/* + * Copyright © 2012, 2013 Thierry Reding + * Copyright © 2013 Erik Faye-Lund + * Copyright © 2014 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __DRM_TEGRA_H__ +#define __DRM_TEGRA_H__ 1 + +#include <stdint.h> +#include <stdlib.h> + +struct drm_tegra_bo; +struct drm_tegra; + +int drm_tegra_new(struct drm_tegra **drmp, int fd); +void drm_tegra_close(struct drm_tegra *drm); + +int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm, + uint32_t flags, uint32_t size); +int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm, + uint32_t handle, uint32_t flags, uint32_t size); +struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo); +void drm_tegra_bo_unref(struct drm_tegra_bo *bo); +int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle); +int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr); +int drm_tegra_bo_unmap(struct drm_tegra_bo *bo); + +#endif /* __DRM_TEGRA_H__ */ diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index d3252b6..2c9a17a 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -1456,7 +1456,7 @@ int main(int argc, char **argv) int drop_master = 0; int test_vsync = 0; int test_cursor = 0; - const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", "tilcdc", "msm", "sti" }; + const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", "tilcdc", "msm", "sti", "tegra" }; char *device = NULL; char *module = NULL; unsigned int i; diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c index 50e29dc..cdc1ef6 100644 --- a/tests/vbltest/vbltest.c +++ b/tests/vbltest/vbltest.c @@ -105,7 +105,7 @@ static void usage(char *name) int main(int argc, char **argv) { int i, c, fd, ret; - char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos", "omapdrm", "tilcdc", "msm" }; + char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos", "omapdrm", "tilcdc", "msm", "tegra" }; drmVBlank vbl; drmEventContext evctx; struct vbl_info handler_info; |
From: <kr...@ke...> - 2015-12-14 19:40:30
|
.gitignore | 1 include/drm/i915_drm.h | 59 +++++++++-- intel/intel-symbol-check | 2 intel/intel_bufmgr.c | 20 +++ intel/intel_bufmgr.h | 2 intel/intel_bufmgr_gem.c | 245 +++++++++++++++++++++++++++++++++++++++------- intel/intel_bufmgr_priv.h | 21 +++ 7 files changed, 305 insertions(+), 45 deletions(-) New commits: commit d6ffb997263402eebdcb029e061ae0221925f643 Author: Kristian Høgsberg Kristensen <kri...@in...> Date: Mon Dec 14 11:33:26 2015 -0800 intel: Add drm_intel_bo_set_softpin_offset to intel-symbol-check Signed-off-by: Kristian Høgsberg Kristensen <kri...@in...> diff --git a/intel/intel-symbol-check b/intel/intel-symbol-check index 64ec4ed..bde7634 100755 --- a/intel/intel-symbol-check +++ b/intel/intel-symbol-check @@ -34,6 +34,7 @@ drm_intel_bo_mrb_exec drm_intel_bo_pin drm_intel_bo_reference drm_intel_bo_references +drm_intel_bo_set_softpin_offset drm_intel_bo_set_tiling drm_intel_bo_subdata drm_intel_bo_unmap commit 3b7d97102027db191c0fc81c3265f7916a6112fc Author: Kristian Høgsberg Kristensen <kri...@in...> Date: Mon Dec 14 10:55:55 2015 -0800 Add tests/drmdevice to .gitignore Signed-off-by: Kristian Høgsberg Kristensen <kri...@in...> diff --git a/.gitignore b/.gitignore index 79b2ac1..a45e0af 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,7 @@ via.kld tests/auth tests/amdgpu/amdgpu_test tests/dristat +tests/drmdevice tests/drmsl tests/drmstat tests/getclient commit 8b4d57e7b75cb0bd01d11ad7f597909034a316aa Author: MichaÅ Winiarski <mic...@in...> Date: Wed Sep 9 16:07:10 2015 +0200 intel: Add support for softpin Softpin allows userspace to take greater control of GPU virtual address space and eliminates the need of relocations. It can also be used to mirror addresses between GPU and CPU (shared virtual memory). Calls to drm_intel_bo_emit_reloc are still required to build the list of drm_i915_gem_exec_objects at exec time, but no entries in relocs are created. Self-relocs don't make any sense for softpinned objects and can indicate a programming errors, thus are forbidden. Softpinned objects are marked by asterisk in debug dumps. Cc: Thomas Daniel <tho...@in...> Cc: Kristian Høgsberg <kr...@bi...> Cc: Zou Nanhai <nan...@in...> Cc: Michel Thierry <mic...@in...> Cc: Ben Widawsky <be...@bw...> Cc: Chris Wilson <ch...@ch...> Reviewed-by: Kristian Høgsberg <kr...@bi...> Signed-off-by: Kristian Høgsberg <kr...@bi...> Signed-off-by: MichaÅ Winiarski <mic...@in...> diff --git a/intel/intel_bufmgr.c b/intel/intel_bufmgr.c index 0856e60..a285340 100644 --- a/intel/intel_bufmgr.c +++ b/intel/intel_bufmgr.c @@ -261,6 +261,15 @@ drm_intel_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, } int +drm_intel_bo_set_softpin_offset(drm_intel_bo *bo, uint64_t offset) +{ + if (bo->bufmgr->bo_set_softpin_offset) + return bo->bufmgr->bo_set_softpin_offset(bo, offset); + + return -ENODEV; +} + +int drm_intel_bo_disable_reuse(drm_intel_bo *bo) { if (bo->bufmgr->bo_disable_reuse) diff --git a/intel/intel_bufmgr.h b/intel/intel_bufmgr.h index a14c78f..a1abbcd 100644 --- a/intel/intel_bufmgr.h +++ b/intel/intel_bufmgr.h @@ -165,6 +165,7 @@ int drm_intel_bo_flink(drm_intel_bo *bo, uint32_t * name); int drm_intel_bo_busy(drm_intel_bo *bo); int drm_intel_bo_madvise(drm_intel_bo *bo, int madv); int drm_intel_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable); +int drm_intel_bo_set_softpin_offset(drm_intel_bo *bo, uint64_t offset); int drm_intel_bo_disable_reuse(drm_intel_bo *bo); int drm_intel_bo_is_reusable(drm_intel_bo *bo); diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index 1eae898..265516f 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -200,6 +200,13 @@ struct _drm_intel_bo_gem { drm_intel_reloc_target *reloc_target_info; /** Number of entries in relocs */ int reloc_count; + /** Array of BOs that are referenced by this buffer and will be softpinned */ + drm_intel_bo **softpin_target; + /** Number softpinned BOs that are referenced by this buffer */ + int softpin_target_count; + /** Maximum amount of softpinned BOs that are referenced by this buffer */ + int softpin_target_size; + /** Mapped address for the buffer, saved across map/unmap cycles */ void *mem_virtual; /** GTT virtual address for the buffer, saved across map/unmap cycles */ @@ -262,6 +269,11 @@ struct _drm_intel_bo_gem { bool use_48b_address_range; /** + * Whether this buffer is softpinned at offset specified by the user + */ + bool is_softpin; + + /** * Size in bytes of this buffer and its relocation descendents. * * Used to avoid costly tree walking in @@ -414,8 +426,9 @@ drm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem) drm_intel_bo *bo = bufmgr_gem->exec_bos[i]; drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; - if (bo_gem->relocs == NULL) { - DBG("%2d: %d (%s)\n", i, bo_gem->gem_handle, + if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL) { + DBG("%2d: %d %s(%s)\n", i, bo_gem->gem_handle, + bo_gem->is_softpin ? "*" : "", bo_gem->name); continue; } @@ -425,18 +438,33 @@ drm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem) drm_intel_bo_gem *target_gem = (drm_intel_bo_gem *) target_bo; - DBG("%2d: %d (%s)@0x%08x %08x -> " - "%d (%s)@0x%08x %08x + 0x%08x\n", + DBG("%2d: %d %s(%s)@0x%016llx -> " + "%d (%s)@0x%016llx + 0x%08x\n", i, - bo_gem->gem_handle, bo_gem->name, - upper_32_bits(bo_gem->relocs[j].offset), - lower_32_bits(bo_gem->relocs[j].offset), + bo_gem->gem_handle, + bo_gem->is_softpin ? "*" : "", + bo_gem->name, + (unsigned long long) bo_gem->relocs[j].offset, target_gem->gem_handle, target_gem->name, - upper_32_bits(target_bo->offset64), - lower_32_bits(target_bo->offset64), + (unsigned long long) target_bo->offset64, bo_gem->relocs[j].delta); } + + for (j = 0; j < bo_gem->softpin_target_count; j++) { + drm_intel_bo *target_bo = bo_gem->softpin_target[j]; + drm_intel_bo_gem *target_gem = + (drm_intel_bo_gem *) target_bo; + DBG("%2d: %d %s(%s) -> " + "%d *(%s)@0x%016lx\n", + i, + bo_gem->gem_handle, + bo_gem->is_softpin ? "*" : "", + bo_gem->name, + target_gem->gem_handle, + target_gem->name, + target_bo->offset64); + } } } @@ -506,6 +534,8 @@ drm_intel_add_validate_buffer2(drm_intel_bo *bo, int need_fence) flags |= EXEC_OBJECT_NEEDS_FENCE; if (bo_gem->use_48b_address_range) flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS; + if (bo_gem->is_softpin) + flags |= EXEC_OBJECT_PINNED; if (bo_gem->validate_index != -1) { bufmgr_gem->exec2_objects[bo_gem->validate_index].flags |= flags; @@ -535,7 +565,8 @@ drm_intel_add_validate_buffer2(drm_intel_bo *bo, int need_fence) bufmgr_gem->exec2_objects[index].relocation_count = bo_gem->reloc_count; bufmgr_gem->exec2_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs; bufmgr_gem->exec2_objects[index].alignment = bo->align; - bufmgr_gem->exec2_objects[index].offset = 0; + bufmgr_gem->exec2_objects[index].offset = bo_gem->is_softpin ? + bo->offset64 : 0; bufmgr_gem->exec_bos[index] = bo; bufmgr_gem->exec2_objects[index].flags = flags; bufmgr_gem->exec2_objects[index].rsvd1 = 0; @@ -1291,8 +1322,12 @@ drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time) time); } } + for (i = 0; i < bo_gem->softpin_target_count; i++) + drm_intel_gem_bo_unreference_locked_timed(bo_gem->softpin_target[i], + time); bo_gem->reloc_count = 0; bo_gem->used_as_reloc_target = false; + bo_gem->softpin_target_count = 0; DBG("bo_unreference final: %d (%s)\n", bo_gem->gem_handle, bo_gem->name); @@ -1306,6 +1341,11 @@ drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time) free(bo_gem->relocs); bo_gem->relocs = NULL; } + if (bo_gem->softpin_target) { + free(bo_gem->softpin_target); + bo_gem->softpin_target = NULL; + bo_gem->softpin_target_size = 0; + } /* Clear any left-over mappings */ if (bo_gem->map_count) { @@ -1943,14 +1983,6 @@ do_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, bo_gem->reloc_tree_fences += target_bo_gem->reloc_tree_fences; } - bo_gem->relocs[bo_gem->reloc_count].offset = offset; - bo_gem->relocs[bo_gem->reloc_count].delta = target_offset; - bo_gem->relocs[bo_gem->reloc_count].target_handle = - target_bo_gem->gem_handle; - bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains; - bo_gem->relocs[bo_gem->reloc_count].write_domain = write_domain; - bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset64; - bo_gem->reloc_target_info[bo_gem->reloc_count].bo = target_bo; if (target_bo != bo) drm_intel_gem_bo_reference(target_bo); @@ -1960,6 +1992,13 @@ do_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, else bo_gem->reloc_target_info[bo_gem->reloc_count].flags = 0; + bo_gem->relocs[bo_gem->reloc_count].offset = offset; + bo_gem->relocs[bo_gem->reloc_count].delta = target_offset; + bo_gem->relocs[bo_gem->reloc_count].target_handle = + target_bo_gem->gem_handle; + bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains; + bo_gem->relocs[bo_gem->reloc_count].write_domain = write_domain; + bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset64; bo_gem->reloc_count++; return 0; @@ -1973,15 +2012,57 @@ drm_intel_gem_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable) } static int +drm_intel_gem_bo_add_softpin_target(drm_intel_bo *bo, drm_intel_bo *target_bo) +{ + drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; + drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; + drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo; + if (bo_gem->has_error) + return -ENOMEM; + + if (target_bo_gem->has_error) { + bo_gem->has_error = true; + return -ENOMEM; + } + + if (!target_bo_gem->is_softpin) + return -EINVAL; + if (target_bo_gem == bo_gem) + return -EINVAL; + + if (bo_gem->softpin_target_count == bo_gem->softpin_target_size) { + int new_size = bo_gem->softpin_target_size * 2; + if (new_size == 0) + new_size = bufmgr_gem->max_relocs; + + bo_gem->softpin_target = realloc(bo_gem->softpin_target, new_size * + sizeof(drm_intel_bo *)); + if (!bo_gem->softpin_target) + return -ENOMEM; + + bo_gem->softpin_target_size = new_size; + } + bo_gem->softpin_target[bo_gem->softpin_target_count] = target_bo; + drm_intel_gem_bo_reference(target_bo); + bo_gem->softpin_target_count++; + + return 0; +} + +static int drm_intel_gem_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, drm_intel_bo *target_bo, uint32_t target_offset, uint32_t read_domains, uint32_t write_domain) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; + drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *)target_bo; - return do_bo_emit_reloc(bo, offset, target_bo, target_offset, - read_domains, write_domain, - !bufmgr_gem->fenced_relocs); + if (target_bo_gem->is_softpin) + return drm_intel_gem_bo_add_softpin_target(bo, target_bo); + else + return do_bo_emit_reloc(bo, offset, target_bo, target_offset, + read_domains, write_domain, + !bufmgr_gem->fenced_relocs); } static int @@ -2014,6 +2095,8 @@ drm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo) * * Any further drm_intel_bufmgr_check_aperture_space() queries * involving this buffer in the tree are undefined after this call. + * + * This also removes all softpinned targets being referenced by the BO. */ void drm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start) @@ -2040,6 +2123,12 @@ drm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start) } bo_gem->reloc_count = start; + for (i = 0; i < bo_gem->softpin_target_count; i++) { + drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->softpin_target[i]; + drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo, time.tv_sec); + } + bo_gem->softpin_target_count = 0; + pthread_mutex_unlock(&bufmgr_gem->lock); } @@ -2080,7 +2169,7 @@ drm_intel_gem_bo_process_reloc2(drm_intel_bo *bo) drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; int i; - if (bo_gem->relocs == NULL) + if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL) return; for (i = 0; i < bo_gem->reloc_count; i++) { @@ -2101,6 +2190,17 @@ drm_intel_gem_bo_process_reloc2(drm_intel_bo *bo) /* Add the target to the validate list */ drm_intel_add_validate_buffer2(target_bo, need_fence); } + + for (i = 0; i < bo_gem->softpin_target_count; i++) { + drm_intel_bo *target_bo = bo_gem->softpin_target[i]; + + if (target_bo == bo) + continue; + + drm_intel_gem_bo_mark_mmaps_incoherent(bo); + drm_intel_gem_bo_process_reloc2(target_bo); + drm_intel_add_validate_buffer2(target_bo, false); + } } @@ -2138,12 +2238,14 @@ drm_intel_update_buffer_offsets2 (drm_intel_bufmgr_gem *bufmgr_gem) /* Update the buffer offset */ if (bufmgr_gem->exec2_objects[i].offset != bo->offset64) { - DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n", + /* If we're seeing softpinned object here it means that the kernel + * has relocated our object... Indicating a programming error + */ + assert(!bo_gem->is_softpin); + DBG("BO %d (%s) migrated: 0x%016llx -> 0x%016llx\n", bo_gem->gem_handle, bo_gem->name, - upper_32_bits(bo->offset64), - lower_32_bits(bo->offset64), - upper_32_bits(bufmgr_gem->exec2_objects[i].offset), - lower_32_bits(bufmgr_gem->exec2_objects[i].offset)); + (unsigned long long) bo->offset64, + (unsigned long long) bufmgr_gem->exec2_objects[i].offset); bo->offset64 = bufmgr_gem->exec2_objects[i].offset; bo->offset = bufmgr_gem->exec2_objects[i].offset; } @@ -2465,6 +2567,17 @@ drm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, return 0; } +static int +drm_intel_gem_bo_set_softpin_offset(drm_intel_bo *bo, uint64_t offset) +{ + drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; + + bo_gem->is_softpin = true; + bo->offset64 = offset; + bo->offset = offset; + return 0; +} + drm_intel_bo * drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int size) { @@ -2844,6 +2957,13 @@ _drm_intel_gem_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo) return 1; } + for (i = 0; i< bo_gem->softpin_target_count; i++) { + if (bo_gem->softpin_target[i] == target_bo) + return 1; + if (_drm_intel_gem_bo_references(bo_gem->softpin_target[i], target_bo)) + return 1; + } + return 0; } @@ -3300,6 +3420,11 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size) ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); bufmgr_gem->has_vebox = (ret == 0) & (*gp.value > 0); + gp.param = I915_PARAM_HAS_EXEC_SOFTPIN; + ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); + if (ret == 0 && *gp.value > 0) + bufmgr_gem->bufmgr.bo_set_softpin_offset = drm_intel_gem_bo_set_softpin_offset; + if (bufmgr_gem->gen < 4) { gp.param = I915_PARAM_NUM_FENCES_AVAIL; gp.value = &bufmgr_gem->available_fences; diff --git a/intel/intel_bufmgr_priv.h b/intel/intel_bufmgr_priv.h index 5c17ffb..7e360a0 100644 --- a/intel/intel_bufmgr_priv.h +++ b/intel/intel_bufmgr_priv.h @@ -241,6 +241,13 @@ struct _drm_intel_bufmgr { uint32_t * swizzle_mode); /** + * Set the offset at which this buffer will be softpinned + * \param bo Buffer to set the softpin offset for + * \param offset Softpin offset + */ + int (*bo_set_softpin_offset) (drm_intel_bo *bo, uint64_t offset); + + /** * Create a visible name for a buffer which can be used by other apps * * \param buf Buffer to create a name for commit 5453f89b70dc4305f8525d5053b2704db2e0e1e7 Author: Michel Thierry <mic...@in...> Date: Thu Sep 3 15:23:59 2015 +0100 intel: add drm_intel_bo_use_48b_address_range to symbol-check test Signed-off-by: Michel Thierry <mic...@in...> Reviewed-by: Kristian Høgsberg Kristensen <kri...@in...> Signed-off-by: Kristian Høgsberg Kristensen <kri...@in...> diff --git a/intel/intel-symbol-check b/intel/intel-symbol-check index c555e6d..64ec4ed 100755 --- a/intel/intel-symbol-check +++ b/intel/intel-symbol-check @@ -39,6 +39,7 @@ drm_intel_bo_subdata drm_intel_bo_unmap drm_intel_bo_unpin drm_intel_bo_unreference +drm_intel_bo_use_48b_address_range drm_intel_bo_wait_rendering drm_intel_bufmgr_check_aperture_space drm_intel_bufmgr_destroy commit 3350add5cc166b5d0e829377747bf6a94a4b0c09 Author: Michel Thierry <mic...@in...> Date: Thu Sep 3 15:23:58 2015 +0100 intel: 48b ppgtt support (EXEC_OBJECT_SUPPORTS_48B_ADDRESS flag) Gen8+ supports 48-bit virtual addresses, but some objects must always be allocated inside the 32-bit address range. In specific, any resource used with flat/heapless (0x00000000-0xfffff000) General State Heap (GSH) or Instruction State Heap (ISH) must be in a 32-bit range, because the General State Offset and Instruction State Offset are limited to 32-bits. The i915 driver has been modified to provide a flag to set when the 4GB limit is not necessary in a given bo (EXEC_OBJECT_SUPPORTS_48B_ADDRESS). 48-bit range will only be used when explicitly requested. Callers to the existing drm_intel_bo_emit_reloc function should set the use_48b_address_range flag beforehand, in order to use full ppgtt range. v2: Make set/clear functions nops on pre-gen8 platforms, and use them internally in emit_reloc functions (Ben) s/48BADDRESS/48B_ADDRESS/ (Dave) v3: Keep set/clear functions internal, no-one needs to use them directly. v4: Don't set 48bit-support flag in emit reloc, check for ppgtt type before enabling set/clear function, print full offsets in debug statements, using port of lower_32_bits and upper_32_bits from linux kernel (MichaÅ) References: http://lists.freedesktop.org/archives/intel-gfx/2015-July/072612.html Cc: Ben Widawsky <be...@bw...> Cc: MichaÅ Winiarski <mic...@in...> Signed-off-by: Michel Thierry <mic...@in...> Reviewed-by: Kristian Høgsberg Kristensen <kri...@in...> Signed-off-by: Kristian Høgsberg Kristensen <kri...@in...> diff --git a/intel/intel_bufmgr.c b/intel/intel_bufmgr.c index 14ea9f9..0856e60 100644 --- a/intel/intel_bufmgr.c +++ b/intel/intel_bufmgr.c @@ -293,6 +293,17 @@ drm_intel_bo_madvise(drm_intel_bo *bo, int madv) } int +drm_intel_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable) +{ + if (bo->bufmgr->bo_use_48b_address_range) { + bo->bufmgr->bo_use_48b_address_range(bo, enable); + return 0; + } + + return -ENODEV; +} + +int drm_intel_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo) { return bo->bufmgr->bo_references(bo, target_bo); diff --git a/intel/intel_bufmgr.h b/intel/intel_bufmgr.h index 95eecb8..a14c78f 100644 --- a/intel/intel_bufmgr.h +++ b/intel/intel_bufmgr.h @@ -164,6 +164,7 @@ int drm_intel_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, int drm_intel_bo_flink(drm_intel_bo *bo, uint32_t * name); int drm_intel_bo_busy(drm_intel_bo *bo); int drm_intel_bo_madvise(drm_intel_bo *bo, int madv); +int drm_intel_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable); int drm_intel_bo_disable_reuse(drm_intel_bo *bo); int drm_intel_bo_is_reusable(drm_intel_bo *bo); diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index 63122d0..1eae898 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -83,6 +83,22 @@ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define MAX2(A, B) ((A) > (B) ? (A) : (B)) +/** + * upper_32_bits - return bits 32-63 of a number + * @n: the number we're accessing + * + * A basic shift-right of a 64- or 32-bit quantity. Use this to suppress + * the "right shift count >= width of type" warning when that quantity is + * 32-bits. + */ +#define upper_32_bits(n) ((__u32)(((n) >> 16) >> 16)) + +/** + * lower_32_bits - return bits 0-31 of a number + * @n: the number we're accessing + */ +#define lower_32_bits(n) ((__u32)(n)) + typedef struct _drm_intel_bo_gem drm_intel_bo_gem; struct drm_intel_gem_bo_bucket { @@ -237,6 +253,15 @@ struct _drm_intel_bo_gem { bool is_userptr; /** + * Boolean of whether this buffer can be placed in the full 48-bit + * address range on gen8+. + * + * By default, buffers will be keep in a 32-bit range, unless this + * flag is explicitly set. + */ + bool use_48b_address_range; + + /** * Size in bytes of this buffer and its relocation descendents. * * Used to avoid costly tree walking in @@ -400,14 +425,16 @@ drm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem) drm_intel_bo_gem *target_gem = (drm_intel_bo_gem *) target_bo; - DBG("%2d: %d (%s)@0x%08llx -> " - "%d (%s)@0x%08lx + 0x%08x\n", + DBG("%2d: %d (%s)@0x%08x %08x -> " + "%d (%s)@0x%08x %08x + 0x%08x\n", i, bo_gem->gem_handle, bo_gem->name, - (unsigned long long)bo_gem->relocs[j].offset, + upper_32_bits(bo_gem->relocs[j].offset), + lower_32_bits(bo_gem->relocs[j].offset), target_gem->gem_handle, target_gem->name, - target_bo->offset64, + upper_32_bits(target_bo->offset64), + lower_32_bits(target_bo->offset64), bo_gem->relocs[j].delta); } } @@ -473,11 +500,15 @@ drm_intel_add_validate_buffer2(drm_intel_bo *bo, int need_fence) drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; int index; + int flags = 0; + + if (need_fence) + flags |= EXEC_OBJECT_NEEDS_FENCE; + if (bo_gem->use_48b_address_range) + flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS; if (bo_gem->validate_index != -1) { - if (need_fence) - bufmgr_gem->exec2_objects[bo_gem->validate_index].flags |= - EXEC_OBJECT_NEEDS_FENCE; + bufmgr_gem->exec2_objects[bo_gem->validate_index].flags |= flags; return; } @@ -506,13 +537,9 @@ drm_intel_add_validate_buffer2(drm_intel_bo *bo, int need_fence) bufmgr_gem->exec2_objects[index].alignment = bo->align; bufmgr_gem->exec2_objects[index].offset = 0; bufmgr_gem->exec_bos[index] = bo; - bufmgr_gem->exec2_objects[index].flags = 0; + bufmgr_gem->exec2_objects[index].flags = flags; bufmgr_gem->exec2_objects[index].rsvd1 = 0; bufmgr_gem->exec2_objects[index].rsvd2 = 0; - if (need_fence) { - bufmgr_gem->exec2_objects[index].flags |= - EXEC_OBJECT_NEEDS_FENCE; - } bufmgr_gem->exec_count++; } @@ -785,6 +812,7 @@ retry: bo_gem->used_as_reloc_target = false; bo_gem->has_error = false; bo_gem->reusable = true; + bo_gem->use_48b_address_range = false; drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, alignment); @@ -931,6 +959,7 @@ drm_intel_gem_bo_alloc_userptr(drm_intel_bufmgr *bufmgr, bo_gem->used_as_reloc_target = false; bo_gem->has_error = false; bo_gem->reusable = false; + bo_gem->use_48b_address_range = false; drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0); @@ -1086,6 +1115,7 @@ drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr, bo_gem->bo.handle = open_arg.handle; bo_gem->global_name = handle; bo_gem->reusable = false; + bo_gem->use_48b_address_range = false; memclear(get_tiling); get_tiling.handle = bo_gem->gem_handle; @@ -1935,6 +1965,13 @@ do_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, return 0; } +static void +drm_intel_gem_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable) +{ + drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; + bo_gem->use_48b_address_range = enable; +} + static int drm_intel_gem_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, drm_intel_bo *target_bo, uint32_t target_offset, @@ -2078,10 +2115,12 @@ drm_intel_update_buffer_offsets(drm_intel_bufmgr_gem *bufmgr_gem) /* Update the buffer offset */ if (bufmgr_gem->exec_objects[i].offset != bo->offset64) { - DBG("BO %d (%s) migrated: 0x%08lx -> 0x%08llx\n", - bo_gem->gem_handle, bo_gem->name, bo->offset64, - (unsigned long long)bufmgr_gem->exec_objects[i]. - offset); + DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n", + bo_gem->gem_handle, bo_gem->name, + upper_32_bits(bo->offset64), + lower_32_bits(bo->offset64), + upper_32_bits(bufmgr_gem->exec_objects[i].offset), + lower_32_bits(bufmgr_gem->exec_objects[i].offset)); bo->offset64 = bufmgr_gem->exec_objects[i].offset; bo->offset = bufmgr_gem->exec_objects[i].offset; } @@ -2099,9 +2138,12 @@ drm_intel_update_buffer_offsets2 (drm_intel_bufmgr_gem *bufmgr_gem) /* Update the buffer offset */ if (bufmgr_gem->exec2_objects[i].offset != bo->offset64) { - DBG("BO %d (%s) migrated: 0x%08lx -> 0x%08llx\n", - bo_gem->gem_handle, bo_gem->name, bo->offset64, - (unsigned long long)bufmgr_gem->exec2_objects[i].offset); + DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n", + bo_gem->gem_handle, bo_gem->name, + upper_32_bits(bo->offset64), + lower_32_bits(bo->offset64), + upper_32_bits(bufmgr_gem->exec2_objects[i].offset), + lower_32_bits(bufmgr_gem->exec2_objects[i].offset)); bo->offset64 = bufmgr_gem->exec2_objects[i].offset; bo->offset = bufmgr_gem->exec2_objects[i].offset; } @@ -2486,6 +2528,7 @@ drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int s bo_gem->used_as_reloc_target = false; bo_gem->has_error = false; bo_gem->reusable = false; + bo_gem->use_48b_address_range = false; DRMINITLISTHEAD(&bo_gem->vma_list); DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named); @@ -3283,6 +3326,13 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size) } } + if (bufmgr_gem->gen >= 8) { + gp.param = I915_PARAM_HAS_ALIASING_PPGTT; + ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); + if (ret == 0 && *gp.value == 3) + bufmgr_gem->bufmgr.bo_use_48b_address_range = drm_intel_gem_bo_use_48b_address_range; + } + /* Let's go with one relocation per every 2 dwords (but round down a bit * since a power of two will mean an extra page allocation for the reloc * buffer). diff --git a/intel/intel_bufmgr_priv.h b/intel/intel_bufmgr_priv.h index 59ebd18..5c17ffb 100644 --- a/intel/intel_bufmgr_priv.h +++ b/intel/intel_bufmgr_priv.h @@ -152,6 +152,20 @@ struct _drm_intel_bufmgr { void (*destroy) (drm_intel_bufmgr *bufmgr); /** + * Indicate if the buffer can be placed anywhere in the full ppgtt + * address range (2^48). + * + * Any resource used with flat/heapless (0x00000000-0xfffff000) + * General State Heap (GSH) or Intructions State Heap (ISH) must + * be in a 32-bit range. 48-bit range will only be used when explicitly + * requested. + * + * \param bo Buffer to set the use_48b_address_range flag. + * \param enable The flag value. + */ + void (*bo_use_48b_address_range) (drm_intel_bo *bo, uint32_t enable); + + /** * Add relocation entry in reloc_buf, which will be updated with the * target buffer's real offset on on command submission. * commit 7d74a83d22e694b2cd71e40992fd5a970d227e32 Author: Kristian Høgsberg Kristensen <kri...@in...> Date: Mon Dec 14 11:27:53 2015 -0800 intel: Update i915_drm.h Copy from drm-intel-nightly a307a3a81c2bf2883457e03abcf5c9520cf452c1. Signed-off-by: Kristian Høgsberg Kristensen <kri...@in...> diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index ded43b1..0e51d42 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -27,7 +27,7 @@ #ifndef _I915_DRM_H_ #define _I915_DRM_H_ -#include <drm.h> +#include "drm.h" /* Please note that modifications to all structs defined here are * subject to backwards-compatibility constraints. @@ -171,8 +171,12 @@ typedef struct _drm_i915_sarea { #define I915_BOX_TEXTURE_LOAD 0x8 #define I915_BOX_LOST_CONTEXT 0x10 -/* I915 specific ioctls - * The device specific ioctl range is 0x40 to 0x79. +/* + * i915 specific ioctls. + * + * The device specific ioctl range is [DRM_COMMAND_BASE, DRM_COMMAND_END) ie + * [0x40, 0xa0) (a0 is excluded). The numbers below are defined as offset + * against DRM_COMMAND_BASE and should be between [0x0, 0x60). */ #define DRM_I915_INIT 0x00 #define DRM_I915_FLUSH 0x01 @@ -270,7 +274,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image) #define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) #define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) -#define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) +#define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) #define DRM_IOCTL_I915_GEM_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait) #define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create) #define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy) @@ -350,9 +354,16 @@ typedef struct drm_i915_irq_wait { #define I915_PARAM_REVISION 32 #define I915_PARAM_SUBSLICE_TOTAL 33 #define I915_PARAM_EU_TOTAL 34 +#define I915_PARAM_HAS_GPU_RESET 35 +#define I915_PARAM_HAS_RESOURCE_STREAMER 36 +#define I915_PARAM_HAS_EXEC_SOFTPIN 37 typedef struct drm_i915_getparam { - int param; + __s32 param; + /* + * WARNING: Using pointers instead of fixed-size u64 means we need to write + * compat32 code. Don't repeat this mistake. + */ int *value; } drm_i915_getparam_t; @@ -672,15 +683,21 @@ struct drm_i915_gem_exec_object2 { __u64 alignment; /** - * Returned value of the updated offset of the object, for future - * presumed_offset writes. + * When the EXEC_OBJECT_PINNED flag is specified this is populated by + * the user with the GTT offset at which this object will be pinned. + * When the I915_EXEC_NO_RELOC flag is specified this must contain the + * presumed_offset of the object. + * During execbuffer2 the kernel populates it with the value of the + * current GTT offset of the object, for future presumed_offset writes. */ __u64 offset; #define EXEC_OBJECT_NEEDS_FENCE (1<<0) #define EXEC_OBJECT_NEEDS_GTT (1<<1) #define EXEC_OBJECT_WRITE (1<<2) -#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_WRITE<<1) +#define EXEC_OBJECT_SUPPORTS_48B_ADDRESS (1<<3) +#define EXEC_OBJECT_PINNED (1<<4) +#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_PINNED<<1) __u64 flags; __u64 rsvd1; @@ -760,7 +777,12 @@ struct drm_i915_gem_execbuffer2 { #define I915_EXEC_BSD_RING1 (1<<13) #define I915_EXEC_BSD_RING2 (2<<13) -#define __I915_EXEC_UNKNOWN_FLAGS -(1<<15) +/** Tell the kernel that the batchbuffer is processed by + * the resource streamer. + */ +#define I915_EXEC_RESOURCE_STREAMER (1<<15) + +#define __I915_EXEC_UNKNOWN_FLAGS -(I915_EXEC_RESOURCE_STREAMER<<1) #define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) #define i915_execbuffer2_set_context_id(eb2, context) \ @@ -996,6 +1018,7 @@ struct drm_intel_overlay_put_image { /* flags */ #define I915_OVERLAY_UPDATE_ATTRS (1<<0) #define I915_OVERLAY_UPDATE_GAMMA (1<<1) +#define I915_OVERLAY_DISABLE_DEST_COLORKEY (1<<2) struct drm_intel_overlay_attrs { __u32 flags; __u32 color_key; @@ -1062,9 +1085,23 @@ struct drm_i915_gem_context_destroy { }; 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 val; /* Return value */ }; +/* Known registers: + * + * Render engine timestamp - 0x2358 + 64bit - gen7+ + * - Note this register returns an invalid value if using the default + * single instruction 8byte read, in order to workaround that use + * offset (0x2538 | 1) instead. + * + */ struct drm_i915_reset_stats { __u32 ctx_id; @@ -1100,7 +1137,9 @@ struct drm_i915_gem_context_param { __u32 ctx_id; __u32 size; __u64 param; -#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1 +#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1 +#define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2 +#define I915_CONTEXT_PARAM_GTT_SIZE 0x3 __u64 value; }; |
From: <ma...@ke...> - 2016-01-20 01:19:07
|
amdgpu/amdgpu.h | 65 ++++++++++++++++ amdgpu/amdgpu_bo.c | 14 --- amdgpu/amdgpu_cs.c | 173 +++++++++++++++++++++++++++++++++++++++++++-- amdgpu/amdgpu_internal.h | 15 +++ configure.ac | 3 intel/intel_decode.c | 2 tests/amdgpu/basic_tests.c | 133 ++++++++++++++++++++++++++++++++++ 7 files changed, 387 insertions(+), 18 deletions(-) New commits: commit 6b79c66b841dded6ffa6b56f14e4eb10a90a7c07 Author: Junwei Zhang <Jer...@am...> Date: Tue Dec 8 08:34:55 2015 +0800 amdgpu: list each entry safely for sw semaphore when submit ib Signed-off-by: Junwei Zhang <Jer...@am...> Reviewed-by: Michel Dänzer <mic...@am...> Reviewed-by: David Zhou <dav...@am...> Reviewed-by: Christian König <chr...@am...> diff --git a/amdgpu/amdgpu_cs.c b/amdgpu/amdgpu_cs.c index 1848ade..b4f41b0 100644 --- a/amdgpu/amdgpu_cs.c +++ b/amdgpu/amdgpu_cs.c @@ -179,7 +179,7 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context, struct drm_amdgpu_cs_chunk_dep *dependencies = NULL; struct drm_amdgpu_cs_chunk_dep *sem_dependencies = NULL; struct list_head *sem_list; - amdgpu_semaphore_handle sem; + amdgpu_semaphore_handle sem, tmp; uint32_t i, size, sem_count = 0; bool user_fence; int r = 0; @@ -282,7 +282,7 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context, goto error_unlock; } sem_count = 0; - LIST_FOR_EACH_ENTRY(sem, sem_list, list) { + LIST_FOR_EACH_ENTRY_SAFE(sem, tmp, sem_list, list) { struct amdgpu_cs_fence *info = &sem->signal_fence; struct drm_amdgpu_cs_chunk_dep *dep = &sem_dependencies[sem_count++]; dep->ip_type = info->ip_type; commit d4d4184363a62ece6b8830cacaf390b5638d7f8e Author: Chunming Zhou <dav...@am...> Date: Mon Aug 10 17:08:25 2015 +0800 tests/amdgpu: add semaphore test Signed-off-by: Chunming Zhou <dav...@am...> Reviewed-by: Jammy Zhou <Jam...@am...> Reviewed-by: Christian König <chr...@am...> diff --git a/tests/amdgpu/basic_tests.c b/tests/amdgpu/basic_tests.c index e489e6e..fa0ed12 100644 --- a/tests/amdgpu/basic_tests.c +++ b/tests/amdgpu/basic_tests.c @@ -47,6 +47,7 @@ static void amdgpu_command_submission_gfx(void); static void amdgpu_command_submission_compute(void); static void amdgpu_command_submission_sdma(void); static void amdgpu_userptr_test(void); +static void amdgpu_semaphore_test(void); CU_TestInfo basic_tests[] = { { "Query Info Test", amdgpu_query_info_test }, @@ -55,6 +56,7 @@ CU_TestInfo basic_tests[] = { { "Command submission Test (GFX)", amdgpu_command_submission_gfx }, { "Command submission Test (Compute)", amdgpu_command_submission_compute }, { "Command submission Test (SDMA)", amdgpu_command_submission_sdma }, + { "SW semaphore Test", amdgpu_semaphore_test }, CU_TEST_INFO_NULL, }; #define BUFFER_SIZE (8 * 1024) @@ -77,6 +79,9 @@ CU_TestInfo basic_tests[] = { #define SDMA_OPCODE_COPY 1 # define SDMA_COPY_SUB_OPCODE_LINEAR 0 +#define GFX_COMPUTE_NOP 0xffff1000 +#define SDMA_NOP 0x0 + int suite_basic_tests_init(void) { int r; @@ -333,6 +338,134 @@ static void amdgpu_command_submission_gfx(void) amdgpu_command_submission_gfx_shared_ib(); } +static void amdgpu_semaphore_test(void) +{ + amdgpu_context_handle context_handle[2]; + amdgpu_semaphore_handle sem; + amdgpu_bo_handle ib_result_handle[2]; + void *ib_result_cpu[2]; + uint64_t ib_result_mc_address[2]; + struct amdgpu_cs_request ibs_request[2] = {0}; + struct amdgpu_cs_ib_info ib_info[2] = {0}; + struct amdgpu_cs_fence fence_status = {0}; + uint32_t *ptr; + uint32_t expired; + amdgpu_bo_list_handle bo_list[2]; + amdgpu_va_handle va_handle[2]; + int r, i; + + r = amdgpu_cs_create_semaphore(&sem); + CU_ASSERT_EQUAL(r, 0); + for (i = 0; i < 2; i++) { + r = amdgpu_cs_ctx_create(device_handle, &context_handle[i]); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &ib_result_handle[i], &ib_result_cpu[i], + &ib_result_mc_address[i], &va_handle[i]); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_get_bo_list(device_handle, ib_result_handle[i], + NULL, &bo_list[i]); + CU_ASSERT_EQUAL(r, 0); + } + + /* 1. same context different engine */ + ptr = ib_result_cpu[0]; + ptr[0] = SDMA_NOP; + ib_info[0].ib_mc_address = ib_result_mc_address[0]; + ib_info[0].size = 1; + + ibs_request[0].ip_type = AMDGPU_HW_IP_DMA; + ibs_request[0].number_of_ibs = 1; + ibs_request[0].ibs = &ib_info[0]; + ibs_request[0].resources = bo_list[0]; + ibs_request[0].fence_info.handle = NULL; + r = amdgpu_cs_submit(context_handle[0], 0,&ibs_request[0], 1); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_cs_signal_semaphore(context_handle[0], AMDGPU_HW_IP_DMA, 0, 0, sem); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_wait_semaphore(context_handle[0], AMDGPU_HW_IP_GFX, 0, 0, sem); + CU_ASSERT_EQUAL(r, 0); + ptr = ib_result_cpu[1]; + ptr[0] = GFX_COMPUTE_NOP; + ib_info[1].ib_mc_address = ib_result_mc_address[1]; + ib_info[1].size = 1; + + ibs_request[1].ip_type = AMDGPU_HW_IP_GFX; + ibs_request[1].number_of_ibs = 1; + ibs_request[1].ibs = &ib_info[1]; + ibs_request[1].resources = bo_list[1]; + ibs_request[1].fence_info.handle = NULL; + + r = amdgpu_cs_submit(context_handle[0], 0,&ibs_request[1], 1); + CU_ASSERT_EQUAL(r, 0); + + fence_status.context = context_handle[0]; + fence_status.ip_type = AMDGPU_HW_IP_GFX; + fence_status.fence = ibs_request[1].seq_no; + r = amdgpu_cs_query_fence_status(&fence_status, + 500000000, 0, &expired); + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_EQUAL(expired, true); + + /* 2. same engine different context */ + ptr = ib_result_cpu[0]; + ptr[0] = GFX_COMPUTE_NOP; + ib_info[0].ib_mc_address = ib_result_mc_address[0]; + ib_info[0].size = 1; + + ibs_request[0].ip_type = AMDGPU_HW_IP_GFX; + ibs_request[0].number_of_ibs = 1; + ibs_request[0].ibs = &ib_info[0]; + ibs_request[0].resources = bo_list[0]; + ibs_request[0].fence_info.handle = NULL; + r = amdgpu_cs_submit(context_handle[0], 0,&ibs_request[0], 1); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_cs_signal_semaphore(context_handle[0], AMDGPU_HW_IP_GFX, 0, 0, sem); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_wait_semaphore(context_handle[1], AMDGPU_HW_IP_GFX, 0, 0, sem); + CU_ASSERT_EQUAL(r, 0); + ptr = ib_result_cpu[1]; + ptr[0] = GFX_COMPUTE_NOP; + ib_info[1].ib_mc_address = ib_result_mc_address[1]; + ib_info[1].size = 1; + + ibs_request[1].ip_type = AMDGPU_HW_IP_GFX; + ibs_request[1].number_of_ibs = 1; + ibs_request[1].ibs = &ib_info[1]; + ibs_request[1].resources = bo_list[1]; + ibs_request[1].fence_info.handle = NULL; + r = amdgpu_cs_submit(context_handle[1], 0,&ibs_request[1], 1); + + CU_ASSERT_EQUAL(r, 0); + + fence_status.context = context_handle[1]; + fence_status.ip_type = AMDGPU_HW_IP_GFX; + fence_status.fence = ibs_request[1].seq_no; + r = amdgpu_cs_query_fence_status(&fence_status, + 500000000, 0, &expired); + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_EQUAL(expired, true); + for (i = 0; i < 2; i++) { + r = amdgpu_bo_unmap_and_free(ib_result_handle[i], va_handle[i], + ib_result_mc_address[i], 4096); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_list_destroy(bo_list[i]); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_free(context_handle[i]); + CU_ASSERT_EQUAL(r, 0); + } + + r = amdgpu_cs_destroy_semaphore(sem); + CU_ASSERT_EQUAL(r, 0); +} + static void amdgpu_command_submission_compute(void) { amdgpu_context_handle context_handle; commit 6afadeaf13279fcdbc48999f522e1dc90a9dfdaf Author: Marek Olšák <mar...@am...> Date: Tue Jan 12 22:13:07 2016 +0100 amdgpu: add semaphore support the semaphore is a binary semaphore. the work flow is: 1. create sem 2. signal sem 3. wait sem, reset sem after signalled 4. destroy sem. Signed-off-by: Chunming Zhou <dav...@am...> Reviewed-by: Jammy Zhou <Jam...@am...> Reviewed-by: Christian König <chr...@am...> diff --git a/amdgpu/amdgpu.h b/amdgpu/amdgpu.h index e44d802..0851306 100644 --- a/amdgpu/amdgpu.h +++ b/amdgpu/amdgpu.h @@ -124,6 +124,11 @@ typedef struct amdgpu_bo_list *amdgpu_bo_list_handle; */ typedef struct amdgpu_va *amdgpu_va_handle; +/** + * Define handle for semaphore + */ +typedef struct amdgpu_semaphore *amdgpu_semaphore_handle; + /*--------------------------------------------------------------------------*/ /* -------------------------- Structures ---------------------------------- */ /*--------------------------------------------------------------------------*/ @@ -1180,4 +1185,64 @@ int amdgpu_bo_va_op(amdgpu_bo_handle bo, uint64_t flags, uint32_t ops); +/** + * create semaphore + * + * \param sem - \c [out] semaphore handle + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_cs_create_semaphore(amdgpu_semaphore_handle *sem); + +/** + * signal semaphore + * + * \param context - \c [in] GPU Context + * \param ip_type - \c [in] Hardware IP block type = AMDGPU_HW_IP_* + * \param ip_instance - \c [in] Index of the IP block of the same type + * \param ring - \c [in] Specify ring index of the IP + * \param sem - \c [in] semaphore handle + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_cs_signal_semaphore(amdgpu_context_handle ctx, + uint32_t ip_type, + uint32_t ip_instance, + uint32_t ring, + amdgpu_semaphore_handle sem); + +/** + * wait semaphore + * + * \param context - \c [in] GPU Context + * \param ip_type - \c [in] Hardware IP block type = AMDGPU_HW_IP_* + * \param ip_instance - \c [in] Index of the IP block of the same type + * \param ring - \c [in] Specify ring index of the IP + * \param sem - \c [in] semaphore handle + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_cs_wait_semaphore(amdgpu_context_handle ctx, + uint32_t ip_type, + uint32_t ip_instance, + uint32_t ring, + amdgpu_semaphore_handle sem); + +/** + * destroy semaphore + * + * \param sem - \c [in] semaphore handle + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_cs_destroy_semaphore(amdgpu_semaphore_handle sem); + #endif /* #ifdef _AMDGPU_H_ */ diff --git a/amdgpu/amdgpu_cs.c b/amdgpu/amdgpu_cs.c index 6747158..1848ade 100644 --- a/amdgpu/amdgpu_cs.c +++ b/amdgpu/amdgpu_cs.c @@ -40,6 +40,9 @@ #include "amdgpu_drm.h" #include "amdgpu_internal.h" +static int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem); +static int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem); + /** * Create command submission context * @@ -53,6 +56,7 @@ int amdgpu_cs_ctx_create(amdgpu_device_handle dev, { struct amdgpu_context *gpu_context; union drm_amdgpu_ctx args; + int i, j, k; int r; if (NULL == dev) @@ -66,6 +70,10 @@ int amdgpu_cs_ctx_create(amdgpu_device_handle dev, gpu_context->dev = dev; + r = pthread_mutex_init(&gpu_context->sequence_mutex, NULL); + if (r) + goto error; + /* Create the context */ memset(&args, 0, sizeof(args)); args.in.op = AMDGPU_CTX_OP_ALLOC_CTX; @@ -74,11 +82,16 @@ int amdgpu_cs_ctx_create(amdgpu_device_handle dev, goto error; gpu_context->id = args.out.alloc.ctx_id; + for (i = 0; i < AMDGPU_HW_IP_NUM; i++) + for (j = 0; j < AMDGPU_HW_IP_INSTANCE_MAX_COUNT; j++) + for (k = 0; k < AMDGPU_CS_MAX_RINGS; k++) + list_inithead(&gpu_context->sem_list[i][j][k]); *context = (amdgpu_context_handle)gpu_context; return 0; error: + pthread_mutex_destroy(&gpu_context->sequence_mutex); free(gpu_context); return r; } @@ -94,18 +107,32 @@ error: int amdgpu_cs_ctx_free(amdgpu_context_handle context) { union drm_amdgpu_ctx args; + int i, j, k; int r; if (NULL == context) return -EINVAL; + pthread_mutex_destroy(&context->sequence_mutex); + /* now deal with kernel side */ memset(&args, 0, sizeof(args)); args.in.op = AMDGPU_CTX_OP_FREE_CTX; args.in.ctx_id = context->id; r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CTX, &args, sizeof(args)); - + for (i = 0; i < AMDGPU_HW_IP_NUM; i++) { + for (j = 0; j < AMDGPU_HW_IP_INSTANCE_MAX_COUNT; j++) { + for (k = 0; k < AMDGPU_CS_MAX_RINGS; k++) { + amdgpu_semaphore_handle sem; + LIST_FOR_EACH_ENTRY(sem, &context->sem_list[i][j][k], list) { + list_del(&sem->list); + amdgpu_cs_reset_sem(sem); + amdgpu_cs_unreference_sem(sem); + } + } + } + } free(context); return r; @@ -150,7 +177,10 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context, struct drm_amdgpu_cs_chunk *chunks; struct drm_amdgpu_cs_chunk_data *chunk_data; struct drm_amdgpu_cs_chunk_dep *dependencies = NULL; - uint32_t i, size; + struct drm_amdgpu_cs_chunk_dep *sem_dependencies = NULL; + struct list_head *sem_list; + amdgpu_semaphore_handle sem; + uint32_t i, size, sem_count = 0; bool user_fence; int r = 0; @@ -162,7 +192,7 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context, return -EINVAL; user_fence = (ibs_request->fence_info.handle != NULL); - size = ibs_request->number_of_ibs + (user_fence ? 2 : 1); + size = ibs_request->number_of_ibs + (user_fence ? 2 : 1) + 1; chunk_array = alloca(sizeof(uint64_t) * size); chunks = alloca(sizeof(struct drm_amdgpu_cs_chunk) * size); @@ -196,6 +226,8 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context, chunk_data[i].ib_data.flags = ib->flags; } + pthread_mutex_lock(&context->sequence_mutex); + if (user_fence) { i = cs.in.num_chunks++; @@ -240,15 +272,49 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context, chunks[i].chunk_data = (uint64_t)(uintptr_t)dependencies; } + sem_list = &context->sem_list[ibs_request->ip_type][ibs_request->ip_instance][ibs_request->ring]; + LIST_FOR_EACH_ENTRY(sem, sem_list, list) + sem_count++; + if (sem_count) { + sem_dependencies = malloc(sizeof(struct drm_amdgpu_cs_chunk_dep) * sem_count); + if (!sem_dependencies) { + r = -ENOMEM; + goto error_unlock; + } + sem_count = 0; + LIST_FOR_EACH_ENTRY(sem, sem_list, list) { + struct amdgpu_cs_fence *info = &sem->signal_fence; + struct drm_amdgpu_cs_chunk_dep *dep = &sem_dependencies[sem_count++]; + dep->ip_type = info->ip_type; + dep->ip_instance = info->ip_instance; + dep->ring = info->ring; + dep->ctx_id = info->context->id; + dep->handle = info->fence; + + list_del(&sem->list); + amdgpu_cs_reset_sem(sem); + amdgpu_cs_unreference_sem(sem); + } + i = cs.in.num_chunks++; + + /* dependencies chunk */ + chunk_array[i] = (uint64_t)(uintptr_t)&chunks[i]; + chunks[i].chunk_id = AMDGPU_CHUNK_ID_DEPENDENCIES; + chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_dep) / 4 * sem_count; + chunks[i].chunk_data = (uint64_t)(uintptr_t)sem_dependencies; + } + r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CS, &cs, sizeof(cs)); if (r) goto error_unlock; ibs_request->seq_no = cs.out.handle; - + context->last_seq[ibs_request->ip_type][ibs_request->ip_instance][ibs_request->ring] = ibs_request->seq_no; error_unlock: + pthread_mutex_unlock(&context->sequence_mutex); free(dependencies); + free(sem_dependencies); return r; } @@ -369,3 +435,102 @@ int amdgpu_cs_query_fence_status(struct amdgpu_cs_fence *fence, return r; } +int amdgpu_cs_create_semaphore(amdgpu_semaphore_handle *sem) +{ + struct amdgpu_semaphore *gpu_semaphore; + + if (NULL == sem) + return -EINVAL; + + gpu_semaphore = calloc(1, sizeof(struct amdgpu_semaphore)); + if (NULL == gpu_semaphore) + return -ENOMEM; + + atomic_set(&gpu_semaphore->refcount, 1); + *sem = gpu_semaphore; + + return 0; +} + +int amdgpu_cs_signal_semaphore(amdgpu_context_handle ctx, + uint32_t ip_type, + uint32_t ip_instance, + uint32_t ring, + amdgpu_semaphore_handle sem) +{ + if (NULL == ctx) + return -EINVAL; + if (ip_type >= AMDGPU_HW_IP_NUM) + return -EINVAL; + if (ring >= AMDGPU_CS_MAX_RINGS) + return -EINVAL; + if (NULL == sem) + return -EINVAL; + /* sem has been signaled */ + if (sem->signal_fence.context) + return -EINVAL; + pthread_mutex_lock(&ctx->sequence_mutex); + sem->signal_fence.context = ctx; + sem->signal_fence.ip_type = ip_type; + sem->signal_fence.ip_instance = ip_instance; + sem->signal_fence.ring = ring; + sem->signal_fence.fence = ctx->last_seq[ip_type][ip_instance][ring]; + update_references(NULL, &sem->refcount); + pthread_mutex_unlock(&ctx->sequence_mutex); + return 0; +} + +int amdgpu_cs_wait_semaphore(amdgpu_context_handle ctx, + uint32_t ip_type, + uint32_t ip_instance, + uint32_t ring, + amdgpu_semaphore_handle sem) +{ + if (NULL == ctx) + return -EINVAL; + if (ip_type >= AMDGPU_HW_IP_NUM) + return -EINVAL; + if (ring >= AMDGPU_CS_MAX_RINGS) + return -EINVAL; + if (NULL == sem) + return -EINVAL; + /* must signal first */ + if (NULL == sem->signal_fence.context) + return -EINVAL; + + pthread_mutex_lock(&ctx->sequence_mutex); + list_add(&sem->list, &ctx->sem_list[ip_type][ip_instance][ring]); + pthread_mutex_unlock(&ctx->sequence_mutex); + return 0; +} + +static int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem) +{ + if (NULL == sem) + return -EINVAL; + if (NULL == sem->signal_fence.context) + return -EINVAL; + + sem->signal_fence.context = NULL;; + sem->signal_fence.ip_type = 0; + sem->signal_fence.ip_instance = 0; + sem->signal_fence.ring = 0; + sem->signal_fence.fence = 0; + + return 0; +} + +static int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem) +{ + if (NULL == sem) + return -EINVAL; + + if (update_references(&sem->refcount, NULL)) + free(sem); + return 0; +} + +int amdgpu_cs_destroy_semaphore(amdgpu_semaphore_handle sem) +{ + return amdgpu_cs_unreference_sem(sem); +} diff --git a/amdgpu/amdgpu_internal.h b/amdgpu/amdgpu_internal.h index 7dd5c1c..557ba1f 100644 --- a/amdgpu/amdgpu_internal.h +++ b/amdgpu/amdgpu_internal.h @@ -111,8 +111,23 @@ struct amdgpu_bo_list { struct amdgpu_context { struct amdgpu_device *dev; + /** Mutex for accessing fences and to maintain command submissions + in good sequence. */ + pthread_mutex_t sequence_mutex; /* context id*/ uint32_t id; + uint64_t last_seq[AMDGPU_HW_IP_NUM][AMDGPU_HW_IP_INSTANCE_MAX_COUNT][AMDGPU_CS_MAX_RINGS]; + struct list_head sem_list[AMDGPU_HW_IP_NUM][AMDGPU_HW_IP_INSTANCE_MAX_COUNT][AMDGPU_CS_MAX_RINGS]; +}; + +/** + * Structure describing sw semaphore based on scheduler + * + */ +struct amdgpu_semaphore { + atomic_t refcount; + struct list_head list; + struct amdgpu_cs_fence signal_fence; }; /** commit f06c9928198d9348fb31325a2a480afbc29c04b8 Author: Chunming Zhou <Dav...@am...> Date: Mon Nov 30 14:08:07 2015 +0800 amdgpu: validate user memory for userptr Signed-off-by: Chunming Zhou <Dav...@am...> Reviewed-by: Christian König <chr...@am...> diff --git a/amdgpu/amdgpu_bo.c b/amdgpu/amdgpu_bo.c index 2ae1c18..d30fd1e 100644 --- a/amdgpu/amdgpu_bo.c +++ b/amdgpu/amdgpu_bo.c @@ -539,7 +539,8 @@ int amdgpu_create_bo_from_user_mem(amdgpu_device_handle dev, struct drm_amdgpu_gem_userptr args; args.addr = (uintptr_t)cpu; - args.flags = AMDGPU_GEM_USERPTR_ANONONLY | AMDGPU_GEM_USERPTR_REGISTER; + args.flags = AMDGPU_GEM_USERPTR_ANONONLY | AMDGPU_GEM_USERPTR_REGISTER | + AMDGPU_GEM_USERPTR_VALIDATE; args.size = size; r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_GEM_USERPTR, &args, sizeof(args)); commit 50386e09dbdc6fd70d02efd1371d9ad061c8d447 Author: monk.liu <mon...@am...> Date: Tue Aug 25 16:53:07 2015 +0800 amdgpu: drop address patching logics we don't support non-page-aligned cpu pointer anymore Signed-off-by: monk.liu <mon...@am...> Reviewed-by: Christian König <chr...@am...> diff --git a/amdgpu/amdgpu_bo.c b/amdgpu/amdgpu_bo.c index 1a5a401..2ae1c18 100644 --- a/amdgpu/amdgpu_bo.c +++ b/amdgpu/amdgpu_bo.c @@ -537,17 +537,8 @@ int amdgpu_create_bo_from_user_mem(amdgpu_device_handle dev, int r; struct amdgpu_bo *bo; struct drm_amdgpu_gem_userptr args; - uintptr_t cpu0; - uint32_t ps, off; - memset(&args, 0, sizeof(args)); - ps = getpagesize(); - - cpu0 = ROUND_DOWN((uintptr_t)cpu, ps); - off = (uintptr_t)cpu - cpu0; - size = ROUND_UP(size + off, ps); - - args.addr = cpu0; + args.addr = (uintptr_t)cpu; args.flags = AMDGPU_GEM_USERPTR_ANONONLY | AMDGPU_GEM_USERPTR_REGISTER; args.size = size; r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_GEM_USERPTR, commit 5198f2b2e658651d9cb81d67998ba7b2c39e12d7 Author: Marek Olšák <mar...@am...> Date: Tue Jan 12 22:09:24 2016 +0100 configure.ac: disable annoying warning -Wmissing-field-initializers It warns for all "{}" initializers. Reviewed-by: David Herrmann <dh....@gm...> Reviewed-by: Ilia Mirkin <im...@al...> diff --git a/configure.ac b/configure.ac index c8c4ace..057a846 100644 --- a/configure.ac +++ b/configure.ac @@ -174,7 +174,8 @@ MAYBE_WARN="-Wall -Wextra \ -Wstrict-aliasing=2 -Winit-self \ -Wdeclaration-after-statement -Wold-style-definition \ -Wno-unused-parameter \ --Wno-attributes -Wno-long-long -Winline -Wshadow" +-Wno-attributes -Wno-long-long -Winline -Wshadow \ +-Wno-missing-field-initializers" # invalidate cached value if MAYBE_WARN has changed if test "x$libdrm_cv_warn_maybe" != "x$MAYBE_WARN"; then diff --git a/intel/intel_decode.c b/intel/intel_decode.c index e7aef74..287c342 100644 --- a/intel/intel_decode.c +++ b/intel/intel_decode.c @@ -38,8 +38,6 @@ #include "intel_chipset.h" #include "intel_bufmgr.h" -/* The compiler throws ~90 warnings. Do not spam the build, until we fix them. */ -#pragma GCC diagnostic ignored "-Wmissing-field-initializers" /* Struct for tracking drm_intel_decode state. */ struct drm_intel_decode { |
From: <ab...@ke...> - 2016-07-23 07:50:39
|
Makefile.am | 2 Makefile.sources | 3 - freedreno/Makefile.am | 2 include/drm/virtgpu_drm.h | 109 +++++++++++++++++++++++---------------------- intel/Makefile.am | 1 libkms/Makefile.am | 2 man/drm-kms.xml | 2 nouveau/Makefile.am | 2 radeon/Makefile.am | 3 - radeon/radeon_cs_gem.c | 2 tests/modetest/Makefile.am | 2 11 files changed, 67 insertions(+), 63 deletions(-) New commits: commit 248b3343ce4b855c89bdad4e8251885d1fa6904e Author: Andreas Boll <and...@gm...> Date: Thu Jul 21 14:27:33 2016 +0200 radeon: Fix typo in stderr message Signed-off-by: Andreas Boll <and...@gm...> Reviewed-by: Emil Velikov <emi...@gm...> diff --git a/radeon/radeon_cs_gem.c b/radeon/radeon_cs_gem.c index cdec64e..23f33af 100644 --- a/radeon/radeon_cs_gem.c +++ b/radeon/radeon_cs_gem.c @@ -323,7 +323,7 @@ static int cs_gem_end(struct radeon_cs_int *cs, return -EPIPE; } if (cs->section_ndw != cs->section_cdw) { - fprintf(stderr, "CS section size missmatch start at (%s,%s,%d) %d vs %d\n", + fprintf(stderr, "CS section size mismatch start at (%s,%s,%d) %d vs %d\n", cs->section_file, cs->section_func, cs->section_line, cs->section_ndw, cs->section_cdw); fprintf(stderr, "CS section end at (%s,%s,%d)\n", file, func, line); commit 22263ca11a44abb57639f19318ad1dd4ef7fe956 Author: Andreas Boll <and...@gm...> Date: Thu Jul 21 14:25:41 2016 +0200 man: Fix typo Signed-off-by: Andreas Boll <and...@gm...> Reviewed-by: Emil Velikov <emi...@gm...> diff --git a/man/drm-kms.xml b/man/drm-kms.xml index 5f04157..ae38dc8 100644 --- a/man/drm-kms.xml +++ b/man/drm-kms.xml @@ -126,7 +126,7 @@ <listitem> <para><emphasis>Framebuffers</emphasis> are abstract memory objects that provide a source of pixel data to scanout to a CRTC. - Applications explicitely request the creation of framebuffers + Applications explicitly request the creation of framebuffers and can control their behavior. Framebuffers rely on the underneath memory manager for low-level memory operations. When creating a framebuffer, applications pass a memory handle commit 7e9e373935bc47e59156c53ba299a3df0b18a4c3 Author: Andreas Boll <and...@gm...> Date: Thu Jul 21 14:03:33 2016 +0200 automake: Include virtgpu_drm.h in the release tarball The plan is to use this version of virtgpu_drm.h in mesa and drop mesa's local copy. To actually use this header it needs to be shipped in the tarball. This was missed in c745e541a9d8dfd3fb5e1ac57297e58d34d9328f Signed-off-by: Andreas Boll <and...@gm...> Reviewed-by: Emil Velikov <emi...@gm...> diff --git a/Makefile.sources b/Makefile.sources index 1a1f0fe..a57036a 100644 --- a/Makefile.sources +++ b/Makefile.sources @@ -33,7 +33,8 @@ LIBDRM_INCLUDE_H_FILES := \ include/drm/sis_drm.h \ include/drm/tegra_drm.h \ include/drm/vc4_drm.h \ - include/drm/via_drm.h + include/drm/via_drm.h \ + include/drm/virtgpu_drm.h LIBDRM_INCLUDE_VMWGFX_H_FILES := \ include/drm/vmwgfx_drm.h commit 9af2ccdef3428ade565d8213803a9dd094427f26 Author: Andreas Boll <and...@gm...> Date: Fri Jul 22 11:45:36 2016 +0200 virtgpu: Update kernel header Generated using make headers_install. This brings the C++ guard, proper include path for drm.h and the switching to kernel types for fixed-with integers. Generated from drm-next commit c11dea5b0290984fa48111957ba3fdc5b3bdae5a Suggested-by: Emil Velikov <emi...@gm...> Signed-off-by: Andreas Boll <and...@gm...> Reviewed-by: Emil Velikov <emi...@gm...> diff --git a/include/drm/virtgpu_drm.h b/include/drm/virtgpu_drm.h index abf11c5..91a31ff 100644 --- a/include/drm/virtgpu_drm.h +++ b/include/drm/virtgpu_drm.h @@ -24,13 +24,16 @@ #ifndef VIRTGPU_DRM_H #define VIRTGPU_DRM_H -#include <stddef.h> -#include "drm/drm.h" +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif /* Please note that modifications to all structs defined here are * subject to backwards-compatibility constraints. * - * Do not use pointers, use uint64_t instead for 32 bit / 64 bit user/kernel + * Do not use pointers, use __u64 instead for 32 bit / 64 bit user/kernel * compatibility Keep fields aligned to their size */ @@ -45,88 +48,88 @@ #define DRM_VIRTGPU_GET_CAPS 0x09 struct drm_virtgpu_map { - uint64_t offset; /* use for mmap system call */ - uint32_t handle; - uint32_t pad; + __u64 offset; /* use for mmap system call */ + __u32 handle; + __u32 pad; }; struct drm_virtgpu_execbuffer { - uint32_t flags; /* for future use */ - uint32_t size; - uint64_t command; /* void* */ - uint64_t bo_handles; - uint32_t num_bo_handles; - uint32_t pad; + __u32 flags; /* for future use */ + __u32 size; + __u64 command; /* void* */ + __u64 bo_handles; + __u32 num_bo_handles; + __u32 pad; }; #define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */ struct drm_virtgpu_getparam { - uint64_t param; - uint64_t value; + __u64 param; + __u64 value; }; /* NO_BO flags? NO resource flag? */ /* resource flag for y_0_top */ struct drm_virtgpu_resource_create { - uint32_t target; - uint32_t format; - uint32_t bind; - uint32_t width; - uint32_t height; - uint32_t depth; - uint32_t array_size; - uint32_t last_level; - uint32_t nr_samples; - uint32_t flags; - uint32_t bo_handle; /* if this is set - recreate a new resource attached to this bo ? */ - uint32_t res_handle; /* returned by kernel */ - uint32_t size; /* validate transfer in the host */ - uint32_t stride; /* validate transfer in the host */ + __u32 target; + __u32 format; + __u32 bind; + __u32 width; + __u32 height; + __u32 depth; + __u32 array_size; + __u32 last_level; + __u32 nr_samples; + __u32 flags; + __u32 bo_handle; /* if this is set - recreate a new resource attached to this bo ? */ + __u32 res_handle; /* returned by kernel */ + __u32 size; /* validate transfer in the host */ + __u32 stride; /* validate transfer in the host */ }; struct drm_virtgpu_resource_info { - uint32_t bo_handle; - uint32_t res_handle; - uint32_t size; - uint32_t stride; + __u32 bo_handle; + __u32 res_handle; + __u32 size; + __u32 stride; }; struct drm_virtgpu_3d_box { - uint32_t x; - uint32_t y; - uint32_t z; - uint32_t w; - uint32_t h; - uint32_t d; + __u32 x; + __u32 y; + __u32 z; + __u32 w; + __u32 h; + __u32 d; }; struct drm_virtgpu_3d_transfer_to_host { - uint32_t bo_handle; + __u32 bo_handle; struct drm_virtgpu_3d_box box; - uint32_t level; - uint32_t offset; + __u32 level; + __u32 offset; }; struct drm_virtgpu_3d_transfer_from_host { - uint32_t bo_handle; + __u32 bo_handle; struct drm_virtgpu_3d_box box; - uint32_t level; - uint32_t offset; + __u32 level; + __u32 offset; }; #define VIRTGPU_WAIT_NOWAIT 1 /* like it */ struct drm_virtgpu_3d_wait { - uint32_t handle; /* 0 is an invalid handle */ - uint32_t flags; + __u32 handle; /* 0 is an invalid handle */ + __u32 flags; }; struct drm_virtgpu_get_caps { - uint32_t cap_set_id; - uint32_t cap_set_ver; - uint64_t addr; - uint32_t size; - uint32_t pad; + __u32 cap_set_id; + __u32 cap_set_ver; + __u64 addr; + __u32 size; + __u32 pad; }; #define DRM_IOCTL_VIRTGPU_MAP \ @@ -164,4 +167,8 @@ struct drm_virtgpu_get_caps { DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GET_CAPS, \ struct drm_virtgpu_get_caps) +#if defined(__cplusplus) +} +#endif + #endif commit a5446775f27b52c120c75b8f82656aa64f93319d Author: Andreas Boll <and...@gm...> Date: Thu Jul 21 12:05:03 2016 +0200 automake: Don't include Android Makefiles in the release tarball Currently only some Android Makefiles are included in the release tarball. To be more consistent one could either add the remaining files or don't ship Android Makefiles altogether. According to Emil the Android folk doesn't use our release tarballs. Thus it makes sense to remove those files from distribution which also means less work for maintenance in the future. Suggested-by: Emil Velikov <emi...@gm...> Signed-off-by: Andreas Boll <and...@gm...> Reviewed-by: Emil Velikov <emi...@gm...> diff --git a/Makefile.am b/Makefile.am index feecba7..2ceb352 100644 --- a/Makefile.am +++ b/Makefile.am @@ -120,8 +120,6 @@ libdrm_la_SOURCES = $(LIBDRM_FILES) libdrmincludedir = ${includedir} libdrminclude_HEADERS = $(LIBDRM_H_FILES) -EXTRA_DIST = Android.mk - klibdrmincludedir = ${includedir}/libdrm klibdrminclude_HEADERS = $(LIBDRM_INCLUDE_H_FILES) diff --git a/freedreno/Makefile.am b/freedreno/Makefile.am index 9b7ec7d..0771d14 100644 --- a/freedreno/Makefile.am +++ b/freedreno/Makefile.am @@ -27,4 +27,4 @@ pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libdrm_freedreno.pc TESTS = freedreno-symbol-check -EXTRA_DIST = Android.mk $(TESTS) +EXTRA_DIST = $(TESTS) diff --git a/intel/Makefile.am b/intel/Makefile.am index d004568..c52e8c0 100644 --- a/intel/Makefile.am +++ b/intel/Makefile.am @@ -66,7 +66,6 @@ EXTRA_DIST = \ $(BATCHES:.batch=.batch-ref.txt) \ $(BATCHES:.batch=.batch-ref.txt) \ tests/test-batch.sh \ - Android.mk \ $(TESTS) test_decode_LDADD = libdrm_intel.la ../libdrm.la diff --git a/libkms/Makefile.am b/libkms/Makefile.am index 6c0ab7a..7c1debe 100644 --- a/libkms/Makefile.am +++ b/libkms/Makefile.am @@ -44,4 +44,4 @@ pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libkms.pc TESTS = kms-symbol-check -EXTRA_DIST = Android.mk $(TESTS) +EXTRA_DIST = $(TESTS) diff --git a/nouveau/Makefile.am b/nouveau/Makefile.am index 76cdeca..344a844 100644 --- a/nouveau/Makefile.am +++ b/nouveau/Makefile.am @@ -30,4 +30,4 @@ pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libdrm_nouveau.pc TESTS = nouveau-symbol-check -EXTRA_DIST = Android.mk $(TESTS) +EXTRA_DIST = $(TESTS) diff --git a/radeon/Makefile.am b/radeon/Makefile.am index 31f19e5..e241531 100644 --- a/radeon/Makefile.am +++ b/radeon/Makefile.am @@ -44,4 +44,4 @@ pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libdrm_radeon.pc TESTS = radeon-symbol-check -EXTRA_DIST = Android.mk $(LIBDRM_RADEON_BOF_FILES) $(TESTS) +EXTRA_DIST = $(LIBDRM_RADEON_BOF_FILES) $(TESTS) diff --git a/tests/modetest/Makefile.am b/tests/modetest/Makefile.am index 25ce372..9686ccb 100644 --- a/tests/modetest/Makefile.am +++ b/tests/modetest/Makefile.am @@ -22,5 +22,3 @@ modetest_LDADD = \ $(top_builddir)/tests/util/libutil.la \ $(CAIRO_LIBS) \ -lpthread - -EXTRA_DIST = Android.mk commit 9d1ce35c68bd05a56199afd94600716ea269187a Author: Andreas Boll <and...@gm...> Date: Thu Jul 21 10:54:15 2016 +0200 radeon: Wire up radeon-symbol-check to make check This was missed in 552de225bf2740ba0cb52312c21353d71d934b8c Signed-off-by: Andreas Boll <and...@gm...> Reviewed-by: Emil Velikov <emi...@gm...> diff --git a/radeon/Makefile.am b/radeon/Makefile.am index 25c03d3..31f19e5 100644 --- a/radeon/Makefile.am +++ b/radeon/Makefile.am @@ -43,4 +43,5 @@ libdrm_radeoninclude_HEADERS = $(LIBDRM_RADEON_H_FILES) pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libdrm_radeon.pc +TESTS = radeon-symbol-check EXTRA_DIST = Android.mk $(LIBDRM_RADEON_BOF_FILES) $(TESTS) |
From: <ma...@ke...> - 2017-10-12 18:53:10
|
amdgpu/amdgpu-symbol-check | 4 ++ amdgpu/amdgpu.h | 64 +++++++++++++++++++++++++++++++++++++++++++++ amdgpu/amdgpu_cs.c | 54 +++++++++++++++++++++++++++++++++++++ configure.ac | 2 - include/drm/amdgpu_drm.h | 21 ++++++++++++++ xf86drm.c | 22 +++++++++++++++ xf86drm.h | 3 ++ 7 files changed, 169 insertions(+), 1 deletion(-) New commits: commit 290d29d9794813a2fe0578dbb905ad09bc810516 Author: Marek Olšák <mar...@am...> Date: Thu Oct 12 20:48:54 2017 +0200 configure.ac: bump version to 2.4.84 diff --git a/configure.ac b/configure.ac index f847a664..ccb910a2 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_PREREQ([2.63]) AC_INIT([libdrm], - [2.4.83], + [2.4.84], [https://bugs.freedesktop.org/enter_bug.cgi?product=DRI], [libdrm]) commit c74d4614048f65b412caa572c900d15adba38ce3 Author: Marek Olšák <mar...@am...> Date: Fri Sep 8 16:05:54 2017 +0200 amdgpu: add amdgpu_cs_fence_to_handle v2: update amdgpu-symbol-check Reviewed-by: Chunming Zhou <dav...@am...> diff --git a/amdgpu/amdgpu-symbol-check b/amdgpu/amdgpu-symbol-check index 7ecfc982..d9f89ef3 100755 --- a/amdgpu/amdgpu-symbol-check +++ b/amdgpu/amdgpu-symbol-check @@ -34,6 +34,7 @@ amdgpu_cs_ctx_free amdgpu_cs_destroy_semaphore amdgpu_cs_destroy_syncobj amdgpu_cs_export_syncobj +amdgpu_cs_fence_to_handle amdgpu_cs_import_syncobj amdgpu_cs_query_fence_status amdgpu_cs_query_reset_state diff --git a/amdgpu/amdgpu.h b/amdgpu/amdgpu.h index 979acfc8..23cde108 100644 --- a/amdgpu/amdgpu.h +++ b/amdgpu/amdgpu.h @@ -1433,6 +1433,20 @@ int amdgpu_cs_syncobj_import_sync_file(amdgpu_device_handle dev, int sync_file_fd); /** + * Export an amdgpu fence as a handle (syncobj or fd). + * + * \param what AMDGPU_FENCE_TO_HANDLE_GET_{SYNCOBJ, FD} + * \param out_handle returned handle + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + */ +int amdgpu_cs_fence_to_handle(amdgpu_device_handle dev, + struct amdgpu_cs_fence *fence, + uint32_t what, + uint32_t *out_handle); + +/** * Submit raw command submission to kernel * * \param dev - \c [in] device handle diff --git a/amdgpu/amdgpu_cs.c b/amdgpu/amdgpu_cs.c index 2cde7bff..9577d5c9 100644 --- a/amdgpu/amdgpu_cs.c +++ b/amdgpu/amdgpu_cs.c @@ -713,3 +713,25 @@ void amdgpu_cs_chunk_fence_to_dep(struct amdgpu_cs_fence *fence, dep->ctx_id = fence->context->id; dep->handle = fence->fence; } + +int amdgpu_cs_fence_to_handle(amdgpu_device_handle dev, + struct amdgpu_cs_fence *fence, + uint32_t what, + uint32_t *out_handle) +{ + union drm_amdgpu_fence_to_handle fth = {0}; + int r; + + fth.in.fence.ctx_id = fence->context->id; + fth.in.fence.ip_type = fence->ip_type; + fth.in.fence.ip_instance = fence->ip_instance; + fth.in.fence.ring = fence->ring; + fth.in.fence.seq_no = fence->fence; + fth.in.what = what; + + r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_FENCE_TO_HANDLE, + &fth, sizeof(fth)); + if (r == 0) + *out_handle = fth.out.handle; + return r; +} commit 59aa57b363ba8de550aced1d397c54fd9e5e213c Author: Marek Olšák <mar...@am...> Date: Mon Sep 11 21:58:03 2017 +0200 amdgpu: add amdgpu_cs_syncobj_wait v2: update amdgpu-symbol-check Reviewed-by: Chunming Zhou <dav...@am...> diff --git a/amdgpu/amdgpu-symbol-check b/amdgpu/amdgpu-symbol-check index bc9ed3f9..7ecfc982 100755 --- a/amdgpu/amdgpu-symbol-check +++ b/amdgpu/amdgpu-symbol-check @@ -42,6 +42,7 @@ amdgpu_cs_submit amdgpu_cs_submit_raw amdgpu_cs_syncobj_export_sync_file amdgpu_cs_syncobj_import_sync_file +amdgpu_cs_syncobj_wait amdgpu_cs_wait_fences amdgpu_cs_wait_semaphore amdgpu_device_deinitialize diff --git a/amdgpu/amdgpu.h b/amdgpu/amdgpu.h index b44b9b64..979acfc8 100644 --- a/amdgpu/amdgpu.h +++ b/amdgpu/amdgpu.h @@ -1354,6 +1354,26 @@ int amdgpu_cs_destroy_syncobj(amdgpu_device_handle dev, uint32_t syncobj); /** + * Wait for one or all sync objects to signal. + * + * \param dev - \c [in] self-explanatory + * \param handles - \c [in] array of sync object handles + * \param num_handles - \c [in] self-explanatory + * \param timeout_nsec - \c [in] self-explanatory + * \param flags - \c [in] a bitmask of DRM_SYNCOBJ_WAIT_FLAGS_* + * \param first_signaled - \c [in] self-explanatory + * + * \return 0 on success\n + * -ETIME - Timeout + * <0 - Negative POSIX Error code + * + */ +int amdgpu_cs_syncobj_wait(amdgpu_device_handle dev, + uint32_t *handles, unsigned num_handles, + int64_t timeout_nsec, unsigned flags, + uint32_t *first_signaled); + +/** * Export kernel sync object to shareable fd. * * \param dev - \c [in] device handle diff --git a/amdgpu/amdgpu_cs.c b/amdgpu/amdgpu_cs.c index 4a055366..2cde7bff 100644 --- a/amdgpu/amdgpu_cs.c +++ b/amdgpu/amdgpu_cs.c @@ -615,6 +615,18 @@ int amdgpu_cs_destroy_syncobj(amdgpu_device_handle dev, return drmSyncobjDestroy(dev->fd, handle); } +int amdgpu_cs_syncobj_wait(amdgpu_device_handle dev, + uint32_t *handles, unsigned num_handles, + int64_t timeout_nsec, unsigned flags, + uint32_t *first_signaled) +{ + if (NULL == dev) + return -EINVAL; + + return drmSyncobjWait(dev->fd, handles, num_handles, timeout_nsec, + flags, first_signaled); +} + int amdgpu_cs_export_syncobj(amdgpu_device_handle dev, uint32_t handle, int *shared_fd) commit 2048a9e7278d64954080077fb29d603fbb611873 Author: Marek Olšák <mar...@am...> Date: Mon Sep 11 21:57:32 2017 +0200 drm: add drmSyncobjWait wrapper Reviewed-by: Chunming Zhou <dav...@am...> diff --git a/xf86drm.c b/xf86drm.c index 6ea01129..8a327170 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -4225,3 +4225,25 @@ int drmSyncobjExportSyncFile(int fd, uint32_t handle, int *sync_file_fd) *sync_file_fd = args.fd; return 0; } + +int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles, + int64_t timeout_nsec, unsigned flags, + uint32_t *first_signaled) +{ + struct drm_syncobj_wait args; + int ret; + + memclear(args); + args.handles = (intptr_t)handles; + args.timeout_nsec = timeout_nsec; + args.count_handles = num_handles; + args.flags = flags; + + ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, &args); + if (ret < 0) + return ret; + + if (first_signaled) + *first_signaled = args.first_signaled; + return ret; +} diff --git a/xf86drm.h b/xf86drm.h index 2855a3ee..ea650eff 100644 --- a/xf86drm.h +++ b/xf86drm.h @@ -860,6 +860,9 @@ extern int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle); extern int drmSyncobjImportSyncFile(int fd, uint32_t handle, int sync_file_fd); extern int drmSyncobjExportSyncFile(int fd, uint32_t handle, int *sync_file_fd); +extern int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles, + int64_t timeout_nsec, unsigned flags, + uint32_t *first_signaled); #if defined(__cplusplus) } commit b6e24501a1f8c58501fdfa39b435e440ee667feb Author: Marek Olšák <mar...@am...> Date: Mon Sep 11 21:12:12 2017 +0200 amdgpu: add sync_file import and export functions v2: update amdgpu-symbol-check Reviewed-by: Chunming Zhou <dav...@am...> diff --git a/amdgpu/amdgpu-symbol-check b/amdgpu/amdgpu-symbol-check index c5b85b52..bc9ed3f9 100755 --- a/amdgpu/amdgpu-symbol-check +++ b/amdgpu/amdgpu-symbol-check @@ -40,6 +40,8 @@ amdgpu_cs_query_reset_state amdgpu_cs_signal_semaphore amdgpu_cs_submit amdgpu_cs_submit_raw +amdgpu_cs_syncobj_export_sync_file +amdgpu_cs_syncobj_import_sync_file amdgpu_cs_wait_fences amdgpu_cs_wait_semaphore amdgpu_device_deinitialize diff --git a/amdgpu/amdgpu.h b/amdgpu/amdgpu.h index 238b1aaa..b44b9b64 100644 --- a/amdgpu/amdgpu.h +++ b/amdgpu/amdgpu.h @@ -1383,6 +1383,36 @@ int amdgpu_cs_import_syncobj(amdgpu_device_handle dev, uint32_t *syncobj); /** + * Export kernel sync object to a sync_file. + * + * \param dev - \c [in] device handle + * \param syncobj - \c [in] sync object handle + * \param sync_file_fd - \c [out] sync_file file descriptor. + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * + */ +int amdgpu_cs_syncobj_export_sync_file(amdgpu_device_handle dev, + uint32_t syncobj, + int *sync_file_fd); + +/** + * Import kernel sync object from a sync_file. + * + * \param dev - \c [in] device handle + * \param syncobj - \c [in] sync object handle + * \param sync_file_fd - \c [in] sync_file file descriptor. + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * + */ +int amdgpu_cs_syncobj_import_sync_file(amdgpu_device_handle dev, + uint32_t syncobj, + int sync_file_fd); + +/** * Submit raw command submission to kernel * * \param dev - \c [in] device handle diff --git a/amdgpu/amdgpu_cs.c b/amdgpu/amdgpu_cs.c index dfba8754..4a055366 100644 --- a/amdgpu/amdgpu_cs.c +++ b/amdgpu/amdgpu_cs.c @@ -635,6 +635,26 @@ int amdgpu_cs_import_syncobj(amdgpu_device_handle dev, return drmSyncobjFDToHandle(dev->fd, shared_fd, handle); } +int amdgpu_cs_syncobj_export_sync_file(amdgpu_device_handle dev, + uint32_t syncobj, + int *sync_file_fd) +{ + if (NULL == dev) + return -EINVAL; + + return drmSyncobjExportSyncFile(dev->fd, syncobj, sync_file_fd); +} + +int amdgpu_cs_syncobj_import_sync_file(amdgpu_device_handle dev, + uint32_t syncobj, + int sync_file_fd) +{ + if (NULL == dev) + return -EINVAL; + + return drmSyncobjImportSyncFile(dev->fd, syncobj, sync_file_fd); +} + int amdgpu_cs_submit_raw(amdgpu_device_handle dev, amdgpu_context_handle context, amdgpu_bo_list_handle bo_list_handle, commit ad4df736a9f8098cd47008c72948ceff9e9f9dac Author: Marek Olšák <mar...@am...> Date: Thu Oct 12 20:31:44 2017 +0200 include: sync drm.h and amdgpu_drm.h with airlied/drm-next diff --git a/include/drm/amdgpu_drm.h b/include/drm/amdgpu_drm.h index d9aa4a33..4c6e8c48 100644 --- a/include/drm/amdgpu_drm.h +++ b/include/drm/amdgpu_drm.h @@ -52,6 +52,7 @@ extern "C" { #define DRM_AMDGPU_GEM_USERPTR 0x11 #define DRM_AMDGPU_WAIT_FENCES 0x12 #define DRM_AMDGPU_VM 0x13 +#define DRM_AMDGPU_FENCE_TO_HANDLE 0x14 #define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create) #define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap) @@ -67,6 +68,7 @@ extern "C" { #define DRM_IOCTL_AMDGPU_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_USERPTR, struct drm_amdgpu_gem_userptr) #define DRM_IOCTL_AMDGPU_WAIT_FENCES DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_FENCES, union drm_amdgpu_wait_fences) #define DRM_IOCTL_AMDGPU_VM DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_VM, union drm_amdgpu_vm) +#define DRM_IOCTL_AMDGPU_FENCE_TO_HANDLE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_FENCE_TO_HANDLE, union drm_amdgpu_fence_to_handle) #define AMDGPU_GEM_DOMAIN_CPU 0x1 #define AMDGPU_GEM_DOMAIN_GTT 0x2 @@ -87,6 +89,8 @@ extern "C" { #define AMDGPU_GEM_CREATE_SHADOW (1 << 4) /* Flag that allocating the BO should use linear VRAM */ #define AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS (1 << 5) +/* Flag that BO is always valid in this VM */ +#define AMDGPU_GEM_CREATE_VM_ALWAYS_VALID (1 << 6) struct drm_amdgpu_gem_create_in { /** the requested memory size */ @@ -513,6 +517,20 @@ struct drm_amdgpu_cs_chunk_sem { __u32 handle; }; +#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ 0 +#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ_FD 1 +#define AMDGPU_FENCE_TO_HANDLE_GET_SYNC_FILE_FD 2 + +union drm_amdgpu_fence_to_handle { + struct { + struct drm_amdgpu_fence fence; + __u32 what; + } in; + struct { + __u32 handle; + } out; +}; + struct drm_amdgpu_cs_chunk_data { union { struct drm_amdgpu_cs_chunk_ib ib_data; @@ -764,6 +782,7 @@ struct drm_amdgpu_info_device { __u64 max_memory_clock; /* cu information */ __u32 cu_active_number; + /* NOTE: cu_ao_mask is INVALID, DON'T use it */ __u32 cu_ao_mask; __u32 cu_bitmap[4][4]; /** Render backend pipe mask. One render backend is CB+DB. */ @@ -818,6 +837,8 @@ struct drm_amdgpu_info_device { /* max gs wavefront per vgt*/ __u32 max_gs_waves_per_vgt; __u32 _pad1; + /* always on cu bitmap */ + __u32 cu_ao_bitmap[4][4]; }; struct drm_amdgpu_info_hw_ip { |
From: <an...@ke...> - 2017-11-10 20:23:46
|
include/drm/README | 22 ------- include/drm/mga_drm.h | 12 +++- include/drm/nouveau_drm.h | 94 ++++++++++++++++++--------------- include/drm/qxl_drm.h | 82 ++++++++++++++++------------- include/drm/r128_drm.h | 10 +++ include/drm/radeon_drm.h | 128 +++++++++++++++++++++++----------------------- include/drm/savage_drm.h | 20 +++++-- include/drm/sis_drm.h | 10 +++ include/drm/tegra_drm.h | 14 +++-- include/drm/vc4_drm.h | 47 +++++++++++++++- include/drm/via_drm.h | 8 ++ include/drm/vmwgfx_drm.h | 9 +++ 12 files changed, 280 insertions(+), 176 deletions(-) New commits: commit 21885876af4c2c8a51547bb81d6d10413eed71d5 Author: Eric Anholt <er...@an...> Date: Wed Nov 8 11:31:20 2017 -0800 headers: Drop outdated node about a delta in drm_mode.h. Fixed in 9433b702fc16 ("headers: Sync drm{,_mode}.h with the kernel") Signed-off-by: Eric Anholt <er...@an...> Reviewed-by: Emil Velikov <emi...@gm...> diff --git a/include/drm/README b/include/drm/README index 042cfb17..5b518ddf 100644 --- a/include/drm/README +++ b/include/drm/README @@ -91,11 +91,6 @@ Most UMS headers: Status: ? Promote to fixed size ints, which match the current (32bit) ones. - -drm_mode.h - - Missing DPI encode/connector pair. -Status: Trivial. - i915_drm.h - Missing PARAMS - HAS_POOLED_EU, MIN_EU_IN_POOL CONTEXT_PARAM_NO_ERROR_CAPTURE Status: Trivial. commit f696698e0249a8b65ef7d1a0c484633fc3f286ef Author: Eric Anholt <er...@an...> Date: Wed Nov 8 11:22:55 2017 -0800 headers: Sync up kernel changes to use kernel types instead of stdint.h. This pulls in pieces of drm-next d65d31388a23 ("Merge tag 'drm-misc-next-fixes-2017-11-07' of git://anongit.freedesktop.org/drm/drm-misc into drm-next") Signed-off-by: Eric Anholt <er...@an...> Reviewed-by: Emil Velikov <emi...@gm...> diff --git a/include/drm/README b/include/drm/README index 6e12ca4d..042cfb17 100644 --- a/include/drm/README +++ b/include/drm/README @@ -102,19 +102,14 @@ Status: Trivial. nouveau_drm.h - Missing macros NOUVEAU_GETPARAM*, NOUVEAU_DRM_HEADER_PATCHLEVEL, structs, -enums, using stdint.h over the __u* types. +enums Status: ? -qxl_drm.h - - Using the stdint.h uint*_t over the respective __u* ones -Status: Trivial. - r128_drm.h - Broken compat ioctls. radeon_drm.h - - Missing RADEON_TILING_R600_NO_SCANOUT, CIK_TILE_MODE_*, broken UMS ioctls, -using stdint types. + - Missing RADEON_TILING_R600_NO_SCANOUT, CIK_TILE_MODE_*, broken UMS ioctls - Both kernel and libdrm: missing padding - drm_radeon_gem_{create,{g,s}et_tiling,set_domain} others ? Status: ? diff --git a/include/drm/nouveau_drm.h b/include/drm/nouveau_drm.h index 542a732b..cb077821 100644 --- a/include/drm/nouveau_drm.h +++ b/include/drm/nouveau_drm.h @@ -111,34 +111,34 @@ struct drm_nouveau_setparam { #define NOUVEAU_GEM_TILE_NONCONTIG 0x00000008 struct drm_nouveau_gem_info { - uint32_t handle; - uint32_t domain; - uint64_t size; - uint64_t offset; - uint64_t map_handle; - uint32_t tile_mode; - uint32_t tile_flags; + __u32 handle; + __u32 domain; + __u64 size; + __u64 offset; + __u64 map_handle; + __u32 tile_mode; + __u32 tile_flags; }; struct drm_nouveau_gem_new { struct drm_nouveau_gem_info info; - uint32_t channel_hint; - uint32_t align; + __u32 channel_hint; + __u32 align; }; #define NOUVEAU_GEM_MAX_BUFFERS 1024 struct drm_nouveau_gem_pushbuf_bo_presumed { - uint32_t valid; - uint32_t domain; - uint64_t offset; + __u32 valid; + __u32 domain; + __u64 offset; }; struct drm_nouveau_gem_pushbuf_bo { - uint64_t user_priv; - uint32_t handle; - uint32_t read_domains; - uint32_t write_domains; - uint32_t valid_domains; + __u64 user_priv; + __u32 handle; + __u32 read_domains; + __u32 write_domains; + __u32 valid_domains; struct drm_nouveau_gem_pushbuf_bo_presumed presumed; }; @@ -147,47 +147,47 @@ struct drm_nouveau_gem_pushbuf_bo { #define NOUVEAU_GEM_RELOC_OR (1 << 2) #define NOUVEAU_GEM_MAX_RELOCS 1024 struct drm_nouveau_gem_pushbuf_reloc { - uint32_t reloc_bo_index; - uint32_t reloc_bo_offset; - uint32_t bo_index; - uint32_t flags; - uint32_t data; - uint32_t vor; - uint32_t tor; + __u32 reloc_bo_index; + __u32 reloc_bo_offset; + __u32 bo_index; + __u32 flags; + __u32 data; + __u32 vor; + __u32 tor; }; #define NOUVEAU_GEM_MAX_PUSH 512 struct drm_nouveau_gem_pushbuf_push { - uint32_t bo_index; - uint32_t pad; - uint64_t offset; - uint64_t length; + __u32 bo_index; + __u32 pad; + __u64 offset; + __u64 length; }; struct drm_nouveau_gem_pushbuf { - uint32_t channel; - uint32_t nr_buffers; - uint64_t buffers; - uint32_t nr_relocs; - uint32_t nr_push; - uint64_t relocs; - uint64_t push; - uint32_t suffix0; - uint32_t suffix1; - uint64_t vram_available; - uint64_t gart_available; + __u32 channel; + __u32 nr_buffers; + __u64 buffers; + __u32 nr_relocs; + __u32 nr_push; + __u64 relocs; + __u64 push; + __u32 suffix0; + __u32 suffix1; + __u64 vram_available; + __u64 gart_available; }; #define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001 #define NOUVEAU_GEM_CPU_PREP_NOBLOCK 0x00000002 #define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004 struct drm_nouveau_gem_cpu_prep { - uint32_t handle; - uint32_t flags; + __u32 handle; + __u32 flags; }; struct drm_nouveau_gem_cpu_fini { - uint32_t handle; + __u32 handle; }; enum nouveau_bus_type { diff --git a/include/drm/qxl_drm.h b/include/drm/qxl_drm.h index a520123b..38a0dbdf 100644 --- a/include/drm/qxl_drm.h +++ b/include/drm/qxl_drm.h @@ -52,14 +52,14 @@ extern "C" { #define DRM_QXL_ALLOC_SURF 0x06 struct drm_qxl_alloc { - uint32_t size; - uint32_t handle; /* 0 is an invalid handle */ + __u32 size; + __u32 handle; /* 0 is an invalid handle */ }; struct drm_qxl_map { - uint64_t offset; /* use for mmap system call */ - uint32_t handle; - uint32_t pad; + __u64 offset; /* use for mmap system call */ + __u32 handle; + __u32 pad; }; /* @@ -72,59 +72,59 @@ struct drm_qxl_map { #define QXL_RELOC_TYPE_SURF 2 struct drm_qxl_reloc { - uint64_t src_offset; /* offset into src_handle or src buffer */ - uint64_t dst_offset; /* offset in dest handle */ - uint32_t src_handle; /* dest handle to compute address from */ - uint32_t dst_handle; /* 0 if to command buffer */ - uint32_t reloc_type; - uint32_t pad; + __u64 src_offset; /* offset into src_handle or src buffer */ + __u64 dst_offset; /* offset in dest handle */ + __u32 src_handle; /* dest handle to compute address from */ + __u32 dst_handle; /* 0 if to command buffer */ + __u32 reloc_type; + __u32 pad; }; struct drm_qxl_command { - uint64_t command; /* void* */ - uint64_t relocs; /* struct drm_qxl_reloc* */ - uint32_t type; - uint32_t command_size; - uint32_t relocs_num; - uint32_t pad; + __u64 command; /* void* */ + __u64 relocs; /* struct drm_qxl_reloc* */ + __u32 type; + __u32 command_size; + __u32 relocs_num; + __u32 pad; }; /* XXX: call it drm_qxl_commands? */ struct drm_qxl_execbuffer { - uint32_t flags; /* for future use */ - uint32_t commands_num; - uint64_t commands; /* struct drm_qxl_command* */ + __u32 flags; /* for future use */ + __u32 commands_num; + __u64 commands; /* struct drm_qxl_command* */ }; struct drm_qxl_update_area { - uint32_t handle; - uint32_t top; - uint32_t left; - uint32_t bottom; - uint32_t right; - uint32_t pad; + __u32 handle; + __u32 top; + __u32 left; + __u32 bottom; + __u32 right; + __u32 pad; }; #define QXL_PARAM_NUM_SURFACES 1 /* rom->n_surfaces */ #define QXL_PARAM_MAX_RELOCS 2 struct drm_qxl_getparam { - uint64_t param; - uint64_t value; + __u64 param; + __u64 value; }; /* these are one bit values */ struct drm_qxl_clientcap { - uint32_t index; - uint32_t pad; + __u32 index; + __u32 pad; }; struct drm_qxl_alloc_surf { - uint32_t format; - uint32_t width; - uint32_t height; - int32_t stride; - uint32_t handle; - uint32_t pad; + __u32 format; + __u32 width; + __u32 height; + __s32 stride; + __u32 handle; + __u32 pad; }; #define DRM_IOCTL_QXL_ALLOC \ diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index f09cc04c..a1e385d6 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -797,9 +797,9 @@ typedef struct drm_radeon_surface_free { #define RADEON_GEM_DOMAIN_VRAM 0x4 struct drm_radeon_gem_info { - uint64_t gart_size; - uint64_t vram_size; - uint64_t vram_visible; + __u64 gart_size; + __u64 vram_size; + __u64 vram_visible; }; #define RADEON_GEM_NO_BACKING_STORE (1 << 0) @@ -811,11 +811,11 @@ struct drm_radeon_gem_info { #define RADEON_GEM_NO_CPU_ACCESS (1 << 4) struct drm_radeon_gem_create { - uint64_t size; - uint64_t alignment; - uint32_t handle; - uint32_t initial_domain; - uint32_t flags; + __u64 size; + __u64 alignment; + __u32 handle; + __u32 initial_domain; + __u32 flags; }; /* @@ -829,10 +829,10 @@ struct drm_radeon_gem_create { #define RADEON_GEM_USERPTR_REGISTER (1 << 3) struct drm_radeon_gem_userptr { - uint64_t addr; - uint64_t size; - uint32_t flags; - uint32_t handle; + __u64 addr; + __u64 size; + __u32 flags; + __u32 handle; }; #define RADEON_TILING_MACRO 0x1 @@ -855,72 +855,72 @@ struct drm_radeon_gem_userptr { #define RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK 0xf struct drm_radeon_gem_set_tiling { - uint32_t handle; - uint32_t tiling_flags; - uint32_t pitch; + __u32 handle; + __u32 tiling_flags; + __u32 pitch; }; struct drm_radeon_gem_get_tiling { - uint32_t handle; - uint32_t tiling_flags; - uint32_t pitch; + __u32 handle; + __u32 tiling_flags; + __u32 pitch; }; struct drm_radeon_gem_mmap { - uint32_t handle; - uint32_t pad; - uint64_t offset; - uint64_t size; - uint64_t addr_ptr; + __u32 handle; + __u32 pad; + __u64 offset; + __u64 size; + __u64 addr_ptr; }; struct drm_radeon_gem_set_domain { - uint32_t handle; - uint32_t read_domains; - uint32_t write_domain; + __u32 handle; + __u32 read_domains; + __u32 write_domain; }; struct drm_radeon_gem_wait_idle { - uint32_t handle; - uint32_t pad; + __u32 handle; + __u32 pad; }; struct drm_radeon_gem_busy { - uint32_t handle; - uint32_t domain; + __u32 handle; + __u32 domain; }; struct drm_radeon_gem_pread { /** Handle for the object being read. */ - uint32_t handle; - uint32_t pad; + __u32 handle; + __u32 pad; /** Offset into the object to read from */ - uint64_t offset; + __u64 offset; /** Length of data to read */ - uint64_t size; + __u64 size; /** Pointer to write the data into. */ /* void *, but pointers are not 32/64 compatible */ - uint64_t data_ptr; + __u64 data_ptr; }; struct drm_radeon_gem_pwrite { /** Handle for the object being written to. */ - uint32_t handle; - uint32_t pad; + __u32 handle; + __u32 pad; /** Offset into the object to write to */ - uint64_t offset; + __u64 offset; /** Length of data to write */ - uint64_t size; + __u64 size; /** Pointer to read the data from. */ /* void *, but pointers are not 32/64 compatible */ - uint64_t data_ptr; + __u64 data_ptr; }; /* Sets or returns a value associated with a buffer. */ struct drm_radeon_gem_op { - uint32_t handle; /* buffer */ - uint32_t op; /* RADEON_GEM_OP_* */ - uint64_t value; /* input or return value */ + __u32 handle; /* buffer */ + __u32 op; /* RADEON_GEM_OP_* */ + __u64 value; /* input or return value */ }; #define RADEON_GEM_OP_GET_INITIAL_DOMAIN 0 @@ -940,11 +940,11 @@ struct drm_radeon_gem_op { #define RADEON_VM_PAGE_SNOOPED (1 << 4) struct drm_radeon_gem_va { - uint32_t handle; - uint32_t operation; - uint32_t vm_id; - uint32_t flags; - uint64_t offset; + __u32 handle; + __u32 operation; + __u32 vm_id; + __u32 flags; + __u64 offset; }; #define RADEON_CHUNK_ID_RELOCS 0x01 @@ -966,29 +966,29 @@ struct drm_radeon_gem_va { /* 0 = normal, + = higher priority, - = lower priority */ struct drm_radeon_cs_chunk { - uint32_t chunk_id; - uint32_t length_dw; - uint64_t chunk_data; + __u32 chunk_id; + __u32 length_dw; + __u64 chunk_data; }; /* drm_radeon_cs_reloc.flags */ #define RADEON_RELOC_PRIO_MASK (0xf << 0) struct drm_radeon_cs_reloc { - uint32_t handle; - uint32_t read_domains; - uint32_t write_domain; - uint32_t flags; + __u32 handle; + __u32 read_domains; + __u32 write_domain; + __u32 flags; }; struct drm_radeon_cs { - uint32_t num_chunks; - uint32_t cs_id; - /* this points to uint64_t * which point to cs chunks */ - uint64_t chunks; + __u32 num_chunks; + __u32 cs_id; + /* this points to __u64 * which point to cs chunks */ + __u64 chunks; /* updates to the limits after this CS ioctl */ - uint64_t gart_limit; - uint64_t vram_limit; + __u64 gart_limit; + __u64 vram_limit; }; #define RADEON_INFO_DEVICE_ID 0x00 @@ -1047,9 +1047,9 @@ struct drm_radeon_cs { #define RADEON_INFO_GPU_RESET_COUNTER 0x26 struct drm_radeon_info { - uint32_t request; - uint32_t pad; - uint64_t value; + __u32 request; + __u32 pad; + __u64 value; }; /* Those correspond to the tile index to use, this is to explicitly state commit 59808bcacd48f4168c3c1093b4616c2ee039b5a1 Author: Eric Anholt <er...@an...> Date: Wed Nov 8 11:18:47 2017 -0800 headers: Sync up mga_drm.h from drm-next. The kernel started using the struct from drm.h instead of the typedef. Signed-off-by: Eric Anholt <er...@an...> Reviewed-by: Emil Velikov <emi...@gm...> diff --git a/include/drm/README b/include/drm/README index 47d80929..6e12ca4d 100644 --- a/include/drm/README +++ b/include/drm/README @@ -100,10 +100,6 @@ i915_drm.h - Missing PARAMS - HAS_POOLED_EU, MIN_EU_IN_POOL CONTEXT_PARAM_NO_ERROR_CAPTURE Status: Trivial. -mga_drm.h - - Typo fix, use struct over typedef. -Status: Trivial. - nouveau_drm.h - Missing macros NOUVEAU_GETPARAM*, NOUVEAU_DRM_HEADER_PATCHLEVEL, structs, enums, using stdint.h over the __u* types. diff --git a/include/drm/mga_drm.h b/include/drm/mga_drm.h index 7035a664..79300111 100644 --- a/include/drm/mga_drm.h +++ b/include/drm/mga_drm.h @@ -252,7 +252,7 @@ typedef struct _drm_mga_sarea { #define DRM_MGA_DMA_BOOTSTRAP 0x0c #define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t) -#define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t) +#define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, struct drm_lock) #define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET) #define DRM_IOCTL_MGA_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MGA_SWAP) #define DRM_IOCTL_MGA_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t) commit 8affa2699587b8239135b75ade24ee837df1606c Author: Eric Anholt <er...@an...> Date: Wed Nov 8 11:09:54 2017 -0800 headers: Sync up some comment spelling and whitespace fixes from drm-next. This pulls in pieces of drm-next d65d31388a23 ("Merge tag 'drm-misc-next-fixes-2017-11-07' of git://anongit.freedesktop.org/drm/drm-misc into drm-next") Signed-off-by: Eric Anholt <er...@an...> Reviewed-by: Emil Velikov <emi...@gm...> diff --git a/include/drm/mga_drm.h b/include/drm/mga_drm.h index f54e7a2e..7035a664 100644 --- a/include/drm/mga_drm.h +++ b/include/drm/mga_drm.h @@ -111,7 +111,7 @@ extern "C" { */ #define MGA_NR_SAREA_CLIPRECTS 8 -/* 2 heaps (1 for card, 1 for agp), each divided into upto 128 +/* 2 heaps (1 for card, 1 for agp), each divided into up to 128 * regions, subject to a minimum region size of (1<<16) == 64k. * * Clients may subdivide regions internally, but when sharing between diff --git a/include/drm/qxl_drm.h b/include/drm/qxl_drm.h index ccd841b1..a520123b 100644 --- a/include/drm/qxl_drm.h +++ b/include/drm/qxl_drm.h @@ -34,7 +34,7 @@ extern "C" { /* Please note that modifications to all structs defined here are * subject to backwards-compatibility constraints. * - * Do not use pointers, use uint64_t instead for 32 bit / 64 bit user/kernel + * Do not use pointers, use __u64 instead for 32 bit / 64 bit user/kernel * compatibility Keep fields aligned to their size */ diff --git a/include/drm/savage_drm.h b/include/drm/savage_drm.h index 26f387b7..1a91234e 100644 --- a/include/drm/savage_drm.h +++ b/include/drm/savage_drm.h @@ -35,7 +35,7 @@ extern "C" { #ifndef __SAVAGE_SAREA_DEFINES__ #define __SAVAGE_SAREA_DEFINES__ -/* 2 heaps (1 for card, 1 for agp), each divided into upto 128 +/* 2 heaps (1 for card, 1 for agp), each divided into up to 128 * regions, subject to a minimum region size of (1<<16) == 64k. * * Clients may subdivide regions internally, but when sharing between @@ -69,10 +69,10 @@ typedef struct _drm_savage_sarea { #define DRM_SAVAGE_BCI_EVENT_EMIT 0x02 #define DRM_SAVAGE_BCI_EVENT_WAIT 0x03 -#define DRM_IOCTL_SAVAGE_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t) -#define DRM_IOCTL_SAVAGE_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t) -#define DRM_IOCTL_SAVAGE_EVENT_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t) -#define DRM_IOCTL_SAVAGE_EVENT_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t) +#define DRM_IOCTL_SAVAGE_BCI_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t) +#define DRM_IOCTL_SAVAGE_BCI_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t) +#define DRM_IOCTL_SAVAGE_BCI_EVENT_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t) +#define DRM_IOCTL_SAVAGE_BCI_EVENT_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t) #define SAVAGE_DMA_PCI 1 #define SAVAGE_DMA_AGP 3 commit 8d34bba212342ec0e187cd3602d01edba2d7ec26 Author: Eric Anholt <er...@an...> Date: Wed Nov 8 11:06:55 2017 -0800 headers: Sync up some header guard changes from drm-next. This pulls in pieces of drm-next d65d31388a23 ("Merge tag 'drm-misc-next-fixes-2017-11-07' of git://anongit.freedesktop.org/drm/drm-misc into drm-next") Signed-off-by: Eric Anholt <er...@an...> Reviewed-by: Emil Velikov <emi...@gm...> diff --git a/include/drm/README b/include/drm/README index 870b0b5b..47d80929 100644 --- a/include/drm/README +++ b/include/drm/README @@ -86,10 +86,6 @@ Outdated or Broken Headers This section contains a list of headers and the respective "issues" they might have relative to their kernel equivalent. -Nearly all headers: - - Missing extern C notation. -Status: Trivial. - Most UMS headers: - Not using fixed size integers - compat ioctls are broken. Status: ? diff --git a/include/drm/mga_drm.h b/include/drm/mga_drm.h index b630e8fa..f54e7a2e 100644 --- a/include/drm/mga_drm.h +++ b/include/drm/mga_drm.h @@ -37,6 +37,10 @@ #include "drm.h" +#if defined(__cplusplus) +extern "C" { +#endif + /* WARNING: If you change any of these defines, make sure to change the * defines in the Xserver file (mga_sarea.h) */ @@ -416,4 +420,8 @@ typedef struct drm_mga_getparam { void *value; } drm_mga_getparam_t; +#if defined(__cplusplus) +} +#endif + #endif diff --git a/include/drm/nouveau_drm.h b/include/drm/nouveau_drm.h index e418f9f3..542a732b 100644 --- a/include/drm/nouveau_drm.h +++ b/include/drm/nouveau_drm.h @@ -27,6 +27,12 @@ #define NOUVEAU_DRM_HEADER_PATCHLEVEL 16 +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + struct drm_nouveau_channel_alloc { uint32_t fb_ctxdma_handle; uint32_t tt_ctxdma_handle; @@ -207,4 +213,8 @@ struct drm_nouveau_sarea { #define DRM_NOUVEAU_GEM_CPU_FINI 0x43 #define DRM_NOUVEAU_GEM_INFO 0x44 +#if defined(__cplusplus) +} +#endif + #endif /* __NOUVEAU_DRM_H__ */ diff --git a/include/drm/qxl_drm.h b/include/drm/qxl_drm.h index 1e331a86..ccd841b1 100644 --- a/include/drm/qxl_drm.h +++ b/include/drm/qxl_drm.h @@ -27,6 +27,10 @@ #include <stddef.h> #include "drm.h" +#if defined(__cplusplus) +extern "C" { +#endif + /* Please note that modifications to all structs defined here are * subject to backwards-compatibility constraints. * @@ -149,4 +153,8 @@ struct drm_qxl_alloc_surf { DRM_IOWR(DRM_COMMAND_BASE + DRM_QXL_ALLOC_SURF,\ struct drm_qxl_alloc_surf) +#if defined(__cplusplus) +} +#endif + #endif diff --git a/include/drm/r128_drm.h b/include/drm/r128_drm.h index ede78ff9..bf431a02 100644 --- a/include/drm/r128_drm.h +++ b/include/drm/r128_drm.h @@ -33,6 +33,12 @@ #ifndef __R128_DRM_H__ #define __R128_DRM_H__ +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + /* WARNING: If you change any of these defines, make sure to change the * defines in the X server file (r128_sarea.h) */ @@ -323,4 +329,8 @@ typedef struct drm_r128_getparam { void *value; } drm_r128_getparam_t; +#if defined(__cplusplus) +} +#endif + #endif diff --git a/include/drm/savage_drm.h b/include/drm/savage_drm.h index f7a75eff..26f387b7 100644 --- a/include/drm/savage_drm.h +++ b/include/drm/savage_drm.h @@ -26,6 +26,12 @@ #ifndef __SAVAGE_DRM_H__ #define __SAVAGE_DRM_H__ +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + #ifndef __SAVAGE_SAREA_DEFINES__ #define __SAVAGE_SAREA_DEFINES__ @@ -207,4 +213,8 @@ union drm_savage_cmd_header { } clear1; /* SAVAGE_CMD_CLEAR data */ }; +#if defined(__cplusplus) +} +#endif + #endif diff --git a/include/drm/sis_drm.h b/include/drm/sis_drm.h index 30f7b382..8e51bb9a 100644 --- a/include/drm/sis_drm.h +++ b/include/drm/sis_drm.h @@ -27,6 +27,12 @@ #ifndef __SIS_DRM_H__ #define __SIS_DRM_H__ +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + /* SiS specific ioctls */ #define NOT_USED_0_3 #define DRM_SIS_FB_ALLOC 0x04 @@ -64,4 +70,8 @@ typedef struct { unsigned int offset, size; } drm_sis_fb_t; +#if defined(__cplusplus) +} +#endif + #endif /* __SIS_DRM_H__ */ diff --git a/include/drm/tegra_drm.h b/include/drm/tegra_drm.h index 7c0fe0ed..12f9bf84 100644 --- a/include/drm/tegra_drm.h +++ b/include/drm/tegra_drm.h @@ -20,10 +20,14 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef _UAPI_TEGRA_DRM_H_ -#define _UAPI_TEGRA_DRM_H_ +#ifndef _TEGRA_DRM_H_ +#define _TEGRA_DRM_H_ -#include <drm.h> +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif #define DRM_TEGRA_GEM_CREATE_TILED (1 << 0) #define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1) @@ -198,4 +202,8 @@ struct drm_tegra_gem_get_flags { #define DRM_IOCTL_TEGRA_GEM_SET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_FLAGS, struct drm_tegra_gem_set_flags) #define DRM_IOCTL_TEGRA_GEM_GET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_FLAGS, struct drm_tegra_gem_get_flags) +#if defined(__cplusplus) +} +#endif + #endif diff --git a/include/drm/via_drm.h b/include/drm/via_drm.h index 182f8792..8b69e819 100644 --- a/include/drm/via_drm.h +++ b/include/drm/via_drm.h @@ -26,6 +26,10 @@ #include "drm.h" +#if defined(__cplusplus) +extern "C" { +#endif + /* WARNING: These defines must be the same as what the Xserver uses. * if you change them, you must change the defines in the Xserver. */ @@ -272,4 +276,8 @@ typedef struct drm_via_dmablit { drm_via_blitsync_t sync; } drm_via_dmablit_t; +#if defined(__cplusplus) +} +#endif + #endif /* _VIA_DRM_H_ */ diff --git a/include/drm/vmwgfx_drm.h b/include/drm/vmwgfx_drm.h index 5b68b4d1..d325a410 100644 --- a/include/drm/vmwgfx_drm.h +++ b/include/drm/vmwgfx_drm.h @@ -30,6 +30,10 @@ #include "drm.h" +#if defined(__cplusplus) +extern "C" { +#endif + #define DRM_VMW_MAX_SURFACE_FACES 6 #define DRM_VMW_MAX_MIP_LEVELS 24 @@ -1087,4 +1091,9 @@ union drm_vmw_extended_context_arg { enum drm_vmw_extended_context req; struct drm_vmw_context_arg rep; }; + +#if defined(__cplusplus) +} +#endif + #endif commit e38de517991a20d7a2abdffc1bc4fd702e8f673c Author: Eric Anholt <er...@an...> Date: Wed Nov 8 11:04:31 2017 -0800 headers: Sync vc4 header from drm-next. This updates the header with the contents from drm-next d65d31388a23 ("Merge tag 'drm-misc-next-fixes-2017-11-07' of git://anongit.freedesktop.org/drm/drm-misc into drm-next") Signed-off-by: Eric Anholt <er...@an...> Reviewed-by: Emil Velikov <emi...@gm...> diff --git a/include/drm/vc4_drm.h b/include/drm/vc4_drm.h index 6ac4c5c0..3415a4b7 100644 --- a/include/drm/vc4_drm.h +++ b/include/drm/vc4_drm.h @@ -21,8 +21,8 @@ * IN THE SOFTWARE. */ -#ifndef _UAPI_VC4_DRM_H_ -#define _UAPI_VC4_DRM_H_ +#ifndef _VC4_DRM_H_ +#define _VC4_DRM_H_ #include "drm.h" @@ -40,6 +40,8 @@ extern "C" { #define DRM_VC4_GET_PARAM 0x07 #define DRM_VC4_SET_TILING 0x08 #define DRM_VC4_GET_TILING 0x09 +#define DRM_VC4_LABEL_BO 0x0a +#define DRM_VC4_GEM_MADVISE 0x0b #define DRM_IOCTL_VC4_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SUBMIT_CL, struct drm_vc4_submit_cl) #define DRM_IOCTL_VC4_WAIT_SEQNO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_SEQNO, struct drm_vc4_wait_seqno) @@ -51,6 +53,8 @@ extern "C" { #define DRM_IOCTL_VC4_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_PARAM, struct drm_vc4_get_param) #define DRM_IOCTL_VC4_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SET_TILING, struct drm_vc4_set_tiling) #define DRM_IOCTL_VC4_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_TILING, struct drm_vc4_get_tiling) +#define DRM_IOCTL_VC4_LABEL_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_LABEL_BO, struct drm_vc4_label_bo) +#define DRM_IOCTL_VC4_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GEM_MADVISE, struct drm_vc4_gem_madvise) struct drm_vc4_submit_rcl_surface { __u32 hindex; /* Handle index, or ~0 if not present. */ @@ -153,6 +157,16 @@ struct drm_vc4_submit_cl { __u32 pad:24; #define VC4_SUBMIT_CL_USE_CLEAR_COLOR (1 << 0) +/* By default, the kernel gets to choose the order that the tiles are + * rendered in. If this is set, then the tiles will be rendered in a + * raster order, with the right-to-left vs left-to-right and + * top-to-bottom vs bottom-to-top dictated by + * VC4_SUBMIT_CL_RCL_ORDER_INCREASING_*. This allows overlapping + * blits to be implemented using the 3D engine. + */ +#define VC4_SUBMIT_CL_FIXED_RCL_ORDER (1 << 1) +#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X (1 << 2) +#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y (1 << 3) __u32 flags; /* Returned value of the seqno of this render job (for the @@ -292,6 +306,8 @@ struct drm_vc4_get_hang_state { #define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3 #define DRM_VC4_PARAM_SUPPORTS_ETC1 4 #define DRM_VC4_PARAM_SUPPORTS_THREADED_FS 5 +#define DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER 6 +#define DRM_VC4_PARAM_SUPPORTS_MADVISE 7 struct drm_vc4_get_param { __u32 param; @@ -311,8 +327,33 @@ struct drm_vc4_set_tiling { __u64 modifier; }; +/** + * struct drm_vc4_label_bo - Attach a name to a BO for debug purposes. + */ +struct drm_vc4_label_bo { + __u32 handle; + __u32 len; + __u64 name; +}; + +/* + * States prefixed with '__' are internal states and cannot be passed to the + * DRM_IOCTL_VC4_GEM_MADVISE ioctl. + */ +#define VC4_MADV_WILLNEED 0 +#define VC4_MADV_DONTNEED 1 +#define __VC4_MADV_PURGED 2 +#define __VC4_MADV_NOTSUPP 3 + +struct drm_vc4_gem_madvise { + __u32 handle; + __u32 madv; + __u32 retained; + __u32 pad; +}; + #if defined(__cplusplus) } #endif -#endif /* _UAPI_VC4_DRM_H_ */ +#endif /* _VC4_DRM_H_ */ |
From: <git...@ke...> - 2018-08-07 11:28:36
|
amdgpu/Makefile.sources | 6 amdgpu/amdgpu_bo.c | 57 +++--- amdgpu/amdgpu_device.c | 67 ++------ amdgpu/amdgpu_internal.h | 6 amdgpu/handle_table.c | 72 ++++++++ amdgpu/handle_table.h | 41 +++++ amdgpu/util_hash.c | 383 ----------------------------------------------- amdgpu/util_hash.h | 103 ------------ amdgpu/util_hash_table.c | 270 --------------------------------- amdgpu/util_hash_table.h | 71 -------- 10 files changed, 163 insertions(+), 913 deletions(-) New commits: commit cbf0bb7f192b814be84dff538fb90dacf65958c7 Author: Christian König <chr...@am...> Date: Thu Aug 2 10:45:19 2018 +0200 amdgpu: always add all BOs to handle table This way we can always find a BO structure by its handle. Signed-off-by: Christian König <chr...@am...> Reviewed-by: Michel Dänzer <mic...@am...> Reviewed-and-Tested-by: Junwei Zhang <Jer...@am...> diff --git a/amdgpu/amdgpu_bo.c b/amdgpu/amdgpu_bo.c index 02592377..422c7c99 100644 --- a/amdgpu/amdgpu_bo.c +++ b/amdgpu/amdgpu_bo.c @@ -87,6 +87,10 @@ int amdgpu_bo_alloc(amdgpu_device_handle dev, bo->handle = args.out.handle; + pthread_mutex_lock(&bo->dev->bo_table_mutex); + r = handle_table_insert(&bo->dev->bo_handles, bo->handle, bo); + pthread_mutex_unlock(&bo->dev->bo_table_mutex); + pthread_mutex_init(&bo->cpu_access_mutex, NULL); if (r) @@ -171,13 +175,6 @@ int amdgpu_bo_query_info(amdgpu_bo_handle bo, return 0; } -static void amdgpu_add_handle_to_table(amdgpu_bo_handle bo) -{ - pthread_mutex_lock(&bo->dev->bo_table_mutex); - handle_table_insert(&bo->dev->bo_handles, bo->handle, bo); - pthread_mutex_unlock(&bo->dev->bo_table_mutex); -} - static int amdgpu_bo_export_flink(amdgpu_bo_handle bo) { struct drm_gem_flink flink; @@ -240,14 +237,11 @@ int amdgpu_bo_export(amdgpu_bo_handle bo, return 0; case amdgpu_bo_handle_type_kms: - amdgpu_add_handle_to_table(bo); - /* fall through */ case amdgpu_bo_handle_type_kms_noimport: *shared_handle = bo->handle; return 0; case amdgpu_bo_handle_type_dma_buf_fd: - amdgpu_add_handle_to_table(bo); return drmPrimeHandleToFD(bo->dev->fd, bo->handle, DRM_CLOEXEC | DRM_RDWR, (int*)shared_handle); commit d6cb0ee408e88310f2b4caefc51b655410072974 Author: Christian König <chr...@am...> Date: Thu Aug 2 10:58:51 2018 +0200 amdgpu: remove the hash table implementation Not used any more. Signed-off-by: Christian König <chr...@am...> Reviewed-by: Michel Dänzer <mic...@am...> Reviewed-and-Tested-by: Junwei Zhang <Jer...@am...> diff --git a/amdgpu/Makefile.sources b/amdgpu/Makefile.sources index 62577ba5..d6df324a 100644 --- a/amdgpu/Makefile.sources +++ b/amdgpu/Makefile.sources @@ -7,10 +7,6 @@ LIBDRM_AMDGPU_FILES := \ amdgpu_internal.h \ amdgpu_vamgr.c \ amdgpu_vm.c \ - util_hash.c \ - util_hash.h \ - util_hash_table.c \ - util_hash_table.h \ handle_table.c \ handle_table.h diff --git a/amdgpu/util_hash.c b/amdgpu/util_hash.c deleted file mode 100644 index 7e590419..00000000 --- a/amdgpu/util_hash.c +++ /dev/null @@ -1,383 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - /* - * Authors: - * Zack Rusin <za...@vm...> - */ - -#include "util_hash.h" - -#include <stdlib.h> -#include <assert.h> - -#define MAX(a, b) ((a > b) ? (a) : (b)) - -static const int MinNumBits = 4; - -static const unsigned char prime_deltas[] = { - 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3, - 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0 -}; - -static int primeForNumBits(int numBits) -{ - return (1 << numBits) + prime_deltas[numBits]; -} - -/* Returns the smallest integer n such that - primeForNumBits(n) >= hint. -*/ -static int countBits(int hint) -{ - int numBits = 0; - int bits = hint; - - while (bits > 1) { - bits >>= 1; - numBits++; - } - - if (numBits >= (int)sizeof(prime_deltas)) { - numBits = sizeof(prime_deltas) - 1; - } else if (primeForNumBits(numBits) < hint) { - ++numBits; - } - return numBits; -} - -struct util_node { - struct util_node *next; - unsigned key; - void *value; -}; - -struct util_hash_data { - struct util_node *fakeNext; - struct util_node **buckets; - int size; - int nodeSize; - short userNumBits; - short numBits; - int numBuckets; -}; - -struct util_hash { - union { - struct util_hash_data *d; - struct util_node *e; - } data; -}; - -static void *util_data_allocate_node(struct util_hash_data *hash) -{ - return malloc(hash->nodeSize); -} - -static void util_free_node(struct util_node *node) -{ - free(node); -} - -static struct util_node * -util_hash_create_node(struct util_hash *hash, - unsigned akey, void *avalue, - struct util_node **anextNode) -{ - struct util_node *node = util_data_allocate_node(hash->data.d); - - if (!node) - return NULL; - - node->key = akey; - node->value = avalue; - - node->next = (struct util_node*)(*anextNode); - *anextNode = node; - ++hash->data.d->size; - return node; -} - -static void util_data_rehash(struct util_hash_data *hash, int hint) -{ - if (hint < 0) { - hint = countBits(-hint); - if (hint < MinNumBits) - hint = MinNumBits; - hash->userNumBits = (short)hint; - while (primeForNumBits(hint) < (hash->size >> 1)) - ++hint; - } else if (hint < MinNumBits) { - hint = MinNumBits; - } - - if (hash->numBits != hint) { - struct util_node *e = (struct util_node *)(hash); - struct util_node **oldBuckets = hash->buckets; - int oldNumBuckets = hash->numBuckets; - int i = 0; - - hash->numBits = (short)hint; - hash->numBuckets = primeForNumBits(hint); - hash->buckets = malloc(sizeof(struct util_node*) * hash->numBuckets); - for (i = 0; i < hash->numBuckets; ++i) - hash->buckets[i] = e; - - for (i = 0; i < oldNumBuckets; ++i) { - struct util_node *firstNode = oldBuckets[i]; - while (firstNode != e) { - unsigned h = firstNode->key; - struct util_node *lastNode = firstNode; - struct util_node *afterLastNode; - struct util_node **beforeFirstNode; - - while (lastNode->next != e && lastNode->next->key == h) - lastNode = lastNode->next; - - afterLastNode = lastNode->next; - beforeFirstNode = &hash->buckets[h % hash->numBuckets]; - while (*beforeFirstNode != e) - beforeFirstNode = &(*beforeFirstNode)->next; - lastNode->next = *beforeFirstNode; - *beforeFirstNode = firstNode; - firstNode = afterLastNode; - } - } - free(oldBuckets); - } -} - -static void util_data_might_grow(struct util_hash_data *hash) -{ - if (hash->size >= hash->numBuckets) - util_data_rehash(hash, hash->numBits + 1); -} - -static void util_data_has_shrunk(struct util_hash_data *hash) -{ - if (hash->size <= (hash->numBuckets >> 3) && - hash->numBits > hash->userNumBits) { - int max = MAX(hash->numBits-2, hash->userNumBits); - util_data_rehash(hash, max); - } -} - -static struct util_node *util_data_first_node(struct util_hash_data *hash) -{ - struct util_node *e = (struct util_node *)(hash); - struct util_node **bucket = hash->buckets; - int n = hash->numBuckets; - while (n--) { - if (*bucket != e) - return *bucket; - ++bucket; - } - return e; -} - -static struct util_node **util_hash_find_node(struct util_hash *hash, unsigned akey) -{ - struct util_node **node; - - if (hash->data.d->numBuckets) { - node = (struct util_node **)(&hash->data.d->buckets[akey % hash->data.d->numBuckets]); - assert(*node == hash->data.e || (*node)->next); - while (*node != hash->data.e && (*node)->key != akey) - node = &(*node)->next; - } else { - node = (struct util_node **)((const struct util_node * const *)(&hash->data.e)); - } - return node; -} - -drm_private struct util_hash_iter -util_hash_insert(struct util_hash *hash, unsigned key, void *data) -{ - util_data_might_grow(hash->data.d); - - { - struct util_node **nextNode = util_hash_find_node(hash, key); - struct util_node *node = util_hash_create_node(hash, key, data, nextNode); - if (!node) { - struct util_hash_iter null_iter = {hash, 0}; - return null_iter; - } - - { - struct util_hash_iter iter = {hash, node}; - return iter; - } - } -} - -drm_private struct util_hash *util_hash_create(void) -{ - struct util_hash *hash = malloc(sizeof(struct util_hash)); - if (!hash) - return NULL; - - hash->data.d = malloc(sizeof(struct util_hash_data)); - if (!hash->data.d) { - free(hash); - return NULL; - } - - hash->data.d->fakeNext = 0; - hash->data.d->buckets = 0; - hash->data.d->size = 0; - hash->data.d->nodeSize = sizeof(struct util_node); - hash->data.d->userNumBits = (short)MinNumBits; - hash->data.d->numBits = 0; - hash->data.d->numBuckets = 0; - - return hash; -} - -drm_private void util_hash_delete(struct util_hash *hash) -{ - struct util_node *e_for_x = (struct util_node *)(hash->data.d); - struct util_node **bucket = (struct util_node **)(hash->data.d->buckets); - int n = hash->data.d->numBuckets; - while (n--) { - struct util_node *cur = *bucket++; - while (cur != e_for_x) { - struct util_node *next = cur->next; - util_free_node(cur); - cur = next; - } - } - free(hash->data.d->buckets); - free(hash->data.d); - free(hash); -} - -drm_private struct util_hash_iter -util_hash_find(struct util_hash *hash, unsigned key) -{ - struct util_node **nextNode = util_hash_find_node(hash, key); - struct util_hash_iter iter = {hash, *nextNode}; - return iter; -} - -drm_private unsigned util_hash_iter_key(struct util_hash_iter iter) -{ - if (!iter.node || iter.hash->data.e == iter.node) - return 0; - return iter.node->key; -} - -drm_private void *util_hash_iter_data(struct util_hash_iter iter) -{ - if (!iter.node || iter.hash->data.e == iter.node) - return 0; - return iter.node->value; -} - -static struct util_node *util_hash_data_next(struct util_node *node) -{ - union { - struct util_node *next; - struct util_node *e; - struct util_hash_data *d; - } a; - int start; - struct util_node **bucket; - int n; - - a.next = node->next; - if (!a.next) { - /* iterating beyond the last element */ - return 0; - } - if (a.next->next) - return a.next; - - start = (node->key % a.d->numBuckets) + 1; - bucket = a.d->buckets + start; - n = a.d->numBuckets - start; - while (n--) { - if (*bucket != a.e) - return *bucket; - ++bucket; - } - return a.e; -} - -drm_private struct util_hash_iter -util_hash_iter_next(struct util_hash_iter iter) -{ - struct util_hash_iter next = {iter.hash, util_hash_data_next(iter.node)}; - return next; -} - -drm_private int util_hash_iter_is_null(struct util_hash_iter iter) -{ - if (!iter.node || iter.node == iter.hash->data.e) - return 1; - return 0; -} - -drm_private void *util_hash_take(struct util_hash *hash, unsigned akey) -{ - struct util_node **node = util_hash_find_node(hash, akey); - if (*node != hash->data.e) { - void *t = (*node)->value; - struct util_node *next = (*node)->next; - util_free_node(*node); - *node = next; - --hash->data.d->size; - util_data_has_shrunk(hash->data.d); - return t; - } - return 0; -} - -drm_private struct util_hash_iter util_hash_first_node(struct util_hash *hash) -{ - struct util_hash_iter iter = {hash, util_data_first_node(hash->data.d)}; - return iter; -} - -drm_private struct util_hash_iter -util_hash_erase(struct util_hash *hash, struct util_hash_iter iter) -{ - struct util_hash_iter ret = iter; - struct util_node *node = iter.node; - struct util_node **node_ptr; - - if (node == hash->data.e) - return iter; - - ret = util_hash_iter_next(ret); - node_ptr = (struct util_node**)(&hash->data.d->buckets[node->key % hash->data.d->numBuckets]); - while (*node_ptr != node) - node_ptr = &(*node_ptr)->next; - *node_ptr = node->next; - util_free_node(node); - --hash->data.d->size; - return ret; -} diff --git a/amdgpu/util_hash.h b/amdgpu/util_hash.h deleted file mode 100644 index 6eed1569..00000000 --- a/amdgpu/util_hash.h +++ /dev/null @@ -1,103 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Hash implementation. - * - * This file provides a hash implementation that is capable of dealing - * with collisions. It stores colliding entries in linked list. All - * functions operating on the hash return an iterator. The iterator - * itself points to the collision list. If there wasn't any collision - * the list will have just one entry, otherwise client code should - * iterate over the entries to find the exact entry among ones that - * had the same key (e.g. memcmp could be used on the data to check - * that) - * - * @author Zack Rusin <za...@vm...> - */ - -#ifndef UTIL_HASH_H -#define UTIL_HASH_H - -#include <stdbool.h> - -#include "libdrm_macros.h" - -struct util_hash; -struct util_node; - -struct util_hash_iter { - struct util_hash *hash; - struct util_node *node; -}; - - -drm_private struct util_hash *util_hash_create(void); -drm_private void util_hash_delete(struct util_hash *hash); - - -/** - * Adds a data with the given key to the hash. If entry with the given - * key is already in the hash, this current entry is instered before it - * in the collision list. - * Function returns iterator pointing to the inserted item in the hash. - */ -drm_private struct util_hash_iter -util_hash_insert(struct util_hash *hash, unsigned key, void *data); - -/** - * Removes the item pointed to by the current iterator from the hash. - * Note that the data itself is not erased and if it was a malloc'ed pointer - * it will have to be freed after calling this function by the callee. - * Function returns iterator pointing to the item after the removed one in - * the hash. - */ -drm_private struct util_hash_iter -util_hash_erase(struct util_hash *hash, struct util_hash_iter iter); - -drm_private void *util_hash_take(struct util_hash *hash, unsigned key); - - -drm_private struct util_hash_iter util_hash_first_node(struct util_hash *hash); - -/** - * Return an iterator pointing to the first entry in the collision list. - */ -drm_private struct util_hash_iter -util_hash_find(struct util_hash *hash, unsigned key); - - -drm_private int util_hash_iter_is_null(struct util_hash_iter iter); -drm_private unsigned util_hash_iter_key(struct util_hash_iter iter); -drm_private void *util_hash_iter_data(struct util_hash_iter iter); - - -drm_private struct util_hash_iter -util_hash_iter_next(struct util_hash_iter iter); - -#endif diff --git a/amdgpu/util_hash_table.c b/amdgpu/util_hash_table.c deleted file mode 100644 index e06d4415..00000000 --- a/amdgpu/util_hash_table.c +++ /dev/null @@ -1,270 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * General purpose hash table implementation. - * - * Just uses the util_hash for now, but it might be better switch to a linear - * probing hash table implementation at some point -- as it is said they have - * better lookup and cache performance and it appears to be possible to write - * a lock-free implementation of such hash tables . - * - * @author José Fonseca <jfo...@vm...> - */ - - -#include "util_hash_table.h" -#include "util_hash.h" - -#include <stdlib.h> -#include <assert.h> - -struct util_hash_table -{ - struct util_hash *head; - - /** Hash function */ - unsigned (*make_hash)(void *key); - - /** Compare two keys */ - int (*compare)(void *key1, void *key2); -}; - -struct util_hash_table_item -{ - void *key; - void *value; -}; - - -static struct util_hash_table_item * -util_hash_table_item(struct util_hash_iter iter) -{ - return (struct util_hash_table_item *)util_hash_iter_data(iter); -} - -drm_private struct util_hash_table * -util_hash_table_create(unsigned (*hash)(void *key), - int (*compare)(void *key1, void *key2)) -{ - struct util_hash_table *ht; - - ht = malloc(sizeof(struct util_hash_table)); - if(!ht) - return NULL; - - ht->head = util_hash_create(); - if(!ht->head) { - free(ht); - return NULL; - } - - ht->make_hash = hash; - ht->compare = compare; - - return ht; -} - -static struct util_hash_iter -util_hash_table_find_iter(struct util_hash_table *ht, - void *key, unsigned key_hash) -{ - struct util_hash_iter iter; - struct util_hash_table_item *item; - - iter = util_hash_find(ht->head, key_hash); - while (!util_hash_iter_is_null(iter)) { - item = (struct util_hash_table_item *)util_hash_iter_data(iter); - if (!ht->compare(item->key, key)) - break; - iter = util_hash_iter_next(iter); - } - - return iter; -} - -static struct util_hash_table_item * -util_hash_table_find_item(struct util_hash_table *ht, - void *key, unsigned key_hash) -{ - struct util_hash_iter iter; - struct util_hash_table_item *item; - - iter = util_hash_find(ht->head, key_hash); - while (!util_hash_iter_is_null(iter)) { - item = (struct util_hash_table_item *)util_hash_iter_data(iter); - if (!ht->compare(item->key, key)) - return item; - iter = util_hash_iter_next(iter); - } - - return NULL; -} - -drm_private void -util_hash_table_set(struct util_hash_table *ht, void *key, void *value) -{ - unsigned key_hash; - struct util_hash_table_item *item; - struct util_hash_iter iter; - - assert(ht); - if (!ht) - return; - - key_hash = ht->make_hash(key); - - item = util_hash_table_find_item(ht, key, key_hash); - if(item) { - /* TODO: key/value destruction? */ - item->value = value; - return; - } - - item = malloc(sizeof(struct util_hash_table_item)); - if(!item) - return; - - item->key = key; - item->value = value; - - iter = util_hash_insert(ht->head, key_hash, item); - if(util_hash_iter_is_null(iter)) { - free(item); - return; - } -} - -drm_private void *util_hash_table_get(struct util_hash_table *ht, void *key) -{ - unsigned key_hash; - struct util_hash_table_item *item; - - assert(ht); - if (!ht) - return NULL; - - key_hash = ht->make_hash(key); - - item = util_hash_table_find_item(ht, key, key_hash); - if(!item) - return NULL; - - return item->value; -} - -drm_private void util_hash_table_remove(struct util_hash_table *ht, void *key) -{ - unsigned key_hash; - struct util_hash_iter iter; - struct util_hash_table_item *item; - - assert(ht); - if (!ht) - return; - - key_hash = ht->make_hash(key); - - iter = util_hash_table_find_iter(ht, key, key_hash); - if(util_hash_iter_is_null(iter)) - return; - - item = util_hash_table_item(iter); - assert(item); - free(item); - - util_hash_erase(ht->head, iter); -} - -drm_private void util_hash_table_clear(struct util_hash_table *ht) -{ - struct util_hash_iter iter; - struct util_hash_table_item *item; - - assert(ht); - if (!ht) - return; - - iter = util_hash_first_node(ht->head); - while (!util_hash_iter_is_null(iter)) { - item = (struct util_hash_table_item *)util_hash_take(ht->head, util_hash_iter_key(iter)); - free(item); - iter = util_hash_first_node(ht->head); - } -} - -drm_private void util_hash_table_foreach(struct util_hash_table *ht, - void (*callback)(void *key, void *value, void *data), - void *data) -{ - struct util_hash_iter iter; - struct util_hash_table_item *item; - - assert(ht); - if (!ht) - return; - - iter = util_hash_first_node(ht->head); - while (!util_hash_iter_is_null(iter)) { - item = (struct util_hash_table_item *)util_hash_iter_data(iter); - callback(item->key, item->value, data); - iter = util_hash_iter_next(iter); - } -} - -static void util_hash_table_inc(void *k, void *v, void *d) -{ - ++*(size_t *)d; -} - -drm_private size_t util_hash_table_count(struct util_hash_table *ht) -{ - size_t count = 0; - util_hash_table_foreach(ht, util_hash_table_inc, &count); - return count; -} - -drm_private void util_hash_table_destroy(struct util_hash_table *ht) -{ - struct util_hash_iter iter; - struct util_hash_table_item *item; - - assert(ht); - if (!ht) - return; - - iter = util_hash_first_node(ht->head); - while (!util_hash_iter_is_null(iter)) { - item = (struct util_hash_table_item *)util_hash_iter_data(iter); - free(item); - iter = util_hash_iter_next(iter); - } - - util_hash_delete(ht->head); - free(ht); -} diff --git a/amdgpu/util_hash_table.h b/amdgpu/util_hash_table.h deleted file mode 100644 index 3ab81a12..00000000 --- a/amdgpu/util_hash_table.h +++ /dev/null @@ -1,71 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * General purpose hash table. - * - * @author José Fonseca <jfo...@vm...> - */ - -#ifndef U_HASH_TABLE_H_ -#define U_HASH_TABLE_H_ - -#include "libdrm_macros.h" - -/** - * Generic purpose hash table. - */ -struct util_hash_table; - -/** - * Create an hash table. - * - * @param hash hash function - * @param compare should return 0 for two equal keys. - */ -drm_private struct util_hash_table * -util_hash_table_create(unsigned (*hash)(void *key), - int (*compare)(void *key1, void *key2)); - -drm_private void -util_hash_table_set(struct util_hash_table *ht, void *key, void *value); - -drm_private void *util_hash_table_get(struct util_hash_table *ht, void *key); - -drm_private void util_hash_table_remove(struct util_hash_table *ht, void *key); - -drm_private void util_hash_table_clear(struct util_hash_table *ht); - -drm_private void util_hash_table_foreach(struct util_hash_table *ht, - void (*callback)(void *key, void *value, void *data), - void *data); - -drm_private size_t util_hash_table_count(struct util_hash_table *ht); - -drm_private void util_hash_table_destroy(struct util_hash_table *ht); - -#endif /* U_HASH_TABLE_H_ */ commit 9a38e850a543a3ea9c1315f501cd4484baed079d Author: Christian König <chr...@am...> Date: Thu Aug 2 10:56:11 2018 +0200 amdgpu: use handle table for flink names Instead of the hash use the handle table. Signed-off-by: Christian König <chr...@am...> Reviewed-by: Michel Dänzer <mic...@am...> Reviewed-and-Tested-by: Junwei Zhang <Jer...@am...> diff --git a/amdgpu/amdgpu_bo.c b/amdgpu/amdgpu_bo.c index 66edb8d4..02592377 100644 --- a/amdgpu/amdgpu_bo.c +++ b/amdgpu/amdgpu_bo.c @@ -37,7 +37,6 @@ #include "xf86drm.h" #include "amdgpu_drm.h" #include "amdgpu_internal.h" -#include "util_hash_table.h" #include "util_math.h" static void amdgpu_close_kms_handle(amdgpu_device_handle dev, @@ -219,12 +218,10 @@ static int amdgpu_bo_export_flink(amdgpu_bo_handle bo) } pthread_mutex_lock(&bo->dev->bo_table_mutex); - util_hash_table_set(bo->dev->bo_flink_names, - (void*)(uintptr_t)bo->flink_name, - bo); + r = handle_table_insert(&bo->dev->bo_flink_names, bo->flink_name, bo); pthread_mutex_unlock(&bo->dev->bo_table_mutex); - return 0; + return r; } int amdgpu_bo_export(amdgpu_bo_handle bo, @@ -301,8 +298,7 @@ int amdgpu_bo_import(amdgpu_device_handle dev, /* If we have already created a buffer with this handle, find it. */ switch (type) { case amdgpu_bo_handle_type_gem_flink_name: - bo = util_hash_table_get(dev->bo_flink_names, - (void*)(uintptr_t)shared_handle); + bo = handle_table_lookup(&dev->bo_flink_names, shared_handle); break; case amdgpu_bo_handle_type_dma_buf_fd: @@ -370,8 +366,13 @@ int amdgpu_bo_import(amdgpu_device_handle dev, } bo->flink_name = shared_handle; bo->alloc_size = open_arg.size; - util_hash_table_set(dev->bo_flink_names, - (void*)(uintptr_t)bo->flink_name, bo); + r = handle_table_insert(&dev->bo_flink_names, shared_handle, + bo); + if (r) { + pthread_mutex_unlock(&dev->bo_table_mutex); + amdgpu_bo_free(bo); + return r; + } break; case amdgpu_bo_handle_type_dma_buf_fd: @@ -410,10 +411,9 @@ int amdgpu_bo_free(amdgpu_bo_handle buf_handle) /* Remove the buffer from the hash tables. */ handle_table_remove(&dev->bo_handles, bo->handle); - if (bo->flink_name) { - util_hash_table_remove(dev->bo_flink_names, - (void*)(uintptr_t)bo->flink_name); - } + if (bo->flink_name) + handle_table_remove(&dev->bo_flink_names, + bo->flink_name); /* Release CPU access. */ if (bo->cpu_map_count > 0) { diff --git a/amdgpu/amdgpu_device.c b/amdgpu/amdgpu_device.c index 824c1dae..73eeeed6 100644 --- a/amdgpu/amdgpu_device.c +++ b/amdgpu/amdgpu_device.c @@ -39,7 +39,6 @@ #include "xf86drm.h" #include "amdgpu_drm.h" #include "amdgpu_internal.h" -#include "util_hash_table.h" #include "util_math.h" #define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x))) @@ -47,16 +46,6 @@ static pthread_mutex_t fd_mutex = PTHREAD_MUTEX_INITIALIZER; static amdgpu_device_handle fd_list; -static unsigned handle_hash(void *key) -{ - return PTR_TO_UINT(key); -} - -static int handle_compare(void *key1, void *key2) -{ - return PTR_TO_UINT(key1) != PTR_TO_UINT(key2); -} - static int fd_compare(int fd1, int fd2) { char *name1 = drmGetPrimaryDeviceNameFromFd(fd1); @@ -123,7 +112,7 @@ static void amdgpu_device_free_internal(amdgpu_device_handle dev) amdgpu_vamgr_deinit(&dev->vamgr_high_32); amdgpu_vamgr_deinit(&dev->vamgr_high); handle_table_fini(&dev->bo_handles); - util_hash_table_destroy(dev->bo_flink_names); + handle_table_fini(&dev->bo_flink_names); pthread_mutex_destroy(&dev->bo_table_mutex); free(dev->marketing_name); free(dev); @@ -228,8 +217,6 @@ int amdgpu_device_initialize(int fd, dev->minor_version = version->version_minor; drmFreeVersion(version); - dev->bo_flink_names = util_hash_table_create(handle_hash, - handle_compare); pthread_mutex_init(&dev->bo_table_mutex, NULL); /* Check if acceleration is working. */ diff --git a/amdgpu/amdgpu_internal.h b/amdgpu/amdgpu_internal.h index 36ebc738..a340abbd 100644 --- a/amdgpu/amdgpu_internal.h +++ b/amdgpu/amdgpu_internal.h @@ -76,7 +76,7 @@ struct amdgpu_device { /** List of buffer handles. Protected by bo_table_mutex. */ struct handle_table bo_handles; /** List of buffer GEM flink names. Protected by bo_table_mutex. */ - struct util_hash_table *bo_flink_names; + struct handle_table bo_flink_names; /** This protects all hash tables. */ pthread_mutex_t bo_table_mutex; struct drm_amdgpu_info_device dev_info; commit bde850bc32293702ff0bdd7b0acb5164c385785e Author: Christian König <chr...@am...> Date: Thu Aug 2 10:47:02 2018 +0200 amdgpu: use handle table for KMS handles Instead of the hash use the handle table. Signed-off-by: Christian König <chr...@am...> Reviewed-by: Michel Dänzer <mic...@am...> Reviewed-and-Tested-by: Junwei Zhang <Jer...@am...> diff --git a/amdgpu/amdgpu_bo.c b/amdgpu/amdgpu_bo.c index d29be244..66edb8d4 100644 --- a/amdgpu/amdgpu_bo.c +++ b/amdgpu/amdgpu_bo.c @@ -90,8 +90,12 @@ int amdgpu_bo_alloc(amdgpu_device_handle dev, pthread_mutex_init(&bo->cpu_access_mutex, NULL); - *buf_handle = bo; - return 0; + if (r) + amdgpu_bo_free(bo); + else + *buf_handle = bo; + + return r; } int amdgpu_bo_set_metadata(amdgpu_bo_handle bo, @@ -171,8 +175,7 @@ int amdgpu_bo_query_info(amdgpu_bo_handle bo, static void amdgpu_add_handle_to_table(amdgpu_bo_handle bo) { pthread_mutex_lock(&bo->dev->bo_table_mutex); - util_hash_table_set(bo->dev->bo_handles, - (void*)(uintptr_t)bo->handle, bo); + handle_table_insert(&bo->dev->bo_handles, bo->handle, bo); pthread_mutex_unlock(&bo->dev->bo_table_mutex); } @@ -303,8 +306,7 @@ int amdgpu_bo_import(amdgpu_device_handle dev, break; case amdgpu_bo_handle_type_dma_buf_fd: - bo = util_hash_table_get(dev->bo_handles, - (void*)(uintptr_t)shared_handle); + bo = handle_table_lookup(&dev->bo_handles, shared_handle); break; case amdgpu_bo_handle_type_kms: @@ -387,7 +389,7 @@ int amdgpu_bo_import(amdgpu_device_handle dev, bo->dev = dev; pthread_mutex_init(&bo->cpu_access_mutex, NULL); - util_hash_table_set(dev->bo_handles, (void*)(uintptr_t)bo->handle, bo); + handle_table_insert(&dev->bo_handles, bo->handle, bo); pthread_mutex_unlock(&dev->bo_table_mutex); output->buf_handle = bo; @@ -406,8 +408,7 @@ int amdgpu_bo_free(amdgpu_bo_handle buf_handle) if (update_references(&bo->refcount, NULL)) { /* Remove the buffer from the hash tables. */ - util_hash_table_remove(dev->bo_handles, - (void*)(uintptr_t)bo->handle); + handle_table_remove(&dev->bo_handles, bo->handle); if (bo->flink_name) { util_hash_table_remove(dev->bo_flink_names, diff --git a/amdgpu/amdgpu_device.c b/amdgpu/amdgpu_device.c index 38fd186d..824c1dae 100644 --- a/amdgpu/amdgpu_device.c +++ b/amdgpu/amdgpu_device.c @@ -122,8 +122,8 @@ static void amdgpu_device_free_internal(amdgpu_device_handle dev) amdgpu_vamgr_deinit(&dev->vamgr); amdgpu_vamgr_deinit(&dev->vamgr_high_32); amdgpu_vamgr_deinit(&dev->vamgr_high); + handle_table_fini(&dev->bo_handles); util_hash_table_destroy(dev->bo_flink_names); - util_hash_table_destroy(dev->bo_handles); pthread_mutex_destroy(&dev->bo_table_mutex); free(dev->marketing_name); free(dev); @@ -230,7 +230,6 @@ int amdgpu_device_initialize(int fd, dev->bo_flink_names = util_hash_table_create(handle_hash, handle_compare); - dev->bo_handles = util_hash_table_create(handle_hash, handle_compare); pthread_mutex_init(&dev->bo_table_mutex, NULL); /* Check if acceleration is working. */ diff --git a/amdgpu/amdgpu_internal.h b/amdgpu/amdgpu_internal.h index 83012cab..36ebc738 100644 --- a/amdgpu/amdgpu_internal.h +++ b/amdgpu/amdgpu_internal.h @@ -32,6 +32,7 @@ #include "xf86atomic.h" #include "amdgpu.h" #include "util_double_list.h" +#include "handle_table.h" #define AMDGPU_CS_MAX_RINGS 8 /* do not use below macro if b is not power of 2 aligned value */ @@ -73,7 +74,7 @@ struct amdgpu_device { char *marketing_name; /** List of buffer handles. Protected by bo_table_mutex. */ - struct util_hash_table *bo_handles; + struct handle_table bo_handles; /** List of buffer GEM flink names. Protected by bo_table_mutex. */ struct util_hash_table *bo_flink_names; /** This protects all hash tables. */ commit 52370cc6eb37e31f44daf563bada4392f6a58e49 Author: Christian König <chr...@am...> Date: Thu Aug 2 10:42:41 2018 +0200 amdgpu: add handle table implementation v2 The kernel handles are dense and the kernel always tries to use the lowest free id. Use this to implement a more efficient handle table by using a resizeable array instead of a hash. v2: add handle_table_fini function, extra key checks, fix typo in function name Signed-off-by: Christian König <chr...@am...> Reviewed-by: Michel Dänzer <mic...@am...> Reviewed-and-Tested-by: Junwei Zhang <Jer...@am...> diff --git a/amdgpu/Makefile.sources b/amdgpu/Makefile.sources index 498b64cc..62577ba5 100644 --- a/amdgpu/Makefile.sources +++ b/amdgpu/Makefile.sources @@ -10,7 +10,9 @@ LIBDRM_AMDGPU_FILES := \ util_hash.c \ util_hash.h \ util_hash_table.c \ - util_hash_table.h + util_hash_table.h \ + handle_table.c \ + handle_table.h LIBDRM_AMDGPU_H_FILES := \ amdgpu.h diff --git a/amdgpu/handle_table.c b/amdgpu/handle_table.c new file mode 100644 index 00000000..15cd4763 --- /dev/null +++ b/amdgpu/handle_table.c @@ -0,0 +1,72 @@ +/* + * Copyright 2018 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include "handle_table.h" +#include "util_math.h" + +drm_private int handle_table_insert(struct handle_table *table, uint32_t key, + void *value) +{ + if (key >= table->max_key) { + uint32_t alignment = sysconf(_SC_PAGESIZE) / sizeof(void*); + uint32_t max_key = ALIGN(key, alignment); + void **values; + + values = realloc(table->values, max_key * sizeof(void *)); + if (!values) + return -ENOMEM; + + memset(values + table->max_key, 0, (max_key - table->max_key) * + sizeof(void *)); + + table->max_key = max_key; + table->values = values; + } + table->values[key] = value; + return 0; +} + +drm_private void handle_table_remove(struct handle_table *table, uint32_t key) +{ + if (key < table->max_key) + table->values[key] = NULL; +} + +drm_private void *handle_table_lookup(struct handle_table *table, uint32_t key) +{ + if (key < table->max_key) + return table->values[key]; + else + return NULL; +} + +drm_private void handle_table_fini(struct handle_table *table) +{ + free(table->values); + table->max_key = 0; + table->values = NULL; +} diff --git a/amdgpu/handle_table.h b/amdgpu/handle_table.h new file mode 100644 index 00000000..461193f6 --- /dev/null +++ b/amdgpu/handle_table.h @@ -0,0 +1,41 @@ +/* + * Copyright 2018 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _HANDLE_TABLE_H_ +#define _HANDLE_TABLE_H_ + +#include <stdint.h> +#include "libdrm_macros.h" + +struct handle_table { + uint32_t max_key; + void **values; +}; + +drm_private int handle_table_insert(struct handle_table *table, uint32_t key, + void *value); +drm_private void handle_table_remove(struct handle_table *table, uint32_t key); +drm_private void *handle_table_lookup(struct handle_table *table, uint32_t key); +drm_private void handle_table_fini(struct handle_table *table); + +#endif /* _HANDLE_TABLE_H_ */ commit 7aa1a511336dd7cb26dafef81d76edd6978a6cdf Author: Christian König <chr...@am...> Date: Wed Aug 1 20:44:44 2018 +0200 amdgpu: stop using the hash table for fd_tab We have so few devices that just walking a linked list is probably faster. Signed-off-by: Christian König <chr...@am...> Reviewed-by: Michel Dänzer <mic...@am...> Reviewed-and-Tested-by: Junwei Zhang <Jer...@am...> diff --git a/amdgpu/amdgpu_device.c b/amdgpu/amdgpu_device.c index d7aec6a4..38fd186d 100644 --- a/amdgpu/amdgpu_device.c +++ b/amdgpu/amdgpu_device.c @@ -43,10 +43,9 @@ #include "util_math.h" #define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x))) -#define UINT_TO_PTR(x) ((void *)((intptr_t)(x))) static pthread_mutex_t fd_mutex = PTHREAD_MUTEX_INITIALIZER; -static struct util_hash_table *fd_tab; +static amdgpu_device_handle fd_list; static unsigned handle_hash(void *key) { @@ -58,28 +57,8 @@ static int handle_compare(void *key1, void *key2) return PTR_TO_UINT(key1) != PTR_TO_UINT(key2); } -static unsigned fd_hash(void *key) +static int fd_compare(int fd1, int fd2) { - int fd = PTR_TO_UINT(key); - char *name = drmGetPrimaryDeviceNameFromFd(fd); - unsigned result = 0; - char *c; - - if (name == NULL) - return 0; - - for (c = name; *c; ++c) - result += *c; - - free(name); - - return result; -} - -static int fd_compare(void *key1, void *key2) -{ - int fd1 = PTR_TO_UINT(key1); - int fd2 = PTR_TO_UINT(key2); char *name1 = drmGetPrimaryDeviceNameFromFd(fd1); char *name2 = drmGetPrimaryDeviceNameFromFd(fd2); int result; @@ -127,16 +106,17 @@ static int amdgpu_get_auth(int fd, int *auth) static void amdgpu_device_free_internal(amdgpu_device_handle dev) { + amdgpu_device_handle *node = &fd_list; + pthread_mutex_lock(&fd_mutex); - util_hash_table_remove(fd_tab, UINT_TO_PTR(dev->fd)); - if (util_hash_table_count(fd_tab) == 0) { - util_hash_table_destroy(fd_tab); - fd_tab = NULL; - } + while (*node != dev && (*node)->next) + node = &(*node)->next; + *node = (*node)->next; + pthread_mutex_unlock(&fd_mutex); + close(dev->fd); if ((dev->flink_fd >= 0) && (dev->fd != dev->flink_fd)) close(dev->flink_fd); - pthread_mutex_unlock(&fd_mutex); amdgpu_vamgr_deinit(&dev->vamgr_32); amdgpu_vamgr_deinit(&dev->vamgr); @@ -187,8 +167,6 @@ int amdgpu_device_initialize(int fd, *device_handle = NULL; pthread_mutex_lock(&fd_mutex); - if (!fd_tab) - fd_tab = util_hash_table_create(fd_hash, fd_compare); r = amdgpu_get_auth(fd, &flag_auth); if (r) { fprintf(stderr, "%s: amdgpu_get_auth (1) failed (%i)\n", @@ -196,7 +174,11 @@ int amdgpu_device_initialize(int fd, pthread_mutex_unlock(&fd_mutex); return r; } - dev = util_hash_table_get(fd_tab, UINT_TO_PTR(fd)); + + for (dev = fd_list; dev; dev = dev->next) + if (fd_compare(dev->fd, fd) == 0) + break; + if (dev) { r = amdgpu_get_auth(dev->fd, &flag_authexist); if (r) { @@ -297,7 +279,8 @@ int amdgpu_device_initialize(int fd, *major_version = dev->major_version; *minor_version = dev->minor_version; *device_handle = dev; - util_hash_table_set(fd_tab, UINT_TO_PTR(dev->fd), dev); + dev->next = fd_list; + fd_list = dev; pthread_mutex_unlock(&fd_mutex); return 0; diff --git a/amdgpu/amdgpu_internal.h b/amdgpu/amdgpu_internal.h index 99b8ce0b..83012cab 100644 --- a/amdgpu/amdgpu_internal.h +++ b/amdgpu/amdgpu_internal.h @@ -65,6 +65,7 @@ struct amdgpu_va { struct amdgpu_device { atomic_t refcount; + struct amdgpu_device *next; int fd; int flink_fd; unsigned major_version; |
From: <git...@ke...> - 2019-03-18 15:51:15
|
data/amdgpu.ids | 1 tests/amdgpu/amdgpu_test.c | 14 tests/amdgpu/basic_tests.c | 1228 +++++++++++++++++++++++++++++++++++++++++- tests/amdgpu/deadlock_tests.c | 103 +++ 4 files changed, 1343 insertions(+), 3 deletions(-) New commits: commit 852a9d20ad645d399774a2b3ff1746521841ba54 Author: Cui, Flora <Flo...@am...> Date: Fri Mar 15 08:51:21 2019 +0000 tests/amdgpu: add memcpy draw test add memcpy draw test for gfx9 Signed-off-by: Flora Cui <flo...@am...> Tested-by: Rui Teng <rui...@am...> Signed-off-by: Alex Deucher <ale...@am...> diff --git a/tests/amdgpu/basic_tests.c b/tests/amdgpu/basic_tests.c index 0ba61993..a364f67a 100644 --- a/tests/amdgpu/basic_tests.c +++ b/tests/amdgpu/basic_tests.c @@ -343,7 +343,8 @@ static const uint32_t preamblecache_gfx9[] = { }; enum ps_type { - PS_CONST + PS_CONST, + PS_TEX }; static const uint32_t ps_const_shader_gfx9[] = { @@ -391,6 +392,49 @@ static const uint32_t ps_const_context_reg_gfx9[][2] = { {0xA1C5, 0x00000004}, //{ mmSPI_SHADER_COL_FORMAT, 0x00000004 } }; +static const uint32_t ps_tex_shader_gfx9[] = { + 0xBEFC000C, 0xBE8E017E, 0xBEFE077E, 0xD4180000, + 0xD4190001, 0xD41C0100, 0xD41D0101, 0xF0800F00, + 0x00400206, 0xBEFE010E, 0xBF8C0F70, 0xD2960000, + 0x00020702, 0xD2960001, 0x00020B04, 0xC4001C0F, + 0x00000100, 0xBF810000 +}; + +static const uint32_t ps_tex_shader_patchinfo_offset_gfx9[] = { + 0x0000000B +}; + +static const uint32_t ps_tex_shader_patchinfo_code_size_gfx9 = 6; + +static const uint32_t ps_tex_shader_patchinfo_code_gfx9[][10][6] = { + {{ 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001890, 0x00000000 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001801, 0x00000002 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001803, 0x00000302 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001803, 0x00000502 }, + { 0xD2960000, 0x00020702, 0xD2960001, 0x00020B04, 0xC4001C0F, 0x00000100 }, + { 0xD2950000, 0x00020702, 0xD2950001, 0x00020B04, 0xC4001C0F, 0x00000100 }, + { 0xD2940000, 0x00020702, 0xD2940001, 0x00020B04, 0xC4001C0F, 0x00000100 }, + { 0xD2970000, 0x00020702, 0xD2970001, 0x00020B04, 0xC4001C0F, 0x00000100 }, + { 0xD2980000, 0x00020702, 0xD2980001, 0x00020B04, 0xC4001C0F, 0x00000100 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC400180F, 0x05040302 } + } +}; + +static const uint32_t ps_tex_sh_registers_gfx9[][2] = { + {0x2C0A, 0x000C0081},//{ mmSPI_SHADER_PGM_RSRC1_PS, 0x000C0081 }, + {0x2C0B, 0x00000018}, //{ mmSPI_SHADER_PGM_RSRC2_PS, 0x00000018 } +}; + +static const uint32_t ps_tex_context_reg_gfx9[][2] = { + {0xA1B4, 0x00000002}, //{ mmSPI_PS_INPUT_ADDR, 0x00000002 }, + {0xA1B6, 0x00000001}, //{ mmSPI_PS_IN_CONTROL, 0x00000001 }, + {0xA08F, 0x0000000F}, //{ mmCB_SHADER_MASK, 0x0000000F }, + {0xA203, 0x00000010}, //{ mmDB_SHADER_CONTROL, 0x00000010 }, + {0xA1C4, 0x00000000}, //{ mmSPI_SHADER_Z_FORMAT, 0x00000000 }, + {0xA1B8, 0x00000000}, //{ mmSPI_BARYC_CNTL, 0x00000000 /* Always 0 for now */}, + {0xA1C5, 0x00000004}, //{ mmSPI_SHADER_COL_FORMAT, 0x00000004 } +}; + static const uint32_t vs_RectPosTexFast_shader_gfx9[] = { 0x7E000B00, 0x020000F3, 0xD042000A, 0x00010100, 0x7E020202, 0x7E040200, 0x020000F3, 0x7E060206, @@ -2425,6 +2469,13 @@ static int amdgpu_draw_load_ps_shader(uint8_t *ptr, int ps_type) patchinfo_code_size = ps_const_shader_patchinfo_code_size_gfx9; patchcode_offset = ps_const_shader_patchinfo_offset_gfx9; break; + case PS_TEX: + shader = ps_tex_shader_gfx9; + shader_size = sizeof(ps_tex_shader_gfx9); + patchinfo_code = (const uint32_t *)ps_tex_shader_patchinfo_code_gfx9; + patchinfo_code_size = ps_tex_shader_patchinfo_code_size_gfx9; + patchcode_offset = ps_tex_shader_patchinfo_offset_gfx9; + break; default: return -1; break; @@ -2578,7 +2629,9 @@ static int amdgpu_draw_setup_and_write_drawblt_state(uint32_t *ptr) return i; } -static int amdgpu_draw_vs_RectPosTexFast_write2hw(uint32_t *ptr, uint64_t shader_addr) +static int amdgpu_draw_vs_RectPosTexFast_write2hw(uint32_t *ptr, + int ps_type, + uint64_t shader_addr) { int i = 0; @@ -2625,7 +2678,13 @@ static int amdgpu_draw_vs_RectPosTexFast_write2hw(uint32_t *ptr, uint64_t shader ptr[i++] = PACKET3(PKT3_SET_SH_REG, 4); ptr[i++] = 0x50; - i += 4; + i += 2; + if (ps_type == PS_CONST) { + i += 2; + } else if (ps_type == PS_TEX) { + ptr[i++] = 0x3f800000; + ptr[i++] = 0x3f800000; + } ptr[i++] = PACKET3(PKT3_SET_SH_REG, 4); ptr[i++] = 0x54; @@ -2634,17 +2693,26 @@ static int amdgpu_draw_vs_RectPosTexFast_write2hw(uint32_t *ptr, uint64_t shader return i; } -static int amdgpu_draw_ps_write2hw(uint32_t *ptr, uint64_t shader_addr) +static int amdgpu_draw_ps_write2hw(uint32_t *ptr, + int ps_type, + uint64_t shader_addr) { int i, j; const uint32_t *sh_registers; const uint32_t *context_registers; uint32_t num_sh_reg, num_context_reg; - sh_registers = (const uint32_t *)ps_const_sh_registers_gfx9; - context_registers = (const uint32_t *)ps_const_context_reg_gfx9; - num_sh_reg = ps_num_sh_registers_gfx9; - num_context_reg = ps_num_context_registers_gfx9; + if (ps_type == PS_CONST) { + sh_registers = (const uint32_t *)ps_const_sh_registers_gfx9; + context_registers = (const uint32_t *)ps_const_context_reg_gfx9; + num_sh_reg = ps_num_sh_registers_gfx9; + num_context_reg = ps_num_context_registers_gfx9; + } else if (ps_type == PS_TEX) { + sh_registers = (const uint32_t *)ps_tex_sh_registers_gfx9; + context_registers = (const uint32_t *)ps_tex_context_reg_gfx9; + num_sh_reg = ps_num_sh_registers_gfx9; + num_context_reg = ps_num_context_registers_gfx9; + } i = 0; @@ -2746,9 +2814,9 @@ void amdgpu_memset_draw(amdgpu_device_handle device_handle, i += amdgpu_draw_setup_and_write_drawblt_state(ptr_cmd + i); - i += amdgpu_draw_vs_RectPosTexFast_write2hw(ptr_cmd + i, mc_address_shader_vs); + i += amdgpu_draw_vs_RectPosTexFast_write2hw(ptr_cmd + i, PS_CONST, mc_address_shader_vs); - i += amdgpu_draw_ps_write2hw(ptr_cmd + i, mc_address_shader_ps); + i += amdgpu_draw_ps_write2hw(ptr_cmd + i, PS_CONST, mc_address_shader_ps); ptr_cmd[i++] = PACKET3(PKT3_SET_SH_REG, 4); ptr_cmd[i++] = 0xc; @@ -2853,6 +2921,178 @@ static void amdgpu_memset_draw_test(amdgpu_device_handle device_handle, CU_ASSERT_EQUAL(r, 0); } +static void amdgpu_memcpy_draw(amdgpu_device_handle device_handle, + amdgpu_bo_handle bo_shader_ps, + amdgpu_bo_handle bo_shader_vs, + uint64_t mc_address_shader_ps, + uint64_t mc_address_shader_vs, + uint32_t ring) +{ + amdgpu_context_handle context_handle; + amdgpu_bo_handle bo_dst, bo_src, bo_cmd, resources[5]; + volatile unsigned char *ptr_dst; + unsigned char *ptr_src; + uint32_t *ptr_cmd; + uint64_t mc_address_dst, mc_address_src, mc_address_cmd; + amdgpu_va_handle va_dst, va_src, va_cmd; + int i, r; + int bo_size = 16384; + int bo_cmd_size = 4096; + struct amdgpu_cs_request ibs_request = {0}; + struct amdgpu_cs_ib_info ib_info= {0}; + uint32_t hang_state, hangs, expired; + amdgpu_bo_list_handle bo_list; + struct amdgpu_cs_fence fence_status = {0}; + + r = amdgpu_cs_ctx_create(device_handle, &context_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_cmd_size, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &bo_cmd, (void **)&ptr_cmd, + &mc_address_cmd, &va_cmd); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_src, (void **)&ptr_src, + &mc_address_src, &va_src); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_dst, (void **)&ptr_dst, + &mc_address_dst, &va_dst); + CU_ASSERT_EQUAL(r, 0); + + memset(ptr_src, 0x55, bo_size); + + i = 0; + i += amdgpu_draw_init(ptr_cmd + i); + + i += amdgpu_draw_setup_and_write_drawblt_surf_info(ptr_cmd + i, mc_address_dst); + + i += amdgpu_draw_setup_and_write_drawblt_state(ptr_cmd + i); + + i += amdgpu_draw_vs_RectPosTexFast_write2hw(ptr_cmd + i, PS_TEX, mc_address_shader_vs); + + i += amdgpu_draw_ps_write2hw(ptr_cmd + i, PS_TEX, mc_address_shader_ps); + + ptr_cmd[i++] = PACKET3(PKT3_SET_SH_REG, 8); + ptr_cmd[i++] = 0xc; + ptr_cmd[i++] = mc_address_src >> 8; + ptr_cmd[i++] = mc_address_src >> 40 | 0x10e00000; + ptr_cmd[i++] = 0x7c01f; + ptr_cmd[i++] = 0x90500fac; + ptr_cmd[i++] = 0x3e000; + i += 3; + + ptr_cmd[i++] = PACKET3(PKT3_SET_SH_REG, 4); + ptr_cmd[i++] = 0x14; + ptr_cmd[i++] = 0x92; + i += 3; + + ptr_cmd[i++] = PACKET3(PKT3_SET_SH_REG, 1); + ptr_cmd[i++] = 0x191; + ptr_cmd[i++] = 0; + + i += amdgpu_draw_draw(ptr_cmd + i); + + while (i & 7) + ptr_cmd[i++] = 0xffff1000; /* type3 nop packet */ + + resources[0] = bo_dst; + resources[1] = bo_src; + resources[2] = bo_shader_ps; + resources[3] = bo_shader_vs; + resources[4] = bo_cmd; + r = amdgpu_bo_list_create(device_handle, 5, resources, NULL, &bo_list); + CU_ASSERT_EQUAL(r, 0); + + ib_info.ib_mc_address = mc_address_cmd; + ib_info.size = i; + ibs_request.ip_type = AMDGPU_HW_IP_GFX; + ibs_request.ring = ring; + ibs_request.resources = bo_list; + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.fence_info.handle = NULL; + r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1); + CU_ASSERT_EQUAL(r, 0); + + fence_status.ip_type = AMDGPU_HW_IP_GFX; + fence_status.ip_instance = 0; + fence_status.ring = ring; + fence_status.context = context_handle; + fence_status.fence = ibs_request.seq_no; + + /* wait for IB accomplished */ + r = amdgpu_cs_query_fence_status(&fence_status, + AMDGPU_TIMEOUT_INFINITE, + 0, &expired); + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_EQUAL(expired, true); + + /* verify if memcpy test result meets with expected */ + i = 0; + while(i < bo_size) { + CU_ASSERT_EQUAL(ptr_dst[i], ptr_src[i]); + i++; + } + + r = amdgpu_bo_list_destroy(bo_list); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_src, va_src, mc_address_src, bo_size); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_bo_unmap_and_free(bo_dst, va_dst, mc_address_dst, bo_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_cmd, va_cmd, mc_address_cmd, bo_cmd_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_free(context_handle); + CU_ASSERT_EQUAL(r, 0); +} + +static void amdgpu_memcpy_draw_test(amdgpu_device_handle device_handle, uint32_t ring) +{ + amdgpu_bo_handle bo_shader_ps, bo_shader_vs; + void *ptr_shader_ps; + void *ptr_shader_vs; + uint64_t mc_address_shader_ps, mc_address_shader_vs; + amdgpu_va_handle va_shader_ps, va_shader_vs; + int bo_shader_size = 4096; + int r; + + r = amdgpu_bo_alloc_and_map(device_handle, bo_shader_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_shader_ps, &ptr_shader_ps, + &mc_address_shader_ps, &va_shader_ps); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_shader_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_shader_vs, &ptr_shader_vs, + &mc_address_shader_vs, &va_shader_vs); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_draw_load_ps_shader(ptr_shader_ps, PS_TEX); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_draw_load_vs_shader(ptr_shader_vs); + CU_ASSERT_EQUAL(r, 0); + + amdgpu_memcpy_draw(device_handle, bo_shader_ps, bo_shader_vs, + mc_address_shader_ps, mc_address_shader_vs, ring); + + r = amdgpu_bo_unmap_and_free(bo_shader_ps, va_shader_ps, mc_address_shader_ps, bo_shader_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_shader_vs, va_shader_vs, mc_address_shader_vs, bo_shader_size); + CU_ASSERT_EQUAL(r, 0); +} + static void amdgpu_draw_test(void) { int r; @@ -2862,6 +3102,8 @@ static void amdgpu_draw_test(void) r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_GFX, 0, &info); CU_ASSERT_EQUAL(r, 0); - for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { amdgpu_memset_draw_test(device_handle, ring_id); + amdgpu_memcpy_draw_test(device_handle, ring_id); + } } commit 00dd9b72a13863dd73cf1340f3700a2bb00f0fe3 Author: Cui, Flora <Flo...@am...> Date: Fri Mar 15 08:51:18 2019 +0000 tests/amdgpu: add memset draw test add memset draw test for gfx9 Signed-off-by: Flora Cui <flo...@am...> Tested-by: Rui Teng <rui...@am...> Signed-off-by: Alex Deucher <ale...@am...> diff --git a/tests/amdgpu/amdgpu_test.c b/tests/amdgpu/amdgpu_test.c index 8cc87b13..a793ca7d 100644 --- a/tests/amdgpu/amdgpu_test.c +++ b/tests/amdgpu/amdgpu_test.c @@ -445,6 +445,11 @@ static void amdgpu_disable_suites() if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV) if (amdgpu_set_test_active(BASIC_TESTS_STR, "Dispatch Test", CU_FALSE)) fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + + /* This test was ran on GFX9 only */ + if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV) + if (amdgpu_set_test_active(BASIC_TESTS_STR, "Draw Test", CU_FALSE)) + fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); } /* The main() function for setting up and running the tests. diff --git a/tests/amdgpu/basic_tests.c b/tests/amdgpu/basic_tests.c index 2f559f4e..0ba61993 100644 --- a/tests/amdgpu/basic_tests.c +++ b/tests/amdgpu/basic_tests.c @@ -50,6 +50,7 @@ static void amdgpu_semaphore_test(void); static void amdgpu_sync_dependency_test(void); static void amdgpu_bo_eviction_test(void); static void amdgpu_dispatch_test(void); +static void amdgpu_draw_test(void); static void amdgpu_command_submission_write_linear_helper(unsigned ip_type); static void amdgpu_command_submission_const_fill_helper(unsigned ip_type); @@ -72,6 +73,7 @@ CU_TestInfo basic_tests[] = { { "SW semaphore Test", amdgpu_semaphore_test }, { "Sync dependency Test", amdgpu_sync_dependency_test }, { "Dispatch Test", amdgpu_dispatch_test }, + { "Draw Test", amdgpu_draw_test }, CU_TEST_INFO_NULL, }; #define BUFFER_SIZE (8 * 1024) @@ -318,6 +320,99 @@ static const uint32_t buffercopy_cs_shader_gfx9[] = { 0xBF8C0F70, 0xE01C2000, 0x80010100, 0xBF810000 }; +static const uint32_t preamblecache_gfx9[] = { + 0xc0026900, 0x81, 0x80000000, 0x40004000, 0xc0026900, 0x8c, 0xaa99aaaa, 0x0, + 0xc0026900, 0x90, 0x80000000, 0x40004000, 0xc0026900, 0x94, 0x80000000, 0x40004000, + 0xc0026900, 0xb4, 0x0, 0x3f800000, 0xc0016900, 0x103, 0x0, + 0xc0016900, 0x208, 0x0, 0xc0016900, 0x290, 0x0, + 0xc0016900, 0x2a1, 0x0, 0xc0026900, 0x2ad, 0x0, 0x0, + 0xc0016900, 0x2d5, 0x10000, 0xc0016900, 0x2dc, 0x0, + 0xc0066900, 0x2de, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0026900, 0x2e5, 0x0, 0x0, + 0xc0056900, 0x2f9, 0x5, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, + 0xc0026900, 0x311, 0x3, 0x0, 0xc0026900, 0x316, 0x1e, 0x20, + 0xc0016900, 0x349, 0x0, 0xc0016900, 0x358, 0x0, 0xc0016900, 0x367, 0x0, + 0xc0016900, 0x376, 0x0, 0xc0016900, 0x385, 0x0, 0xc0016900, 0x19, 0x0, + 0xc0056900, 0xe8, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xc0076900, 0x1e1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xc0026900, 0x204, 0x90000, 0x4, 0xc0046900, 0x20c, 0x0, 0x0, 0x0, 0x0, + 0xc0016900, 0x2b2, 0x0, 0xc0026900, 0x30e, 0xffffffff, 0xffffffff, + 0xc0016900, 0x314, 0x0, 0xc0002f00, 0x1, 0xc0016900, 0x1, 0x1, + 0xc0016900, 0x18, 0x2, 0xc0016900, 0x206, 0x300, 0xc0017900, 0x20000243, 0x0, + 0xc0017900, 0x248, 0xffffffff, 0xc0017900, 0x249, 0x0, 0xc0017900, 0x24a, 0x0, + 0xc0017900, 0x24b, 0x0 +}; + +enum ps_type { + PS_CONST +}; + +static const uint32_t ps_const_shader_gfx9[] = { + 0x7E000200, 0x7E020201, 0x7E040202, 0x7E060203, + 0xD2960000, 0x00020300, 0xD2960001, 0x00020702, + 0xC4001C0F, 0x00000100, 0xBF810000 +}; + +static const uint32_t ps_const_shader_patchinfo_code_size_gfx9 = 6; + +static const uint32_t ps_const_shader_patchinfo_code_gfx9[][10][6] = { + {{ 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001890, 0x00000000 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001801, 0x00000000 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001803, 0x00000100 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC4001803, 0x00000300 }, + { 0xD2960000, 0x00020300, 0xD2960001, 0x00020702, 0xC4001C0F, 0x00000100 }, + { 0xD2950000, 0x00020300, 0xD2950001, 0x00020702, 0xC4001C0F, 0x00000100 }, + { 0xD2940000, 0x00020300, 0xD2940001, 0x00020702, 0xC4001C0F, 0x00000100 }, + { 0xD2970000, 0x00020300, 0xD2970001, 0x00020702, 0xC4001C0F, 0x00000100 }, + { 0xD2980000, 0x00020300, 0xD2980001, 0x00020702, 0xC4001C0F, 0x00000100 }, + { 0xBF800000, 0xBF800000, 0xBF800000, 0xBF800000, 0xC400180F, 0x03020100 } + } +}; + +static const uint32_t ps_const_shader_patchinfo_offset_gfx9[] = { + 0x00000004 +}; + +static const uint32_t ps_num_sh_registers_gfx9 = 2; + +static const uint32_t ps_const_sh_registers_gfx9[][2] = { + {0x2C0A, 0x000C0040},//{ mmSPI_SHADER_PGM_RSRC1_PS, 0x000C0040 }, + {0x2C0B, 0x00000008}, //{ mmSPI_SHADER_PGM_RSRC2_PS, 0x00000008 } +}; + +static const uint32_t ps_num_context_registers_gfx9 = 7; + +static const uint32_t ps_const_context_reg_gfx9[][2] = { + {0xA1B4, 0x00000002}, //{ mmSPI_PS_INPUT_ADDR, 0x00000002 }, + {0xA1B6, 0x00000000}, //{ mmSPI_PS_IN_CONTROL, 0x00000000 }, + {0xA08F, 0x0000000F}, //{ mmCB_SHADER_MASK, 0x0000000F }, + {0xA203, 0x00000010}, //{ mmDB_SHADER_CONTROL, 0x00000010 }, + {0xA1C4, 0x00000000}, //{ mmSPI_SHADER_Z_FORMAT, 0x00000000 }, + {0xA1B8, 0x00000000}, //{ mmSPI_BARYC_CNTL, 0x00000000 /* Always 0 for now */}, + {0xA1C5, 0x00000004}, //{ mmSPI_SHADER_COL_FORMAT, 0x00000004 } +}; + +static const uint32_t vs_RectPosTexFast_shader_gfx9[] = { + 0x7E000B00, 0x020000F3, 0xD042000A, 0x00010100, + 0x7E020202, 0x7E040200, 0x020000F3, 0x7E060206, + 0x7E080204, 0xD1000001, 0x002A0302, 0x7C840080, + 0x7E000200, 0x7E040203, 0x7E0A0201, 0xD1000003, + 0x002A0704, 0x7E0C0207, 0x7E0E0205, 0x00000101, + 0x00020505, 0x7E040208, 0x7E0A02F2, 0x00060903, + 0x00080D07, 0x7E0C0209, 0xC40008CF, 0x05020100, + 0xC400020F, 0x05060403, 0xBF810000 +}; + +static const uint32_t cached_cmd_gfx9[] = { + 0xc0016900, 0x0, 0x0, 0xc0026900, 0x3, 0x2a, 0x0, + 0xc0046900, 0xa, 0x0, 0x0, 0x0, 0x200020, + 0xc0016900, 0x83, 0xffff, 0xc0026900, 0x8e, 0xf, 0xf, + 0xc0056900, 0x105, 0x0, 0x0, 0x0, 0x0, 0x12, + 0xc0026900, 0x10b, 0x0, 0x0, 0xc0016900, 0x1e0, 0x0, + 0xc0036900, 0x200, 0x0, 0x10000, 0xcc0011, + 0xc0026900, 0x292, 0x20, 0x60201b8, + 0xc0026900, 0x2b0, 0x0, 0x0, 0xc0016900, 0x2f8, 0x0 +}; + int amdgpu_bo_alloc_and_map_raw(amdgpu_device_handle dev, unsigned size, unsigned alignment, unsigned heap, uint64_t alloc_flags, uint64_t mapping_flags, amdgpu_bo_handle *bo, void **cpu, @@ -2311,3 +2406,462 @@ static void amdgpu_dispatch_test(void) amdgpu_memcpy_dispatch_test(device_handle, AMDGPU_HW_IP_GFX, ring_id); } } + +static int amdgpu_draw_load_ps_shader(uint8_t *ptr, int ps_type) +{ + int i; + uint32_t shader_offset= 256; + uint32_t mem_offset, patch_code_offset; + uint32_t shader_size, patchinfo_code_size; + const uint32_t *shader; + const uint32_t *patchinfo_code; + const uint32_t *patchcode_offset; + + switch (ps_type) { + case PS_CONST: + shader = ps_const_shader_gfx9; + shader_size = sizeof(ps_const_shader_gfx9); + patchinfo_code = (const uint32_t *)ps_const_shader_patchinfo_code_gfx9; + patchinfo_code_size = ps_const_shader_patchinfo_code_size_gfx9; + patchcode_offset = ps_const_shader_patchinfo_offset_gfx9; + break; + default: + return -1; + break; + } + + /* write main shader program */ + for (i = 0 ; i < 10; i++) { + mem_offset = i * shader_offset; + memcpy(ptr + mem_offset, shader, shader_size); + } + + /* overwrite patch codes */ + for (i = 0 ; i < 10; i++) { + mem_offset = i * shader_offset + patchcode_offset[0] * sizeof(uint32_t); + patch_code_offset = i * patchinfo_code_size; + memcpy(ptr + mem_offset, + patchinfo_code + patch_code_offset, + patchinfo_code_size * sizeof(uint32_t)); + } + + return 0; +} + +/* load RectPosTexFast_VS */ +static int amdgpu_draw_load_vs_shader(uint8_t *ptr) +{ + const uint32_t *shader; + uint32_t shader_size; + + shader = vs_RectPosTexFast_shader_gfx9; + shader_size = sizeof(vs_RectPosTexFast_shader_gfx9); + + memcpy(ptr, shader, shader_size); + + return 0; +} + +static int amdgpu_draw_init(uint32_t *ptr) +{ + int i = 0; + const uint32_t *preamblecache_ptr; + uint32_t preamblecache_size; + + /* Write context control and load shadowing register if necessary */ + ptr[i++] = PACKET3(PKT3_CONTEXT_CONTROL, 1); + ptr[i++] = 0x80000000; + ptr[i++] = 0x80000000; + + preamblecache_ptr = preamblecache_gfx9; + preamblecache_size = sizeof(preamblecache_gfx9); + + memcpy(ptr + i, preamblecache_ptr, preamblecache_size); + return i + preamblecache_size/sizeof(uint32_t); +} + +static int amdgpu_draw_setup_and_write_drawblt_surf_info(uint32_t *ptr, + uint64_t dst_addr) +{ + int i = 0; + + /* setup color buffer */ + /* offset reg + 0xA318 CB_COLOR0_BASE + 0xA319 CB_COLOR0_BASE_EXT + 0xA31A CB_COLOR0_ATTRIB2 + 0xA31B CB_COLOR0_VIEW + 0xA31C CB_COLOR0_INFO + 0xA31D CB_COLOR0_ATTRIB + 0xA31E CB_COLOR0_DCC_CONTROL + 0xA31F CB_COLOR0_CMASK + 0xA320 CB_COLOR0_CMASK_BASE_EXT + 0xA321 CB_COLOR0_FMASK + 0xA322 CB_COLOR0_FMASK_BASE_EXT + 0xA323 CB_COLOR0_CLEAR_WORD0 + 0xA324 CB_COLOR0_CLEAR_WORD1 + 0xA325 CB_COLOR0_DCC_BASE + 0xA326 CB_COLOR0_DCC_BASE_EXT */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 15); + ptr[i++] = 0x318; + ptr[i++] = dst_addr >> 8; + ptr[i++] = dst_addr >> 40; + ptr[i++] = 0x7c01f; + ptr[i++] = 0; + ptr[i++] = 0x50438; + ptr[i++] = 0x10140000; + i += 9; + + /* mmCB_MRT0_EPITCH */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x1e8; + ptr[i++] = 0x1f; + + /* 0xA32B CB_COLOR1_BASE */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x32b; + ptr[i++] = 0; + + /* 0xA33A CB_COLOR1_BASE */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x33a; + ptr[i++] = 0; + + /* SPI_SHADER_COL_FORMAT */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x1c5; + ptr[i++] = 9; + + /* Setup depth buffer */ + /* mmDB_Z_INFO */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 2); + ptr[i++] = 0xe; + i += 2; + + return i; +} + +static int amdgpu_draw_setup_and_write_drawblt_state(uint32_t *ptr) +{ + int i = 0; + const uint32_t *cached_cmd_ptr; + uint32_t cached_cmd_size; + + /* mmPA_SC_TILE_STEERING_OVERRIDE */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0xd7; + ptr[i++] = 0; + + ptr[i++] = 0xffff1000; + ptr[i++] = 0xc0021000; + + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0xd7; + ptr[i++] = 1; + + /* mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 16); + ptr[i++] = 0x2fe; + i += 16; + + /* mmPA_SC_CENTROID_PRIORITY_0 */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 2); + ptr[i++] = 0x2f5; + i += 2; + + cached_cmd_ptr = cached_cmd_gfx9; + cached_cmd_size = sizeof(cached_cmd_gfx9); + + memcpy(ptr + i, cached_cmd_ptr, cached_cmd_size); + i += cached_cmd_size/sizeof(uint32_t); + + return i; +} + +static int amdgpu_draw_vs_RectPosTexFast_write2hw(uint32_t *ptr, uint64_t shader_addr) +{ + int i = 0; + + /* mmPA_CL_VS_OUT_CNTL */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x207; + ptr[i++] = 0; + + /* mmSPI_SHADER_PGM_RSRC3_VS */ + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 1); + ptr[i++] = 0x46; + ptr[i++] = 0xffff; + + /* mmSPI_SHADER_PGM_LO_VS...mmSPI_SHADER_PGM_HI_VS */ + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 2); + ptr[i++] = 0x48; + ptr[i++] = shader_addr >> 8; + ptr[i++] = shader_addr >> 40; + + /* mmSPI_SHADER_PGM_RSRC1_VS */ + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 1); + ptr[i++] = 0x4a; + ptr[i++] = 0xc0081; + /* mmSPI_SHADER_PGM_RSRC2_VS */ + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 1); + ptr[i++] = 0x4b; + ptr[i++] = 0x18; + + /* mmSPI_VS_OUT_CONFIG */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x1b1; + ptr[i++] = 2; + + /* mmSPI_SHADER_POS_FORMAT */ + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x1c3; + ptr[i++] = 4; + + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 4); + ptr[i++] = 0x4c; + i += 2; + ptr[i++] = 0x42000000; + ptr[i++] = 0x42000000; + + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 4); + ptr[i++] = 0x50; + i += 4; + + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 4); + ptr[i++] = 0x54; + i += 4; + + return i; +} + +static int amdgpu_draw_ps_write2hw(uint32_t *ptr, uint64_t shader_addr) +{ + int i, j; + const uint32_t *sh_registers; + const uint32_t *context_registers; + uint32_t num_sh_reg, num_context_reg; + + sh_registers = (const uint32_t *)ps_const_sh_registers_gfx9; + context_registers = (const uint32_t *)ps_const_context_reg_gfx9; + num_sh_reg = ps_num_sh_registers_gfx9; + num_context_reg = ps_num_context_registers_gfx9; + + i = 0; + + /* 0x2c07 SPI_SHADER_PGM_RSRC3_PS + 0x2c08 SPI_SHADER_PGM_LO_PS + 0x2c09 SPI_SHADER_PGM_HI_PS */ + shader_addr += 256 * 9; + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 3); + ptr[i++] = 0x7; + ptr[i++] = 0xffff; + ptr[i++] = shader_addr >> 8; + ptr[i++] = shader_addr >> 40; + + for (j = 0; j < num_sh_reg; j++) { + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 1); + ptr[i++] = sh_registers[j * 2] - 0x2c00; + ptr[i++] = sh_registers[j * 2 + 1]; + } + + for (j = 0; j < num_context_reg; j++) { + if (context_registers[j * 2] != 0xA1C5) { + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = context_registers[j * 2] - 0xa000; + ptr[i++] = context_registers[j * 2 + 1]; + } + + if (context_registers[j * 2] == 0xA1B4) { + ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr[i++] = 0x1b3; + ptr[i++] = 2; + } + } + + return i; +} + +static int amdgpu_draw_draw(uint32_t *ptr) +{ + int i = 0; + + /* mmIA_MULTI_VGT_PARAM */ + ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1); + ptr[i++] = 0x40000258; + ptr[i++] = 0xd00ff; + + /* mmVGT_PRIMITIVE_TYPE */ + ptr[i++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1); + ptr[i++] = 0x10000242; + ptr[i++] = 0x11; + + ptr[i++] = PACKET3(PACKET3_DRAW_INDEX_AUTO, 1); + ptr[i++] = 3; + ptr[i++] = 2; + + return i; +} + +void amdgpu_memset_draw(amdgpu_device_handle device_handle, + amdgpu_bo_handle bo_shader_ps, + amdgpu_bo_handle bo_shader_vs, + uint64_t mc_address_shader_ps, + uint64_t mc_address_shader_vs, + uint32_t ring_id) +{ + amdgpu_context_handle context_handle; + amdgpu_bo_handle bo_dst, bo_cmd, resources[4]; + volatile unsigned char *ptr_dst; + uint32_t *ptr_cmd; + uint64_t mc_address_dst, mc_address_cmd; + amdgpu_va_handle va_dst, va_cmd; + int i, r; + int bo_dst_size = 16384; + int bo_cmd_size = 4096; + struct amdgpu_cs_request ibs_request = {0}; + struct amdgpu_cs_ib_info ib_info = {0}; + struct amdgpu_cs_fence fence_status = {0}; + uint32_t expired; + amdgpu_bo_list_handle bo_list; + + r = amdgpu_cs_ctx_create(device_handle, &context_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_cmd_size, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &bo_cmd, (void **)&ptr_cmd, + &mc_address_cmd, &va_cmd); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_dst_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_dst, (void **)&ptr_dst, + &mc_address_dst, &va_dst); + CU_ASSERT_EQUAL(r, 0); + + i = 0; + i += amdgpu_draw_init(ptr_cmd + i); + + i += amdgpu_draw_setup_and_write_drawblt_surf_info(ptr_cmd + i, mc_address_dst); + + i += amdgpu_draw_setup_and_write_drawblt_state(ptr_cmd + i); + + i += amdgpu_draw_vs_RectPosTexFast_write2hw(ptr_cmd + i, mc_address_shader_vs); + + i += amdgpu_draw_ps_write2hw(ptr_cmd + i, mc_address_shader_ps); + + ptr_cmd[i++] = PACKET3(PKT3_SET_SH_REG, 4); + ptr_cmd[i++] = 0xc; + ptr_cmd[i++] = 0x33333333; + ptr_cmd[i++] = 0x33333333; + ptr_cmd[i++] = 0x33333333; + ptr_cmd[i++] = 0x33333333; + + i += amdgpu_draw_draw(ptr_cmd + i); + + while (i & 7) + ptr_cmd[i++] = 0xffff1000; /* type3 nop packet */ + + resources[0] = bo_dst; + resources[1] = bo_shader_ps; + resources[2] = bo_shader_vs; + resources[3] = bo_cmd; + r = amdgpu_bo_list_create(device_handle, 3, resources, NULL, &bo_list); + CU_ASSERT_EQUAL(r, 0); + + ib_info.ib_mc_address = mc_address_cmd; + ib_info.size = i; + ibs_request.ip_type = AMDGPU_HW_IP_GFX; + ibs_request.ring = ring_id; + ibs_request.resources = bo_list; + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.fence_info.handle = NULL; + + /* submit CS */ + r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_list_destroy(bo_list); + CU_ASSERT_EQUAL(r, 0); + + fence_status.ip_type = AMDGPU_HW_IP_GFX; + fence_status.ip_instance = 0; + fence_status.ring = ring_id; + fence_status.context = context_handle; + fence_status.fence = ibs_request.seq_no; + + /* wait for IB accomplished */ + r = amdgpu_cs_query_fence_status(&fence_status, + AMDGPU_TIMEOUT_INFINITE, + 0, &expired); + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_EQUAL(expired, true); + + /* verify if memset test result meets with expected */ + i = 0; + while(i < bo_dst_size) { + CU_ASSERT_EQUAL(ptr_dst[i++], 0x33); + } + + r = amdgpu_bo_unmap_and_free(bo_dst, va_dst, mc_address_dst, bo_dst_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_cmd, va_cmd, mc_address_cmd, bo_cmd_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_free(context_handle); + CU_ASSERT_EQUAL(r, 0); +} + +static void amdgpu_memset_draw_test(amdgpu_device_handle device_handle, + uint32_t ring) +{ + amdgpu_bo_handle bo_shader_ps, bo_shader_vs; + void *ptr_shader_ps; + void *ptr_shader_vs; + uint64_t mc_address_shader_ps, mc_address_shader_vs; + amdgpu_va_handle va_shader_ps, va_shader_vs; + int r; + int bo_shader_size = 4096; + + r = amdgpu_bo_alloc_and_map(device_handle, bo_shader_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_shader_ps, &ptr_shader_ps, + &mc_address_shader_ps, &va_shader_ps); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_shader_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_shader_vs, &ptr_shader_vs, + &mc_address_shader_vs, &va_shader_vs); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_draw_load_ps_shader(ptr_shader_ps, PS_CONST); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_draw_load_vs_shader(ptr_shader_vs); + CU_ASSERT_EQUAL(r, 0); + + amdgpu_memset_draw(device_handle, bo_shader_ps, bo_shader_vs, + mc_address_shader_ps, mc_address_shader_vs, ring); + + r = amdgpu_bo_unmap_and_free(bo_shader_ps, va_shader_ps, mc_address_shader_ps, bo_shader_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_shader_vs, va_shader_vs, mc_address_shader_vs, bo_shader_size); + CU_ASSERT_EQUAL(r, 0); +} + +static void amdgpu_draw_test(void) +{ + int r; + struct drm_amdgpu_info_hw_ip info; + uint32_t ring_id; + + r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_GFX, 0, &info); + CU_ASSERT_EQUAL(r, 0); + + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) + amdgpu_memset_draw_test(device_handle, ring_id); +} commit c1ced0bafdb4c817a30ff7b8c4ceb7db1e93ecc5 Author: Cui, Flora <Flo...@am...> Date: Fri Mar 15 08:51:13 2019 +0000 tests/amdgpu: add memcpy dispatch test add memcpy dispatch test for gfx9 Signed-off-by: Flora Cui <flo...@am...> Tested-by: Rui Teng <rui...@am...> Reviewed-by: Hawking Zhang <Haw...@am...> Signed-off-by: Alex Deucher <ale...@am...> diff --git a/tests/amdgpu/basic_tests.c b/tests/amdgpu/basic_tests.c index fe6db09a..2f559f4e 100644 --- a/tests/amdgpu/basic_tests.c +++ b/tests/amdgpu/basic_tests.c @@ -294,6 +294,7 @@ static uint32_t shader_bin[] = { enum cs_type { CS_BUFFERCLEAR, + CS_BUFFERCOPY }; static const uint32_t bufferclear_cs_shader_gfx9[] = { @@ -312,6 +313,11 @@ static const uint32_t bufferclear_cs_shader_registers_gfx9[][2] = { static const uint32_t bufferclear_cs_shader_registers_num_gfx9 = 5; +static const uint32_t buffercopy_cs_shader_gfx9[] = { + 0xD1FD0000, 0x04010C08, 0xE00C2000, 0x80000100, + 0xBF8C0F70, 0xE01C2000, 0x80010100, 0xBF810000 +}; + int amdgpu_bo_alloc_and_map_raw(amdgpu_device_handle dev, unsigned size, unsigned alignment, unsigned heap, uint64_t alloc_flags, uint64_t mapping_flags, amdgpu_bo_handle *bo, void **cpu, @@ -1920,6 +1926,10 @@ static int amdgpu_dispatch_load_cs_shader(uint8_t *ptr, shader = bufferclear_cs_shader_gfx9; shader_size = sizeof(bufferclear_cs_shader_gfx9); break; + case CS_BUFFERCOPY: + shader = buffercopy_cs_shader_gfx9; + shader_size = sizeof(buffercopy_cs_shader_gfx9); + break; default: return -1; break; @@ -2134,6 +2144,151 @@ static void amdgpu_memset_dispatch_test(amdgpu_device_handle device_handle, CU_ASSERT_EQUAL(r, 0); } +void amdgpu_memcpy_dispatch_test(amdgpu_device_handle device_handle, + uint32_t ip_type, + uint32_t ring) +{ + amdgpu_context_handle context_handle; + amdgpu_bo_handle bo_src, bo_dst, bo_shader, bo_cmd, resources[4]; + volatile unsigned char *ptr_dst; + void *ptr_shader; + unsigned char *ptr_src; + uint32_t *ptr_cmd; + uint64_t mc_address_src, mc_address_dst, mc_address_shader, mc_address_cmd; + amdgpu_va_handle va_src, va_dst, va_shader, va_cmd; + int i, r; + int bo_dst_size = 16384; + int bo_shader_size = 4096; + int bo_cmd_size = 4096; + struct amdgpu_cs_request ibs_request = {0}; + struct amdgpu_cs_ib_info ib_info= {0}; + uint32_t expired; + amdgpu_bo_list_handle bo_list; + struct amdgpu_cs_fence fence_status = {0}; + + r = amdgpu_cs_ctx_create(device_handle, &context_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_cmd_size, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &bo_cmd, (void **)&ptr_cmd, + &mc_address_cmd, &va_cmd); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_shader_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_shader, &ptr_shader, + &mc_address_shader, &va_shader); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_dispatch_load_cs_shader(ptr_shader, CS_BUFFERCOPY ); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_dst_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_src, (void **)&ptr_src, + &mc_address_src, &va_src); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_dst_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_dst, (void **)&ptr_dst, + &mc_address_dst, &va_dst); + CU_ASSERT_EQUAL(r, 0); + + memset(ptr_src, 0x55, bo_dst_size); + + i = 0; + i += amdgpu_dispatch_init(ptr_cmd + i, ip_type); + + /* Issue commands to set cu mask used in current dispatch */ + i += amdgpu_dispatch_write_cumask(ptr_cmd + i); + + /* Writes shader state to HW */ + i += amdgpu_dispatch_write2hw(ptr_cmd + i, mc_address_shader); + + /* Write constant data */ + /* Writes the texture resource constants data to the SGPRs */ + ptr_cmd[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 4); + ptr_cmd[i++] = 0x240; + ptr_cmd[i++] = mc_address_src; + ptr_cmd[i++] = (mc_address_src >> 32) | 0x100000; + ptr_cmd[i++] = 0x400; + ptr_cmd[i++] = 0x74fac; + + /* Writes the UAV constant data to the SGPRs. */ + ptr_cmd[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 4); + ptr_cmd[i++] = 0x244; + ptr_cmd[i++] = mc_address_dst; + ptr_cmd[i++] = (mc_address_dst >> 32) | 0x100000; + ptr_cmd[i++] = 0x400; + ptr_cmd[i++] = 0x74fac; + + /* dispatch direct command */ + ptr_cmd[i++] = PACKET3_COMPUTE(PACKET3_DISPATCH_DIRECT, 3); + ptr_cmd[i++] = 0x10; + ptr_cmd[i++] = 1; + ptr_cmd[i++] = 1; + ptr_cmd[i++] = 1; + + while (i & 7) + ptr_cmd[i++] = 0xffff1000; /* type3 nop packet */ + + resources[0] = bo_shader; + resources[1] = bo_src; + resources[2] = bo_dst; + resources[3] = bo_cmd; + r = amdgpu_bo_list_create(device_handle, 4, resources, NULL, &bo_list); + CU_ASSERT_EQUAL(r, 0); + + ib_info.ib_mc_address = mc_address_cmd; + ib_info.size = i; + ibs_request.ip_type = ip_type; + ibs_request.ring = ring; + ibs_request.resources = bo_list; + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.fence_info.handle = NULL; + r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1); + CU_ASSERT_EQUAL(r, 0); + + fence_status.ip_type = ip_type; + fence_status.ip_instance = 0; + fence_status.ring = ring; + fence_status.context = context_handle; + fence_status.fence = ibs_request.seq_no; + + /* wait for IB accomplished */ + r = amdgpu_cs_query_fence_status(&fence_status, + AMDGPU_TIMEOUT_INFINITE, + 0, &expired); + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_EQUAL(expired, true); + + /* verify if memcpy test result meets with expected */ + i = 0; + while(i < bo_dst_size) { + CU_ASSERT_EQUAL(ptr_dst[i], ptr_src[i]); + i++; + } + + r = amdgpu_bo_list_destroy(bo_list); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_src, va_src, mc_address_src, bo_dst_size); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_bo_unmap_and_free(bo_dst, va_dst, mc_address_dst, bo_dst_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_cmd, va_cmd, mc_address_cmd, bo_cmd_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_shader, va_shader, mc_address_shader, bo_shader_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_free(context_handle); + CU_ASSERT_EQUAL(r, 0); +} static void amdgpu_dispatch_test(void) { int r; @@ -2143,12 +2298,16 @@ static void amdgpu_dispatch_test(void) r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_COMPUTE, 0, &info); CU_ASSERT_EQUAL(r, 0); - for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { amdgpu_memset_dispatch_test(device_handle, AMDGPU_HW_IP_COMPUTE, ring_id); + amdgpu_memcpy_dispatch_test(device_handle, AMDGPU_HW_IP_COMPUTE, ring_id); + } r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_GFX, 0, &info); CU_ASSERT_EQUAL(r, 0); - for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { amdgpu_memset_dispatch_test(device_handle, AMDGPU_HW_IP_GFX, ring_id); + amdgpu_memcpy_dispatch_test(device_handle, AMDGPU_HW_IP_GFX, ring_id); + } } commit 8db4e2db41491ba05b7fe4da0725114bbf2378b2 Author: Cui, Flora <Flo...@am...> Date: Fri Mar 15 08:50:54 2019 +0000 tests/amdgpu: add memset dispatch test add memset dispatch test for gfx9 v2: disable dispatch test for other ASICs Signed-off-by: Flora Cui <flo...@am...> Tested-by: Rui Teng <rui...@am...> Reviewed-by: Hawking Zhang <Haw...@am...> Signed-off-by: Alex Deucher <ale...@am...> diff --git a/tests/amdgpu/amdgpu_test.c b/tests/amdgpu/amdgpu_test.c index 38b8a681..8cc87b13 100644 --- a/tests/amdgpu/amdgpu_test.c +++ b/tests/amdgpu/amdgpu_test.c @@ -440,6 +440,11 @@ static void amdgpu_disable_suites() if (family_id < AMDGPU_FAMILY_VI || family_id > AMDGPU_FAMILY_RV) if (amdgpu_set_test_active(BASIC_TESTS_STR, "Sync dependency Test", CU_FALSE)) fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + + /* This test was ran on GFX9 only */ + if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV) + if (amdgpu_set_test_active(BASIC_TESTS_STR, "Dispatch Test", CU_FALSE)) + fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); } /* The main() function for setting up and running the tests. diff --git a/tests/amdgpu/basic_tests.c b/tests/amdgpu/basic_tests.c index dbae4d53..fe6db09a 100644 --- a/tests/amdgpu/basic_tests.c +++ b/tests/amdgpu/basic_tests.c @@ -49,6 +49,7 @@ static void amdgpu_userptr_test(void); static void amdgpu_semaphore_test(void); static void amdgpu_sync_dependency_test(void); static void amdgpu_bo_eviction_test(void); +static void amdgpu_dispatch_test(void); static void amdgpu_command_submission_write_linear_helper(unsigned ip_type); static void amdgpu_command_submission_const_fill_helper(unsigned ip_type); @@ -70,6 +71,7 @@ CU_TestInfo basic_tests[] = { { "Command submission Test (SDMA)", amdgpu_command_submission_sdma }, { "SW semaphore Test", amdgpu_semaphore_test }, { "Sync dependency Test", amdgpu_sync_dependency_test }, + { "Dispatch Test", amdgpu_dispatch_test }, CU_TEST_INFO_NULL, }; #define BUFFER_SIZE (8 * 1024) @@ -117,6 +119,7 @@ CU_TestInfo basic_tests[] = { #define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \ (((op) & 0xFF) << 8) | \ ((n) & 0x3FFF) << 16) +#define PACKET3_COMPUTE(op, n) PACKET3(op, n) | (1 << 1) /* Packet 3 types */ #define PACKET3_NOP 0x10 @@ -245,8 +248,11 @@ CU_TestInfo basic_tests[] = { #define PACKET3_SET_SH_REG_START 0x00002c00 #define PACKET3_DISPATCH_DIRECT 0x15 - - +#define PACKET3_EVENT_WRITE 0x46 +#define PACKET3_ACQUIRE_MEM 0x58 +#define PACKET3_SET_CONTEXT_REG 0x69 +#define PACKET3_SET_UCONFIG_REG 0x79 +#define PACKET3_DRAW_INDEX_AUTO 0x2D /* gfx 8 */ #define mmCOMPUTE_PGM_LO 0x2e0c #define mmCOMPUTE_PGM_RSRC1 0x2e12 @@ -286,6 +292,25 @@ static uint32_t shader_bin[] = { #define CODE_OFFSET 512 #define DATA_OFFSET 1024 +enum cs_type { + CS_BUFFERCLEAR, +}; + +static const uint32_t bufferclear_cs_shader_gfx9[] = { + 0xD1FD0000, 0x04010C08, 0x7E020204, 0x7E040205, + 0x7E060206, 0x7E080207, 0xE01C2000, 0x80000100, + 0xBF810000 +}; + +static const uint32_t bufferclear_cs_shader_registers_gfx9[][2] = { + {0x2e12, 0x000C0041}, //{ mmCOMPUTE_PGM_RSRC1, 0x000C0041 }, + {0x2e13, 0x00000090}, //{ mmCOMPUTE_PGM_RSRC2, 0x00000090 }, + {0x2e07, 0x00000040}, //{ mmCOMPUTE_NUM_THREAD_X, 0x00000040 }, + {0x2e08, 0x00000001}, //{ mmCOMPUTE_NUM_THREAD_Y, 0x00000001 }, + {0x2e09, 0x00000001}, //{ mmCOMPUTE_NUM_THREAD_Z, 0x00000001 } +}; + +static const uint32_t bufferclear_cs_shader_registers_num_gfx9 = 5; int amdgpu_bo_alloc_and_map_raw(amdgpu_device_handle dev, unsigned size, unsigned alignment, unsigned heap, uint64_t alloc_flags, @@ -1883,3 +1908,247 @@ static void amdgpu_sync_dependency_test(void) free(ibs_request.dependencies); } + +static int amdgpu_dispatch_load_cs_shader(uint8_t *ptr, + int cs_type) +{ + uint32_t shader_size; + const uint32_t *shader; + + switch (cs_type) { + case CS_BUFFERCLEAR: + shader = bufferclear_cs_shader_gfx9; + shader_size = sizeof(bufferclear_cs_shader_gfx9); + break; + default: + return -1; + break; + } + + memcpy(ptr, shader, shader_size); + return 0; +} + +static int amdgpu_dispatch_init(uint32_t *ptr, uint32_t ip_type) +{ + int i = 0; + + /* Write context control and load shadowing register if necessary */ + if (ip_type == AMDGPU_HW_IP_GFX) { + ptr[i++] = PACKET3(PKT3_CONTEXT_CONTROL, 1); + ptr[i++] = 0x80000000; + ptr[i++] = 0x80000000; + } + + /* Issue commands to set default compute state. */ + /* clear mmCOMPUTE_START_Z - mmCOMPUTE_START_X */ + ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 3); + ptr[i++] = 0x204; + i += 3; + /* clear mmCOMPUTE_RESOURCE_LIMITS */ + ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 1); + ptr[i++] = 0x215; + ptr[i++] = 0; + /* clear mmCOMPUTE_TMPRING_SIZE */ + ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 1); + ptr[i++] = 0x218; + ptr[i++] = 0; + + return i; +} + +static int amdgpu_dispatch_write_cumask(uint32_t *ptr) +{ + int i = 0; + + /* Issue commands to set cu mask used in current dispatch */ + /* set mmCOMPUTE_STATIC_THREAD_MGMT_SE1 - mmCOMPUTE_STATIC_THREAD_MGMT_SE0 */ + ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 2); + ptr[i++] = 0x216; + ptr[i++] = 0xffffffff; + ptr[i++] = 0xffffffff; + /* set mmCOMPUTE_STATIC_THREAD_MGMT_SE3 - mmCOMPUTE_STATIC_THREAD_MGMT_SE2 */ + ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 2); + ptr[i++] = 0x219; + ptr[i++] = 0xffffffff; + ptr[i++] = 0xffffffff; + + return i; +} + +static int amdgpu_dispatch_write2hw(uint32_t *ptr, uint64_t shader_addr) +{ + int i, j; + + i = 0; + + /* Writes shader state to HW */ + /* set mmCOMPUTE_PGM_HI - mmCOMPUTE_PGM_LO */ + ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 2); + ptr[i++] = 0x20c; + ptr[i++] = (shader_addr >> 8); + ptr[i++] = (shader_addr >> 40); + /* write sh regs*/ + for (j = 0; j < bufferclear_cs_shader_registers_num_gfx9; j++) { + ptr[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 1); + /* - Gfx9ShRegBase */ + ptr[i++] = bufferclear_cs_shader_registers_gfx9[j][0] - 0x2c00; + ptr[i++] = bufferclear_cs_shader_registers_gfx9[j][1]; + } + + return i; +} + +static void amdgpu_memset_dispatch_test(amdgpu_device_handle device_handle, + uint32_t ip_type, + uint32_t ring) +{ + amdgpu_context_handle context_handle; + amdgpu_bo_handle bo_dst, bo_shader, bo_cmd, resources[3]; + volatile unsigned char *ptr_dst; + void *ptr_shader; + uint32_t *ptr_cmd; + uint64_t mc_address_dst, mc_address_shader, mc_address_cmd; + amdgpu_va_handle va_dst, va_shader, va_cmd; + int i, r; + int bo_dst_size = 16384; + int bo_shader_size = 4096; + int bo_cmd_size = 4096; + struct amdgpu_cs_request ibs_request = {0}; + struct amdgpu_cs_ib_info ib_info= {0}; + amdgpu_bo_list_handle bo_list; + struct amdgpu_cs_fence fence_status = {0}; + uint32_t expired; + + r = amdgpu_cs_ctx_create(device_handle, &context_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_cmd_size, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &bo_cmd, (void **)&ptr_cmd, + &mc_address_cmd, &va_cmd); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_shader_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_shader, &ptr_shader, + &mc_address_shader, &va_shader); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_dispatch_load_cs_shader(ptr_shader, CS_BUFFERCLEAR); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_dst_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_dst, (void **)&ptr_dst, + &mc_address_dst, &va_dst); + CU_ASSERT_EQUAL(r, 0); + + i = 0; + i += amdgpu_dispatch_init(ptr_cmd + i, ip_type); + + /* Issue commands to set cu mask used in current dispatch */ + i += amdgpu_dispatch_write_cumask(ptr_cmd + i); + + /* Writes shader state to HW */ + i += amdgpu_dispatch_write2hw(ptr_cmd + i, mc_address_shader); + + /* Write constant data */ + /* Writes the UAV constant data to the SGPRs. */ + ptr_cmd[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 4); + ptr_cmd[i++] = 0x240; + ptr_cmd[i++] = mc_address_dst; + ptr_cmd[i++] = (mc_address_dst >> 32) | 0x100000; + ptr_cmd[i++] = 0x400; + ptr_cmd[i++] = 0x74fac; + + /* Sets a range of pixel shader constants */ + ptr_cmd[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 4); + ptr_cmd[i++] = 0x244; + ptr_cmd[i++] = 0x22222222; + ptr_cmd[i++] = 0x22222222; + ptr_cmd[i++] = 0x22222222; + ptr_cmd[i++] = 0x22222222; + + /* dispatch direct command */ + ptr_cmd[i++] = PACKET3_COMPUTE(PACKET3_DISPATCH_DIRECT, 3); + ptr_cmd[i++] = 0x10; + ptr_cmd[i++] = 1; + ptr_cmd[i++] = 1; + ptr_cmd[i++] = 1; + + while (i & 7) + ptr_cmd[i++] = 0xffff1000; /* type3 nop packet */ + + resources[0] = bo_dst; + resources[1] = bo_shader; + resources[2] = bo_cmd; + r = amdgpu_bo_list_create(device_handle, 3, resources, NULL, &bo_list); + CU_ASSERT_EQUAL(r, 0); + + ib_info.ib_mc_address = mc_address_cmd; + ib_info.size = i; + ibs_request.ip_type = ip_type; + ibs_request.ring = ring; + ibs_request.resources = bo_list; + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.fence_info.handle = NULL; + + /* submit CS */ + r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_list_destroy(bo_list); + CU_ASSERT_EQUAL(r, 0); + + fence_status.ip_type = ip_type; + fence_status.ip_instance = 0; + fence_status.ring = ring; + fence_status.context = context_handle; + fence_status.fence = ibs_request.seq_no; + + /* wait for IB accomplished */ + r = amdgpu_cs_query_fence_status(&fence_status, + AMDGPU_TIMEOUT_INFINITE, + 0, &expired); + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_EQUAL(expired, true); + + /* verify if memset test result meets with expected */ + i = 0; + while(i < bo_dst_size) { + CU_ASSERT_EQUAL(ptr_dst[i++], 0x22); + } + + r = amdgpu_bo_unmap_and_free(bo_dst, va_dst, mc_address_dst, bo_dst_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_shader, va_shader, mc_address_shader, bo_shader_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_cmd, va_cmd, mc_address_cmd, bo_cmd_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_free(context_handle); + CU_ASSERT_EQUAL(r, 0); +} + +static void amdgpu_dispatch_test(void) +{ + int r; + struct drm_amdgpu_info_hw_ip info; + uint32_t ring_id; + + r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_COMPUTE, 0, &info); + CU_ASSERT_EQUAL(r, 0); + + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) + amdgpu_memset_dispatch_test(device_handle, AMDGPU_HW_IP_COMPUTE, ring_id); + + r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_GFX, 0, &info); + CU_ASSERT_EQUAL(r, 0); + + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) + amdgpu_memset_dispatch_test(device_handle, AMDGPU_HW_IP_GFX, ring_id); +} commit 8c6dbd7938092ff64b64bb8d637d56b0dc3f7fc9 Author: Cui, Flora <Flo...@am...> Date: Wed Mar 6 06:37:13 2019 +0000 tests/amdgpu: add deadlock test for sdma deadlock test for sdma will cause gpu recoverty. disable the test for now until GPU reset recovery could survive at least 1000 times test. v2: add modprobe parameter Reviewed-and-tested-by: Evan Quan <eva...@am...> Acked-by: Christian König <chr...@am...> Signed-off-by: Flora Cui <flo...@am...> Signed-off-by: Alex Deucher <ale...@am...> diff --git a/tests/amdgpu/amdgpu_test.c b/tests/amdgpu/amdgpu_test.c index ebf44098..38b8a681 100644 --- a/tests/amdgpu/amdgpu_test.c +++ b/tests/amdgpu/amdgpu_test.c @@ -426,6 +426,10 @@ static void amdgpu_disable_suites() "compute ring block test (set amdgpu.lockup_timeout=50)", CU_FALSE)) fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + if (amdgpu_set_test_active(DEADLOCK_TESTS_STR, + "sdma ring block test (set amdgpu.lockup_timeout=50)", CU_FALSE)) + fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + if (amdgpu_set_test_active(BO_TESTS_STR, "Metadata", CU_FALSE)) fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); diff --git a/tests/amdgpu/deadlock_tests.c b/tests/amdgpu/deadlock_tests.c index a6c2635d..91368c15 100644 --- a/tests/amdgpu/deadlock_tests.c +++ b/tests/amdgpu/deadlock_tests.c @@ -96,6 +96,9 @@ #define mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x54f +#define SDMA_PKT_HEADER_OP(x) (x & 0xff) +#define SDMA_OP_POLL_REGMEM 8 + static amdgpu_device_handle device_handle; static uint32_t major_version; static uint32_t minor_version; @@ -110,6 +113,7 @@ static void amdgpu_deadlock_gfx(void); static void amdgpu_deadlock_compute(void); static void amdgpu_illegal_reg_access(); static void amdgpu_illegal_mem_access(); +static void amdgpu_deadlock_sdma(void); CU_BOOL suite_deadlock_tests_enable(void) { @@ -171,6 +175,7 @@ int suite_deadlock_tests_clean(void) CU_TestInfo deadlock_tests[] = { { "gfx ring block test (set amdgpu.lockup_timeout=50)", amdgpu_deadlock_gfx }, { "compute ring block test (set amdgpu.lockup_timeout=50)", amdgpu_deadlock_compute }, + { "sdma ring block test (set amdgpu.lockup_timeout=50)", amdgpu_deadlock_sdma }, { "illegal reg access test", amdgpu_illegal_reg_access }, { "illegal mem access test (set amdgpu.vm_fault_stop=2)", amdgpu_illegal_mem_access }, CU_TEST_INFO_NULL, @@ -260,7 +265,6 @@ static void amdgpu_deadlock_helper(unsigned ip_type) ibs_request.ibs = &ib_info; ibs_request.resources = bo_list; ibs_request.fence_info.handle = NULL; - for (i = 0; i < 200; i++) { r = amdgpu_cs_submit(context_handle, 0,&ibs_request, 1); CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1); @@ -291,6 +295,103 @@ static void amdgpu_deadlock_helper(unsigned ip_type) CU_ASSERT_EQUAL(r, 0); } +static void amdgpu_deadlock_sdma(void) +{ + amdgpu_context_handle context_handle; + amdgpu_bo_handle ib_result_handle; + void *ib_result_cpu; + uint64_t ib_result_mc_address; + struct amdgpu_cs_request ibs_request; + struct amdgpu_cs_ib_info ib_info; + struct amdgpu_cs_fence fence_status; + uint32_t expired; + int i, r; + amdgpu_bo_list_handle bo_list; + amdgpu_va_handle va_handle; + struct drm_amdgpu_info_hw_ip info; + uint32_t ring_id; + + r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_DMA, 0, &info); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_create(device_handle, &context_handle); + CU_ASSERT_EQUAL(r, 0); + + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { + r = pthread_create(&stress_thread, NULL, write_mem_address, NULL); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map_raw(device_handle, 4096, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, use_uc_mtype ? AMDGPU_VM_MTYPE_UC : 0, + &ib_result_handle, &ib_result_cpu, + &ib_result_mc_address, &va_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL, + &bo_list); + CU_ASSERT_EQUAL(r, 0); + + ptr = ib_result_cpu; + i = 0; + + ptr[i++] = SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) | + (0 << 26) | /* WAIT_REG_MEM */ + (4 << 28) | /* != */ + (1 << 31); /* memory */ + ptr[i++] = (ib_result_mc_address + 256*4) & 0xfffffffc; + ptr[i++] = ((ib_result_mc_address + 256*4) >> 32) & 0xffffffff; + ptr[i++] = 0x00000000; /* reference value */ + ptr[i++] = 0xffffffff; /* and mask */ + ptr[i++] = 4 | /* poll interval */ + (0xfff << 16); /* retry count */ + + for (; i < 16; i++) + ptr[i] = 0; + + ptr[256] = 0x0; /* the memory we wait on to change */ + + memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info)); + ib_info.ib_mc_address = ib_result_mc_address; + ib_info.size = 16; + + memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request)); + ibs_request.ip_type = AMDGPU_HW_IP_DMA; + ibs_request.ring = ring_id; + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.resources = bo_list; + ibs_request.fence_info.handle = NULL; + + for (i = 0; i < 200; i++) { + r = amdgpu_cs_submit(context_handle, 0,&ibs_request, 1); + CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1); + + } + + memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence)); + fence_status.context = context_handle; + fence_status.ip_type = AMDGPU_HW_IP_DMA; + fence_status.ip_instance = 0; + fence_status.ring = ring_id; + fence_status.fence = ibs_request.seq_no; + + r = amdgpu_cs_query_fence_status(&fence_status, + AMDGPU_TIMEOUT_INFINITE,0, &expired); + CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1); + + pthread_join(stress_thread, NULL); + + r = amdgpu_bo_list_destroy(bo_list); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle, + ib_result_mc_address, 4096); + CU_ASSERT_EQUAL(r, 0); + } + r = amdgpu_cs_ctx_free(context_handle); + CU_ASSERT_EQUAL(r, 0); +} + static void bad_access_helper(int reg_access) { amdgpu_context_handle context_handle; commit c8bc69a165e1ec62ccea56efbb70b1854337606b Author: Alex Deucher <ale...@am...> Date: Tue Mar 5 11:14:31 2019 -0500 amdgpu: add marketing name for AMD Radeon VII Signed-off-by: Alex Deucher <ale...@am...> diff --git a/data/amdgpu.ids b/data/amdgpu.ids index d24c7ee6..f61497e4 100644 --- a/data/amdgpu.ids +++ b/data/amdgpu.ids @@ -45,6 +45,7 @@ 6665, 83, AMD Radeon (TM) R5 M320 6667, 0, AMD Radeon R5 M200 Series 666F, 0, AMD Radeon HD 8500M +66AF, C1, AMD Radeon VII 6780, 0, ATI FirePro V (FireGL V) Graphics Adapter 678A, 0, ATI FirePro V (FireGL V) Graphics Adapter 6798, 0, AMD Radeon HD 7900 Series |
From: <git...@ke...> - 2019-12-09 20:47:24
|
tests/amdgpu/amdgpu_test.c | 35 ++ tests/amdgpu/amdgpu_test.h | 5 tests/amdgpu/basic_tests.c | 581 +++++++++++++++++++++++++++++++++++++++--- tests/amdgpu/deadlock_tests.c | 66 ++++ 4 files changed, 646 insertions(+), 41 deletions(-) New commits: commit 31a6ec141ad0f190af59a96d86f0ebe8fcee6287 Author: Flora Cui <flo...@am...> Date: Mon Mar 18 16:45:31 2019 +0800 tests/amdgpu: add gfx ring bad slow draw test for gfx9 Signed-off-by: Flora Cui <flo...@am...> Reviewed-by: Marek Olšák <mar...@am...> diff --git a/tests/amdgpu/amdgpu_test.c b/tests/amdgpu/amdgpu_test.c index 54bd33dc..ea4a9113 100644 --- a/tests/amdgpu/amdgpu_test.c +++ b/tests/amdgpu/amdgpu_test.c @@ -481,6 +481,12 @@ static void amdgpu_disable_suites() "gfx ring bad draw test (set amdgpu.lockup_timeout=50)", CU_FALSE)) fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + /* This test was ran on GFX9 only */ + //if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV) + if (amdgpu_set_test_active(DEADLOCK_TESTS_STR, + "gfx ring slow bad draw test (set amdgpu.lockup_timeout=50)", CU_FALSE)) + fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + if (amdgpu_set_test_active(BO_TESTS_STR, "Metadata", CU_FALSE)) fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); diff --git a/tests/amdgpu/amdgpu_test.h b/tests/amdgpu/amdgpu_test.h index 21c024fd..f5492258 100644 --- a/tests/amdgpu/amdgpu_test.h +++ b/tests/amdgpu/amdgpu_test.h @@ -240,6 +240,8 @@ void amdgpu_dispatch_hang_helper(amdgpu_device_handle device_handle, uint32_t ip void amdgpu_dispatch_hang_slow_helper(amdgpu_device_handle device_handle, uint32_t ip_type); void amdgpu_memcpy_draw_test(amdgpu_device_handle device_handle, uint32_t ring, int hang); +void amdgpu_memcpy_draw_hang_slow_test(amdgpu_device_handle device_handle, uint32_t ring); + /** * Helper functions */ diff --git a/tests/amdgpu/basic_tests.c b/tests/amdgpu/basic_tests.c index 44e6cce4..84f3827d 100644 --- a/tests/amdgpu/basic_tests.c +++ b/tests/amdgpu/basic_tests.c @@ -358,7 +358,8 @@ static const uint32_t preamblecache_gfx9[] = { enum ps_type { PS_CONST, PS_TEX, - PS_HANG + PS_HANG, + PS_HANG_SLOW }; static const uint32_t ps_const_shader_gfx9[] = { @@ -510,6 +511,21 @@ struct amdgpu_test_shader memcpy_cs_hang_slow_rv = { 1 }; +unsigned int memcpy_ps_hang_slow_ai_codes[] = { + 0xbefc000c, 0xbe8e017e, 0xbefe077e, 0xd4080000, + 0xd4090001, 0xd40c0100, 0xd40d0101, 0xf0800f00, + 0x00400002, 0xbefe010e, 0xbf8c0f70, 0xbf800000, + 0xbf800000, 0xbf800000, 0xbf800000, 0xc400180f, + 0x03020100, 0xbf810000 +}; + +struct amdgpu_test_shader memcpy_ps_hang_slow_ai = { + memcpy_ps_hang_slow_ai_codes, + 7, + 2, + 9 +}; + int amdgpu_bo_alloc_and_map_raw(amdgpu_device_handle dev, unsigned size, unsigned alignment, unsigned heap, uint64_t alloc_flags, uint64_t mapping_flags, amdgpu_bo_handle *bo, void **cpu, @@ -2759,6 +2775,35 @@ void amdgpu_dispatch_hang_slow_helper(amdgpu_device_handle device_handle, uint32 } } +static int amdgpu_draw_load_ps_shader_hang_slow(uint32_t *ptr, int family) +{ + struct amdgpu_test_shader *shader; + int i, loop = 0x40000; + + switch (family) { + case AMDGPU_FAMILY_AI: + case AMDGPU_FAMILY_RV: + shader = &memcpy_ps_hang_slow_ai; + break; + default: + return -1; + break; + } + + memcpy(ptr, shader->shader, shader->header_length * sizeof(uint32_t)); + + for (i = 0; i < loop; i++) + memcpy(ptr + shader->header_length + shader->body_length * i, + shader->shader + shader->header_length, + shader->body_length * sizeof(uint32_t)); + + memcpy(ptr + shader->header_length + shader->body_length * loop, + shader->shader + shader->header_length + shader->body_length, + shader->foot_length * sizeof(uint32_t)); + + return 0; +} + static int amdgpu_draw_load_ps_shader(uint8_t *ptr, int ps_type) { int i; @@ -2846,7 +2891,8 @@ static int amdgpu_draw_init(uint32_t *ptr) } static int amdgpu_draw_setup_and_write_drawblt_surf_info(uint32_t *ptr, - uint64_t dst_addr) + uint64_t dst_addr, + int hang_slow) { int i = 0; @@ -2871,7 +2917,7 @@ static int amdgpu_draw_setup_and_write_drawblt_surf_info(uint32_t *ptr, ptr[i++] = 0x318; ptr[i++] = dst_addr >> 8; ptr[i++] = dst_addr >> 40; - ptr[i++] = 0x7c01f; + ptr[i++] = hang_slow ? 0x1ffc7ff : 0x7c01f; ptr[i++] = 0; ptr[i++] = 0x50438; ptr[i++] = 0x10140000; @@ -2880,7 +2926,7 @@ static int amdgpu_draw_setup_and_write_drawblt_surf_info(uint32_t *ptr, /* mmCB_MRT0_EPITCH */ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); ptr[i++] = 0x1e8; - ptr[i++] = 0x1f; + ptr[i++] = hang_slow ? 0x7ff : 0x1f; /* 0xA32B CB_COLOR1_BASE */ ptr[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); @@ -2906,7 +2952,7 @@ static int amdgpu_draw_setup_and_write_drawblt_surf_info(uint32_t *ptr, return i; } -static int amdgpu_draw_setup_and_write_drawblt_state(uint32_t *ptr) +static int amdgpu_draw_setup_and_write_drawblt_state(uint32_t *ptr, int hang_slow) { int i = 0; const uint32_t *cached_cmd_ptr; @@ -2938,6 +2984,8 @@ static int amdgpu_draw_setup_and_write_drawblt_state(uint32_t *ptr) cached_cmd_size = sizeof(cached_cmd_gfx9); memcpy(ptr + i, cached_cmd_ptr, cached_cmd_size); + if (hang_slow) + *(ptr + i + 12) = 0x8000800; i += cached_cmd_size/sizeof(uint32_t); return i; @@ -2945,7 +2993,8 @@ static int amdgpu_draw_setup_and_write_drawblt_state(uint32_t *ptr) static int amdgpu_draw_vs_RectPosTexFast_write2hw(uint32_t *ptr, int ps_type, - uint64_t shader_addr) + uint64_t shader_addr, + int hang_slow) { int i = 0; @@ -2987,8 +3036,8 @@ static int amdgpu_draw_vs_RectPosTexFast_write2hw(uint32_t *ptr, ptr[i++] = PACKET3(PKT3_SET_SH_REG, 4); ptr[i++] = 0x4c; i += 2; - ptr[i++] = 0x42000000; - ptr[i++] = 0x42000000; + ptr[i++] = hang_slow ? 0x45000000 : 0x42000000; + ptr[i++] = hang_slow ? 0x45000000 : 0x42000000; ptr[i++] = PACKET3(PKT3_SET_SH_REG, 4); ptr[i++] = 0x50; @@ -3125,11 +3174,11 @@ void amdgpu_memset_draw(amdgpu_device_handle device_handle, i = 0; i += amdgpu_draw_init(ptr_cmd + i); - i += amdgpu_draw_setup_and_write_drawblt_surf_info(ptr_cmd + i, mc_address_dst); + i += amdgpu_draw_setup_and_write_drawblt_surf_info(ptr_cmd + i, mc_address_dst, 0); - i += amdgpu_draw_setup_and_write_drawblt_state(ptr_cmd + i); + i += amdgpu_draw_setup_and_write_drawblt_state(ptr_cmd + i, 0); - i += amdgpu_draw_vs_RectPosTexFast_write2hw(ptr_cmd + i, PS_CONST, mc_address_shader_vs); + i += amdgpu_draw_vs_RectPosTexFast_write2hw(ptr_cmd + i, PS_CONST, mc_address_shader_vs, 0); i += amdgpu_draw_ps_write2hw(ptr_cmd + i, PS_CONST, mc_address_shader_ps); @@ -3288,11 +3337,11 @@ static void amdgpu_memcpy_draw(amdgpu_device_handle device_handle, i = 0; i += amdgpu_draw_init(ptr_cmd + i); - i += amdgpu_draw_setup_and_write_drawblt_surf_info(ptr_cmd + i, mc_address_dst); + i += amdgpu_draw_setup_and_write_drawblt_surf_info(ptr_cmd + i, mc_address_dst, 0); - i += amdgpu_draw_setup_and_write_drawblt_state(ptr_cmd + i); + i += amdgpu_draw_setup_and_write_drawblt_state(ptr_cmd + i, 0); - i += amdgpu_draw_vs_RectPosTexFast_write2hw(ptr_cmd + i, PS_TEX, mc_address_shader_vs); + i += amdgpu_draw_vs_RectPosTexFast_write2hw(ptr_cmd + i, PS_TEX, mc_address_shader_vs, 0); i += amdgpu_draw_ps_write2hw(ptr_cmd + i, PS_TEX, mc_address_shader_ps); @@ -3438,6 +3487,168 @@ static void amdgpu_draw_test(void) } } +void amdgpu_memcpy_draw_hang_slow_test(amdgpu_device_handle device_handle, uint32_t ring) +{ + amdgpu_context_handle context_handle; + amdgpu_bo_handle bo_shader_ps, bo_shader_vs; + amdgpu_bo_handle bo_dst, bo_src, bo_cmd, resources[5]; + void *ptr_shader_ps; + void *ptr_shader_vs; + volatile unsigned char *ptr_dst; + unsigned char *ptr_src; + uint32_t *ptr_cmd; + uint64_t mc_address_dst, mc_address_src, mc_address_cmd; + uint64_t mc_address_shader_ps, mc_address_shader_vs; + amdgpu_va_handle va_shader_ps, va_shader_vs; + amdgpu_va_handle va_dst, va_src, va_cmd; + struct amdgpu_gpu_info gpu_info = {0}; + int i, r; + int bo_size = 0x4000000; + int bo_shader_ps_size = 0x400000; + int bo_shader_vs_size = 4096; + int bo_cmd_size = 4096; + struct amdgpu_cs_request ibs_request = {0}; + struct amdgpu_cs_ib_info ib_info= {0}; + uint32_t hang_state, hangs, expired; + amdgpu_bo_list_handle bo_list; + struct amdgpu_cs_fence fence_status = {0}; + + r = amdgpu_query_gpu_info(device_handle, &gpu_info); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_create(device_handle, &context_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_cmd_size, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &bo_cmd, (void **)&ptr_cmd, + &mc_address_cmd, &va_cmd); + CU_ASSERT_EQUAL(r, 0); + memset(ptr_cmd, 0, bo_cmd_size); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_shader_ps_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_shader_ps, &ptr_shader_ps, + &mc_address_shader_ps, &va_shader_ps); + CU_ASSERT_EQUAL(r, 0); + memset(ptr_shader_ps, 0, bo_shader_ps_size); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_shader_vs_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_shader_vs, &ptr_shader_vs, + &mc_address_shader_vs, &va_shader_vs); + CU_ASSERT_EQUAL(r, 0); + memset(ptr_shader_vs, 0, bo_shader_vs_size); + + r = amdgpu_draw_load_ps_shader_hang_slow(ptr_shader_ps, gpu_info.family_id); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_draw_load_vs_shader(ptr_shader_vs); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_src, (void **)&ptr_src, + &mc_address_src, &va_src); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_dst, (void **)&ptr_dst, + &mc_address_dst, &va_dst); + CU_ASSERT_EQUAL(r, 0); + + memset(ptr_src, 0x55, bo_size); + + i = 0; + i += amdgpu_draw_init(ptr_cmd + i); + + i += amdgpu_draw_setup_and_write_drawblt_surf_info(ptr_cmd + i, mc_address_dst, 1); + + i += amdgpu_draw_setup_and_write_drawblt_state(ptr_cmd + i, 1); + + i += amdgpu_draw_vs_RectPosTexFast_write2hw(ptr_cmd + i, PS_TEX, + mc_address_shader_vs, 1); + + i += amdgpu_draw_ps_write2hw(ptr_cmd + i, PS_TEX, mc_address_shader_ps); + + ptr_cmd[i++] = PACKET3(PKT3_SET_SH_REG, 8); + ptr_cmd[i++] = 0xc; + ptr_cmd[i++] = mc_address_src >> 8; + ptr_cmd[i++] = mc_address_src >> 40 | 0x10e00000; + ptr_cmd[i++] = 0x1ffc7ff; + ptr_cmd[i++] = 0x90500fac; + ptr_cmd[i++] = 0xffe000; + i += 3; + + ptr_cmd[i++] = PACKET3(PKT3_SET_SH_REG, 4); + ptr_cmd[i++] = 0x14; + ptr_cmd[i++] = 0x92; + i += 3; + + ptr_cmd[i++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + ptr_cmd[i++] = 0x191; + ptr_cmd[i++] = 0; + + i += amdgpu_draw_draw(ptr_cmd + i); + + while (i & 7) + ptr_cmd[i++] = 0xffff1000; /* type3 nop packet */ + + resources[0] = bo_dst; + resources[1] = bo_src; + resources[2] = bo_shader_ps; + resources[3] = bo_shader_vs; + resources[4] = bo_cmd; + r = amdgpu_bo_list_create(device_handle, 5, resources, NULL, &bo_list); + CU_ASSERT_EQUAL(r, 0); + + ib_info.ib_mc_address = mc_address_cmd; + ib_info.size = i; + ibs_request.ip_type = AMDGPU_HW_IP_GFX; + ibs_request.ring = ring; + ibs_request.resources = bo_list; + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.fence_info.handle = NULL; + r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1); + CU_ASSERT_EQUAL(r, 0); + + fence_status.ip_type = AMDGPU_HW_IP_GFX; + fence_status.ip_instance = 0; + fence_status.ring = ring; + fence_status.context = context_handle; + fence_status.fence = ibs_request.seq_no; + + /* wait for IB accomplished */ + r = amdgpu_cs_query_fence_status(&fence_status, + AMDGPU_TIMEOUT_INFINITE, + 0, &expired); + + r = amdgpu_cs_query_reset_state(context_handle, &hang_state, &hangs); + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_EQUAL(hang_state, AMDGPU_CTX_UNKNOWN_RESET); + + r = amdgpu_bo_list_destroy(bo_list); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_dst, va_dst, mc_address_dst, bo_size); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_bo_unmap_and_free(bo_src, va_src, mc_address_src, bo_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_cmd, va_cmd, mc_address_cmd, bo_cmd_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_shader_ps, va_shader_ps, mc_address_shader_ps, bo_shader_ps_size); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_bo_unmap_and_free(bo_shader_vs, va_shader_vs, mc_address_shader_vs, bo_shader_vs_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_free(context_handle); + CU_ASSERT_EQUAL(r, 0); +} + static void amdgpu_gpu_reset_test(void) { int r; diff --git a/tests/amdgpu/deadlock_tests.c b/tests/amdgpu/deadlock_tests.c index 0735a724..d6eb35b1 100644 --- a/tests/amdgpu/deadlock_tests.c +++ b/tests/amdgpu/deadlock_tests.c @@ -119,6 +119,7 @@ static void amdgpu_dispatch_hang_compute(void); static void amdgpu_dispatch_hang_slow_gfx(void); static void amdgpu_dispatch_hang_slow_compute(void); static void amdgpu_draw_hang_gfx(void); +static void amdgpu_draw_hang_slow_gfx(void); CU_BOOL suite_deadlock_tests_enable(void) { @@ -188,6 +189,7 @@ CU_TestInfo deadlock_tests[] = { { "gfx ring bad slow dispatch test (set amdgpu.lockup_timeout=50)", amdgpu_dispatch_hang_slow_gfx }, { "compute ring bad slow dispatch test (set amdgpu.lockup_timeout=50,50)", amdgpu_dispatch_hang_slow_compute }, { "gfx ring bad draw test (set amdgpu.lockup_timeout=50)", amdgpu_draw_hang_gfx }, + { "gfx ring slow bad draw test (set amdgpu.lockup_timeout=50)", amdgpu_draw_hang_slow_gfx }, CU_TEST_INFO_NULL, }; @@ -526,3 +528,19 @@ static void amdgpu_draw_hang_gfx(void) amdgpu_memcpy_draw_test(device_handle, ring_id, 0); } } + +static void amdgpu_draw_hang_slow_gfx(void) +{ + struct drm_amdgpu_info_hw_ip info; + uint32_t ring_id; + int r; + + r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_GFX, 0, &info); + CU_ASSERT_EQUAL(r, 0); + + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { + amdgpu_memcpy_draw_test(device_handle, ring_id, 0); + amdgpu_memcpy_draw_hang_slow_test(device_handle, ring_id); + amdgpu_memcpy_draw_test(device_handle, ring_id, 0); + } +} commit 5e1f6533a0b15587220f661872c86981706b4d42 Author: Flora Cui <flo...@am...> Date: Mon Mar 18 14:14:42 2019 +0800 tests/amdgpu: add gfx ring draw hang test for gfx9 Signed-off-by: Flora Cui <flo...@am...> Reviewed-by: Marek Olšák <mar...@am...> diff --git a/tests/amdgpu/amdgpu_test.c b/tests/amdgpu/amdgpu_test.c index 08387fc7..54bd33dc 100644 --- a/tests/amdgpu/amdgpu_test.c +++ b/tests/amdgpu/amdgpu_test.c @@ -476,6 +476,11 @@ static void amdgpu_disable_suites() "compute ring bad slow dispatch test (set amdgpu.lockup_timeout=50,50)", CU_FALSE)) fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + //if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV) + if (amdgpu_set_test_active(DEADLOCK_TESTS_STR, + "gfx ring bad draw test (set amdgpu.lockup_timeout=50)", CU_FALSE)) + fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + if (amdgpu_set_test_active(BO_TESTS_STR, "Metadata", CU_FALSE)) fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); diff --git a/tests/amdgpu/amdgpu_test.h b/tests/amdgpu/amdgpu_test.h index e0baf549..21c024fd 100644 --- a/tests/amdgpu/amdgpu_test.h +++ b/tests/amdgpu/amdgpu_test.h @@ -238,7 +238,8 @@ extern CU_TestInfo syncobj_timeline_tests[]; void amdgpu_dispatch_hang_helper(amdgpu_device_handle device_handle, uint32_t ip_type); void amdgpu_dispatch_hang_slow_helper(amdgpu_device_handle device_handle, uint32_t ip_type); - +void amdgpu_memcpy_draw_test(amdgpu_device_handle device_handle, uint32_t ring, + int hang); /** * Helper functions */ diff --git a/tests/amdgpu/basic_tests.c b/tests/amdgpu/basic_tests.c index 0ce268fb..44e6cce4 100644 --- a/tests/amdgpu/basic_tests.c +++ b/tests/amdgpu/basic_tests.c @@ -357,7 +357,8 @@ static const uint32_t preamblecache_gfx9[] = { enum ps_type { PS_CONST, - PS_TEX + PS_TEX, + PS_HANG }; static const uint32_t ps_const_shader_gfx9[] = { @@ -2783,6 +2784,12 @@ static int amdgpu_draw_load_ps_shader(uint8_t *ptr, int ps_type) patchinfo_code_size = ps_tex_shader_patchinfo_code_size_gfx9; patchcode_offset = ps_tex_shader_patchinfo_offset_gfx9; break; + case PS_HANG: + shader = memcpy_ps_hang; + shader_size = sizeof(memcpy_ps_hang); + + memcpy(ptr, shader, shader_size); + return 0; default: return -1; break; @@ -3236,7 +3243,7 @@ static void amdgpu_memcpy_draw(amdgpu_device_handle device_handle, amdgpu_bo_handle bo_shader_vs, uint64_t mc_address_shader_ps, uint64_t mc_address_shader_vs, - uint32_t ring) + uint32_t ring, int hang) { amdgpu_context_handle context_handle; amdgpu_bo_handle bo_dst, bo_src, bo_cmd, resources[5]; @@ -3341,14 +3348,20 @@ static void amdgpu_memcpy_draw(amdgpu_device_handle device_handle, r = amdgpu_cs_query_fence_status(&fence_status, AMDGPU_TIMEOUT_INFINITE, 0, &expired); - CU_ASSERT_EQUAL(r, 0); - CU_ASSERT_EQUAL(expired, true); + if (!hang) { + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_EQUAL(expired, true); - /* verify if memcpy test result meets with expected */ - i = 0; - while(i < bo_size) { - CU_ASSERT_EQUAL(ptr_dst[i], ptr_src[i]); - i++; + /* verify if memcpy test result meets with expected */ + i = 0; + while(i < bo_size) { + CU_ASSERT_EQUAL(ptr_dst[i], ptr_src[i]); + i++; + } + } else { + r = amdgpu_cs_query_reset_state(context_handle, &hang_state, &hangs); + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_EQUAL(hang_state, AMDGPU_CTX_UNKNOWN_RESET); } r = amdgpu_bo_list_destroy(bo_list); @@ -3366,7 +3379,8 @@ static void amdgpu_memcpy_draw(amdgpu_device_handle device_handle, CU_ASSERT_EQUAL(r, 0); } -static void amdgpu_memcpy_draw_test(amdgpu_device_handle device_handle, uint32_t ring) +void amdgpu_memcpy_draw_test(amdgpu_device_handle device_handle, uint32_t ring, + int hang) { amdgpu_bo_handle bo_shader_ps, bo_shader_vs; void *ptr_shader_ps; @@ -3374,6 +3388,7 @@ static void amdgpu_memcpy_draw_test(amdgpu_device_handle device_handle, uint32_t uint64_t mc_address_shader_ps, mc_address_shader_vs; amdgpu_va_handle va_shader_ps, va_shader_vs; int bo_shader_size = 4096; + enum ps_type ps_type = hang ? PS_HANG : PS_TEX; int r; r = amdgpu_bo_alloc_and_map(device_handle, bo_shader_size, 4096, @@ -3390,14 +3405,14 @@ static void amdgpu_memcpy_draw_test(amdgpu_device_handle device_handle, uint32_t CU_ASSERT_EQUAL(r, 0); memset(ptr_shader_vs, 0, bo_shader_size); - r = amdgpu_draw_load_ps_shader(ptr_shader_ps, PS_TEX); + r = amdgpu_draw_load_ps_shader(ptr_shader_ps, ps_type); CU_ASSERT_EQUAL(r, 0); r = amdgpu_draw_load_vs_shader(ptr_shader_vs); CU_ASSERT_EQUAL(r, 0); amdgpu_memcpy_draw(device_handle, bo_shader_ps, bo_shader_vs, - mc_address_shader_ps, mc_address_shader_vs, ring); + mc_address_shader_ps, mc_address_shader_vs, ring, hang); r = amdgpu_bo_unmap_and_free(bo_shader_ps, va_shader_ps, mc_address_shader_ps, bo_shader_size); CU_ASSERT_EQUAL(r, 0); @@ -3419,7 +3434,7 @@ static void amdgpu_draw_test(void) for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { amdgpu_memset_draw_test(device_handle, ring_id); - amdgpu_memcpy_draw_test(device_handle, ring_id); + amdgpu_memcpy_draw_test(device_handle, ring_id, 0); } } diff --git a/tests/amdgpu/deadlock_tests.c b/tests/amdgpu/deadlock_tests.c index 949dc298..0735a724 100644 --- a/tests/amdgpu/deadlock_tests.c +++ b/tests/amdgpu/deadlock_tests.c @@ -118,6 +118,7 @@ static void amdgpu_dispatch_hang_gfx(void); static void amdgpu_dispatch_hang_compute(void); static void amdgpu_dispatch_hang_slow_gfx(void); static void amdgpu_dispatch_hang_slow_compute(void); +static void amdgpu_draw_hang_gfx(void); CU_BOOL suite_deadlock_tests_enable(void) { @@ -186,6 +187,7 @@ CU_TestInfo deadlock_tests[] = { { "compute ring bad dispatch test (set amdgpu.lockup_timeout=50,50)", amdgpu_dispatch_hang_compute }, { "gfx ring bad slow dispatch test (set amdgpu.lockup_timeout=50)", amdgpu_dispatch_hang_slow_gfx }, { "compute ring bad slow dispatch test (set amdgpu.lockup_timeout=50,50)", amdgpu_dispatch_hang_slow_compute }, + { "gfx ring bad draw test (set amdgpu.lockup_timeout=50)", amdgpu_draw_hang_gfx }, CU_TEST_INFO_NULL, }; @@ -506,3 +508,21 @@ static void amdgpu_dispatch_hang_slow_compute(void) { amdgpu_dispatch_hang_slow_helper(device_handle, AMDGPU_HW_IP_COMPUTE); } + +static void amdgpu_draw_hang_gfx(void) +{ + int r; + struct drm_amdgpu_info_hw_ip info; + uint32_t ring_id; + + r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_GFX, 0, &info); + CU_ASSERT_EQUAL(r, 0); + if (!info.available_rings) + printf("SKIP ... as there's no graphic ring\n"); + + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { + amdgpu_memcpy_draw_test(device_handle, ring_id, 0); + amdgpu_memcpy_draw_test(device_handle, ring_id, 1); + amdgpu_memcpy_draw_test(device_handle, ring_id, 0); + } +} commit 71b9e68d999be479b560d2930d8325ad627bf4be Author: Flora Cui <flo...@am...> Date: Mon Mar 18 15:32:30 2019 +0800 tests/amdgpu: add bad slow dispatch test add gfx/compute bad slow dispatch test for gfx9 Signed-off-by: Flora Cui <flo...@am...> Reviewed-by: Marek Olšák <mar...@am...> diff --git a/tests/amdgpu/amdgpu_test.c b/tests/amdgpu/amdgpu_test.c index 08642203..08387fc7 100644 --- a/tests/amdgpu/amdgpu_test.c +++ b/tests/amdgpu/amdgpu_test.c @@ -464,6 +464,18 @@ static void amdgpu_disable_suites() "compute ring bad dispatch test (set amdgpu.lockup_timeout=50)", CU_FALSE)) fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + /* This test was ran on GFX9 only */ + //if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV) + if (amdgpu_set_test_active(DEADLOCK_TESTS_STR, + "gfx ring bad slow dispatch test (set amdgpu.lockup_timeout=50)", CU_FALSE)) + fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + + /* This test was ran on GFX9 only */ + //if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV) + if (amdgpu_set_test_active(DEADLOCK_TESTS_STR, + "compute ring bad slow dispatch test (set amdgpu.lockup_timeout=50,50)", CU_FALSE)) + fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + if (amdgpu_set_test_active(BO_TESTS_STR, "Metadata", CU_FALSE)) fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); diff --git a/tests/amdgpu/amdgpu_test.h b/tests/amdgpu/amdgpu_test.h index e1d90253..e0baf549 100644 --- a/tests/amdgpu/amdgpu_test.h +++ b/tests/amdgpu/amdgpu_test.h @@ -237,6 +237,7 @@ CU_BOOL suite_syncobj_timeline_tests_enable(void); extern CU_TestInfo syncobj_timeline_tests[]; void amdgpu_dispatch_hang_helper(amdgpu_device_handle device_handle, uint32_t ip_type); +void amdgpu_dispatch_hang_slow_helper(amdgpu_device_handle device_handle, uint32_t ip_type); /** * Helper functions diff --git a/tests/amdgpu/basic_tests.c b/tests/amdgpu/basic_tests.c index 9dde7af0..0ce268fb 100644 --- a/tests/amdgpu/basic_tests.c +++ b/tests/amdgpu/basic_tests.c @@ -307,7 +307,8 @@ static uint32_t shader_bin[] = { enum cs_type { CS_BUFFERCLEAR, CS_BUFFERCOPY, - CS_HANG + CS_HANG, + CS_HANG_SLOW }; static const uint32_t bufferclear_cs_shader_gfx9[] = { @@ -477,6 +478,37 @@ unsigned int memcpy_ps_hang[] = { 0xF800180F, 0x03020100, 0xBF810000 }; +struct amdgpu_test_shader { + uint32_t *shader; + uint32_t header_length; + uint32_t body_length; + uint32_t foot_length; +}; + +unsigned int memcpy_cs_hang_slow_ai_codes[] = { + 0xd1fd0000, 0x04010c08, 0xe00c2000, 0x80000100, + 0xbf8c0f70, 0xe01c2000, 0x80010100, 0xbf810000 +}; + +struct amdgpu_test_shader memcpy_cs_hang_slow_ai = { + memcpy_cs_hang_slow_ai_codes, + 4, + 3, + 1 +}; + +unsigned int memcpy_cs_hang_slow_rv_codes[] = { + 0x8e00860c, 0x32000000, 0xe00c2000, 0x80010100, + 0xbf8c0f70, 0xe01c2000, 0x80020100, 0xbf810000 +}; + +struct amdgpu_test_shader memcpy_cs_hang_slow_rv = { + memcpy_cs_hang_slow_rv_codes, + 4, + 3, + 1 +}; + int amdgpu_bo_alloc_and_map_raw(amdgpu_device_handle dev, unsigned size, unsigned alignment, unsigned heap, uint64_t alloc_flags, uint64_t mapping_flags, amdgpu_bo_handle *bo, void **cpu, @@ -2074,6 +2106,37 @@ static void amdgpu_sync_dependency_test(void) free(ibs_request.dependencies); } +static int amdgpu_dispatch_load_cs_shader_hang_slow(uint32_t *ptr, int family) +{ + struct amdgpu_test_shader *shader; + int i, loop = 0x10000; + + switch (family) { + case AMDGPU_FAMILY_AI: + shader = &memcpy_cs_hang_slow_ai; + break; + case AMDGPU_FAMILY_RV: + shader = &memcpy_cs_hang_slow_rv; + break; + default: + return -1; + break; + } + + memcpy(ptr, shader->shader, shader->header_length * sizeof(uint32_t)); + + for (i = 0; i < loop; i++) + memcpy(ptr + shader->header_length + shader->body_length * i, + shader->shader + shader->header_length, + shader->body_length * sizeof(uint32_t)); + + memcpy(ptr + shader->header_length + shader->body_length * loop, + shader->shader + shader->header_length + shader->body_length, + shader->foot_length * sizeof(uint32_t)); + + return 0; +} + static int amdgpu_dispatch_load_cs_shader(uint8_t *ptr, int cs_type) { @@ -2526,6 +2589,175 @@ void amdgpu_dispatch_hang_helper(amdgpu_device_handle device_handle, uint32_t ip } } +static void amdgpu_memcpy_dispatch_hang_slow_test(amdgpu_device_handle device_handle, + uint32_t ip_type, uint32_t ring) +{ + amdgpu_context_handle context_handle; + amdgpu_bo_handle bo_src, bo_dst, bo_shader, bo_cmd, resources[4]; + volatile unsigned char *ptr_dst; + void *ptr_shader; + unsigned char *ptr_src; + uint32_t *ptr_cmd; + uint64_t mc_address_src, mc_address_dst, mc_address_shader, mc_address_cmd; + amdgpu_va_handle va_src, va_dst, va_shader, va_cmd; + int i, r; + int bo_dst_size = 0x4000000; + int bo_shader_size = 0x400000; + int bo_cmd_size = 4096; + struct amdgpu_cs_request ibs_request = {0}; + struct amdgpu_cs_ib_info ib_info= {0}; + uint32_t hang_state, hangs, expired; + struct amdgpu_gpu_info gpu_info = {0}; + amdgpu_bo_list_handle bo_list; + struct amdgpu_cs_fence fence_status = {0}; + + r = amdgpu_query_gpu_info(device_handle, &gpu_info); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_create(device_handle, &context_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_cmd_size, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &bo_cmd, (void **)&ptr_cmd, + &mc_address_cmd, &va_cmd); + CU_ASSERT_EQUAL(r, 0); + memset(ptr_cmd, 0, bo_cmd_size); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_shader_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_shader, &ptr_shader, + &mc_address_shader, &va_shader); + CU_ASSERT_EQUAL(r, 0); + memset(ptr_shader, 0, bo_shader_size); + + r = amdgpu_dispatch_load_cs_shader_hang_slow(ptr_shader, gpu_info.family_id); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_dst_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_src, (void **)&ptr_src, + &mc_address_src, &va_src); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, bo_dst_size, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, + &bo_dst, (void **)&ptr_dst, + &mc_address_dst, &va_dst); + CU_ASSERT_EQUAL(r, 0); + + memset(ptr_src, 0x55, bo_dst_size); + + i = 0; + i += amdgpu_dispatch_init(ptr_cmd + i, ip_type); + + /* Issue commands to set cu mask used in current dispatch */ + i += amdgpu_dispatch_write_cumask(ptr_cmd + i); + + /* Writes shader state to HW */ + i += amdgpu_dispatch_write2hw(ptr_cmd + i, mc_address_shader); + + /* Write constant data */ + /* Writes the texture resource constants data to the SGPRs */ + ptr_cmd[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 4); + ptr_cmd[i++] = 0x240; + ptr_cmd[i++] = mc_address_src; + ptr_cmd[i++] = (mc_address_src >> 32) | 0x100000; + ptr_cmd[i++] = 0x400000; + ptr_cmd[i++] = 0x74fac; + + /* Writes the UAV constant data to the SGPRs. */ + ptr_cmd[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 4); + ptr_cmd[i++] = 0x244; + ptr_cmd[i++] = mc_address_dst; + ptr_cmd[i++] = (mc_address_dst >> 32) | 0x100000; + ptr_cmd[i++] = 0x400000; + ptr_cmd[i++] = 0x74fac; + + /* clear mmCOMPUTE_RESOURCE_LIMITS */ + ptr_cmd[i++] = PACKET3_COMPUTE(PKT3_SET_SH_REG, 1); + ptr_cmd[i++] = 0x215; + ptr_cmd[i++] = 0; + + /* dispatch direct command */ + ptr_cmd[i++] = PACKET3_COMPUTE(PACKET3_DISPATCH_DIRECT, 3); + ptr_cmd[i++] = 0x10000; + ptr_cmd[i++] = 1; + ptr_cmd[i++] = 1; + ptr_cmd[i++] = 1; + + while (i & 7) + ptr_cmd[i++] = 0xffff1000; /* type3 nop packet */ + + resources[0] = bo_shader; + resources[1] = bo_src; + resources[2] = bo_dst; + resources[3] = bo_cmd; + r = amdgpu_bo_list_create(device_handle, 4, resources, NULL, &bo_list); + CU_ASSERT_EQUAL(r, 0); + + ib_info.ib_mc_address = mc_address_cmd; + ib_info.size = i; + ibs_request.ip_type = ip_type; + ibs_request.ring = ring; + ibs_request.resources = bo_list; + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.fence_info.handle = NULL; + r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1); + CU_ASSERT_EQUAL(r, 0); + + fence_status.ip_type = ip_type; + fence_status.ip_instance = 0; + fence_status.ring = ring; + fence_status.context = context_handle; + fence_status.fence = ibs_request.seq_no; + + /* wait for IB accomplished */ + r = amdgpu_cs_query_fence_status(&fence_status, + AMDGPU_TIMEOUT_INFINITE, + 0, &expired); + + r = amdgpu_cs_query_reset_state(context_handle, &hang_state, &hangs); + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_EQUAL(hang_state, AMDGPU_CTX_UNKNOWN_RESET); + + r = amdgpu_bo_list_destroy(bo_list); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_src, va_src, mc_address_src, bo_dst_size); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_bo_unmap_and_free(bo_dst, va_dst, mc_address_dst, bo_dst_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_cmd, va_cmd, mc_address_cmd, bo_cmd_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(bo_shader, va_shader, mc_address_shader, bo_shader_size); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_free(context_handle); + CU_ASSERT_EQUAL(r, 0); +} + +void amdgpu_dispatch_hang_slow_helper(amdgpu_device_handle device_handle, uint32_t ip_type) +{ + int r; + struct drm_amdgpu_info_hw_ip info; + uint32_t ring_id; + + r = amdgpu_query_hw_ip_info(device_handle, ip_type, 0, &info); + CU_ASSERT_EQUAL(r, 0); + if (!info.available_rings) + printf("SKIP ... as there's no ring for ip %d\n", ip_type); + + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { + amdgpu_memcpy_dispatch_test(device_handle, ip_type, ring_id, 0); + amdgpu_memcpy_dispatch_hang_slow_test(device_handle, ip_type, ring_id); + amdgpu_memcpy_dispatch_test(device_handle, ip_type, ring_id, 0); + } +} + static int amdgpu_draw_load_ps_shader(uint8_t *ptr, int ps_type) { int i; diff --git a/tests/amdgpu/deadlock_tests.c b/tests/amdgpu/deadlock_tests.c index 58f93b50..949dc298 100644 --- a/tests/amdgpu/deadlock_tests.c +++ b/tests/amdgpu/deadlock_tests.c @@ -116,6 +116,8 @@ static void amdgpu_illegal_mem_access(); static void amdgpu_deadlock_sdma(void); static void amdgpu_dispatch_hang_gfx(void); static void amdgpu_dispatch_hang_compute(void); +static void amdgpu_dispatch_hang_slow_gfx(void); +static void amdgpu_dispatch_hang_slow_compute(void); CU_BOOL suite_deadlock_tests_enable(void) { @@ -182,6 +184,8 @@ CU_TestInfo deadlock_tests[] = { { "illegal mem access test (set amdgpu.vm_fault_stop=2)", amdgpu_illegal_mem_access }, { "gfx ring bad dispatch test (set amdgpu.lockup_timeout=50)", amdgpu_dispatch_hang_gfx }, { "compute ring bad dispatch test (set amdgpu.lockup_timeout=50,50)", amdgpu_dispatch_hang_compute }, + { "gfx ring bad slow dispatch test (set amdgpu.lockup_timeout=50)", amdgpu_dispatch_hang_slow_gfx }, + { "compute ring bad slow dispatch test (set amdgpu.lockup_timeout=50,50)", amdgpu_dispatch_hang_slow_compute }, CU_TEST_INFO_NULL, }; @@ -492,3 +496,13 @@ static void amdgpu_dispatch_hang_compute(void) { amdgpu_dispatch_hang_helper(device_handle, AMDGPU_HW_IP_COMPUTE); } + +static void amdgpu_dispatch_hang_slow_gfx(void) +{ + amdgpu_dispatch_hang_slow_helper(device_handle, AMDGPU_HW_IP_GFX); +} + +static void amdgpu_dispatch_hang_slow_compute(void) +{ + amdgpu_dispatch_hang_slow_helper(device_handle, AMDGPU_HW_IP_COMPUTE); +} commit d72b9189c45befc0f66dd8e719e5d531746c4a65 Author: Flora Cui <flo...@am...> Date: Mon Mar 18 10:58:53 2019 +0800 tests/amdgpu: add dispatch hang test add compute/gfx dispatch hang test for gfx9 Signed-off-by: Flora Cui <flo...@am...> Reviewed-by: Marek Olšák <mar...@am...> diff --git a/tests/amdgpu/amdgpu_test.c b/tests/amdgpu/amdgpu_test.c index 5aadd7e6..08642203 100644 --- a/tests/amdgpu/amdgpu_test.c +++ b/tests/amdgpu/amdgpu_test.c @@ -452,6 +452,18 @@ static void amdgpu_disable_suites() "sdma ring block test (set amdgpu.lockup_timeout=50)", CU_FALSE)) fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + /* This test was ran on GFX9 only */ + //if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV) + if (amdgpu_set_test_active(DEADLOCK_TESTS_STR, + "gfx ring bad dispatch test (set amdgpu.lockup_timeout=50)", CU_FALSE)) + fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + + /* This test was ran on GFX9 only */ + //if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV) + if (amdgpu_set_test_active(DEADLOCK_TESTS_STR, + "compute ring bad dispatch test (set amdgpu.lockup_timeout=50)", CU_FALSE)) + fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + if (amdgpu_set_test_active(BO_TESTS_STR, "Metadata", CU_FALSE)) fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); diff --git a/tests/amdgpu/amdgpu_test.h b/tests/amdgpu/amdgpu_test.h index 36675ea3..e1d90253 100644 --- a/tests/amdgpu/amdgpu_test.h +++ b/tests/amdgpu/amdgpu_test.h @@ -236,6 +236,7 @@ CU_BOOL suite_syncobj_timeline_tests_enable(void); */ extern CU_TestInfo syncobj_timeline_tests[]; +void amdgpu_dispatch_hang_helper(amdgpu_device_handle device_handle, uint32_t ip_type); /** * Helper functions diff --git a/tests/amdgpu/basic_tests.c b/tests/amdgpu/basic_tests.c index b2468212..9dde7af0 100644 --- a/tests/amdgpu/basic_tests.c +++ b/tests/amdgpu/basic_tests.c @@ -306,7 +306,8 @@ static uint32_t shader_bin[] = { enum cs_type { CS_BUFFERCLEAR, - CS_BUFFERCOPY + CS_BUFFERCOPY, + CS_HANG }; static const uint32_t bufferclear_cs_shader_gfx9[] = { @@ -468,6 +469,14 @@ static const uint32_t cached_cmd_gfx9[] = { 0xc0026900, 0x2b0, 0x0, 0x0, 0xc0016900, 0x2f8, 0x0 }; +unsigned int memcpy_ps_hang[] = { + 0xFFFFFFFF, 0xBEFE0A7E, 0xBEFC0304, 0xC0C20100, + 0xC0800300, 0xC8080000, 0xC80C0100, 0xC8090001, + 0xC80D0101, 0xBF8C007F, 0xF0800F00, 0x00010002, + 0xBEFE040C, 0xBF8C0F70, 0xBF800000, 0xBF800000, + 0xF800180F, 0x03020100, 0xBF810000 +}; + int amdgpu_bo_alloc_and_map_raw(amdgpu_device_handle dev, unsigned size, unsigned alignment, unsigned heap, uint64_t alloc_flags, uint64_t mapping_flags, amdgpu_bo_handle *bo, void **cpu, @@ -2080,6 +2089,10 @@ static int amdgpu_dispatch_load_cs_shader(uint8_t *ptr, shader = buffercopy_cs_shader_gfx9; shader_size = sizeof(buffercopy_cs_shader_gfx9); break; + case CS_HANG: + shader = memcpy_ps_hang; + shader_size = sizeof(memcpy_ps_hang); + break; default: return -1; break; @@ -2300,7 +2313,8 @@ static void amdgpu_memset_dispatch_test(amdgpu_device_handle device_handle, static void amdgpu_memcpy_dispatch_test(amdgpu_device_handle device_handle, uint32_t ip_type, - uint32_t ring) + uint32_t ring, + int hang) { amdgpu_context_handle context_handle; amdgpu_bo_handle bo_src, bo_dst, bo_shader, bo_cmd, resources[4]; @@ -2316,7 +2330,8 @@ static void amdgpu_memcpy_dispatch_test(amdgpu_device_handle device_handle, int bo_cmd_size = 4096; struct amdgpu_cs_request ibs_request = {0}; struct amdgpu_cs_ib_info ib_info= {0}; - uint32_t expired; + uint32_t expired, hang_state, hangs; + enum cs_type cs_type; amdgpu_bo_list_handle bo_list; struct amdgpu_cs_fence fence_status = {0}; @@ -2337,7 +2352,8 @@ static void amdgpu_memcpy_dispatch_test(amdgpu_device_handle device_handle, CU_ASSERT_EQUAL(r, 0); memset(ptr_shader, 0, bo_shader_size); - r = amdgpu_dispatch_load_cs_shader(ptr_shader, CS_BUFFERCOPY ); + cs_type = hang ? CS_HANG : CS_BUFFERCOPY; + r = amdgpu_dispatch_load_cs_shader(ptr_shader, cs_type); CU_ASSERT_EQUAL(r, 0); r = amdgpu_bo_alloc_and_map(device_handle, bo_dst_size, 4096, @@ -2423,14 +2439,21 @@ static void amdgpu_memcpy_dispatch_test(amdgpu_device_handle device_handle, r = amdgpu_cs_query_fence_status(&fence_status, AMDGPU_TIMEOUT_INFINITE, 0, &expired); - CU_ASSERT_EQUAL(r, 0); - CU_ASSERT_EQUAL(expired, true); - /* verify if memcpy test result meets with expected */ - i = 0; - while(i < bo_dst_size) { - CU_ASSERT_EQUAL(ptr_dst[i], ptr_src[i]); - i++; + if (!hang) { + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_EQUAL(expired, true); + + /* verify if memcpy test result meets with expected */ + i = 0; + while(i < bo_dst_size) { + CU_ASSERT_EQUAL(ptr_dst[i], ptr_src[i]); + i++; + } + } else { + r = amdgpu_cs_query_reset_state(context_handle, &hang_state, &hangs); + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_EQUAL(hang_state, AMDGPU_CTX_UNKNOWN_RESET); } r = amdgpu_bo_list_destroy(bo_list); @@ -2464,7 +2487,7 @@ static void amdgpu_compute_dispatch_test(void) for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { amdgpu_memset_dispatch_test(device_handle, AMDGPU_HW_IP_COMPUTE, ring_id); - amdgpu_memcpy_dispatch_test(device_handle, AMDGPU_HW_IP_COMPUTE, ring_id); + amdgpu_memcpy_dispatch_test(device_handle, AMDGPU_HW_IP_COMPUTE, ring_id, 0); } } @@ -2481,7 +2504,25 @@ static void amdgpu_gfx_dispatch_test(void) for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { amdgpu_memset_dispatch_test(device_handle, AMDGPU_HW_IP_GFX, ring_id); - amdgpu_memcpy_dispatch_test(device_handle, AMDGPU_HW_IP_GFX, ring_id); + amdgpu_memcpy_dispatch_test(device_handle, AMDGPU_HW_IP_GFX, ring_id, 0); + } +} + +void amdgpu_dispatch_hang_helper(amdgpu_device_handle device_handle, uint32_t ip_type) +{ + int r; + struct drm_amdgpu_info_hw_ip info; + uint32_t ring_id; + + r = amdgpu_query_hw_ip_info(device_handle, ip_type, 0, &info); + CU_ASSERT_EQUAL(r, 0); + if (!info.available_rings) + printf("SKIP ... as there's no ring for ip %d\n", ip_type); + + for (ring_id = 0; (1 << ring_id) & info.available_rings; ring_id++) { + amdgpu_memcpy_dispatch_test(device_handle, ip_type, ring_id, 0); + amdgpu_memcpy_dispatch_test(device_handle, ip_type, ring_id, 1); + amdgpu_memcpy_dispatch_test(device_handle, ip_type, ring_id, 0); } } diff --git a/tests/amdgpu/deadlock_tests.c b/tests/amdgpu/deadlock_tests.c index 91368c15..58f93b50 100644 --- a/tests/amdgpu/deadlock_tests.c +++ b/tests/amdgpu/deadlock_tests.c @@ -114,6 +114,8 @@ static void amdgpu_deadlock_compute(void); static void amdgpu_illegal_reg_access(); static void amdgpu_illegal_mem_access(); static void amdgpu_deadlock_sdma(void); +static void amdgpu_dispatch_hang_gfx(void); +static void amdgpu_dispatch_hang_compute(void); CU_BOOL suite_deadlock_tests_enable(void) { @@ -178,6 +180,8 @@ CU_TestInfo deadlock_tests[] = { { "sdma ring block test (set amdgpu.lockup_timeout=50)", amdgpu_deadlock_sdma }, { "illegal reg access test", amdgpu_illegal_reg_access }, { "illegal mem access test (set amdgpu.vm_fault_stop=2)", amdgpu_illegal_mem_access }, + { "gfx ring bad dispatch test (set amdgpu.lockup_timeout=50)", amdgpu_dispatch_hang_gfx }, + { "compute ring bad dispatch test (set amdgpu.lockup_timeout=50,50)", amdgpu_dispatch_hang_compute }, CU_TEST_INFO_NULL, }; @@ -478,3 +482,13 @@ static void amdgpu_illegal_mem_access() { bad_access_helper(0); } + +static void amdgpu_dispatch_hang_gfx(void) +{ + amdgpu_dispatch_hang_helper(device_handle, AMDGPU_HW_IP_GFX); +} + +static void amdgpu_dispatch_hang_compute(void) +{ + amdgpu_dispatch_hang_helper(device_handle, AMDGPU_HW_IP_COMPUTE); +} commit 67017ea07e8f1e027cac1add9876d6be4e27b4b9 Author: Flora Cui <flo...@am...> Date: Fri Nov 15 16:32:14 2019 +0800 tests/amdgpu: update draw test for gfx9 Signed-off-by: Flora Cui <flo...@am...> Reviewed-by: Marek Olšák <mar...@am...> diff --git a/tests/amdgpu/basic_tests.c b/tests/amdgpu/basic_tests.c index 978f81e8..b2468212 100644 --- a/tests/amdgpu/basic_tests.c +++ b/tests/amdgpu/basic_tests.c @@ -461,7 +461,7 @@ static const uint32_t cached_cmd_gfx9[] = { 0xc0016900, 0x0, 0x0, 0xc0026900, 0x3, 0x2a, 0x0, 0xc0046900, 0xa, 0x0, 0x0, 0x0, 0x200020, 0xc0016900, 0x83, 0xffff, 0xc0026900, 0x8e, 0xf, 0xf, - 0xc0056900, 0x105, 0x0, 0x0, 0x0, 0x0, 0x1a, + 0xc0056900, 0x105, 0x0, 0x0, 0x0, 0x0, 0x12, 0xc0026900, 0x10b, 0x0, 0x0, 0xc0016900, 0x1e0, 0x0, 0xc0036900, 0x200, 0x0, 0x10000, 0xcc0011, 0xc0026900, 0x292, 0x20, 0x60201b8, commit d93856fe82dbefae04692897fb08fcdb1cd53cac Author: changzhu <Cha...@am...> Date: Mon Nov 4 11:48:19 2019 +0800 tests/amdgpu: enable dispatch/draw tests for Renoir It can run dispatch/draw tests on new renoir chips. So it needs to enable dispatch/draw tests for Renoir again. Change-Id: I3a72a4bbfe0fc663ee0e3e58d8e9c304f513e568 Signed-off-by: changzhu <Cha...@am...> Reviewed-by: Flora Cui <flo...@am...> Reviewed-by: Marek Olšák <mar...@am...> Reviewed-by: Huang Rui <ray...@am...> diff --git a/tests/amdgpu/basic_tests.c b/tests/amdgpu/basic_tests.c index 0f4aa5db..978f81e8 100644 --- a/tests/amdgpu/basic_tests.c +++ b/tests/amdgpu/basic_tests.c @@ -2869,7 +2869,7 @@ void amdgpu_memset_draw(amdgpu_device_handle device_handle, resources[1] = bo_shader_ps; resources[2] = bo_shader_vs; resources[3] = bo_cmd; - r = amdgpu_bo_list_create(device_handle, 3, resources, NULL, &bo_list); + r = amdgpu_bo_list_create(device_handle, 4, resources, NULL, &bo_list); CU_ASSERT_EQUAL(r, 0); ib_info.ib_mc_address = mc_address_cmd; |
From: GitLab M. <git...@ke...> - 2021-05-09 17:20:03
|
nouveau/nouveau.c | 30 ++++++++++++++++++++++-------- nouveau/private.h | 17 ++++++++++------- nouveau/pushbuf.c | 9 +++++++-- 3 files changed, 39 insertions(+), 17 deletions(-) New commits: commit cfbea78fdf85c0ea1bfd3e0038738f998f48b770 Author: Karol Herbst <kh...@re...> Date: Wed May 5 14:14:30 2021 +0200 nouveau: add debug option to sync pushbuffer submissions Signed-off-by: Karol Herbst <kh...@re...> Reviewed-by: Ilia Mirkin <im...@al...> diff --git a/nouveau/private.h b/nouveau/private.h index dcc23d16..b81d4b1e 100644 --- a/nouveau/private.h +++ b/nouveau/private.h @@ -13,6 +13,7 @@ /* * 0x00000001 dump all pushbuffers + * 0x00000002 submit pushbuffers synchronously * 0x80000000 if compiled with SIMULATE return -EINVAL for all pb submissions */ drm_private extern uint32_t nouveau_debug; diff --git a/nouveau/pushbuf.c b/nouveau/pushbuf.c index 7f1ed8ca..10ff3f57 100644 --- a/nouveau/pushbuf.c +++ b/nouveau/pushbuf.c @@ -339,6 +339,8 @@ pushbuf_submit(struct nouveau_pushbuf *push, struct nouveau_object *chan) req.suffix0 = nvpb->suffix0; req.suffix1 = nvpb->suffix1; req.vram_available = 0; /* for valgrind */ + if (dbg_on(1)) + req.vram_available |= NOUVEAU_GEM_PUSHBUF_SYNC; req.gart_available = 0; if (dbg_on(0)) commit 91c3eb17009a07b4df33e4544dc4a75e5f672b44 Author: Karol Herbst <kh...@re...> Date: Wed May 5 14:05:52 2021 +0200 novueau: document debug flags Signed-off-by: Karol Herbst <kh...@re...> Reviewed-by: Ilia Mirkin <im...@al...> diff --git a/nouveau/private.h b/nouveau/private.h index 55fe57d8..dcc23d16 100644 --- a/nouveau/private.h +++ b/nouveau/private.h @@ -11,6 +11,10 @@ #include "nouveau.h" +/* + * 0x00000001 dump all pushbuffers + * 0x80000000 if compiled with SIMULATE return -EINVAL for all pb submissions + */ drm_private extern uint32_t nouveau_debug; drm_private extern FILE *nouveau_out; #define dbg_on(lvl) (nouveau_debug & (1 << lvl)) commit 17a51b0b31c6e7f0d862fe30d3a3222d152c2966 Author: Karol Herbst <kh...@re...> Date: Wed May 5 14:01:57 2021 +0200 nouveau: rework debugging so we can also dump into a file Signed-off-by: Karol Herbst <kh...@re...> Reviewed-by: Ilia Mirkin <im...@al...> diff --git a/nouveau/nouveau.c b/nouveau/nouveau.c index 80c62c58..9fa940a9 100644 --- a/nouveau/nouveau.c +++ b/nouveau/nouveau.c @@ -46,15 +46,33 @@ #include "nvif/ioctl.h" #include "nvif/unpack.h" +drm_private FILE *nouveau_out = NULL; drm_private uint32_t nouveau_debug = 0; static void -debug_init(char *args) +debug_init(void) { - if (args) { - int n = strtol(args, NULL, 0); + static bool once = false; + char *debug, *out; + + if (once) + return; + once = true; + + debug = getenv("NOUVEAU_LIBDRM_DEBUG"); + if (debug) { + int n = strtol(debug, NULL, 0); if (n >= 0) nouveau_debug = n; + + } + + nouveau_out = stderr; + out = getenv("NOUVEAU_LIBDRM_OUT"); + if (out) { + FILE *fout = fopen(out, "w"); + if (fout) + nouveau_out = fout; } } @@ -325,7 +343,7 @@ nouveau_drm_new(int fd, struct nouveau_drm **pdrm) struct nouveau_drm *drm; drmVersionPtr ver; - debug_init(getenv("NOUVEAU_LIBDRM_DEBUG")); + debug_init(); if (!(drm = calloc(1, sizeof(*drm)))) return -ENOMEM; diff --git a/nouveau/private.h b/nouveau/private.h index 13cec3cd..55fe57d8 100644 --- a/nouveau/private.h +++ b/nouveau/private.h @@ -1,6 +1,8 @@ #ifndef __NOUVEAU_LIBDRM_PRIVATE_H__ #define __NOUVEAU_LIBDRM_PRIVATE_H__ +#include <stdio.h> + #include <libdrm_macros.h> #include <xf86drm.h> #include <xf86atomic.h> @@ -10,12 +12,13 @@ #include "nouveau.h" drm_private extern uint32_t nouveau_debug; +drm_private extern FILE *nouveau_out; #define dbg_on(lvl) (nouveau_debug & (1 << lvl)) #define dbg(lvl, fmt, args...) do { \ if (dbg_on((lvl))) \ - fprintf(stderr, "nouveau: "fmt, ##args); \ + fprintf(nouveau_out, "nouveau: "fmt, ##args); \ } while(0) -#define err(fmt, args...) fprintf(stderr, "nouveau: "fmt, ##args) +#define err(fmt, args...) fprintf(nouveau_out, "nouveau: "fmt, ##args) struct nouveau_client_kref { struct drm_nouveau_gem_pushbuf_bo *kref; commit c0ae9cfa001788bc33d69bd3e65a2d4c417e2a5f Author: Karol Herbst <kh...@re...> Date: Wed May 5 14:01:29 2021 +0200 nouveau: make debug features accessible in normal builds Signed-off-by: Karol Herbst <kh...@re...> Reviewed-by: Ilia Mirkin <im...@al...> diff --git a/nouveau/nouveau.c b/nouveau/nouveau.c index f18d1426..80c62c58 100644 --- a/nouveau/nouveau.c +++ b/nouveau/nouveau.c @@ -46,7 +46,6 @@ #include "nvif/ioctl.h" #include "nvif/unpack.h" -#ifdef DEBUG drm_private uint32_t nouveau_debug = 0; static void @@ -58,7 +57,6 @@ debug_init(char *args) nouveau_debug = n; } } -#endif static int nouveau_object_ioctl(struct nouveau_object *obj, void *data, uint32_t size) @@ -327,9 +325,7 @@ nouveau_drm_new(int fd, struct nouveau_drm **pdrm) struct nouveau_drm *drm; drmVersionPtr ver; -#ifdef DEBUG debug_init(getenv("NOUVEAU_LIBDRM_DEBUG")); -#endif if (!(drm = calloc(1, sizeof(*drm)))) return -ENOMEM; diff --git a/nouveau/private.h b/nouveau/private.h index 034a958e..13cec3cd 100644 --- a/nouveau/private.h +++ b/nouveau/private.h @@ -9,17 +9,12 @@ #include "nouveau.h" -#ifdef DEBUG drm_private extern uint32_t nouveau_debug; #define dbg_on(lvl) (nouveau_debug & (1 << lvl)) #define dbg(lvl, fmt, args...) do { \ if (dbg_on((lvl))) \ fprintf(stderr, "nouveau: "fmt, ##args); \ } while(0) -#else -#define dbg_on(lvl) (0) -#define dbg(lvl, fmt, args...) -#endif #define err(fmt, args...) fprintf(stderr, "nouveau: "fmt, ##args) struct nouveau_client_kref { commit 2f04bd2d891dde617a4c7829188333cbdcdf0038 Author: Karol Herbst <kh...@re...> Date: Sun May 3 16:21:09 2020 +0200 nouveau: mask push buffer length pushbuf_dump nvc0 sets the NVC0_IB_ENTRY_1_NO_PREFETCH bit on some pushbuffers Signed-off-by: Karol Herbst <kh...@re...> Reviewed-by: Ilia Mirkin <im...@al...> diff --git a/nouveau/pushbuf.c b/nouveau/pushbuf.c index 363ff0fc..7f1ed8ca 100644 --- a/nouveau/pushbuf.c +++ b/nouveau/pushbuf.c @@ -292,7 +292,7 @@ pushbuf_dump(struct nouveau_pushbuf_krec *krec, int krec_id, int chid) kref = krec->buffer + kpsh->bo_index; bo = (void *)(unsigned long)kref->user_priv; bgn = (uint32_t *)((char *)bo->map + kpsh->offset); - end = bgn + (kpsh->length /4); + end = bgn + ((kpsh->length & 0x7fffff) /4); err("ch%d: psh %s%08x %010llx %010llx\n", chid, bo->map ? "" : "(unmapped) ", kpsh->bo_index, commit 52fd2a25426fac43422589ada027ab208de20e32 Author: Karol Herbst <kh...@re...> Date: Sun May 3 16:19:53 2020 +0200 nouveau: fix crash in pushbuf_dump with an unmapped bo Signed-off-by: Karol Herbst <kh...@re...> Reviewed-by: Ilia Mirkin <im...@al...> diff --git a/nouveau/pushbuf.c b/nouveau/pushbuf.c index e5f73f0d..363ff0fc 100644 --- a/nouveau/pushbuf.c +++ b/nouveau/pushbuf.c @@ -294,9 +294,12 @@ pushbuf_dump(struct nouveau_pushbuf_krec *krec, int krec_id, int chid) bgn = (uint32_t *)((char *)bo->map + kpsh->offset); end = bgn + (kpsh->length /4); - err("ch%d: psh %08x %010llx %010llx\n", chid, kpsh->bo_index, + err("ch%d: psh %s%08x %010llx %010llx\n", chid, + bo->map ? "" : "(unmapped) ", kpsh->bo_index, (unsigned long long)kpsh->offset, (unsigned long long)(kpsh->offset + kpsh->length)); + if (!bo->map) + continue; while (bgn < end) err("\t0x%08x\n", *bgn++); } |
From: GitLab M. <git...@ke...> - 2021-06-09 20:28:26
|
tests/amdgpu/amdgpu_test.c | 107 +++++++++ tests/amdgpu/amdgpu_test.h | 27 ++ tests/amdgpu/basic_tests.c | 5 tests/amdgpu/hotunplug_tests.c | 445 +++++++++++++++++++++++++++++++++++++++++ tests/amdgpu/meson.build | 1 5 files changed, 579 insertions(+), 6 deletions(-) New commits: commit d615430c6843c19b0e7bc3ad6fb3f4b1074e2d4c Author: Andrey Grodzovsky <and...@am...> Date: Fri Jun 4 16:08:41 2021 -0400 tests/amdgpu/hotunplug: Add hotunplug with exported fence Disconnect device while fence is exported. Also disable this test for sytem with single GPU. Signed-off-by: Andrey Grodzovsky <and...@am...> Reviewed-by: Alex Deucher ale...@am... diff --git a/tests/amdgpu/amdgpu_test.c b/tests/amdgpu/amdgpu_test.c index 6e0d3699..88d42768 100644 --- a/tests/amdgpu/amdgpu_test.c +++ b/tests/amdgpu/amdgpu_test.c @@ -449,7 +449,8 @@ static void amdgpu_disable_suites() { amdgpu_device_handle device_handle; uint32_t major_version, minor_version, family_id; - int i; + drmDevicePtr devices[MAX_CARDS_SUPPORTED]; + int i, drm_count; int size = sizeof(suites_active_stat) / sizeof(suites_active_stat[0]); if (amdgpu_device_initialize(drm_amdgpu[0], &major_version, @@ -461,6 +462,8 @@ static void amdgpu_disable_suites() if (amdgpu_device_deinitialize(device_handle)) return; + drm_count = drmGetDevices2(0, devices, MAX_CARDS_SUPPORTED); + /* Set active status for suites based on their policies */ for (i = 0; i < size; ++i) if (amdgpu_set_suite_active(suites_active_stat[i].pName, @@ -540,6 +543,11 @@ static void amdgpu_disable_suites() //if (family_id < AMDGPU_FAMILY_AI || family_id > AMDGPU_FAMILY_RV) if (amdgpu_set_test_active(BASIC_TESTS_STR, "GPU reset Test", CU_FALSE)) fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + + /* You need at least 2 devices for this */ + if (drm_count < 2) + if (amdgpu_set_test_active(HOTUNPLUG_TESTS_STR, "Unplug with exported fence", CU_FALSE)) + fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); } int test_device_index; diff --git a/tests/amdgpu/hotunplug_tests.c b/tests/amdgpu/hotunplug_tests.c index 9a8fe79a..23ea1407 100644 --- a/tests/amdgpu/hotunplug_tests.c +++ b/tests/amdgpu/hotunplug_tests.c @@ -141,7 +141,6 @@ static int amdgpu_hotunplug_setup_test() strcat(sysfs_remove, "/remove"); return 0; - } static int amdgpu_hotunplug_teardown_test() @@ -347,9 +346,100 @@ static void amdgpu_hotunplug_with_exported_bo(void) CU_ASSERT_EQUAL(r > 0, 1); } +static void amdgpu_hotunplug_with_exported_fence(void) +{ + amdgpu_bo_handle ib_result_handle; + void *ib_result_cpu; + uint64_t ib_result_mc_address; + uint32_t *ptr, sync_obj_handle, sync_obj_handle2; + int i, r; + amdgpu_bo_list_handle bo_list; + amdgpu_va_handle va_handle; + uint32_t major2, minor2; + amdgpu_device_handle device2; + amdgpu_context_handle context; + struct amdgpu_cs_request ibs_request; + struct amdgpu_cs_ib_info ib_info; + struct amdgpu_cs_fence fence_status = {0}; + int shared_fd; + + r = amdgpu_hotunplug_setup_test(); + CU_ASSERT_EQUAL(r , 0); + + r = amdgpu_device_initialize(drm_amdgpu[1], &major2, &minor2, &device2); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_create(device_handle, &context); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &ib_result_handle, &ib_result_cpu, + &ib_result_mc_address, &va_handle); + CU_ASSERT_EQUAL(r, 0); + + ptr = ib_result_cpu; + for (i = 0; i < 16; ++i) + ptr[i] = GFX_COMPUTE_NOP; + + r = amdgpu_bo_list_create(device_handle, 1, &ib_result_handle, NULL, &bo_list); + CU_ASSERT_EQUAL(r, 0); + + memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info)); + ib_info.ib_mc_address = ib_result_mc_address; + ib_info.size = 16; + + memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request)); + ibs_request.ip_type = AMDGPU_HW_IP_GFX; + ibs_request.ring = 0; + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.resources = bo_list; + + CU_ASSERT_EQUAL(amdgpu_cs_submit(context, 0, &ibs_request, 1), 0); + + fence_status.context = context; + fence_status.ip_type = AMDGPU_HW_IP_GFX; + fence_status.ip_instance = 0; + fence_status.fence = ibs_request.seq_no; + + CU_ASSERT_EQUAL(amdgpu_cs_fence_to_handle(device_handle, &fence_status, + AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ, + &sync_obj_handle), + 0); + + CU_ASSERT_EQUAL(amdgpu_cs_export_syncobj(device_handle, sync_obj_handle, &shared_fd), 0); + + CU_ASSERT_EQUAL(amdgpu_cs_import_syncobj(device2, shared_fd, &sync_obj_handle2), 0); + + CU_ASSERT_EQUAL(amdgpu_cs_destroy_syncobj(device_handle, sync_obj_handle), 0); + + CU_ASSERT_EQUAL(amdgpu_bo_list_destroy(bo_list), 0); + CU_ASSERT_EQUAL(amdgpu_bo_unmap_and_free(ib_result_handle, va_handle, + ib_result_mc_address, 4096), 0); + CU_ASSERT_EQUAL(amdgpu_cs_ctx_free(context), 0); + + r = amdgpu_hotunplug_remove(); + CU_ASSERT_EQUAL(r > 0, 1); + + CU_ASSERT_EQUAL(amdgpu_cs_syncobj_wait(device2, &sync_obj_handle2, 1, 100000000, 0, NULL), 0); + + CU_ASSERT_EQUAL(amdgpu_cs_destroy_syncobj(device2, sync_obj_handle2), 0); + + amdgpu_device_deinitialize(device2); + + r = amdgpu_hotunplug_teardown_test(); + CU_ASSERT_EQUAL(r , 0); + + r = amdgpu_hotunplug_rescan(); + CU_ASSERT_EQUAL(r > 0, 1); +} + + CU_TestInfo hotunplug_tests[] = { { "Unplug card and rescan the bus to plug it back", amdgpu_hotunplug_simple }, { "Same as first test but with command submission", amdgpu_hotunplug_with_cs }, { "Unplug with exported bo", amdgpu_hotunplug_with_exported_bo }, + { "Unplug with exported fence", amdgpu_hotunplug_with_exported_fence }, CU_TEST_INFO_NULL, }; commit 93a4708ac08c1a5eb28bd6b714b6bd19a11acf0c Author: Andrey Grodzovsky <and...@am...> Date: Tue Jun 1 14:30:08 2021 -0400 tests/amdgpu/hotunplug: Add hotunplug with exported bo test Disconnect device while BO is exported. Signed-off-by: Andrey Grodzovsky <and...@am...> Reviewed-by: Alex Deucher ale...@am... diff --git a/tests/amdgpu/hotunplug_tests.c b/tests/amdgpu/hotunplug_tests.c index 520e1fcb..9a8fe79a 100644 --- a/tests/amdgpu/hotunplug_tests.c +++ b/tests/amdgpu/hotunplug_tests.c @@ -304,10 +304,52 @@ static void amdgpu_hotunplug_with_cs(void) amdgpu_hotunplug_test(true); } +static void amdgpu_hotunplug_with_exported_bo(void) +{ + int r; + uint32_t dma_buf_fd; + unsigned int *ptr; + amdgpu_bo_handle bo_handle; + + struct amdgpu_bo_alloc_request request = { + .alloc_size = 4096, + .phys_alignment = 4096, + .preferred_heap = AMDGPU_GEM_DOMAIN_GTT, + .flags = 0, + }; + + r = amdgpu_hotunplug_setup_test(); + CU_ASSERT_EQUAL(r , 0); + + amdgpu_bo_alloc(device_handle, &request, &bo_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_export(bo_handle, amdgpu_bo_handle_type_dma_buf_fd, &dma_buf_fd); + CU_ASSERT_EQUAL(r, 0); + + ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf_fd, 0); + CU_ASSERT_NOT_EQUAL(ptr, MAP_FAILED); + + r = amdgpu_hotunplug_remove(); + CU_ASSERT_EQUAL(r > 0, 1); + + amdgpu_bo_free(bo_handle); + + r = amdgpu_hotunplug_teardown_test(); + CU_ASSERT_EQUAL(r , 0); + + *ptr = 0xdeafbeef; + + munmap(ptr, 4096); + close (dma_buf_fd); + + r = amdgpu_hotunplug_rescan(); + CU_ASSERT_EQUAL(r > 0, 1); +} + CU_TestInfo hotunplug_tests[] = { { "Unplug card and rescan the bus to plug it back", amdgpu_hotunplug_simple }, { "Same as first test but with command submission", amdgpu_hotunplug_with_cs }, + { "Unplug with exported bo", amdgpu_hotunplug_with_exported_bo }, CU_TEST_INFO_NULL, }; - - commit b5f611cc370bb939b132df68f164c832690339c6 Author: Andrey Grodzovsky <and...@am...> Date: Mon May 31 14:13:06 2021 -0400 tests/amdgpu/hotunplug: Add unplug with cs test. Same as simple test but while doing cs Signed-off-by: Andrey Grodzovsky <and...@am...> Reviewed-by: Alex Deucher ale...@am... diff --git a/tests/amdgpu/hotunplug_tests.c b/tests/amdgpu/hotunplug_tests.c index 99854993..520e1fcb 100644 --- a/tests/amdgpu/hotunplug_tests.c +++ b/tests/amdgpu/hotunplug_tests.c @@ -38,11 +38,13 @@ #include "xf86drm.h" #include <pthread.h> +#define GFX_COMPUTE_NOP 0xffff1000 static amdgpu_device_handle device_handle; static uint32_t major_version; static uint32_t minor_version; static char *sysfs_remove = NULL; +static bool do_cs; CU_BOOL suite_hotunplug_tests_enable(void) { @@ -110,7 +112,7 @@ static int amdgpu_hotunplug_setup_test() int r; char *tmp_str; - if (amdgpu_open_device_on_test_index(open_render_node) <= 0) { + if (amdgpu_open_device_on_test_index(open_render_node) < 0) { printf("\n\n Failed to reopen device file!\n"); return CUE_SINIT_FAILED; @@ -165,17 +167,126 @@ static inline int amdgpu_hotunplug_rescan() return amdgpu_hotunplug_trigger("/sys/bus/pci/rescan"); } +static int amdgpu_cs_sync(amdgpu_context_handle context, + unsigned int ip_type, + int ring, + unsigned int seqno) +{ + struct amdgpu_cs_fence fence = { + .context = context, + .ip_type = ip_type, + .ring = ring, + .fence = seqno, + }; + uint32_t expired; + + return amdgpu_cs_query_fence_status(&fence, + AMDGPU_TIMEOUT_INFINITE, + 0, &expired); +} -static void amdgpu_hotunplug_simple(void) +static void *amdgpu_nop_cs() +{ + amdgpu_bo_handle ib_result_handle; + void *ib_result_cpu; + uint64_t ib_result_mc_address; + uint32_t *ptr; + int i, r; + amdgpu_bo_list_handle bo_list; + amdgpu_va_handle va_handle; + amdgpu_context_handle context; + struct amdgpu_cs_request ibs_request; + struct amdgpu_cs_ib_info ib_info; + + r = amdgpu_cs_ctx_create(device_handle, &context); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &ib_result_handle, &ib_result_cpu, + &ib_result_mc_address, &va_handle); + CU_ASSERT_EQUAL(r, 0); + + ptr = ib_result_cpu; + for (i = 0; i < 16; ++i) + ptr[i] = GFX_COMPUTE_NOP; + + r = amdgpu_bo_list_create(device_handle, 1, &ib_result_handle, NULL, &bo_list); + CU_ASSERT_EQUAL(r, 0); + + memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info)); + ib_info.ib_mc_address = ib_result_mc_address; + ib_info.size = 16; + + memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request)); + ibs_request.ip_type = AMDGPU_HW_IP_GFX; + ibs_request.ring = 0; + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.resources = bo_list; + + while (do_cs) + amdgpu_cs_submit(context, 0, &ibs_request, 1); + + amdgpu_cs_sync(context, AMDGPU_HW_IP_GFX, 0, ibs_request.seq_no); + amdgpu_bo_list_destroy(bo_list); + amdgpu_bo_unmap_and_free(ib_result_handle, va_handle, + ib_result_mc_address, 4096); + + amdgpu_cs_ctx_free(context); + + return (void *)0; +} + +static pthread_t* amdgpu_create_cs_thread() +{ + int r; + pthread_t *thread = malloc(sizeof(*thread)); + if (!thread) + return NULL; + + do_cs = true; + + r = pthread_create(thread, NULL, amdgpu_nop_cs, NULL); + CU_ASSERT_EQUAL(r, 0); + + /* Give thread enough time to start*/ + usleep(100000); + return thread; +} + +static void amdgpu_destroy_cs_thread(pthread_t *thread) +{ + void *status; + + do_cs = false; + + pthread_join(*thread, &status); + CU_ASSERT_EQUAL(status, 0); + + free(thread); +} + + +static void amdgpu_hotunplug_test(bool with_cs) { int r; + pthread_t *thread = NULL; r = amdgpu_hotunplug_setup_test(); CU_ASSERT_EQUAL(r , 0); + if (with_cs) { + thread = amdgpu_create_cs_thread(); + CU_ASSERT_NOT_EQUAL(thread, NULL); + } + r = amdgpu_hotunplug_remove(); CU_ASSERT_EQUAL(r > 0, 1); + if (with_cs) + amdgpu_destroy_cs_thread(thread); + r = amdgpu_hotunplug_teardown_test(); CU_ASSERT_EQUAL(r , 0); @@ -183,8 +294,19 @@ static void amdgpu_hotunplug_simple(void) CU_ASSERT_EQUAL(r > 0, 1); } +static void amdgpu_hotunplug_simple(void) +{ + amdgpu_hotunplug_test(false); +} + +static void amdgpu_hotunplug_with_cs(void) +{ + amdgpu_hotunplug_test(true); +} + CU_TestInfo hotunplug_tests[] = { { "Unplug card and rescan the bus to plug it back", amdgpu_hotunplug_simple }, + { "Same as first test but with command submission", amdgpu_hotunplug_with_cs }, CU_TEST_INFO_NULL, }; commit d4b780a73554a6c431110cbdf8644a33cd2443ac Author: Andrey Grodzovsky <and...@am...> Date: Wed May 26 15:15:33 2021 -0400 test/amdgpu/hotunplug: Add test suite for GPU unplug Add plug/unplug device and open/close device file infrastructure. Add basic test - unplug device while device file still open. Close device file afterwards and replug the device. Signed-off-by: Andrey Grodzovsky <and...@am...> Reviewed-by: Alex Deucher ale...@am... diff --git a/tests/amdgpu/amdgpu_test.c b/tests/amdgpu/amdgpu_test.c index 7c35d9a0..6e0d3699 100644 --- a/tests/amdgpu/amdgpu_test.c +++ b/tests/amdgpu/amdgpu_test.c @@ -66,6 +66,7 @@ #define RAS_TESTS_STR "RAS Tests" #define SYNCOBJ_TIMELINE_TESTS_STR "SYNCOBJ TIMELINE Tests" #define SECURITY_TESTS_STR "Security Tests" +#define HOTUNPLUG_TESTS_STR "Hotunplug Tests" /** * Open handles for amdgpu devices @@ -144,6 +145,12 @@ static CU_SuiteInfo suites[] = { .pCleanupFunc = suite_security_tests_clean, .pTests = security_tests, }, + { + .pName = HOTUNPLUG_TESTS_STR, + .pInitFunc = suite_hotunplug_tests_init, + .pCleanupFunc = suite_hotunplug_tests_clean, + .pTests = hotunplug_tests, + }, CU_SUITE_INFO_NULL, }; @@ -205,6 +212,10 @@ static Suites_Active_Status suites_active_stat[] = { .pName = SECURITY_TESTS_STR, .pActive = suite_security_tests_enable, }, + { + .pName = HOTUNPLUG_TESTS_STR, + .pActive = suite_hotunplug_tests_enable, + }, }; diff --git a/tests/amdgpu/amdgpu_test.h b/tests/amdgpu/amdgpu_test.h index 9e4515c4..cc12756d 100644 --- a/tests/amdgpu/amdgpu_test.h +++ b/tests/amdgpu/amdgpu_test.h @@ -273,6 +273,29 @@ amdgpu_command_submission_write_linear_helper_with_secure(amdgpu_device_handle unsigned ip_type, bool secure); + + +/** + * Initialize hotunplug test suite + */ +int suite_hotunplug_tests_init(); + +/** + * Deinitialize hotunplug test suite + */ +int suite_hotunplug_tests_clean(); + +/** + * Decide if the suite is enabled by default or not. + */ +CU_BOOL suite_hotunplug_tests_enable(void); + +/** + * Tests in uvd enc test suite + */ +extern CU_TestInfo hotunplug_tests[]; + + /** * Helper functions */ diff --git a/tests/amdgpu/hotunplug_tests.c b/tests/amdgpu/hotunplug_tests.c new file mode 100644 index 00000000..99854993 --- /dev/null +++ b/tests/amdgpu/hotunplug_tests.c @@ -0,0 +1,191 @@ +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * +*/ + +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#if HAVE_ALLOCA_H +# include <alloca.h> +#endif + +#include "CUnit/Basic.h" + +#include "amdgpu_test.h" +#include "amdgpu_drm.h" +#include "amdgpu_internal.h" +#include "xf86drm.h" +#include <pthread.h> + + +static amdgpu_device_handle device_handle; +static uint32_t major_version; +static uint32_t minor_version; +static char *sysfs_remove = NULL; + +CU_BOOL suite_hotunplug_tests_enable(void) +{ + CU_BOOL enable = CU_TRUE; + drmDevicePtr device; + + if (drmGetDevice2(drm_amdgpu[0], DRM_DEVICE_GET_PCI_REVISION, &device)) { + printf("\n\nGPU Failed to get DRM device PCI info!\n"); + return CU_FALSE; + } + + if (device->bustype != DRM_BUS_PCI) { + printf("\n\nGPU device is not on PCI bus!\n"); + amdgpu_device_deinitialize(device_handle); + return CU_FALSE; + } + + /* Disable until the hot-unplug support in kernel gets into drm-next */ + if (major_version < 0xff) + enable = false; + + if (amdgpu_device_initialize(drm_amdgpu[0], &major_version, + &minor_version, &device_handle)) + return CU_FALSE; + + /* TODO Once DRM version for unplug feature ready compare here agains it*/ + + if (amdgpu_device_deinitialize(device_handle)) + return CU_FALSE; + + return enable; +} + +int suite_hotunplug_tests_init(void) +{ + /* We need to open/close device at each test manually */ + amdgpu_close_devices(); + + return CUE_SUCCESS; +} + +int suite_hotunplug_tests_clean(void) +{ + + + return CUE_SUCCESS; +} + +static int amdgpu_hotunplug_trigger(const char *pathname) +{ + int fd, len; + + fd = open(pathname, O_WRONLY); + if (fd < 0) + return -errno; + + len = write(fd, "1", 1); + close(fd); + + return len; +} + +static int amdgpu_hotunplug_setup_test() +{ + int r; + char *tmp_str; + + if (amdgpu_open_device_on_test_index(open_render_node) <= 0) { + printf("\n\n Failed to reopen device file!\n"); + return CUE_SINIT_FAILED; + + + + } + + r = amdgpu_device_initialize(drm_amdgpu[0], &major_version, + &minor_version, &device_handle); + + if (r) { + if ((r == -EACCES) && (errno == EACCES)) + printf("\n\nError:%s. " + "Hint:Try to run this test program as root.", + strerror(errno)); + return CUE_SINIT_FAILED; + } + + tmp_str = amdgpu_get_device_from_fd(drm_amdgpu[0]); + if (!tmp_str){ + printf("\n\n Device path not found!\n"); + return CUE_SINIT_FAILED; + } + + sysfs_remove = realloc(tmp_str, strlen(tmp_str) * 2); + strcat(sysfs_remove, "/remove"); + + return 0; + +} + +static int amdgpu_hotunplug_teardown_test() +{ + if (amdgpu_device_deinitialize(device_handle)) + return CUE_SCLEAN_FAILED; + + amdgpu_close_devices(); + + if (sysfs_remove) + free(sysfs_remove); + + return 0; +} + +static inline int amdgpu_hotunplug_remove() +{ + return amdgpu_hotunplug_trigger(sysfs_remove); +} + +static inline int amdgpu_hotunplug_rescan() +{ + return amdgpu_hotunplug_trigger("/sys/bus/pci/rescan"); +} + + +static void amdgpu_hotunplug_simple(void) +{ + int r; + + r = amdgpu_hotunplug_setup_test(); + CU_ASSERT_EQUAL(r , 0); + + r = amdgpu_hotunplug_remove(); + CU_ASSERT_EQUAL(r > 0, 1); + + r = amdgpu_hotunplug_teardown_test(); + CU_ASSERT_EQUAL(r , 0); + + r = amdgpu_hotunplug_rescan(); + CU_ASSERT_EQUAL(r > 0, 1); +} + +CU_TestInfo hotunplug_tests[] = { + { "Unplug card and rescan the bus to plug it back", amdgpu_hotunplug_simple }, + CU_TEST_INFO_NULL, +}; + + diff --git a/tests/amdgpu/meson.build b/tests/amdgpu/meson.build index eb16a50c..e6e30812 100644 --- a/tests/amdgpu/meson.build +++ b/tests/amdgpu/meson.build @@ -25,6 +25,7 @@ if dep_cunit.found() 'amdgpu_test.c', 'basic_tests.c', 'bo_tests.c', 'cs_tests.c', 'vce_tests.c', 'uvd_enc_tests.c', 'vcn_tests.c', 'deadlock_tests.c', 'vm_tests.c', 'ras_tests.c', 'syncobj_tests.c', 'security_tests.c', + 'hotunplug_tests.c' ), dependencies : [dep_cunit, dep_threads, dep_atomic_ops], include_directories : [inc_root, inc_drm, include_directories('../../amdgpu')], commit d330f68c11833230908b21f48c13da1ab1612fd3 Author: Andrey Grodzovsky <and...@am...> Date: Mon May 31 11:11:58 2021 -0400 test/amdgpu: Add helper functions for hot unplug Expose close device and add open device wich preserves test index. Signed-off-by: Andrey Grodzovsky <and...@am...> Reviewed-by: Alex Deucher ale...@am... diff --git a/tests/amdgpu/amdgpu_test.c b/tests/amdgpu/amdgpu_test.c index 77bbfbcc..7c35d9a0 100644 --- a/tests/amdgpu/amdgpu_test.c +++ b/tests/amdgpu/amdgpu_test.c @@ -37,6 +37,13 @@ #include <sys/time.h> #include <stdarg.h> #include <stdint.h> +#include <linux/limits.h> +#ifdef MAJOR_IN_MKDEV +#include <sys/mkdev.h> +#endif +#ifdef MAJOR_IN_SYSMACROS +#include <sys/sysmacros.h> +#endif #include "drm.h" #include "xf86drmMode.h" @@ -339,12 +346,13 @@ static int amdgpu_open_devices(int open_render_node) /* Close AMD devices. */ -static void amdgpu_close_devices() +void amdgpu_close_devices() { int i; for (i = 0; i < MAX_CARDS_SUPPORTED; i++) - if (drm_amdgpu[i] >=0) + if (drm_amdgpu[i] >=0) { close(drm_amdgpu[i]); + } } /* Print AMD devices information */ @@ -523,6 +531,79 @@ static void amdgpu_disable_suites() fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); } +int test_device_index; + +int amdgpu_open_device_on_test_index(int render_node) +{ + int i; + + if (amdgpu_open_devices(open_render_node) <= 0) { + perror("Cannot open AMDGPU device"); + return -1; + } + + if (test_device_index >= 0) { + /* Most tests run on device of drm_amdgpu[0]. + * Swap the chosen device to drm_amdgpu[0]. + */ + i = drm_amdgpu[0]; + drm_amdgpu[0] = drm_amdgpu[test_device_index]; + drm_amdgpu[test_device_index] = i; + } + + return 0; + + +} + + +static bool amdgpu_node_is_drm(int maj, int min) +{ +#ifdef __linux__ + char path[64]; + struct stat sbuf; + + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device/drm", + maj, min); + return stat(path, &sbuf) == 0; +#elif defined(__FreeBSD__) + char name[SPECNAMELEN]; + + if (!devname_r(makedev(maj, min), S_IFCHR, name, sizeof(name))) + return 0; + /* Handle drm/ and dri/ as both are present in different FreeBSD version + * FreeBSD on amd64/i386/powerpc external kernel modules create node in + * in /dev/drm/ and links in /dev/dri while a WIP in kernel driver creates + * only device nodes in /dev/dri/ */ + return (!strncmp(name, "drm/", 4) || !strncmp(name, "dri/", 4)); +#else + return maj == DRM_MAJOR; +#endif +} + +char *amdgpu_get_device_from_fd(int fd) +{ +#ifdef __linux__ + struct stat sbuf; + char path[PATH_MAX + 1]; + unsigned int maj, min; + + if (fstat(fd, &sbuf)) + return NULL; + + maj = major(sbuf.st_rdev); + min = minor(sbuf.st_rdev); + + if (!amdgpu_node_is_drm(maj, min) || !S_ISCHR(sbuf.st_mode)) + return NULL; + + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); + return strdup(path); +#else + return NULL; +#endif +} + /* The main() function for setting up and running the tests. * Returns a CUE_SUCCESS on successful running, another * CUnit error code on failure. @@ -538,7 +619,6 @@ int main(int argc, char **argv) int display_devices = 0;/* By default not to display devices' info */ CU_pSuite pSuite = NULL; CU_pTest pTest = NULL; - int test_device_index; int display_list = 0; int force_run = 0; diff --git a/tests/amdgpu/amdgpu_test.h b/tests/amdgpu/amdgpu_test.h index 4970d0dd..9e4515c4 100644 --- a/tests/amdgpu/amdgpu_test.h +++ b/tests/amdgpu/amdgpu_test.h @@ -476,4 +476,8 @@ void amdgpu_test_exec_cs_helper_raw(amdgpu_device_handle device_handle, struct amdgpu_cs_request *ibs_request, bool secure); +void amdgpu_close_devices(); +int amdgpu_open_device_on_test_index(int render_node); +char *amdgpu_get_device_from_fd(int fd); + #endif /* #ifdef _AMDGPU_TEST_H_ */ commit ae2e2bd68a1583c25112507b0885a92a82ebce13 Author: Andrey Grodzovsky <and...@am...> Date: Tue Jun 1 14:56:54 2021 -0400 tests/amdgpu: Fix valgrind warning Struct access after free Signed-off-by: Andrey Grodzovsky <and...@am...> Reviewed-by: Alex Deucher ale...@am... diff --git a/tests/amdgpu/basic_tests.c b/tests/amdgpu/basic_tests.c index 3a4214f5..0180f9ce 100644 --- a/tests/amdgpu/basic_tests.c +++ b/tests/amdgpu/basic_tests.c @@ -626,13 +626,14 @@ CU_BOOL suite_basic_tests_enable(void) &minor_version, &device_handle)) return CU_FALSE; - if (amdgpu_device_deinitialize(device_handle)) - return CU_FALSE; family_id = device_handle->info.family_id; chip_id = device_handle->info.chip_external_rev; chip_rev = device_handle->info.chip_rev; + if (amdgpu_device_deinitialize(device_handle)) + return CU_FALSE; + /* disable gfx engine basic test cases for some asics have no CPG */ if (asic_is_gfx_pipe_removed(family_id, chip_id, chip_rev)) { if (amdgpu_set_test_active("Basic Tests", |
From: GitLab M. <git...@ke...> - 2021-06-22 11:18:38
|
.gitlab-ci.yml | 2 .gitlab-ci/debian-install.sh | 2 README.rst | 18 + core-symbols.txt | 2 gen_table_fourcc.py | 84 ++++++++ meson.build | 9 tests/modetest/modetest.c | 75 +++---- xf86drm.c | 421 +++++++++++++++++++++++++++++++++++++++++++ xf86drm.h | 11 + 9 files changed, 575 insertions(+), 49 deletions(-) New commits: commit 5d97031e8aa717c83993fcdaa45b0812ddceb3b0 Author: Marius Vlad <mar...@co...> Date: Thu Feb 11 13:08:05 2021 +0200 README.rst: Include some notes about syncing uapi headers Signed-off-by: Marius Vlad <mar...@co...> diff --git a/README.rst b/README.rst index da995d0b..74608031 100644 --- a/README.rst +++ b/README.rst @@ -13,6 +13,24 @@ but a new libdrm will always work with an older kernel. libdrm is a low-level library, typically used by graphics drivers such as the Mesa drivers, the X drivers, libva and similar projects. +Syncing with the Linux kernel headers +------------------------------------- + +The library should be regularly updated to match the recent changes in the +`include/uapi/drm/`. + +libdrm maintains a human-readable version for the token format modifier, with +the simpler ones being extracted automatically from `drm_fourcc.h` header file +with the help of a python script. This might not always possible, as some of +the vendors require decoding/extracting them programmatically. For that +reason one can enhance the current vendor functions to include/provide the +newly added token formats, or, in case there's no such decoding +function, to add one that performs the tasks of extracting them. + +For simpler format modifier tokens there's a script (gen_table_fourcc.py) that +creates a static table, by going over `drm_fourcc.h` header file. The script +could be further modified if it can't handle new (simpler) token format +modifiers instead of the generated static table. Compiling --------- commit 65d89398081b33b7498bccaee6915e977f589ec2 Author: Marius Vlad <mar...@co...> Date: Wed Feb 24 00:51:45 2021 +0200 xf86drm: Add support for decoding AMLOGIC format modifiers Signed-off-by: Marius Vlad <mar...@co...> diff --git a/xf86drm.c b/xf86drm.c index 7b4dbf05..1f0b847a 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -172,10 +172,14 @@ drmGetFormatModifierNameFromNvidia(uint64_t modifier); static char * drmGetFormatModifierNameFromAmd(uint64_t modifier); +static char * +drmGetFormatModifierNameFromAmlogic(uint64_t modifier); + static const struct drmVendorInfo modifier_format_vendor_table[] = { { DRM_FORMAT_MOD_VENDOR_ARM, drmGetFormatModifierNameFromArm }, { DRM_FORMAT_MOD_VENDOR_NVIDIA, drmGetFormatModifierNameFromNvidia }, { DRM_FORMAT_MOD_VENDOR_AMD, drmGetFormatModifierNameFromAmd }, + { DRM_FORMAT_MOD_VENDOR_AMLOGIC, drmGetFormatModifierNameFromAmlogic }, }; #ifndef AFBC_FORMAT_MOD_MODE_VALUE_MASK @@ -447,6 +451,37 @@ drmGetFormatModifierNameFromAmd(uint64_t modifier) return mod_amd; } +static char * +drmGetFormatModifierNameFromAmlogic(uint64_t modifier) +{ + uint64_t layout = modifier & 0xff; + uint64_t options = (modifier >> 8) & 0xff; + char *mod_amlogic = NULL; + + const char *layout_str; + const char *opts_str; + + switch (layout) { + case AMLOGIC_FBC_LAYOUT_BASIC: + layout_str = "BASIC"; + break; + case AMLOGIC_FBC_LAYOUT_SCATTER: + layout_str = "SCATTER"; + break; + default: + layout_str = "INVALID_LAYOUT"; + break; + } + + if (options & AMLOGIC_FBC_OPTION_MEM_SAVING) + opts_str = "MEM_SAVING"; + else + opts_str = "0"; + + asprintf(&mod_amlogic, "FBC,LAYOUT=%s,OPTIONS=%s", layout_str, opts_str); + return mod_amlogic; +} + static unsigned log2_int(unsigned x) { unsigned l; commit 9ae8f17d563a81212ca2f61a3427ed559c105644 Author: Marius Vlad <mar...@co...> Date: Wed Feb 17 15:59:30 2021 +0200 xf86drm: Add support for decoding AMD format modifiers Signed-off-by: Marius Vlad <mar...@co...> diff --git a/xf86drm.c b/xf86drm.c index 91155010..7b4dbf05 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -169,9 +169,13 @@ drmGetFormatModifierNameFromArm(uint64_t modifier); static char * drmGetFormatModifierNameFromNvidia(uint64_t modifier); +static char * +drmGetFormatModifierNameFromAmd(uint64_t modifier); + static const struct drmVendorInfo modifier_format_vendor_table[] = { { DRM_FORMAT_MOD_VENDOR_ARM, drmGetFormatModifierNameFromArm }, { DRM_FORMAT_MOD_VENDOR_NVIDIA, drmGetFormatModifierNameFromNvidia }, + { DRM_FORMAT_MOD_VENDOR_AMD, drmGetFormatModifierNameFromAmd }, }; #ifndef AFBC_FORMAT_MOD_MODE_VALUE_MASK @@ -190,6 +194,18 @@ static const struct drmFormatVendorModifierInfo arm_mode_value_table[] = { { AFBC_FORMAT_MOD_USM, "USM" }, }; +static bool is_x_t_amd_gfx9_tile(uint64_t tile) +{ + switch (tile) { + case AMD_FMT_MOD_TILE_GFX9_64K_S_X: + case AMD_FMT_MOD_TILE_GFX9_64K_D_X: + case AMD_FMT_MOD_TILE_GFX9_64K_R_X: + return true; + } + + return false; +} + static char * drmGetFormatModifierNameFromArm(uint64_t modifier) { @@ -280,6 +296,157 @@ drmGetFormatModifierNameFromNvidia(uint64_t modifier) return NULL; } +static void +drmGetFormatModifierNameFromAmdDcc(uint64_t modifier, FILE *fp) +{ + uint64_t dcc_max_compressed_block = + AMD_FMT_MOD_GET(DCC_MAX_COMPRESSED_BLOCK, modifier); + uint64_t dcc_retile = AMD_FMT_MOD_GET(DCC_RETILE, modifier); + + const char *dcc_max_compressed_block_str = NULL; + + fprintf(fp, ",DCC"); + + if (dcc_retile) + fprintf(fp, ",DCC_RETILE"); + + if (!dcc_retile && AMD_FMT_MOD_GET(DCC_PIPE_ALIGN, modifier)) + fprintf(fp, ",DCC_PIPE_ALIGN"); + + if (AMD_FMT_MOD_GET(DCC_INDEPENDENT_64B, modifier)) + fprintf(fp, ",DCC_INDEPENDENT_64B"); + + if (AMD_FMT_MOD_GET(DCC_INDEPENDENT_128B, modifier)) + fprintf(fp, ",DCC_INDEPENDENT_128B"); + + switch (dcc_max_compressed_block) { + case AMD_FMT_MOD_DCC_BLOCK_64B: + dcc_max_compressed_block_str = "64B"; + break; + case AMD_FMT_MOD_DCC_BLOCK_128B: + dcc_max_compressed_block_str = "128B"; + break; + case AMD_FMT_MOD_DCC_BLOCK_256B: + dcc_max_compressed_block_str = "256B"; + break; + } + + if (dcc_max_compressed_block_str) + fprintf(fp, ",DCC_MAX_COMPRESSED_BLOCK=%s", + dcc_max_compressed_block_str); + + if (AMD_FMT_MOD_GET(DCC_CONSTANT_ENCODE, modifier)) + fprintf(fp, ",DCC_CONSTANT_ENCODE"); +} + +static void +drmGetFormatModifierNameFromAmdTile(uint64_t modifier, FILE *fp) +{ + uint64_t pipe_xor_bits, bank_xor_bits, packers, rb; + uint64_t pipe, pipe_align, dcc, dcc_retile, tile_version; + + pipe_align = AMD_FMT_MOD_GET(DCC_PIPE_ALIGN, modifier); + pipe_xor_bits = AMD_FMT_MOD_GET(PIPE_XOR_BITS, modifier); + dcc = AMD_FMT_MOD_GET(DCC, modifier); + dcc_retile = AMD_FMT_MOD_GET(DCC_RETILE, modifier); + tile_version = AMD_FMT_MOD_GET(TILE_VERSION, modifier); + + fprintf(fp, ",PIPE_XOR_BITS=%"PRIu64, pipe_xor_bits); + + if (tile_version == AMD_FMT_MOD_TILE_VER_GFX9) { + bank_xor_bits = AMD_FMT_MOD_GET(BANK_XOR_BITS, modifier); + fprintf(fp, ",BANK_XOR_BITS=%"PRIu64, bank_xor_bits); + } + + if (tile_version == AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) { + packers = AMD_FMT_MOD_GET(PACKERS, modifier); + fprintf(fp, ",PACKERS=%"PRIu64, packers); + } + + if (dcc && tile_version == AMD_FMT_MOD_TILE_VER_GFX9) { + rb = AMD_FMT_MOD_GET(RB, modifier); + fprintf(fp, ",RB=%"PRIu64, rb); + } + + if (dcc && tile_version == AMD_FMT_MOD_TILE_VER_GFX9 && + (dcc_retile || pipe_align)) { + pipe = AMD_FMT_MOD_GET(PIPE, modifier); + fprintf(fp, ",PIPE_%"PRIu64, pipe); + } +} + +static char * +drmGetFormatModifierNameFromAmd(uint64_t modifier) +{ + uint64_t tile, tile_version, dcc; + FILE *fp; + char *mod_amd = NULL; + size_t size = 0; + + const char *str_tile = NULL; + const char *str_tile_version = NULL; + + tile = AMD_FMT_MOD_GET(TILE, modifier); + tile_version = AMD_FMT_MOD_GET(TILE_VERSION, modifier); + dcc = AMD_FMT_MOD_GET(DCC, modifier); + + fp = open_memstream(&mod_amd, &size); + if (!fp) + return NULL; + + /* add tile */ + switch (tile_version) { + case AMD_FMT_MOD_TILE_VER_GFX9: + str_tile_version = "GFX9"; + break; + case AMD_FMT_MOD_TILE_VER_GFX10: + str_tile_version = "GFX10"; + break; + case AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS: + str_tile_version = "GFX10_RBPLUS"; + break; + } + + if (str_tile_version) { + fprintf(fp, "%s", str_tile_version); + } else { + fclose(fp); + free(mod_amd); + return NULL; + } + + /* add tile str */ + switch (tile) { + case AMD_FMT_MOD_TILE_GFX9_64K_S: + str_tile = "GFX9_64K_S"; + break; + case AMD_FMT_MOD_TILE_GFX9_64K_D: + str_tile = "GFX9_64K_D"; + break; + case AMD_FMT_MOD_TILE_GFX9_64K_S_X: + str_tile = "GFX9_64K_S_X"; + break; + case AMD_FMT_MOD_TILE_GFX9_64K_D_X: + str_tile = "GFX9_64K_D_X"; + break; + case AMD_FMT_MOD_TILE_GFX9_64K_R_X: + str_tile = "GFX9_64K_R_X"; + break; + } + + if (str_tile) + fprintf(fp, ",%s", str_tile); + + if (dcc) + drmGetFormatModifierNameFromAmdDcc(modifier, fp); + + if (tile_version >= AMD_FMT_MOD_TILE_VER_GFX9 && is_x_t_amd_gfx9_tile(tile)) + drmGetFormatModifierNameFromAmdTile(modifier, fp); + + fclose(fp); + return mod_amd; +} + static unsigned log2_int(unsigned x) { unsigned l; commit 99a0522aef04e08c6e0be7a7a020f12c51d24c47 Author: Marius Vlad <mar...@co...> Date: Mon Feb 1 13:45:58 2021 +0200 xf86drm: Add support for decoding Nvidia format modifiers Signed-off-by: Marius Vlad <mar...@co...> diff --git a/xf86drm.c b/xf86drm.c index 3f063b29..91155010 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -61,6 +61,7 @@ #include <sys/sysctl.h> #endif #include <math.h> +#include <inttypes.h> #if defined(__FreeBSD__) #include <sys/param.h> @@ -165,8 +166,12 @@ struct drmFormatVendorModifierInfo { static char * drmGetFormatModifierNameFromArm(uint64_t modifier); +static char * +drmGetFormatModifierNameFromNvidia(uint64_t modifier); + static const struct drmVendorInfo modifier_format_vendor_table[] = { { DRM_FORMAT_MOD_VENDOR_ARM, drmGetFormatModifierNameFromArm }, + { DRM_FORMAT_MOD_VENDOR_NVIDIA, drmGetFormatModifierNameFromNvidia }, }; #ifndef AFBC_FORMAT_MOD_MODE_VALUE_MASK @@ -250,6 +255,31 @@ drmGetFormatModifierNameFromArm(uint64_t modifier) return modifier_name; } +static char * +drmGetFormatModifierNameFromNvidia(uint64_t modifier) +{ + uint64_t height, kind, gen, sector, compression; + + height = modifier & 0xf; + kind = (modifier >> 12) & 0xff; + + gen = (modifier >> 20) & 0x3; + sector = (modifier >> 22) & 0x1; + compression = (modifier >> 23) & 0x7; + + /* just in case there could other simpler modifiers, not yet added, avoid + * testing against TEGRA_TILE */ + if ((modifier & 0x10) == 0x10) { + char *mod_nvidia; + asprintf(&mod_nvidia, "BLOCK_LINEAR_2D,HEIGHT=%"PRIu64",KIND=%"PRIu64"," + "GEN=%"PRIu64",SECTOR=%"PRIu64",COMPRESSION=%"PRIu64"", height, + kind, gen, sector, compression); + return mod_nvidia; + } + + return NULL; +} + static unsigned log2_int(unsigned x) { unsigned l; commit a04b674887586bf05594abaf7c55fd8d630898db Author: Marius Vlad <mar...@co...> Date: Mon Feb 1 13:39:43 2021 +0200 xf86drm: Add a vendor function to decode the format modifier As format modifiers can be encoded in quite complex forms, the static table previously added is not sufficient to retrieve, extract and decode the token formats to a human-readable string. This patch introduces a vendor specific callback which could be used to perform an additional search to match up with vendor encoding scheme, which, will be used first, before resorting to searching the static table. With it, add support for decoding the ARM format modifiers. Signed-off-by: Marius Vlad <mar...@co...> diff --git a/xf86drm.c b/xf86drm.c index 24163665..3f063b29 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -152,6 +152,104 @@ struct drmFormatModifierVendorInfo { #include "generated_static_table_fourcc.h" +struct drmVendorInfo { + uint8_t vendor; + char *(*vendor_cb)(uint64_t modifier); +}; + +struct drmFormatVendorModifierInfo { + uint64_t modifier; + const char *modifier_name; +}; + +static char * +drmGetFormatModifierNameFromArm(uint64_t modifier); + +static const struct drmVendorInfo modifier_format_vendor_table[] = { + { DRM_FORMAT_MOD_VENDOR_ARM, drmGetFormatModifierNameFromArm }, +}; + +#ifndef AFBC_FORMAT_MOD_MODE_VALUE_MASK +#define AFBC_FORMAT_MOD_MODE_VALUE_MASK 0x000fffffffffffffULL +#endif + +static const struct drmFormatVendorModifierInfo arm_mode_value_table[] = { + { AFBC_FORMAT_MOD_YTR, "YTR" }, + { AFBC_FORMAT_MOD_SPLIT, "SPLIT" }, + { AFBC_FORMAT_MOD_SPARSE, "SPARSE" }, + { AFBC_FORMAT_MOD_CBR, "CBR" }, + { AFBC_FORMAT_MOD_TILED, "TILED" }, + { AFBC_FORMAT_MOD_SC, "SC" }, + { AFBC_FORMAT_MOD_DB, "DB" }, + { AFBC_FORMAT_MOD_BCH, "BCH" }, + { AFBC_FORMAT_MOD_USM, "USM" }, +}; + +static char * +drmGetFormatModifierNameFromArm(uint64_t modifier) +{ + uint64_t type = (modifier >> 52) & 0xf; + uint64_t mode_value = modifier & AFBC_FORMAT_MOD_MODE_VALUE_MASK; + uint64_t block_size = mode_value & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK; + + FILE *fp; + char *modifier_name = NULL; + size_t size = 0; + unsigned int i; + + const char *block = NULL; + const char *mode = NULL; + bool did_print_mode = false; + + /* misc type is already handled by the static table */ + if (type != DRM_FORMAT_MOD_ARM_TYPE_AFBC) + return NULL; + + fp = open_memstream(&modifier_name, &size); + if (!fp) + return NULL; + + /* add block, can only have a (single) block */ + switch (block_size) { + case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16: + block = "16x16"; + break; + case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8: + block = "32x8"; + break; + case AFBC_FORMAT_MOD_BLOCK_SIZE_64x4: + block = "64x4"; + break; + case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4: + block = "32x8_64x4"; + break; + } + + if (!block) { + fclose(fp); + free(modifier_name); + return NULL; + } + + fprintf(fp, "BLOCK_SIZE=%s,", block); + + /* add mode */ + for (i = 0; i < ARRAY_SIZE(arm_mode_value_table); i++) { + if (arm_mode_value_table[i].modifier & mode_value) { + mode = arm_mode_value_table[i].modifier_name; + if (!did_print_mode) { + fprintf(fp, "MODE=%s", mode); + did_print_mode = true; + } else { + fprintf(fp, "|%s", mode); + } + } + } + + fclose(fp); + return modifier_name; +} + static unsigned log2_int(unsigned x) { unsigned l; @@ -4651,8 +4749,8 @@ drmGetFormatModifierVendor(uint64_t modifier) /** Retrieves a human-readable representation string from a format token * modifier * - * If the format modifier was not in the table, this function would return - * NULL. + * If the dedicated function was not able to extract a valid name or searching + * the format modifier was not in the table, this function would return NULL. * * \param modifier the token format * \return a malloc'ed string representation of the modifier. Caller is @@ -4662,6 +4760,17 @@ drmGetFormatModifierVendor(uint64_t modifier) drm_public char * drmGetFormatModifierName(uint64_t modifier) { - char *modifier_found = drmGetFormatModifierFromSimpleTokens(modifier); + uint8_t vendorid = fourcc_mod_get_vendor(modifier); + char *modifier_found = NULL; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(modifier_format_vendor_table); i++) { + if (modifier_format_vendor_table[i].vendor == vendorid) + modifier_found = modifier_format_vendor_table[i].vendor_cb(modifier); + } + + if (!modifier_found) + return drmGetFormatModifierFromSimpleTokens(modifier); + return modifier_found; } commit 67e911977fbe1f444045f59028c149a04ba29566 Author: Marius Vlad <mar...@co...> Date: Mon Feb 1 13:23:20 2021 +0200 xf86drm: Add a human readable representation for format modifiers Introduces two new methods to retrieve a human readable representation of a format modifier: drmGetFormatModifierName() - returns a format modifier as a string, from a token modifier drmGetFormatModifierVendor() - returns the vendor as a string, from a token modifier and the fourcc_mod_get_vendor macro that returns the vendor. New format modifiers added in drm_fourcc.h uapi kernel header should be sync'ed up with libdrm and should include a human readable representation for that format modifier, in order to display it correctly as a string. That happens with the help of a python script that reads up drm_fourcc header file and outputs a static table comprised of token modifiers alongside a vendor table (Suggested-by Simon Ser <co...@em...>). The reason for doing it in libdrm is to have a unified place instead of each user of libdrm having a way to keep track of the format modifiers. With this patch, modetest has also been modified to make use of it. Signed-off-by: Marius Vlad <mar...@co...> diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7cd6d0f1..26eaf83b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,7 +14,7 @@ # repository's registry will be used there as well. variables: UPSTREAM_REPO: mesa/drm - DEBIAN_TAG: "2020-11-15" + DEBIAN_TAG: "2021-02-11" DEBIAN_VERSION: buster-slim DEBIAN_IMAGE: "$CI_REGISTRY_IMAGE/debian/$DEBIAN_VERSION:$DEBIAN_TAG" diff --git a/.gitlab-ci/debian-install.sh b/.gitlab-ci/debian-install.sh index 886e808f..ab901360 100644 --- a/.gitlab-ci/debian-install.sh +++ b/.gitlab-ci/debian-install.sh @@ -63,4 +63,4 @@ done # Test that the oldest Meson version we claim to support is still supported -pip3 install meson==0.43 +pip3 install meson==0.46 diff --git a/core-symbols.txt b/core-symbols.txt index 410054b3..a79e6260 100644 --- a/core-symbols.txt +++ b/core-symbols.txt @@ -196,3 +196,5 @@ drmUnmap drmUnmapBufs drmUpdateDrawableInfo drmWaitVBlank +drmGetFormatModifierName +drmGetFormatModifierVendor diff --git a/gen_table_fourcc.py b/gen_table_fourcc.py new file mode 100644 index 00000000..4e8bc409 --- /dev/null +++ b/gen_table_fourcc.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 + +# Copyright 2021 Collabora, Ltd. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice (including the +# next paragraph) shall be included in all copies or substantial +# portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Helper script that reads drm_fourcc.h and writes a static table with the +# simpler format token modifiers + +import sys +import re + +filename = sys.argv[1] +towrite = sys.argv[2] + +fm_re = { + 'intel': r'^#define I915_FORMAT_MOD_(\w+)', + 'others': r'^#define DRM_FORMAT_MOD_((?:ARM|SAMSUNG|QCOM|VIVANTE|NVIDIA|BROADCOM|ALLWINNER)\w+)\s', + 'vendors': r'^#define DRM_FORMAT_MOD_VENDOR_(\w+)' +} + +def print_fm_intel(f, f_mod): + f.write(' {{ DRM_MODIFIER_INTEL({}, {}) }},\n'.format(f_mod, f_mod)) + +# generic write func +def print_fm(f, vendor, mod, f_name): + f.write(' {{ DRM_MODIFIER({}, {}, {}) }},\n'.format(vendor, mod, f_name)) + +with open(filename, "r") as f: + data = f.read() + for k, v in fm_re.items(): + fm_re[k] = re.findall(v, data, flags=re.M) + +with open(towrite, "w") as f: + f.write('''\ +/* AUTOMATICALLY GENERATED by gen_table_fourcc.py. You should modify + that script instead of adding here entries manually! */ +static const struct drmFormatModifierInfo drm_format_modifier_table[] = { +''') + f.write(' { DRM_MODIFIER_INVALID(NONE, INVALID_MODIFIER) },\n') + f.write(' { DRM_MODIFIER_LINEAR(NONE, LINEAR) },\n') + + for entry in fm_re['intel']: + print_fm_intel(f, entry) + + for entry in fm_re['others']: + (vendor, mod) = entry.split('_', 1) + if vendor == 'ARM' and (mod == 'TYPE_AFBC' or mod == 'TYPE_MISC'): + continue + print_fm(f, vendor, mod, mod) + + f.write('''\ +}; +''') + + f.write('''\ +static const struct drmFormatModifierVendorInfo drm_format_modifier_vendor_table[] = { +''') + + for entry in fm_re['vendors']: + f.write(" {{ DRM_FORMAT_MOD_VENDOR_{}, \"{}\" }},\n".format(entry, entry)) + + f.write('''\ +}; +''') diff --git a/meson.build b/meson.build index fd59c4b3..2bbb485b 100644 --- a/meson.build +++ b/meson.build @@ -23,7 +23,7 @@ project( ['c'], version : '2.4.106', license : 'MIT', - meson_version : '>= 0.43', + meson_version : '>= 0.46', default_options : ['buildtype=debugoptimized', 'c_std=gnu99'], ) @@ -51,6 +51,11 @@ prog_nm = find_program('nm') intel_atomics = false lib_atomics = false +python3 = import('python').find_installation() +format_mod_static_table = custom_target('format_mod_static_table', + output : 'generated_static_table_fourcc.h', input: 'include/drm/drm_fourcc.h', + command : [python3, files('gen_table_fourcc.py'), '@INPUT@', '@OUTPUT@']) + dep_atomic_ops = dependency('atomic_ops', required : false) if cc.links(''' int atomic_add(int *i) { return __sync_add_and_fetch (i, 1); } @@ -300,7 +305,7 @@ libdrm = library( 'xf86drm.c', 'xf86drmHash.c', 'xf86drmRandom.c', 'xf86drmSL.c', 'xf86drmMode.c' ), - config_file, + config_file, format_mod_static_table ], c_args : libdrm_c_args, dependencies : [dep_valgrind, dep_rt, dep_m], diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index fc75383a..2c83bd03 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -265,52 +265,37 @@ static void dump_blob(struct device *dev, uint32_t blob_id) static const char *modifier_to_string(uint64_t modifier) { - switch (modifier) { - case DRM_FORMAT_MOD_INVALID: - return "INVALID"; - case DRM_FORMAT_MOD_LINEAR: - return "LINEAR"; - case I915_FORMAT_MOD_X_TILED: - return "X_TILED"; - case I915_FORMAT_MOD_Y_TILED: - return "Y_TILED"; - case I915_FORMAT_MOD_Yf_TILED: - return "Yf_TILED"; - case I915_FORMAT_MOD_Y_TILED_CCS: - return "Y_TILED_CCS"; - case I915_FORMAT_MOD_Yf_TILED_CCS: - return "Yf_TILED_CCS"; - case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE: - return "SAMSUNG_64_32_TILE"; - case DRM_FORMAT_MOD_VIVANTE_TILED: - return "VIVANTE_TILED"; - case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED: - return "VIVANTE_SUPER_TILED"; - case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED: - return "VIVANTE_SPLIT_TILED"; - case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED: - return "VIVANTE_SPLIT_SUPER_TILED"; - case DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED: - return "NVIDIA_TEGRA_TILED"; - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0): - return "NVIDIA_16BX2_BLOCK(0)"; - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1): - return "NVIDIA_16BX2_BLOCK(1)"; - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2): - return "NVIDIA_16BX2_BLOCK(2)"; - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3): - return "NVIDIA_16BX2_BLOCK(3)"; - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4): - return "NVIDIA_16BX2_BLOCK(4)"; - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5): - return "NVIDIA_16BX2_BLOCK(5)"; - case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: - return "MOD_BROADCOM_VC4_T_TILED"; - case DRM_FORMAT_MOD_QCOM_COMPRESSED: - return "QCOM_COMPRESSED"; - default: - return "(UNKNOWN MODIFIER)"; + static char mod_string[4096]; + + char *modifier_name = drmGetFormatModifierName(modifier); + char *vendor_name = drmGetFormatModifierVendor(modifier); + memset(mod_string, 0x00, sizeof(mod_string)); + + if (!modifier_name) { + if (vendor_name) + snprintf(mod_string, sizeof(mod_string), "%s_%s", + vendor_name, "UNKNOWN_MODIFIER"); + else + snprintf(mod_string, sizeof(mod_string), "%s_%s", + "UNKNOWN_VENDOR", "UNKNOWN_MODIFIER"); + /* safe, as free is no-op for NULL */ + free(vendor_name); + return mod_string; } + + if (modifier == DRM_FORMAT_MOD_LINEAR) { + snprintf(mod_string, sizeof(mod_string), "%s", modifier_name); + free(modifier_name); + free(vendor_name); + return mod_string; + } + + snprintf(mod_string, sizeof(mod_string), "%s_%s", + vendor_name, modifier_name); + + free(modifier_name); + free(vendor_name); + return mod_string; } static void dump_in_formats(struct device *dev, uint32_t blob_id) diff --git a/xf86drm.c b/xf86drm.c index edfeb347..24163665 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -76,6 +76,7 @@ #include "xf86drm.h" #include "libdrm_macros.h" +#include "drm_fourcc.h" #include "util_math.h" @@ -124,6 +125,33 @@ static drmServerInfoPtr drm_server_info; static bool drmNodeIsDRM(int maj, int min); static char *drmGetMinorNameForFD(int fd, int type); +#define DRM_MODIFIER(v, f, f_name) \ + .modifier = DRM_FORMAT_MOD_##v ## _ ##f, \ + .modifier_name = #f_name + +#define DRM_MODIFIER_INVALID(v, f_name) \ + .modifier = DRM_FORMAT_MOD_INVALID, .modifier_name = #f_name + +#define DRM_MODIFIER_LINEAR(v, f_name) \ + .modifier = DRM_FORMAT_MOD_LINEAR, .modifier_name = #f_name + +/* Intel is abit special as the format doesn't follow other vendors naming + * scheme */ +#define DRM_MODIFIER_INTEL(f, f_name) \ + .modifier = I915_FORMAT_MOD_##f, .modifier_name = #f_name + +struct drmFormatModifierInfo { + uint64_t modifier; + const char *modifier_name; +}; + +struct drmFormatModifierVendorInfo { + uint8_t vendor; + const char *vendor_name; +}; + +#include "generated_static_table_fourcc.h" + static unsigned log2_int(unsigned x) { unsigned l; @@ -4585,3 +4613,55 @@ drm_public int drmSyncobjTransfer(int fd, return ret; } + +static char * +drmGetFormatModifierFromSimpleTokens(uint64_t modifier) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(drm_format_modifier_table); i++) { + if (drm_format_modifier_table[i].modifier == modifier) + return strdup(drm_format_modifier_table[i].modifier_name); + } + + return NULL; +} + +/** Retrieves a human-readable representation of a vendor (as a string) from + * the format token modifier + * + * \param modifier the format modifier token + * \return a char pointer to the human-readable form of the vendor. Caller is + * responsible for freeing it. + */ +drm_public char * +drmGetFormatModifierVendor(uint64_t modifier) +{ + unsigned int i; + uint8_t vendor = fourcc_mod_get_vendor(modifier); + + for (i = 0; i < ARRAY_SIZE(drm_format_modifier_vendor_table); i++) { + if (drm_format_modifier_vendor_table[i].vendor == vendor) + return strdup(drm_format_modifier_vendor_table[i].vendor_name); + } + + return NULL; +} + +/** Retrieves a human-readable representation string from a format token + * modifier + * + * If the format modifier was not in the table, this function would return + * NULL. + * + * \param modifier the token format + * \return a malloc'ed string representation of the modifier. Caller is + * responsible for freeing the string returned. + * + */ +drm_public char * +drmGetFormatModifierName(uint64_t modifier) +{ + char *modifier_found = drmGetFormatModifierFromSimpleTokens(modifier); + return modifier_found; +} diff --git a/xf86drm.h b/xf86drm.h index 9fc06ab8..930d2f40 100644 --- a/xf86drm.h +++ b/xf86drm.h @@ -944,6 +944,17 @@ extern int drmSyncobjTransfer(int fd, uint32_t src_handle, uint64_t src_point, uint32_t flags); +extern char * +drmGetFormatModifierVendor(uint64_t modifier); + +extern char * +drmGetFormatModifierName(uint64_t modifier); + +#ifndef fourcc_mod_get_vendor +#define fourcc_mod_get_vendor(modifier) \ + (((modifier) >> 56) & 0xff) +#endif + #if defined(__cplusplus) } #endif |