From: <da...@ke...> - 2006-07-19 17:20:06
|
shared-core/radeon_cp.c | 21 ++++++++++++++++----- shared-core/radeon_drv.h | 14 ++++++++++---- shared-core/radeon_state.c | 6 ++++++ 3 files changed, 32 insertions(+), 9 deletions(-) New commits: diff-tree d5e0f8bdaf8769642950b8219f0e80f6b523817d (from 2a47f6bfecea5dabcbf79d5e1aaf271f50070b89) Author: Michel Dänzer <mi...@tu...> Date: Wed Jul 19 19:18:32 2006 +0200 Use RADEON_RB3D_DSTCACHE_CTLSTAT instead of RADEON_RB2D_DSTCACHE_CTLSTAT. The latter seems to be a read-only mirror of the former. diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 5f953a4..695b5ec 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -864,13 +864,13 @@ static int radeon_do_pixcache_flush(drm_ dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - tmp = RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT); - tmp |= RADEON_RB2D_DC_FLUSH_ALL; - RADEON_WRITE(RADEON_RB2D_DSTCACHE_CTLSTAT, tmp); + tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT); + tmp |= RADEON_RB3D_DC_FLUSH_ALL; + RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp); for (i = 0; i < dev_priv->usec_timeout; i++) { - if (!(RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT) - & RADEON_RB2D_DC_BUSY)) { + if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT) + & RADEON_RB3D_DC_BUSY)) { return 0; } DRM_UDELAY(1); diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 25ce40c..63b5ace 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -543,6 +543,11 @@ extern int r300_do_cp_cmdbuf(drm_device_ # define RADEON_RB3D_ZC_FREE (1 << 2) # define RADEON_RB3D_ZC_FLUSH_ALL 0x5 # define RADEON_RB3D_ZC_BUSY (1 << 31) +#define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325c +# define RADEON_RB3D_DC_FLUSH (3 << 0) +# define RADEON_RB3D_DC_FREE (3 << 2) +# define RADEON_RB3D_DC_FLUSH_ALL 0xf +# define RADEON_RB3D_DC_BUSY (1 << 31) #define RADEON_RB3D_ZSTENCILCNTL 0x1c2c # define RADEON_Z_TEST_MASK (7 << 4) # define RADEON_Z_TEST_ALWAYS (7 << 4) @@ -1015,13 +1020,13 @@ do { \ } while (0) #define RADEON_FLUSH_CACHE() do { \ - OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \ - OUT_RING( RADEON_RB2D_DC_FLUSH ); \ + OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) ); \ + OUT_RING( RADEON_RB3D_DC_FLUSH ); \ } while (0) #define RADEON_PURGE_CACHE() do { \ - OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \ - OUT_RING( RADEON_RB2D_DC_FLUSH_ALL ); \ + OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) ); \ + OUT_RING( RADEON_RB3D_DC_FLUSH_ALL ); \ } while (0) #define RADEON_FLUSH_ZCACHE() do { \ diff-tree 2a47f6bfecea5dabcbf79d5e1aaf271f50070b89 (from c91748e702af1c59d88a4b6c2afb20a781dc6660) Author: Michel Dänzer <mi...@tu...> Date: Wed Jul 19 19:16:26 2006 +0200 Make sure CHIP_IS_AGP flag is set when not overriding to PCI mode. This allows using AGP after overriding to PCI mode in a previous session without reloading the DRM. diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 54763fc..5f953a4 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -1351,6 +1351,11 @@ static int radeon_do_init_cp(drm_device_ DRM_DEBUG("Forcing AGP card to PCI mode\n"); dev_priv->flags &= ~CHIP_IS_AGP; } + else if (!(dev_priv->flags & CHIP_IS_AGP)) + { + DRM_DEBUG("Restoring AGP flag\n"); + dev_priv->flags |= CHIP_IS_AGP; + } if ((!(dev_priv->flags & CHIP_IS_AGP)) && !dev->sg) { DRM_ERROR("PCI GART memory not allocated!\n"); diff-tree c91748e702af1c59d88a4b6c2afb20a781dc6660 (from e337eadcec9c1e2cf885167c076ab2407bd6c090) Author: Michel Dänzer <mi...@tu...> Date: Wed Jul 19 19:13:00 2006 +0200 When writeback isn't used, actually disable it in the hardware. Not doing this might waste bus bandwidth or even cause memory corruption or system crashes on systems that check bus transfers. No such incident has been reported though. diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index ccb0023..54763fc 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -1258,6 +1258,12 @@ static void radeon_test_writeback(drm_ra dev_priv->writeback_works = 0; DRM_INFO("writeback forced off\n"); } + + if (!dev_priv->writeback_works) { + /* Disable writeback to avoid unnecessary bus master transfers */ + RADEON_WRITE(RADEON_CP_RB_CNTL, RADEON_READ(RADEON_CP_RB_CNTL) | RADEON_RB_NO_UPDATE); + RADEON_WRITE(RADEON_SCRATCH_UMSK, 0); + } } /* Enable or disable PCI-E GART on the chip */ diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 441c297..25ce40c 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -679,6 +679,7 @@ extern int r300_do_cp_cmdbuf(drm_device_ #define RADEON_CP_RB_BASE 0x0700 #define RADEON_CP_RB_CNTL 0x0704 # define RADEON_BUF_SWAP_32BIT (2 << 16) +# define RADEON_RB_NO_UPDATE (1 << 27) #define RADEON_CP_RB_RPTR_ADDR 0x070c #define RADEON_CP_RB_RPTR 0x0710 #define RADEON_CP_RB_WPTR 0x0714 diff-tree e337eadcec9c1e2cf885167c076ab2407bd6c090 (from 7dea64677b62418b14d34c41399cdb8bf8b817cd) Author: Michel Dänzer <mi...@tu...> Date: Wed Jul 19 19:07:06 2006 +0200 Implement RADEON_PARAM_SCRATCH_OFFSET getparam. When this succeeds, userspace can read the scratch register contents from the mapped writeback page directly. diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 2c169ac..58251dd 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -3025,6 +3025,11 @@ static int radeon_cp_getparam(DRM_IOCTL_ case RADEON_PARAM_GART_TEX_HANDLE: value = dev_priv->gart_textures_offset; break; + case RADEON_PARAM_SCRATCH_OFFSET: + if (!dev_priv->writeback_works) + return DRM_ERR(EINVAL); + value = RADEON_SCRATCH_REG_OFFSET; + break; case RADEON_PARAM_CARD_TYPE: if (dev_priv->flags & CHIP_IS_PCIE) diff-tree 7dea64677b62418b14d34c41399cdb8bf8b817cd (from b9243ce3d5ed6bd70851a132871387d4d2e886bc) Author: Michel Dänzer <mi...@tu...> Date: Wed Jul 19 19:01:33 2006 +0200 Some debug output when the getparam ioctl is called with an unknown parameter. diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 7e0cb6a..2c169ac 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -3035,6 +3035,7 @@ static int radeon_cp_getparam(DRM_IOCTL_ value = RADEON_CARD_PCI; break; default: + DRM_DEBUG( "Invalid parameter %d\n", param.param ); return DRM_ERR(EINVAL); } |
From: <gs...@ke...> - 2006-10-02 19:47:48
|
libdrm/xf86drm.h | 3 linux-core/drmP.h | 3 linux-core/drm_bufs.c | 10 + linux-core/drm_vm.c | 16 +++ shared-core/drm.h | 3 shared-core/mach64_dma.c | 232 +++++++++++++++++++++++---------------------- shared-core/mach64_drm.h | 2 shared-core/mach64_drv.h | 7 - shared-core/mach64_state.c | 209 ++++++++++++++++++---------------------- 9 files changed, 253 insertions(+), 232 deletions(-) New commits: diff-tree c9e3aa961eb90265ec024ff57013786e4d47d0e7 (from f3deef730d52c94ce21ada7e4ceb63aa28a8601b) Author: George Sapountzis <gs...@ya...> Date: Mon Oct 2 06:13:38 2006 +0300 Bug 6242: [mach64] Use private DMA buffers, part #4. mach64_state.c: convert the DRM_MACH64_BLIT ioctl to submit a pointer to user-space memory rather than a DMA buffer index, similar to DRM_MACH64_VERTEX. This change allows the DDX to map the DMA buffers read-only and eliminate a security problem where a client can alter the contents of the DMA buffer after submission to the DRM. This change also affects the DRI/DRM interface. Performace-wise, it basically affects PCI mode where I get a ~12% speedup for some Mesa demos I tested. This is mainly due to eliminating an ioctl for allocating the DMA buffer. mach64_dma.c: move the responsibility for allocating memory for the DMA ring in PCI mode to the DDX. This change affects the DDX/DRM interface and unifies a couple of PCI/AGP code paths for ring memory in the DRM. Bump the mach64 DRM version major and date. diff --git a/shared-core/mach64_dma.c b/shared-core/mach64_dma.c index 7cba8ad..3a5fdee 100644 --- a/shared-core/mach64_dma.c +++ b/shared-core/mach64_dma.c @@ -815,17 +815,18 @@ static int mach64_do_dma_init(drm_device return DRM_ERR(EINVAL); } + dev_priv->ring_map = drm_core_findmap(dev, init->ring_offset); + if (!dev_priv->ring_map) { + DRM_ERROR("can not find ring map!\n"); + dev->dev_private = (void *)dev_priv; + mach64_do_cleanup_dma(dev); + return DRM_ERR(EINVAL); + } + dev_priv->sarea_priv = (drm_mach64_sarea_t *) ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset); if (!dev_priv->is_pci) { - dev_priv->ring_map = drm_core_findmap(dev, init->ring_offset); - if (!dev_priv->ring_map) { - DRM_ERROR("can not find ring map!\n"); - dev->dev_private = (void *)dev_priv; - mach64_do_cleanup_dma(dev); - return DRM_ERR(EINVAL); - } drm_core_ioremap(dev_priv->ring_map, dev); if (!dev_priv->ring_map->handle) { DRM_ERROR("can not ioremap virtual address for" @@ -891,27 +892,9 @@ static int mach64_do_dma_init(drm_device } } - /* allocate descriptor memory from pci pool */ - DRM_DEBUG("Allocating dma descriptor ring\n"); dev_priv->ring.size = 0x4000; /* 16KB */ - - if (dev_priv->is_pci) { - dev_priv->ring.dmah = drm_pci_alloc(dev, dev_priv->ring.size, - dev_priv->ring.size, - 0xfffffffful); - - if (!dev_priv->ring.dmah) { - DRM_ERROR("Allocating dma descriptor ring failed\n"); - return DRM_ERR(ENOMEM); - } else { - dev_priv->ring.start = dev_priv->ring.dmah->vaddr; - dev_priv->ring.start_addr = - (u32) dev_priv->ring.dmah->busaddr; - } - } else { - dev_priv->ring.start = dev_priv->ring_map->handle; - dev_priv->ring.start_addr = (u32) dev_priv->ring_map->offset; - } + dev_priv->ring.start = dev_priv->ring_map->handle; + dev_priv->ring.start_addr = (u32) dev_priv->ring_map->offset; memset(dev_priv->ring.start, 0, dev_priv->ring.size); DRM_INFO("descriptor ring: cpu addr %p, bus addr: 0x%08x\n", @@ -1149,18 +1132,14 @@ int mach64_do_cleanup_dma(drm_device_t * if (dev->dev_private) { drm_mach64_private_t *dev_priv = dev->dev_private; - if (dev_priv->is_pci) { - if (dev_priv->ring.dmah) { - drm_pci_free(dev, dev_priv->ring.dmah); - } - } else { + if (!dev_priv->is_pci) { if (dev_priv->ring_map) drm_core_ioremapfree(dev_priv->ring_map, dev); - } - if (dev->agp_buffer_map) { - drm_core_ioremapfree(dev->agp_buffer_map, dev); - dev->agp_buffer_map = NULL; + if (dev->agp_buffer_map) { + drm_core_ioremapfree(dev->agp_buffer_map, dev); + dev->agp_buffer_map = NULL; + } } mach64_destroy_freelist(dev); diff --git a/shared-core/mach64_drm.h b/shared-core/mach64_drm.h index 1fd8c00..083f959 100644 --- a/shared-core/mach64_drm.h +++ b/shared-core/mach64_drm.h @@ -237,7 +237,7 @@ typedef struct drm_mach64_vertex { } drm_mach64_vertex_t; typedef struct drm_mach64_blit { - int idx; + void *buf; int pitch; int offset; int format; diff --git a/shared-core/mach64_drv.h b/shared-core/mach64_drv.h index e8dc71e..bb8b309 100644 --- a/shared-core/mach64_drv.h +++ b/shared-core/mach64_drv.h @@ -42,9 +42,9 @@ #define DRIVER_NAME "mach64" #define DRIVER_DESC "DRM module for the ATI Rage Pro" -#define DRIVER_DATE "20020904" +#define DRIVER_DATE "20060718" -#define DRIVER_MAJOR 1 +#define DRIVER_MAJOR 2 #define DRIVER_MINOR 0 #define DRIVER_PATCHLEVEL 0 @@ -61,7 +61,6 @@ typedef struct drm_mach64_freelist { } drm_mach64_freelist_t; typedef struct drm_mach64_descriptor_ring { - drm_dma_handle_t *dmah; /* Handle to pci dma memory */ void *start; /* write pointer (cpu address) to start of descriptor ring */ u32 start_addr; /* bus address of beginning of descriptor ring */ int size; /* size of ring in bytes */ diff --git a/shared-core/mach64_state.c b/shared-core/mach64_state.c index 31e3b56..38cefca 100644 --- a/shared-core/mach64_state.c +++ b/shared-core/mach64_state.c @@ -480,16 +480,16 @@ static int mach64_do_get_frames_queued(d /* Copy and verify a client submited buffer. * FIXME: Make an assembly optimized version */ -static __inline__ int copy_and_verify_from_user(u32 *to, - const u32 __user *ufrom, - unsigned long bytes) +static __inline__ int copy_from_user_vertex(u32 *to, + const u32 __user *ufrom, + unsigned long bytes) { unsigned long n = bytes; /* dwords remaining in buffer */ u32 *from, *orig_from; from = drm_alloc(bytes, DRM_MEM_DRIVER); if (from == NULL) - return ENOMEM; + return DRM_ERR(ENOMEM); if (DRM_COPY_FROM_USER(from, ufrom, bytes)) { drm_free(from, bytes, DRM_MEM_DRIVER); @@ -571,7 +571,7 @@ static int mach64_dma_dispatch_vertex(DR return DRM_ERR(EAGAIN); } - verify_ret = copy_and_verify_from_user(GETBUFPTR(copy_buf), buf, used); + verify_ret = copy_from_user_vertex(GETBUFPTR(copy_buf), buf, used); if (verify_ret != 0) { mach64_freelist_put(dev_priv, copy_buf); @@ -627,13 +627,27 @@ _vertex_done: return verify_ret; } +static __inline__ int copy_from_user_blit(u32 *to, + const u32 __user *ufrom, + unsigned long bytes) +{ + to = (u32 *)((char *)to + MACH64_HOSTDATA_BLIT_OFFSET); + + if (DRM_COPY_FROM_USER(to, ufrom, bytes)) { + return DRM_ERR(EFAULT); + } + + return 0; +} + static int mach64_dma_dispatch_blit(DRMFILE filp, drm_device_t * dev, drm_mach64_blit_t * blit) { drm_mach64_private_t *dev_priv = dev->dev_private; - drm_device_dma_t *dma = dev->dma; int dword_shift, dwords; - drm_buf_t *buf; + unsigned long used; + drm_buf_t *copy_buf; + int verify_ret = 0; DMALOCALS; /* The compiler won't optimize away a division by a variable, @@ -660,34 +674,34 @@ static int mach64_dma_dispatch_blit(DRMF return DRM_ERR(EINVAL); } - /* Dispatch the blit buffer. - */ - buf = dma->buflist[blit->idx]; - - if (buf->filp != filp) { - DRM_ERROR("process %d (filp %p) using buffer with filp %p\n", - DRM_CURRENTPID, filp, buf->filp); - return DRM_ERR(EINVAL); - } - - if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", blit->idx); - return DRM_ERR(EINVAL); - } - /* Set buf->used to the bytes of blit data based on the blit dimensions * and verify the size. When the setup is emitted to the buffer with * the DMA* macros below, buf->used is incremented to include the bytes * used for setup as well as the blit data. */ dwords = (blit->width * blit->height) >> dword_shift; - buf->used = dwords << 2; - if (buf->used <= 0 || - buf->used > MACH64_BUFFER_SIZE - MACH64_HOSTDATA_BLIT_OFFSET) { - DRM_ERROR("Invalid blit size: %d bytes\n", buf->used); + used = dwords << 2; + if (used <= 0 || + used > MACH64_BUFFER_SIZE - MACH64_HOSTDATA_BLIT_OFFSET) { + DRM_ERROR("Invalid blit size: %lu bytes\n", used); return DRM_ERR(EINVAL); } + copy_buf = mach64_freelist_get(dev_priv); + if (copy_buf == NULL) { + DRM_ERROR("%s: couldn't get buffer\n", __FUNCTION__); + return DRM_ERR(EAGAIN); + } + + verify_ret = copy_from_user_blit(GETBUFPTR(copy_buf), blit->buf, used); + + if (verify_ret != 0) { + mach64_freelist_put(dev_priv, copy_buf); + goto _blit_done; + } + + copy_buf->used = used; + /* FIXME: Use a last buffer flag and reduce the state emitted for subsequent, * continuation buffers? */ @@ -696,7 +710,7 @@ static int mach64_dma_dispatch_blit(DRMF * a register command every 16 dwords. State setup is added at the start of the * buffer -- the client leaves space for this based on MACH64_HOSTDATA_BLIT_OFFSET */ - DMASETPTR(buf); + DMASETPTR(copy_buf); DMAOUTREG(MACH64_Z_CNTL, 0); DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); @@ -726,12 +740,13 @@ static int mach64_dma_dispatch_blit(DRMF DMAOUTREG(MACH64_DST_X_Y, (blit->y << 16) | blit->x); DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (blit->height << 16) | blit->width); - DRM_DEBUG("%s: %d bytes\n", __FUNCTION__, buf->used); + DRM_DEBUG("%s: %lu bytes\n", __FUNCTION__, used); /* Add the buffer to the queue */ DMAADVANCEHOSTDATA(dev_priv); - return 0; +_blit_done: + return verify_ret; } /* ================================================================ @@ -829,7 +844,6 @@ int mach64_dma_vertex(DRM_IOCTL_ARGS) int mach64_dma_blit(DRM_IOCTL_ARGS) { DRM_DEVICE; - drm_device_dma_t *dma = dev->dma; drm_mach64_private_t *dev_priv = dev->dev_private; drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mach64_blit_t blit; @@ -840,15 +854,6 @@ int mach64_dma_blit(DRM_IOCTL_ARGS) DRM_COPY_FROM_USER_IOCTL(blit, (drm_mach64_blit_t *) data, sizeof(blit)); - DRM_DEBUG("%s: pid=%d index=%d\n", - __FUNCTION__, DRM_CURRENTPID, blit.idx); - - if (blit.idx < 0 || blit.idx >= dma->buf_count) { - DRM_ERROR("buffer index %d (of %d max)\n", - blit.idx, dma->buf_count - 1); - return DRM_ERR(EINVAL); - } - ret = mach64_dma_dispatch_blit(filp, dev, &blit); /* Make sure we restore the 3D state next time. diff-tree f3deef730d52c94ce21ada7e4ceb63aa28a8601b (from 25760c30d4aedb370423d0bb03c014cab47b5d4f) Author: George Sapountzis <gs...@ya...> Date: Mon Oct 2 05:46:42 2006 +0300 Bug 6242: [mach64] Use private DMA buffers, part #3. Add DRM_PCI_BUFFER_RO flag for mapping PCI DMA buffer read-only. An additional flag is needed, since PCI DMA buffers do not have an associated map. diff --git a/libdrm/xf86drm.h b/libdrm/xf86drm.h index 2ad7080..d58baa7 100644 --- a/libdrm/xf86drm.h +++ b/libdrm/xf86drm.h @@ -149,7 +149,8 @@ typedef enum { DRM_PAGE_ALIGN = 0x01, DRM_AGP_BUFFER = 0x02, DRM_SG_BUFFER = 0x04, - DRM_FB_BUFFER = 0x08 + DRM_FB_BUFFER = 0x08, + DRM_PCI_BUFFER_RO = 0x10 } drmBufDescFlags; typedef enum { diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 5c9644e..2bbec70 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -449,7 +449,8 @@ typedef struct drm_device_dma { enum { _DRM_DMA_USE_AGP = 0x01, _DRM_DMA_USE_SG = 0x02, - _DRM_DMA_USE_FB = 0x04 + _DRM_DMA_USE_FB = 0x04, + _DRM_DMA_USE_PCI_RO = 0x08 } flags; } drm_device_dma_t; diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c index abd7c82..a2a3dbf 100644 --- a/linux-core/drm_bufs.c +++ b/linux-core/drm_bufs.c @@ -942,6 +942,9 @@ int drm_addbufs_pci(drm_device_t * dev, request->count = entry->buf_count; request->size = size; + if (request->flags & _DRM_PCI_BUFFER_RO) + dma->flags = _DRM_DMA_USE_PCI_RO; + atomic_dec(&dev->buf_alloc); return 0; @@ -1528,9 +1531,10 @@ int drm_freebufs(struct inode *inode, st * \param arg pointer to a drm_buf_map structure. * \return zero on success or a negative number on failure. * - * Maps the AGP or SG buffer region with do_mmap(), and copies information - * about each buffer into user space. The PCI buffers are already mapped on the - * addbufs_pci() call. + * Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information + * about each buffer into user space. For PCI buffers, it calls do_mmap() with + * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls + * drm_mmap_dma(). */ int drm_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 9672269..adff7d1 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -506,6 +506,22 @@ static int drm_mmap_dma(struct file *fil } unlock_kernel(); + if (!capable(CAP_SYS_ADMIN) && + (dma->flags & _DRM_DMA_USE_PCI_RO)) { + vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE); +#if defined(__i386__) || defined(__x86_64__) + pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW; +#else + /* Ye gads this is ugly. With more thought + we could move this up higher and use + `protection_map' instead. */ + vma->vm_page_prot = + __pgprot(pte_val + (pte_wrprotect + (__pte(pgprot_val(vma->vm_page_prot))))); +#endif + } + vma->vm_ops = &drm_vm_dma_ops; #if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ diff --git a/shared-core/drm.h b/shared-core/drm.h index 7f90a96..8c0c5d2 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -416,7 +416,8 @@ typedef struct drm_buf_desc { _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_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 diff-tree 25760c30d4aedb370423d0bb03c014cab47b5d4f (from eea150e776657faca7d5b76aca75a33dc74fbc9d) Author: George Sapountzis <gs...@ya...> Date: Mon Aug 28 05:44:37 2006 +0300 Bug 6242: [mach64] Use private DMA buffers, part #2. Factor out from mach64_dma_dispatch_vertex() the code to reclaim an unsed buffer, in preperation for using it in mach64_dma_dispatch_blit() also. diff --git a/shared-core/mach64_dma.c b/shared-core/mach64_dma.c index 3f4394c..7cba8ad 100644 --- a/shared-core/mach64_dma.c +++ b/shared-core/mach64_dma.c @@ -1449,6 +1449,33 @@ drm_buf_t *mach64_freelist_get(drm_mach6 return entry->buf; } +int mach64_freelist_put(drm_mach64_private_t * dev_priv, drm_buf_t * copy_buf) +{ + struct list_head *ptr; + drm_mach64_freelist_t *entry; + +#if MACH64_EXTRA_CHECKING + list_for_each(ptr, &dev_priv->pending) { + entry = list_entry(ptr, drm_mach64_freelist_t, list); + if (copy_buf == entry->buf) { + DRM_ERROR("%s: Trying to release a pending buf\n", + __FUNCTION__); + return DRM_ERR(EFAULT); + } + } +#endif + ptr = dev_priv->placeholders.next; + entry = list_entry(ptr, drm_mach64_freelist_t, list); + copy_buf->pending = 0; + copy_buf->used = 0; + entry->buf = copy_buf; + entry->discard = 1; + list_del(ptr); + list_add_tail(ptr, &dev_priv->free_list); + + return 0; +} + /*@}*/ diff --git a/shared-core/mach64_drv.h b/shared-core/mach64_drv.h index 2a5f2ff..e8dc71e 100644 --- a/shared-core/mach64_drv.h +++ b/shared-core/mach64_drv.h @@ -123,6 +123,8 @@ extern void mach64_driver_lastclose(drm_ extern int mach64_init_freelist(drm_device_t * dev); extern void mach64_destroy_freelist(drm_device_t * dev); extern drm_buf_t *mach64_freelist_get(drm_mach64_private_t * dev_priv); +extern int mach64_freelist_put(drm_mach64_private_t * dev_priv, + drm_buf_t * copy_buf); extern int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv, int entries); diff --git a/shared-core/mach64_state.c b/shared-core/mach64_state.c index ce44f0d..31e3b56 100644 --- a/shared-core/mach64_state.c +++ b/shared-core/mach64_state.c @@ -546,12 +546,15 @@ static __inline__ int copy_and_verify_fr } static int mach64_dma_dispatch_vertex(DRMFILE filp, drm_device_t * dev, - int prim, void *buf, unsigned long used, - int discard) + drm_mach64_vertex_t * vertex) { drm_mach64_private_t *dev_priv = dev->dev_private; drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_buf_t *copy_buf; + void *buf = vertex->buf; + unsigned long used = vertex->used; + int ret = 0; + int i = 0; int done = 0; int verify_ret = 0; DMALOCALS; @@ -559,87 +562,65 @@ static int mach64_dma_dispatch_vertex(DR DRM_DEBUG("%s: buf=%p used=%lu nbox=%d\n", __FUNCTION__, buf, used, sarea_priv->nbox); - if (used) { - int ret = 0; - int i = 0; - - copy_buf = mach64_freelist_get(dev_priv); - if (copy_buf == NULL) { - DRM_ERROR("%s: couldn't get buffer in DMAGETPTR\n", - __FUNCTION__); - return DRM_ERR(EAGAIN); - } + if (!used) + goto _vertex_done; - if ((verify_ret = - copy_and_verify_from_user(GETBUFPTR(copy_buf), buf, - used)) == 0) { - - copy_buf->used = used; - - DMASETPTR(copy_buf); - - if (sarea_priv->dirty & ~MACH64_UPLOAD_CLIPRECTS) { - ret = mach64_emit_state(filp, dev_priv); - if (ret < 0) - return ret; - } + copy_buf = mach64_freelist_get(dev_priv); + if (copy_buf == NULL) { + DRM_ERROR("%s: couldn't get buffer\n", __FUNCTION__); + return DRM_ERR(EAGAIN); + } + + verify_ret = copy_and_verify_from_user(GETBUFPTR(copy_buf), buf, used); + + if (verify_ret != 0) { + mach64_freelist_put(dev_priv, copy_buf); + goto _vertex_done; + } - do { - /* Emit the next cliprect */ - if (i < sarea_priv->nbox) { - ret = - mach64_emit_cliprect(filp, dev_priv, - &sarea_priv-> - boxes[i]); - if (ret < 0) { - /* failed to get buffer */ - return ret; - } else if (ret != 0) { - /* null intersection with scissor */ - continue; - } - } - if ((i >= sarea_priv->nbox - 1)) - done = 1; + copy_buf->used = used; - /* Add the buffer to the DMA queue */ - DMAADVANCE(dev_priv, done); + DMASETPTR(copy_buf); - } while (++i < sarea_priv->nbox); + if (sarea_priv->dirty & ~MACH64_UPLOAD_CLIPRECTS) { + ret = mach64_emit_state(filp, dev_priv); + if (ret < 0) + return ret; + } + + do { + /* Emit the next cliprect */ + if (i < sarea_priv->nbox) { + ret = mach64_emit_cliprect(filp, dev_priv, + &sarea_priv->boxes[i]); + if (ret < 0) { + /* failed to get buffer */ + return ret; + } else if (ret != 0) { + /* null intersection with scissor */ + continue; + } } + if ((i >= sarea_priv->nbox - 1)) + done = 1; - if (copy_buf->pending && !done) { + /* Add the buffer to the DMA queue */ + DMAADVANCE(dev_priv, done); + + } while (++i < sarea_priv->nbox); + + if (!done) { + if (copy_buf->pending) { DMADISCARDBUF(); - } else if (!done) { - /* This buffer wasn't used (no cliprects or verify failed), so place it back - * on the free list + } else { + /* This buffer wasn't used (no cliprects), so place it + * back on the free list */ - struct list_head *ptr; - drm_mach64_freelist_t *entry; -#if MACH64_EXTRA_CHECKING - list_for_each(ptr, &dev_priv->pending) { - entry = - list_entry(ptr, drm_mach64_freelist_t, - list); - if (copy_buf == entry->buf) { - DRM_ERROR - ("%s: Trying to release a pending buf\n", - __FUNCTION__); - return DRM_ERR(EFAULT); - } - } -#endif - ptr = dev_priv->placeholders.next; - entry = list_entry(ptr, drm_mach64_freelist_t, list); - copy_buf->pending = 0; - copy_buf->used = 0; - entry->buf = copy_buf; - entry->discard = 1; - list_del(ptr); - list_add_tail(ptr, &dev_priv->free_list); + mach64_freelist_put(dev_priv, copy_buf); } } +_vertex_done: sarea_priv->dirty &= ~MACH64_UPLOAD_CLIPRECTS; sarea_priv->nbox = 0; @@ -842,8 +823,7 @@ int mach64_dma_vertex(DRM_IOCTL_ARGS) if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS; - return mach64_dma_dispatch_vertex(filp, dev, vertex.prim, vertex.buf, - vertex.used, vertex.discard); + return mach64_dma_dispatch_vertex(filp, dev, &vertex); } int mach64_dma_blit(DRM_IOCTL_ARGS) diff-tree eea150e776657faca7d5b76aca75a33dc74fbc9d (from d1b31a228b72b8dd8e588f0a0cc8eeabc3845f70) Author: George Sapountzis <gs...@ya...> Date: Sun Jul 16 02:15:02 2006 +0300 Bug 6242: [mach64] Use private DMA buffers, part #1. Factor out from mach64_freelist_get() the code to reclaim a completed buffer, this is to improve readability for me. diff --git a/shared-core/mach64_dma.c b/shared-core/mach64_dma.c index 36fddf0..3f4394c 100644 --- a/shared-core/mach64_dma.c +++ b/shared-core/mach64_dma.c @@ -1329,17 +1329,88 @@ int mach64_do_release_used_buffers(drm_m return 0; } +static int mach64_do_reclaim_completed(drm_mach64_private_t * dev_priv) +{ + drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; + struct list_head *ptr; + struct list_head *tmp; + drm_mach64_freelist_t *entry; + u32 head, tail, ofs; + + mach64_ring_tick(dev_priv, ring); + head = ring->head; + tail = ring->tail; + + if (head == tail) { +#if MACH64_EXTRA_CHECKING + if (MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE) { + DRM_ERROR("Empty ring with non-idle engine!\n"); + mach64_dump_ring_info(dev_priv); + return -1; + } +#endif + /* last pass is complete, so release everything */ + mach64_do_release_used_buffers(dev_priv); + DRM_DEBUG("%s: idle engine, freed all buffers.\n", + __FUNCTION__); + if (list_empty(&dev_priv->free_list)) { + DRM_ERROR("Freelist empty with idle engine\n"); + return -1; + } + return 0; + } + /* Look for a completed buffer and bail out of the loop + * as soon as we find one -- don't waste time trying + * to free extra bufs here, leave that to do_release_used_buffers + */ + list_for_each_safe(ptr, tmp, &dev_priv->pending) { + entry = list_entry(ptr, drm_mach64_freelist_t, list); + ofs = entry->ring_ofs; + if (entry->discard && + ((head < tail && (ofs < head || ofs >= tail)) || + (head > tail && (ofs < head && ofs >= tail)))) { +#if MACH64_EXTRA_CHECKING + int i; + + for (i = head; i != tail; i = (i + 4) & ring->tail_mask) + { + u32 o1 = le32_to_cpu(((u32 *) ring-> + start)[i + 1]); + u32 o2 = GETBUFADDR(entry->buf); + + if (o1 == o2) { + DRM_ERROR + ("Attempting to free used buffer: " + "i=%d buf=0x%08x\n", + i, o1); + mach64_dump_ring_info(dev_priv); + return -1; + } + } +#endif + /* found a processed buffer */ + entry->buf->pending = 0; + list_del(ptr); + list_add_tail(ptr, &dev_priv->free_list); + DRM_DEBUG + ("%s: freed processed buffer (head=%d tail=%d " + "buf ring ofs=%d).\n", + __FUNCTION__, head, tail, ofs); + return 0; + } + } + + return 1; +} + drm_buf_t *mach64_freelist_get(drm_mach64_private_t * dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; drm_mach64_freelist_t *entry; struct list_head *ptr; - struct list_head *tmp; int t; if (list_empty(&dev_priv->free_list)) { - u32 head, tail, ofs; - if (list_empty(&dev_priv->pending)) { DRM_ERROR ("Couldn't get buffer - pending and free lists empty\n"); @@ -1351,81 +1422,15 @@ drm_buf_t *mach64_freelist_get(drm_mach6 return NULL; } - tail = ring->tail; for (t = 0; t < dev_priv->usec_timeout; t++) { - mach64_ring_tick(dev_priv, ring); - head = ring->head; + int ret; - if (head == tail) { -#if MACH64_EXTRA_CHECKING - if (MACH64_READ(MACH64_GUI_STAT) & - MACH64_GUI_ACTIVE) { - DRM_ERROR - ("Empty ring with non-idle engine!\n"); - mach64_dump_ring_info(dev_priv); - return NULL; - } -#endif - /* last pass is complete, so release everything */ - mach64_do_release_used_buffers(dev_priv); - DRM_DEBUG - ("%s: idle engine, freed all buffers.\n", - __FUNCTION__); - if (list_empty(&dev_priv->free_list)) { - DRM_ERROR - ("Freelist empty with idle engine\n"); - return NULL; - } + ret = mach64_do_reclaim_completed(dev_priv); + if (ret == 0) goto _freelist_entry_found; - } - /* Look for a completed buffer and bail out of the loop - * as soon as we find one -- don't waste time trying - * to free extra bufs here, leave that to do_release_used_buffers - */ - list_for_each_safe(ptr, tmp, &dev_priv->pending) { - entry = - list_entry(ptr, drm_mach64_freelist_t, - list); - ofs = entry->ring_ofs; - if (entry->discard && - ((head < tail - && (ofs < head || ofs >= tail)) - || (head > tail - && (ofs < head && ofs >= tail)))) { -#if MACH64_EXTRA_CHECKING - int i; + if (ret < 0) + return NULL; - for (i = head; i != tail; - i = (i + 4) & ring->tail_mask) { - u32 o1 = - le32_to_cpu(((u32 *) ring-> - start)[i + 1]); - u32 o2 = GETBUFADDR(entry->buf); - - if (o1 == o2) { - DRM_ERROR - ("Attempting to free used buffer: " - "i=%d buf=0x%08x\n", - i, o1); - mach64_dump_ring_info - (dev_priv); - return NULL; - } - } -#endif - /* found a processed buffer */ - entry->buf->pending = 0; - list_del(ptr); - entry->buf->used = 0; - list_add_tail(ptr, - &dev_priv->placeholders); - DRM_DEBUG - ("%s: freed processed buffer (head=%d tail=%d " - "buf ring ofs=%d).\n", - __FUNCTION__, head, tail, ofs); - return entry->buf; - } - } DRM_UDELAY(1); } mach64_dump_ring_info(dev_priv); diff-tree d1b31a228b72b8dd8e588f0a0cc8eeabc3845f70 (from f6238cf6244b32bd84e3d2819963d7f5473867c8) Author: George Sapountzis <gs...@ya...> Date: Sun Jul 16 01:02:06 2006 +0300 Bug 6209: [mach64] AGP DMA buffers not mapped correctly. Map the DMA buffers from the same linear address as the vertex bufs. If dev->agp_buffer_token is not set, mach64 drm maps the DMA buffers from linear address 0x0. diff --git a/shared-core/mach64_dma.c b/shared-core/mach64_dma.c index 4c8edea..36fddf0 100644 --- a/shared-core/mach64_dma.c +++ b/shared-core/mach64_dma.c @@ -834,6 +834,7 @@ static int mach64_do_dma_init(drm_device mach64_do_cleanup_dma(dev); return DRM_ERR(ENOMEM); } + dev->agp_buffer_token = init->buffers_offset; dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { |
From: <th...@ke...> - 2007-04-03 08:31:52
|
linux-core/drm_bo.c | 11 +++++++++-- linux-core/drm_compat.c | 8 +++++--- linux-core/drm_fence.c | 2 +- linux-core/drm_vm.c | 4 +++- shared-core/i915_irq.c | 2 ++ 5 files changed, 20 insertions(+), 7 deletions(-) New commits: diff-tree 38d18acb8f3617d79735f71564d9f49e608461ec (from 139e4bbc73c65d6e1d7fc831ae15c8b28f92e821) Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> Date: Tue Apr 3 10:24:06 2007 +0200 Add a fence flush event to each fence-signaled check when lazy-waiting to make sure we don't lose any sequence numbers if, for some reason, they don't generate an IRQ. diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 6dd04a3..be075bb 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -301,7 +301,7 @@ static int drm_fence_lazy_wait(drm_devic do { DRM_WAIT_ON(ret, fc->fence_queue, 3 * DRM_HZ, - fence_signaled(dev, fence, mask, 0)); + fence_signaled(dev, fence, mask, 1)); if (time_after_eq(jiffies, _end)) break; } while (ret == -EINTR && ignore_signals); diff-tree 139e4bbc73c65d6e1d7fc831ae15c8b28f92e821 (from 7743af94492681f5aaf7cfdef78d695a6db7cbd0) Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> Date: Tue Apr 3 10:21:41 2007 +0200 Make sure we ack irqs before we read a breadcrumb so that breadcrumb updates that occur _AFTER_ we've read the breadcrumb really generates a new IRQ. diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 5da5410..4047e77 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -294,6 +294,8 @@ irqreturn_t i915_driver_irq_handler(DRM_ return IRQ_NONE; I915_WRITE16(I915REG_INT_IDENTITY_R, temp); + (void) I915_READ16(I915REG_INT_IDENTITY_R); + DRM_READMEMORYBARRIER(); dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); diff-tree 7743af94492681f5aaf7cfdef78d695a6db7cbd0 (from d85e243259259d7702db0d344ae1ff7d26598227) Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> Date: Fri Mar 30 14:14:26 2007 +0200 Evicted no-move buffers can get lost if they end up in another memory type than local. diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index cea6ef6..17d6fbc 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -75,7 +75,8 @@ void drm_bo_add_to_lru(drm_buffer_object { drm_mem_type_manager_t *man; - if (!(bo->mem.mask & (DRM_BO_FLAG_NO_MOVE | DRM_BO_FLAG_NO_EVICT))) { + if (!(bo->mem.mask & (DRM_BO_FLAG_NO_MOVE | DRM_BO_FLAG_NO_EVICT)) + || bo->mem.mem_type != bo->pinned_mem_type) { man = &bo->dev->bm.man[bo->mem.mem_type]; list_add_tail(&bo->lru, &man->lru); } else { diff-tree d85e243259259d7702db0d344ae1ff7d26598227 (from 72d457fc1973a61f906a42d049c1c160cc7dee4e) Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> Date: Fri Mar 30 12:23:22 2007 +0200 Fix an oops when trying to clean a not yet initialized memory type. diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 1bdc6fe..cea6ef6 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1991,10 +1991,16 @@ static int drm_bo_lock_mm(drm_device_t * drm_mem_type_manager_t *man = &bm->man[mem_type]; if (mem_type == 0 || mem_type >= DRM_BO_MEM_TYPES) { - DRM_ERROR("Illegal memory manager memory type %u,\n", mem_type); + DRM_ERROR("Illegal memory manager memory type %u.\n", mem_type); return -EINVAL; } + if (!man->has_type) { + DRM_ERROR("Memory type %u has not been initialized.\n", + mem_type); + return 0; + } + drm_bo_clean_unfenced(dev); ret = drm_bo_force_list_clean(dev, &man->lru, mem_type, 0, 1, 0); if (ret) diff-tree 72d457fc1973a61f906a42d049c1c160cc7dee4e (from 5395a92d40337aa3de424f87fb38cb5a0ca45bcf) Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> Date: Thu Mar 29 21:33:41 2007 +0200 Make sure CMA (Can't map aperture) pages are mapped uncached. (Should really make this write-combined using PATs, at some point). diff --git a/linux-core/drm_compat.c b/linux-core/drm_compat.c index 2344181..9ac5658 100644 --- a/linux-core/drm_compat.c +++ b/linux-core/drm_compat.c @@ -275,12 +275,14 @@ static struct page *drm_bo_vm_fault(stru goto out_unlock; } pfn = page_to_pfn(page); - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + vma->vm_page_prot = (bo->mem.flags & DRM_BO_FLAG_CACHED) ? + vm_get_page_prot(vma->vm_flags) : + drm_io_prot(_DRM_TTM, vma); } - + err = vm_insert_pfn(vma, address, pfn); - if (!err || err == -EBUSY) + if (!err || err == -EBUSY) data->type = VM_FAULT_MINOR; else data->type = VM_FAULT_OOM; diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 54a0849..1f905fb 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -796,7 +796,9 @@ static unsigned long drm_bo_vm_nopfn(str goto out_unlock; } pfn = page_to_pfn(page); - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + vma->vm_page_prot = (bo->mem.flags & DRM_BO_FLAG_CACHED) ? + vm_get_page_prot(vma->vm_flags) : + drm_io_prot(_DRM_TTM, vma); } err = vm_insert_pfn(vma, address, pfn); |
From: <dar...@ke...> - 2007-08-15 04:33:47
|
linux-core/nouveau_sgdma.c | 17 +++++++++++++++++ shared-core/nouveau_drv.h | 2 ++ shared-core/nouveau_mem.c | 4 ++-- shared-core/nouveau_notifier.c | 34 +++++++++++++++++++++++----------- shared-core/nv04_instmem.c | 15 ++++++++++----- 5 files changed, 54 insertions(+), 18 deletions(-) New commits: diff-tree 10f9b7bd0b471487371813083bd3481629b2a56f (from a615d2fde77092062f7e2bbfa39705b5f34547e8) Author: Ben Skeggs <sk...@gm...> Date: Wed Aug 15 14:14:23 2007 +1000 nouveau: Use count parameter in nouveau_notifier_alloc(). diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 91f605e..71b8cbe 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -45,11 +45,12 @@ nouveau_notifier_init_channel(struct nou flags = NOUVEAU_MEM_FB; flags |= (NOUVEAU_MEM_MAPPED | NOUVEAU_MEM_FB_ACCEPTABLE); - DRM_DEBUG("Allocating notifier block in %d\n", flags); chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags, (struct drm_file *)-2); if (!chan->notifier_block) return -ENOMEM; + DRM_DEBUG("Allocated notifier block in 0x%08x\n", + chan->notifier_block->flags); ret = nouveau_mem_init_heap(&chan->notifier_heap, 0, chan->notifier_block->size); @@ -99,7 +100,7 @@ nouveau_notifier_alloc(struct nouveau_ch return -EINVAL; } - mem = nouveau_mem_alloc_block(chan->notifier_heap, 32, 0, + mem = nouveau_mem_alloc_block(chan->notifier_heap, count*32, 0, (struct drm_file *)-2); if (!mem) { DRM_ERROR("Channel %d notifier block full\n", chan->id); diff-tree a615d2fde77092062f7e2bbfa39705b5f34547e8 (from c3faa589b09616acdfd827be1719f6c2706c49ab) Author: Ben Skeggs <sk...@gm...> Date: Wed Aug 15 13:53:58 2007 +1000 nouveau: Turn some messages into DRM_DEBUGs.. diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c index 419522f..92fa6b0 100644 --- a/shared-core/nouveau_mem.c +++ b/shared-core/nouveau_mem.c @@ -531,13 +531,13 @@ alloc_ok: block->map_handle = entry->user_token; } - DRM_INFO("allocated 0x%llx\n", block->start); + DRM_DEBUG("allocated 0x%llx type=0x%08x\n", block->start, block->flags); return block; } void nouveau_mem_free(struct drm_device* dev, struct mem_block* block) { - DRM_INFO("freeing 0x%llx\n", block->start); + DRM_DEBUG("freeing 0x%llx type=0x%08x\n", block->start, block->flags); if (block->flags&NOUVEAU_MEM_MAPPED) drm_rmmap(dev, block->map); nouveau_mem_free_block(block); diff-tree c3faa589b09616acdfd827be1719f6c2706c49ab (from ee01d3755ac03f2c47e3b4d9bf084d68e6ee95bc) Author: Ben Skeggs <sk...@gm...> Date: Wed Aug 15 13:36:54 2007 +1000 nouveau: Allow GART notifiers when using sgdma code. diff --git a/linux-core/nouveau_sgdma.c b/linux-core/nouveau_sgdma.c index df970d1..97d5330 100644 --- a/linux-core/nouveau_sgdma.c +++ b/linux-core/nouveau_sgdma.c @@ -316,3 +316,20 @@ nouveau_sgdma_nottm_hack_takedown(struct { } +int +nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; + int pte; + + pte = (offset >> NV_CTXDMA_PAGE_SHIFT); + if (dev_priv->card_type < NV_50) { + *page = INSTANCE_RD(gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK; + return 0; + } + + DRM_ERROR("Unimplemented on NV50\n"); + return -EINVAL; +} + diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index b7459b1..e96c8fa 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -421,6 +421,8 @@ extern void nouveau_irq_uninstall /* nouveau_sgdma.c */ extern int nouveau_sgdma_init(struct drm_device *); extern void nouveau_sgdma_takedown(struct drm_device *); +extern int nouveau_sgdma_get_page(struct drm_device *, uint32_t offset, + uint32_t *page); extern struct drm_ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *); extern int nouveau_sgdma_nottm_hack_init(struct drm_device *); extern void nouveau_sgdma_nottm_hack_takedown(struct drm_device *); diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 31547aa..91f605e 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -37,14 +37,13 @@ nouveau_notifier_init_channel(struct nou int flags, ret; /*TODO: PCI notifier blocks */ - if (dev_priv->agp_heap && - dev_priv->gart_info.type != NOUVEAU_GART_SGDMA) - flags = NOUVEAU_MEM_AGP | NOUVEAU_MEM_FB_ACCEPTABLE; - else if ( dev_priv->pci_heap ) + if (dev_priv->agp_heap) + flags = NOUVEAU_MEM_AGP; + else if (dev_priv->pci_heap) flags = NOUVEAU_MEM_PCI; else flags = NOUVEAU_MEM_FB; - flags |= NOUVEAU_MEM_MAPPED; + flags |= (NOUVEAU_MEM_MAPPED | NOUVEAU_MEM_FB_ACCEPTABLE); DRM_DEBUG("Allocating notifier block in %d\n", flags); chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags, @@ -88,6 +87,7 @@ nouveau_notifier_alloc(struct nouveau_ch int count, uint32_t *b_offset) { struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *nobj = NULL; struct mem_block *mem; uint32_t offset; @@ -107,18 +107,29 @@ nouveau_notifier_alloc(struct nouveau_ch } mem->flags = NOUVEAU_MEM_NOTIFIER; - offset = chan->notifier_block->start + mem->start; + offset = chan->notifier_block->start; if (chan->notifier_block->flags & NOUVEAU_MEM_FB) { target = NV_DMA_TARGET_VIDMEM; - } else if (chan->notifier_block->flags & NOUVEAU_MEM_AGP) { - target = NV_DMA_TARGET_AGP; - } else if (chan->notifier_block->flags & NOUVEAU_MEM_PCI) { + } else + if (chan->notifier_block->flags & NOUVEAU_MEM_AGP) { + if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA && + dev_priv->card_type < NV_50) { + ret = nouveau_sgdma_get_page(dev, offset, &offset); + if (ret) + return ret; + target = NV_DMA_TARGET_PCI; + } else { + target = NV_DMA_TARGET_AGP; + } + } else + if (chan->notifier_block->flags & NOUVEAU_MEM_PCI) { target = NV_DMA_TARGET_PCI_NONLINEAR; } else { DRM_ERROR("Bad DMA target, flags 0x%08x!\n", chan->notifier_block->flags); return -EINVAL; } + offset += mem->start; if ((ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset, mem->size, diff-tree ee01d3755ac03f2c47e3b4d9bf084d68e6ee95bc (from a6ea60c77e8d4a266d696e0d99c11b1f39578dcc) Author: Ben Skeggs <sk...@gm...> Date: Wed Aug 15 13:34:57 2007 +1000 nouveau: Workaround mysterious PRAMIN clobbering by the card. diff --git a/shared-core/nv04_instmem.c b/shared-core/nv04_instmem.c index b5569b5..fed6ff7 100644 --- a/shared-core/nv04_instmem.c +++ b/shared-core/nv04_instmem.c @@ -94,6 +94,14 @@ int nv04_instmem_init(struct drm_device * the space that was reserved for RAMHT/FC/RO. */ offset = dev_priv->ramfc_offset + dev_priv->ramfc_size; + + /* On my NV4E, there's *something* clobbering the 16KiB just after + * where we setup these fixed tables. No idea what it is just yet, + * so reserve this space on all NV4X cards for now. + */ + if (dev_priv->card_type >= NV_40) + offset += 16*1024; + ret = nouveau_mem_init_heap(&dev_priv->ramin_heap, offset, dev_priv->ramin_rsvd_vram - offset); if (ret) { diff-tree a6ea60c77e8d4a266d696e0d99c11b1f39578dcc (from 02c4e0e757b69cd6ae38b8ab2c078b3f06fea661) Author: Ben Skeggs <sk...@gm...> Date: Wed Aug 15 01:40:46 2007 +1000 nouveau: Catch all NV4x chips instead of just NV_40. diff --git a/shared-core/nv04_instmem.c b/shared-core/nv04_instmem.c index 5e0f6f4..b5569b5 100644 --- a/shared-core/nv04_instmem.c +++ b/shared-core/nv04_instmem.c @@ -9,21 +9,18 @@ nv04_instmem_determine_amount(struct drm int i; /* Figure out how much instance memory we need */ - switch (dev_priv->card_type) { - case NV_40: + if (dev_priv->card_type >= NV_40) { /* We'll want more instance memory than this on some NV4x cards. * There's a 16MB aperture to play with that maps onto the end * of vram. For now, only reserve a small piece until we know * more about what each chipset requires. */ dev_priv->ramin_rsvd_vram = (1*1024* 1024); - break; - default: + } else { /*XXX: what *are* the limits on <NV40 cards?, and does RAMIN * exist in vram on those cards as well? */ dev_priv->ramin_rsvd_vram = (512*1024); - break; } DRM_DEBUG("RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram>>10); |
From: <an...@ke...> - 2007-08-15 18:07:32
|
.gitignore | 2 + bsd-core/ati_pcigart.c | 8 ++-- bsd-core/drm_agpsupport.c | 8 ++-- bsd-core/drm_auth.c | 8 ++-- bsd-core/drm_bufs.c | 7 ++- bsd-core/drm_context.c | 7 ++- bsd-core/drm_dma.c | 11 ++++-- bsd-core/drm_drawable.c | 8 ++-- bsd-core/drm_drv.c | 9 +++- bsd-core/drm_fops.c | 8 ++-- bsd-core/drm_ioctl.c | 46 ++++++++++++++----------- bsd-core/drm_irq.c | 8 ++-- bsd-core/drm_lock.c | 22 ++++++++++-- bsd-core/drm_memory.c | 11 ++++-- bsd-core/drm_pci.c | 14 +++---- bsd-core/drm_scatter.c | 9 +++- bsd-core/drm_sysctl.c | 5 ++ bsd-core/drm_vm.c | 4 ++ tests/Makefile.am | 2 + tests/getstats.c | 51 +++++++++++++++++++++++++++ tests/setversion.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++ 21 files changed, 267 insertions(+), 65 deletions(-) New commits: diff-tree 4cdd871e90cd5fe440d0a4af5d69f1d84e49e742 (from 56133e04de40e3004018d069cb229e62ee10e0f4) Author: vehemens <veh...@ve...> Date: Wed Aug 15 11:05:44 2007 -0700 Bug #11989: Fix regression in getstats ioctl (kernel panic). diff --git a/bsd-core/drm_ioctl.c b/bsd-core/drm_ioctl.c index d6af428..ce78bb8 100644 --- a/bsd-core/drm_ioctl.c +++ b/bsd-core/drm_ioctl.c @@ -205,7 +205,7 @@ int drm_getstats(drm_device_t *dev, void drm_stats_t *stats = data; int i; - memset(&stats, 0, sizeof(stats)); + memset(stats, 0, sizeof(drm_stats_t)); DRM_LOCK(); diff-tree 56133e04de40e3004018d069cb229e62ee10e0f4 (from a23a47b16cf813f0e7e9616ef6eb66f6ae0bc2ac) Author: Eric Anholt <er...@an...> Date: Wed Aug 15 11:04:56 2007 -0700 BSD: Fix regression in setversion ioctl (current version not returned). diff --git a/bsd-core/drm_ioctl.c b/bsd-core/drm_ioctl.c index 328f1d1..d6af428 100644 --- a/bsd-core/drm_ioctl.c +++ b/bsd-core/drm_ioctl.c @@ -232,23 +232,27 @@ int drm_getstats(drm_device_t *dev, void int drm_setversion(drm_device_t *dev, void *data, struct drm_file *file_priv) { drm_set_version_t *sv = data; - drm_set_version_t retv; + drm_set_version_t ver; int if_version; - retv.drm_di_major = DRM_IF_MAJOR; - retv.drm_di_minor = DRM_IF_MINOR; - retv.drm_dd_major = dev->driver.major; - retv.drm_dd_minor = dev->driver.minor; - - if (sv->drm_di_major != -1) { - if (sv->drm_di_major != DRM_IF_MAJOR || - sv->drm_di_minor < 0 || sv->drm_di_minor > DRM_IF_MINOR) { + /* Save the incoming data, and set the response before continuing + * any further. + */ + ver = *sv; + sv->drm_di_major = DRM_IF_MAJOR; + sv->drm_di_minor = DRM_IF_MINOR; + sv->drm_dd_major = dev->driver.major; + sv->drm_dd_minor = dev->driver.minor; + + if (ver.drm_di_major != -1) { + if (ver.drm_di_major != DRM_IF_MAJOR || + ver.drm_di_minor < 0 || ver.drm_di_minor > DRM_IF_MINOR) { return EINVAL; } - if_version = DRM_IF_VERSION(sv->drm_di_major, - sv->drm_dd_minor); + if_version = DRM_IF_VERSION(ver.drm_di_major, + ver.drm_dd_minor); dev->if_version = DRM_MAX(if_version, dev->if_version); - if (sv->drm_di_minor >= 1) { + if (ver.drm_di_minor >= 1) { /* * Version 1.1 includes tying of DRM to specific device */ @@ -256,10 +260,10 @@ int drm_setversion(drm_device_t *dev, vo } } - if (sv->drm_dd_major != -1) { - if (sv->drm_dd_major != dev->driver.major || - sv->drm_dd_minor < 0 || - sv->drm_dd_minor > dev->driver.minor) + if (ver.drm_dd_major != -1) { + if (ver.drm_dd_major != dev->driver.major || + ver.drm_dd_minor < 0 || + ver.drm_dd_minor > dev->driver.minor) { return EINVAL; } diff-tree a23a47b16cf813f0e7e9616ef6eb66f6ae0bc2ac (from 8a881b47f7c21be2cdeff4b0d1b00d39d503f358) Author: Eric Anholt <er...@an...> Date: Wed Aug 15 11:03:10 2007 -0700 Add a regression test for the setversion interface. diff --git a/.gitignore b/.gitignore index 47c7d4a..8ae98e8 100644 --- a/.gitignore +++ b/.gitignore @@ -58,4 +58,5 @@ tests/getclient tests/getstats tests/getversion tests/openclose +tests/setversion tests/updatedraw diff --git a/tests/Makefile.am b/tests/Makefile.am index b5f8c04..acd12b3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -20,6 +20,7 @@ TESTS = auth \ getversion \ getclient \ getstats \ + setversion \ updatedraw EXTRA_PROGRAMS = $(TESTS) diff --git a/tests/setversion.c b/tests/setversion.c new file mode 100644 index 0000000..dc6eccf --- /dev/null +++ b/tests/setversion.c @@ -0,0 +1,84 @@ +/* + * Copyright © 2007 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 (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. + * + * Authors: + * Eric Anholt <er...@an...> + * + */ + +#include <limits.h> +#include "drmtest.h" + +/** + * Checks DRM_IOCTL_SET_VERSION. + * + * This tests that we can get the actual version out, and that setting invalid + * major/minor numbers fails appropriately. It does not check the actual + * behavior differenses resulting from an increased DI version. + */ +int main(int argc, char **argv) +{ + int fd, ret; + drm_set_version_t sv, version; + + fd = drm_open_any(); + + /* First, check that we can get the DD/DI versions. */ + memset(&version, 0, sizeof(version)); + version.drm_di_major = -1; + version.drm_di_minor = -1; + version.drm_dd_major = -1; + version.drm_dd_minor = -1; + ret = ioctl(fd, DRM_IOCTL_SET_VERSION, &version); + assert(ret == 0); + assert(version.drm_di_major != -1); + assert(version.drm_di_minor != -1); + assert(version.drm_dd_major != -1); + assert(version.drm_dd_minor != -1); + + /* Check that an invalid DI major fails */ + sv = version; + sv.drm_di_major++; + ret = ioctl(fd, DRM_IOCTL_SET_VERSION, &sv); + assert(ret == -1 && errno == EINVAL); + + /* Check that an invalid DI minor fails */ + sv = version; + sv.drm_di_major++; + ret = ioctl(fd, DRM_IOCTL_SET_VERSION, &sv); + assert(ret == -1 && errno == EINVAL); + + /* Check that an invalid DD major fails */ + sv = version; + sv.drm_dd_major++; + ret = ioctl(fd, DRM_IOCTL_SET_VERSION, &sv); + assert(ret == -1 && errno == EINVAL); + + /* Check that an invalid DD minor fails */ + sv = version; + sv.drm_dd_minor++; + ret = ioctl(fd, DRM_IOCTL_SET_VERSION, &sv); + assert(ret == -1 && errno == EINVAL); + + close(fd); + return 0; +} diff-tree 8a881b47f7c21be2cdeff4b0d1b00d39d503f358 (from 5346fc5f36b5e7c55fc7b5cd46f1e4d7563a86a4) Author: Eric Anholt <er...@an...> Date: Wed Aug 15 10:52:01 2007 -0700 Add simple regression test for getstats (does it not crash the kernel?). diff --git a/.gitignore b/.gitignore index f63c153..47c7d4a 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,7 @@ tests/auth tests/dristat tests/drmstat tests/getclient +tests/getstats tests/getversion tests/openclose tests/updatedraw diff --git a/tests/Makefile.am b/tests/Makefile.am index e846efb..b5f8c04 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -19,6 +19,7 @@ TESTS = auth \ openclose \ getversion \ getclient \ + getstats \ updatedraw EXTRA_PROGRAMS = $(TESTS) diff --git a/tests/getstats.c b/tests/getstats.c new file mode 100644 index 0000000..bd55b12 --- /dev/null +++ b/tests/getstats.c @@ -0,0 +1,51 @@ +/* + * Copyright © 2007 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 (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. + * + * Authors: + * Eric Anholt <er...@an...> + * + */ + +#include <limits.h> +#include "drmtest.h" + +/** + * Checks DRM_IOCTL_GET_STATS. + * + * I don't care too much about the actual contents, just that the kernel + * doesn't crash. + */ +int main(int argc, char **argv) +{ + int fd, ret; + drm_stats_t stats; + + fd = drm_open_any(); + + ret = ioctl(fd, DRM_IOCTL_GET_STATS, &stats); + assert(ret == 0); + + assert(stats.count >= 0); + + close(fd); + return 0; +} diff-tree 5346fc5f36b5e7c55fc7b5cd46f1e4d7563a86a4 (from 10f9b7bd0b471487371813083bd3481629b2a56f) Author: Eric Anholt <er...@an...> Date: Tue Aug 14 14:41:24 2007 -0700 BSD: Replace brief description in each file's first line with doxygen later on. The brief descriptions usually had the wrong filename in them. diff --git a/bsd-core/ati_pcigart.c b/bsd-core/ati_pcigart.c index 682eace..db19a75 100644 --- a/bsd-core/ati_pcigart.c +++ b/bsd-core/ati_pcigart.c @@ -1,6 +1,3 @@ -/* ati_pcigart.h -- ATI PCI GART support -*- linux-c -*- - * Created: Wed Dec 13 21:52:19 2000 by ga...@va... - */ /*- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. @@ -29,6 +26,11 @@ * */ +/** @file ati_pcigart.c + * Implementation of ATI's PCIGART, which provides an aperture in card virtual + * address space with addresses remapped to system memory. + */ + #include "drmP.h" #define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */ diff --git a/bsd-core/drm_agpsupport.c b/bsd-core/drm_agpsupport.c index e8e162d..9aed557 100644 --- a/bsd-core/drm_agpsupport.c +++ b/bsd-core/drm_agpsupport.c @@ -1,6 +1,3 @@ -/* drm_agpsupport.h -- DRM support for AGP/GART backend -*- linux-c -*- - * Created: Mon Dec 13 09:56:45 1999 by fa...@pr... - */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. @@ -31,6 +28,11 @@ * */ +/** @file drm_agpsupport.c + * Support code for tying the kernel AGP support to DRM drivers and + * the DRM's AGP ioctls. + */ + #include "drmP.h" #ifdef __FreeBSD__ diff --git a/bsd-core/drm_auth.c b/bsd-core/drm_auth.c index 9b5f4f7..aa8238c 100644 --- a/bsd-core/drm_auth.c +++ b/bsd-core/drm_auth.c @@ -1,6 +1,3 @@ -/* drm_auth.c -- IOCTLs for authentication -*- linux-c -*- - * Created: Tue Feb 2 08:37:54 1999 by fa...@va... - */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. @@ -31,6 +28,11 @@ * */ +/** @file drm_auth.c + * Implementation of the get/authmagic ioctls implementing the authentication + * scheme between the master and clients. + */ + #include "drmP.h" static int drm_hash_magic(drm_magic_t magic) diff --git a/bsd-core/drm_bufs.c b/bsd-core/drm_bufs.c index a0a3fc7..65d8c82 100644 --- a/bsd-core/drm_bufs.c +++ b/bsd-core/drm_bufs.c @@ -1,6 +1,3 @@ -/* drm_bufs.h -- Generic buffer template -*- linux-c -*- - * Created: Thu Nov 23 03:10:50 2000 by ga...@va... - */ /*- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. @@ -31,6 +28,10 @@ * */ +/** @file drm_bufs.c + * Implementation of the ioctls for setup of DRM mappings and DMA buffers. + */ + #include "dev/pci/pcireg.h" #include "drmP.h" diff --git a/bsd-core/drm_context.c b/bsd-core/drm_context.c index e34e875..4155ee9 100644 --- a/bsd-core/drm_context.c +++ b/bsd-core/drm_context.c @@ -1,6 +1,3 @@ -/* drm_context.h -- IOCTLs for generic contexts -*- linux-c -*- - * Created: Fri Nov 24 18:31:37 2000 by ga...@va... - */ /*- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. @@ -31,6 +28,10 @@ * */ +/** @file drm_context.c + * Implementation of the context management ioctls. + */ + #include "drmP.h" /* ================================================================ diff --git a/bsd-core/drm_dma.c b/bsd-core/drm_dma.c index 4896cf2..71ef845 100644 --- a/bsd-core/drm_dma.c +++ b/bsd-core/drm_dma.c @@ -1,6 +1,3 @@ -/* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*- - * Created: Fri Mar 19 14:30:16 1999 by fa...@va... - */ /*- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. @@ -31,6 +28,14 @@ * */ +/** @file drm_dma.c + * Support code for DMA buffer management. + * + * The implementation used to be significantly more complicated, but the + * complexity has been moved into the drivers as different buffer management + * schemes evolved. + */ + #include "drmP.h" int drm_dma_setup(drm_device_t *dev) diff --git a/bsd-core/drm_drawable.c b/bsd-core/drm_drawable.c index 7e038ab..fb318d4 100644 --- a/bsd-core/drm_drawable.c +++ b/bsd-core/drm_drawable.c @@ -1,6 +1,3 @@ -/* drm_drawable.h -- IOCTLs for drawables -*- linux-c -*- - * Created: Tue Feb 2 08:37:54 1999 by fa...@va... - */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. @@ -31,6 +28,11 @@ * */ +/** @file drm_drawable.c + * This file implements ioctls to store information along with DRM drawables, + * such as the current set of cliprects for vblank-synced buffer swaps. + */ + #include "drmP.h" struct bsd_drm_drawable_info { diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c index a978f50..208f438 100644 --- a/bsd-core/drm_drv.c +++ b/bsd-core/drm_drv.c @@ -1,6 +1,3 @@ -/* drm_drv.h -- Generic driver template -*- linux-c -*- - * Created: Thu Nov 23 03:10:50 2000 by ga...@va... - */ /*- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. @@ -31,6 +28,12 @@ * */ +/** @file drm_drv.c + * The catch-all file for DRM device support, including module setup/teardown, + * open/close, and ioctl dispatch. + */ + + #include <sys/limits.h> #include "drmP.h" #include "drm.h" diff --git a/bsd-core/drm_fops.c b/bsd-core/drm_fops.c index 2d037ea..20bae8d 100644 --- a/bsd-core/drm_fops.c +++ b/bsd-core/drm_fops.c @@ -1,6 +1,3 @@ -/* drm_fops.h -- File operations for DRM -*- linux-c -*- - * Created: Mon Jan 4 08:58:31 1999 by fa...@va... - */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. @@ -32,6 +29,11 @@ * */ +/** @file drm_fops.c + * Support code for dealing with the file privates associated with each + * open of the DRM device. + */ + #include "drmP.h" drm_file_t *drm_find_file_by_proc(drm_device_t *dev, DRM_STRUCTPROC *p) diff --git a/bsd-core/drm_ioctl.c b/bsd-core/drm_ioctl.c index ebdb214..328f1d1 100644 --- a/bsd-core/drm_ioctl.c +++ b/bsd-core/drm_ioctl.c @@ -1,6 +1,3 @@ -/* drm_ioctl.h -- IOCTL processing for DRM -*- linux-c -*- - * Created: Fri Jan 8 09:01:26 1999 by fa...@va... - */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. @@ -31,6 +28,11 @@ * */ +/** @file drm_ioctl.c + * Varios minor DRM ioctls not applicable to other files, such as versioning + * information and reporting DRM information to userland. + */ + #include "drmP.h" /* diff --git a/bsd-core/drm_irq.c b/bsd-core/drm_irq.c index 9c437e9..0772445 100644 --- a/bsd-core/drm_irq.c +++ b/bsd-core/drm_irq.c @@ -1,6 +1,3 @@ -/* drm_irq.c -- IRQ IOCTL and function support - * Created: Fri Oct 18 2003 by anholt@FreeBSD.org - */ /*- * Copyright 2003 Eric Anholt * All Rights Reserved. @@ -28,6 +25,11 @@ * */ +/** @file drm_irq.c + * Support code for handling setup/teardown of interrupt handlers and + * handing interrupt handlers off to the drivers. + */ + #include "drmP.h" #include "drm.h" diff --git a/bsd-core/drm_lock.c b/bsd-core/drm_lock.c index 5acb13d..326c083 100644 --- a/bsd-core/drm_lock.c +++ b/bsd-core/drm_lock.c @@ -1,6 +1,3 @@ -/* lock.c -- IOCTLs for locking -*- linux-c -*- - * Created: Tue Feb 2 08:37:54 1999 by fa...@va... - */ /*- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. @@ -31,6 +28,25 @@ * */ +/** @file drm_lock.c + * Implementation of the ioctls and other support code for dealing with the + * hardware lock. + * + * The DRM hardware lock is a shared structure between the kernel and userland. + * + * On uncontended access where the new context was the last context, the + * client may take the lock without dropping down into the kernel, using atomic + * compare-and-set. + * + * If the client finds during compare-and-set that it was not the last owner + * of the lock, it calls the DRM lock ioctl, which may sleep waiting for the + * lock, and may have side-effects of kernel-managed context switching. + * + * When the client releases the lock, if the lock is marked as being contended + * by another client, then the DRM unlock ioctl is called so that the + * contending client may be woken up. + */ + #include "drmP.h" int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context) diff --git a/bsd-core/drm_memory.c b/bsd-core/drm_memory.c index 6d467e9..1f1f7f4 100644 --- a/bsd-core/drm_memory.c +++ b/bsd-core/drm_memory.c @@ -1,6 +1,3 @@ -/* drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*- - * Created: Thu Feb 4 14:00:34 1999 by fa...@va... - */ /*- *Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. @@ -31,6 +28,14 @@ * */ +/** @file drm_memory.c + * Wrappers for kernel memory allocation routines, and MTRR management support. + * + * This file previously implemented a memory consumption tracking system using + * the "area" argument for various different types of allocations, but that + * has been stripped out for now. + */ + #include "drmP.h" MALLOC_DEFINE(M_DRM, "drm", "DRM Data Structures"); diff --git a/bsd-core/drm_pci.c b/bsd-core/drm_pci.c index a33f5f9..6ec6b98 100644 --- a/bsd-core/drm_pci.c +++ b/bsd-core/drm_pci.c @@ -1,10 +1,3 @@ -/** - * \file drm_pci.h - * \brief PCI consistent, DMA-accessible memory functions. - * - * \author Eric Anholt <anholt@FreeBSD.org> - */ - /*- * Copyright 2003 Eric Anholt. * All Rights Reserved. @@ -28,6 +21,13 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/** + * \file drm_pci.h + * \brief PCI consistent, DMA-accessible memory allocation. + * + * \author Eric Anholt <anholt@FreeBSD.org> + */ + #include "drmP.h" /**********************************************************************/ diff --git a/bsd-core/drm_scatter.c b/bsd-core/drm_scatter.c index 91c3c6c..92e715e 100644 --- a/bsd-core/drm_scatter.c +++ b/bsd-core/drm_scatter.c @@ -1,5 +1,3 @@ -/* drm_scatter.h -- IOCTLs to manage scatter/gather memory -*- linux-c -*- - * Created: Mon Dec 18 23:20:54 2000 by ga...@va... */ /*- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. @@ -29,6 +27,13 @@ * */ +/** @file drm_scatter.c + * Allocation of memory for scatter-gather mappings by the graphics chip. + * + * The memory allocated here is then made into an aperture in the card + * by drm_ati_pcigart_init(). + */ + #include "drmP.h" #define DEBUG_SCATTER 0 diff --git a/bsd-core/drm_sysctl.c b/bsd-core/drm_sysctl.c index b2d0cc0..3de5b8a 100644 --- a/bsd-core/drm_sysctl.c +++ b/bsd-core/drm_sysctl.c @@ -21,6 +21,11 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/** @file drm_sysctl.c + * Implementation of various sysctls for controlling DRM behavior and reporting + * debug information. + */ + #include "drmP.h" #include "drm.h" diff --git a/bsd-core/drm_vm.c b/bsd-core/drm_vm.c index af1dbaa..fea31f5 100644 --- a/bsd-core/drm_vm.c +++ b/bsd-core/drm_vm.c @@ -21,6 +21,10 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/** @file drm_vm.c + * Support code for mmaping of DRM maps. + */ + #include "drmP.h" #include "drm.h" |
From: <an...@ke...> - 2007-08-15 21:15:57
|
.gitignore | 1 bsd-core/drm_drv.c | 21 +--- bsd-core/drm_lock.c | 6 + tests/Makefile.am | 1 tests/auth.c | 2 tests/lock.c | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/setversion.c | 2 7 files changed, 278 insertions(+), 17 deletions(-) New commits: diff-tree 6e93c35ba7c5001e756d0c9d1a4f534384652a5a (from 9254e00e4bbbc02282415cd0ca7bd6b5cb52be82) Author: Eric Anholt <er...@an...> Date: Wed Aug 15 13:42:04 2007 -0700 BSD: Return EINVAL if drm_unlock is called on an unheld or other-owner lock. diff --git a/bsd-core/drm_lock.c b/bsd-core/drm_lock.c index 326c083..fb86fc6 100644 --- a/bsd-core/drm_lock.c +++ b/bsd-core/drm_lock.c @@ -173,6 +173,12 @@ int drm_unlock(drm_device_t *dev, void * DRM_CURRENTPID, lock->context); return EINVAL; } + /* Check that the context unlock being requested actually matches + * who currently holds the lock. + */ + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) != lock->context) + return EINVAL; atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); diff-tree 9254e00e4bbbc02282415cd0ca7bd6b5cb52be82 (from 8a1ca401b403848d894f664977f9e939eaf07291) Author: Eric Anholt <er...@an...> Date: Wed Aug 15 13:41:24 2007 -0700 Add a set of tests for DRM locking, exposing issues on BSD. diff --git a/.gitignore b/.gitignore index 8ae98e8..0991da8 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,7 @@ tests/drmstat tests/getclient tests/getstats tests/getversion +tests/lock tests/openclose tests/setversion tests/updatedraw diff --git a/tests/Makefile.am b/tests/Makefile.am index acd12b3..dce1754 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -20,6 +20,7 @@ TESTS = auth \ getversion \ getclient \ getstats \ + lock \ setversion \ updatedraw diff --git a/tests/lock.c b/tests/lock.c new file mode 100644 index 0000000..3f62755 --- /dev/null +++ b/tests/lock.c @@ -0,0 +1,262 @@ +/* + * Copyright © 2007 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 (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. + * + * Authors: + * Eric Anholt <er...@an...> + * + */ + +/** @file lock.c + * Tests various potential failures of the DRM locking mechanisms + */ + +#include <limits.h> +#include "drmtest.h" + +enum auth_event { + SERVER_READY, + CLIENT_MAGIC, + SERVER_LOCKED, + CLIENT_LOCKED, +}; + +int commfd[2]; +unsigned int lock1 = 0x00001111; +unsigned int lock2 = 0x00002222; + +/* return time in milliseconds */ +static unsigned int +get_millis() +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +static void +wait_event(int pipe, enum auth_event expected_event) +{ + int ret; + enum auth_event event; + unsigned char in; + + ret = read(commfd[pipe], &in, 1); + if (ret == -1) + err(1, "read error"); + event = in; + + if (event != expected_event) + errx(1, "unexpected event: %d\n", event); +} + +static void +send_event(int pipe, enum auth_event send_event) +{ + int ret; + unsigned char event; + + event = send_event; + ret = write(commfd[pipe], &event, 1); + if (ret == -1) + err(1, "failed to send event %d", event); +} + +static void +client_auth(int drmfd) +{ + struct drm_auth auth; + int ret; + + wait_event(0, SERVER_READY); + + /* Get a client magic number and pass it to the master for auth. */ + ret = ioctl(drmfd, DRM_IOCTL_GET_MAGIC, &auth); + if (ret == -1) + err(1, "Couldn't get client magic"); + send_event(0, CLIENT_MAGIC); + ret = write(commfd[0], &auth.magic, sizeof(auth.magic)); + if (ret == -1) + err(1, "Couldn't write auth data"); +} + +static void +server_auth(int drmfd) +{ + struct drm_auth auth; + int ret; + + send_event(1, SERVER_READY); + wait_event(1, CLIENT_MAGIC); + ret = read(commfd[1], &auth.magic, sizeof(auth.magic)); + if (ret == -1) + err(1, "Failure to read client magic"); + + ret = ioctl(drmfd, DRM_IOCTL_AUTH_MAGIC, &auth); + if (ret == -1) + err(1, "Failure to authenticate client magic\n"); +} + +/** Tests that locking is successful in normal conditions */ +static void +test_lock_unlock(int drmfd) +{ + int ret; + + ret = drmGetLock(drmfd, lock1, 0); + if (ret != 0) + err(1, "Locking failed"); + ret = drmUnlock(drmfd, lock1); + if (ret != 0) + err(1, "Unlocking failed"); +} + +/** Tests that unlocking the lock while it's not held works correctly */ +static void +test_unlock_unlocked(int drmfd) +{ + int ret; + + ret = drmUnlock(drmfd, lock1); + if (ret == 0) + err(1, "Unlocking unlocked lock succeeded"); +} + +/** Tests that unlocking a lock held by another context fails appropriately */ +static void +test_unlock_unowned(int drmfd) +{ + int ret; + + ret = drmGetLock(drmfd, lock1, 0); + assert(ret == 0); + ret = drmUnlock(drmfd, lock2); + if (ret == 0) + errx(1, "Unlocking other context's lock succeeded"); + ret = drmUnlock(drmfd, lock1); + assert(ret == 0); +} + +/** + * Tests that an open/close by the same process doesn't result in the lock + * being dropped. + */ +static void test_open_close_locked(drmfd) +{ + int ret, tempfd; + + ret = drmGetLock(drmfd, lock1, 0); + assert(ret == 0); + /* XXX: Need to make sure that this is the same device as drmfd */ + tempfd = drm_open_any(); + close(tempfd); + ret = drmUnlock(drmfd, lock1); + if (ret != 0) + errx(1, "lock lost during open/close by same pid"); + + close(drmfd); +} + +static void client() +{ + int drmfd, ret; + unsigned int time; + + /* XXX: Should make sure we open the same DRM as the master */ + drmfd = drm_open_any(); + + client_auth(drmfd); + + /* Wait for the server to grab the lock, then grab it ourselves (to + * contest it). Hopefully we hit it within the window of when the + * server locks. + */ + wait_event(0, SERVER_LOCKED); + ret = drmGetLock(drmfd, lock2, 0); + time = get_millis(); + if (ret != 0) + err(1, "Failed to get lock on client\n"); + drmUnlock(drmfd, lock2); + + /* Tell the server that our locking completed, and when it did */ + send_event(0, CLIENT_LOCKED); + ret = write(commfd[0], &time, sizeof(time)); + + exit(0); +} + +static void server() +{ + int drmfd, tempfd, ret; + unsigned int client_time, unlock_time; + + drmfd = drm_open_any_master(); + + test_lock_unlock(drmfd); + test_unlock_unlocked(drmfd); + test_unlock_unowned(drmfd); + test_open_close_locked(drmfd); + + /* Perform the authentication sequence with the client. */ + server_auth(drmfd); + + /* Now, test that the client attempting to lock while the server + * holds the lock works correctly. + */ + ret = drmGetLock(drmfd, lock1, 0); + assert(ret == 0); + send_event(1, SERVER_LOCKED); + /* Wait a while for the client to do its thing */ + sleep(1); + ret = drmUnlock(drmfd, lock1); + assert(ret == 0); + unlock_time = get_millis(); + + wait_event(1, CLIENT_LOCKED); + ret = read(commfd[1], &client_time, sizeof(client_time)); + if (ret == -1) + err(1, "Failure to read client magic"); + + if (client_time < unlock_time) + errx(1, "Client took lock before server released it"); +} + +int main(int argc, char **argv) +{ + int ret; + + + ret = pipe(commfd); + if (ret == -1) + err(1, "Couldn't create pipe"); + + ret = fork(); + if (ret == -1) + err(1, "failure to fork client"); + if (ret == 0) + client(); + else + server(); + + return 0; +} + diff-tree 8a1ca401b403848d894f664977f9e939eaf07291 (from d1a2b26a99205b802919aa0901b4e19cb2d251fe) Author: Eric Anholt <er...@an...> Date: Wed Aug 15 13:13:24 2007 -0700 Fix a bad error message in auth.c regression test. diff --git a/tests/auth.c b/tests/auth.c index 45265d6..4160d1d 100644 --- a/tests/auth.c +++ b/tests/auth.c @@ -108,7 +108,7 @@ static void server() ret = ioctl(drmfd, DRM_IOCTL_AUTH_MAGIC, &auth); if (ret == -1) - err(1, "Authenticating bad magic succeeded\n"); + err(1, "Failure to authenticate client magic\n"); wait_event(1, CLIENT_DONE); } diff-tree d1a2b26a99205b802919aa0901b4e19cb2d251fe (from a9ee144eab5bbd5f90747c38cdc016da46c124fe) Author: Eric Anholt <er...@an...> Date: Wed Aug 15 13:08:19 2007 -0700 Require master in setversion test, since it requires auth. diff --git a/tests/setversion.c b/tests/setversion.c index dc6eccf..f4bfbfb 100644 --- a/tests/setversion.c +++ b/tests/setversion.c @@ -40,7 +40,7 @@ int main(int argc, char **argv) int fd, ret; drm_set_version_t sv, version; - fd = drm_open_any(); + fd = drm_open_any_master(); /* First, check that we can get the DD/DI versions. */ memset(&version, 0, sizeof(version)); diff-tree a9ee144eab5bbd5f90747c38cdc016da46c124fe (from 4cdd871e90cd5fe440d0a4af5d69f1d84e49e742) Author: vehemens <veh...@ve...> Date: Wed Aug 15 11:12:46 2007 -0700 BSD: simplify drm_ioctl() after other refactoring. diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c index 208f438..afd9035 100644 --- a/bsd-core/drm_drv.c +++ b/bsd-core/drm_drv.c @@ -821,14 +821,7 @@ int drm_close(struct cdev *kdev, int fla int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags, DRM_STRUCTPROC *p) { -#ifdef __FreeBSD__ - drm_device_t *dev = kdev->si_drv1; -#elif defined(__NetBSD__) - drm_device_t *dev = device_lookup(&drm_cd, minor(kdev)); -#else - drm_device_t *dev = device_lookup(&drm_cd, - minor(kdev)))->dv_cfdata->cf_driver->cd_devs[minor(kdev)]; -#endif + drm_device_t *dev = drm_get_device_from_kdev(kdev); int retcode = 0; drm_ioctl_desc_t *ioctl; int (*func)(drm_device_t *dev, void *data, struct drm_file *file_priv); @@ -915,15 +908,13 @@ int drm_ioctl(struct cdev *kdev, u_long ((ioctl->flags & DRM_MASTER) && !file_priv->master)) return EACCES; - if (is_driver_ioctl) - DRM_LOCK(); - retcode = func(dev, data, file_priv); if (is_driver_ioctl) { + DRM_LOCK(); + /* shared code returns -errno */ + retcode = -func(dev, data, file_priv); DRM_UNLOCK(); - /* Driver ioctls in shared code follow the linux convention of - * returning -errno instead of errno. - */ - retcode = -retcode; + } else { + retcode = func(dev, data, file_priv); } if (retcode != 0) |
From: <jk...@ke...> - 2007-11-02 23:48:18
|
linux-core/Makefile.kernel | 2 linux-core/nouveau_buffer.c | 224 +++++++++++++++++++++++++++++++++----------- linux-core/nouveau_drv.c | 25 ---- linux-core/nouveau_fence.c | 129 +++++++++++++++++++++++++ shared-core/nouveau_drv.h | 23 +--- 5 files changed, 310 insertions(+), 93 deletions(-) New commits: commit 998d120a47cab85e985b24932fe8f4682f5f78e9 Author: Jeremy Kolb <jk...@br...> Date: Fri Nov 2 19:46:27 2007 -0400 nouveau: add darktama's email address to authors section. diff --git a/linux-core/nouveau_buffer.c b/linux-core/nouveau_buffer.c index 1a210e4..799731a 100644 --- a/linux-core/nouveau_buffer.c +++ b/linux-core/nouveau_buffer.c @@ -23,8 +23,8 @@ */ /* * Authors: Dave Airlied <ai...@li...> - * Jeremy Kolb <jk...@br...> - * Ben Skeggs + * Ben Skeggs <dar...@ii...> + * Jeremy Kolb <jk...@br...> */ #include "drmP.h" commit 2dc2ee7a5aed18b82a1125d8e56a7ef92be18532 Author: Jeremy Kolb <jk...@br...> Date: Fri Nov 2 19:44:30 2007 -0400 nouveau: put it all together. diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index bcbd78f..d1f3bb7 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -22,7 +22,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_sgdma.o nouveau_dma.o nouveau_buffer.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_buffer.c b/linux-core/nouveau_buffer.c index 41c5074..1a210e4 100644 --- a/linux-core/nouveau_buffer.c +++ b/linux-core/nouveau_buffer.c @@ -230,3 +230,30 @@ void nouveau_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_create_ttm_backend_entry, + .fence_type = nouveau_fence_types, + .invalidate_caches = nouveau_invalidate_caches, + .init_mem_type = nouveau_init_mem_type, + .evict_mask = nouveau_evict_mask, + .move = nouveau_move, + .ttm_cache_flush= nouveau_flush_ttm +}; + diff --git a/linux-core/nouveau_drv.c b/linux-core/nouveau_drv.c index 1bd8d97..ac70d7a 100644 --- a/linux-core/nouveau_drv.c +++ b/linux-core/nouveau_drv.c @@ -41,33 +41,6 @@ static struct pci_device_id pciidlist[] = { } }; -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 -}; - -static 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_create_ttm_backend_entry, - .fence_type = nouveau_fence_types, - .invalidate_caches = nouveau_invalidate_caches, - .init_mem_type = nouveau_init_mem_type, - .evict_mask = nouveau_evict_mask, - .move = nouveau_move, - .ttm_cache_flush= nouveau_flush_ttm -}; - extern struct drm_ioctl_desc nouveau_ioctls[]; extern int nouveau_max_ioctl; @@ -109,6 +82,7 @@ static struct drm_driver driver = { }, .bo_driver = &nouveau_bo_driver, + .fence_driver = &nouveau_fence_driver, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 41258a5..8383627 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -39,12 +39,6 @@ #define NOUVEAU_FAMILY 0x0000FFFF #define NOUVEAU_FLAGS 0xFFFF0000 -#if 0 -#if defined(__linux__) -#define NOUVEAU_HAVE_BUFFER -#endif -#endif - #include "nouveau_drm.h" #include "nouveau_reg.h" @@ -153,6 +147,9 @@ struct nouveau_drm_channel { /* Notifiers */ uint32_t notify0_offset; + /* Fences */ + uint32_t next_sequence; + /* Buffer moves */ uint32_t m2mf_dma_source; uint32_t m2mf_dma_destin; @@ -560,16 +557,12 @@ extern void nv04_timer_takedown(struct drm_device *); extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -#ifdef NOUVEAU_HAVE_BUFFER /* nouveau_buffer.c */ -extern struct drm_ttm_backend *nouveau_create_ttm_backend_entry(struct drm_device *dev); -extern int nouveau_fence_types(struct drm_buffer_object *bo, uint32_t *fclass, uint32_t *type); -extern int nouveau_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags); -extern int nouveau_init_mem_type(struct drm_device *dev, uint32_t type, struct drm_mem_type_manager *man); -extern uint32_t nouveau_evict_mask(struct drm_buffer_object *bo); -extern int nouveau_move(struct drm_buffer_object *bo, int evict, int no_wait, struct drm_bo_mem_reg *new_mem); -void nouveau_flush_ttm(struct drm_ttm *ttm); -#endif +extern struct drm_bo_driver nouveau_bo_driver; + +/* nouveau_fence.c */ +extern struct drm_fence_driver nouveau_fence_driver; +extern void nouveau_fence_handler(struct drm_device *dev, int channel); #if defined(__powerpc__) #define NV_READ(reg) in_be32((void __iomem *)(dev_priv->mmio)->handle + (reg) ) commit c1aa08106e0a7190c7a303ec8a9b6b5339251137 Author: Jeremy Kolb <jk...@br...> Date: Fri Nov 2 19:43:53 2007 -0400 nouveau: Add darktama's fencing code. Restructure some stuff. diff --git a/linux-core/nouveau_fence.c b/linux-core/nouveau_fence.c new file mode 100644 index 0000000..e510aec --- /dev/null +++ b/linux-core/nouveau_fence.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * 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 THE COPYRIGHT OWNER(S) 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_dma.h" + +static int +nouveau_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t flags) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + DRM_DEBUG("class=%d, flags=0x%08x\n", class, flags); + + /* DRM's channel always uses IRQs to signal fences */ + if (class == dev_priv->channel.chan->id) + return 1; + + /* Other channels don't use IRQs at all yet */ + return 0; +} + +static int +nouveau_fence_emit(struct drm_device *dev, uint32_t class, uint32_t flags, + uint32_t *breadcrumb, uint32_t *native_type) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->fifos[class]; + struct nouveau_drm_channel *dchan = &dev_priv->channel; + + DRM_DEBUG("class=%d, flags=0x%08x\n", class, flags); + + /* We can't emit fences on client channels */ + if (chan != dchan->chan) + return 0; + + *breadcrumb = ++dchan->next_sequence; + *native_type = DRM_FENCE_TYPE_EXE; + + BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_SET_REF, 1); + OUT_RING (*breadcrumb); + BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); + OUT_RING (NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE_LE_AWAKEN); + BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1); + OUT_RING (0); + FIRE_RING (); + + return 0; +} + +static void +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]; + uint32_t pending_types = 0; + + DRM_DEBUG("class=%d\n", class); + + pending_types = fc->pending_flush | + ((fc->pending_exe_flush) ? DRM_FENCE_TYPE_EXE : 0); + + if (pending_types) { + uint32_t sequence = NV_READ(NV03_FIFO_REGS(class) + 0x48); + + drm_fence_handler(dev, class, sequence, pending_types, 0); + } +} + +static void +nouveau_fence_poke_flush(struct drm_device *dev, uint32_t class) +{ + struct drm_fence_manager *fm = &dev->fm; + unsigned long flags; + + DRM_DEBUG("class=%d\n", class); + + write_lock_irqsave(&fm->lock, flags); + nouveau_fence_perform_flush(dev, class); + write_unlock_irqrestore(&fm->lock, flags); +} + +void +nouveau_fence_handler(struct drm_device *dev, int channel) +{ + struct drm_fence_manager *fm = &dev->fm; + + DRM_DEBUG("class=%d\n", channel); + + write_lock(&fm->lock); + nouveau_fence_perform_flush(dev, channel); + write_unlock(&fm->lock); +} + +struct drm_fence_driver nouveau_fence_driver = { + .num_classes = 8, + .wrap_diff = (1 << 30), + .flush_diff = (1 << 29), + .sequence_mask = 0xffffffffU, + .lazy_capable = 1, + .has_irq = nouveau_fence_has_irq, + .emit = nouveau_fence_emit, + .poke_flush = nouveau_fence_poke_flush +}; + commit 2c6cbea7dedc0b06114117b4c4ce2a23f74c54f6 Author: Jeremy Kolb <jk...@br...> Date: Thu Nov 1 23:35:46 2007 -0400 nouveau: incorporate darktama's buffer object work. diff --git a/linux-core/nouveau_buffer.c b/linux-core/nouveau_buffer.c index bb9f6f4..41c5074 100644 --- a/linux-core/nouveau_buffer.c +++ b/linux-core/nouveau_buffer.c @@ -24,17 +24,29 @@ /* * Authors: Dave Airlied <ai...@li...> * Jeremy Kolb <jk...@br...> + * Ben Skeggs */ #include "drmP.h" #include "nouveau_drm.h" #include "nouveau_drv.h" - -#ifdef NOUVEAU_HAVE_BUFFER +#include "nouveau_dma.h" struct drm_ttm_backend *nouveau_create_ttm_backend_entry(struct drm_device * dev) { - return drm_agp_init_ttm(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; } int nouveau_fence_types(struct drm_buffer_object *bo, @@ -57,46 +69,67 @@ int nouveau_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags) } int nouveau_init_mem_type(struct drm_device *dev, - uint32_t type, - struct drm_mem_type_manager *man) + uint32_t type, + struct drm_mem_type_manager *man) { - 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, 0); - man->io_size = drm_get_resource_len(dev, 0); - break; - - case DRM_BO_MEM_TT: - if (!(drm_core_has_AGP(dev) && dev->agp)) { - DRM_ERROR("AGP is not enabled for memory type %u\n", - (unsigned)type); - return -EINVAL; - } - - man->io_offset = dev->agp->agp_info.aper_base; - man->io_size = dev->agp->agp_info.aper_size * 1024 * 1024; - man->io_addr = NULL; - man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | - _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_NEEDS_IOREMAP; - man->drm_bus_maptype = _DRM_AGP; - break; - - default: - DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); - return -EINVAL; - } - return 0; + 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, 0); + man->io_size = drm_get_resource_len(dev, 0); + 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; } uint32_t nouveau_evict_mask(struct drm_buffer_object *bo) @@ -105,91 +138,63 @@ uint32_t nouveau_evict_mask(struct drm_buffer_object *bo) case DRM_BO_MEM_LOCAL: case DRM_BO_MEM_TT: return DRM_BO_FLAG_MEM_LOCAL; - case DRM_BO_MEM_VRAM: - if (bo->mem.num_pages > 128) - return DRM_BO_MEM_TT; - else - return DRM_BO_MEM_LOCAL; default: return DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED; } - -} - -static void nouveau_emit_copy_blit(struct drm_device * dev, - uint32_t src_offset, - uint32_t dst_offset, - uint32_t pages, int direction) -{ - return; + return 0; } -static int nouveau_move_blit(struct drm_buffer_object *bo, - int evict, - int no_wait, - struct drm_bo_mem_reg *new_mem) +/* 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; - int dir = 0; + 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); + } - if ((old_mem->mem_type == new_mem->mem_type) && - (new_mem->mm_node->start < - old_mem->mm_node->start + old_mem->mm_node->size)) { - dir = 1; + 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; } - nouveau_emit_copy_blit(bo->dev, - old_mem->mm_node->start << PAGE_SHIFT, - new_mem->mm_node->start << PAGE_SHIFT, - new_mem->num_pages, dir); - - /* we don't need to cleanup out mess because our fences - * are from userland. so this cleanup call is probably wrong. - */ return drm_bo_move_accel_cleanup(bo, evict, no_wait, 0, - DRM_FENCE_TYPE_EXE, - 0, - new_mem); - -} - -static int nouveau_move_flip(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_bo_mem_reg tmp_mem; - int ret; - - tmp_mem = *new_mem; - tmp_mem.mm_node = NULL; - tmp_mem.mask = DRM_BO_FLAG_MEM_TT | - DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING; - - ret = drm_bo_mem_space(bo, &tmp_mem, no_wait); - if (ret) - return ret; - - ret = drm_bind_ttm(bo->ttm, tmp_mem.mm_node->start); - if (ret) - goto out_cleanup; - - ret = nouveau_move_blit(bo, 1, no_wait, &tmp_mem); - if (ret) - goto out_cleanup; - - ret = drm_bo_move_ttm(bo, evict, no_wait, new_mem); - -out_cleanup: - if (tmp_mem.mm_node) { - mutex_lock(&dev->struct_mutex); - if (tmp_mem.mm_node != bo->pinned_node) - drm_mm_put_block(tmp_mem.mm_node); - tmp_mem.mm_node = NULL; - mutex_unlock(&dev->struct_mutex); - } - return ret; + DRM_FENCE_TYPE_EXE, + 0, new_mem); } int nouveau_move(struct drm_buffer_object *bo, @@ -199,17 +204,22 @@ int nouveau_move(struct drm_buffer_object *bo, { struct drm_bo_mem_reg *old_mem = &bo->mem; - if (old_mem->mem_type == DRM_BO_MEM_LOCAL) { - /* local to VRAM */ - return drm_bo_move_memcpy(bo, evict, no_wait, new_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 (new_mem->mem_type == DRM_BO_MEM_LOCAL) { - /* VRAM to local */ - /*if (nouveau_move_flip(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_move_blit(bo, evict, no_wait, new_mem))*/ + if (nouveau_bo_move_m2mf(bo, evict, no_wait, new_mem)) return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); } return 0; @@ -220,4 +230,3 @@ void nouveau_flush_ttm(struct drm_ttm *ttm) } -#endif diff --git a/linux-core/nouveau_drv.c b/linux-core/nouveau_drv.c index 9e6c8f4..1bd8d97 100644 --- a/linux-core/nouveau_drv.c +++ b/linux-core/nouveau_drv.c @@ -41,9 +41,18 @@ static struct pci_device_id pciidlist[] = { } }; -#ifdef NOUVEAU_HAVE_BUFFER -static uint32_t nouveau_mem_prios[] = { 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_LOCAL }; +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 +}; static struct drm_bo_driver nouveau_bo_driver = { .mem_type_prio = nouveau_mem_prios, @@ -58,7 +67,6 @@ static struct drm_bo_driver nouveau_bo_driver = { .move = nouveau_move, .ttm_cache_flush= nouveau_flush_ttm }; -#endif extern struct drm_ioctl_desc nouveau_ioctls[]; extern int nouveau_max_ioctl; @@ -99,9 +107,8 @@ static struct drm_driver driver = { .probe = probe, .remove = __devexit_p(drm_cleanup_pci), }, -#ifdef NOUVEAU_HAVE_BUFFER - .bo_driver = &nouveau_bo_driver, -#endif + + .bo_driver = &nouveau_bo_driver, .name = DRIVER_NAME, .desc = DRIVER_DESC, commit 239e81093f05e7d81f95a55527f3c9fcb8fc483a Author: Jeremy Kolb <jk...@br...> Date: Thu Nov 1 19:04:38 2007 -0400 nouveau: more filling in for ttm. Change copyright since it's based off of radeon code. diff --git a/linux-core/nouveau_buffer.c b/linux-core/nouveau_buffer.c index e9f09eb..bb9f6f4 100644 --- a/linux-core/nouveau_buffer.c +++ b/linux-core/nouveau_buffer.c @@ -1,5 +1,5 @@ /* - * Copyright 2005 Stephane Marchesin. + * Copyright 2007 Dave Airlied * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -22,7 +22,8 @@ * OTHER DEALINGS IN THE SOFTWARE. */ /* - * Authors: Jeremy Kolb <jk...@br...> + * Authors: Dave Airlied <ai...@li...> + * Jeremy Kolb <jk...@br...> */ #include "drmP.h" @@ -33,8 +34,6 @@ struct drm_ttm_backend *nouveau_create_ttm_backend_entry(struct drm_device * dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - return drm_agp_init_ttm(dev); } @@ -61,8 +60,6 @@ int nouveau_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 | @@ -119,6 +116,82 @@ uint32_t nouveau_evict_mask(struct drm_buffer_object *bo) } +static void nouveau_emit_copy_blit(struct drm_device * dev, + uint32_t src_offset, + uint32_t dst_offset, + uint32_t pages, int direction) +{ + return; +} + +static int nouveau_move_blit(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; + int dir = 0; + + if ((old_mem->mem_type == new_mem->mem_type) && + (new_mem->mm_node->start < + old_mem->mm_node->start + old_mem->mm_node->size)) { + dir = 1; + } + + nouveau_emit_copy_blit(bo->dev, + old_mem->mm_node->start << PAGE_SHIFT, + new_mem->mm_node->start << PAGE_SHIFT, + new_mem->num_pages, dir); + + /* we don't need to cleanup out mess because our fences + * are from userland. so this cleanup call is probably wrong. + */ + return drm_bo_move_accel_cleanup(bo, evict, no_wait, 0, + DRM_FENCE_TYPE_EXE, + 0, + new_mem); + +} + +static int nouveau_move_flip(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_bo_mem_reg tmp_mem; + int ret; + + tmp_mem = *new_mem; + tmp_mem.mm_node = NULL; + tmp_mem.mask = DRM_BO_FLAG_MEM_TT | + DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING; + + ret = drm_bo_mem_space(bo, &tmp_mem, no_wait); + if (ret) + return ret; + + ret = drm_bind_ttm(bo->ttm, tmp_mem.mm_node->start); + if (ret) + goto out_cleanup; + + ret = nouveau_move_blit(bo, 1, no_wait, &tmp_mem); + if (ret) + goto out_cleanup; + + ret = drm_bo_move_ttm(bo, evict, no_wait, new_mem); + +out_cleanup: + if (tmp_mem.mm_node) { + mutex_lock(&dev->struct_mutex); + if (tmp_mem.mm_node != bo->pinned_node) + drm_mm_put_block(tmp_mem.mm_node); + tmp_mem.mm_node = NULL; + mutex_unlock(&dev->struct_mutex); + } + return ret; +} + int nouveau_move(struct drm_buffer_object *bo, int evict, int no_wait, @@ -127,12 +200,17 @@ int nouveau_move(struct drm_buffer_object *bo, struct drm_bo_mem_reg *old_mem = &bo->mem; if (old_mem->mem_type == DRM_BO_MEM_LOCAL) { + /* local to VRAM */ return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); + } else if (new_mem->mem_type == DRM_BO_MEM_LOCAL) { - return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); + /* VRAM to local */ + /*if (nouveau_move_flip(bo, evict, no_wait, new_mem))*/ + return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); } else { - return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); + /*if (nouveau_move_blit(bo, evict, no_wait, new_mem))*/ + return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); } return 0; } |
From: <ke...@ke...> - 2007-12-21 20:16:59
|
libdrm/xf86drm.c | 6 - libdrm/xf86mm.h | 2 linux-core/drm_agpsupport.c | 16 +++- linux-core/drm_bo.c | 169 +++++++++++++++++++++++++++++--------------- linux-core/drm_bo_move.c | 14 +-- linux-core/drm_objects.h | 119 +++++++++++++++++++++++++++--- linux-core/drm_ttm.c | 113 ++++++++++++++++++++--------- linux-core/drm_vm.c | 4 - linux-core/i915_buffer.c | 15 +++ linux-core/i915_drv.c | 4 - linux-core/nouveau_buffer.c | 15 ++- linux-core/nouveau_sgdma.c | 9 +- linux-core/via_buffer.c | 2 shared-core/drm.h | 25 +++++- shared-core/i915_drv.h | 6 - shared-core/via_drv.c | 2 shared-core/via_drv.h | 2 17 files changed, 380 insertions(+), 143 deletions(-) New commits: commit da3601e43ae75695f3b080904b1e090c8eb1cd8e Author: Keith Packard <ke...@ke...> Date: Sun Dec 16 22:00:45 2007 -0800 Change drm_bo_type_dc to drm_bo_type_device and comment usage of this value. I couldn't figure out what drm_bo_type_dc was for; Dave Airlie finally clued me in that it was the 'normal' buffer objects with kernel allocated pages that could be mmapped from the drm device file. I thought that 'drm_bo_type_device' was a more descriptive name. I also added a bunch of comments describing the use of the type enum values and the functions that use them. diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 171c074..df10e12 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -146,7 +146,7 @@ static int drm_bo_add_ttm(struct drm_buffer_object *bo) page_flags |= DRM_TTM_PAGE_WRITE; switch (bo->type) { - case drm_bo_type_dc: + case drm_bo_type_device: case drm_bo_type_kernel: bo->ttm = drm_ttm_create(dev, bo->num_pages << PAGE_SHIFT, page_flags, dev->bm.dummy_read_page); @@ -1155,7 +1155,12 @@ static void drm_bo_fill_rep_arg(struct drm_buffer_object *bo, rep->size = bo->num_pages * PAGE_SIZE; rep->offset = bo->offset; - if (bo->type == drm_bo_type_dc) + /* + * drm_bo_type_device buffers have user-visible + * handles which can be used to share across + * processes. Hand that back to the application + */ + if (bo->type == drm_bo_type_device) rep->arg_handle = bo->map_list.user_token; else rep->arg_handle = 0; @@ -1786,7 +1791,12 @@ int drm_buffer_object_create(struct drm_device *dev, if (ret) goto out_err; - if (bo->type == drm_bo_type_dc) { + /* + * For drm_bo_type_device buffers, allocate + * address space from the device so that applications + * can mmap the buffer from there + */ + if (bo->type == drm_bo_type_device) { mutex_lock(&dev->struct_mutex); ret = drm_bo_setup_vm_locked(bo); mutex_unlock(&dev->struct_mutex); @@ -1849,7 +1859,12 @@ int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *fil return -EINVAL; } - bo_type = (req->buffer_start) ? drm_bo_type_user : drm_bo_type_dc; + /* + * If the buffer creation request comes in with a starting address, + * that points at the desired user pages to map. Otherwise, create + * a drm_bo_type_device buffer, which uses pages allocated from the kernel + */ + bo_type = (req->buffer_start) ? drm_bo_type_user : drm_bo_type_device; /* * User buffers cannot be shared @@ -2607,6 +2622,14 @@ void drm_bo_unmap_virtual(struct drm_buffer_object *bo) unmap_mapping_range(dev->dev_mapping, offset, holelen, 1); } +/** + * drm_bo_takedown_vm_locked: + * + * @bo: the buffer object to remove any drm device mapping + * + * Remove any associated vm mapping on the drm device node that + * would have been created for a drm_bo_type_device buffer + */ static void drm_bo_takedown_vm_locked(struct drm_buffer_object *bo) { struct drm_map_list *list; @@ -2614,7 +2637,7 @@ static void drm_bo_takedown_vm_locked(struct drm_buffer_object *bo) struct drm_device *dev = bo->dev; DRM_ASSERT_LOCKED(&dev->struct_mutex); - if (bo->type != drm_bo_type_dc) + if (bo->type != drm_bo_type_device) return; list = &bo->map_list; @@ -2637,6 +2660,16 @@ static void drm_bo_takedown_vm_locked(struct drm_buffer_object *bo) drm_bo_usage_deref_locked(&bo); } +/** + * drm_bo_setup_vm_locked: + * + * @bo: the buffer to allocate address space for + * + * Allocate address space in the drm device so that applications + * can mmap the buffer and access the contents. This only + * applies to drm_bo_type_device objects as others are not + * placed in the drm device address space. + */ static int drm_bo_setup_vm_locked(struct drm_buffer_object *bo) { struct drm_map_list *list = &bo->map_list; diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 98421e4..a2d10b5 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -404,9 +404,31 @@ struct drm_bo_mem_reg { }; enum drm_bo_type { - drm_bo_type_dc, + /* + * drm_bo_type_device are 'normal' drm allocations, + * pages are allocated from within the kernel automatically + * and the objects can be mmap'd from the drm device. Each + * drm_bo_type_device object has a unique name which can be + * used by other processes to share access to the underlying + * buffer. + */ + drm_bo_type_device, + /* + * drm_bo_type_user are buffers of pages that already exist + * in the process address space. They are more limited than + * drm_bo_type_device buffers in that they must always + * remain cached (as we assume the user pages are mapped cached), + * and they are not sharable to other processes through DRM + * (although, regular shared memory should still work fine). + */ drm_bo_type_user, - drm_bo_type_kernel, /* for initial kernel allocations */ + /* + * drm_bo_type_kernel are buffers that exist solely for use + * within the kernel. The pages cannot be mapped into the + * process. One obvious use would be for the ring + * buffer where user access would not (ideally) be required. + */ + drm_bo_type_kernel, }; struct drm_buffer_object { commit d1187641d64f442968a3b9ea6a19de6cdd45acd4 Author: Keith Packard <ke...@ke...> Date: Sun Dec 16 20:16:50 2007 -0800 Rename inappropriately named 'mask' fields to 'proposed_flags' instead. Flags pending validation were stored in a misleadingly named field, 'mask'. As 'mask' is already used to indicate pieces of a flags field which are changing, it seems better to use a name reflecting the actual purpose of this field. I chose 'proposed_flags' as they may not actually end up in 'flags', and in an case will be modified when they are moved over. This affects the API, but not ABI of the user-mode interface. diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c index 4265c32..e3550de 100644 --- a/libdrm/xf86drm.c +++ b/libdrm/xf86drm.c @@ -2578,7 +2578,7 @@ static void drmBOCopyReply(const struct drm_bo_info_rep *rep, drmBO *buf) buf->size = rep->size; buf->offset = rep->offset; buf->mapHandle = rep->arg_handle; - buf->mask = rep->mask; + buf->proposedFlags = rep->proposed_flags; buf->start = rep->buffer_start; buf->fenceFlags = rep->fence_flags; buf->replyFlags = rep->rep_flags; @@ -2592,7 +2592,7 @@ static void drmBOCopyReply(const struct drm_bo_info_rep *rep, drmBO *buf) int drmBOCreate(int fd, unsigned long size, unsigned pageAlignment, void *user_buffer, - uint64_t mask, + uint64_t flags, unsigned hint, drmBO *buf) { struct drm_bo_create_arg arg; @@ -2602,7 +2602,7 @@ int drmBOCreate(int fd, unsigned long size, memset(buf, 0, sizeof(*buf)); memset(&arg, 0, sizeof(arg)); - req->mask = mask; + req->flags = flags; req->hint = hint; req->size = size; req->page_alignment = pageAlignment; diff --git a/libdrm/xf86mm.h b/libdrm/xf86mm.h index d3df849..c80288a 100644 --- a/libdrm/xf86mm.h +++ b/libdrm/xf86mm.h @@ -110,7 +110,7 @@ typedef struct _drmBO unsigned handle; uint64_t mapHandle; uint64_t flags; - uint64_t mask; + uint64_t proposedFlags; unsigned mapFlags; unsigned long size; unsigned long offset; diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index e7b9c5b..171c074 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -80,7 +80,7 @@ void drm_bo_add_to_lru(struct drm_buffer_object *bo) DRM_ASSERT_LOCKED(&bo->dev->struct_mutex); - if (!(bo->mem.mask & (DRM_BO_FLAG_NO_MOVE | DRM_BO_FLAG_NO_EVICT)) + if (!(bo->mem.proposed_flags & (DRM_BO_FLAG_NO_MOVE | DRM_BO_FLAG_NO_EVICT)) || bo->mem.mem_type != bo->pinned_mem_type) { man = &bo->dev->bm.man[bo->mem.mem_type]; list_add_tail(&bo->lru, &man->lru); @@ -142,7 +142,7 @@ static int drm_bo_add_ttm(struct drm_buffer_object *bo) DRM_ASSERT_LOCKED(&bo->mutex); bo->ttm = NULL; - if (bo->mem.mask & DRM_BO_FLAG_WRITE) + if (bo->mem.proposed_flags & DRM_BO_FLAG_WRITE) page_flags |= DRM_TTM_PAGE_WRITE; switch (bo->type) { @@ -214,11 +214,11 @@ static int drm_bo_handle_move_mem(struct drm_buffer_object *bo, struct drm_bo_mem_reg *old_mem = &bo->mem; uint64_t save_flags = old_mem->flags; - uint64_t save_mask = old_mem->mask; + uint64_t save_proposed_flags = old_mem->proposed_flags; *old_mem = *mem; mem->mm_node = NULL; - old_mem->mask = save_mask; + old_mem->proposed_flags = save_proposed_flags; DRM_FLAG_MASKED(save_flags, mem->flags, DRM_BO_MASK_MEMTYPE); } else if (!(old_man->flags & _DRM_FLAG_MEMTYPE_FIXED) && @@ -708,7 +708,7 @@ static int drm_bo_evict(struct drm_buffer_object *bo, unsigned mem_type, evict_mem.mm_node = NULL; evict_mem = bo->mem; - evict_mem.mask = dev->driver->bo_driver->evict_mask(bo); + evict_mem.proposed_flags = dev->driver->bo_driver->evict_flags(bo); ret = drm_bo_mem_space(bo, &evict_mem, no_wait); if (ret) { @@ -872,7 +872,7 @@ int drm_bo_mem_space(struct drm_buffer_object *bo, type_ok = drm_bo_mt_compatible(man, bo->type == drm_bo_type_user, - mem_type, mem->mask, + mem_type, mem->proposed_flags, &cur_flags); if (!type_ok) @@ -924,7 +924,7 @@ int drm_bo_mem_space(struct drm_buffer_object *bo, if (!drm_bo_mt_compatible(man, bo->type == drm_bo_type_user, mem_type, - mem->mask, + mem->proposed_flags, &cur_flags)) continue; @@ -944,11 +944,25 @@ int drm_bo_mem_space(struct drm_buffer_object *bo, } EXPORT_SYMBOL(drm_bo_mem_space); -static int drm_bo_new_mask(struct drm_buffer_object *bo, - uint64_t new_flags, uint64_t used_mask) +/* + * drm_bo_propose_flags: + * + * @bo: the buffer object getting new flags + * + * @new_flags: the new set of proposed flag bits + * + * @new_mask: the mask of bits changed in new_flags + * + * Modify the proposed_flag bits in @bo + */ +static int drm_bo_modify_proposed_flags (struct drm_buffer_object *bo, + uint64_t new_flags, uint64_t new_mask) { - uint32_t new_props; + uint32_t new_access; + /* Copy unchanging bits from existing proposed_flags */ + DRM_FLAG_MASKED(new_flags, bo->mem.proposed_flags, ~new_mask); + if (bo->type == drm_bo_type_user && ((new_flags & (DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING)) != (DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING))) { @@ -956,7 +970,7 @@ static int drm_bo_new_mask(struct drm_buffer_object *bo, return -EINVAL; } - if ((used_mask & DRM_BO_FLAG_NO_EVICT) && !DRM_SUSER(DRM_CURPROC)) { + if ((new_mask & DRM_BO_FLAG_NO_EVICT) && !DRM_SUSER(DRM_CURPROC)) { DRM_ERROR("DRM_BO_FLAG_NO_EVICT is only available to priviliged processes.\n"); return -EPERM; } @@ -966,15 +980,15 @@ static int drm_bo_new_mask(struct drm_buffer_object *bo, return -EPERM; } - new_props = new_flags & (DRM_BO_FLAG_EXE | DRM_BO_FLAG_WRITE | - DRM_BO_FLAG_READ); + new_access = new_flags & (DRM_BO_FLAG_EXE | DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_READ); - if (!new_props) { + if (new_access == 0) { DRM_ERROR("Invalid buffer object rwx properties\n"); return -EINVAL; } - bo->mem.mask = new_flags; + bo->mem.proposed_flags = new_flags; return 0; } @@ -1109,8 +1123,8 @@ static int drm_bo_wait_unfenced(struct drm_buffer_object *bo, int no_wait, ret = 0; mutex_unlock(&bo->mutex); - DRM_WAIT_ON(ret, bo->event_queue, 3 * DRM_HZ, - !drm_bo_check_unfenced(bo)); + DRM_WAIT_ON (ret, bo->event_queue, 3 * DRM_HZ, + !drm_bo_check_unfenced(bo)); mutex_lock(&bo->mutex); if (ret == -EINTR) return -EAGAIN; @@ -1146,7 +1160,7 @@ static void drm_bo_fill_rep_arg(struct drm_buffer_object *bo, else rep->arg_handle = 0; - rep->mask = bo->mem.mask; + rep->proposed_flags = bo->mem.proposed_flags; rep->buffer_start = bo->buffer_start; rep->fence_flags = bo->fence_type; rep->rep_flags = 0; @@ -1292,7 +1306,7 @@ static void drm_buffer_user_object_unmap(struct drm_file *file_priv, /* * bo->mutex locked. - * Note that new_mem_flags are NOT transferred to the bo->mem.mask. + * Note that new_mem_flags are NOT transferred to the bo->mem.proposed_flags. */ int drm_bo_move_buffer(struct drm_buffer_object *bo, uint64_t new_mem_flags, @@ -1318,7 +1332,7 @@ int drm_bo_move_buffer(struct drm_buffer_object *bo, uint64_t new_mem_flags, mem.num_pages = bo->num_pages; mem.size = mem.num_pages << PAGE_SHIFT; - mem.mask = new_mem_flags; + mem.proposed_flags = new_mem_flags; mem.page_alignment = bo->mem.page_alignment; mutex_lock(&bm->evict_mutex); @@ -1361,18 +1375,18 @@ out_unlock: static int drm_bo_mem_compat(struct drm_bo_mem_reg *mem) { - uint32_t flag_diff = (mem->mask ^ mem->flags); + uint32_t flag_diff = (mem->proposed_flags ^ mem->flags); - if ((mem->mask & mem->flags & DRM_BO_MASK_MEM) == 0) + if ((mem->proposed_flags & mem->flags & DRM_BO_MASK_MEM) == 0) return 0; if ((flag_diff & DRM_BO_FLAG_CACHED) && - (/* !(mem->mask & DRM_BO_FLAG_CACHED) ||*/ - (mem->mask & DRM_BO_FLAG_FORCE_CACHING))) + (/* !(mem->proposed_flags & DRM_BO_FLAG_CACHED) ||*/ + (mem->proposed_flags & DRM_BO_FLAG_FORCE_CACHING))) return 0; if ((flag_diff & DRM_BO_FLAG_MAPPABLE) && - ((mem->mask & DRM_BO_FLAG_MAPPABLE) || - (mem->mask & DRM_BO_FLAG_FORCE_MAPPABLE))) + ((mem->proposed_flags & DRM_BO_FLAG_MAPPABLE) || + (mem->proposed_flags & DRM_BO_FLAG_FORCE_MAPPABLE))) return 0; return 1; } @@ -1408,8 +1422,8 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo, uint32_t ftype; int ret; - DRM_DEBUG("New flags 0x%016llx, Old flags 0x%016llx\n", - (unsigned long long) bo->mem.mask, + DRM_DEBUG("Proposed flags 0x%016llx, Old flags 0x%016llx\n", + (unsigned long long) bo->mem.proposed_flags, (unsigned long long) bo->mem.flags); ret = driver->fence_type(bo, &fence_class, &ftype); @@ -1450,7 +1464,7 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo, */ if (!drm_bo_mem_compat(&bo->mem)) { - ret = drm_bo_move_buffer(bo, bo->mem.mask, no_wait, + ret = drm_bo_move_buffer(bo, bo->mem.proposed_flags, no_wait, move_unfenced); if (ret) { if (ret != -EAGAIN) @@ -1463,7 +1477,7 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo, * Pinned buffers. */ - if (bo->mem.mask & (DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE)) { + if (bo->mem.proposed_flags & (DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE)) { bo->pinned_mem_type = bo->mem.mem_type; mutex_lock(&dev->struct_mutex); list_del_init(&bo->pinned_lru); @@ -1499,7 +1513,13 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo, if (ret) return ret; } - DRM_FLAG_MASKED(bo->mem.flags, bo->mem.mask, ~DRM_BO_MASK_MEMTYPE); + /* + * Validation has succeeded, move the access and other + * non-mapping-related flag bits from the proposed flags to + * the active flags + */ + + DRM_FLAG_MASKED(bo->mem.flags, bo->mem.proposed_flags, ~DRM_BO_MASK_MEMTYPE); /* * Finally, adjust lru to be sure. @@ -1563,9 +1583,7 @@ int drm_bo_do_validate(struct drm_buffer_object *bo, if (ret) goto out; - - DRM_FLAG_MASKED(flags, bo->mem.mask, ~mask); - ret = drm_bo_new_mask(bo, flags, mask); + ret = drm_bo_modify_proposed_flags (bo, flags, mask); if (ret) goto out; @@ -1712,7 +1730,7 @@ out: int drm_buffer_object_create(struct drm_device *dev, unsigned long size, enum drm_bo_type type, - uint64_t mask, + uint64_t flags, uint32_t hint, uint32_t page_alignment, unsigned long buffer_start, @@ -1757,12 +1775,14 @@ int drm_buffer_object_create(struct drm_device *dev, bo->mem.page_alignment = page_alignment; bo->buffer_start = buffer_start & PAGE_MASK; bo->priv_flags = 0; - bo->mem.flags = DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED | - DRM_BO_FLAG_MAPPABLE; - bo->mem.mask = DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED | - DRM_BO_FLAG_MAPPABLE; + bo->mem.flags = (DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED | + DRM_BO_FLAG_MAPPABLE); + bo->mem.proposed_flags = 0; atomic_inc(&bm->count); - ret = drm_bo_new_mask(bo, mask, mask); + /* + * Use drm_bo_modify_proposed_flags to error-check the proposed flags + */ + ret = drm_bo_modify_proposed_flags (bo, flags, flags); if (ret) goto out_err; @@ -1831,18 +1851,21 @@ int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *fil bo_type = (req->buffer_start) ? drm_bo_type_user : drm_bo_type_dc; + /* + * User buffers cannot be shared + */ if (bo_type == drm_bo_type_user) - req->mask &= ~DRM_BO_FLAG_SHAREABLE; + req->flags &= ~DRM_BO_FLAG_SHAREABLE; ret = drm_buffer_object_create(file_priv->head->dev, - req->size, bo_type, req->mask, + req->size, bo_type, req->flags, req->hint, req->page_alignment, req->buffer_start, &entry); if (ret) goto out; ret = drm_bo_add_user_object(file_priv, entry, - req->mask & DRM_BO_FLAG_SHAREABLE); + req->flags & DRM_BO_FLAG_SHAREABLE); if (ret) { drm_bo_usage_deref_unlocked(&entry); goto out; @@ -2034,7 +2057,7 @@ static int drm_bo_leave_list(struct drm_buffer_object *bo, DRM_ERROR("A DRM_BO_NO_EVICT buffer present at " "cleanup. Removing flag and evicting.\n"); bo->mem.flags &= ~DRM_BO_FLAG_NO_EVICT; - bo->mem.mask &= ~DRM_BO_FLAG_NO_EVICT; + bo->mem.proposed_flags &= ~DRM_BO_FLAG_NO_EVICT; } if (bo->mem.mem_type == mem_type) diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c index 4afdfbb..b06a09f 100644 --- a/linux-core/drm_bo_move.c +++ b/linux-core/drm_bo_move.c @@ -54,7 +54,7 @@ int drm_bo_move_ttm(struct drm_buffer_object *bo, struct drm_ttm *ttm = bo->ttm; struct drm_bo_mem_reg *old_mem = &bo->mem; uint64_t save_flags = old_mem->flags; - uint64_t save_mask = old_mem->mask; + uint64_t save_proposed_flags = old_mem->proposed_flags; int ret; if (old_mem->mem_type == DRM_BO_MEM_TT) { @@ -78,7 +78,7 @@ int drm_bo_move_ttm(struct drm_buffer_object *bo, *old_mem = *new_mem; new_mem->mm_node = NULL; - old_mem->mask = save_mask; + old_mem->proposed_flags = save_proposed_flags; DRM_FLAG_MASKED(save_flags, new_mem->flags, DRM_BO_MASK_MEMTYPE); return 0; } @@ -210,7 +210,7 @@ int drm_bo_move_memcpy(struct drm_buffer_object *bo, void *new_iomap; int ret; uint64_t save_flags = old_mem->flags; - uint64_t save_mask = old_mem->mask; + uint64_t save_proposed_flags = old_mem->proposed_flags; unsigned long i; unsigned long page; unsigned long add = 0; @@ -255,7 +255,7 @@ out2: *old_mem = *new_mem; new_mem->mm_node = NULL; - old_mem->mask = save_mask; + old_mem->proposed_flags = save_proposed_flags; DRM_FLAG_MASKED(save_flags, new_mem->flags, DRM_BO_MASK_MEMTYPE); if ((man->flags & _DRM_FLAG_MEMTYPE_FIXED) && (ttm != NULL)) { @@ -330,7 +330,7 @@ int drm_bo_move_accel_cleanup(struct drm_buffer_object *bo, struct drm_bo_mem_reg *old_mem = &bo->mem; int ret; uint64_t save_flags = old_mem->flags; - uint64_t save_mask = old_mem->mask; + uint64_t save_proposed_flags = old_mem->proposed_flags; struct drm_buffer_object *old_obj; if (bo->fence) @@ -399,7 +399,7 @@ int drm_bo_move_accel_cleanup(struct drm_buffer_object *bo, *old_mem = *new_mem; new_mem->mm_node = NULL; - old_mem->mask = save_mask; + old_mem->proposed_flags = save_proposed_flags; DRM_FLAG_MASKED(save_flags, new_mem->flags, DRM_BO_MASK_MEMTYPE); return 0; } diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 47b6b01..98421e4 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -385,8 +385,20 @@ struct drm_bo_mem_reg { unsigned long num_pages; uint32_t page_alignment; uint32_t mem_type; + /* + * Current buffer status flags, indicating + * where the buffer is located and which + * access modes are in effect + */ uint64_t flags; - uint64_t mask; + /** + * These are the flags proposed for + * a validate operation. If the + * validate succeeds, they'll get moved + * into the flags field + */ + uint64_t proposed_flags; + uint32_t desired_tile_stride; uint32_t hw_tile_stride; }; @@ -511,9 +523,36 @@ struct drm_bo_driver { int (*invalidate_caches) (struct drm_device *dev, uint64_t flags); int (*init_mem_type) (struct drm_device *dev, uint32_t type, struct drm_mem_type_manager *man); - uint32_t(*evict_mask) (struct drm_buffer_object *bo); + /* + * evict_flags: + * + * @bo: the buffer object to be evicted + * + * Return the bo flags for a buffer which is not mapped to the hardware. + * These will be placed in proposed_flags so that when the move is + * finished, they'll end up in bo->mem.flags + */ + uint64_t(*evict_flags) (struct drm_buffer_object *bo); + /* + * move: + * + * @bo: the buffer to move + * + * @evict: whether this motion is evicting the buffer from + * the graphics address space + * + * @no_wait: whether this should give up and return -EBUSY + * if this move would require sleeping + * + * @new_mem: the new memory region receiving the buffer + * + * Move a buffer between two memory regions. + */ int (*move) (struct drm_buffer_object *bo, int evict, int no_wait, struct drm_bo_mem_reg *new_mem); + /* + * ttm_cache_flush + */ void (*ttm_cache_flush)(struct drm_ttm *ttm); }; @@ -554,7 +593,7 @@ extern int drm_fence_buffer_objects(struct drm_device *dev, struct drm_fence_object **used_fence); extern void drm_bo_add_to_lru(struct drm_buffer_object *bo); extern int drm_buffer_object_create(struct drm_device *dev, unsigned long size, - enum drm_bo_type type, uint64_t mask, + enum drm_bo_type type, uint64_t flags, uint32_t hint, uint32_t page_alignment, unsigned long buffer_start, struct drm_buffer_object **bo); diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index f2681cc..dcefcb3 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -751,10 +751,10 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, */ if (!(bo->mem.flags & DRM_BO_FLAG_MAPPABLE)) { - uint32_t new_mask = bo->mem.mask | + uint32_t new_flags = bo->mem.proposed_flags | DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_FORCE_MAPPABLE; - err = drm_bo_move_buffer(bo, new_mask, 0, 0); + err = drm_bo_move_buffer(bo, new_flags, 0, 0); if (err) { ret = (err != -EAGAIN) ? NOPFN_SIGBUS : NOPFN_REFAULT; goto out_unlock; diff --git a/linux-core/i915_buffer.c b/linux-core/i915_buffer.c index b000a72..3dd236d 100644 --- a/linux-core/i915_buffer.c +++ b/linux-core/i915_buffer.c @@ -38,11 +38,11 @@ struct drm_ttm_backend *i915_create_ttm_backend_entry(struct drm_device *dev) return drm_agp_init_ttm(dev); } -int i915_fence_types(struct drm_buffer_object *bo, +int i915_fence_type(struct drm_buffer_object *bo, uint32_t *fclass, uint32_t *type) { - if (bo->mem.mask & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) + if (bo->mem.proposed_flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) *type = 3; else *type = 1; @@ -110,7 +110,16 @@ int i915_init_mem_type(struct drm_device *dev, uint32_t type, return 0; } -uint32_t i915_evict_mask(struct drm_buffer_object *bo) +/* + * i915_evict_flags: + * + * @bo: the buffer object to be evicted + * + * Return the bo flags for a buffer which is not mapped to the hardware. + * These will be placed in proposed_flags so that when the move is + * finished, they'll end up in bo->mem.flags + */ +uint64_t i915_evict_flags(struct drm_buffer_object *bo) { switch (bo->mem.mem_type) { case DRM_BO_MEM_LOCAL: diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index d2bcf4b..d3a4ab3 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -61,10 +61,10 @@ static struct drm_bo_driver i915_bo_driver = { .num_mem_type_prio = sizeof(i915_mem_prios)/sizeof(uint32_t), .num_mem_busy_prio = sizeof(i915_busy_prios)/sizeof(uint32_t), .create_ttm_backend_entry = i915_create_ttm_backend_entry, - .fence_type = i915_fence_types, + .fence_type = i915_fence_type, .invalidate_caches = i915_invalidate_caches, .init_mem_type = i915_init_mem_type, - .evict_mask = i915_evict_mask, + .evict_flags = i915_evict_flags, .move = i915_move, .ttm_cache_flush = i915_flush_ttm, }; diff --git a/linux-core/nouveau_buffer.c b/linux-core/nouveau_buffer.c index 59751ff..a652bb1 100644 --- a/linux-core/nouveau_buffer.c +++ b/linux-core/nouveau_buffer.c @@ -56,7 +56,7 @@ nouveau_bo_fence_type(struct drm_buffer_object *bo, { /* When we get called, *fclass is set to the requested fence class */ - if (bo->mem.mask & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) + if (bo->mem.proposed_flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) *type = 3; else *type = 1; @@ -130,8 +130,8 @@ nouveau_bo_init_mem_type(struct drm_device *dev, uint32_t type, return 0; } -static uint32_t -nouveau_bo_evict_mask(struct drm_buffer_object *bo) +static uint64_t +nouveau_bo_evict_flags(struct drm_buffer_object *bo) { switch (bo->mem.mem_type) { case DRM_BO_MEM_LOCAL: @@ -207,8 +207,9 @@ nouveau_bo_move_gart(struct drm_buffer_object *bo, int evict, int no_wait, tmp_mem = *new_mem; tmp_mem.mm_node = NULL; - tmp_mem.mask = DRM_BO_FLAG_MEM_TT | - DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING; + tmp_mem.proposed_flags = (DRM_BO_FLAG_MEM_TT | + DRM_BO_FLAG_CACHED | + DRM_BO_FLAG_FORCE_CACHING); ret = drm_bo_mem_space(bo, &tmp_mem, no_wait); @@ -291,7 +292,7 @@ struct drm_bo_driver nouveau_bo_driver = { .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, + .evict_flags = nouveau_bo_evict_flags, .move = nouveau_bo_move, .ttm_cache_flush= nouveau_bo_flush_ttm }; diff --git a/linux-core/via_buffer.c b/linux-core/via_buffer.c index ea75524..532fae6 100644 --- a/linux-core/via_buffer.c +++ b/linux-core/via_buffer.c @@ -144,7 +144,7 @@ int via_init_mem_type(struct drm_device * dev, uint32_t type, return 0; } -uint32_t via_evict_mask(struct drm_buffer_object *bo) +uint64_t via_evict_flags(struct drm_buffer_object *bo) { switch (bo->mem.mem_type) { case DRM_BO_MEM_LOCAL: diff --git a/shared-core/drm.h b/shared-core/drm.h index 6f6f238..6b4125f 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -662,6 +662,10 @@ struct drm_fence_arg { #define DRM_BO_FLAG_EXE (1ULL << 2) /* + * All of the bits related to access mode + */ +#define DRM_BO_MASK_ACCESS (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE) +/* * Status flags. Can be read to determine the actual state of a buffer. * Can also be set in the buffer mask before validation. */ @@ -741,10 +745,21 @@ struct drm_fence_arg { #define DRM_BO_FLAG_MEM_PRIV4 (1ULL << 31) /* We can add more of these now with a 64-bit flag type */ -/* Memory flag mask */ +/* + * This is a mask covering all of the memory type flags; easier to just + * use a single constant than a bunch of | values. It covers + * DRM_BO_FLAG_MEM_LOCAL through DRM_BO_FLAG_MEM_PRIV4 + */ #define DRM_BO_MASK_MEM 0x00000000FF000000ULL -#define DRM_BO_MASK_MEMTYPE 0x00000000FF0800A0ULL - +/* + * This adds all of the CPU-mapping options in with the memory + * type to label all bits which change how the page gets mapped + */ +#define DRM_BO_MASK_MEMTYPE (DRM_BO_MASK_MEM | \ + DRM_BO_FLAG_CACHED_MAPPED | \ + DRM_BO_FLAG_CACHED | \ + DRM_BO_FLAG_MAPPABLE) + /* Driver-private flags */ #define DRM_BO_MASK_DRIVER 0xFFFF000000000000ULL @@ -794,7 +809,7 @@ struct drm_bo_info_req { }; struct drm_bo_create_req { - uint64_t mask; + uint64_t flags; uint64_t size; uint64_t buffer_start; unsigned int hint; @@ -810,7 +825,7 @@ struct drm_bo_create_req { struct drm_bo_info_rep { uint64_t flags; - uint64_t mask; + uint64_t proposed_flags; uint64_t size; uint64_t offset; uint64_t arg_handle; diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index bdc7841..2bdd4b7 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -303,12 +303,12 @@ extern int i915_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t f #ifdef I915_HAVE_BUFFER /* i915_buffer.c */ extern struct drm_ttm_backend *i915_create_ttm_backend_entry(struct drm_device *dev); -extern int i915_fence_types(struct drm_buffer_object *bo, uint32_t *fclass, - uint32_t *type); +extern int i915_fence_type(struct drm_buffer_object *bo, uint32_t *fclass, + uint32_t *type); extern int i915_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags); extern int i915_init_mem_type(struct drm_device *dev, uint32_t type, struct drm_mem_type_manager *man); -extern uint32_t i915_evict_mask(struct drm_buffer_object *bo); +extern uint64_t i915_evict_flags(struct drm_buffer_object *bo); extern int i915_move(struct drm_buffer_object *bo, int evict, int no_wait, struct drm_bo_mem_reg *new_mem); void i915_flush_ttm(struct drm_ttm *ttm); diff --git a/shared-core/via_drv.c b/shared-core/via_drv.c index 9f09955..6528a7c 100644 --- a/shared-core/via_drv.c +++ b/shared-core/via_drv.c @@ -74,7 +74,7 @@ static struct drm_bo_driver via_bo_driver = { .fence_type = via_fence_types, .invalidate_caches = via_invalidate_caches, .init_mem_type = via_init_mem_type, - .evict_mask = via_evict_mask, + .evict_flags = via_evict_flags, .move = NULL, }; #endif diff --git a/shared-core/via_drv.h b/shared-core/via_drv.h index d6da8bd..39aedb1 100644 --- a/shared-core/via_drv.h +++ b/shared-core/via_drv.h @@ -211,7 +211,7 @@ extern int via_fence_types(struct drm_buffer_object *bo, uint32_t *fclass, extern int via_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags); extern int via_init_mem_type(struct drm_device *dev, uint32_t type, struct drm_mem_type_manager *man); -extern uint32_t via_evict_mask(struct drm_buffer_object *bo); +extern uint64_t via_evict_flags(struct drm_buffer_object *bo); extern int via_move(struct drm_buffer_object *bo, int evict, int no_wait, struct drm_bo_mem_reg *new_mem); #endif commit 37fb2ac4071f62bad2c36cc9ca84f9c8feee6bf5 Author: Keith Packard <ke...@ke...> Date: Sun Dec 16 01:47:51 2007 -0800 Use dummy_read_page for unpopulated kernel-allocated ttm pages. Previously, dummy_read_page was used only for read-only user allocations; it filled in pages that were not present in the user address map (presumably, these were allocated but never written to pages). This patch allows them to be used for read-only ttms allocated from the kernel, so that applications can over-allocate buffers without forcing every page to be allocated. diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index e8bfaea..0218701 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -505,12 +505,14 @@ static int drm_agp_needs_unbind_cache_adjust(struct drm_ttm_backend *backend) static int drm_agp_populate(struct drm_ttm_backend *backend, - unsigned long num_pages, struct page **pages) + unsigned long num_pages, struct page **pages, + struct page *dummy_read_page) { struct drm_agp_ttm_backend *agp_be = container_of(backend, struct drm_agp_ttm_backend, backend); struct page **cur_page, **last_page = pages + num_pages; DRM_AGP_MEM *mem; + int dummy_page_count = 0; if (drm_alloc_memctl(num_pages * sizeof(void *))) return -1; @@ -528,8 +530,16 @@ static int drm_agp_populate(struct drm_ttm_backend *backend, DRM_DEBUG("Current page count is %ld\n", (long) mem->page_count); mem->page_count = 0; - for (cur_page = pages; cur_page < last_page; ++cur_page) - mem->memory[mem->page_count++] = phys_to_gart(page_to_phys(*cur_page)); + for (cur_page = pages; cur_page < last_page; ++cur_page) { + struct page *page = *cur_page; + if (!page) { + page = dummy_read_page; + ++dummy_page_count; + } + mem->memory[mem->page_count++] = phys_to_gart(page_to_phys(page)); + } + if (dummy_page_count) + DRM_DEBUG("Mapped %d dummy pages\n", dummy_page_count); agp_be->mem = mem; return 0; } diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 375420d..47b6b01 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -263,7 +263,8 @@ struct drm_ttm_backend; struct drm_ttm_backend_func { int (*needs_ub_cache_adjust) (struct drm_ttm_backend *backend); int (*populate) (struct drm_ttm_backend *backend, - unsigned long num_pages, struct page **pages); + unsigned long num_pages, struct page **pages, + struct page *dummy_read_page); void (*clear) (struct drm_ttm_backend *backend); int (*bind) (struct drm_ttm_backend *backend, struct drm_bo_mem_reg *bo_mem); diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index c1fc13f..a9d8733 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -262,7 +262,6 @@ int drm_ttm_set_user(struct drm_ttm *ttm, { struct mm_struct *mm = tsk->mm; int ret; - int i; int write = (ttm->page_flags & DRM_TTM_PAGE_WRITE) != 0; BUG_ON(num_pages != ttm->num_pages); @@ -278,11 +277,6 @@ int drm_ttm_set_user(struct drm_ttm *ttm, return -ENOMEM; } - for (i = 0; i < num_pages; ++i) { - if (ttm->pages[i] == NULL) - ttm->pages[i] = ttm->dummy_read_page; - } - return 0; } @@ -304,12 +298,14 @@ int drm_ttm_populate(struct drm_ttm *ttm) return 0; be = ttm->be; - for (i = 0; i < ttm->num_pages; ++i) { - page = drm_ttm_get_page(ttm, i); - if (!page) - return -ENOMEM; + if (ttm->page_flags & DRM_TTM_PAGE_WRITE) { + for (i = 0; i < ttm->num_pages; ++i) { + page = drm_ttm_get_page(ttm, i); + if (!page) + return -ENOMEM; + } } - be->func->populate(be, ttm->num_pages, ttm->pages); + be->func->populate(be, ttm->num_pages, ttm->pages, ttm->dummy_read_page); ttm->state = ttm_unbound; return 0; } diff --git a/linux-core/nouveau_sgdma.c b/linux-core/nouveau_sgdma.c index f3bf534..6c61819 100644 --- a/linux-core/nouveau_sgdma.c +++ b/linux-core/nouveau_sgdma.c @@ -25,7 +25,7 @@ nouveau_sgdma_needs_ub_cache_adjust(struct drm_ttm_backend *be) static int nouveau_sgdma_populate(struct drm_ttm_backend *be, unsigned long num_pages, - struct page **pages) + struct page **pages, struct page *dummy_read_page) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; int p, d, o; @@ -41,8 +41,11 @@ nouveau_sgdma_populate(struct drm_ttm_backend *be, unsigned long num_pages, nvbe->pages_populated = d = 0; for (p = 0; p < num_pages; p++) { for (o = 0; o < PAGE_SIZE; o += NV_CTXDMA_PAGE_SIZE) { + struct page *page = pages[p]; + if (!page) + page = dummy_read_page; nvbe->pagelist[d] = pci_map_page(nvbe->dev->pdev, - pages[p], o, + page, o, NV_CTXDMA_PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); if (pci_dma_mapping_error(nvbe->pagelist[d])) { @@ -299,7 +302,7 @@ nouveau_sgdma_nottm_hack_init(struct drm_device *dev) } dev_priv->gart_info.sg_handle = sgreq.handle; - if ((ret = be->func->populate(be, dev->sg->pages, dev->sg->pagelist))) { + if ((ret = be->func->populate(be, dev->sg->pages, dev->sg->pagelist, dev->bm.dummy_read_page))) { DRM_ERROR("failed populate: %d\n", ret); return ret; } commit 881ee70ab7bab5d6f6140dc9bf1e19c7b5844084 Author: Keith Packard <ke...@ke...> Date: Sun Dec 16 01:12:07 2007 -0800 Move dummy_read_page from drm_ttm_set_user to drm_ttm_create. I'm hoping to use the dummy_read_page for kernel allocated buffers to avoid allocating extra pages for read-only buffers (like vertex and batch buffers). This also eliminates the 'write' parameter to drm_ttm_set_user and just has DRM_TTM_PAGE_WRITE passed into drm_ttm_create. diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index eced94e..e7b9c5b 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -137,27 +137,32 @@ static int drm_bo_add_ttm(struct drm_buffer_object *bo) { struct drm_device *dev = bo->dev; int ret = 0; + uint32_t page_flags = 0; DRM_ASSERT_LOCKED(&bo->mutex); bo->ttm = NULL; + if (bo->mem.mask & DRM_BO_FLAG_WRITE) + page_flags |= DRM_TTM_PAGE_WRITE; + switch (bo->type) { case drm_bo_type_dc: case drm_bo_type_kernel: - bo->ttm = drm_ttm_create(dev, bo->num_pages << PAGE_SHIFT, 0); + bo->ttm = drm_ttm_create(dev, bo->num_pages << PAGE_SHIFT, + page_flags, dev->bm.dummy_read_page); if (!bo->ttm) ret = -ENOMEM; break; case drm_bo_type_user: - bo->ttm = drm_ttm_create(dev, bo->num_pages << PAGE_SHIFT, DRM_TTM_PAGE_USER); + bo->ttm = drm_ttm_create(dev, bo->num_pages << PAGE_SHIFT, + page_flags | DRM_TTM_PAGE_USER, + dev->bm.dummy_read_page); if (!bo->ttm) ret = -ENOMEM; ret = drm_ttm_set_user(bo->ttm, current, - bo->mem.mask & DRM_BO_FLAG_WRITE, bo->buffer_start, - bo->num_pages, - dev->bm.dummy_read_page); + bo->num_pages); if (ret) return ret; diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index fa029d8..375420d 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -297,7 +297,9 @@ struct drm_ttm { }; -extern struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size, uint32_t page_flags); +extern struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size, + uint32_t page_flags, + struct page *dummy_read_page); extern int drm_ttm_bind(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); @@ -307,10 +309,8 @@ extern void drm_ttm_cache_flush(void); extern int drm_ttm_populate(struct drm_ttm *ttm); extern int drm_ttm_set_user(struct drm_ttm *ttm, struct task_struct *tsk, - int write, unsigned long start, - unsigned long num_pages, - struct page *dummy_read_page); + unsigned long num_pages); /* * Destroy a ttm. The user normally calls drmRmMap or a similar IOCTL to do @@ -362,7 +362,7 @@ extern int drm_ttm_destroy(struct drm_ttm *ttm); /* * This ttm will be written to by the GPU */ -#define DRM_TTM_PAGE_USER_WRITE (1 << 6) +#define DRM_TTM_PAGE_WRITE (1 << 6) /* * This ttm was mapped to the GPU, and so the contents may have * been modified diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index e3b9fcc..c1fc13f 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -145,7 +145,7 @@ static void drm_ttm_free_user_pages(struct drm_ttm *ttm) int i; BUG_ON(!(ttm->page_flags & DRM_TTM_PAGE_USER)); - write = ((ttm->page_flags & DRM_TTM_PAGE_USER_WRITE) != 0); + write = ((ttm->page_flags & DRM_TTM_PAGE_WRITE) != 0); dirty = ((ttm->page_flags & DRM_TTM_PAGE_USER_DIRTY) != 0); for (i = 0; i < ttm->num_pages; ++i) { @@ -257,22 +257,17 @@ EXPORT_SYMBOL(drm_ttm_get_page); */ int drm_ttm_set_user(struct drm_ttm *ttm, struct task_struct *tsk, - int write, unsigned long start, - unsigned long num_pages, - struct page *dummy_read_page) + unsigned long num_pages) { struct mm_struct *mm = tsk->mm; int ret; int i; + int write = (ttm->page_flags & DRM_TTM_PAGE_WRITE) != 0; BUG_ON(num_pages != ttm->num_pages); BUG_ON((ttm->page_flags & DRM_TTM_PAGE_USER) == 0); - ttm->dummy_read_page = dummy_read_page; - if (write) - ttm->page_flags |= DRM_TTM_PAGE_USER_WRITE; - down_read(&mm->mmap_sem); ret = get_user_pages(tsk, mm, start, num_pages, write, 0, ttm->pages, NULL); @@ -331,7 +326,8 @@ int drm_ttm_populate(struct drm_ttm *ttm) * Allocate and initialize a ttm, leaving it unpopulated at this time */ -struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size, uint32_t page_flags) +struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size, + uint32_t page_flags, struct page *dummy_read_page) { struct drm_bo_driver *bo_driver = dev->driver->bo_driver; struct drm_ttm *ttm; @@ -351,6 +347,8 @@ struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size, uint3 ttm->page_flags = page_flags; + ttm->dummy_read_page = dummy_read_page; + /* * Account also for AGP module memory usage. */ commit 6d44f48002c19d67187adb660ef74dd1870d52c2 Author: Keith Packard <ke...@ke...> Date: Sun Dec 16 00:54:25 2007 -0800 Clean up and document drm_ttm.c APIs. drm_bind_ttm -> drm_ttm_bind. Aside from changing drm_bind_ttm to drm_ttm_bind, this patch adds only documentation and fixes the functions inside drm_ttm.c to all be prefixed with drm_ttm_. diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 7033a8b..eced94e 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -199,7 +199,7 @@ static int drm_bo_handle_move_mem(struct drm_buffer_object *bo, goto out_err; if (mem->mem_type != DRM_BO_MEM_LOCAL) { - ret = drm_bind_ttm(bo->ttm, mem); + ret = drm_ttm_bind(bo->ttm, mem); if (ret) goto out_err; } diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c index 00d8d3e..4afdfbb 100644 --- a/linux-core/drm_bo_move.c +++ b/linux-core/drm_bo_move.c @@ -71,7 +71,7 @@ int drm_bo_move_ttm(struct drm_buffer_object *bo, save_flags = old_mem->flags; } if (new_mem->mem_type != DRM_BO_MEM_LOCAL) { - ret = drm_bind_ttm(ttm, new_mem); + ret = drm_ttm_bind(ttm, new_mem); if (ret) return ret; } diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 0926b47..fa029d8 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -298,7 +298,7 @@ struct drm_ttm { }; 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 int drm_ttm_bind(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); extern void drm_ttm_fixup_caching(struct drm_ttm *ttm); @@ -331,14 +331,47 @@ extern int drm_ttm_destroy(struct drm_ttm *ttm); * Page flags. */ +/* + * This ttm should not be cached by the CPU + */ #define DRM_TTM_PAGE_UNCACHED (1 << 0) +/* + * This flat is not used at this time; I don't know what the + * intent was + */ #define DRM_TTM_PAGE_USED (1 << 1) +/* + * This flat is not used at this time; I don't know what the + * intent was + */ #define DRM_TTM_PAGE_BOUND (1 << 2) +/* + * This flat is not used at this time; I don't know what the + * intent was + */ #define DRM_TTM_PAGE_PRESENT (1 << 3) +/* + * The array of page pointers was allocated with vmalloc + * instead of drm_calloc. + */ #define DRM_TTM_PAGE_VMALLOC (1 << 4) +/* + * This ttm is mapped from user space + */ #define DRM_TTM_PAGE_USER (1 << 5) -#define DRM_TTM_PAGE_USER_WRITE (1 << 6) +/* + * This ttm will be written to by the GPU + */ +#define DRM_TTM_PAGE_USER_WRITE (1 << 6) +/* + * This ttm was mapped to the GPU, and so the contents may have + * been modified + */ #define DRM_TTM_PAGE_USER_DIRTY (1 << 7) +/* + * This flag is not used at this time; I don't know what the + * intent was. + */ #define DRM_TTM_PAGE_USER_DMA (1 << 8) /*************************************************** diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index 4c1b327..e3b9fcc 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -46,7 +46,7 @@ EXPORT_SYMBOL(drm_ttm_cache_flush); * Use kmalloc if possible. Otherwise fall back to vmalloc. */ -static void ttm_alloc_pages(struct drm_ttm *ttm) +static void drm_ttm_alloc_pages(struct drm_ttm *ttm) { unsigned long size = ttm->num_pages * sizeof(*ttm->pages); ttm->pages = NULL; @@ -66,7 +66,7 @@ static void ttm_alloc_pages(struct drm_ttm *ttm) drm_free_memctl(size); } -static void ttm_free_pages(struct drm_ttm *ttm) +static void drm_ttm_free_pages(struct drm_ttm *ttm) { unsigned long size = ttm->num_pages * sizeof(*ttm->pages); @@ -103,7 +103,7 @@ static struct page *drm_ttm_alloc_page(void) * for range of pages in a ttm. */ -static int drm_set_caching(struct drm_ttm *ttm, int noncached) +static int drm_ttm_set_caching(struct drm_ttm *ttm, int noncached) { int i; struct page **cur_page; @@ -208,14 +208,14 @@ int drm_ttm_destroy(struct drm_ttm *ttm) if (ttm->pages) { if (ttm->page_flags & DRM_TTM_PAGE_UNCACHED) - drm_set_caching(ttm, 0); + drm_ttm_set_caching(ttm, 0); if (ttm->page_flags & DRM_TTM_PAGE_USER) drm_ttm_free_user_pages(ttm); else drm_ttm_free_alloced_pages(ttm); - ttm_free_pages(ttm); + drm_ttm_free_pages(ttm); } drm_ctl_free(ttm, sizeof(*ttm), DRM_MEM_TTM); @@ -291,6 +291,14 @@ int drm_ttm_set_user(struct drm_ttm *ttm, return 0; } +/** + * drm_ttm_populate: + * + * @ttm: the object to allocate pages for + * + * Allocate pages for all unset page entries, then + * call the backend to create the hardware mappings + */ int drm_ttm_populate(struct drm_ttm *ttm) { struct page *page; @@ -311,8 +319,16 @@ int drm_ttm_populate(struct drm_ttm *ttm) return 0; } -/* - * Initialize a ttm. +/** + * drm_ttm_create: + * + * @dev: the drm_device + * + * @size: The size (in bytes) of the desired object + * + * @page_flags: various DRM_TTM_PAGE_* flags. See drm_object.h. + * + * Allocate and initialize a ttm, leaving it unpopulated at this time */ struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size, uint32_t page_flags) @@ -339,7 +355,7 @@ struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size, uint3 * Account also for AGP module memory usage. */ - ttm_alloc_pages(ttm); + drm_ttm_alloc_pages(ttm); if (!ttm->pages) { drm_ttm_destroy(ttm); DRM_ERROR("Failed allocating page table\n"); @@ -355,10 +371,15 @@ struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size, uint3 return ttm; } -/* - * Unbind a ttm region from the aperture. +/** + * drm_ttm_evict: + * + * @ttm: the object to be unbound from the aperture. + * + * Transition a ttm from bound to evicted, where it + * isn't present in the aperture, but various caches may + * not be consistent. */ - void drm_ttm_evict(struct drm_ttm *ttm) { struct drm_ttm_backend *be = ttm->be; @@ -372,17 +393,33 @@ void drm_ttm_evict(struct drm_ttm *ttm) ttm->state = ttm_evicted; } +/** + * drm_ttm_fixup_caching: + * + * @ttm: the object to set unbound + * + * XXX this function is misnamed. Transition a ttm from evicted to + * unbound, flushing caches as appropriate. + */ void drm_ttm_fixup_caching(struct drm_ttm *ttm) { if (ttm->state == ttm_evicted) { struct drm_ttm_backend *be = ttm->be; if (be->func->needs_ub_cache_adjust(be)) - drm_set_caching(ttm, 0); + drm_ttm_set_caching(ttm, 0); ttm->state = ttm_unbound; } } +/** + * drm_ttm_unbind: + * + * @ttm: the object to unbind from the graphics device + * + * Unbind an object from the aperture. This removes the mappings + * from the graphics device and flushes caches if necessary. + */ void drm_ttm_unbind(struct drm_ttm *ttm) { if (ttm->state == ttm_bound) @@ -391,7 +428,19 @@ void drm_ttm_unbind(struct drm_ttm *ttm) drm_ttm_fixup_caching(ttm); } -int drm_bind_ttm(struct drm_ttm *ttm, struct drm_bo_mem_reg *bo_mem) +/** + * drm_ttm_bind: + * + * @ttm: the ttm object to bind to the graphics device + * + * @bo_mem: the aperture memory region which will hold the object + * + * Bind a ttm object to the aperture. This ensures that the necessary + * pages are allocated, flushes CPU caches as needed and marks the + * ttm as DRM_TTM_PAGE_USER_DIRTY to indicate that it may have been + * modified by the GPU + */ +int drm_ttm_bind(struct drm_ttm *ttm, struct drm_bo_mem_reg *bo_mem) { struct drm_bo_driver *bo_driver = ttm->dev->driver->bo_driver; int ret = 0; @@ -409,7 +458,7 @@ int drm_bind_ttm(struct drm_ttm *ttm, struct drm_bo_mem_reg *bo_mem) return ret; if (ttm->state == ttm_unbound && !(bo_mem->flags & DRM_BO_FLAG_CACHED)) - drm_set_caching(ttm, DRM_TTM_PAGE_UNCACHED); + drm_ttm_set_caching(ttm, DRM_TTM_PAGE_UNCACHED); else if ((bo_mem->flags & DRM_BO_FLAG_CACHED_MAPPED) && bo_driver->ttm_cache_flush) bo_driver->ttm_cache_flush(ttm); @@ -426,4 +475,4 @@ int drm_bind_ttm(struct drm_ttm *ttm, struct drm_bo_mem_reg *bo_mem) ttm->page_flags |= DRM_TTM_PAGE_USER_DIRTY; return 0; } -EXPORT_SYMBOL(drm_bind_ttm); +EXPORT_SYMBOL(drm_ttm_bind); diff --git a/linux-core/nouveau_buffer.c b/linux-core/nouveau_buffer.c index 9b252a0..59751ff 100644 --- a/linux-core/nouveau_buffer.c +++ b/linux-core/nouveau_buffer.c @@ -215,7 +215,7 @@ nouveau_bo_move_gart(struct drm_buffer_object *bo, int evict, int no_wait, if (ret) return ret; - ret = drm_bind_ttm(bo->ttm, &tmp_mem); + ret = drm_ttm_bind (bo->ttm, &tmp_mem); if (ret) goto out_cleanup; |
From: <th...@ke...> - 2008-03-12 11:40:02
|
linux-core/Makefile.kernel | 2 linux-core/drm_compat.c | 4 linux-core/drm_compat.h | 1 linux-core/i915_execbuf.c | 911 +++++++++++++++++++++++++++++++++++++++++++++ shared-core/i915_dma.c | 563 --------------------------- shared-core/i915_drm.h | 14 shared-core/i915_drv.h | 12 7 files changed, 941 insertions(+), 566 deletions(-) New commits: commit 88bd1e4a350d011ec44f6786e0bfdf8fb386800c Merge: 2a618e5... 612c22f... Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> Date: Wed Mar 12 11:34:29 2008 +0100 Merge branch 'intel-post-reloc' Conflicts: linux-core/drm_compat.c linux-core/drm_compat.h linux-core/drm_ttm.c shared-core/i915_dma.c Bump driver minor to 13 due to introduction of new relocation type. diff --cc linux-core/drm_compat.c index d4044cb,32e43a0..5dabeae --- a/linux-core/drm_compat.c +++ b/linux-core/drm_compat.c @@@ -730,7 -730,8 +730,7 @@@ void *idr_replace(struct idr *idp, voi EXPORT_SYMBOL(idr_replace); #endif - #if defined(DRM_KMAP_ATOMIC_PROT_PFN) && defined(CONFIG_HIMEM) -#if defined(CONFIG_X86) - ++#if defined(DRM_KMAP_ATOMIC_PROT_PFN) #define drm_kmap_get_fixmap_pte(vaddr) \ pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), vaddr), (vaddr)), (vaddr)) @@@ -758,5 -759,5 +758,3 @@@ void *kmap_atomic_prot_pfn(unsigned lon EXPORT_SYMBOL(kmap_atomic_prot_pfn); #endif -- -- diff --cc linux-core/drm_compat.h index 8f2d9a9,39027cf..0613b5d --- a/linux-core/drm_compat.h +++ b/linux-core/drm_compat.h @@@ -328,7 -328,7 +328,8 @@@ void *idr_replace(struct idr *idp, voi typedef _Bool bool; #endif -#if defined(CONFIG_X86) ++ +#if (defined(CONFIG_X86) && defined(CONFIG_X86_32) && defined(CONFIG_HIMEM)) #define DRM_KMAP_ATOMIC_PROT_PFN extern void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t protection); diff --cc linux-core/i915_execbuf.c index 0000000,cb0e734..ff83d79 mode 000000,100644..100644 --- a/linux-core/i915_execbuf.c +++ b/linux-core/i915_execbuf.c @@@ -1,0 -1,912 +1,911 @@@ + /* + * Copyright 2003-2008 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. + * + * Authors: + * Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> + * Dave Airlie - * ? ++ * Keith Packard ++ * ... ? + */ + + #include "drmP.h" + #include "drm.h" + #include "i915_drm.h" + #include "i915_drv.h" + + #if DRM_DEBUG_CODE + #define DRM_DEBUG_RELOCATION (drm_debug != 0) + #else + #define DRM_DEBUG_RELOCATION 0 + #endif + + enum i915_buf_idle { - i915_reloc_unchecked, - i915_reloc_idle, - i915_reloc_busy ++ I915_RELOC_UNCHECKED, ++ I915_RELOC_IDLE, ++ I915_RELOC_BUSY + }; + + struct i915_relocatee_info { + struct drm_buffer_object *buf; + unsigned long offset; + uint32_t *data_page; + unsigned page_offset; + struct drm_bo_kmap_obj kmap; + int is_iomem; + int dst; + int idle; + int performed_ring_relocs; + #ifdef DRM_KMAP_ATOMIC_PROT_PFN + unsigned long pfn; + pgprot_t pg_prot; + #endif + }; + + struct drm_i915_validate_buffer { + struct drm_buffer_object *buffer; + struct drm_bo_info_rep rep; + int presumed_offset_correct; + void __user *data; + int ret; + enum i915_buf_idle idle; + }; + + /* + * I'd like to use MI_STORE_DATA_IMM here, but I can't make + * it work. Seems like GART writes are broken with that + * instruction. Also I'm not sure that MI_FLUSH will + * act as a memory barrier for that instruction. It will + * for this single dword 2D blit. + */ + + static void i915_emit_ring_reloc(struct drm_device *dev, uint32_t offset, + uint32_t value) + { + struct drm_i915_private *dev_priv = + (struct drm_i915_private *)dev->dev_private; + + RING_LOCALS; + i915_kernel_lost_context(dev); + BEGIN_LP_RING(6); + OUT_RING((0x02 << 29) | (0x40 << 22) | (0x3 << 20) | (0x3)); + OUT_RING((0x3 << 24) | (0xF0 << 16) | (0x40)); + OUT_RING((0x1 << 16) | (0x4)); + OUT_RING(offset); + OUT_RING(value); + OUT_RING(0); + ADVANCE_LP_RING(); + } + + static void i915_dereference_buffers_locked(struct drm_i915_validate_buffer + *buffers, unsigned num_buffers) + { + while (num_buffers--) + drm_bo_usage_deref_locked(&buffers[num_buffers].buffer); + } + + int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, + struct drm_i915_validate_buffer *buffers, + struct i915_relocatee_info *relocatee, uint32_t * reloc) + { + unsigned index; + unsigned long new_cmd_offset; + u32 val; + int ret, i; + int buf_index = -1; + + /* + * FIXME: O(relocs * buffers) complexity. + */ + + for (i = 0; i <= num_buffers; i++) + if (buffers[i].buffer) + if (reloc[2] == buffers[i].buffer->base.hash.key) + buf_index = i; + + if (buf_index == -1) { + DRM_ERROR("Illegal relocation buffer %08X\n", reloc[2]); + return -EINVAL; + } + + /* + * Short-circuit relocations that were correctly + * guessed by the client + */ + if (buffers[buf_index].presumed_offset_correct && !DRM_DEBUG_RELOCATION) + return 0; + + new_cmd_offset = reloc[0]; + if (!relocatee->data_page || + !drm_bo_same_page(relocatee->offset, new_cmd_offset)) { + drm_bo_kunmap(&relocatee->kmap); + relocatee->data_page = NULL; + relocatee->offset = new_cmd_offset; + - if (unlikely(relocatee->idle == i915_reloc_unchecked)) { ++ if (unlikely(relocatee->idle == I915_RELOC_UNCHECKED)) { + ret = drm_bo_wait(relocatee->buf, 0, 0, 0); + if (ret) + return ret; - relocatee->idle = i915_reloc_idle; ++ relocatee->idle = I915_RELOC_IDLE; + } + + ret = drm_bo_kmap(relocatee->buf, new_cmd_offset >> PAGE_SHIFT, + 1, &relocatee->kmap); + if (ret) { + DRM_ERROR + ("Could not map command buffer to apply relocs\n %08lx", + new_cmd_offset); + return ret; + } + relocatee->data_page = drm_bmo_virtual(&relocatee->kmap, + &relocatee->is_iomem); + relocatee->page_offset = (relocatee->offset & PAGE_MASK); + } + + val = buffers[buf_index].buffer->offset; + index = (reloc[0] - relocatee->page_offset) >> 2; + + /* add in validate */ + val = val + reloc[1]; + + if (DRM_DEBUG_RELOCATION) { + if (buffers[buf_index].presumed_offset_correct && + relocatee->data_page[index] != val) { + DRM_DEBUG + ("Relocation mismatch source %d target %d buffer %d user %08x kernel %08x\n", + reloc[0], reloc[1], buf_index, + relocatee->data_page[index], val); + } + } + + if (relocatee->is_iomem) + iowrite32(val, relocatee->data_page + index); + else + relocatee->data_page[index] = val; + return 0; + } + + int i915_process_relocs(struct drm_file *file_priv, + uint32_t buf_handle, + uint32_t __user ** reloc_user_ptr, + struct i915_relocatee_info *relocatee, + struct drm_i915_validate_buffer *buffers, + uint32_t num_buffers) + { + int ret, reloc_stride; + uint32_t cur_offset; + uint32_t reloc_count; + uint32_t reloc_type; + uint32_t reloc_buf_size; + uint32_t *reloc_buf = NULL; + int i; + + /* do a copy from user from the user ptr */ + ret = get_user(reloc_count, *reloc_user_ptr); + if (ret) { + DRM_ERROR("Could not map relocation buffer.\n"); + goto out; + } + + ret = get_user(reloc_type, (*reloc_user_ptr) + 1); + if (ret) { + DRM_ERROR("Could not map relocation buffer.\n"); + goto out; + } + + if (reloc_type != 0) { + DRM_ERROR("Unsupported relocation type requested\n"); + ret = -EINVAL; + goto out; + } + + reloc_buf_size = + (I915_RELOC_HEADER + + (reloc_count * I915_RELOC0_STRIDE)) * sizeof(uint32_t); + reloc_buf = kmalloc(reloc_buf_size, GFP_KERNEL); + if (!reloc_buf) { + DRM_ERROR("Out of memory for reloc buffer\n"); + ret = -ENOMEM; + goto out; + } + + if (copy_from_user(reloc_buf, *reloc_user_ptr, reloc_buf_size)) { + ret = -EFAULT; + goto out; + } + + /* get next relocate buffer handle */ + *reloc_user_ptr = (uint32_t *) * (unsigned long *)&reloc_buf[2]; + + reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); /* may be different for other types of relocs */ + + DRM_DEBUG("num relocs is %d, next is %p\n", reloc_count, + *reloc_user_ptr); + + for (i = 0; i < reloc_count; i++) { + cur_offset = I915_RELOC_HEADER + (i * I915_RELOC0_STRIDE); + + ret = i915_apply_reloc(file_priv, num_buffers, buffers, + relocatee, reloc_buf + cur_offset); + if (ret) + goto out; + } + + out: + if (reloc_buf) + kfree(reloc_buf); + + if (relocatee->data_page) { + drm_bo_kunmap(&relocatee->kmap); + relocatee->data_page = NULL; + } + + return ret; + } + + static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle, + uint32_t __user * reloc_user_ptr, + struct drm_i915_validate_buffer *buffers, + uint32_t buf_count) + { - struct drm_device *dev = file_priv->head->dev; ++ struct drm_device *dev = file_priv->minor->dev; + struct i915_relocatee_info relocatee; + int ret = 0; + int b; + + /* + * Short circuit relocations when all previous + * buffers offsets were correctly guessed by + * the client + */ + if (!DRM_DEBUG_RELOCATION) { + for (b = 0; b < buf_count; b++) + if (!buffers[b].presumed_offset_correct) + break; + + if (b == buf_count) + return 0; + } + + memset(&relocatee, 0, sizeof(relocatee)); - relocatee.idle = i915_reloc_unchecked; ++ relocatee.idle = I915_RELOC_UNCHECKED; + + mutex_lock(&dev->struct_mutex); + relocatee.buf = drm_lookup_buffer_object(file_priv, buf_handle, 1); + mutex_unlock(&dev->struct_mutex); + if (!relocatee.buf) { + DRM_DEBUG("relocatee buffer invalid %08x\n", buf_handle); + ret = -EINVAL; + goto out_err; + } + + mutex_lock(&relocatee.buf->mutex); + while (reloc_user_ptr) { + ret = + i915_process_relocs(file_priv, buf_handle, &reloc_user_ptr, + &relocatee, buffers, buf_count); + if (ret) { + DRM_ERROR("process relocs failed\n"); + goto out_err1; + } + } + + out_err1: + mutex_unlock(&relocatee.buf->mutex); + drm_bo_usage_deref_unlocked(&relocatee.buf); + out_err: + return ret; + } + + static void i915_clear_relocatee(struct i915_relocatee_info *relocatee) + { + if (relocatee->data_page) { + #ifndef DRM_KMAP_ATOMIC_PROT_PFN + drm_bo_kunmap(&relocatee->kmap); + #else + kunmap_atomic(relocatee->data_page, KM_USER0); + #endif + relocatee->data_page = NULL; + } + relocatee->buf = NULL; + relocatee->dst = ~0; + } + + static int i915_update_relocatee(struct i915_relocatee_info *relocatee, + struct drm_i915_validate_buffer *buffers, + unsigned int dst, unsigned long dst_offset) + { + int ret; + + if (unlikely(dst != relocatee->dst || NULL == relocatee->buf)) { + i915_clear_relocatee(relocatee); + relocatee->dst = dst; + relocatee->buf = buffers[dst].buffer; + relocatee->idle = buffers[dst].idle; + + /* + * Check for buffer idle. If the buffer is busy, revert to + * ring relocations. + */ + - if (relocatee->idle == i915_reloc_unchecked) { ++ if (relocatee->idle == I915_RELOC_UNCHECKED) { + preempt_enable(); + ret = mutex_lock_interruptible(&relocatee->buf->mutex); + if (unlikely(ret)) + return -EAGAIN; + + ret = drm_bo_wait(relocatee->buf, 0, 0, 1); + if (ret == 0) - relocatee->idle = i915_reloc_idle; ++ relocatee->idle = I915_RELOC_IDLE; + else { - relocatee->idle = i915_reloc_busy; ++ relocatee->idle = I915_RELOC_BUSY; + relocatee->performed_ring_relocs = 1; + } + mutex_unlock(&relocatee->buf->mutex); + preempt_disable(); + buffers[dst].idle = relocatee->idle; + } + } + - if (relocatee->idle == i915_reloc_busy) ++ if (relocatee->idle == I915_RELOC_BUSY) + return 0; + + if (unlikely(dst_offset > relocatee->buf->num_pages * PAGE_SIZE)) { + DRM_ERROR("Relocation destination out of bounds.\n"); + return -EINVAL; + } + if (unlikely(!drm_bo_same_page(relocatee->page_offset, dst_offset) || + NULL == relocatee->data_page)) { + #ifdef DRM_KMAP_ATOMIC_PROT_PFN + if (NULL != relocatee->data_page) { + kunmap_atomic(relocatee->data_page, KM_USER0); + relocatee->data_page = NULL; + } + ret = drm_bo_pfn_prot(relocatee->buf, dst_offset, + &relocatee->pfn, &relocatee->pg_prot); + if (ret) { + DRM_ERROR("Can't map relocation destination.\n"); + return -EINVAL; + } + relocatee->data_page = + kmap_atomic_prot_pfn(relocatee->pfn, KM_USER0, + relocatee->pg_prot); + #else + if (NULL != relocatee->data_page) { + drm_bo_kunmap(&relocatee->kmap); + relocatee->data_page = NULL; + } + + ret = drm_bo_kmap(relocatee->buf, dst_offset >> PAGE_SHIFT, + 1, &relocatee->kmap); + if (ret) { + DRM_ERROR("Can't map relocation destination.\n"); + return ret; + } + + relocatee->data_page = drm_bmo_virtual(&relocatee->kmap, + &relocatee->is_iomem); + #endif + relocatee->page_offset = dst_offset & PAGE_MASK; + } + return 0; + } + + static int i915_apply_post_reloc(uint32_t reloc[], + struct drm_i915_validate_buffer *buffers, + uint32_t num_buffers, + struct i915_relocatee_info *relocatee) + { + uint32_t reloc_buffer = reloc[2]; + uint32_t dst_buffer = reloc[3]; + uint32_t val; + uint32_t index; + int ret; + + if (likely(buffers[reloc_buffer].presumed_offset_correct)) + return 0; + if (unlikely(reloc_buffer >= num_buffers)) { + DRM_ERROR("Invalid reloc buffer index.\n"); + return -EINVAL; + } + if (unlikely(dst_buffer >= num_buffers)) { + DRM_ERROR("Invalid dest buffer index.\n"); + return -EINVAL; + } + + ret = i915_update_relocatee(relocatee, buffers, dst_buffer, reloc[0]); + if (unlikely(ret)) + return ret; + + val = buffers[reloc_buffer].buffer->offset; + index = (reloc[0] - relocatee->page_offset) >> 2; + val = val + reloc[1]; + - if (relocatee->idle == i915_reloc_busy) { ++ if (relocatee->idle == I915_RELOC_BUSY) { + i915_emit_ring_reloc(relocatee->buf->dev, + relocatee->buf->offset + reloc[0], val); + return 0; + } + #ifdef DRM_KMAP_ATOMIC_PROT_PFN + relocatee->data_page[index] = val; + #else + if (likely(relocatee->is_iomem)) + iowrite32(val, relocatee->data_page + index); + else + relocatee->data_page[index] = val; + #endif + + return 0; + } + + static int i915_post_relocs(struct drm_file *file_priv, + uint32_t __user * new_reloc_ptr, + struct drm_i915_validate_buffer *buffers, + unsigned int num_buffers) + { + uint32_t *reloc; + uint32_t reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); + uint32_t header_size = I915_RELOC_HEADER * sizeof(uint32_t); + struct i915_relocatee_info relocatee; + uint32_t reloc_type; + uint32_t num_relocs; + uint32_t count; + int ret = 0; + int i; + int short_circuit = 1; + uint32_t __user *reloc_ptr; + uint64_t new_reloc_data; + uint32_t reloc_buf_size; + uint32_t *reloc_buf; + + for (i = 0; i < num_buffers; ++i) { + if (unlikely(!buffers[i].presumed_offset_correct)) { + short_circuit = 0; + break; + } + } + + if (likely(short_circuit)) + return 0; + + memset(&relocatee, 0, sizeof(relocatee)); + + while (new_reloc_ptr) { + reloc_ptr = new_reloc_ptr; + + ret = get_user(num_relocs, reloc_ptr); + if (unlikely(ret)) + goto out; + if (unlikely(!access_ok(VERIFY_READ, reloc_ptr, + header_size + + num_relocs * reloc_stride))) + return -EFAULT; + + ret = __get_user(reloc_type, reloc_ptr + 1); + if (unlikely(ret)) + goto out; + + if (unlikely(reloc_type != 1)) { + DRM_ERROR("Unsupported relocation type requested.\n"); + ret = -EINVAL; + goto out; + } + + ret = __get_user(new_reloc_data, reloc_ptr + 2); + new_reloc_ptr = (uint32_t __user *) (unsigned long) + new_reloc_data; + + reloc_ptr += I915_RELOC_HEADER; + + if (num_relocs == 0) + goto out; + + reloc_buf_size = + (num_relocs * I915_RELOC0_STRIDE) * sizeof(uint32_t); + reloc_buf = kmalloc(reloc_buf_size, GFP_KERNEL); + if (!reloc_buf) { + DRM_ERROR("Out of memory for reloc buffer\n"); + ret = -ENOMEM; + goto out; + } + + if (__copy_from_user(reloc_buf, reloc_ptr, reloc_buf_size)) { + ret = -EFAULT; + goto out; + } + reloc = reloc_buf; + preempt_disable(); + for (count = 0; count < num_relocs; ++count) { + ret = i915_apply_post_reloc(reloc, buffers, + num_buffers, &relocatee); + if (unlikely(ret)) { + preempt_enable(); + goto out; + } + reloc += I915_RELOC0_STRIDE; + } + preempt_enable(); + + if (reloc_buf) { + kfree(reloc_buf); + reloc_buf = NULL; + } + i915_clear_relocatee(&relocatee); + } + + out: + /* + * Flush ring relocs so the command parser will pick them up. + */ + + if (relocatee.performed_ring_relocs) - (void)i915_emit_mi_flush(file_priv->head->dev, 0); ++ (void)i915_emit_mi_flush(file_priv->minor->dev, 0); + + i915_clear_relocatee(&relocatee); + if (reloc_buf) { + kfree(reloc_buf); + reloc_buf = NULL; + } + + return ret; + } + + static int i915_check_presumed(struct drm_i915_op_arg *arg, + struct drm_buffer_object *bo, + uint32_t __user * data, int *presumed_ok) + { + struct drm_bo_op_req *req = &arg->d.req; + uint32_t hint_offset; + uint32_t hint = req->bo_req.hint; + + *presumed_ok = 0; + + if (!(hint & DRM_BO_HINT_PRESUMED_OFFSET)) + return 0; + if (bo->offset == req->bo_req.presumed_offset) { + *presumed_ok = 1; + return 0; + } + + /* + * We need to turn off the HINT_PRESUMED_OFFSET for this buffer in + * the user-space IOCTL argument list, since the buffer has moved, + * we're about to apply relocations and we might subsequently + * hit an -EAGAIN. In that case the argument list will be reused by + * user-space, but the presumed offset is no longer valid. + * + * Needless to say, this is a bit ugly. + */ + + hint_offset = (uint32_t *) & req->bo_req.hint - (uint32_t *) arg; + hint &= ~DRM_BO_HINT_PRESUMED_OFFSET; + return __put_user(hint, data + hint_offset); + } + + /* + * Validate, add fence and relocate a block of bos from a userspace list + */ + int i915_validate_buffer_list(struct drm_file *file_priv, + unsigned int fence_class, uint64_t data, + struct drm_i915_validate_buffer *buffers, + uint32_t * num_buffers, + uint32_t __user ** post_relocs) + { + struct drm_i915_op_arg arg; + struct drm_bo_op_req *req = &arg.d.req; + int ret = 0; + unsigned buf_count = 0; + uint32_t buf_handle; + uint32_t __user *reloc_user_ptr; + struct drm_i915_validate_buffer *item = buffers; + *post_relocs = NULL; + + do { + if (buf_count >= *num_buffers) { + DRM_ERROR("Buffer count exceeded %d\n.", *num_buffers); + ret = -EINVAL; + goto out_err; + } + item = buffers + buf_count; + item->buffer = NULL; + item->presumed_offset_correct = 0; - item->idle = i915_reloc_unchecked; ++ item->idle = I915_RELOC_UNCHECKED; + + if (copy_from_user + (&arg, (void __user *)(unsigned long)data, sizeof(arg))) { + ret = -EFAULT; + goto out_err; + } + + ret = 0; + if (req->op != drm_bo_validate) { + DRM_ERROR + ("Buffer object operation wasn't \"validate\".\n"); + ret = -EINVAL; + goto out_err; + } + item->ret = 0; + item->data = (void __user *)(unsigned long)data; + + buf_handle = req->bo_req.handle; + reloc_user_ptr = (uint32_t *) (unsigned long)arg.reloc_ptr; + + /* + * Switch mode to post-validation relocations? + */ + + if (unlikely((buf_count == 0) && (*post_relocs == NULL) && + (reloc_user_ptr != NULL))) { + uint32_t reloc_type; + + ret = get_user(reloc_type, reloc_user_ptr + 1); + if (ret) + goto out_err; + + if (reloc_type == 1) + *post_relocs = reloc_user_ptr; + + } + + if ((*post_relocs == NULL) && (reloc_user_ptr != NULL)) { + ret = + i915_exec_reloc(file_priv, buf_handle, + reloc_user_ptr, buffers, buf_count); + if (ret) + goto out_err; + DRM_MEMORYBARRIER(); + } + + ret = drm_bo_handle_validate(file_priv, req->bo_req.handle, + req->bo_req.flags, + req->bo_req.mask, req->bo_req.hint, + req->bo_req.fence_class, 0, + &item->rep, &item->buffer); + if (ret) { + DRM_ERROR("error on handle validate %d\n", ret); + goto out_err; + } + + buf_count++; + + ret = i915_check_presumed(&arg, item->buffer, + (uint32_t __user *) + (unsigned long)data, + &item->presumed_offset_correct); + if (ret) + goto out_err; + + data = arg.next; + } while (data != 0); + out_err: + *num_buffers = buf_count; + item->ret = (ret != -EAGAIN) ? ret : 0; + return ret; + } + + /* + * Remove all buffers from the unfenced list. + * If the execbuffer operation was aborted, for example due to a signal, + * this also make sure that buffers retain their original state and + * fence pointers. + * Copy back buffer information to user-space unless we were interrupted + * by a signal. In which case the IOCTL must be rerun. + */ + + static int i915_handle_copyback(struct drm_device *dev, + struct drm_i915_validate_buffer *buffers, + unsigned int num_buffers, int ret) + { + int err = ret; + int i; + struct drm_i915_op_arg arg; + + if (ret) + drm_putback_buffer_objects(dev); + + if (ret != -EAGAIN) { + for (i = 0; i < num_buffers; ++i) { + arg.handled = 1; + arg.d.rep.ret = buffers->ret; + arg.d.rep.bo_info = buffers->rep; + if (__copy_to_user(buffers->data, &arg, sizeof(arg))) + err = -EFAULT; + buffers++; + } + } + + return err; + } + + /* + * Create a fence object, and if that fails, pretend that everything is + * OK and just idle the GPU. + */ + + void i915_fence_or_sync(struct drm_file *file_priv, + uint32_t fence_flags, + struct drm_fence_arg *fence_arg, + struct drm_fence_object **fence_p) + { - struct drm_device *dev = file_priv->head->dev; ++ struct drm_device *dev = file_priv->minor->dev; + int ret; + struct drm_fence_object *fence; + + ret = drm_fence_buffer_objects(dev, NULL, fence_flags, NULL, &fence); + + if (ret) { + + /* + * Fence creation failed. + * Fall back to synchronous operation and idle the engine. + */ + + (void)i915_emit_mi_flush(dev, MI_READ_FLUSH); + (void)i915_quiescent(dev); + + if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { + + /* + * Communicate to user-space that + * fence creation has failed and that + * the engine is idle. + */ + + fence_arg->handle = ~0; + fence_arg->error = ret; + } + + drm_putback_buffer_objects(dev); + if (fence_p) + *fence_p = NULL; + return; + } + + if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { + + ret = drm_fence_add_user_object(file_priv, fence, + fence_flags & + DRM_FENCE_FLAG_SHAREABLE); + if (!ret) + drm_fence_fill_arg(fence, fence_arg); + else { + /* + * Fence user object creation failed. + * We must idle the engine here as well, as user- + * space expects a fence object to wait on. Since we + * have a fence object we wait for it to signal + * to indicate engine "sufficiently" idle. + */ + + (void)drm_fence_object_wait(fence, 0, 1, fence->type); + drm_fence_usage_deref_unlocked(&fence); + fence_arg->handle = ~0; + fence_arg->error = ret; + } + } + + if (fence_p) + *fence_p = fence; + else if (fence) + drm_fence_usage_deref_unlocked(&fence); + } + + int i915_execbuffer(struct drm_device *dev, void *data, + struct drm_file *file_priv) + { + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) + dev_priv->sarea_priv; + struct drm_i915_execbuffer *exec_buf = data; + struct drm_i915_batchbuffer *batch = &exec_buf->batch; + struct drm_fence_arg *fence_arg = &exec_buf->fence_arg; + int num_buffers; + int ret; + uint32_t __user *post_relocs; - struct drm_i915_validate_buffer *buffers; + + if (!dev_priv->allow_batchbuffer) { + DRM_ERROR("Batchbuffer ioctl disabled\n"); + return -EINVAL; + } + + if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects, + batch->num_cliprects * + sizeof(struct + drm_clip_rect))) + return -EFAULT; + + if (exec_buf->num_buffers > dev_priv->max_validate_buffers) + return -EINVAL; + + ret = drm_bo_read_lock(&dev->bm.bm_lock); + if (ret) + return ret; + + /* + * The cmdbuf_mutex makes sure the validate-submit-fence + * operation is atomic. + */ + + ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex); + if (ret) { + drm_bo_read_unlock(&dev->bm.bm_lock); + return -EAGAIN; + } + + num_buffers = exec_buf->num_buffers; + - buffers = - drm_calloc(num_buffers, sizeof(struct drm_i915_validate_buffer), - DRM_MEM_DRIVER); - if (!buffers) { ++ if (!dev_priv->val_bufs) { ++ dev_priv->val_bufs = ++ vmalloc(sizeof(struct drm_i915_validate_buffer) * ++ dev_priv->max_validate_buffers); ++ } ++ if (!dev_priv->val_bufs) { + drm_bo_read_unlock(&dev->bm.bm_lock); + mutex_unlock(&dev_priv->cmdbuf_mutex); + return -ENOMEM; + } + + /* validate buffer list + fixup relocations */ + ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list, - buffers, &num_buffers, &post_relocs); ++ dev_priv->val_bufs, &num_buffers, ++ &post_relocs); + if (ret) + goto out_err0; + + if (post_relocs) { + ret = i915_post_relocs(file_priv, post_relocs, - buffers, num_buffers); ++ dev_priv->val_bufs, num_buffers); + if (ret) + goto out_err0; + } + + /* make sure all previous memory operations have passed */ + DRM_MEMORYBARRIER(); + + if (!post_relocs) { + drm_agp_chipset_flush(dev); - batch->start = buffers[num_buffers - 1].buffer->offset; ++ batch->start = ++ dev_priv->val_bufs[num_buffers - 1].buffer->offset; + } else { - batch->start += buffers[0].buffer->offset; ++ batch->start += dev_priv->val_bufs[0].buffer->offset; + } + + DRM_DEBUG("i915 exec batchbuffer, start %x used %d cliprects %d\n", + batch->start, batch->used, batch->num_cliprects); + + ret = i915_dispatch_batchbuffer(dev, batch); + if (ret) + goto out_err0; + if (sarea_priv) + sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + i915_fence_or_sync(file_priv, fence_arg->flags, fence_arg, NULL); + + out_err0: - ret = i915_handle_copyback(dev, buffers, num_buffers, ret); ++ ret = i915_handle_copyback(dev, dev_priv->val_bufs, num_buffers, ret); + mutex_lock(&dev->struct_mutex); - i915_dereference_buffers_locked(buffers, num_buffers); ++ i915_dereference_buffers_locked(dev_priv->val_bufs, num_buffers); + mutex_unlock(&dev->struct_mutex); - - drm_free(buffers, - (exec_buf->num_buffers * sizeof(struct drm_buffer_object *)), - DRM_MEM_DRIVER); - + mutex_unlock(&dev_priv->cmdbuf_mutex); + drm_bo_read_unlock(&dev->bm.bm_lock); + return ret; + } diff --cc shared-core/i915_dma.c index f6df74a,1ab4f19..407befc --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@@ -796,563 -796,7 +796,6 @@@ static int i915_cmdbuffer(struct drm_de #define DRM_DEBUG_RELOCATION 0 #endif - #ifdef I915_HAVE_BUFFER -- - struct i915_relocatee_info { - struct drm_buffer_object *buf; - unsigned long offset; - u32 *data_page; - unsigned page_offset; - struct drm_bo_kmap_obj kmap; - int is_iomem; - int idle; - int evicted; - }; - - struct drm_i915_validate_buffer { - struct drm_buffer_object *buffer; - struct drm_bo_info_rep rep; - int presumed_offset_correct; - void __user *data; - int ret; - }; - - static void i915_dereference_buffers_locked(struct drm_i915_validate_buffer *buffers, - unsigned num_buffers) - { - while (num_buffers--) - drm_bo_usage_deref_locked(&buffers[num_buffers].buffer); - } - - int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, - struct drm_i915_validate_buffer *buffers, - struct i915_relocatee_info *relocatee, - uint32_t *reloc) - { - unsigned index; - unsigned long new_cmd_offset; - u32 val; - int ret, i; - int buf_index = -1; - - /* - * FIXME: O(relocs * buffers) complexity. - */ - - for (i = 0; i <= num_buffers; i++) - if (buffers[i].buffer) - if (reloc[2] == buffers[i].buffer->base.hash.key) - buf_index = i; - - if (buf_index == -1) { - DRM_ERROR("Illegal relocation buffer %08X\n", reloc[2]); - return -EINVAL; - } - - /* - * Short-circuit relocations that were correctly - * guessed by the client - */ - if (buffers[buf_index].presumed_offset_correct && !DRM_DEBUG_RELOCATION) - return 0; - - new_cmd_offset = reloc[0]; - if (!relocatee->data_page || - !drm_bo_same_page(relocatee->offset, new_cmd_offset)) { - drm_bo_kunmap(&relocatee->kmap); - relocatee->data_page = NULL; - relocatee->offset = new_cmd_offset; - - if (unlikely(!relocatee->idle)) { - ret = drm_bo_wait(relocatee->buf, 0, 0, 0); - if (ret) - return ret; - relocatee->idle = 1; - } - - ret = drm_bo_kmap(relocatee->buf, new_cmd_offset >> PAGE_SHIFT, - 1, &relocatee->kmap); - if (ret) { - DRM_ERROR("Could not map command buffer to apply relocs\n %08lx", new_cmd_offset); - return ret; - } - relocatee->data_page = drm_bmo_virtual(&relocatee->kmap, - &relocatee->is_iomem); - relocatee->page_offset = (relocatee->offset & PAGE_MASK); - - if (!relocatee->evicted && - relocatee->buf->mem.flags & DRM_BO_FLAG_CACHED_MAPPED) { - drm_bo_evict_cached(relocatee->buf); - relocatee->evicted = 1; - } - } - - val = buffers[buf_index].buffer->offset; - index = (reloc[0] - relocatee->page_offset) >> 2; - - /* add in validate */ - val = val + reloc[1]; - - if (DRM_DEBUG_RELOCATION) { - if (buffers[buf_index].presumed_offset_correct && - relocatee->data_page[index] != val) { - DRM_DEBUG ("Relocation mismatch source %d target %d buffer %d user %08x kernel %08x\n", - reloc[0], reloc[1], buf_index, relocatee->data_page[index], val); - } - } - - if (relocatee->is_iomem) - iowrite32(val, relocatee->data_page + index); - else - relocatee->data_page[index] = val; - return 0; - } - - int i915_process_relocs(struct drm_file *file_priv, - uint32_t buf_handle, - uint32_t __user **reloc_user_ptr, - struct i915_relocatee_info *relocatee, - struct drm_i915_validate_buffer *buffers, - uint32_t num_buffers) - { - int ret, reloc_stride; - uint32_t cur_offset; - uint32_t reloc_count; - uint32_t reloc_type; - uint32_t reloc_buf_size; - uint32_t *reloc_buf = NULL; - int i; - - /* do a copy from user from the user ptr */ - ret = get_user(reloc_count, *reloc_user_ptr); - if (ret) { - DRM_ERROR("Could not map relocation buffer.\n"); - goto out; - } - - ret = get_user(reloc_type, (*reloc_user_ptr)+1); - if (ret) { - DRM_ERROR("Could not map relocation buffer.\n"); - goto out; - } - - if (reloc_type != 0) { - DRM_ERROR("Unsupported relocation type requested\n"); - ret = -EINVAL; - goto out; - } - - reloc_buf_size = (I915_RELOC_HEADER + (reloc_count * I915_RELOC0_STRIDE)) * sizeof(uint32_t); - reloc_buf = kmalloc(reloc_buf_size, GFP_KERNEL); - if (!reloc_buf) { - DRM_ERROR("Out of memory for reloc buffer\n"); - ret = -ENOMEM; - goto out; - } - - if (copy_from_user(reloc_buf, *reloc_user_ptr, reloc_buf_size)) { - ret = -EFAULT; - goto out; - } - - /* get next relocate buffer handle */ - *reloc_user_ptr = (uint32_t *)*(unsigned long *)&reloc_buf[2]; - - reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); /* may be different for other types of relocs */ - - DRM_DEBUG("num relocs is %d, next is %p\n", reloc_count, *reloc_user_ptr); - - for (i = 0; i < reloc_count; i++) { - cur_offset = I915_RELOC_HEADER + (i * I915_RELOC0_STRIDE); - - ret = i915_apply_reloc(file_priv, num_buffers, buffers, - relocatee, reloc_buf + cur_offset); - if (ret) - goto out; - } - - out: - if (reloc_buf) - kfree(reloc_buf); - - if (relocatee->data_page) { - drm_bo_kunmap(&relocatee->kmap); - relocatee->data_page = NULL; - } - - return ret; - } - - static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle, - uint32_t __user *reloc_user_ptr, - struct drm_i915_validate_buffer *buffers, - uint32_t buf_count) - { - struct drm_device *dev = file_priv->minor->dev; - struct i915_relocatee_info relocatee; - int ret = 0; - int b; - - /* - * Short circuit relocations when all previous - * buffers offsets were correctly guessed by - * the client - */ - if (!DRM_DEBUG_RELOCATION) { - for (b = 0; b < buf_count; b++) - if (!buffers[b].presumed_offset_correct) - break; - - if (b == buf_count) - return 0; - } - - memset(&relocatee, 0, sizeof(relocatee)); - - mutex_lock(&dev->struct_mutex); - relocatee.buf = drm_lookup_buffer_object(file_priv, buf_handle, 1); - mutex_unlock(&dev->struct_mutex); - if (!relocatee.buf) { - DRM_DEBUG("relocatee buffer invalid %08x\n", buf_handle); - ret = -EINVAL; - goto out_err; - } - - mutex_lock (&relocatee.buf->mutex); - while (reloc_user_ptr) { - ret = i915_process_relocs(file_priv, buf_handle, &reloc_user_ptr, &relocatee, buffers, buf_count); - if (ret) { - DRM_ERROR("process relocs failed\n"); - goto out_err1; - } - } - - out_err1: - mutex_unlock (&relocatee.buf->mutex); - drm_bo_usage_deref_unlocked(&relocatee.buf); - out_err: - return ret; - } - - static int i915_check_presumed(struct drm_i915_op_arg *arg, - struct drm_buffer_object *bo, - uint32_t __user *data, - int *presumed_ok) - { - struct drm_bo_op_req *req = &arg->d.req; - uint32_t hint_offset; - uint32_t hint = req->bo_req.hint; - - *presumed_ok = 0; - - if (!(hint & DRM_BO_HINT_PRESUMED_OFFSET)) - return 0; - if (bo->offset == req->bo_req.presumed_offset) { - *presumed_ok = 1; - return 0; - } - - /* - * We need to turn off the HINT_PRESUMED_OFFSET for this buffer in - * the user-space IOCTL argument list, since the buffer has moved, - * we're about to apply relocations and we might subsequently - * hit an -EAGAIN. In that case the argument list will be reused by - * user-space, but the presumed offset is no longer valid. - * - * Needless to say, this is a bit ugly. - */ - - hint_offset = (uint32_t *)&req->bo_req.hint - (uint32_t *)arg; - hint &= ~DRM_BO_HINT_PRESUMED_OFFSET; - return __put_user(hint, data + hint_offset); - } - - - /* - * Validate, add fence and relocate a block of bos from a userspace list - */ - int i915_validate_buffer_list(struct drm_file *file_priv, - unsigned int fence_class, uint64_t data, - struct drm_i915_validate_buffer *buffers, - uint32_t *num_buffers) - { - struct drm_i915_op_arg arg; - struct drm_bo_op_req *req = &arg.d.req; - int ret = 0; - unsigned buf_count = 0; - uint32_t buf_handle; - uint32_t __user *reloc_user_ptr; - struct drm_i915_validate_buffer *item = buffers; - - do { - if (buf_count >= *num_buffers) { - DRM_ERROR("Buffer count exceeded %d\n.", *num_buffers); - ret = -EINVAL; - goto out_err; - } - item = buffers + buf_count; - item->buffer = NULL; - item->presumed_offset_correct = 0; - - buffers[buf_count].buffer = NULL; - - if (copy_from_user(&arg, (void __user *)(unsigned long)data, sizeof(arg))) { - ret = -EFAULT; - goto out_err; - } - - ret = 0; - if (req->op != drm_bo_validate) { - DRM_ERROR - ("Buffer object operation wasn't \"validate\".\n"); - ret = -EINVAL; - goto out_err; - } - item->ret = 0; - item->data = (void __user *) (unsigned long) data; - - buf_handle = req->bo_req.handle; - reloc_user_ptr = (uint32_t *)(unsigned long)arg.reloc_ptr; - - if (reloc_user_ptr) { - ret = i915_exec_reloc(file_priv, buf_handle, reloc_user_ptr, buffers, buf_count); - if (ret) - goto out_err; - DRM_MEMORYBARRIER(); - } - - ret = drm_bo_handle_validate(file_priv, req->bo_req.handle, - req->bo_req.flags, req->bo_req.mask, - req->bo_req.hint, - req->bo_req.fence_class, 0, - &item->rep, - &item->buffer); - - if (ret) { - DRM_ERROR("error on handle validate %d\n", ret); - goto out_err; - } - - buf_count++; - - ret = i915_check_presumed(&arg, item->buffer, - (uint32_t __user *) - (unsigned long) data, - &item->presumed_offset_correct); - if (ret) - goto out_err; - - data = arg.next; - } while (data != 0); - out_err: - *num_buffers = buf_count; - item->ret = (ret != -EAGAIN) ? ret : 0; - return ret; - } - - - /* - * Remove all buffers from the unfenced list. - * If the execbuffer operation was aborted, for example due to a signal, - * this also make sure that buffers retain their original state and - * fence pointers. - * Copy back buffer information to user-space unless we were interrupted - * by a signal. In which case the IOCTL must be rerun. - */ - - static int i915_handle_copyback(struct drm_device *dev, - struct drm_i915_validate_buffer *buffers, - unsigned int num_buffers, int ret) - { - int err = ret; - int i; - struct drm_i915_op_arg arg; - - if (ret) - drm_putback_buffer_objects(dev); - - if (ret != -EAGAIN) { - for (i = 0; i < num_buffers; ++i) { - arg.handled = 1; - arg.d.rep.ret = buffers->ret; - arg.d.rep.bo_info = buffers->rep; - if (__copy_to_user(buffers->data, &arg, sizeof(arg))) - err = -EFAULT; - buffers++; - } - } - return err; - } - - /* - * Create a fence object, and if that fails, pretend that everything is - * OK and just idle the GPU. - */ - - void i915_fence_or_sync(struct drm_file *file_priv, - uint32_t fence_flags, - struct drm_fence_arg *fence_arg, - struct drm_fence_object **fence_p) - { - struct drm_device *dev = file_priv->minor->dev; - int ret; - struct drm_fence_object *fence; - - ret = drm_fence_buffer_objects(dev, NULL, fence_flags, - NULL, &fence); - - if (ret) { - - /* - * Fence creation failed. - * Fall back to synchronous operation and idle the engine. - */ - - (void) i915_emit_mi_flush(dev, MI_READ_FLUSH); - (void) i915_quiescent(dev); - - if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { - - /* - * Communicate to user-space that - * fence creation has failed and that - * the engine is idle. - */ - - fence_arg->handle = ~0; - fence_arg->error = ret; - } - - drm_putback_buffer_objects(dev); - if (fence_p) - *fence_p = NULL; - return; - } - - if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { - - ret = drm_fence_add_user_object(file_priv, fence, - fence_flags & - DRM_FENCE_FLAG_SHAREABLE); - if (!ret) - drm_fence_fill_arg(fence, fence_arg); - else { - /* - * Fence user object creation failed. - * We must idle the engine here as well, as user- - * space expects a fence object to wait on. Since we - * have a fence object we wait for it to signal - * to indicate engine "sufficiently" idle. - */ - - (void) drm_fence_object_wait(fence, 0, 1, - fence->type); - drm_fence_usage_deref_unlocked(&fence); - fence_arg->handle = ~0; - fence_arg->error = ret; - } - } - - if (fence_p) - *fence_p = fence; - else if (fence) - drm_fence_usage_deref_unlocked(&fence); - } - - - static int i915_execbuffer(struct drm_device *dev, void *data, - struct drm_file *file_priv) - { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) - dev_priv->sarea_priv; - struct drm_i915_execbuffer *exec_buf = data; - struct drm_i915_batchbuffer *batch = &exec_buf->batch; - struct drm_fence_arg *fence_arg = &exec_buf->fence_arg; - int num_buffers; - int ret; - - if (!dev_priv->allow_batchbuffer) { - DRM_ERROR("Batchbuffer ioctl disabled\n"); - return -EINVAL; - } - - - if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects, - batch->num_cliprects * - sizeof(struct drm_clip_rect))) - return -EFAULT; - - if (exec_buf->num_buffers > dev_priv->max_validate_buffers) - return -EINVAL; - - ret = drm_bo_read_lock(&dev->bm.bm_lock); - if (ret) - return ret; - - /* - * The cmdbuf_mutex makes sure the validate-submit-fence - * operation is atomic. - */ - - ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex); - if (ret) { - drm_bo_read_unlock(&dev->bm.bm_lock); - return -EAGAIN; - } - - num_buffers = exec_buf->num_buffers; - - if (!dev_priv->val_bufs) { - dev_priv->val_bufs = - vmalloc(sizeof(struct drm_i915_validate_buffer)* - dev_priv->max_validate_buffers); - } - if (!dev_priv->val_bufs) { - drm_bo_read_unlock(&dev->bm.bm_lock); - mutex_unlock(&dev_priv->cmdbuf_mutex); - return -ENOMEM; - } - - /* validate buffer list + fixup relocations */ - ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list, - dev_priv->val_bufs, &num_buffers); - if (ret) - goto out_err0; - - /* make sure all previous memory operations have passed */ - DRM_MEMORYBARRIER(); - drm_agp_chipset_flush(dev); - - /* submit buffer */ - batch->start = dev_priv->val_bufs[num_buffers-1].buffer->offset; - - DRM_DEBUG("i915 exec batchbuffer, start %x used %d cliprects %d\n", - batch->start, batch->used, batch->num_cliprects); - - ret = i915_dispatch_batchbuffer(dev, batch); - if (ret) - goto out_err0; - - if (sarea_priv) - sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); - - i915_fence_or_sync(file_priv, fence_arg->flags, fence_arg, NULL); - - out_err0: - - /* handle errors */ - ret = i915_handle_copyback(dev, dev_priv->val_bufs, num_buffers, ret); - mutex_lock(&dev->struct_mutex); - i915_dereference_buffers_locked(dev_priv->val_bufs, num_buffers); - mutex_unlock(&dev->struct_mutex); - - mutex_unlock(&dev_priv->cmdbuf_mutex); - drm_bo_read_unlock(&dev->bm.bm_lock); - return ret; - } - #endif - static int i915_do_cleanup_pageflip(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; diff --cc shared-core/i915_drv.h index 3bc39e2,4811ee8..59f515c --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@@ -37,7 -37,7 +37,7 @@@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" --#define DRIVER_DATE "20070209" ++#define DRIVER_DATE "20080312" #if defined(__linux__) #define I915_HAVE_FENCE @@@ -61,7 -61,7 +61,7 @@@ */ #define DRIVER_MAJOR 1 #if defined(I915_HAVE_FENCE) && defined(I915_HAVE_BUFFER) --#define DRIVER_MINOR 12 ++#define DRIVER_MINOR 13 #else #define DRIVER_MINOR 6 #endif commit 612c22f131a25915196e69d7ec1adb6f4ec84a60 Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> Date: Fri Feb 29 15:38:55 2008 +0100 Working revision. diff --git a/linux-core/i915_execbuf.c b/linux-core/i915_execbuf.c index 1e515a5..cb0e734 100644 --- a/linux-core/i915_execbuf.c +++ b/linux-core/i915_execbuf.c @@ -1,5 +1,5 @@ /* - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2003-2008 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -22,6 +22,10 @@ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * Authors: + * Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> + * Dave Airlie + * ? */ #include "drmP.h" @@ -48,8 +52,9 @@ struct i915_relocatee_info { unsigned page_offset; struct drm_bo_kmap_obj kmap; int is_iomem; - int dst; + int dst; int idle; + int performed_ring_relocs; #ifdef DRM_KMAP_ATOMIC_PROT_PFN unsigned long pfn; pgprot_t pg_prot; @@ -65,13 +70,20 @@ struct drm_i915_validate_buffer { enum i915_buf_idle idle; }; +/* + * I'd like to use MI_STORE_DATA_IMM here, but I can't make + * it work. Seems like GART writes are broken with that + * instruction. Also I'm not sure that MI_FLUSH will + * act as a memory barrier for that instruction. It will + * for this single dword 2D blit. + */ + static void i915_emit_ring_reloc(struct drm_device *dev, uint32_t offset, uint32_t value) { struct drm_i915_private *dev_priv = - (struct drm_i915_private *) dev->dev_private; + (struct drm_i915_private *)dev->dev_private; - DRM_INFO("Ring reloc.\n"); RING_LOCALS; i915_kernel_lost_context(dev); BEGIN_LP_RING(6); @@ -84,8 +96,8 @@ static void i915_emit_ring_reloc(struct drm_device *dev, uint32_t offset, ADVANCE_LP_RING(); } -static void i915_dereference_buffers_locked(struct drm_i915_validate_buffer *buffers, - unsigned num_buffers) +static void i915_dereference_buffers_locked(struct drm_i915_validate_buffer + *buffers, unsigned num_buffers) { while (num_buffers--) drm_bo_usage_deref_locked(&buffers[num_buffers].buffer); @@ -93,8 +105,7 @@ static void i915_dereference_buffers_locked(struct drm_i915_validate_buffer *buf int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, struct drm_i915_validate_buffer *buffers, - struct i915_relocatee_info *relocatee, - uint32_t *reloc) + struct i915_relocatee_info *relocatee, uint32_t * reloc) { unsigned index; unsigned long new_cmd_offset; @@ -130,18 +141,19 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, relocatee->data_page = NULL; relocatee->offset = new_cmd_offset; - /* - * Note on buffer idle: - * Since we're applying relocations, this part of the - * buffer is obviously not used by the GPU and we don't - * need to wait for buffer idle. This is an important - * consideration for user-space buffer pools. - */ + if (unlikely(relocatee->idle == i915_reloc_unchecked)) { + ret = drm_bo_wait(relocatee->buf, 0, 0, 0); + if (ret) + return ret; + relocatee->idle = i915_reloc_idle; + } ret = drm_bo_kmap(relocatee->buf, new_cmd_offset >> PAGE_SHIFT, 1, &relocatee->kmap); if (ret) { - DRM_ERROR("Could not map command buffer to apply relocs\n %08lx", new_cmd_offset); + DRM_ERROR + ("Could not map command buffer to apply relocs\n %08lx", + new_cmd_offset); return ret; } relocatee->data_page = drm_bmo_virtual(&relocatee->kmap, @@ -158,8 +170,10 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, if (DRM_DEBUG_RELOCATION) { if (buffers[buf_index].presumed_offset_correct && relocatee->data_page[index] != val) { - DRM_DEBUG ("Relocation mismatch source %d target %d buffer %d user %08x kernel %08x\n", - reloc[0], reloc[1], buf_index, relocatee->data_page[index], val); + DRM_DEBUG + ("Relocation mismatch source %d target %d buffer %d user %08x kernel %08x\n", + reloc[0], reloc[1], buf_index, + relocatee->data_page[index], val); } } @@ -172,7 +186,7 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, int i915_process_relocs(struct drm_file *file_priv, uint32_t buf_handle, - uint32_t __user **reloc_user_ptr, + uint32_t __user ** reloc_user_ptr, struct i915_relocatee_info *relocatee, struct drm_i915_validate_buffer *buffers, uint32_t num_buffers) @@ -192,7 +206,7 @@ int i915_process_relocs(struct drm_file *file_priv, goto out; } - ret = get_user(reloc_type, (*reloc_user_ptr)+1); + ret = get_user(reloc_type, (*reloc_user_ptr) + 1); if (ret) { DRM_ERROR("Could not map relocation buffer.\n"); goto out; @@ -204,7 +218,9 @@ int i915_process_relocs(struct drm_file *file_priv, goto out; } - reloc_buf_size = (I915_RELOC_HEADER + (reloc_count * I915_RELOC0_STRIDE)) * sizeof(uint32_t); + reloc_buf_size = + (I915_RELOC_HEADER + + (reloc_count * I915_RELOC0_STRIDE)) * sizeof(uint32_t); reloc_buf = kmalloc(reloc_buf_size, GFP_KERNEL); if (!reloc_buf) { DRM_ERROR("Out of memory for reloc buffer\n"); @@ -218,26 +234,27 @@ int i915_process_relocs(struct drm_file *file_priv, } /* get next relocate buffer handle */ - *reloc_user_ptr = (uint32_t *)*(unsigned long *)&reloc_buf[2]; + *reloc_user_ptr = (uint32_t *) * (unsigned long *)&reloc_buf[2]; - reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); /* may be different for other types of relocs */ + reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); /* may be different for other types of relocs */ - DRM_DEBUG("num relocs is %d, next is %p\n", reloc_count, *reloc_user_ptr); + DRM_DEBUG("num relocs is %d, next is %p\n", reloc_count, + *reloc_user_ptr); for (i = 0; i < reloc_count; i++) { cur_offset = I915_RELOC_HEADER + (i * I915_RELOC0_STRIDE); - + ret = i915_apply_reloc(file_priv, num_buffers, buffers, relocatee, reloc_buf + cur_offset); if (ret) goto out; } -out: + out: if (reloc_buf) kfree(reloc_buf); - if (relocatee->data_page) { + if (relocatee->data_page) { drm_bo_kunmap(&relocatee->kmap); relocatee->data_page = NULL; } @@ -246,7 +263,7 @@ out: } static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle, - uint32_t __user *reloc_user_ptr, + uint32_t __user * reloc_user_ptr, struct drm_i915_validate_buffer *buffers, uint32_t buf_count) { @@ -264,12 +281,13 @@ static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle, for (b = 0; b < buf_count; b++) if (!buffers[b].presumed_offset_correct) break; - + if (b == buf_count) return 0; } memset(&relocatee, 0, sizeof(relocatee)); + relocatee.idle = i915_reloc_unchecked; mutex_lock(&dev->struct_mutex); relocatee.buf = drm_lookup_buffer_object(file_priv, buf_handle, 1); @@ -280,23 +298,24 @@ static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle, goto out_err; } - mutex_lock (&relocatee.buf->mutex); + mutex_lock(&relocatee.buf->mutex); while (reloc_user_ptr) { - ret = i915_process_relocs(file_priv, buf_handle, &reloc_user_ptr, &relocatee, buffers, buf_count); + ret = + i915_process_relocs(file_priv, buf_handle, &reloc_user_ptr, + &relocatee, buffers, buf_count); if (ret) { DRM_ERROR("process relocs failed\n"); goto out_err1; } } -out_err1: - mutex_unlock (&relocatee.buf->mutex); + out_err1: + mutex_unlock(&relocatee.buf->mutex); drm_bo_usage_deref_unlocked(&relocatee.buf); -out_err: + out_err: return ret; } - static void i915_clear_relocatee(struct i915_relocatee_info *relocatee) { if (relocatee->data_page) { @@ -311,20 +330,23 @@ static void i915_clear_relocatee(struct i915_relocatee_info *relocatee) relocatee->dst = ~0; } - static int i915_update_relocatee(struct i915_relocatee_info *relocatee, struct drm_i915_validate_buffer *buffers, - unsigned int dst, - unsigned long dst_offset) + unsigned int dst, unsigned long dst_offset) { int ret; - + if (unlikely(dst != relocatee->dst || NULL == relocatee->buf)) { i915_clear_relocatee(relocatee); relocatee->dst = dst; relocatee->buf = buffers[dst].buffer; - relocatee->idle = i915_reloc_idle; buffers[dst].idle; -#if 0 + relocatee->idle = buffers[dst].idle; + + /* + * Check for buffer idle. If the buffer is busy, revert to + * ring relocations. + */ + if (relocatee->idle == i915_reloc_unchecked) { preempt_enable(); ret = mutex_lock_interruptible(&relocatee->buf->mutex); @@ -332,16 +354,20 @@ static int i915_update_relocatee(struct i915_relocatee_info *relocatee, return -EAGAIN; ret = drm_bo_wait(relocatee->buf, 0, 0, 1); - relocatee->idle = (ret == 0) ? i915_reloc_idle : i915_reloc_busy; + if (ret == 0) + relocatee->idle = i915_reloc_idle; + else { + relocatee->idle = i915_reloc_busy; + relocatee->performed_ring_relocs = 1; + } mutex_unlock(&relocatee->buf->mutex); preempt_disable(); buffers[dst].idle = relocatee->idle; } -#endif } if (relocatee->idle == i915_reloc_busy) - return 0; + return 0; if (unlikely(dst_offset > relocatee->buf->num_pages * PAGE_SIZE)) { DRM_ERROR("Relocation destination out of bounds.\n"); @@ -355,15 +381,14 @@ static int i915_update_relocatee(struct i915_relocatee_info *relocatee, relocatee->data_page = NULL; } ret = drm_bo_pfn_prot(relocatee->buf, dst_offset, - &relocatee->pfn, - &relocatee->pg_prot); + &relocatee->pfn, &relocatee->pg_prot); if (ret) { DRM_ERROR("Can't map relocation destination.\n"); return -EINVAL; } relocatee->data_page = - kmap_atomic_prot_pfn(relocatee->pfn, KM_USER0, - relocatee->pg_prot); + kmap_atomic_prot_pfn(relocatee->pfn, KM_USER0, + relocatee->pg_prot); #else if (NULL != relocatee->data_page) { drm_bo_kunmap(&relocatee->kmap); @@ -378,7 +403,7 @@ static int i915_update_relocatee(struct i915_relocatee_info *relocatee, } relocatee->data_page = drm_bmo_virtual(&relocatee->kmap, - &relocatee->is_iomem); + &relocatee->is_iomem); #endif relocatee->page_offset = dst_offset & PAGE_MASK; } @@ -407,8 +432,7 @@ static int i915_apply_post_reloc(uint32_t reloc[], return -EINVAL; } - ret = i915_update_relocatee(relocatee, buffers, dst_buffer, - reloc[0]); + ret = i915_update_relocatee(relocatee, buffers, dst_buffer, reloc[0]); if (unlikely(ret)) return ret; @@ -417,12 +441,10 @@ static int i915_apply_post_reloc(uint32_t reloc[], val = val + reloc[1]; if (relocatee->idle == i915_reloc_busy) { - i915_emit_ring_reloc(relocatee->buf->dev, - relocatee->buf->offset + reloc[0], - val); + i915_emit_ring_reloc(relocatee->buf->dev, + relocatee->buf->offset + reloc[0], val); return 0; } - #ifdef DRM_KMAP_ATOMIC_PROT_PFN relocatee->data_page[index] = val; #else @@ -436,7 +458,7 @@ static int i915_apply_post_reloc(uint32_t reloc[], } static int i915_post_relocs(struct drm_file *file_priv, - uint32_t __user *new_reloc_ptr, + uint32_t __user * new_reloc_ptr, struct drm_i915_validate_buffer *buffers, unsigned int num_buffers) { @@ -455,7 +477,7 @@ static int i915_post_relocs(struct drm_file *file_priv, uint32_t reloc_buf_size; uint32_t *reloc_buf; - for (i=0; i<num_buffers; ++i) { + for (i = 0; i < num_buffers; ++i) { if (unlikely(!buffers[i].presumed_offset_correct)) { short_circuit = 0; break; @@ -467,7 +489,7 @@ static int i915_post_relocs(struct drm_file *file_priv, memset(&relocatee, 0, sizeof(relocatee)); - while(new_reloc_ptr) { + while (new_reloc_ptr) { reloc_ptr = new_reloc_ptr; ret = get_user(num_relocs, reloc_ptr); @@ -475,7 +497,7 @@ static int i915_post_relocs(struct drm_file *file_priv, goto out; if (unlikely(!access_ok(VERIFY_READ, reloc_ptr, header_size + - num_relocs * reloc_stride))) + num_relocs * reloc_stride))) return -EFAULT; ret = __get_user(reloc_type, reloc_ptr + 1); @@ -490,14 +512,15 @@ static int i915_post_relocs(struct drm_file *file_priv, ret = __get_user(new_reloc_data, reloc_ptr + 2); new_reloc_ptr = (uint32_t __user *) (unsigned long) - new_reloc_data; + new_reloc_data; reloc_ptr += I915_RELOC_HEADER; if (num_relocs == 0) goto out; - reloc_buf_size = (num_relocs * I915_RELOC0_STRIDE) * sizeof(uint32_t); + reloc_buf_size = + (num_relocs * I915_RELOC0_STRIDE) * sizeof(uint32_t); reloc_buf = kmalloc(reloc_buf_size, GFP_KERNEL); if (!reloc_buf) { DRM_ERROR("Out of memory for reloc buffer\n"); @@ -527,9 +550,17 @@ static int i915_post_relocs(struct drm_file *file_priv, reloc_buf = NULL; } i915_clear_relocatee(&relocatee); - } + } + + out: + /* + * Flush ring relocs so the command parser will pick them up. + */ -out: + if (relocatee.performed_ring_relocs) + (void)i915_emit_mi_flush(file_priv->head->dev, 0); + + i915_clear_relocatee(&relocatee); if (reloc_buf) { kfree(reloc_buf); reloc_buf = NULL; @@ -540,8 +571,7 @@ out: static int i915_check_presumed(struct drm_i915_op_arg *arg, struct drm_buffer_object *bo, - uint32_t __user *data, - int *presumed_ok) + uint32_t __user * data, int *presumed_ok) { struct drm_bo_op_req *req = &arg->d.req; uint32_t hint_offset; @@ -566,20 +596,19 @@ static int i915_check_presumed(struct drm_i915_op_arg *arg, * Needless to say, this is a bit ugly. */ - hint_offset = (uint32_t *)&req->bo_req.hint - (uint32_t *)arg; + hint_offset = (uint32_t *) & req->bo_req.hint - (uint32_t *) arg; hint &= ~DRM_BO_HINT_PRESUMED_OFFSET; return __put_user(hint, data + hint_offset); } - /* * Validate, add fence and relocate a block of bos from a userspace list */ int i915_validate_buffer_list(struct drm_file *file_priv, unsigned int fence_class, uint64_t data, struct drm_i915_validate_buffer *buffers, - uint32_t *num_buffers, - uint32_t __user **post_relocs) + uint32_t * num_buffers, + uint32_t __user ** post_relocs) { struct drm_i915_op_arg arg; struct drm_bo_op_req *req = &arg.d.req; @@ -599,8 +628,10 @@ int i915_validate_buffer_list(struct drm_file *file_priv, item = buffers + buf_count; item->buffer = NULL; item->presumed_offset_correct = 0; + item->idle = i915_reloc_unchecked; - if (copy_from_user(&arg, (void __user *)(unsigned long)data, sizeof(arg))) { + if (copy_from_user + (&arg, (void __user *)(unsigned long)data, sizeof(arg))) { ret = -EFAULT; goto out_err; } @@ -613,10 +644,10 @@ int i915_validate_buffer_list(struct drm_file *file_priv, goto out_err; } item->ret = 0; - item->data = (void __user *) (unsigned long) data; + item->data = (void __user *)(unsigned long)data; buf_handle = req->bo_req.handle; - reloc_user_ptr = (uint32_t *)(unsigned long)arg.reloc_ptr; + reloc_user_ptr = (uint32_t *) (unsigned long)arg.reloc_ptr; /* * Switch mode to post-validation relocations? @@ -626,7 +657,7 @@ int i915_validate_buffer_list(struct drm_file *file_priv, (reloc_user_ptr != NULL))) { uint32_t reloc_type; - ret = get_user(reloc_type, reloc_user_ptr+1); + ret = get_user(reloc_type, reloc_user_ptr + 1); if (ret) goto out_err; @@ -636,18 +667,19 @@ int i915_validate_buffer_list(struct drm_file *file_priv, } if ((*post_relocs == NULL) && (reloc_user_ptr != NULL)) { - ret = i915_exec_reloc(file_priv, buf_handle, reloc_user_ptr, buffers, buf_count); + ret = + i915_exec_reloc(file_priv, buf_handle, + reloc_user_ptr, buffers, buf_count); if (ret) goto out_err; DRM_MEMORYBARRIER(); } ret = drm_bo_handle_validate(file_priv, req->bo_req.handle, - req->bo_req.flags, req->bo_req.mask, - req->bo_req.hint, + req->bo_req.flags, + req->bo_req.mask, req->bo_req.hint, req->bo_req.fence_class, 0, - &item->rep, - &item->buffer); + &item->rep, &item->buffer); if (ret) { DRM_ERROR("error on handle validate %d\n", ret); goto out_err; @@ -657,20 +689,19 @@ int i915_validate_buf... [truncated message content] |
From: <ai...@ke...> - 2008-03-24 08:54:06
|
shared-core/r300_cmdbuf.c | 89 ++++++++++++++++++++++++++++++++++++++++------ shared-core/r300_reg.h | 6 +++ shared-core/radeon_drm.h | 7 +++ 3 files changed, 91 insertions(+), 11 deletions(-) New commits: commit 4323ee3e5b263a1dc8cfdf72485a20a3c1d8f144 Merge: a244d29... 36e11dd... Author: Dave Airlie <ai...@re...> Date: Mon Mar 24 18:47:50 2008 +1000 Merge branch 'r500-fp' commit 36e11dd3801734ff5af9f5edb7aa698f0e2c49c2 Author: Dave Airlie <ai...@re...> Date: Fri Mar 21 16:59:52 2008 +1000 r500: fragment program upload is also used to upload constants. Limit frag address to 8 bits diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index 040a363..1ae2e67 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -804,26 +804,38 @@ static __inline__ int r300_emit_r500fp(drm_radeon_private_t *dev_priv, { int sz; int addr; + int type; + int clamp; + int stride; RING_LOCALS; sz = header.r500fp.count; - addr = (header.r500fp.adrhi << 8) | header.r500fp.adrlo; + /* address is 9 bits 0 - 8, bit 1 of flags is part of address */ + addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo; - DRM_DEBUG("r500fp %d %d\n", sz, addr); + type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE); + clamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP); + + addr |= (type << 16); + addr |= (clamp << 17); + + stride = type ? 4 : 6; + + DRM_DEBUG("r500fp %d %d type: %d\n", sz, addr, type); if (!sz) return 0; - if (sz * 6 * 4 > cmdbuf->bufsz) + if (sz * stride * 4 > cmdbuf->bufsz) return -EINVAL; - BEGIN_RING(3 + sz * 6); + BEGIN_RING(3 + sz * stride); OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr); - OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * 6 - 1)); - OUT_RING_TABLE((int *)cmdbuf->buf, sz * 6); + OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * stride - 1)); + OUT_RING_TABLE((int *)cmdbuf->buf, sz * stride); ADVANCE_RING(); - cmdbuf->buf += sz * 6 * 4; - cmdbuf->bufsz -= sz * 6 * 4; + cmdbuf->buf += sz * stride * 4; + cmdbuf->bufsz -= sz * stride * 4; return 0; } diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h index 3437320..c4d9cc6 100644 --- a/shared-core/radeon_drm.h +++ b/shared-core/radeon_drm.h @@ -258,7 +258,7 @@ typedef union { unsigned char cmd_type, reg, n_bufs, flags; } scratch; struct { - unsigned char cmd_type, count, adrlo, adrhi; + unsigned char cmd_type, count, adrlo, adrhi_flags; } r500fp; } drm_r300_cmd_header_t; @@ -270,6 +270,9 @@ typedef union { #define RADEON_USE_HIERZ 0x40000000 #define RADEON_USE_COMP_ZBUF 0x20000000 +#define R500FP_CONSTANT_TYPE (1 << 1) +#define R500FP_CONSTANT_CLAMP (1 << 2) + /* Primitive types */ #define RADEON_POINTS 0x1 commit 316979356f05796c5bd5a47dfc29fe48d6874b49 Author: Dave Airlie <ai...@re...> Date: Thu Mar 20 14:20:53 2008 +1000 drm: fixup r500fp submission diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index ccf82d1..040a363 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -332,6 +332,7 @@ static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv, sz = header.packet0.count; reg = (header.packet0.reghi << 8) | header.packet0.reglo; + DRM_DEBUG("R300_CMD_PACKET0: reg %04x, sz %d\n", reg, sz); if (!sz) return 0; @@ -808,23 +809,21 @@ static __inline__ int r300_emit_r500fp(drm_radeon_private_t *dev_priv, sz = header.r500fp.count; addr = (header.r500fp.adrhi << 8) | header.r500fp.adrlo; + DRM_DEBUG("r500fp %d %d\n", sz, addr); if (!sz) return 0; - if (sz * 16 > cmdbuf->bufsz) + if (sz * 6 * 4 > cmdbuf->bufsz) return -EINVAL; - BEGIN_RING(4 + sz * 4); - /* Wait for VAP to come to senses.. */ - /* there is no need to emit it multiple times, (only once before VAP is programmed, - but this optimization is for later */ + BEGIN_RING(3 + sz * 6); OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr); - OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * 4 - 1)); - OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4); + OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * 6 - 1)); + OUT_RING_TABLE((int *)cmdbuf->buf, sz * 6); ADVANCE_RING(); - cmdbuf->buf += sz * 16; - cmdbuf->bufsz -= sz * 16; + cmdbuf->buf += sz * 6 * 4; + cmdbuf->bufsz -= sz * 6 * 4; return 0; } @@ -868,7 +867,6 @@ int r300_do_cp_cmdbuf(struct drm_device *dev, switch (header.header.cmd_type) { case R300_CMD_PACKET0: - DRM_DEBUG("R300_CMD_PACKET0\n"); ret = r300_emit_packet0(dev_priv, cmdbuf, header); if (ret) { DRM_ERROR("r300_emit_packet0 failed\n"); commit a3c808d8feff9dc379f71f971ca20ec3c686b0c0 Author: Dave Airlie <ai...@re...> Date: Wed Mar 19 16:10:37 2008 +1000 move some more r300 regs into not allowed on r500 diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index 89a84b7..ccf82d1 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -192,9 +192,7 @@ void r300_init_reg_flags(struct drm_device *dev) ADD_RANGE(0x43A4, 2); ADD_RANGE(0x43E8, 1); - ADD_RANGE(R300_PFS_CNTL_0, 3); - ADD_RANGE(R300_PFS_NODE_0, 4); - ADD_RANGE(R300_PFS_TEXI_0, 64); + ADD_RANGE(0x46A4, 5); ADD_RANGE(R300_RE_FOG_STATE, 1); @@ -240,6 +238,9 @@ void r300_init_reg_flags(struct drm_device *dev) ADD_RANGE(R500_RS_IP_0, 16); ADD_RANGE(R500_RS_INST_0, 16); } else { + ADD_RANGE(R300_PFS_CNTL_0, 3); + ADD_RANGE(R300_PFS_NODE_0, 4); + ADD_RANGE(R300_PFS_TEXI_0, 64); ADD_RANGE(R300_PFS_INSTR0_0, 64); ADD_RANGE(R300_PFS_INSTR1_0, 64); ADD_RANGE(R300_PFS_INSTR2_0, 64); commit 3add9494037e7c88b5e5a476001176784d743a26 Author: Dave Airlie <ai...@re...> Date: Mon Mar 17 11:08:03 2008 +1000 initial r500 RS and FP register and upload code diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index a26a71d..89a84b7 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -189,18 +189,14 @@ void r300_init_reg_flags(struct drm_device *dev) ADD_RANGE(R300_RE_CULL_CNTL, 1); ADD_RANGE(0x42C0, 2); ADD_RANGE(R300_RS_CNTL_0, 2); - ADD_RANGE(R300_RS_INTERP_0, 8); - ADD_RANGE(R300_RS_ROUTE_0, 8); + ADD_RANGE(0x43A4, 2); ADD_RANGE(0x43E8, 1); ADD_RANGE(R300_PFS_CNTL_0, 3); ADD_RANGE(R300_PFS_NODE_0, 4); ADD_RANGE(R300_PFS_TEXI_0, 64); ADD_RANGE(0x46A4, 5); - ADD_RANGE(R300_PFS_INSTR0_0, 64); - ADD_RANGE(R300_PFS_INSTR1_0, 64); - ADD_RANGE(R300_PFS_INSTR2_0, 64); - ADD_RANGE(R300_PFS_INSTR3_0, 64); + ADD_RANGE(R300_RE_FOG_STATE, 1); ADD_RANGE(R300_FOG_COLOR_R, 3); ADD_RANGE(R300_PP_ALPHA_TEST, 2); @@ -241,7 +237,16 @@ void r300_init_reg_flags(struct drm_device *dev) ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8); if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { - ADD_RANGE(0x4074, 16); + ADD_RANGE(R500_RS_IP_0, 16); + ADD_RANGE(R500_RS_INST_0, 16); + } else { + ADD_RANGE(R300_PFS_INSTR0_0, 64); + ADD_RANGE(R300_PFS_INSTR1_0, 64); + ADD_RANGE(R300_PFS_INSTR2_0, 64); + ADD_RANGE(R300_PFS_INSTR3_0, 64); + ADD_RANGE(R300_RS_INTERP_0, 8); + ADD_RANGE(R300_RS_ROUTE_0, 8); + } } @@ -787,6 +792,44 @@ static int r300_scratch(drm_radeon_private_t *dev_priv, } /** + * Uploads user-supplied vertex program instructions or parameters onto + * the graphics card. + * Called by r300_do_cp_cmdbuf. + */ +static __inline__ int r300_emit_r500fp(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf, + drm_r300_cmd_header_t header) +{ + int sz; + int addr; + RING_LOCALS; + + sz = header.r500fp.count; + addr = (header.r500fp.adrhi << 8) | header.r500fp.adrlo; + + if (!sz) + return 0; + if (sz * 16 > cmdbuf->bufsz) + return -EINVAL; + + BEGIN_RING(4 + sz * 4); + /* Wait for VAP to come to senses.. */ + /* there is no need to emit it multiple times, (only once before VAP is programmed, + but this optimization is for later */ + OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr); + OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * 4 - 1)); + OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4); + + ADVANCE_RING(); + + cmdbuf->buf += sz * 16; + cmdbuf->bufsz -= sz * 16; + + return 0; +} + + +/** * Parses and validates a user-supplied command buffer and emits appropriate * commands on the DMA ring buffer. * Called by the ioctl handler function radeon_cp_cmdbuf. @@ -932,6 +975,19 @@ int r300_do_cp_cmdbuf(struct drm_device *dev, } break; + case R300_CMD_R500FP: + if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) { + DRM_ERROR("Calling r500 command on r300 card\n"); + ret = -EINVAL; + goto cleanup; + } + DRM_DEBUG("R300_CMD_R500FP\n"); + ret = r300_emit_r500fp(dev_priv, cmdbuf, header); + if (ret) { + DRM_ERROR("r300_emit_r500fp failed\n"); + goto cleanup; + } + break; default: DRM_ERROR("bad cmd_type %i at %p\n", header.header.cmd_type, diff --git a/shared-core/r300_reg.h b/shared-core/r300_reg.h index 29198c8..578e7e9 100644 --- a/shared-core/r300_reg.h +++ b/shared-core/r300_reg.h @@ -1626,6 +1626,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define R300_CP_CMD_BITBLT_MULTI 0xC0009B00 +#define R500_GA_US_VECTOR_INDEX 0x4250 +#define R500_GA_US_VECTOR_DATA 0x4254 + +#define R500_RS_IP_0 0x4074 +#define R500_RS_INST_0 0x4320 + #endif /* _R300_REG_H */ /* *INDENT-ON* */ diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h index 0971f97..3437320 100644 --- a/shared-core/radeon_drm.h +++ b/shared-core/radeon_drm.h @@ -228,6 +228,7 @@ typedef union { # define R300_WAIT_2D_CLEAN 0x3 # define R300_WAIT_3D_CLEAN 0x4 #define R300_CMD_SCRATCH 8 +#define R300_CMD_R500FP 9 typedef union { unsigned int u; @@ -256,6 +257,9 @@ typedef union { struct { unsigned char cmd_type, reg, n_bufs, flags; } scratch; + struct { + unsigned char cmd_type, count, adrlo, adrhi; + } r500fp; } drm_r300_cmd_header_t; #define RADEON_FRONT 0x1 |
From: <an...@ke...> - 2008-05-27 22:13:09
|
bsd-core/drm_auth.c | 2 -- bsd-core/drm_bufs.c | 26 +++++++++++++++++--------- bsd-core/drm_drawable.c | 4 +++- bsd-core/drm_vm.c | 3 +-- shared-core/i915_drv.h | 2 +- 5 files changed, 22 insertions(+), 15 deletions(-) New commits: commit df127c303d944720937fa6b54a8a9f84bc2fe518 Author: Owain Ainsworth <og...@st...> Date: Tue May 27 15:12:35 2008 -0700 [BSD] Move unlock in drm_vm.c from accidental platform #ifdeffing. Also remove an unreachable unlock. diff --git a/bsd-core/drm_vm.c b/bsd-core/drm_vm.c index f2a1a1f..9950c37 100644 --- a/bsd-core/drm_vm.c +++ b/bsd-core/drm_vm.c @@ -67,9 +67,9 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot) unsigned long page = offset >> PAGE_SHIFT; unsigned long phys = dma->pagelist[page]; + DRM_SPINUNLOCK(&dev->dma_lock); #if defined(__FreeBSD__) && __FreeBSD_version >= 500102 *paddr = phys; - DRM_SPINUNLOCK(&dev->dma_lock); return 0; #else return atop(phys); @@ -78,7 +78,6 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot) DRM_SPINUNLOCK(&dev->dma_lock); return -1; } - DRM_SPINUNLOCK(&dev->dma_lock); } /* A sequential search of a linked list is commit cc7ad27fe414cdf87b7561778a766a012541f116 Author: Owain Ainsworth <og...@st...> Date: Tue May 27 15:11:25 2008 -0700 [BSD] Fix lock leak in drm_update_draw malloc failure path. diff --git a/bsd-core/drm_drawable.c b/bsd-core/drm_drawable.c index 7c44352..268b956 100644 --- a/bsd-core/drm_drawable.c +++ b/bsd-core/drm_drawable.c @@ -136,8 +136,10 @@ int drm_update_draw(struct drm_device *dev, void *data, if (info->rects == NULL) { info->rects = drm_alloc(sizeof(*info->rects) * update->num, DRM_MEM_DRAWABLE); - if (info->rects == NULL) + if (info->rects == NULL) { + DRM_SPINUNLOCK(&dev->drw_lock); return ENOMEM; + } info->num_rects = update->num; } /* For some reason the pointer arg is unsigned long long. */ commit 9a2ae28fbe0e1e5cce0a5d89fbcc84fbdba1206e Author: Owain Ainsworth <og...@st...> Date: Tue May 27 15:07:04 2008 -0700 [BSD] Fix lock leaks in error paths in drm_bufs.c. diff --git a/bsd-core/drm_bufs.c b/bsd-core/drm_bufs.c index 7cefb77..3508331 100644 --- a/bsd-core/drm_bufs.c +++ b/bsd-core/drm_bufs.c @@ -152,8 +152,10 @@ int drm_addmap(struct drm_device * dev, unsigned long offset, * initialization necessary. */ map = malloc(sizeof(*map), M_DRM, M_ZERO | M_NOWAIT); - if ( !map ) + if ( !map ) { + DRM_LOCK(); return ENOMEM; + } map->offset = offset; map->size = size; @@ -176,6 +178,7 @@ int drm_addmap(struct drm_device * dev, unsigned long offset, map->size, drm_order(map->size), map->handle ); if ( !map->handle ) { free(map, M_DRM); + DRM_LOCK(); return ENOMEM; } map->offset = (unsigned long)map->handle; @@ -216,12 +219,14 @@ int drm_addmap(struct drm_device * dev, unsigned long offset, } if (!valid) { free(map, M_DRM); + DRM_LOCK(); return EACCES; }*/ break; case _DRM_SCATTER_GATHER: if (!dev->sg) { free(map, M_DRM); + DRM_LOCK(); return EINVAL; } map->offset = map->offset + dev->sg->handle; @@ -239,6 +244,7 @@ int drm_addmap(struct drm_device * dev, unsigned long offset, map->dmah = drm_pci_alloc(dev, map->size, align, 0xfffffffful); if (map->dmah == NULL) { free(map, M_DRM); + DRM_LOCK(); return ENOMEM; } map->handle = map->dmah->vaddr; @@ -247,6 +253,7 @@ int drm_addmap(struct drm_device * dev, unsigned long offset, default: DRM_ERROR("Bad map type %d\n", map->type); free(map, M_DRM); + DRM_LOCK(); return EINVAL; } @@ -788,8 +795,6 @@ int drm_addbufs_agp(struct drm_device *dev, drm_buf_desc_t *request) { int order, ret; - DRM_SPINLOCK(&dev->dma_lock); - if (request->count < 0 || request->count > 4096) return EINVAL; @@ -797,6 +802,8 @@ int drm_addbufs_agp(struct drm_device *dev, drm_buf_desc_t *request) if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return EINVAL; + DRM_SPINLOCK(&dev->dma_lock); + /* No more allocations after first buffer-using ioctl. */ if (dev->buf_use != 0) { DRM_SPINUNLOCK(&dev->dma_lock); @@ -819,14 +826,14 @@ int drm_addbufs_sg(struct drm_device *dev, drm_buf_desc_t *request) { int order, ret; - DRM_SPINLOCK(&dev->dma_lock); - if (!DRM_SUSER(DRM_CURPROC)) return EACCES; if (request->count < 0 || request->count > 4096) return EINVAL; - + + DRM_SPINLOCK(&dev->dma_lock); + order = drm_order(request->size); if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return EINVAL; @@ -853,18 +860,18 @@ int drm_addbufs_pci(struct drm_device *dev, drm_buf_desc_t *request) { int order, ret; - DRM_SPINLOCK(&dev->dma_lock); - if (!DRM_SUSER(DRM_CURPROC)) return EACCES; if (request->count < 0 || request->count > 4096) return EINVAL; - + order = drm_order(request->size); if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return EINVAL; + DRM_SPINLOCK(&dev->dma_lock); + /* No more allocations after first buffer-using ioctl. */ if (dev->buf_use != 0) { DRM_SPINUNLOCK(&dev->dma_lock); @@ -967,6 +974,7 @@ int drm_markbufs(struct drm_device *dev, void *data, struct drm_file *file_priv) DRM_SPINLOCK(&dev->dma_lock); if (request->low_mark > dma->bufs[order].buf_count || request->high_mark > dma->bufs[order].buf_count) { + DRM_SPINUNLOCK(&dev->dma_lock); return EINVAL; } commit 200ac59573b43abd112d27a1ddda3c124ba9db2a Author: Owain Ainsworth <og...@st...> Date: Tue May 27 14:59:38 2008 -0700 [BSD] Remove superfluous recursive locking in drm_add_magic. diff --git a/bsd-core/drm_auth.c b/bsd-core/drm_auth.c index 3423e67..f3aafe4 100644 --- a/bsd-core/drm_auth.c +++ b/bsd-core/drm_auth.c @@ -80,7 +80,6 @@ static int drm_add_magic(struct drm_device *dev, drm_file_t *priv, entry->priv = priv; entry->next = NULL; - DRM_LOCK(); if (dev->magiclist[hash].tail) { dev->magiclist[hash].tail->next = entry; dev->magiclist[hash].tail = entry; @@ -88,7 +87,6 @@ static int drm_add_magic(struct drm_device *dev, drm_file_t *priv, dev->magiclist[hash].head = entry; dev->magiclist[hash].tail = entry; } - DRM_UNLOCK(); return 0; } commit e45f95a03b7242115030a74ab27b142bc5c004c4 Author: Jie Luo <clo...@gm...> Date: Tue May 27 14:55:01 2008 -0700 [i915] Fix typo in (unused) START_ADDR definition. diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index b216c81..3c7dd4b 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -600,7 +600,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define HEAD_WRAP_ONE 0x00200000 #define HEAD_ADDR 0x001FFFFC #define RING_START 0x08 -#define START_ADDR 0x0xFFFFF000 +#define START_ADDR 0xFFFFF000 #define RING_LEN 0x0C #define RING_NR_PAGES 0x001FF000 #define RING_REPORT_MASK 0x00000006 |
From: <da...@ke...> - 2008-06-03 09:42:55
|
linux-core/drmP.h | 6 +-- linux-core/drm_drv.c | 2 - linux-core/drm_irq.c | 81 +++++++++++++++++++++++++++++++++++---------------- 3 files changed, 60 insertions(+), 29 deletions(-) New commits: commit ba7263b8c2f8c14c647da725ecbc73fcd456d63c Author: Michel Dänzer <mi...@tu...> Date: Tue Jun 3 11:28:10 2008 +0200 vblank: Don't wait or update the counter while the CRTC is supposedly disabled. Without kernel modesetting, this requires cooperation of the userspace modesetting driver. We may have to leave the vblank interrupt enabled otherwise to avoid problems. diff --git a/linux-core/drmP.h b/linux-core/drmP.h index d7b1960..00db300 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -843,6 +843,7 @@ struct drm_device { int *vblank_enabled; /* so we don't call enable more than once per disable */ u32 *vblank_premodeset; /* for compensation of spurious wraparounds */ + int *vblank_suspend; /* Don't wait while crtc is likely disabled */ struct timer_list vblank_disable_timer; u32 max_vblank_count; /**< size of vblank counter register */ diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index 3627a89..abedbe7 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -112,6 +112,8 @@ static void drm_vblank_cleanup(struct drm_device *dev) DRM_MEM_DRIVER); drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) * dev->num_crtcs, DRM_MEM_DRIVER); + drm_free(dev->vblank_suspend, sizeof(*dev->vblank_suspend) * + dev->num_crtcs, DRM_MEM_DRIVER); dev->num_crtcs = 0; } @@ -160,6 +162,11 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) if (!dev->vblank_premodeset) goto err; + dev->vblank_suspend = drm_calloc(num_crtcs, sizeof(int), + DRM_MEM_DRIVER); + if (!dev->vblank_suspend) + goto err; + /* Zero per-crtc vblank stuff */ for (i = 0; i < num_crtcs; i++) { init_waitqueue_head(&dev->vbl_queue[i]); @@ -343,6 +350,9 @@ void drm_update_vblank_count(struct drm_device *dev, int crtc) unsigned long irqflags; u32 cur_vblank, diff; + if (dev->vblank_suspend[crtc]) + return; + /* * Interrupts were disabled prior to this call, so deal with counter * wrap if needed. @@ -435,7 +445,6 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, { struct drm_modeset_ctl *modeset = data; int crtc, ret = 0; - u32 new; crtc = modeset->crtc; if (crtc >= dev->num_crtcs) { @@ -447,21 +456,25 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, case _DRM_PRE_MODESET: dev->vblank_premodeset[crtc] = dev->driver->get_vblank_counter(dev, crtc); + dev->vblank_suspend[crtc] = 1; break; case _DRM_POST_MODESET: - new = dev->driver->get_vblank_counter(dev, crtc); - - /* Compensate for spurious wraparound */ - if (new < dev->vblank_premodeset[crtc]) { - atomic_sub(dev->max_vblank_count + new - - dev->vblank_premodeset[crtc], - &dev->_vblank_count[crtc]); - DRM_DEBUG("vblank_premodeset[%d]=0x%x, new=0x%x " - "=> _vblank_count[%d]-=0x%x\n", crtc, - dev->vblank_premodeset[crtc], new, - crtc, dev->max_vblank_count + new - - dev->vblank_premodeset[crtc]); + if (dev->vblank_suspend[crtc]) { + u32 new = dev->driver->get_vblank_counter(dev, crtc); + + /* Compensate for spurious wraparound */ + if (new < dev->vblank_premodeset[crtc]) { + atomic_sub(dev->max_vblank_count + new - + dev->vblank_premodeset[crtc], + &dev->_vblank_count[crtc]); + DRM_DEBUG("vblank_premodeset[%d]=0x%x, new=0x%x" + " => _vblank_count[%d]-=0x%x\n", crtc, + dev->vblank_premodeset[crtc], new, + crtc, dev->max_vblank_count + new - + dev->vblank_premodeset[crtc]); + } } + dev->vblank_suspend[crtc] = 0; break; default: ret = -EINVAL; @@ -538,6 +551,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct list_head *vbl_sigs = &dev->vbl_sigs[crtc]; struct drm_vbl_sig *vbl_sig; + if (dev->vblank_suspend[crtc]) + return -EBUSY; + spin_lock_irqsave(&dev->vbl_lock, irqflags); /* Check if this task has already scheduled the same signal @@ -589,15 +605,15 @@ int drm_wait_vblank(struct drm_device *dev, void *data, vblwait->reply.sequence = seq; } else { - unsigned long cur_vblank; - - ret = drm_vblank_get(dev, crtc); - if (ret) - return ret; - DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ, - (((cur_vblank = drm_vblank_count(dev, crtc)) - - vblwait->request.sequence) <= (1 << 23))); - drm_vblank_put(dev, crtc); + if (!dev->vblank_suspend[crtc]) { + ret = drm_vblank_get(dev, crtc); + if (ret) + return ret; + DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ, + ((drm_vblank_count(dev, crtc) + - vblwait->request.sequence) <= (1 << 23))); + drm_vblank_put(dev, crtc); + } if (ret != -EINTR) { struct timeval now; @@ -606,7 +622,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, vblwait->reply.tval_sec = now.tv_sec; vblwait->reply.tval_usec = now.tv_usec; - vblwait->reply.sequence = cur_vblank; + vblwait->reply.sequence = drm_vblank_count(dev, crtc); } } commit 237172b7670611b36d92be3b92983674846f6564 Author: Michel Dänzer <mi...@tu...> Date: Tue Jun 3 11:28:10 2008 +0200 vblank: Clean up compensation for spurious wraparounds of driver counter. Only compensate when the driver counter actually appears to have moved backwards. The compensation deltas need to be incremental instead of absolute; drop the vblank_offset field and just use atomic_sub(). diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 69d31e1..d7b1960 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -840,13 +840,12 @@ struct drm_device { atomic_t *vblank_refcount; /* number of users of vblank interrupts per crtc */ u32 *last_vblank; /* protected by dev->vbl_lock, used */ /* for wraparound handling */ - u32 *vblank_offset; /* used to track how many vblanks */ int *vblank_enabled; /* so we don't call enable more than once per disable */ - u32 *vblank_premodeset; /* were lost during modeset */ + u32 *vblank_premodeset; /* for compensation of spurious wraparounds */ struct timer_list vblank_disable_timer; - unsigned long max_vblank_count; /**< size of vblank counter register */ + u32 max_vblank_count; /**< size of vblank counter register */ spinlock_t tasklet_lock; /**< For drm_locked_tasklet */ void (*locked_tasklet_func)(struct drm_device *dev); diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index ccb3ca8..3627a89 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -112,8 +112,6 @@ static void drm_vblank_cleanup(struct drm_device *dev) DRM_MEM_DRIVER); drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) * dev->num_crtcs, DRM_MEM_DRIVER); - drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * dev->num_crtcs, - DRM_MEM_DRIVER); dev->num_crtcs = 0; } @@ -162,10 +160,6 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) if (!dev->vblank_premodeset) goto err; - dev->vblank_offset = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER); - if (!dev->vblank_offset) - goto err; - /* Zero per-crtc vblank stuff */ for (i = 0; i < num_crtcs; i++) { init_waitqueue_head(&dev->vbl_queue[i]); @@ -330,8 +324,7 @@ int drm_control(struct drm_device *dev, void *data, */ u32 drm_vblank_count(struct drm_device *dev, int crtc) { - return atomic_read(&dev->_vblank_count[crtc]) + - dev->vblank_offset[crtc]; + return atomic_read(&dev->_vblank_count[crtc]); } EXPORT_SYMBOL(drm_vblank_count); @@ -457,7 +450,18 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, break; case _DRM_POST_MODESET: new = dev->driver->get_vblank_counter(dev, crtc); - dev->vblank_offset[crtc] = dev->vblank_premodeset[crtc] - new; + + /* Compensate for spurious wraparound */ + if (new < dev->vblank_premodeset[crtc]) { + atomic_sub(dev->max_vblank_count + new - + dev->vblank_premodeset[crtc], + &dev->_vblank_count[crtc]); + DRM_DEBUG("vblank_premodeset[%d]=0x%x, new=0x%x " + "=> _vblank_count[%d]-=0x%x\n", crtc, + dev->vblank_premodeset[crtc], new, + crtc, dev->max_vblank_count + new - + dev->vblank_premodeset[crtc]); + } break; default: ret = -EINVAL; commit d1dcb2b32e0c51d7cbcaa2ba1e0544452cf8f47b Author: Michel Dänzer <mi...@tu...> Date: Tue Jun 3 11:28:09 2008 +0200 vblank: Special-case driver vblank counter going back by 1. Turns out the radeon driver is affected by the same problem that prompted i915 to revert to less useful counter flipping at the end of the vblank interval. In the long term, we can hopefully implement more reliable methods to achieve counter flipping at the beginning of vblank, but otherwise this should be an acceptable workaround. diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index e2f106e..ccb3ca8 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -360,9 +360,16 @@ void drm_update_vblank_count(struct drm_device *dev, int crtc) cur_vblank = dev->driver->get_vblank_counter(dev, crtc); spin_lock_irqsave(&dev->vbl_lock, irqflags); if (cur_vblank < dev->last_vblank[crtc]) { - diff = dev->max_vblank_count - - dev->last_vblank[crtc]; - diff += cur_vblank; + if (cur_vblank == dev->last_vblank[crtc] - 1) { + diff = 0; + } else { + diff = dev->max_vblank_count - + dev->last_vblank[crtc]; + diff += cur_vblank; + } + + DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n", + crtc, dev->last_vblank[crtc], cur_vblank, diff); } else { diff = cur_vblank - dev->last_vblank[crtc]; } commit 0144ebeb8a713b1420d35004075037cd4b0495a1 Author: Michel Dänzer <mi...@tu...> Date: Tue Jun 3 11:28:09 2008 +0200 vblank: Don't return current sequence number and time if interrupted by signal. diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index 8f27d7f..e2f106e 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -484,7 +484,6 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv) { union drm_wait_vblank *vblwait = data; - struct timeval now; int ret = 0; unsigned int flags, seq, crtc; @@ -588,11 +587,16 @@ int drm_wait_vblank(struct drm_device *dev, void *data, (((cur_vblank = drm_vblank_count(dev, crtc)) - vblwait->request.sequence) <= (1 << 23))); drm_vblank_put(dev, crtc); - do_gettimeofday(&now); - vblwait->reply.tval_sec = now.tv_sec; - vblwait->reply.tval_usec = now.tv_usec; - vblwait->reply.sequence = cur_vblank; + if (ret != -EINTR) { + struct timeval now; + + do_gettimeofday(&now); + + vblwait->reply.tval_sec = now.tv_sec; + vblwait->reply.tval_usec = now.tv_usec; + vblwait->reply.sequence = cur_vblank; + } } done: commit 6b520005c6714d8a8afa68b8a43065a40da298cc Author: Michel Dänzer <mi...@tu...> Date: Tue Jun 3 11:27:39 2008 +0200 Revert "don't copy back if an error was returned." This reverts commit 6671ad1917698b6174a1af314b63b3800d75248c. The vblank ioctl needs to update the userspace parameters when interrupted by a signal, which was prevented by this. Let's see if this breaks other ioctls... diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index b8b8333..609fc83 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -655,7 +655,7 @@ long drm_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) retcode = func(dev, kdata, file_priv); } - if ((retcode == 0) && (cmd & IOC_OUT)) { + if (cmd & IOC_OUT) { if (copy_to_user((void __user *)arg, kdata, _IOC_SIZE(cmd)) != 0) retcode = -EACCES; |
From: <an...@ke...> - 2008-09-10 21:09:56
|
.gitignore | 1 libdrm/Makefile.am | 7 - libdrm/dri_bufmgr.c | 141 ----------------------- libdrm/dri_bufmgr.h | 174 ----------------------------- libdrm/intel/Makefile.am | 7 + libdrm/intel/intel_bufmgr.c | 194 ++++++++++++++++++++++++++++++++ libdrm/intel/intel_bufmgr.h | 133 +++++++++++----------- libdrm/intel/intel_bufmgr_fake.c | 230 ++++++++++++++++++++++++++++++--------- libdrm/intel/intel_bufmgr_gem.c | 154 +++++++------------------- libdrm/intel/intel_bufmgr_priv.h | 165 +++++++++++++++++++++++++++ tests/Makefile.am | 1 tests/gem_flink.c | 128 +++++++++++++++++++++ 12 files changed, 787 insertions(+), 548 deletions(-) New commits: commit 368b392e6dcd19cb75675c0c18d02f70257af1df Author: Eric Anholt <er...@an...> Date: Wed Sep 10 13:54:34 2008 -0700 intel: don't forget to include config.h in bufmgr code. Thanks to airlied for catching this. diff --git a/libdrm/intel/intel_bufmgr.c b/libdrm/intel/intel_bufmgr.c index 45b691d..fc7284b 100644 --- a/libdrm/intel/intel_bufmgr.c +++ b/libdrm/intel/intel_bufmgr.c @@ -25,6 +25,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <string.h> #include <stdlib.h> #include <stdint.h> diff --git a/libdrm/intel/intel_bufmgr_fake.c b/libdrm/intel/intel_bufmgr_fake.c index f9e1cd1..4b4c2a1 100644 --- a/libdrm/intel/intel_bufmgr_fake.c +++ b/libdrm/intel/intel_bufmgr_fake.c @@ -34,6 +34,10 @@ * the bugs in the old texture manager. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> #include <assert.h> diff --git a/libdrm/intel/intel_bufmgr_gem.c b/libdrm/intel/intel_bufmgr_gem.c index 4415272..97e387f 100644 --- a/libdrm/intel/intel_bufmgr_gem.c +++ b/libdrm/intel/intel_bufmgr_gem.c @@ -34,6 +34,10 @@ * Dave Airlie <ai...@li...> */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <xf86drm.h> #include <stdio.h> #include <stdlib.h> commit f9d98beefc9e7b8d06a29f5b69a19f10fd3c435f Author: Eric Anholt <er...@an...> Date: Mon Sep 8 08:51:40 2008 -0700 intel: move drm calls to exec buffers to libdrm_intel. This avoids duplicating the effort in 3 places. Also, added emit/wait fence callbacks back in bufmgr_fake since we need it for non-drm 2d. Sigh. diff --git a/libdrm/intel/intel_bufmgr.c b/libdrm/intel/intel_bufmgr.c index 5a9cdbe..45b691d 100644 --- a/libdrm/intel/intel_bufmgr.c +++ b/libdrm/intel/intel_bufmgr.c @@ -123,14 +123,12 @@ dri_bufmgr_destroy(dri_bufmgr *bufmgr) bufmgr->destroy(bufmgr); } -void *dri_process_relocs(dri_bo *batch_buf) -{ - return batch_buf->bufmgr->process_relocs(batch_buf); -} - -void dri_post_submit(dri_bo *batch_buf) +int +dri_bo_exec(dri_bo *bo, int used, + drm_clip_rect_t *cliprects, int num_cliprects, + int DR4) { - batch_buf->bufmgr->post_submit(batch_buf); + return bo->bufmgr->bo_exec(bo, used, cliprects, num_cliprects, DR4); } void diff --git a/libdrm/intel/intel_bufmgr.h b/libdrm/intel/intel_bufmgr.h index 57a9e33..c44d596 100644 --- a/libdrm/intel/intel_bufmgr.h +++ b/libdrm/intel/intel_bufmgr.h @@ -76,10 +76,9 @@ void dri_bo_wait_rendering(dri_bo *bo); void dri_bufmgr_set_debug(dri_bufmgr *bufmgr, int enable_debug); void dri_bufmgr_destroy(dri_bufmgr *bufmgr); - -void *dri_process_relocs(dri_bo *batch_buf); -void dri_post_process_relocs(dri_bo *batch_buf); -void dri_post_submit(dri_bo *batch_buf); +int dri_bo_exec(dri_bo *bo, int used, + drm_clip_rect_t *cliprects, int num_cliprects, + int DR4); int dri_bufmgr_check_aperture_space(dri_bo **bo_array, int count); int dri_bo_emit_reloc(dri_bo *reloc_buf, @@ -103,6 +102,16 @@ dri_bufmgr *intel_bufmgr_fake_init(int fd, volatile unsigned int *last_dispatch); void intel_bufmgr_fake_set_last_dispatch(dri_bufmgr *bufmgr, volatile unsigned int *last_dispatch); +void intel_bufmgr_fake_set_exec_callback(dri_bufmgr *bufmgr, + int (*exec)(dri_bo *bo, + unsigned int used, + void *priv), + void *priv); +void intel_bufmgr_fake_set_fence_callback(dri_bufmgr *bufmgr, + unsigned int (*emit)(void *priv), + void (*wait)(unsigned int fence, + void *priv), + void *priv); dri_bo *intel_bo_fake_alloc_static(dri_bufmgr *bufmgr, const char *name, unsigned long offset, unsigned long size, void *virtual); diff --git a/libdrm/intel/intel_bufmgr_fake.c b/libdrm/intel/intel_bufmgr_fake.c index 4762903..f9e1cd1 100644 --- a/libdrm/intel/intel_bufmgr_fake.c +++ b/libdrm/intel/intel_bufmgr_fake.c @@ -136,6 +136,31 @@ typedef struct _bufmgr_fake { unsigned need_fence:1; int thrashing; + /** + * Driver callback to emit a fence, returning the cookie. + * + * This allows the driver to hook in a replacement for the DRM usage in + * bufmgr_fake. + * + * Currently, this also requires that a write flush be emitted before + * emitting the fence, but this should change. + */ + unsigned int (*fence_emit)(void *private); + /** Driver callback to wait for a fence cookie to have passed. */ + void (*fence_wait)(unsigned int fence, void *private); + void *fence_priv; + + /** + * Driver callback to execute a buffer. + * + * This allows the driver to hook in a replacement for the DRM usage in + * bufmgr_fake. + */ + int (*exec)(dri_bo *bo, unsigned int used, void *priv); + void *exec_priv; + + /** Driver-supplied argument to driver callbacks */ + void *driver_priv; /* Pointer to kernel-updated sarea data for the last completed user irq */ volatile unsigned int *last_dispatch; @@ -205,12 +230,28 @@ static int FENCE_LTE( unsigned a, unsigned b ) return 0; } +void intel_bufmgr_fake_set_fence_callback(dri_bufmgr *bufmgr, + unsigned int (*emit)(void *priv), + void (*wait)(unsigned int fence, + void *priv), + void *priv) +{ + dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bufmgr; + + bufmgr_fake->fence_emit = emit; + bufmgr_fake->fence_wait = wait; + bufmgr_fake->fence_priv = priv; +} + static unsigned int _fence_emit_internal(dri_bufmgr_fake *bufmgr_fake) { struct drm_i915_irq_emit ie; int ret, seq = 1; + if (bufmgr_fake->fence_emit != NULL) + return bufmgr_fake->fence_emit(bufmgr_fake->fence_priv); + ie.irq_seq = &seq; ret = drmCommandWriteRead(bufmgr_fake->fd, DRM_I915_IRQ_EMIT, &ie, sizeof(ie)); @@ -243,6 +284,11 @@ _fence_wait_internal(dri_bufmgr_fake *bufmgr_fake, unsigned int cookie) unsigned int last_dispatch; int ret; + if (bufmgr_fake->fence_wait != NULL) { + bufmgr_fake->fence_wait(cookie, bufmgr_fake->fence_priv); + return; + } + DBG("wait 0x%08x\n", iw.irq_seq); /* The kernel implementation of IRQ_WAIT is broken for wraparound, and has @@ -1092,38 +1138,6 @@ dri_fake_reloc_and_validate_buffer(dri_bo *bo) return dri_fake_bo_validate(bo); } -static void * -dri_fake_process_relocs(dri_bo *batch_buf) -{ - dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)batch_buf->bufmgr; - dri_bo_fake *batch_fake = (dri_bo_fake *)batch_buf; - int ret; - int retry_count = 0; - - bufmgr_fake->performed_rendering = 0; - - dri_fake_calculate_domains(batch_buf); - - batch_fake->read_domains = I915_GEM_DOMAIN_COMMAND; - - /* we've ran out of RAM so blow the whole lot away and retry */ - restart: - ret = dri_fake_reloc_and_validate_buffer(batch_buf); - if (bufmgr_fake->fail == 1) { - if (retry_count == 0) { - retry_count++; - dri_fake_kick_all(bufmgr_fake); - bufmgr_fake->fail = 0; - goto restart; - } else /* dump out the memory here */ - mmDumpMemInfo(bufmgr_fake->heap); - } - - assert(ret == 0); - - return NULL; -} - static void dri_bo_fake_post_submit(dri_bo *bo) { @@ -1150,12 +1164,74 @@ dri_bo_fake_post_submit(dri_bo *bo) } -static void -dri_fake_post_submit(dri_bo *batch_buf) +void intel_bufmgr_fake_set_exec_callback(dri_bufmgr *bufmgr, + int (*exec)(dri_bo *bo, + unsigned int used, + void *priv), + void *priv) +{ + dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bufmgr; + + bufmgr_fake->exec = exec; + bufmgr_fake->exec_priv = exec; +} + +static int +dri_fake_bo_exec(dri_bo *bo, int used, + drm_clip_rect_t *cliprects, int num_cliprects, + int DR4) { - dri_fake_fence_validated(batch_buf->bufmgr); + dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr; + dri_bo_fake *batch_fake = (dri_bo_fake *)bo; + struct drm_i915_batchbuffer batch; + int ret; + int retry_count = 0; + + bufmgr_fake->performed_rendering = 0; + + dri_fake_calculate_domains(bo); - dri_bo_fake_post_submit(batch_buf); + batch_fake->read_domains = I915_GEM_DOMAIN_COMMAND; + + /* we've ran out of RAM so blow the whole lot away and retry */ + restart: + ret = dri_fake_reloc_and_validate_buffer(bo); + if (bufmgr_fake->fail == 1) { + if (retry_count == 0) { + retry_count++; + dri_fake_kick_all(bufmgr_fake); + bufmgr_fake->fail = 0; + goto restart; + } else /* dump out the memory here */ + mmDumpMemInfo(bufmgr_fake->heap); + } + + assert(ret == 0); + + if (bufmgr_fake->exec != NULL) { + int ret = bufmgr_fake->exec(bo, used, bufmgr_fake->exec_priv); + if (ret != 0) + return ret; + } else { + batch.start = bo->offset; + batch.used = used; + batch.cliprects = cliprects; + batch.num_cliprects = num_cliprects; + batch.DR1 = 0; + batch.DR4 = DR4; + + if (drmCommandWrite(bufmgr_fake->fd, DRM_I915_BATCHBUFFER, &batch, + sizeof(batch))) { + drmMsg("DRM_I915_BATCHBUFFER: %d\n", -errno); + return -errno; + } + } + + dri_fake_fence_validated(bo->bufmgr); + + dri_bo_fake_post_submit(bo); + + return 0; } /** @@ -1264,8 +1340,7 @@ intel_bufmgr_fake_init(int fd, bufmgr_fake->bufmgr.bo_wait_rendering = dri_fake_bo_wait_rendering; bufmgr_fake->bufmgr.bo_emit_reloc = dri_fake_emit_reloc; bufmgr_fake->bufmgr.destroy = dri_fake_destroy; - bufmgr_fake->bufmgr.process_relocs = dri_fake_process_relocs; - bufmgr_fake->bufmgr.post_submit = dri_fake_post_submit; + bufmgr_fake->bufmgr.bo_exec = dri_fake_bo_exec; bufmgr_fake->bufmgr.check_aperture_space = dri_fake_check_aperture_space; bufmgr_fake->bufmgr.debug = 0; diff --git a/libdrm/intel/intel_bufmgr_gem.c b/libdrm/intel/intel_bufmgr_gem.c index 43d2d98..4415272 100644 --- a/libdrm/intel/intel_bufmgr_gem.c +++ b/libdrm/intel/intel_bufmgr_gem.c @@ -87,8 +87,6 @@ typedef struct _dri_bufmgr_gem { /** Array of lists of cached gem objects of power-of-two sizes */ struct dri_gem_bo_bucket cache_bucket[INTEL_GEM_BO_BUCKETS]; - - struct drm_i915_gem_execbuffer exec_arg; } dri_bufmgr_gem; struct _dri_bo_gem { @@ -706,27 +704,6 @@ dri_gem_bo_process_reloc(dri_bo *bo) } } -static void * -dri_gem_process_reloc(dri_bo *batch_buf) -{ - dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *) batch_buf->bufmgr; - - /* Update indices and set up the validate list. */ - dri_gem_bo_process_reloc(batch_buf); - - /* Add the batch buffer to the validation list. There are no relocations - * pointing to it. - */ - intel_add_validate_buffer(batch_buf); - - bufmgr_gem->exec_arg.buffers_ptr = (uintptr_t)bufmgr_gem->exec_objects; - bufmgr_gem->exec_arg.buffer_count = bufmgr_gem->exec_count; - bufmgr_gem->exec_arg.batch_start_offset = 0; - bufmgr_gem->exec_arg.batch_len = 0; /* written in intel_exec_ioctl */ - - return &bufmgr_gem->exec_arg; -} - static void intel_update_buffer_offsets (dri_bufmgr_gem *bufmgr_gem) { @@ -746,11 +723,35 @@ intel_update_buffer_offsets (dri_bufmgr_gem *bufmgr_gem) } } -static void -dri_gem_post_submit(dri_bo *batch_buf) +static int +dri_gem_bo_exec(dri_bo *bo, int used, + drm_clip_rect_t *cliprects, int num_cliprects, + int DR4) { - dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)batch_buf->bufmgr; - int i; + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; + struct drm_i915_gem_execbuffer execbuf; + int ret, i; + + /* Update indices and set up the validate list. */ + dri_gem_bo_process_reloc(bo); + + /* Add the batch buffer to the validation list. There are no relocations + * pointing to it. + */ + intel_add_validate_buffer(bo); + + execbuf.buffers_ptr = (uintptr_t)bufmgr_gem->exec_objects; + execbuf.buffer_count = bufmgr_gem->exec_count; + execbuf.batch_start_offset = 0; + execbuf.batch_len = used; + execbuf.cliprects_ptr = (uintptr_t)cliprects; + execbuf.num_cliprects = num_cliprects; + execbuf.DR1 = 0; + execbuf.DR4 = DR4; + + do { + ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER, &execbuf); + } while (ret == -EAGAIN); intel_update_buffer_offsets (bufmgr_gem); @@ -770,6 +771,8 @@ dri_gem_post_submit(dri_bo *batch_buf) bufmgr_gem->exec_bos[i] = NULL; } bufmgr_gem->exec_count = 0; + + return 0; } static int @@ -913,9 +916,8 @@ intel_bufmgr_gem_init(int fd, int batch_size) bufmgr_gem->bufmgr.bo_unpin = dri_gem_bo_unpin; bufmgr_gem->bufmgr.bo_set_tiling = dri_gem_bo_set_tiling; bufmgr_gem->bufmgr.bo_flink = dri_gem_bo_flink; + bufmgr_gem->bufmgr.bo_exec = dri_gem_bo_exec; bufmgr_gem->bufmgr.destroy = dri_bufmgr_gem_destroy; - bufmgr_gem->bufmgr.process_relocs = dri_gem_process_reloc; - bufmgr_gem->bufmgr.post_submit = dri_gem_post_submit; bufmgr_gem->bufmgr.debug = 0; bufmgr_gem->bufmgr.check_aperture_space = dri_gem_check_aperture_space; /* Initialize the linked lists for BO reuse cache. */ diff --git a/libdrm/intel/intel_bufmgr_priv.h b/libdrm/intel/intel_bufmgr_priv.h index 8a5741f..7f39bfc 100644 --- a/libdrm/intel/intel_bufmgr_priv.h +++ b/libdrm/intel/intel_bufmgr_priv.h @@ -103,23 +103,6 @@ struct _dri_bufmgr { */ void (*destroy)(dri_bufmgr *bufmgr); - /** - * Processes the relocations, either in userland or by converting the list - * for use in batchbuffer submission. - * - * Kernel-based implementations will return a pointer to the arguments - * to be handed with batchbuffer submission to the kernel. The userland - * implementation performs the buffer validation and emits relocations - * into them the appopriate order. - * - * \param batch_buf buffer at the root of the tree of relocations - * \return argument to be completed and passed to the execbuffers ioctl - * (if any). - */ - void *(*process_relocs)(dri_bo *batch_buf); - - void (*post_submit)(dri_bo *batch_buf); - /** * Add relocation entry in reloc_buf, which will be updated with the * target buffer's real offset on on command submission. @@ -140,6 +123,12 @@ struct _dri_bufmgr { int (*bo_emit_reloc)(dri_bo *reloc_buf, uint32_t read_domains, uint32_t write_domain, uint32_t delta, uint32_t offset, dri_bo *target); + + /** Executes the command buffer pointed to by bo. */ + int (*bo_exec)(dri_bo *bo, int used, + drm_clip_rect_t *cliprects, int num_cliprects, + int DR4); + /** * Pin a buffer to the aperture and fix the offset until unpinned * commit 869d8bebedddf2075c59d6bffea8ee640cb80353 Author: Eric Anholt <er...@an...> Date: Sat Sep 6 03:07:41 2008 +0100 intel: Move IRQ emit/wait from callbacks into the bufmgr. In the process, work around the glaring bugs of the kernel irq wait function. diff --git a/libdrm/intel/intel_bufmgr.h b/libdrm/intel/intel_bufmgr.h index 0b473f3..57a9e33 100644 --- a/libdrm/intel/intel_bufmgr.h +++ b/libdrm/intel/intel_bufmgr.h @@ -97,12 +97,12 @@ dri_bo *intel_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name, void intel_bufmgr_gem_enable_reuse(dri_bufmgr *bufmgr); /* intel_bufmgr_fake.c */ -dri_bufmgr *intel_bufmgr_fake_init(unsigned long low_offset, void *low_virtual, +dri_bufmgr *intel_bufmgr_fake_init(int fd, + unsigned long low_offset, void *low_virtual, unsigned long size, - unsigned int (*fence_emit)(void *private), - int (*fence_wait)(void *private, - unsigned int cookie), - void *driver_priv); + volatile unsigned int *last_dispatch); +void intel_bufmgr_fake_set_last_dispatch(dri_bufmgr *bufmgr, + volatile unsigned int *last_dispatch); dri_bo *intel_bo_fake_alloc_static(dri_bufmgr *bufmgr, const char *name, unsigned long offset, unsigned long size, void *virtual); diff --git a/libdrm/intel/intel_bufmgr_fake.c b/libdrm/intel/intel_bufmgr_fake.c index 8e581ae..4762903 100644 --- a/libdrm/intel/intel_bufmgr_fake.c +++ b/libdrm/intel/intel_bufmgr_fake.c @@ -37,6 +37,7 @@ #include <stdlib.h> #include <string.h> #include <assert.h> +#include <errno.h> #include <xf86drm.h> #include "intel_bufmgr.h" #include "intel_bufmgr_priv.h" @@ -135,17 +136,10 @@ typedef struct _bufmgr_fake { unsigned need_fence:1; int thrashing; - /** - * Driver callback to emit a fence, returning the cookie. - * - * Currently, this also requires that a write flush be emitted before - * emitting the fence, but this should change. - */ - unsigned int (*fence_emit)(void *private); - /** Driver callback to wait for a fence cookie to have passed. */ - int (*fence_wait)(void *private, unsigned int fence_cookie); - /** Driver-supplied argument to driver callbacks */ - void *driver_priv; + /* Pointer to kernel-updated sarea data for the last completed user irq */ + volatile unsigned int *last_dispatch; + + int fd; int debug; @@ -214,18 +208,64 @@ static int FENCE_LTE( unsigned a, unsigned b ) static unsigned int _fence_emit_internal(dri_bufmgr_fake *bufmgr_fake) { - bufmgr_fake->last_fence = bufmgr_fake->fence_emit(bufmgr_fake->driver_priv); + struct drm_i915_irq_emit ie; + int ret, seq = 1; + + ie.irq_seq = &seq; + ret = drmCommandWriteRead(bufmgr_fake->fd, DRM_I915_IRQ_EMIT, + &ie, sizeof(ie)); + if (ret) { + drmMsg("%s: drm_i915_irq_emit: %d\n", __FUNCTION__, ret); + abort(); + } + + /* The kernel implementation of IRQ_WAIT is broken for wraparound, and has + * been since it was first introduced. It only checks for + * completed_seq >= seq, and thus returns success early for wrapped irq + * values if the CPU wins a race. + * + * We have to do it up front at emit when we discover wrap, so that another + * client can't race (after we drop the lock) to emit and wait and fail. + */ + if (seq == 0 || seq == 1) { + drmCommandWriteRead(bufmgr_fake->fd, DRM_I915_FLUSH, &ie, sizeof(ie)); + } + + DBG("emit 0x%08x\n", seq); + bufmgr_fake->last_fence = seq; return bufmgr_fake->last_fence; } static void _fence_wait_internal(dri_bufmgr_fake *bufmgr_fake, unsigned int cookie) { + struct drm_i915_irq_wait iw; + unsigned int last_dispatch; int ret; - ret = bufmgr_fake->fence_wait(bufmgr_fake->driver_priv, cookie); + DBG("wait 0x%08x\n", iw.irq_seq); + + /* The kernel implementation of IRQ_WAIT is broken for wraparound, and has + * been since it was first introduced. It only checks for + * completed_seq >= seq, and thus never returns for pre-wrapped irq values + * if the GPU wins the race. + * + * So, check if it looks like a pre-wrapped value and just return success. + */ + if (*bufmgr_fake->last_dispatch - cookie > 0x4000000) + return; + + iw.irq_seq = cookie; + + do { + last_dispatch = *bufmgr_fake->last_dispatch; + ret = drmCommandWrite(bufmgr_fake->fd, DRM_I915_IRQ_WAIT, + &iw, sizeof(iw)); + } while (ret == -EAGAIN || ret == -EINTR || + (ret == -EBUSY && last_dispatch != *bufmgr_fake->last_dispatch)); + if (ret != 0) { - drmMsg("%s:%d: Error %d waiting for fence.\n", __FILE__, __LINE__); + drmMsg("%s:%d: Error %d waiting for fence.\n", __FILE__, __LINE__, ret); abort(); } clear_fenced(bufmgr_fake, cookie); @@ -540,7 +580,7 @@ dri_bufmgr_fake_wait_idle(dri_bufmgr_fake *bufmgr_fake) { unsigned int cookie; - cookie = bufmgr_fake->fence_emit(bufmgr_fake->driver_priv); + cookie = _fence_emit_internal(bufmgr_fake); _fence_wait_internal(bufmgr_fake, cookie); } @@ -1187,13 +1227,19 @@ intel_bufmgr_fake_evict_all(dri_bufmgr *bufmgr) free_block(bufmgr_fake, block); } } +void intel_bufmgr_fake_set_last_dispatch(dri_bufmgr *bufmgr, + volatile unsigned int *last_dispatch) +{ + dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bufmgr; + + bufmgr_fake->last_dispatch = last_dispatch; +} dri_bufmgr * -intel_bufmgr_fake_init(unsigned long low_offset, void *low_virtual, +intel_bufmgr_fake_init(int fd, + unsigned long low_offset, void *low_virtual, unsigned long size, - unsigned int (*fence_emit)(void *private), - int (*fence_wait)(void *private, unsigned int cookie), - void *driver_priv) + volatile unsigned int *last_dispatch) { dri_bufmgr_fake *bufmgr_fake; @@ -1223,9 +1269,8 @@ intel_bufmgr_fake_init(unsigned long low_offset, void *low_virtual, bufmgr_fake->bufmgr.check_aperture_space = dri_fake_check_aperture_space; bufmgr_fake->bufmgr.debug = 0; - bufmgr_fake->fence_emit = fence_emit; - bufmgr_fake->fence_wait = fence_wait; - bufmgr_fake->driver_priv = driver_priv; + bufmgr_fake->fd = fd; + bufmgr_fake->last_dispatch = last_dispatch; return &bufmgr_fake->bufmgr; } diff --git a/libdrm/intel/intel_bufmgr_priv.h b/libdrm/intel/intel_bufmgr_priv.h index 92476ae..8a5741f 100644 --- a/libdrm/intel/intel_bufmgr_priv.h +++ b/libdrm/intel/intel_bufmgr_priv.h @@ -172,29 +172,5 @@ struct _dri_bufmgr { int debug; /**< Enables verbose debugging printouts */ }; -/* intel_bufmgr_gem.c */ -dri_bufmgr *intel_bufmgr_gem_init(int fd, int batch_size); -dri_bo *intel_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name, - unsigned int handle); -void intel_bufmgr_gem_enable_reuse(dri_bufmgr *bufmgr); - -/* intel_bufmgr_fake.c */ -dri_bufmgr *intel_bufmgr_fake_init(unsigned long low_offset, void *low_virtual, - unsigned long size, - unsigned int (*fence_emit)(void *private), - int (*fence_wait)(void *private, - unsigned int cookie), - void *driver_priv); -dri_bo *intel_bo_fake_alloc_static(dri_bufmgr *bufmgr, const char *name, - unsigned long offset, unsigned long size, - void *virtual); - -void intel_bufmgr_fake_contended_lock_take(dri_bufmgr *bufmgr); -void intel_bo_fake_disable_backing_store(dri_bo *bo, - void (*invalidate_cb)(dri_bo *bo, - void *ptr), - void *ptr); -void intel_bufmgr_fake_evict_all(dri_bufmgr *bufmgr); - #endif /* INTEL_BUFMGR_PRIV_H */ commit 738e36acbce24df0ccadb499c5cf62ccb74f56df Author: Eric Anholt <er...@an...> Date: Fri Sep 5 10:35:32 2008 +0100 Move intel libdrm stuff to libdrm_intel.so dri_bufmgr.h is replaced by intel_bufmgr.h, and several functions are renamed, though the structures and many functions remain dri_bufmgr_* and dri_bo_* diff --git a/libdrm/Makefile.am b/libdrm/Makefile.am index b73cb67..b69fcfe 100644 --- a/libdrm/Makefile.am +++ b/libdrm/Makefile.am @@ -25,11 +25,10 @@ libdrm_ladir = $(libdir) libdrm_la_LDFLAGS = -version-number 2:3:0 -no-undefined AM_CFLAGS = -I$(top_srcdir)/shared-core -libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c \ - dri_bufmgr.c libdrm_lists.h -libdrm_la_LIBADD = intel/libdrm_intel.la +libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c + libdrm_lists.h libdrmincludedir = ${includedir} -libdrminclude_HEADERS = xf86drm.h dri_bufmgr.h +libdrminclude_HEADERS = xf86drm.h EXTRA_DIST = ChangeLog TODO diff --git a/libdrm/dri_bufmgr.c b/libdrm/dri_bufmgr.c deleted file mode 100644 index a6eda3b..0000000 --- a/libdrm/dri_bufmgr.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright © 2007 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 (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. - * - * Authors: - * Eric Anholt <er...@an...> - * - */ - -#include <string.h> -#include <stdlib.h> -#include <assert.h> -#include "dri_bufmgr.h" - -/** @file dri_bufmgr.c - * - * Convenience functions for buffer management methods. - */ - -dri_bo * -dri_bo_alloc(dri_bufmgr *bufmgr, const char *name, unsigned long size, - unsigned int alignment) -{ - return bufmgr->bo_alloc(bufmgr, name, size, alignment); -} - -void -dri_bo_reference(dri_bo *bo) -{ - bo->bufmgr->bo_reference(bo); -} - -void -dri_bo_unreference(dri_bo *bo) -{ - if (bo == NULL) - return; - - bo->bufmgr->bo_unreference(bo); -} - -int -dri_bo_map(dri_bo *buf, int write_enable) -{ - return buf->bufmgr->bo_map(buf, write_enable); -} - -int -dri_bo_unmap(dri_bo *buf) -{ - return buf->bufmgr->bo_unmap(buf); -} - -int -dri_bo_subdata(dri_bo *bo, unsigned long offset, - unsigned long size, const void *data) -{ - int ret; - if (bo->bufmgr->bo_subdata) - return bo->bufmgr->bo_subdata(bo, offset, size, data); - if (size == 0 || data == NULL) - return 0; - - ret = dri_bo_map(bo, 1); - if (ret) - return ret; - memcpy((unsigned char *)bo->virtual + offset, data, size); - dri_bo_unmap(bo); - return 0; -} - -int -dri_bo_get_subdata(dri_bo *bo, unsigned long offset, - unsigned long size, void *data) -{ - int ret; - if (bo->bufmgr->bo_subdata) - return bo->bufmgr->bo_get_subdata(bo, offset, size, data); - - if (size == 0 || data == NULL) - return 0; - - ret = dri_bo_map(bo, 0); - if (ret) - return ret; - memcpy(data, (unsigned char *)bo->virtual + offset, size); - dri_bo_unmap(bo); - return 0; -} - -void -dri_bo_wait_rendering(dri_bo *bo) -{ - bo->bufmgr->bo_wait_rendering(bo); -} - -void -dri_bufmgr_destroy(dri_bufmgr *bufmgr) -{ - bufmgr->destroy(bufmgr); -} - -void *dri_process_relocs(dri_bo *batch_buf) -{ - return batch_buf->bufmgr->process_relocs(batch_buf); -} - -void dri_post_submit(dri_bo *batch_buf) -{ - batch_buf->bufmgr->post_submit(batch_buf); -} - -void -dri_bufmgr_set_debug(dri_bufmgr *bufmgr, int enable_debug) -{ - bufmgr->debug = enable_debug; -} - -int -dri_bufmgr_check_aperture_space(dri_bo **bo_array, int count) -{ - return bo_array[0]->bufmgr->check_aperture_space(bo_array, count); -} diff --git a/libdrm/dri_bufmgr.h b/libdrm/dri_bufmgr.h deleted file mode 100644 index e67756b..0000000 --- a/libdrm/dri_bufmgr.h +++ /dev/null @@ -1,174 +0,0 @@ -/************************************************************************** - * - * Copyright © 2007 Intel Corporation - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., 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 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> - * Keith Whitwell <keithw-at-tungstengraphics-dot-com> - * Eric Anholt <er...@an...> - */ - -#ifndef _DRI_BUFMGR_H_ -#define _DRI_BUFMGR_H_ -#include <xf86drm.h> - -typedef struct _dri_bufmgr dri_bufmgr; -typedef struct _dri_bo dri_bo; - -struct _dri_bo { - /** - * Size in bytes of the buffer object. - * - * The size may be larger than the size originally requested for the - * allocation, such as being aligned to page size. - */ - unsigned long size; - /** - * Card virtual address (offset from the beginning of the aperture) for the - * object. Only valid while validated. - */ - unsigned long offset; - /** - * Virtual address for accessing the buffer data. Only valid while mapped. - */ - void *virtual; - /** Buffer manager context associated with this buffer object */ - dri_bufmgr *bufmgr; -}; - -/** - * Context for a buffer manager instance. - * - * Contains public methods followed by private storage for the buffer manager. - */ -struct _dri_bufmgr { - /** - * Allocate a buffer object. - * - * Buffer objects are not necessarily initially mapped into CPU virtual - * address space or graphics device aperture. They must be mapped using - * bo_map() to be used by the CPU, and validated for use using bo_validate() - * to be used from the graphics device. - */ - dri_bo *(*bo_alloc)(dri_bufmgr *bufmgr_ctx, const char *name, - unsigned long size, unsigned int alignment); - - /** Takes a reference on a buffer object */ - void (*bo_reference)(dri_bo *bo); - - /** - * Releases a reference on a buffer object, freeing the data if - * rerefences remain. - */ - void (*bo_unreference)(dri_bo *bo); - - /** - * Maps the buffer into userspace. - * - * This function will block waiting for any existing execution on the - * buffer to complete, first. The resulting mapping is available at - * buf->virtual. - */ - int (*bo_map)(dri_bo *buf, int write_enable); - - /** Reduces the refcount on the userspace mapping of the buffer object. */ - int (*bo_unmap)(dri_bo *buf); - - /** - * Write data into an object. - * - * This is an optional function, if missing, - * dri_bo will map/memcpy/unmap. - */ - int (*bo_subdata) (dri_bo *buf, unsigned long offset, - unsigned long size, const void *data); - - /** - * Read data from an object - * - * This is an optional function, if missing, - * dri_bo will map/memcpy/unmap. - */ - int (*bo_get_subdata) (dri_bo *bo, unsigned long offset, - unsigned long size, void *data); - - /** - * Waits for rendering to an object by the GPU to have completed. - * - * This is not required for any access to the BO by bo_map, bo_subdata, etc. - * It is merely a way for the driver to implement glFinish. - */ - void (*bo_wait_rendering) (dri_bo *bo); - - /** - * Tears down the buffer manager instance. - */ - void (*destroy)(dri_bufmgr *bufmgr); - - /** - * Processes the relocations, either in userland or by converting the list - * for use in batchbuffer submission. - * - * Kernel-based implementations will return a pointer to the arguments - * to be handed with batchbuffer submission to the kernel. The userland - * implementation performs the buffer validation and emits relocations - * into them the appopriate order. - * - * \param batch_buf buffer at the root of the tree of relocations - * \return argument to be completed and passed to the execbuffers ioctl - * (if any). - */ - void *(*process_relocs)(dri_bo *batch_buf); - - void (*post_submit)(dri_bo *batch_buf); - - int (*check_aperture_space)(dri_bo **bo_array, int count); - int debug; /**< Enables verbose debugging printouts */ -}; - -dri_bo *dri_bo_alloc(dri_bufmgr *bufmgr, const char *name, unsigned long size, - unsigned int alignment); -void dri_bo_reference(dri_bo *bo); -void dri_bo_unreference(dri_bo *bo); -int dri_bo_map(dri_bo *buf, int write_enable); -int dri_bo_unmap(dri_bo *buf); - -int dri_bo_subdata(dri_bo *bo, unsigned long offset, - unsigned long size, const void *data); -int dri_bo_get_subdata(dri_bo *bo, unsigned long offset, - unsigned long size, void *data); -void dri_bo_wait_rendering(dri_bo *bo); - -void dri_bufmgr_set_debug(dri_bufmgr *bufmgr, int enable_debug); -void dri_bufmgr_destroy(dri_bufmgr *bufmgr); - -void *dri_process_relocs(dri_bo *batch_buf); -void dri_post_process_relocs(dri_bo *batch_buf); -void dri_post_submit(dri_bo *batch_buf); -int dri_bufmgr_check_aperture_space(dri_bo **bo_array, int count); - -#endif diff --git a/libdrm/intel/Makefile.am b/libdrm/intel/Makefile.am index 31a8512..607c476 100644 --- a/libdrm/intel/Makefile.am +++ b/libdrm/intel/Makefile.am @@ -25,11 +25,16 @@ AM_CFLAGS = \ $(WARN_CFLAGS) \ -I$(top_srcdir)/libdrm \ + -I$(top_srcdir)/libdrm/intel \ -I$(top_srcdir)/shared-core -noinst_LTLIBRARIES = libdrm_intel.la +libdrm_intel_la_LTLIBRARIES = libdrm_intel.la +libdrm_intel_ladir = $(libdir) +libdrm_intel_la_LDFLAGS = -version-number 1:0:0 -no-undefined libdrm_intel_la_SOURCES = \ + intel_bufmgr.c \ + intel_bufmgr_priv.h \ intel_bufmgr_fake.c \ intel_bufmgr_gem.c \ mm.c \ diff --git a/libdrm/intel/intel_bufmgr.c b/libdrm/intel/intel_bufmgr.c new file mode 100644 index 0000000..5a9cdbe --- /dev/null +++ b/libdrm/intel/intel_bufmgr.c @@ -0,0 +1,192 @@ +/* + * Copyright © 2007 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 (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. + * + * Authors: + * Eric Anholt <er...@an...> + * + */ + +#include <string.h> +#include <stdlib.h> +#include <stdint.h> +#include <assert.h> +#include <errno.h> +#include <drm.h> +#include <i915_drm.h> +#include "intel_bufmgr.h" +#include "intel_bufmgr_priv.h" + +/** @file dri_bufmgr.c + * + * Convenience functions for buffer management methods. + */ + +dri_bo * +dri_bo_alloc(dri_bufmgr *bufmgr, const char *name, unsigned long size, + unsigned int alignment) +{ + return bufmgr->bo_alloc(bufmgr, name, size, alignment); +} + +void +dri_bo_reference(dri_bo *bo) +{ + bo->bufmgr->bo_reference(bo); +} + +void +dri_bo_unreference(dri_bo *bo) +{ + if (bo == NULL) + return; + + bo->bufmgr->bo_unreference(bo); +} + +int +dri_bo_map(dri_bo *buf, int write_enable) +{ + return buf->bufmgr->bo_map(buf, write_enable); +} + +int +dri_bo_unmap(dri_bo *buf) +{ + return buf->bufmgr->bo_unmap(buf); +} + +int +dri_bo_subdata(dri_bo *bo, unsigned long offset, + unsigned long size, const void *data) +{ + int ret; + if (bo->bufmgr->bo_subdata) + return bo->bufmgr->bo_subdata(bo, offset, size, data); + if (size == 0 || data == NULL) + return 0; + + ret = dri_bo_map(bo, 1); + if (ret) + return ret; + memcpy((unsigned char *)bo->virtual + offset, data, size); + dri_bo_unmap(bo); + return 0; +} + +int +dri_bo_get_subdata(dri_bo *bo, unsigned long offset, + unsigned long size, void *data) +{ + int ret; + if (bo->bufmgr->bo_subdata) + return bo->bufmgr->bo_get_subdata(bo, offset, size, data); + + if (size == 0 || data == NULL) + return 0; + + ret = dri_bo_map(bo, 0); + if (ret) + return ret; + memcpy(data, (unsigned char *)bo->virtual + offset, size); + dri_bo_unmap(bo); + return 0; +} + +void +dri_bo_wait_rendering(dri_bo *bo) +{ + bo->bufmgr->bo_wait_rendering(bo); +} + +void +dri_bufmgr_destroy(dri_bufmgr *bufmgr) +{ + bufmgr->destroy(bufmgr); +} + +void *dri_process_relocs(dri_bo *batch_buf) +{ + return batch_buf->bufmgr->process_relocs(batch_buf); +} + +void dri_post_submit(dri_bo *batch_buf) +{ + batch_buf->bufmgr->post_submit(batch_buf); +} + +void +dri_bufmgr_set_debug(dri_bufmgr *bufmgr, int enable_debug) +{ + bufmgr->debug = enable_debug; +} + +int +dri_bufmgr_check_aperture_space(dri_bo **bo_array, int count) +{ + return bo_array[0]->bufmgr->check_aperture_space(bo_array, count); +} + +int +dri_bo_flink(dri_bo *bo, uint32_t *name) +{ + if (bo->bufmgr->bo_flink) + return bo->bufmgr->bo_flink(bo, name); + + return -ENODEV; +} + +int +dri_bo_emit_reloc(dri_bo *reloc_buf, + uint32_t read_domains, uint32_t write_domain, + uint32_t delta, uint32_t offset, dri_bo *target_buf) +{ + return reloc_buf->bufmgr->bo_emit_reloc(reloc_buf, + read_domains, write_domain, + delta, offset, target_buf); +} + +int +dri_bo_pin(dri_bo *bo, uint32_t alignment) +{ + if (bo->bufmgr->bo_pin) + return bo->bufmgr->bo_pin(bo, alignment); + + return -ENODEV; +} + +int +dri_bo_unpin(dri_bo *bo) +{ + if (bo->bufmgr->bo_unpin) + return bo->bufmgr->bo_unpin(bo); + + return -ENODEV; +} + +int dri_bo_set_tiling(dri_bo *bo, uint32_t *tiling_mode) +{ + if (bo->bufmgr->bo_set_tiling) + return bo->bufmgr->bo_set_tiling(bo, tiling_mode); + + *tiling_mode = I915_TILING_NONE; + return 0; +} diff --git a/libdrm/intel/intel_bufmgr.h b/libdrm/intel/intel_bufmgr.h index 4d33521..0b473f3 100644 --- a/libdrm/intel/intel_bufmgr.h +++ b/libdrm/intel/intel_bufmgr.h @@ -31,65 +31,65 @@ * Public definitions of Intel-specific bufmgr functions. */ -#ifndef INTEL_BUFMGR_GEM_H -#define INTEL_BUFMGR_GEM_H +#ifndef INTEL_BUFMGR_H +#define INTEL_BUFMGR_H -#include "dri_bufmgr.h" +#include <stdint.h> -/** - * Intel-specific bufmgr bits that follow immediately after the - * generic bufmgr structure. - */ -struct intel_bufmgr { - /** - * Add relocation entry in reloc_buf, which will be updated with the - * target buffer's real offset on on command submission. - * - * Relocations remain in place for the lifetime of the buffer object. - * - * \param reloc_buf Buffer to write the relocation into. - * \param read_domains GEM read domains which the buffer will be read into - * by the command that this relocation is part of. - * \param write_domains GEM read domains which the buffer will be dirtied - * in by the command that this relocation is part of. - * \param delta Constant value to be added to the relocation target's - * offset. - * \param offset Byte offset within batch_buf of the relocated pointer. - * \param target Buffer whose offset should be written into the relocation - * entry. - */ - int (*emit_reloc)(dri_bo *reloc_buf, - uint32_t read_domains, uint32_t write_domain, - uint32_t delta, uint32_t offset, dri_bo *target); - /** - * Pin a buffer to the aperture and fix the offset until unpinned - * - * \param buf Buffer to pin - * \param alignment Required alignment for aperture, in bytes - */ - int (*pin) (dri_bo *buf, uint32_t alignment); +typedef struct _dri_bufmgr dri_bufmgr; +typedef struct _dri_bo dri_bo; + +struct _dri_bo { /** - * Unpin a buffer from the aperture, allowing it to be removed + * Size in bytes of the buffer object. * - * \param buf Buffer to unpin + * The size may be larger than the size originally requested for the + * allocation, such as being aligned to page size. */ - int (*unpin) (dri_bo *buf); + unsigned long size; /** - * Ask that the buffer be placed in tiling mode - * - * \param buf Buffer to set tiling mode for - * \param tiling_mode desired, and returned tiling mode + * Card virtual address (offset from the beginning of the aperture) for the + * object. Only valid while validated. */ - int (*set_tiling) (dri_bo *bo, uint32_t *tiling_mode); + unsigned long offset; /** - * Create a visible name for a buffer which can be used by other apps - * - * \param buf Buffer to create a name for - * \param name Returned name + * Virtual address for accessing the buffer data. Only valid while mapped. */ - int (*flink) (dri_bo *buf, uint32_t *name); + void *virtual; + + /** Buffer manager context associated with this buffer object */ + dri_bufmgr *bufmgr; }; +dri_bo *dri_bo_alloc(dri_bufmgr *bufmgr, const char *name, unsigned long size, + unsigned int alignment); +void dri_bo_reference(dri_bo *bo); +void dri_bo_unreference(dri_bo *bo); +int dri_bo_map(dri_bo *buf, int write_enable); +int dri_bo_unmap(dri_bo *buf); + +int dri_bo_subdata(dri_bo *bo, unsigned long offset, + unsigned long size, const void *data); +int dri_bo_get_subdata(dri_bo *bo, unsigned long offset, + unsigned long size, void *data); +void dri_bo_wait_rendering(dri_bo *bo); + +void dri_bufmgr_set_debug(dri_bufmgr *bufmgr, int enable_debug); +void dri_bufmgr_destroy(dri_bufmgr *bufmgr); + +void *dri_process_relocs(dri_bo *batch_buf); +void dri_post_process_relocs(dri_bo *batch_buf); +void dri_post_submit(dri_bo *batch_buf); +int dri_bufmgr_check_aperture_space(dri_bo **bo_array, int count); + +int dri_bo_emit_reloc(dri_bo *reloc_buf, + uint32_t read_domains, uint32_t write_domain, + uint32_t delta, uint32_t offset, dri_bo *target_buf); +int dri_bo_pin(dri_bo *buf, uint32_t alignment); +int dri_bo_unpin(dri_bo *buf); +int dri_bo_set_tiling(dri_bo *buf, uint32_t *tiling_mode); +int dri_bo_flink(dri_bo *buf, uint32_t *name); + /* intel_bufmgr_gem.c */ dri_bufmgr *intel_bufmgr_gem_init(int fd, int batch_size); dri_bo *intel_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name, @@ -106,25 +106,13 @@ dri_bufmgr *intel_bufmgr_fake_init(unsigned long low_offset, void *low_virtual, dri_bo *intel_bo_fake_alloc_static(dri_bufmgr *bufmgr, const char *name, unsigned long offset, unsigned long size, void *virtual); - -void intel_bufmgr_fake_contended_lock_take(dri_bufmgr *bufmgr); void intel_bo_fake_disable_backing_store(dri_bo *bo, void (*invalidate_cb)(dri_bo *bo, void *ptr), void *ptr); -void intel_bufmgr_fake_evict_all(dri_bufmgr *bufmgr); - -int intel_bo_emit_reloc(dri_bo *reloc_buf, - uint32_t read_domains, uint32_t write_domain, - uint32_t delta, uint32_t offset, dri_bo *target_buf); - -int intel_bo_pin(dri_bo *buf, uint32_t alignment); - -int intel_bo_unpin(dri_bo *buf); -int intel_bo_set_tiling(dri_bo *buf, uint32_t *tiling_mode); - -int intel_bo_flink(dri_bo *buf, uint32_t *name); +void intel_bufmgr_fake_contended_lock_take(dri_bufmgr *bufmgr); +void intel_bufmgr_fake_evict_all(dri_bufmgr *bufmgr); -#endif /* INTEL_BUFMGR_GEM_H */ +#endif /* INTEL_BUFMGR_H */ diff --git a/libdrm/intel/intel_bufmgr_fake.c b/libdrm/intel/intel_bufmgr_fake.c index e2dd9dc..8e581ae 100644 --- a/libdrm/intel/intel_bufmgr_fake.c +++ b/libdrm/intel/intel_bufmgr_fake.c @@ -37,8 +37,9 @@ #include <stdlib.h> #include <string.h> #include <assert.h> -#include "dri_bufmgr.h" +#include <xf86drm.h> #include "intel_bufmgr.h" +#include "intel_bufmgr_priv.h" #include "drm.h" #include "i915_drm.h" #include "mm.h" @@ -105,7 +106,6 @@ struct block { typedef struct _bufmgr_fake { dri_bufmgr bufmgr; - struct intel_bufmgr intel_bufmgr; unsigned long low_offset; unsigned long size; @@ -1216,12 +1216,12 @@ intel_bufmgr_fake_init(unsigned long low_offset, void *low_virtual, bufmgr_fake->bufmgr.bo_map = dri_fake_bo_map; bufmgr_fake->bufmgr.bo_unmap = dri_fake_bo_unmap; bufmgr_fake->bufmgr.bo_wait_rendering = dri_fake_bo_wait_rendering; + bufmgr_fake->bufmgr.bo_emit_reloc = dri_fake_emit_reloc; bufmgr_fake->bufmgr.destroy = dri_fake_destroy; bufmgr_fake->bufmgr.process_relocs = dri_fake_process_relocs; bufmgr_fake->bufmgr.post_submit = dri_fake_post_submit; bufmgr_fake->bufmgr.check_aperture_space = dri_fake_check_aperture_space; bufmgr_fake->bufmgr.debug = 0; - bufmgr_fake->intel_bufmgr.emit_reloc = dri_fake_emit_reloc; bufmgr_fake->fence_emit = fence_emit; bufmgr_fake->fence_wait = fence_wait; diff --git a/libdrm/intel/intel_bufmgr_gem.c b/libdrm/intel/intel_bufmgr_gem.c index 8634fdf..43d2d98 100644 --- a/libdrm/intel/intel_bufmgr_gem.c +++ b/libdrm/intel/intel_bufmgr_gem.c @@ -44,8 +44,8 @@ #include <sys/mman.h> #include "errno.h" -#include "dri_bufmgr.h" #include "intel_bufmgr.h" +#include "intel_bufmgr_priv.h" #include "string.h" #include "i915_drm.h" @@ -76,8 +76,6 @@ struct dri_gem_bo_bucket { typedef struct _dri_bufmgr_gem { dri_bufmgr bufmgr; - struct intel_bufmgr intel_bufmgr; - int fd; int max_relocs; @@ -650,8 +648,8 @@ dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr) * last known offset in target_bo. */ static int -dri_gem_emit_reloc(dri_bo *bo, uint32_t read_domains, uint32_t write_domain, - uint32_t delta, uint32_t offset, dri_bo *target_bo) +dri_gem_bo_emit_reloc(dri_bo *bo, uint32_t read_domains, uint32_t write_domain, + uint32_t delta, uint32_t offset, dri_bo *target_bo) { dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; dri_bo_gem *bo_gem = (dri_bo_gem *)bo; @@ -775,7 +773,7 @@ dri_gem_post_submit(dri_bo *batch_buf) } static int -dri_gem_pin(dri_bo *bo, uint32_t alignment) +dri_gem_bo_pin(dri_bo *bo, uint32_t alignment) { dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; dri_bo_gem *bo_gem = (dri_bo_gem *)bo; @@ -794,7 +792,7 @@ dri_gem_pin(dri_bo *bo, uint32_t alignment) } static int -dri_gem_unpin(dri_bo *bo) +dri_gem_bo_unpin(dri_bo *bo) { dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; dri_bo_gem *bo_gem = (dri_bo_gem *)bo; @@ -811,7 +809,7 @@ dri_gem_unpin(dri_bo *bo) } static int -dri_gem_set_tiling(dri_bo *bo, uint32_t *tiling_mode) +dri_gem_bo_set_tiling(dri_bo *bo, uint32_t *tiling_mode) { dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; dri_bo_gem *bo_gem = (dri_bo_gem *)bo; @@ -832,7 +830,7 @@ dri_gem_set_tiling(dri_bo *bo, uint32_t *tiling_mode) } static int -dri_gem_flink(dri_bo *bo, uint32_t *name) +dri_gem_bo_flink(dri_bo *bo, uint32_t *name) { dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; dri_bo_gem *bo_gem = (dri_bo_gem *)bo; @@ -910,16 +908,16 @@ intel_bufmgr_gem_init(int fd, int batch_size) bufmgr_gem->bufmgr.bo_subdata = dri_gem_bo_subdata; bufmgr_gem->bufmgr.bo_get_subdata = dri_gem_bo_get_subdata; bufmgr_gem->bufmgr.bo_wait_rendering = dri_gem_bo_wait_rendering; + bufmgr_gem->bufmgr.bo_emit_reloc = dri_gem_bo_emit_reloc; + bufmgr_gem->bufmgr.bo_pin = dri_gem_bo_pin; + bufmgr_gem->bufmgr.bo_unpin = dri_gem_bo_unpin; + bufmgr_gem->bufmgr.bo_set_tiling = dri_gem_bo_set_tiling; + bufmgr_gem->bufmgr.bo_flink = dri_gem_bo_flink; bufmgr_gem->bufmgr.destroy = dri_bufmgr_gem_destroy; bufmgr_gem->bufmgr.process_relocs = dri_gem_process_reloc; bufmgr_gem->bufmgr.post_submit = dri_gem_post_submit; bufmgr_gem->bufmgr.debug = 0; bufmgr_gem->bufmgr.check_aperture_space = dri_gem_check_aperture_space; - bufmgr_gem->intel_bufmgr.emit_reloc = dri_gem_emit_reloc; - bufmgr_gem->intel_bufmgr.pin = dri_gem_pin; - bufmgr_gem->intel_bufmgr.unpin = dri_gem_unpin; - bufmgr_gem->intel_bufmgr.set_tiling = dri_gem_set_tiling; - bufmgr_gem->intel_bufmgr.flink = dri_gem_flink; /* Initialize the linked lists for BO reuse cache. */ for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++) bufmgr_gem->cache_bucket[i].tail = &bufmgr_gem->cache_bucket[i].head; @@ -927,67 +925,3 @@ intel_bufmgr_gem_init(int fd, int batch_size) return &bufmgr_gem->bufmgr; } -int -intel_bo_emit_reloc(dri_bo *reloc_buf, - uint32_t read_domains, uint32_t write_domain, - uint32_t delta, uint32_t offset, dri_bo *target_buf) -{ - struct intel_bufmgr *intel_bufmgr; - - intel_bufmgr = (struct intel_bufmgr *)(reloc_buf->bufmgr + 1); - - return intel_bufmgr->emit_reloc(reloc_buf, read_domains, write_domain, - delta, offset, target_buf); -} - -int -intel_bo_pin(dri_bo *bo, uint32_t alignment) -{ - struct intel_bufmgr *intel_bufmgr; - - intel_bufmgr = (struct intel_bufmgr *)(bo->bufmgr + 1); - - if (intel_bufmgr->pin) - return intel_bufmgr->pin(bo, alignment); - - return 0; -} - -int -intel_bo_unpin(dri_bo *bo) -{ - struct intel_bufmgr *intel_bufmgr; - - intel_bufmgr = (struct intel_bufmgr *)(bo->bufmgr + 1); - - if (intel_bufmgr->unpin) - return intel_bufmgr->unpin(bo); - - return 0; -} - -int intel_bo_set_tiling(dri_bo *bo, uint32_t *tiling_mode) -{ - struct intel_bufmgr *intel_bufmgr; - - intel_bufmgr = (struct intel_bufmgr *)(bo->bufmgr + 1); - - if (intel_bufmgr->set_tiling) - return intel_bufmgr->set_tiling (bo, tiling_mode); - - *tiling_mode = I915_TILING_NONE; - return 0; -} - -int intel_bo_flink(dri_bo *bo, uint32_t *name) -{ - struct intel_bufmgr *intel_bufmgr; - - intel_bufmgr = (struct intel_bufmgr *)(bo->bufmgr + 1); - - if (intel_bufmgr->flink) - return intel_bufmgr->flink (bo, name); - - return -ENODEV; -} - diff --git a/libdrm/intel/intel_bufmgr_priv.h b/libdrm/intel/intel_bufmgr_priv.h new file mode 100644 index 0000000..92476ae --- /dev/null +++ b/libdrm/intel/intel_bufmgr_priv.h @@ -0,0 +1,200 @@ +/* + * Copyright © 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 (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. + * + * Authors: + * Eric Anholt <er...@an...> + * + */ + +/** + * @file intel_bufmgr_priv.h + * + * Private definitions of Intel-specific bufmgr functions and structures. + */ + +#ifndef INTEL_BUFMGR_PRIV_H +#define INTEL_BUFMGR_PRIV_H + +/** + * Context for a buffer manager instance. + * + * Contains public methods followed by private storage for the buffer manager. + */ +struct _dri_bufmgr { + /** + * Allocate a buffer object. + * + * Buffer objects are not necessarily initially mapped into CPU virtual + * address space or graphics device aperture. They must be mapped using + * bo_map() to be used by the CPU, and validated for use using bo_validate() + * to be used from the graphics device. + */ + dri_bo *(*bo_alloc)(dri_bufmgr *bufmgr_ctx, const char *name, + unsigned long size, unsigned int alignment); + + /** Takes a reference on a buffer object */ + void (*bo_reference)(dri_bo *bo); + + /** + * Releases a reference on a buffer object, freeing the data if + * rerefences remain. + */ + void (*bo_unreference)(dri_bo *bo); + + /** + * Maps the buffer into userspace. + * + * This function will block waiting for any existing execution on the + * buffer to complete, first. The resulting mapping is available at + * buf->virtual. + */ + int (*bo_map)(dri_bo *buf, int write_enable); + + /** Reduces the refcount on the userspace mapping of the buffer object. */ + int (*bo_unmap)(dri_bo *buf); + + /** + * Write data into an object. + * + * This is an optional function, if missing, + * dri_bo will map/memcpy/unmap. + */ + int (*bo_subdata) (dri_bo *buf, unsigned long offset, + unsigned long size, const void *data); + + /** + * Read data from an object + * + * This is an optional function, if missing, + * dri_bo will map/memcpy/unmap. + */ + int (*bo_get_subdata) (dri_bo *bo, unsigned long offset, + unsigned long size, void *data); + + /** + * Waits for rendering to an object by the GPU to have completed. + * + * This is not required for any access to the BO by bo_map, bo_subdata, etc. + * It is merely a way for the driver to implement glFinish. + */ + void (*bo_wait_rendering) (dri_bo *bo); + + /** + * Tears down the buffer manager instance. + */ + void (*destroy)(dri_bufmgr *bufmgr); + + /** + * Processes the relocations, either in userland or by converting the list + * for use in batchbuffer submission. + * + * Kernel-based implementations will return a pointer to the arguments + * to be handed with batchbuffer submission to the kernel. The userland + * implementation performs the buffer validation and emits relocations + * into them the appopriate order. + * + * \param batch_buf buffer at the root of the tree of relocations + * \return argument to be completed and passed to the execbuffers ioctl + * (if any). + */ + void *(*process_relocs)(dri_bo *batch_buf); + + void (*post_submit)(dri_bo *batch_buf); + + /** + * Add relocation entry in reloc_buf, which will be updated with the + * target buffer's real offset on on command submission. + * + * Relocations remain in place for the lifetime of the buffer object. + * + * \param reloc_buf Buffer to write the relocation into. + * \param read_domains GEM read domains which the buffer will be read into + * by the command that this relocation is part of. + * \param write_domains GEM read domains which the buffer will be dirtied + * in by the command that this relocation is part of. + * \param delta Constant value to be added to the relocation target's + * offset. + * \param offset Byte offset within batch_buf of the relocated pointer. + * \param target Buffer whose offset should be written into the relocation + * entry. + */ + int (*bo_emit_reloc)(dri_bo *reloc_buf, + uint32_t read_domains, uint32_t write_domain, + uint32_t delta, uint32_t offset, dri_bo *target); + /** + * Pin a buffer to the aperture and fix the offset until unpinned + * + * \param buf Buffer to pin + * \param alignment Required alignment for aperture, in bytes + */ + int (*bo_pin) (dri_bo *buf, uint32_t alignment); + /** + * Unpin a buffer from the aperture, allowing it to be removed + * + * \param buf Buffer to unpin + */ + int (*bo_unpin) (dri_bo *buf); + /** + * Ask that the buffer be placed in tiling mode + * + * \param buf Buffer to set tiling mode for + * \param tiling_mode desired, and returned tiling mode + */ + int (*bo_set_tiling) (dri_bo *bo, uint32_t *tiling_mode); + /** + * Create a visible name for a buffer which can be used by other apps + * + * \param buf Buffer to create a name for + * \param name Returned name + */ + int (*bo_flink) (dri_bo *buf, uint32_t *name); + + int (*check_aperture_space)(dri_bo **bo_array, int count); + int debug; /**< Enables verbose debugging printouts */ +}; + +/* intel_bufmgr_gem.c */ +dri_bufmgr *intel_bufmgr_gem_init(int fd, int batch_size); +dri_bo *intel_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name, + unsigned int handle); +void intel_bufmgr_gem_enable_reuse(dri_bufmgr *bufmgr); + +/* intel_bufmgr_fake.c */ +dri_bufmgr *intel_bufmgr_fake_init(unsigned long low_offset, void *low_virtual, + unsigned long size, + unsigned int (*fence_emit)(void *private), + int (*fence_wait)(void *private, + unsigned int cookie), + void *driver_priv); +dri_bo *intel_bo_fake_alloc_static(dri_bufmgr *bufmgr, const char *name, + unsigned long offset, unsigned long size, + void *virtual); + +void intel_bufmgr_fake_contended_lock_take(dri_bufmgr *bufmgr); +void intel_bo_fake_disable_backing_store(dri_bo *bo, + void (*invalidate_cb)(dri_bo *bo, + void *ptr), + void *ptr); +void intel_bufmgr_fake_evict_all(dri_bufmgr *bufmgr); + +#endif /* INTEL_BUFMGR_PRIV_H */ + commit 09cf0f0213652609d09154ce2859c03cf97ab11e Author: Eric Anholt <er...@an...> Date: Wed Sep 3 23:05:16 2008 +0100 drm: Add tests for GEM_FLINK ioctl. diff --git a/.gitignore b/.gitignore index c8a22ea..05b2e7d 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,7 @@ tests/getstats tests/getversion tests/lock tests/gem_basic +tests/gem_flink tests/gem_mmap tests/gem_readwrite tests/openclose diff --git a/tests/Makefile.am b/tests/Makefile.am index 718cc43..95f0f22 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -24,6 +24,7 @@ TESTS = auth \ setversion \ updatedraw \ gem_basic \ + gem_flink \ gem_readwrite \ gem_mmap diff --git a/tests/gem_flink.c b/tests/gem_flink.c new file mode 100644 index 0000000..d2e062f --- /dev/null +++ b/tests/gem_flink.c @@ -0,0 +1,128 @@ +/* + * Copyright © 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 (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. + * + * Authors: + * Eric Anholt <eric@anholt.n... [truncated message content] |
From: <rn...@ke...> - 2009-03-16 05:22:03
|
bsd-core/drmP.h | 20 +++++++++++++------- bsd-core/drm_bufs.c | 4 ++-- bsd-core/drm_drv.c | 2 +- bsd-core/drm_lock.c | 2 +- shared-core/radeon_cp.c | 7 +------ 5 files changed, 18 insertions(+), 17 deletions(-) New commits: commit 6777c6bb8bb399e48500d742e80822808451010b Author: Robert Noland <rn...@2h...> Date: Mon Mar 16 00:17:54 2009 -0500 FreeBSD: Don't set the PZERO flag to mtx_sleep. We also don't support anything old enough to need tsleep. diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c index 2be461d..883e3a0 100644 --- a/bsd-core/drm_drv.c +++ b/bsd-core/drm_drv.c @@ -663,7 +663,7 @@ void drm_close(void *data) } /* Contention */ retcode = mtx_sleep((void *)&dev->lock.lock_queue, - &dev->dev_lock, PZERO | PCATCH, "drmlk2", 0); + &dev->dev_lock, PCATCH, "drmlk2", 0); if (retcode) break; } diff --git a/bsd-core/drm_lock.c b/bsd-core/drm_lock.c index 94b3f8b..24c127a 100644 --- a/bsd-core/drm_lock.c +++ b/bsd-core/drm_lock.c @@ -79,7 +79,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) /* Contention */ ret = mtx_sleep((void *)&dev->lock.lock_queue, &dev->dev_lock, - PZERO | PCATCH, "drmlk2", 0); + PCATCH, "drmlk2", 0); if (ret != 0) break; } diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 872f589..6771d4f 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -1406,12 +1406,7 @@ void radeon_do_release(struct drm_device * dev) #ifdef __linux__ schedule(); #else -#if defined(__FreeBSD__) && __FreeBSD_version > 500000 - mtx_sleep(&ret, &dev->dev_lock, PZERO, "rdnrel", - 1); -#else - tsleep(&ret, PZERO, "rdnrel", 1); -#endif + mtx_sleep(&ret, &dev->dev_lock, 0, "rdnrel", 1); #endif } radeon_do_cp_stop(dev_priv); commit 06e182d0259d1d2e775814fa070c6cce0ee233a8 Author: Robert Noland <rn...@2h...> Date: Mon Mar 16 00:08:06 2009 -0500 FreeBSD: use flsl() instead of ffsl(). I noticed that we were computing drm_order differently than linux. diff --git a/bsd-core/drm_bufs.c b/bsd-core/drm_bufs.c index 88445a4..53cff64 100644 --- a/bsd-core/drm_bufs.c +++ b/bsd-core/drm_bufs.c @@ -1102,7 +1102,7 @@ int drm_order(unsigned long size) if (size == 0) return 0; - order = ffsl(size) - 1; + order = flsl(size) - 1; if (size & ~(1ul << order)) ++order; commit 2ce00c6b674a51bdfaa3276b88d2015c59d4584e Author: Robert Noland <rn...@2h...> Date: Mon Mar 16 00:07:31 2009 -0500 FreeBSD: Minor code cleanup. diff --git a/bsd-core/drm_bufs.c b/bsd-core/drm_bufs.c index 1f83ba3..88445a4 100644 --- a/bsd-core/drm_bufs.c +++ b/bsd-core/drm_bufs.c @@ -213,7 +213,7 @@ int drm_addmap(struct drm_device * dev, unsigned long offset, DRM_LOCK(); return EINVAL; } - map->offset = map->offset + dev->sg->handle; + map->offset += dev->sg->handle; break; case _DRM_CONSISTENT: /* Unfortunately, we don't get any alignment specification from commit b0acc886069c0054da98059319a84eaf60114d32 Author: Robert Noland <rn...@2h...> Date: Mon Mar 16 00:03:40 2009 -0500 FreeBSD: Increase MAX_PCI_RESOURCE We can have more than 3 BARs to access. diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h index 32573b8..affc0a8 100644 --- a/bsd-core/drmP.h +++ b/bsd-core/drmP.h @@ -610,7 +610,7 @@ struct drm_driver_info { }; /* Length for the array of resource pointers for drm_get_resource_*. */ -#define DRM_MAX_PCI_RESOURCE 3 +#define DRM_MAX_PCI_RESOURCE 6 /** * DRM device functions structure commit f78040266bbddf6cf020fb957e3f92000c2bc69b Author: Robert Noland <rn...@2h...> Date: Mon Mar 16 00:01:47 2009 -0500 FreeBSD: Cast map handles to vm_offset_t This prevents some warnings with nouveau. diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h index b1ae993..32573b8 100644 --- a/bsd-core/drmP.h +++ b/bsd-core/drmP.h @@ -237,17 +237,23 @@ typedef u_int8_t u8; #endif #define DRM_READ8(map, offset) \ - *(volatile u_int8_t *) (((unsigned long)(map)->handle) + (offset)) + *(volatile u_int8_t *)(((vm_offset_t)(map)->handle) + \ + (vm_offset_t)(offset)) #define DRM_READ16(map, offset) \ - *(volatile u_int16_t *) (((unsigned long)(map)->handle) + (offset)) + *(volatile u_int16_t *)(((vm_offset_t)(map)->handle) + \ + (vm_offset_t)(offset)) #define DRM_READ32(map, offset) \ - *(volatile u_int32_t *)(((unsigned long)(map)->handle) + (offset)) + *(volatile u_int32_t *)(((vm_offset_t)(map)->handle) + \ + (vm_offset_t)(offset)) #define DRM_WRITE8(map, offset, val) \ - *(volatile u_int8_t *) (((unsigned long)(map)->handle) + (offset)) = val + *(volatile u_int8_t *)(((vm_offset_t)(map)->handle) + \ + (vm_offset_t)(offset)) = val #define DRM_WRITE16(map, offset, val) \ - *(volatile u_int16_t *) (((unsigned long)(map)->handle) + (offset)) = val + *(volatile u_int16_t *)(((vm_offset_t)(map)->handle) + \ + (vm_offset_t)(offset)) = val #define DRM_WRITE32(map, offset, val) \ - *(volatile u_int32_t *)(((unsigned long)(map)->handle) + (offset)) = val + *(volatile u_int32_t *)(((vm_offset_t)(map)->handle) + \ + (vm_offset_t)(offset)) = val #define DRM_VERIFYAREA_READ( uaddr, size ) \ (!useracc(__DECONST(caddr_t, uaddr), size, VM_PROT_READ)) |
From: <ic...@ke...> - 2010-06-21 21:40:17
|
intel/intel_bufmgr_gem.c | 105 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 72 insertions(+), 33 deletions(-) New commits: commit 13e8270504cffa96bd067dc5c792a79555e8b2d4 Author: Chris Wilson <ch...@ch...> Date: Mon Jun 21 15:38:06 2010 +0100 intel: Print out debugging message following ENOSPC execbuffer() returns ENOSPC if it cannot fit the batch buffer into the aperture which is the error we want to diagnose here. Signed-off-by: Chris Wilson <ch...@ch...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index b0d1651..37b7467 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -1608,7 +1608,7 @@ drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used, if (ret != 0) { ret = -errno; - if (ret == -ENOMEM) { + if (ret == -ENOSPC) { fprintf(stderr, "Execbuffer fails to pin. " "Estimate: %u. Actual: %u. Available: %u\n", commit f16b4164d686893949daa3217a011d21c5bd7f95 Author: Chris Wilson <ch...@ch...> Date: Mon Jun 21 15:21:48 2010 +0100 intel: Scan the cache for old bo once every second. Rearrange the cache cleanup so that we always scan following a final unreference, and guard against multiple scans in a single second. Signed-off-by: Chris Wilson <ch...@ch...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index 19eea34..b0d1651 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -93,6 +93,7 @@ typedef struct _drm_intel_bufmgr_gem { /** Array of lists of cached gem objects of power-of-two sizes */ struct drm_intel_gem_bo_bucket cache_bucket[14 * 4]; int num_buckets; + time_t time; uint64_t gtt_size; int available_fences; @@ -848,6 +849,9 @@ drm_intel_gem_cleanup_bo_cache(drm_intel_bufmgr_gem *bufmgr_gem, time_t time) { int i; + if (bufmgr_gem->time == time) + return; + for (i = 0; i < bufmgr_gem->num_buckets; i++) { struct drm_intel_gem_bo_bucket *bucket = &bufmgr_gem->cache_bucket[i]; @@ -865,6 +869,8 @@ drm_intel_gem_cleanup_bo_cache(drm_intel_bufmgr_gem *bufmgr_gem, time_t time) drm_intel_gem_bo_free(&bo_gem->bo); } } + + bufmgr_gem->time = time; } static void @@ -910,8 +916,6 @@ drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time) bo_gem->validate_index = -1; DRMLISTADDTAIL(&bo_gem->head, &bucket->head); - - drm_intel_gem_cleanup_bo_cache(bufmgr_gem, time); } else { drm_intel_gem_bo_free(bo); } @@ -941,6 +945,7 @@ static void drm_intel_gem_bo_unreference(drm_intel_bo *bo) pthread_mutex_lock(&bufmgr_gem->lock); drm_intel_gem_bo_unreference_final(bo, time.tv_sec); + drm_intel_gem_cleanup_bo_cache(bufmgr_gem, time.tv_sec); pthread_mutex_unlock(&bufmgr_gem->lock); } } commit 5eec286838118501dd79178c152000ad4cbd70e1 Author: Chris Wilson <ch...@ch...> Date: Mon Jun 21 14:20:56 2010 +0100 intel: Force stride to be 0 for I915_TILING_NONE. When allocating a tiled buffer, if we remove the desired tiling mode due to it being beyond hardware limits, also remove the stride. This ensures that we only ever use stride 0 with I915_TILING_NONE. Signed-off-by: Chris Wilson <ch...@ch...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index b4be1af..19eea34 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -743,6 +743,9 @@ drm_intel_gem_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name, size = drm_intel_gem_bo_tile_size(bufmgr_gem, size, tiling_mode); } while (*tiling_mode != tiling); + if (*tiling_mode == I915_TILING_NONE) + stride = 0; + bo = drm_intel_gem_bo_alloc_internal(bufmgr, name, size, flags, *tiling_mode, stride); if (!bo) commit 1db22ff741f92b84450ec13093e070a6ad5fc857 Author: Chris Wilson <ch...@ch...> Date: Mon Jun 21 14:27:23 2010 +0100 intel: Defer tiling change to allocation. As we now expose a method to allocate tiled buffers, it makes more sense to defer the SET_TILING until required. Besides the slim chance that it will be a no-op, by delaying the change we are less likely to stall on waiting for a bound buffer to release a fence register. Signed-off-by: Chris Wilson <ch...@ch...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index 2cbd596..b4be1af 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -201,8 +201,9 @@ drm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, uint32_t * swizzle_mode); static int -drm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, - uint32_t stride); +drm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo, + uint32_t tiling_mode, + uint32_t stride); static void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo, time_t time); @@ -550,7 +551,9 @@ static drm_intel_bo * drm_intel_gem_bo_alloc_internal(drm_intel_bufmgr *bufmgr, const char *name, unsigned long size, - unsigned long flags) + unsigned long flags, + uint32_t tiling_mode, + unsigned long stride) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; drm_intel_bo_gem *bo_gem; @@ -616,6 +619,13 @@ retry: bucket); goto retry; } + + if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo, + tiling_mode, + stride)) { + drm_intel_gem_bo_free(&bo_gem->bo); + goto retry; + } } } pthread_mutex_unlock(&bufmgr_gem->lock); @@ -643,6 +653,17 @@ retry: return NULL; } bo_gem->bo.bufmgr = bufmgr; + + bo_gem->tiling_mode = I915_TILING_NONE; + bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; + bo_gem->stride = 0; + + if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo, + tiling_mode, + stride)) { + drm_intel_gem_bo_free(&bo_gem->bo); + return NULL; + } } bo_gem->name = name; @@ -651,9 +672,6 @@ retry: 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->stride = 0; bo_gem->reusable = 1; drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem); @@ -671,7 +689,8 @@ drm_intel_gem_bo_alloc_for_render(drm_intel_bufmgr *bufmgr, unsigned int alignment) { return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, - BO_ALLOC_FOR_RENDER); + BO_ALLOC_FOR_RENDER, + I915_TILING_NONE, 0); } static drm_intel_bo * @@ -680,7 +699,8 @@ drm_intel_gem_bo_alloc(drm_intel_bufmgr *bufmgr, unsigned long size, unsigned int alignment) { - return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, 0); + return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, 0, + I915_TILING_NONE, 0); } static drm_intel_bo * @@ -692,7 +712,6 @@ drm_intel_gem_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name, drm_intel_bo *bo; unsigned long size, stride; uint32_t tiling; - int ret; do { unsigned long aligned_y; @@ -724,18 +743,12 @@ drm_intel_gem_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name, size = drm_intel_gem_bo_tile_size(bufmgr_gem, size, tiling_mode); } while (*tiling_mode != tiling); - bo = drm_intel_gem_bo_alloc_internal(bufmgr, name, size, flags); + bo = drm_intel_gem_bo_alloc_internal(bufmgr, name, size, flags, + *tiling_mode, stride); if (!bo) return NULL; - ret = drm_intel_gem_bo_set_tiling(bo, tiling_mode, stride); - if (ret != 0) { - drm_intel_gem_bo_unreference(bo); - return NULL; - } - *pitch = stride; - return bo; } @@ -857,7 +870,6 @@ drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time) 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_intel_gem_bo_bucket *bucket; - uint32_t tiling_mode; int i; /* Unreference all the target buffers */ @@ -886,9 +898,7 @@ drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time) 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; if (bufmgr_gem->bo_reuse && bo_gem->reusable && bucket != NULL && - drm_intel_gem_bo_set_tiling(bo, &tiling_mode, 0) == 0 && drm_intel_gem_bo_madvise_internal(bufmgr_gem, bo_gem, I915_MADV_DONTNEED)) { bo_gem->free_time = time; @@ -1674,39 +1684,52 @@ drm_intel_gem_bo_unpin(drm_intel_bo *bo) } static int -drm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, - uint32_t stride) +drm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo, + uint32_t tiling_mode, + uint32_t stride) { 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_set_tiling set_tiling; int ret; - if (bo_gem->global_name == 0) - return 0; - - if (*tiling_mode == bo_gem->tiling_mode && + if (tiling_mode == bo_gem->tiling_mode && stride == bo_gem->stride) return 0; memset(&set_tiling, 0, sizeof(set_tiling)); - set_tiling.handle = bo_gem->gem_handle; - do { - set_tiling.tiling_mode = *tiling_mode; + set_tiling.handle = bo_gem->gem_handle; + set_tiling.tiling_mode = tiling_mode; set_tiling.stride = stride; ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling); } while (ret == -1 && errno == EINTR); - if (ret == 0) { - bo_gem->tiling_mode = set_tiling.tiling_mode; - bo_gem->swizzle_mode = set_tiling.swizzle_mode; - bo_gem->stride = stride; + if (ret == -1) + return -errno; + + bo_gem->tiling_mode = set_tiling.tiling_mode; + bo_gem->swizzle_mode = set_tiling.swizzle_mode; + bo_gem->stride = stride; + return 0; +} + +static int +drm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, + uint32_t stride) +{ + drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; + drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; + int ret; + + if (bo_gem->global_name == 0) + return 0; + + ret = drm_intel_gem_bo_set_tiling_internal(bo, *tiling_mode, stride); + if (ret == 0) drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem); - } else - ret = -errno; *tiling_mode = bo_gem->tiling_mode; return ret; commit 056aa9be04e923a45ca00924caa587d6dbf8821d Author: Chris Wilson <ch...@ch...> Date: Mon Jun 21 14:31:29 2010 +0100 intel: Track tiling stride We need to inform the kernel if the tiling stride changes and not only for changes of the tiling mode. Signed-off-by: Chris Wilson <ch...@ch...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index a8e072d..2cbd596 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -132,6 +132,7 @@ struct _drm_intel_bo_gem { */ uint32_t tiling_mode; uint32_t swizzle_mode; + unsigned long stride; time_t free_time; @@ -652,6 +653,7 @@ retry: bo_gem->has_error = 0; bo_gem->tiling_mode = I915_TILING_NONE; bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; + bo_gem->stride = 0; bo_gem->reusable = 1; drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem); @@ -791,6 +793,7 @@ drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr, } bo_gem->tiling_mode = get_tiling.tiling_mode; bo_gem->swizzle_mode = get_tiling.swizzle_mode; + /* XXX stride is unknown */ drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem); DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name); @@ -1679,7 +1682,11 @@ drm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, struct drm_i915_gem_set_tiling set_tiling; int ret; - if (bo_gem->global_name == 0 && *tiling_mode == bo_gem->tiling_mode) + if (bo_gem->global_name == 0) + return 0; + + if (*tiling_mode == bo_gem->tiling_mode && + stride == bo_gem->stride) return 0; memset(&set_tiling, 0, sizeof(set_tiling)); @@ -1696,6 +1703,7 @@ drm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, if (ret == 0) { bo_gem->tiling_mode = set_tiling.tiling_mode; bo_gem->swizzle_mode = set_tiling.swizzle_mode; + bo_gem->stride = stride; drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem); } else ret = -errno; |
From: <kr...@ke...> - 2011-02-17 16:55:08
|
configure.ac | 3 libkms/Makefile.am | 4 libkms/internal.h | 2 libkms/linux.c | 4 libkms/radeon.c | 242 ++++++++++++++++++++++++++++++++++++++++++++ tests/modeprint/Makefile.am | 4 tests/modeprint/modeprint.c | 4 tests/modetest/Makefile.am | 4 tests/modetest/modetest.c | 135 ++++++++++++++---------- 9 files changed, 341 insertions(+), 61 deletions(-) New commits: commit 51c6ae4c3a0e5527d3c6e1632b21546baaba0b29 Author: Benjamin Franzke <ben...@go...> Date: Thu Feb 17 14:09:12 2011 +0100 tests/modeprint: Output masks as hex numbers diff --git a/tests/modeprint/modeprint.c b/tests/modeprint/modeprint.c index 4c612f4..09b8df0 100644 --- a/tests/modeprint/modeprint.c +++ b/tests/modeprint/modeprint.c @@ -193,8 +193,8 @@ int printEncoder(int fd, drmModeResPtr res, drmModeEncoderPtr encoder, uint32_t printf("\tid :%i\n", id); printf("\tcrtc_id :%d\n", encoder->crtc_id); printf("\ttype :%d\n", encoder->encoder_type); - printf("\tpossible_crtcs :%d\n", encoder->possible_crtcs); - printf("\tpossible_clones :%d\n", encoder->possible_clones); + printf("\tpossible_crtcs :0x%x\n", encoder->possible_crtcs); + printf("\tpossible_clones :0x%x\n", encoder->possible_clones); return 0; } commit 17762467850618323f59e91702e3fc0749fbceac Author: Benjamin Franzke <ben...@go...> Date: Thu Feb 17 14:07:58 2011 +0100 tests/modeprint: Remove needless dependency on drm_intel diff --git a/tests/modeprint/Makefile.am b/tests/modeprint/Makefile.am index 2ae0fdc..c4862ac 100644 --- a/tests/modeprint/Makefile.am +++ b/tests/modeprint/Makefile.am @@ -1,6 +1,5 @@ AM_CFLAGS = \ -I$(top_srcdir)/include/drm \ - -I$(top_srcdir)/intel/ \ -I$(top_srcdir) noinst_PROGRAMS = \ @@ -9,5 +8,4 @@ noinst_PROGRAMS = \ modeprint_SOURCES = \ modeprint.c modeprint_LDADD = \ - $(top_builddir)/libdrm.la \ - $(top_builddir)/intel/libdrm_intel.la + $(top_builddir)/libdrm.la commit 8fef29093fae2a08f8c1cb4946687bf4bb62a1ca Author: Benjamin Franzke <ben...@go...> Date: Thu Feb 17 10:47:47 2011 +0100 modetest: Create buffers using libkms diff --git a/tests/modetest/Makefile.am b/tests/modetest/Makefile.am index 16f5e99..2191242 100644 --- a/tests/modetest/Makefile.am +++ b/tests/modetest/Makefile.am @@ -1,6 +1,6 @@ AM_CFLAGS = \ -I$(top_srcdir)/include/drm \ - -I$(top_srcdir)/intel/ \ + -I$(top_srcdir)/libkms/ \ -I$(top_srcdir) \ $(CAIRO_CFLAGS) @@ -11,5 +11,5 @@ modetest_SOURCES = \ modetest.c modetest_LDADD = \ $(top_builddir)/libdrm.la \ - $(top_builddir)/intel/libdrm_intel.la \ + $(top_builddir)/libkms/libkms.la \ $(CAIRO_LIBS) diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index f3a04d0..6a40820 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -51,8 +51,7 @@ #include "xf86drm.h" #include "xf86drmMode.h" -#include "intel_bufmgr.h" -#include "i915_drm.h" +#include "libkms.h" #ifdef HAVE_CAIRO #include <math.h> @@ -354,29 +353,49 @@ connector_find_mode(struct connector *c) c->crtc = c->encoder->crtc_id; } -static drm_intel_bo * -allocate_buffer(drm_intel_bufmgr *bufmgr, +static struct kms_bo * +allocate_buffer(struct kms_driver *kms, int width, int height, int *stride) { - int size; + struct kms_bo *bo; + unsigned bo_attribs[] = { + KMS_WIDTH, 0, + KMS_HEIGHT, 0, + KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8, + KMS_TERMINATE_PROP_LIST + }; + int ret; + + bo_attribs[1] = width; + bo_attribs[3] = height; + + ret = kms_bo_create(kms, bo_attribs, &bo); + if (ret) { + fprintf(stderr, "failed to alloc buffer: %s\n", + strerror(-ret)); + return NULL; + } - /* Scan-out has a 64 byte alignment restriction */ - size = (width + 63) & -64; - *stride = size; - size *= height; + ret = kms_bo_get_prop(bo, KMS_PITCH, stride); + if (ret) { + fprintf(stderr, "failed to retreive buffer stride: %s\n", + strerror(-ret)); + kms_bo_destroy(&bo); + return NULL; + } - return drm_intel_bo_alloc(bufmgr, "frontbuffer", size, 0); + return bo; } static void -make_pwetty(drm_intel_bo *bo, int width, int height, int stride) +make_pwetty(void *data, int width, int height, int stride) { #ifdef HAVE_CAIRO cairo_surface_t *surface; cairo_t *cr; int x, y; - surface = cairo_image_surface_create_for_data(bo->virtual, + surface = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, stride); @@ -415,29 +434,29 @@ make_pwetty(drm_intel_bo *bo, int width, int height, int stride) } static int -create_test_buffer(drm_intel_bufmgr *bufmgr, - int width, int height, int *stride_out, drm_intel_bo **bo_out) +create_test_buffer(struct kms_driver *kms, + int width, int height, int *stride_out, + struct kms_bo **bo_out) { - drm_intel_bo *bo; + struct kms_bo *bo; int ret, i, j, stride; + void *virtual; - bo = allocate_buffer(bufmgr, width, height, &stride); - if (!bo) { - fprintf(stderr, "failed to alloc buffer: %s\n", - strerror(errno)); + bo = allocate_buffer(kms, width, height, &stride); + if (!bo) return -1; - } - ret = drm_intel_gem_bo_map_gtt(bo); + ret = kms_bo_map(bo, &virtual); if (ret) { - fprintf(stderr, "failed to GTT map buffer: %s\n", - strerror(errno)); + fprintf(stderr, "failed to map buffer: %s\n", + strerror(-ret)); + kms_bo_destroy(&bo); return -1; } /* paint the buffer with colored tiles */ for (j = 0; j < height; j++) { - uint32_t *fb_ptr = (uint32_t*)((char*)bo->virtual + j * stride); + uint32_t *fb_ptr = (uint32_t*)((char*)virtual + j * stride); for (i = 0; i < width; i++) { div_t d = div(i, width); fb_ptr[i] = @@ -446,9 +465,9 @@ create_test_buffer(drm_intel_bufmgr *bufmgr, } } - make_pwetty(bo, width, height, stride); + make_pwetty(virtual, width, height, stride); - drm_intel_gem_bo_unmap_gtt(bo); + kms_bo_unmap(bo); *bo_out = bo; *stride_out = stride; @@ -456,32 +475,29 @@ create_test_buffer(drm_intel_bufmgr *bufmgr, } static int -create_grey_buffer(drm_intel_bufmgr *bufmgr, - int width, int height, int *stride_out, drm_intel_bo **bo_out) +create_grey_buffer(struct kms_driver *kms, + int width, int height, int *stride_out, + struct kms_bo **bo_out) { - drm_intel_bo *bo; + struct kms_bo *bo; int size, ret, stride; + void *virtual; - /* Mode size at 32 bpp */ - stride = width * 4; - size = stride * height; - - bo = drm_intel_bo_alloc(bufmgr, "frontbuffer", size, 4096); - if (!bo) { - fprintf(stderr, "failed to alloc buffer: %s\n", - strerror(errno)); + bo = allocate_buffer(kms, width, height, &stride); + if (!bo) return -1; - } - ret = drm_intel_gem_bo_map_gtt(bo); + ret = kms_bo_map(bo, &virtual); if (ret) { - fprintf(stderr, "failed to GTT map buffer: %s\n", - strerror(errno)); + fprintf(stderr, "failed to map buffer: %s\n", + strerror(-ret)); + kms_bo_destroy(&bo); return -1; } - memset(bo->virtual, 0x77, size); - drm_intel_gem_bo_unmap_gtt(bo); + size = stride * height; + memset(virtual, 0x77, size); + kms_bo_unmap(bo); *bo_out = bo; *stride_out = stride; @@ -521,10 +537,11 @@ page_flip_handler(int fd, unsigned int frame, static void set_mode(struct connector *c, int count, int page_flip) { - drm_intel_bufmgr *bufmgr; - drm_intel_bo *bo, *other_bo; + struct kms_driver *kms; + struct kms_bo *bo, *other_bo; unsigned int fb_id, other_fb_id; int i, ret, width, height, x, stride; + unsigned handle; drmEventContext evctx; width = 0; @@ -538,17 +555,18 @@ set_mode(struct connector *c, int count, int page_flip) height = c[i].mode->vdisplay; } - bufmgr = drm_intel_bufmgr_gem_init(fd, 2<<20); - if (!bufmgr) { - fprintf(stderr, "failed to init bufmgr: %s\n", strerror(errno)); + ret = kms_create(fd, &kms); + if (ret) { + fprintf(stderr, "failed to create kms driver: %s\n", + strerror(-ret)); return; } - if (create_test_buffer(bufmgr, width, height, &stride, &bo)) + if (create_test_buffer(kms, width, height, &stride, &bo)) return; - ret = drmModeAddFB(fd, width, height, 32, 32, stride, bo->handle, - &fb_id); + kms_bo_get_prop(bo, KMS_HANDLE, &handle); + ret = drmModeAddFB(fd, width, height, 32, 32, stride, handle, &fb_id); if (ret) { fprintf(stderr, "failed to add fb: %s\n", strerror(errno)); return; @@ -574,11 +592,12 @@ set_mode(struct connector *c, int count, int page_flip) if (!page_flip) return; - - if (create_grey_buffer(bufmgr, width, height, &stride, &other_bo)) + + if (create_grey_buffer(kms, width, height, &stride, &other_bo)) return; - ret = drmModeAddFB(fd, width, height, 32, 32, stride, other_bo->handle, + kms_bo_get_prop(other_bo, KMS_HANDLE, &handle); + ret = drmModeAddFB(fd, width, height, 32, 32, stride, handle, &other_fb_id); if (ret) { fprintf(stderr, "failed to add fb: %s\n", strerror(errno)); @@ -640,6 +659,10 @@ set_mode(struct connector *c, int count, int page_flip) drmHandleEvent(fd, &evctx); } + + kms_bo_destroy(&bo); + kms_bo_destroy(&other_bo); + kms_destroy(&kms); } extern char *optarg; @@ -665,6 +688,9 @@ void usage(char *name) static int page_flipping_supported(int fd) { + /*FIXME: generic ioctl needed? */ + return 1; +#if 0 int ret, value; struct drm_i915_getparam gp; @@ -678,6 +704,7 @@ static int page_flipping_supported(int fd) } return *gp.value; +#endif } int main(int argc, char **argv) commit c75fe3ae738732afda3a7d4222bb3828ed9ef7a8 Author: Benjamin Franzke <ben...@go...> Date: Thu Feb 17 10:46:35 2011 +0100 configure.ac: ac_define HAVE_RADEON diff --git a/configure.ac b/configure.ac index b064665..23ccedf 100644 --- a/configure.ac +++ b/configure.ac @@ -244,6 +244,9 @@ fi AM_CONDITIONAL(HAVE_INTEL, [test "x$INTEL" != "xno"]) AM_CONDITIONAL(HAVE_RADEON, [test "x$RADEON" != "xno"]) +if test "x$RADEON" = xyes; then + AC_DEFINE(HAVE_RADEON, 1, [Have radeon support]) +fi AC_ARG_WITH([kernel-source], [AS_HELP_STRING([--with-kernel-source], commit ed7d177f66885dfbc4e8410154559c4767fefa9f Author: nobled <no...@dr...> Date: Thu Sep 9 10:07:21 2010 +0100 libkms/radeon: Add backend Todo: What tiling should be set on scanout buffers? Haven't tested besides compiling it. diff --git a/libkms/Makefile.am b/libkms/Makefile.am index 2c75878..5c2e63f 100644 --- a/libkms/Makefile.am +++ b/libkms/Makefile.am @@ -26,6 +26,10 @@ if HAVE_NOUVEAU libkms_la_SOURCES += nouveau.c endif +if HAVE_RADEON +libkms_la_SOURCES += radeon.c +endif + libkmsincludedir = ${includedir}/libkms libkmsinclude_HEADERS = libkms.h diff --git a/libkms/internal.h b/libkms/internal.h index 63122d1..51f5e65 100644 --- a/libkms/internal.h +++ b/libkms/internal.h @@ -70,4 +70,6 @@ int intel_create(int fd, struct kms_driver **out); int nouveau_create(int fd, struct kms_driver **out); +int radeon_create(int fd, struct kms_driver **out); + #endif diff --git a/libkms/linux.c b/libkms/linux.c index 02182d3..7449abc 100644 --- a/libkms/linux.c +++ b/libkms/linux.c @@ -111,6 +111,10 @@ linux_from_sysfs(int fd, struct kms_driver **out) else if (!strcmp(name, "nouveau")) ret = nouveau_create(fd, out); #endif +#ifdef HAVE_RADEON + else if (!strcmp(name, "radeon")) + ret = radeon_create(fd, out); +#endif else ret = -ENOSYS; diff --git a/libkms/radeon.c b/libkms/radeon.c new file mode 100644 index 0000000..f5e382a --- /dev/null +++ b/libkms/radeon.c @@ -0,0 +1,242 @@ +/************************************************************************** + * + * 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 "radeon_drm.h" + + +#define ALIGNMENT 512 + +struct radeon_bo +{ + struct kms_bo base; + unsigned map_count; +}; + +static int +radeon_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 +radeon_destroy(struct kms_driver *kms) +{ + free(kms); + return 0; +} + +static int +radeon_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_radeon_gem_create arg; + unsigned size, pitch; + struct radeon_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; + } + } + + switch (type) { + case KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8: + pitch = 4 * 64; + size = 4 * 64 * 64; + break; + case KMS_BO_TYPE_SCANOUT_X8R8G8B8: + pitch = width * 4; + pitch = (pitch + ALIGNMENT - 1) & ~(ALIGNMENT - 1); + size = pitch * height; + break; + default: + return -EINVAL; + } + + bo = calloc(1, sizeof(*bo)); + if (!bo) + return -ENOMEM; + + memset(&arg, 0, sizeof(arg)); + arg.size = size; + arg.alignment = ALIGNMENT; + arg.initial_domain = RADEON_GEM_DOMAIN_CPU; + arg.flags = 0; + arg.handle = 0; + + ret = drmCommandWriteRead(kms->fd, DRM_RADEON_GEM_CREATE, + &arg, sizeof(arg)); + if (ret) + goto err_free; + + bo->base.kms = kms; + bo->base.handle = arg.handle; + bo->base.size = size; + bo->base.pitch = pitch; + bo->base.offset = 0; + bo->map_count = 0; + + *out = &bo->base; + + return 0; + +err_free: + free(bo); + return ret; +} + +static int +radeon_bo_get_prop(struct kms_bo *bo, unsigned key, unsigned *out) +{ + switch (key) { + default: + return -EINVAL; + } +} + +static int +radeon_bo_map(struct kms_bo *_bo, void **out) +{ + struct radeon_bo *bo = (struct radeon_bo *)_bo; + struct drm_radeon_gem_mmap arg; + void *map = NULL; + int ret; + + if (bo->base.ptr) { + bo->map_count++; + *out = bo->base.ptr; + return 0; + } + + memset(&arg, 0, sizeof(arg)); + arg.handle = bo->base.handle; + arg.offset = bo->base.offset; + arg.size = (uint64_t)bo->base.size; + + ret = drmCommandWriteRead(bo->base.kms->fd, DRM_RADEON_GEM_MMAP, + &arg, sizeof(arg)); + if (ret) + return -errno; + + map = mmap(0, arg.size, PROT_READ | PROT_WRITE, MAP_SHARED, + bo->base.kms->fd, arg.addr_ptr); + if (map == MAP_FAILED) + return -errno; + + bo->base.ptr = map; + bo->map_count++; + *out = bo->base.ptr; + + return 0; +} + +static int +radeon_bo_unmap(struct kms_bo *_bo) +{ + struct radeon_bo *bo = (struct radeon_bo *)_bo; + if (--bo->map_count == 0) { + munmap(bo->base.ptr, bo->base.size); + bo->base.ptr = NULL; + } + return 0; +} + +static int +radeon_bo_destroy(struct kms_bo *_bo) +{ + struct radeon_bo *bo = (struct radeon_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 +radeon_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 = radeon_bo_create; + kms->bo_map = radeon_bo_map; + kms->bo_unmap = radeon_bo_unmap; + kms->bo_get_prop = radeon_bo_get_prop; + kms->bo_destroy = radeon_bo_destroy; + kms->get_prop = radeon_get_prop; + kms->destroy = radeon_destroy; + *out = kms; + + return 0; +} |
From: <wal...@ke...> - 2011-10-19 11:37:06
|
tests/modetest/modetest.c | 17 +++++++++++++---- tests/vbltest/vbltest.c | 22 +++++++++++++++++----- 2 files changed, 30 insertions(+), 9 deletions(-) New commits: commit d23146f3f0ad14c8ad482a4832cae859c8d646f2 Author: Jakob Bornecrantz <ja...@vm...> Date: Wed Oct 19 13:32:43 2011 +0200 modetest: Call dirty fb on modeset Signed-off-by: Jakob Bornecrantz <ja...@vm...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index f65a033..229ab8a 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -583,6 +583,10 @@ set_mode(struct connector *c, int count, int page_flip) ret = drmModeSetCrtc(fd, c[i].crtc, fb_id, x, 0, &c[i].id, 1, c[i].mode); + + /* XXX: Actually check if this is needed */ + drmModeDirtyFB(fd, fb_id, NULL, 0); + x += c[i].mode->hdisplay; if (ret) { commit 680b9c4fa3dfb329bd74ec08c17cfc876ea2fc5b Author: Jakob Bornecrantz <ja...@vm...> Date: Wed Oct 19 13:32:26 2011 +0200 modetest: Print extra info if we fail to create a framebuffer Signed-off-by: Jakob Bornecrantz <ja...@vm...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 35045c8..f65a033 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -568,7 +568,8 @@ set_mode(struct connector *c, int count, int page_flip) kms_bo_get_prop(bo, KMS_HANDLE, &handle); ret = drmModeAddFB(fd, width, height, 24, 32, stride, handle, &fb_id); if (ret) { - fprintf(stderr, "failed to add fb: %s\n", strerror(errno)); + fprintf(stderr, "failed to add fb (%ux%u): %s\n", + width, height, strerror(errno)); return; } commit 3c8adda6e1e6b0471b3d70a63d795622bbeb1580 Author: Jakob Bornecrantz <ja...@vm...> Date: Wed Sep 28 23:34:09 2011 +0200 modetest: Check error message from pageflip ioctl Signed-off-by: Jakob Bornecrantz <ja...@vm...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index f6fdcf4..35045c8 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -608,8 +608,12 @@ set_mode(struct connector *c, int count, int page_flip) if (c[i].mode == NULL) continue; - drmModePageFlip(fd, c[i].crtc, other_fb_id, - DRM_MODE_PAGE_FLIP_EVENT, &c[i]); + ret = drmModePageFlip(fd, c[i].crtc, other_fb_id, + DRM_MODE_PAGE_FLIP_EVENT, &c[i]); + if (ret) { + fprintf(stderr, "failed to page flip: %s\n", strerror(errno)); + return; + } gettimeofday(&c[i].start, NULL); c[i].swap_count = 0; c[i].fb_id[0] = fb_id; commit c2925e51979fcb829962e7bf66c13cbc96c39db1 Author: Jakob Bornecrantz <ja...@vm...> Date: Wed Sep 28 17:27:07 2011 +0200 vbltest: Check error codes returned from libdrm Signed-off-by: Jakob Bornecrantz <ja...@vm...> diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c index 2fe56b2..903ca0f 100644 --- a/tests/vbltest/vbltest.c +++ b/tests/vbltest/vbltest.c @@ -102,7 +102,7 @@ static void usage(char *name) int main(int argc, char **argv) { - int i, c, fd; + int i, c, fd, ret; char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx" }; drmVBlank vbl; drmEventContext evctx; @@ -141,7 +141,11 @@ int main(int argc, char **argv) if (secondary) vbl.request.type |= DRM_VBLANK_SECONDARY; vbl.request.sequence = 0; - drmWaitVBlank(fd, &vbl); + ret = drmWaitVBlank(fd, &vbl); + if (ret != 0) { + printf("drmWaitVBlank (relative) failed ret: %i\n", ret); + return -1; + } printf("starting count: %d\n", vbl.request.sequence); @@ -154,7 +158,11 @@ int main(int argc, char **argv) vbl.request.type |= DRM_VBLANK_SECONDARY; vbl.request.sequence = 1; vbl.request.signal = (unsigned long)&handler_info; - drmWaitVBlank(fd, &vbl); + ret = drmWaitVBlank(fd, &vbl); + if (ret != 0) { + printf("drmWaitVBlank (relative, event) failed ret: %i\n", ret); + return -1; + } /* Set up our event handler */ memset(&evctx, 0, sizeof evctx); @@ -181,7 +189,11 @@ int main(int argc, char **argv) break; } - drmHandleEvent(fd, &evctx); + ret = drmHandleEvent(fd, &evctx); + if (ret != 0) { + printf("drmHandleEvent failed: %i\n", ret); + return -1; + } } return 0; commit dc11db2e282c522219bb6e419eb648f3e836bdc0 Author: Jakob Bornecrantz <ja...@vm...> Date: Fri Sep 16 20:50:39 2011 +0200 tests: Add vmwgfx driver to probed drivers in tests Signed-off-by: Jakob Bornecrantz <ja...@vm...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 88c5ce5..f6fdcf4 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -712,7 +712,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", "nouveau" }; + char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx" }; char *modeset = NULL; int i, count = 0; struct connector con_args[2]; diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c index 1297da8..2fe56b2 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; - char *modules[] = { "i915", "radeon", "nouveau" }; + char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx" }; drmVBlank vbl; drmEventContext evctx; struct vbl_info handler_info; |
From: <rob...@ke...> - 2012-04-03 21:50:09
|
omap/omap_drm.c | 2 omap/omap_drm.h | 33 ++-- tests/modetest/modetest.c | 335 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 348 insertions(+), 22 deletions(-) New commits: commit 2f1e2101b4dc0a6dc1c1d1c59c5cc5fbc54b90cf Author: Rob Clark <ro...@ti...> Date: Mon Jan 2 10:31:25 2012 -0600 modetest: add AR15/XR15 (RGB-1555) formats Signed-off-by: Rob Clark <ro...@ti...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 36bdfff..819724a 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -652,6 +652,26 @@ fill422(unsigned char *virtual, int n, int width, int height, int stride) } } +static void +fill1555(unsigned char *virtual, int n, int width, int height, int stride) +{ + int i, j; + /* paint the buffer with colored tiles */ + for (j = 0; j < height; j++) { + uint16_t *ptr = (uint16_t*)((char*)virtual + j * stride); + for (i = 0; i < width; i++) { + div_t d = div(n+i+j, width); + uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6); + unsigned char *rgbp = (unsigned char *)&rgb; + + *(ptr++) = 0x8000 | + (rgbp[RED] >> 3) << 10 | + (rgbp[GREEN] >> 3) << 5 | + (rgbp[BLUE] >> 3); + } + } +} + static int set_plane(struct kms_driver *kms, struct connector *c, struct plane *p) { @@ -756,6 +776,22 @@ set_plane(struct kms_driver *kms, struct connector *c, struct plane *p) 1, 0, p->w, p->h, pitches[0]); format = DRM_FORMAT_YVU420; + } else if (!strcmp(p->format_str, "XR15")) { + pitches[0] = p->w * 2; + offsets[0] = 0; + kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]); + + fill1555(virtual, 0, p->w, p->h, pitches[0]); + + format = DRM_FORMAT_XRGB1555; + } else if (!strcmp(p->format_str, "AR15")) { + pitches[0] = p->w * 2; + offsets[0] = 0; + kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]); + + fill1555(virtual, 0, p->w, p->h, pitches[0]); + + format = DRM_FORMAT_ARGB1555; } else { fprintf(stderr, "Unknown format: %s\n", p->format_str); return -1; commit b83ad866220911e5be1704e6df085705e5ba8eae Author: Rob Clark <ro...@ti...> Date: Wed Dec 14 22:24:14 2011 -0600 modetest: add YUV and multi-planar support Signed-off-by: Rob Clark <ro...@ti...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 2936de0..36bdfff 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -335,6 +335,7 @@ struct plane { uint32_t con_id; /* the id of connector to bind to */ uint32_t w, h; unsigned int fb_id; + char format_str[5]; /* need to leave room for terminating \0 */ }; static void @@ -594,6 +595,63 @@ page_flip_handler(int fd, unsigned int frame, } } +/* swap these for big endian.. */ +#define RED 2 +#define GREEN 1 +#define BLUE 0 + +static void +fill420(unsigned char *y, unsigned char *u, unsigned char *v, + int cs /*chroma pixel stride */, + int n, int width, int height, int stride) +{ + int i, j; + + /* paint the buffer with colored tiles, in blocks of 2x2 */ + for (j = 0; j < height; j+=2) { + unsigned char *y1p = y + j * stride; + unsigned char *y2p = y1p + stride; + unsigned char *up = u + (j/2) * stride * cs / 2; + unsigned char *vp = v + (j/2) * stride * cs / 2; + + for (i = 0; i < width; i+=2) { + div_t d = div(n+i+j, width); + uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6); + unsigned char *rgbp = (unsigned char *)&rgb; + unsigned char y = (0.299 * rgbp[RED]) + (0.587 * rgbp[GREEN]) + (0.114 * rgbp[BLUE]); + + *(y2p++) = *(y1p++) = y; + *(y2p++) = *(y1p++) = y; + + *up = (rgbp[BLUE] - y) * 0.565 + 128; + *vp = (rgbp[RED] - y) * 0.713 + 128; + up += cs; + vp += cs; + } + } +} + +static void +fill422(unsigned char *virtual, int n, int width, int height, int stride) +{ + int i, j; + /* paint the buffer with colored tiles */ + for (j = 0; j < height; j++) { + uint8_t *ptr = (uint8_t*)((char*)virtual + j * stride); + for (i = 0; i < width; i++) { + div_t d = div(n+i+j, width); + uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6); + unsigned char *rgbp = (unsigned char *)&rgb; + unsigned char y = (0.299 * rgbp[RED]) + (0.587 * rgbp[GREEN]) + (0.114 * rgbp[BLUE]); + + *(ptr++) = y; + *(ptr++) = (rgbp[BLUE] - y) * 0.565 + 128; + *(ptr++) = y; + *(ptr++) = (rgbp[RED] - y) * 0.713 + 128; + } + } +} + static int set_plane(struct kms_driver *kms, struct connector *c, struct plane *p) { @@ -602,8 +660,8 @@ set_plane(struct kms_driver *kms, struct connector *c, struct plane *p) uint32_t handles[4], pitches[4], offsets[4] = {0}; /* we only use [0] */ uint32_t plane_id = 0; struct kms_bo *plane_bo; - uint32_t plane_flags = 0; - int i, crtc_x, crtc_y, crtc_w, crtc_h; + uint32_t plane_flags = 0, format; + int i, ret, crtc_x, crtc_y, crtc_w, crtc_h; /* find an unused plane which can be connected to our crtc */ plane_resources = drmModeGetPlaneResources(fd); @@ -627,19 +685,87 @@ set_plane(struct kms_driver *kms, struct connector *c, struct plane *p) drmModeFreePlane(ovr); } + fprintf(stderr, "testing %dx%d@%s overlay plane\n", + p->w, p->h, p->format_str); + if (!plane_id) { fprintf(stderr, "failed to find plane!\n"); return -1; } - /* TODO.. would be nice to test YUV overlays.. */ - if (create_test_buffer(kms, p->w, p->h, &pitches[0], &plane_bo)) - return -1; + if (!strcmp(p->format_str, "XR24")) { + if (create_test_buffer(kms, p->w, p->h, &pitches[0], &plane_bo)) + return -1; + kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]); + format = DRM_FORMAT_XRGB8888; + } else { + void *virtual; + + /* TODO: this always allocates a buffer for 32bpp RGB.. but for + * YUV formats, we don't use all of it.. since 4bytes/pixel is + * worst case, so live with it for now and just don't use all + * the buffer: + */ + plane_bo = allocate_buffer(kms, p->w, p->h, &pitches[0]); + if (!plane_bo) + return -1; - kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]); + ret = kms_bo_map(plane_bo, &virtual); + if (ret) { + fprintf(stderr, "failed to map buffer: %s\n", + strerror(-ret)); + kms_bo_destroy(&plane_bo); + return -1; + } + + /* just testing a limited # of formats to test single + * and multi-planar path.. would be nice to add more.. + */ + if (!strcmp(p->format_str, "YUYV")) { + pitches[0] = p->w * 2; + offsets[0] = 0; + kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]); + + fill422(virtual, 0, p->w, p->h, pitches[0]); + + format = DRM_FORMAT_YUYV; + } else if (!strcmp(p->format_str, "NV12")) { + pitches[0] = p->w; + offsets[0] = 0; + kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]); + pitches[1] = p->w; + offsets[1] = p->w * p->h; + kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[1]); + + fill420(virtual, virtual+offsets[1], virtual+offsets[1]+1, + 2, 0, p->w, p->h, pitches[0]); + + format = DRM_FORMAT_NV12; + } else if (!strcmp(p->format_str, "YV12")) { + pitches[0] = p->w; + offsets[0] = 0; + kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]); + pitches[1] = p->w / 2; + offsets[1] = p->w * p->h; + kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[1]); + pitches[2] = p->w / 2; + offsets[2] = offsets[1] + (p->w * p->h) / 4; + kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[1]); + + fill420(virtual, virtual+offsets[1], virtual+offsets[2], + 1, 0, p->w, p->h, pitches[0]); + + format = DRM_FORMAT_YVU420; + } else { + fprintf(stderr, "Unknown format: %s\n", p->format_str); + return -1; + } + + kms_bo_unmap(plane_bo); + } /* just use single plane format for now.. */ - if (drmModeAddFB2(fd, p->w, p->h, DRM_FORMAT_XRGB8888, + if (drmModeAddFB2(fd, p->w, p->h, format, handles, pitches, offsets, &p->fb_id, plane_flags)) { fprintf(stderr, "failed to add fb: %s\n", strerror(errno)); return -1; @@ -826,6 +952,7 @@ void usage(char *name) fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n"); fprintf(stderr, "\t-s <connector_id>@<crtc_id>:<mode>\tset a mode\n"); fprintf(stderr, "\t-P <connector_id>:<w>x<h>\tset a plane\n"); + fprintf(stderr, "\t-P <connector_id>:<w>x<h>@<format>\tset a plane\n"); fprintf(stderr, "\n\tDefault is to dump all info.\n"); exit(0); } @@ -862,7 +989,7 @@ int main(int argc, char **argv) char *modeset = NULL; int i, count = 0, plane_count = 0; struct connector con_args[2]; - struct plane plane_args[2]; + struct plane plane_args[2] = {0}; opterr = 0; while ((c = getopt(argc, argv, optstr)) != -1) { @@ -900,7 +1027,13 @@ int main(int argc, char **argv) count++; break; case 'P': - if (sscanf(optarg, "%d:%dx%d", + strcpy(plane_args[plane_count].format_str, "XR24"); + if (sscanf(optarg, "%d:%dx%d@%4s", + &plane_args[plane_count].con_id, + &plane_args[plane_count].w, + &plane_args[plane_count].h, + plane_args[plane_count].format_str) != 4 && + sscanf(optarg, "%d:%dx%d", &plane_args[plane_count].con_id, &plane_args[plane_count].w, &plane_args[plane_count].h) != 3) commit d55de747a2bdec5b4885a6c86ea6707e15dfefb5 Author: Rob Clark <ro...@ti...> Date: Wed Dec 14 21:06:43 2011 -0600 modetest: add drm_plane support Signed-off-by: Rob Clark <ro...@ti...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 1e4ec91..2936de0 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -51,6 +51,7 @@ #include "xf86drm.h" #include "xf86drmMode.h" +#include "drm_fourcc.h" #include "libkms.h" #ifdef HAVE_CAIRO @@ -267,6 +268,49 @@ void dump_framebuffers(void) printf("\n"); } +static void dump_planes(void) +{ + drmModePlaneRes *plane_resources; + drmModePlane *ovr; + int i, j; + + plane_resources = drmModeGetPlaneResources(fd); + if (!plane_resources) { + fprintf(stderr, "drmModeGetPlaneResources failed: %s\n", + strerror(errno)); + return; + } + + printf("Planes:\n"); + printf("id\tcrtc\tfb\tCRTC x,y\tx,y\tgamma size\n"); + for (i = 0; i < plane_resources->count_planes; i++) { + ovr = drmModeGetPlane(fd, plane_resources->planes[i]); + if (!ovr) { + fprintf(stderr, "drmModeGetPlane failed: %s\n", + strerror(errno)); + continue; + } + + printf("%d\t%d\t%d\t%d,%d\t\t%d,%d\t%d\n", + ovr->plane_id, ovr->crtc_id, ovr->fb_id, + ovr->crtc_x, ovr->crtc_y, ovr->x, ovr->y, + ovr->gamma_size); + + if (!ovr->count_formats) + continue; + + printf(" formats:"); + for (j = 0; j < ovr->count_formats; j++) + printf(" %4.4s", (char *)&ovr->formats[j]); + printf("\n"); + + drmModeFreePlane(ovr); + } + printf("\n"); + + return; +} + /* * Mode setting with the kernel interfaces is a bit of a chore. * First you have to find the connector in question and make sure the @@ -280,11 +324,18 @@ struct connector { drmModeModeInfo *mode; drmModeEncoder *encoder; int crtc; + int pipe; unsigned int fb_id[2], current_fb_id; struct timeval start; int swap_count; -}; +}; + +struct plane { + uint32_t con_id; /* the id of connector to bind to */ + uint32_t w, h; + unsigned int fb_id; +}; static void connector_find_mode(struct connector *c) @@ -351,6 +402,15 @@ connector_find_mode(struct connector *c) if (c->crtc == -1) c->crtc = c->encoder->crtc_id; + + /* and figure out which crtc index it is: */ + for (i = 0; i < resources->count_crtcs; i++) { + if (c->crtc == resources->crtcs[i]) { + c->pipe = i; + break; + } + } + } static struct kms_bo * @@ -534,13 +594,83 @@ page_flip_handler(int fd, unsigned int frame, } } +static int +set_plane(struct kms_driver *kms, struct connector *c, struct plane *p) +{ + drmModePlaneRes *plane_resources; + drmModePlane *ovr; + uint32_t handles[4], pitches[4], offsets[4] = {0}; /* we only use [0] */ + uint32_t plane_id = 0; + struct kms_bo *plane_bo; + uint32_t plane_flags = 0; + int i, crtc_x, crtc_y, crtc_w, crtc_h; + + /* find an unused plane which can be connected to our crtc */ + plane_resources = drmModeGetPlaneResources(fd); + if (!plane_resources) { + fprintf(stderr, "drmModeGetPlaneResources failed: %s\n", + strerror(errno)); + return -1; + } + + for (i = 0; i < plane_resources->count_planes && !plane_id; i++) { + ovr = drmModeGetPlane(fd, plane_resources->planes[i]); + if (!ovr) { + fprintf(stderr, "drmModeGetPlane failed: %s\n", + strerror(errno)); + return -1; + } + + if ((ovr->possible_crtcs & (1 << c->pipe)) && !ovr->crtc_id) + plane_id = ovr->plane_id; + + drmModeFreePlane(ovr); + } + + if (!plane_id) { + fprintf(stderr, "failed to find plane!\n"); + return -1; + } + + /* TODO.. would be nice to test YUV overlays.. */ + if (create_test_buffer(kms, p->w, p->h, &pitches[0], &plane_bo)) + return -1; + + kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]); + + /* just use single plane format for now.. */ + if (drmModeAddFB2(fd, p->w, p->h, DRM_FORMAT_XRGB8888, + handles, pitches, offsets, &p->fb_id, plane_flags)) { + fprintf(stderr, "failed to add fb: %s\n", strerror(errno)); + return -1; + } + + /* ok, boring.. but for now put in middle of screen: */ + crtc_x = c->mode->hdisplay / 3; + crtc_y = c->mode->vdisplay / 3; + crtc_w = crtc_x; + crtc_h = crtc_y; + + /* note src coords (last 4 args) are in Q16 format */ + if (drmModeSetPlane(fd, plane_id, c->crtc, p->fb_id, + plane_flags, crtc_x, crtc_y, crtc_w, crtc_h, + 0, 0, p->w << 16, p->h << 16)) { + fprintf(stderr, "failed to enable plane: %s\n", + strerror(errno)); + return -1; + } + + return 0; +} + static void -set_mode(struct connector *c, int count, int page_flip) +set_mode(struct connector *c, int count, struct plane *p, int plane_count, + int page_flip) { struct kms_driver *kms; struct kms_bo *bo, *other_bo; unsigned int fb_id, other_fb_id; - int i, ret, width, height, x, stride; + int i, j, ret, width, height, x, stride; unsigned handle; drmEventContext evctx; @@ -593,6 +723,12 @@ set_mode(struct connector *c, int count, int page_flip) fprintf(stderr, "failed to set mode: %s\n", strerror(errno)); return; } + + /* if we have a plane/overlay to show, set that up now: */ + for (j = 0; j < plane_count; j++) + if (p[j].con_id == c[i].id) + if (set_plane(kms, &c[i], &p[j])) + return; } if (!page_flip) @@ -676,19 +812,20 @@ set_mode(struct connector *c, int count, int page_flip) extern char *optarg; extern int optind, opterr, optopt; -static char optstr[] = "ecpmfs:v"; +static char optstr[] = "ecpmfs:P:v"; void usage(char *name) { fprintf(stderr, "usage: %s [-ecpmf]\n", name); fprintf(stderr, "\t-e\tlist encoders\n"); fprintf(stderr, "\t-c\tlist connectors\n"); - fprintf(stderr, "\t-p\tlist CRTCs (pipes)\n"); + fprintf(stderr, "\t-p\tlist CRTCs and planes (pipes)\n"); fprintf(stderr, "\t-m\tlist modes\n"); fprintf(stderr, "\t-f\tlist framebuffers\n"); fprintf(stderr, "\t-v\ttest vsynced page flipping\n"); fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n"); fprintf(stderr, "\t-s <connector_id>@<crtc_id>:<mode>\tset a mode\n"); + fprintf(stderr, "\t-P <connector_id>:<w>x<h>\tset a plane\n"); fprintf(stderr, "\n\tDefault is to dump all info.\n"); exit(0); } @@ -719,12 +856,13 @@ static int page_flipping_supported(int fd) int main(int argc, char **argv) { int c; - int encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0; + int encoders = 0, connectors = 0, crtcs = 0, planes = 0, framebuffers = 0; int test_vsync = 0; char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm" }; char *modeset = NULL; - int i, count = 0; + int i, count = 0, plane_count = 0; struct connector con_args[2]; + struct plane plane_args[2]; opterr = 0; while ((c = getopt(argc, argv, optstr)) != -1) { @@ -737,6 +875,7 @@ int main(int argc, char **argv) break; case 'p': crtcs = 1; + planes = 1; break; case 'm': modes = 1; @@ -760,6 +899,14 @@ int main(int argc, char **argv) usage(argv[0]); count++; break; + case 'P': + if (sscanf(optarg, "%d:%dx%d", + &plane_args[plane_count].con_id, + &plane_args[plane_count].w, + &plane_args[plane_count].h) != 3) + usage(argv[0]); + plane_count++; + break; default: usage(argv[0]); break; @@ -767,7 +914,7 @@ int main(int argc, char **argv) } if (argc == 1) - encoders = connectors = crtcs = modes = framebuffers = 1; + encoders = connectors = crtcs = planes = modes = framebuffers = 1; for (i = 0; i < ARRAY_SIZE(modules); i++) { printf("trying to load module %s...", modules[i]); @@ -801,10 +948,11 @@ int main(int argc, char **argv) dump_resource(encoders); dump_resource(connectors); dump_resource(crtcs); + dump_resource(planes); dump_resource(framebuffers); if (count > 0) { - set_mode(con_args, count, test_vsync); + set_mode(con_args, count, plane_args, plane_count, test_vsync); getchar(); } commit e98ed38ca9c9328f88e0b2fab376020049e4a7fb Author: VÃctor Manuel Jáquez Leal <vj...@ig...> Date: Mon Apr 2 18:08:29 2012 +0200 omap: fix compiler warning When compiling with linaro toolchain version 4.6.2 got this warning. CC omap_drm.lo omap_drm.c: In function 'omap_bo_new_impl': omap_drm.c:139:6: warning: 'bo' may be used uninitialized in this function [-Wuninitialized] This patch initialize bo to NULL avoiding the warning. Signed-off-by: VÃctor Manuel Jáquez Leal <vj...@ig...> Signed-off-by: Rob Clark <ro...@ti...> diff --git a/omap/omap_drm.c b/omap/omap_drm.c index e611806..96e1871 100644 --- a/omap/omap_drm.c +++ b/omap/omap_drm.c @@ -102,7 +102,7 @@ int omap_set_param(struct omap_device *dev, uint64_t param, uint64_t value) static struct omap_bo * omap_bo_new_impl(struct omap_device *dev, union omap_gem_size size, uint32_t flags) { - struct omap_bo *bo; + struct omap_bo *bo = NULL; struct drm_omap_gem_new req = { .size = size, .flags = flags, commit 06eaf09469f2234bf1ca9790dad2ba391ccceb5a Author: Rob Clark <ro...@ti...> Date: Tue Apr 3 16:44:43 2012 -0500 omap: fix license header In syncing with the corresponding kernel header, the wrong license header was inadvertantly copied over. The intention was for the userspace headers to have a MIT license following the convention of the rest of libdrm, xorg, etc. Signed-off-by: Rob Clark <ro...@ti...> diff --git a/omap/omap_drm.h b/omap/omap_drm.h index f277cea..f677cd8 100644 --- a/omap/omap_drm.h +++ b/omap/omap_drm.h @@ -1,20 +1,29 @@ +/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ + /* - * include/drm/omap_drm.h + * Copyright (C) 2011 Texas Instruments, Inc * - * Copyright (C) 2011 Texas Instruments - * Author: Rob Clark <ro...@ti...> + * 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: * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. + * 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. * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. + * Authors: + * Rob Clark <ro...@ti...> */ #ifndef __OMAP_DRM_H__ |
From: <rob...@ke...> - 2012-06-08 14:32:43
|
include/drm/drm.h | 2 + include/drm/drm_mode.h | 25 +++++++++++++ tests/modetest/modetest.c | 37 +++++++++++++++++++ xf86drmMode.c | 87 ++++++++++++++++++++++++++++++++++++++++++++-- xf86drmMode.h | 14 +++++++ 5 files changed, 163 insertions(+), 2 deletions(-) New commits: commit 25e4cb4659c62817aae2ca3b83f2d4f598d6474b Author: Rob Clark <ro...@ti...> Date: Tue Jun 5 12:28:47 2012 -0500 modetest: support plane properties Add support to display plane properties. Signed-off-by: Rob Clark <ro...@ti...> Reviewed-by: Paulo Zanoni <pau...@in...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index dea271a..dc84cf3 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -369,6 +369,7 @@ void dump_framebuffers(void) static void dump_planes(void) { + drmModeObjectPropertiesPtr props; drmModePlaneRes *plane_resources; drmModePlane *ovr; unsigned int i, j; @@ -403,6 +404,19 @@ static void dump_planes(void) printf(" %4.4s", (char *)&ovr->formats[j]); printf("\n"); + printf(" props:\n"); + props = drmModeObjectGetProperties(fd, ovr->plane_id, + DRM_MODE_OBJECT_PLANE); + if (props) { + for (j = 0; j < props->count_props; j++) + dump_prop(props->props[j], + props->prop_values[j]); + drmModeFreeObjectProperties(props); + } else { + printf("\tcould not get plane properties: %s\n", + strerror(errno)); + } + drmModeFreePlane(ovr); } printf("\n"); commit 6df9e6af4b34ef2c5278941ee78de029e4040485 Author: Rob Clark <ro...@ti...> Date: Tue Jun 5 12:28:38 2012 -0500 modetest: support bitmask properties Add support to display bitmask properties. Signed-off-by: Rob Clark <ro...@ti...> Reviewed-by: Paulo Zanoni <pau...@in...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index ce57e65..dea271a 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -207,6 +207,8 @@ dump_prop(uint32_t prop_id, uint64_t value) printf(" immutable"); if (prop->flags & DRM_MODE_PROP_ENUM) printf(" enum"); + if (prop->flags & DRM_MODE_PROP_BITMASK) + printf(" bitmask"); if (prop->flags & DRM_MODE_PROP_BLOB) printf(" blob"); printf("\n"); @@ -224,6 +226,12 @@ dump_prop(uint32_t prop_id, uint64_t value) printf(" %s=%llu", prop->enums[i].name, prop->enums[i].value); printf("\n"); + } else if (prop->flags & DRM_MODE_PROP_BITMASK) { + printf("\t\tvalues:"); + for (i = 0; i < prop->count_enums; i++) + printf(" %s=0x%llx", prop->enums[i].name, + (1LL << prop->enums[i].value)); + printf("\n"); } else { assert(prop->count_enums == 0); } commit 7b228e900f59cda3cafb60692be9dd7aced6ad96 Author: Rob Clark <ro...@ti...> Date: Tue Jun 5 12:28:22 2012 -0500 Add support for bitmask properties A bitmask property is similar to an enum. The enum value is a bit position (0-63), and valid property values consist of a mask of zero or more of (1 << enum_val[n]). Signed-off-by: Rob Clark <ro...@ti...> Reviewed-by: Paulo Zanoni <pau...@in...> diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index f303d94..62ba997 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -226,6 +226,7 @@ struct drm_mode_get_connector { #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) +#define DRM_MODE_PROP_BITMASK (1<<5) /* bitmask of enumerated types */ struct drm_mode_property_enum { __u64 value; diff --git a/xf86drmMode.c b/xf86drmMode.c index a60c7cb..04fdf1f 100644 --- a/xf86drmMode.c +++ b/xf86drmMode.c @@ -575,7 +575,7 @@ drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id) if (prop.count_values) prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t))); - if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_ENUM)) + if (prop.count_enum_blobs && (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK))) prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum))); if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) { @@ -597,7 +597,7 @@ drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id) r->flags = prop.flags; if (prop.count_values) r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t)); - if (prop.flags & DRM_MODE_PROP_ENUM) { + if (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) { r->count_enums = prop.count_enum_blobs; r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum)); } else if (prop.flags & DRM_MODE_PROP_BLOB) { commit 86dece4cf2f7180b854fbd318fa1a57793f0deac Author: Paulo Zanoni <pau...@in...> Date: Tue May 15 18:38:29 2012 -0300 modetest: print CRTC properties Reviewed-by: Eugeni Dodonov <eug...@in...> Reviewed-by: Rob Clark <ro...@ti...> Signed-off-by: Paulo Zanoni <pau...@in...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 8012ecc..ce57e65 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -295,7 +295,9 @@ void dump_connectors(void) void dump_crtcs(void) { drmModeCrtc *crtc; + drmModeObjectPropertiesPtr props; int i; + uint32_t j; printf("CRTCs:\n"); printf("id\tfb\tpos\tsize\n"); @@ -314,6 +316,19 @@ void dump_crtcs(void) crtc->width, crtc->height); dump_mode(&crtc->mode); + printf(" props:\n"); + props = drmModeObjectGetProperties(fd, crtc->crtc_id, + DRM_MODE_OBJECT_CRTC); + if (props) { + for (j = 0; j < props->count_props; j++) + dump_prop(props->props[j], + props->prop_values[j]); + drmModeFreeObjectProperties(props); + } else { + printf("\tcould not get crtc properties: %s\n", + strerror(errno)); + } + drmModeFreeCrtc(crtc); } printf("\n"); commit 8c75703df0fdf65b3851f8eb5822705638decff3 Author: Paulo Zanoni <pau...@in...> Date: Tue May 15 18:38:28 2012 -0300 Add support for generic object properties IOCTLs New library calls: - drmModeObjectGetProperties - drmModeFreeObjectProperties - drmModeObjectSetProperties Reviewed-by: Eugeni Dodonov <eug...@in...> Reviewed-by: Rob Clark <ro...@ti...> Signed-off-by: Paulo Zanoni <pau...@in...> diff --git a/include/drm/drm.h b/include/drm/drm.h index 753d2fc..5e6cd29 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h @@ -731,6 +731,8 @@ struct drm_prime_handle { #define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane) #define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane) #define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2) +#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties) +#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property) /** * Device specific ioctls should only be in their respective headers diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index f36c61a..f303d94 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -250,6 +250,30 @@ struct drm_mode_connector_set_property { __u32 connector_id; }; +#define DRM_MODE_OBJECT_CRTC 0xcccccccc +#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 +#define DRM_MODE_OBJECT_ENCODER 0xe0e0e0e0 +#define DRM_MODE_OBJECT_MODE 0xdededede +#define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0 +#define DRM_MODE_OBJECT_FB 0xfbfbfbfb +#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb +#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee + +struct drm_mode_obj_get_properties { + __u64 props_ptr; + __u64 prop_values_ptr; + __u32 count_props; + __u32 obj_id; + __u32 obj_type; +}; + +struct drm_mode_obj_set_property { + __u64 value; + __u32 prop_id; + __u32 obj_id; + __u32 obj_type; +}; + struct drm_mode_get_blob { __u32 blob_id; __u32 length; diff --git a/xf86drmMode.c b/xf86drmMode.c index c809c44..a60c7cb 100644 --- a/xf86drmMode.c +++ b/xf86drmMode.c @@ -974,3 +974,86 @@ void drmModeFreePlaneResources(drmModePlaneResPtr ptr) drmFree(ptr->planes); drmFree(ptr); } + +drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd, + uint32_t object_id, + uint32_t object_type) +{ + struct drm_mode_obj_get_properties properties; + drmModeObjectPropertiesPtr ret = NULL; + uint32_t count; + +retry: + memset(&properties, 0, sizeof(struct drm_mode_obj_get_properties)); + properties.obj_id = object_id; + properties.obj_type = object_type; + + if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties)) + return 0; + + count = properties.count_props; + + if (count) { + properties.props_ptr = VOID2U64(drmMalloc(count * + sizeof(uint32_t))); + if (!properties.props_ptr) + goto err_allocs; + properties.prop_values_ptr = VOID2U64(drmMalloc(count * + sizeof(uint64_t))); + if (!properties.prop_values_ptr) + goto err_allocs; + } + + if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties)) + goto err_allocs; + + if (count < properties.count_props) { + drmFree(U642VOID(properties.props_ptr)); + drmFree(U642VOID(properties.prop_values_ptr)); + goto retry; + } + count = properties.count_props; + + ret = drmMalloc(sizeof(*ret)); + if (!ret) + goto err_allocs; + + ret->count_props = count; + ret->props = drmAllocCpy(U642VOID(properties.props_ptr), + count, sizeof(uint32_t)); + ret->prop_values = drmAllocCpy(U642VOID(properties.prop_values_ptr), + count, sizeof(uint64_t)); + if (ret->count_props && (!ret->props || !ret->prop_values)) { + drmFree(ret->props); + drmFree(ret->prop_values); + drmFree(ret); + ret = NULL; + } + +err_allocs: + drmFree(U642VOID(properties.props_ptr)); + drmFree(U642VOID(properties.prop_values_ptr)); + return ret; +} + +void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr) +{ + if (!ptr) + return; + drmFree(ptr->props); + drmFree(ptr->prop_values); + drmFree(ptr); +} + +int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type, + uint32_t property_id, uint64_t value) +{ + struct drm_mode_obj_set_property prop; + + prop.value = value; + prop.prop_id = property_id; + prop.obj_id = object_id; + prop.obj_type = object_type; + + return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop); +} diff --git a/xf86drmMode.h b/xf86drmMode.h index 991e3f9..8e40034 100644 --- a/xf86drmMode.h +++ b/xf86drmMode.h @@ -281,6 +281,12 @@ typedef struct _drmModeConnector { uint32_t *encoders; /**< List of encoder ids */ } drmModeConnector, *drmModeConnectorPtr; +typedef struct _drmModeObjectProperties { + uint32_t count_props; + uint32_t *props; + uint64_t *prop_values; +} drmModeObjectProperties, *drmModeObjectPropertiesPtr; + typedef struct _drmModePlane { uint32_t count_formats; uint32_t *formats; @@ -428,6 +434,14 @@ extern int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h); +extern drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd, + uint32_t object_id, + uint32_t object_type); +extern void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr); +extern int drmModeObjectSetProperty(int fd, uint32_t object_id, + uint32_t object_type, uint32_t property_id, + uint64_t value); + #if defined(__cplusplus) || defined(c_plusplus) } #endif |
From: <bwi...@ke...> - 2013-11-08 01:11:06
|
intel/intel_bufmgr_gem.c | 24 +++++++++++++++++++----- intel/intel_chipset.h | 22 +++++++++++++++++++++- intel/intel_decode.c | 4 +++- 3 files changed, 43 insertions(+), 7 deletions(-) New commits: commit dad3c6b9791920f2bda1193d76f260827c4cd3f1 Author: Damien Lespiau <dam...@in...> Date: Fri Feb 15 16:44:05 2013 +0000 intel/bdw: Update MI_BATCH_BUFFER_START for aub dumps The command now takes a 48bits address and is thus 1 dword longer. v2 (Ben): commit message: s/byte/dword (Eric) Signed-off-by: Damien Lespiau <dam...@in...> Reviewed-by: Eric Anholt <er...@an...> Signed-off-by: Ben Widawsky <be...@bw...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index 3eb6e2e..029ca5d 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -2028,8 +2028,14 @@ aub_build_dump_ringbuffer(drm_intel_bufmgr_gem *bufmgr_gem, /* Make a ring buffer to execute our batchbuffer. */ memset(ringbuffer, 0, sizeof(ringbuffer)); - ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START; - ringbuffer[ring_count++] = batch_buffer; + if (bufmgr_gem->gen >= 8) { + ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START | (3 - 2); + ringbuffer[ring_count++] = batch_buffer; + ringbuffer[ring_count++] = 0; + } else { + ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START; + ringbuffer[ring_count++] = batch_buffer; + } /* Write out the ring. This appears to trigger execution of * the ring in the simulator. commit a0c126dcedb8be64c644321c2b2836723117064b Author: Kenneth Graunke <ke...@wh...> Date: Fri Feb 15 09:29:46 2013 -0800 intel/bdw/aub: Update AUB trace block writes for 48-bit addressing. Since our aub file dumping's GTT handling is totally fake, we always put everything in the low 4GB anyway and shouldn't ever need to set AddressHigh to anything other than 0. Signed-off-by: Kenneth Graunke <ke...@wh...> [ben: slight commit message change] Reviewed-by: Eric Anholt <er...@an...> Signed-off-by: Ben Widawsky <be...@bw...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index 32a226c..3eb6e2e 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -1944,12 +1944,14 @@ aub_write_trace_block(drm_intel_bo *bo, uint32_t type, uint32_t subtype, aub_out(bufmgr_gem, CMD_AUB_TRACE_HEADER_BLOCK | - (5 - 2)); + ((bufmgr_gem->gen >= 8 ? 6 : 5) - 2)); aub_out(bufmgr_gem, AUB_TRACE_MEMTYPE_GTT | type | AUB_TRACE_OP_DATA_WRITE); aub_out(bufmgr_gem, subtype); aub_out(bufmgr_gem, bo_gem->aub_offset + offset); aub_out(bufmgr_gem, size); + if (bufmgr_gem->gen >= 8) + aub_out(bufmgr_gem, 0); aub_write_bo_data(bo, offset, size); } @@ -2034,12 +2036,14 @@ aub_build_dump_ringbuffer(drm_intel_bufmgr_gem *bufmgr_gem, */ aub_out(bufmgr_gem, CMD_AUB_TRACE_HEADER_BLOCK | - (5 - 2)); + ((bufmgr_gem->gen >= 8 ? 6 : 5) - 2)); aub_out(bufmgr_gem, AUB_TRACE_MEMTYPE_GTT | ring | AUB_TRACE_OP_COMMAND_WRITE); aub_out(bufmgr_gem, 0); /* general/surface subtype */ aub_out(bufmgr_gem, bufmgr_gem->aub_offset); aub_out(bufmgr_gem, ring_count * 4); + if (bufmgr_gem->gen >= 8) + aub_out(bufmgr_gem, 0); /* FIXME: Need some flush operations here? */ aub_out_data(bufmgr_gem, ringbuffer, ring_count * 4); @@ -2952,11 +2956,13 @@ drm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable) aub_out(bufmgr_gem, 0); /* comment len */ /* Set up the GTT. The max we can handle is 256M */ - aub_out(bufmgr_gem, CMD_AUB_TRACE_HEADER_BLOCK | (5 - 2)); + aub_out(bufmgr_gem, CMD_AUB_TRACE_HEADER_BLOCK | ((bufmgr_gem->gen >= 8 ? 6 : 5) - 2)); aub_out(bufmgr_gem, AUB_TRACE_MEMTYPE_NONLOCAL | 0 | AUB_TRACE_OP_DATA_WRITE); aub_out(bufmgr_gem, 0); /* subtype */ aub_out(bufmgr_gem, 0); /* offset */ aub_out(bufmgr_gem, gtt_size); /* size */ + if (bufmgr_gem->gen >= 8) + aub_out(bufmgr_gem, 0); for (i = 0x000; i < gtt_size; i += 4, entry += 0x1000) { aub_out(bufmgr_gem, entry); } commit 946f847dc6683c88f69ea75e521d83ffbab4d40a Author: Damien Lespiau <dam...@in...> Date: Wed Feb 13 16:09:34 2013 +0000 intel/bdw: Add gen8 to the decode init Signed-off-by: Damien Lespiau <dam...@in...> Reviewed-by: Kenneth Graunke <ke...@wh...> Reviewed-by: Eric Anholt <er...@an...> Signed-off-by: Ben Widawsky <be...@bw...> diff --git a/intel/intel_decode.c b/intel/intel_decode.c index 1b80b75..c0a0caf 100644 --- a/intel/intel_decode.c +++ b/intel/intel_decode.c @@ -3827,7 +3827,9 @@ drm_intel_decode_context_alloc(uint32_t devid) ctx->devid = devid; ctx->out = stdout; - if (IS_GEN7(devid)) + if (IS_GEN8(devid)) + ctx->gen = 8; + else if (IS_GEN7(devid)) ctx->gen = 7; else if (IS_GEN6(devid)) ctx->gen = 6; commit 5b348f3ac0069485ecd86ee30483646fad4b01cc Author: Ben Widawsky <be...@bw...> Date: Wed Feb 13 16:09:33 2013 +0000 intel/bdw: Handle gen8 bufmgr_init [bwidawsk: Added Damien's SOB] Signed-off-by: Damien Lespiau <dam...@in...> Reviewed-by: Kenneth Graunke <ke...@wh...> Reviewed-by: Eric Anholt <er...@an...> Signed-off-by: Ben Widawsky <be...@bw...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index 278f5c8..32a226c 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -3124,6 +3124,8 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size) bufmgr_gem->gen = 6; else if (IS_GEN7(bufmgr_gem->pci_device)) bufmgr_gem->gen = 7; + else if (IS_GEN8(bufmgr_gem->pci_device)) + bufmgr_gem->gen = 8; else { free(bufmgr_gem); return NULL; commit 6ea20a0fe2f3ede1c89176db0aa447b9758fefd1 Author: Ben Widawsky <be...@bw...> Date: Tue Dec 4 13:56:14 2012 -0800 intel/bdw: Add broadwell chipset IDs v2: Rename s/<SECRET>/IRIS/ Reviewed-by: Kenneth Graunke <ke...@wh...> Signed-off-by: Ben Widawsky <be...@bw...> diff --git a/intel/intel_chipset.h b/intel/intel_chipset.h index aeb439e..e5589be 100644 --- a/intel/intel_chipset.h +++ b/intel/intel_chipset.h @@ -148,6 +148,12 @@ #define PCI_CHIP_HASWELL_CRW_E_GT1 0x0D0E /* Reserved */ #define PCI_CHIP_HASWELL_CRW_E_GT2 0x0D1E #define PCI_CHIP_HASWELL_CRW_E_GT3 0x0D2E +#define BDW_SPARE 0x2 +#define BDW_ULT 0x6 +#define BDW_SERVER 0xa +#define BDW_IRIS 0xb +#define BDW_WORKSTATION 0xd +#define BDW_ULX 0xe #define PCI_CHIP_VALLEYVIEW_PO 0x0f30 /* VLV PO board */ #define PCI_CHIP_VALLEYVIEW_1 0x0f31 @@ -296,10 +302,24 @@ IS_HSW_GT2(devid) || \ IS_HSW_GT3(devid)) +#define IS_BROADWELL(devid) (((devid & 0xff00) != 0x1600) ? 0 : \ + (((devid & 0x00f0) >> 4) > 3) ? 0 : \ + ((devid & 0x000f) == BDW_SPARE) ? 1 : \ + ((devid & 0x000f) == BDW_ULT) ? 1 : \ + ((devid & 0x000f) == BDW_IRIS) ? 1 : \ + ((devid & 0x000f) == BDW_SERVER) ? 1 : \ + ((devid & 0x000f) == BDW_WORKSTATION) ? 1 : \ + ((devid & 0x000f) == BDW_ULX) ? 1 : 0) + + +#define IS_GEN8(devid) IS_BROADWELL(devid) + #define IS_9XX(dev) (IS_GEN3(dev) || \ IS_GEN4(dev) || \ IS_GEN5(dev) || \ IS_GEN6(dev) || \ - IS_GEN7(dev)) + IS_GEN7(dev) || \ + IS_GEN8(dev)) + #endif /* _INTEL_CHIPSET_H */ |
From: <da...@ke...> - 2015-02-11 14:36:34
|
.gitignore | 4 - intel/intel_bufmgr_gem.c | 68 +++++++++++----------- tests/Makefile.am | 9 --- tests/gem_basic.c | 102 ---------------------------------- tests/gem_flink.c | 137 ---------------------------------------------- tests/gem_mmap.c | 136 --------------------------------------------- tests/gem_readwrite.c | 139 ----------------------------------------------- xf86drm.c | 112 ++++++++++++++++++++++++++----------- xf86drmMode.c | 55 +++++++++--------- 9 files changed, 139 insertions(+), 623 deletions(-) New commits: commit 3a6c65c546ccb450890676db6a8c7e93caf69d8a Author: Daniel Vetter <dan...@ff...> Date: Wed Feb 11 12:55:38 2015 +0100 tests: remove intel-specific tests These all moved to igt meanwhile. Signed-off-by: Daniel Vetter <dan...@in...> diff --git a/.gitignore b/.gitignore index 3596a4a..06cc928 100644 --- a/.gitignore +++ b/.gitignore @@ -79,10 +79,6 @@ tests/getclient tests/getstats tests/getversion tests/lock -tests/gem_basic -tests/gem_flink -tests/gem_mmap -tests/gem_readwrite tests/openclose tests/setversion tests/updatedraw diff --git a/tests/Makefile.am b/tests/Makefile.am index e7ec4fa..37b8d3a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -58,15 +58,6 @@ TESTS = \ SUBDIRS += vbltest $(NULL) -if HAVE_INTEL -TESTS += \ - gem_basic \ - gem_flink \ - gem_readwrite \ - gem_mmap \ - $(NULL) -endif - check_PROGRAMS += $(TESTS) endif diff --git a/tests/gem_basic.c b/tests/gem_basic.c deleted file mode 100644 index 4e4b6cb..0000000 --- a/tests/gem_basic.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright © 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 (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. - * - * Authors: - * Eric Anholt <er...@an...> - * - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <fcntl.h> -#include <inttypes.h> -#include <errno.h> -#include <sys/stat.h> -#include "drm.h" -#include "i915_drm.h" - -static void -test_bad_close(int fd) -{ - struct drm_gem_close close; - int ret; - - printf("Testing error return on bad close ioctl.\n"); - - close.handle = 0x10101010; - ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close); - - assert(ret == -1 && errno == EINVAL); -} - -static void -test_create_close(int fd) -{ - struct drm_i915_gem_create create; - struct drm_gem_close close; - int ret; - - printf("Testing creating and closing an object.\n"); - - memset(&create, 0, sizeof(create)); - create.size = 16 * 1024; - ret = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create); - assert(ret == 0); - - close.handle = create.handle; - ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close); -} - -static void -test_create_fd_close(int fd) -{ - struct drm_i915_gem_create create; - int ret; - - printf("Testing closing with an object allocated.\n"); - - memset(&create, 0, sizeof(create)); - create.size = 16 * 1024; - ret = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create); - assert(ret == 0); - - close(fd); -} - -int main(int argc, char **argv) -{ - int fd; - - fd = drm_open_matching("8086:*", 0); - if (fd < 0) { - fprintf(stderr, "failed to open intel drm device\n"); - return 0; - } - - test_bad_close(fd); - test_create_close(fd); - test_create_fd_close(fd); - - return 0; -} diff --git a/tests/gem_flink.c b/tests/gem_flink.c deleted file mode 100644 index ce43e42..0000000 --- a/tests/gem_flink.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright © 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 (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. - * - * Authors: - * Eric Anholt <er...@an...> - * - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <fcntl.h> -#include <inttypes.h> -#include <errno.h> -#include <sys/stat.h> -#include "drm.h" -#include "i915_drm.h" - -static void -test_flink(int fd) -{ - struct drm_i915_gem_create create; - struct drm_gem_flink flink; - struct drm_gem_open open; - int ret; - - printf("Testing flink and open.\n"); - - memset(&create, 0, sizeof(create)); - create.size = 16 * 1024; - ret = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create); - assert(ret == 0); - - flink.handle = create.handle; - ret = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); - assert(ret == 0); - - open.name = flink.name; - ret = ioctl(fd, DRM_IOCTL_GEM_OPEN, &open); - assert(ret == 0); - assert(open.handle != 0); -} - -static void -test_double_flink(int fd) -{ - struct drm_i915_gem_create create; - struct drm_gem_flink flink; - struct drm_gem_flink flink2; - int ret; - - printf("Testing repeated flink.\n"); - - memset(&create, 0, sizeof(create)); - create.size = 16 * 1024; - ret = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create); - assert(ret == 0); - - flink.handle = create.handle; - ret = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); - assert(ret == 0); - - flink2.handle = create.handle; - ret = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink2); - assert(ret == 0); - assert(flink2.name == flink.name); -} - -static void -test_bad_flink(int fd) -{ - struct drm_gem_flink flink; - int ret; - - printf("Testing error return on bad flink ioctl.\n"); - - flink.handle = 0x10101010; - ret = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); - assert(ret == -1 && errno == ENOENT); -} - -static void -test_bad_open(int fd) -{ - struct drm_gem_open open; - int ret; - - printf("Testing error return on bad open ioctl.\n"); - - open.name = 0x10101010; - ret = ioctl(fd, DRM_IOCTL_GEM_OPEN, &open); - - assert(ret == -1 && errno == ENOENT); -} - -int main(int argc, char **argv) -{ - int fd; - - if (geteuid()) { - fprintf(stderr, "requires root privileges, skipping\n"); - return 77; - } - - fd = drm_open_matching("8086:*", 0); - if (fd < 0) { - fprintf(stderr, "failed to open intel drm device, skipping\n"); - return 77; - } - - test_flink(fd); - test_double_flink(fd); - test_bad_flink(fd); - test_bad_open(fd); - - return 0; -} diff --git a/tests/gem_mmap.c b/tests/gem_mmap.c deleted file mode 100644 index 2239789..0000000 --- a/tests/gem_mmap.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright © 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 (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. - * - * Authors: - * Eric Anholt <er...@an...> - * - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <fcntl.h> -#include <inttypes.h> -#include <errno.h> -#include <sys/stat.h> -#include "drm.h" -#include "i915_drm.h" - -#define OBJECT_SIZE 16384 - -int do_read(int fd, int handle, void *buf, int offset, int size) -{ - struct drm_i915_gem_pread read; - - /* Ensure that we don't have any convenient data in buf in case - * we fail. - */ - memset(buf, 0xd0, size); - - memset(&read, 0, sizeof(read)); - read.handle = handle; - read.data_ptr = (uintptr_t)buf; - read.size = size; - read.offset = offset; - - return ioctl(fd, DRM_IOCTL_I915_GEM_PREAD, &read); -} - -int do_write(int fd, int handle, void *buf, int offset, int size) -{ - struct drm_i915_gem_pwrite write; - - memset(&write, 0, sizeof(write)); - write.handle = handle; - write.data_ptr = (uintptr_t)buf; - write.size = size; - write.offset = offset; - - return ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &write); -} - -int main(int argc, char **argv) -{ - int fd; - struct drm_i915_gem_create create; - struct drm_i915_gem_mmap mmap; - struct drm_gem_close unref; - uint8_t expected[OBJECT_SIZE]; - uint8_t buf[OBJECT_SIZE]; - uint8_t *addr; - int ret; - int handle; - - fd = drm_open_matching("8086:*", 0); - if (fd < 0) { - fprintf(stderr, "failed to open intel drm device, skipping\n"); - return 0; - } - - memset(&mmap, 0, sizeof(mmap)); - mmap.handle = 0x10101010; - mmap.offset = 0; - mmap.size = 4096; - printf("Testing mmaping of bad object.\n"); - ret = ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &mmap); - assert(ret == -1 && errno == ENOENT); - - memset(&create, 0, sizeof(create)); - create.size = OBJECT_SIZE; - ret = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create); - assert(ret == 0); - handle = create.handle; - - printf("Testing mmaping of newly created object.\n"); - mmap.handle = handle; - mmap.offset = 0; - mmap.size = OBJECT_SIZE; - ret = ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &mmap); - assert(ret == 0); - addr = (uint8_t *)(uintptr_t)mmap.addr_ptr; - - printf("Testing contents of newly created object.\n"); - memset(expected, 0, sizeof(expected)); - assert(memcmp(addr, expected, sizeof(expected)) == 0); - - printf("Testing coherency of writes and mmap reads.\n"); - memset(buf, 0, sizeof(buf)); - memset(buf + 1024, 0x01, 1024); - memset(expected + 1024, 0x01, 1024); - ret = do_write(fd, handle, buf, 0, OBJECT_SIZE); - assert(ret == 0); - assert(memcmp(buf, addr, sizeof(buf)) == 0); - - printf("Testing that mapping stays after close\n"); - unref.handle = handle; - ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, &unref); - assert(ret == 0); - assert(memcmp(buf, addr, sizeof(buf)) == 0); - - printf("Testing unmapping\n"); - munmap(addr, OBJECT_SIZE); - - close(fd); - - return 0; -} diff --git a/tests/gem_readwrite.c b/tests/gem_readwrite.c deleted file mode 100644 index 07dc853..0000000 --- a/tests/gem_readwrite.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright © 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 (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. - * - * Authors: - * Eric Anholt <er...@an...> - * - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <fcntl.h> -#include <inttypes.h> -#include <errno.h> -#include <sys/stat.h> -#include "drm.h" -#include "i915_drm.h" - -#define OBJECT_SIZE 16384 - -int do_read(int fd, int handle, void *buf, int offset, int size) -{ - struct drm_i915_gem_pread read; - - /* Ensure that we don't have any convenient data in buf in case - * we fail. - */ - memset(buf, 0xd0, size); - - memset(&read, 0, sizeof(read)); - read.handle = handle; - read.data_ptr = (uintptr_t)buf; - read.size = size; - read.offset = offset; - - return ioctl(fd, DRM_IOCTL_I915_GEM_PREAD, &read); -} - -int do_write(int fd, int handle, void *buf, int offset, int size) -{ - struct drm_i915_gem_pwrite write; - - memset(&write, 0, sizeof(write)); - write.handle = handle; - write.data_ptr = (uintptr_t)buf; - write.size = size; - write.offset = offset; - - return ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &write); -} - -int main(int argc, char **argv) -{ - int fd; - struct drm_i915_gem_create create; - uint8_t expected[OBJECT_SIZE]; - uint8_t buf[OBJECT_SIZE]; - int ret; - int handle; - - fd = drm_open_matching("8086:*", 0); - if (fd < 0) { - fprintf(stderr, "failed to open intel drm device, skipping\n"); - return 0; - } - - memset(&create, 0, sizeof(create)); - create.size = OBJECT_SIZE; - ret = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create); - assert(ret == 0); - handle = create.handle; - - printf("Testing contents of newly created object.\n"); - ret = do_read(fd, handle, buf, 0, OBJECT_SIZE); - assert(ret == 0); - memset(&expected, 0, sizeof(expected)); - assert(memcmp(expected, buf, sizeof(expected)) == 0); - - printf("Testing read beyond end of buffer.\n"); - ret = do_read(fd, handle, buf, OBJECT_SIZE / 2, OBJECT_SIZE); - printf("%d %d\n", ret, errno); - assert(ret == -1 && errno == EINVAL); - - printf("Testing full write of buffer\n"); - memset(buf, 0, sizeof(buf)); - memset(buf + 1024, 0x01, 1024); - memset(expected + 1024, 0x01, 1024); - ret = do_write(fd, handle, buf, 0, OBJECT_SIZE); - assert(ret == 0); - ret = do_read(fd, handle, buf, 0, OBJECT_SIZE); - assert(ret == 0); - assert(memcmp(buf, expected, sizeof(buf)) == 0); - - printf("Testing partial write of buffer\n"); - memset(buf + 4096, 0x02, 1024); - memset(expected + 4096, 0x02, 1024); - ret = do_write(fd, handle, buf + 4096, 4096, 1024); - assert(ret == 0); - ret = do_read(fd, handle, buf, 0, OBJECT_SIZE); - assert(ret == 0); - assert(memcmp(buf, expected, sizeof(buf)) == 0); - - printf("Testing partial read of buffer\n"); - ret = do_read(fd, handle, buf, 512, 1024); - assert(ret == 0); - assert(memcmp(buf, expected + 512, 1024) == 0); - - printf("Testing read of bad buffer handle\n"); - ret = do_read(fd, 1234, buf, 0, 1024); - assert(ret == -1 && errno == ENOENT); - - printf("Testing write of bad buffer handle\n"); - ret = do_write(fd, 1234, buf, 0, 1024); - assert(ret == -1 && errno == ENOENT); - - close(fd); - - return 0; -} commit fd38794344f7211f45cc213344d0f5b9f9f98dd8 Author: Daniel Vetter <dan...@ff...> Date: Wed Feb 11 12:41:04 2015 +0100 xf86drm: Unconditionally clear ioctl structs We really have to do this to avoid surprises when extending the ABI later on. Especially when growing the structures. A bit overkill to update all the old legacy ioctl wrappers, but can't hurt really either. Reviewed-by: Emil Velikov <emi...@gm...> Reviewed-by: Rob Clark <rob...@gm...> Signed-off-by: Daniel Vetter <dan...@in...> diff --git a/xf86drm.c b/xf86drm.c index 263d683..a2e24eb 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -89,6 +89,8 @@ #define DRM_NODE_PRIMARY 1 #define DRM_NODE_RENDER 2 +#define memclear(s) memset(&s, 0, sizeof(s)) + static drmServerInfoPtr drm_server_info; void drmSetServerInfo(drmServerInfoPtr info) @@ -766,12 +768,7 @@ drmVersionPtr drmGetVersion(int fd) drmVersionPtr retval; drm_version_t *version = drmMalloc(sizeof(*version)); - version->name_len = 0; - version->name = NULL; - version->date_len = 0; - version->date = NULL; - version->desc_len = 0; - version->desc = NULL; + memclear(version); if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) { drmFreeKernelVersion(version); @@ -839,9 +836,12 @@ drmVersionPtr drmGetLibVersion(int fd) int drmGetCap(int fd, uint64_t capability, uint64_t *value) { - struct drm_get_cap cap = { capability, 0 }; + struct drm_get_cap cap; int ret; + memclear(cap); + cap.capability = capability; + ret = drmIoctl(fd, DRM_IOCTL_GET_CAP, &cap); if (ret) return ret; @@ -852,7 +852,11 @@ int drmGetCap(int fd, uint64_t capability, uint64_t *value) int drmSetClientCap(int fd, uint64_t capability, uint64_t value) { - struct drm_set_client_cap cap = { capability, value }; + struct drm_set_client_cap cap; + + memclear(cap); + cap.capability = capability; + cap.value = value; return drmIoctl(fd, DRM_IOCTL_SET_CLIENT_CAP, &cap); } @@ -887,8 +891,7 @@ char *drmGetBusid(int fd) { drm_unique_t u; - u.unique_len = 0; - u.unique = NULL; + memclear(u); if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL; @@ -917,6 +920,7 @@ int drmSetBusid(int fd, const char *busid) { drm_unique_t u; + memclear(u); u.unique = (char *)busid; u.unique_len = strlen(busid); @@ -930,6 +934,8 @@ int drmGetMagic(int fd, drm_magic_t * magic) { drm_auth_t auth; + memclear(auth); + *magic = 0; if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) return -errno; @@ -941,6 +947,7 @@ int drmAuthMagic(int fd, drm_magic_t magic) { drm_auth_t auth; + memclear(auth); auth.magic = magic; if (drmIoctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth)) return -errno; @@ -1002,9 +1009,9 @@ int drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type, { drm_map_t map; + memclear(map); map.offset = offset; map.size = size; - map.handle = 0; map.type = type; map.flags = flags; if (drmIoctl(fd, DRM_IOCTL_ADD_MAP, &map)) @@ -1018,6 +1025,7 @@ int drmRmMap(int fd, drm_handle_t handle) { drm_map_t map; + memclear(map); map.handle = (void *)(uintptr_t)handle; if(drmIoctl(fd, DRM_IOCTL_RM_MAP, &map)) @@ -1046,10 +1054,9 @@ int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags, { drm_buf_desc_t request; + memclear(request); request.count = count; request.size = size; - request.low_mark = 0; - request.high_mark = 0; request.flags = flags; request.agp_start = agp_offset; @@ -1063,8 +1070,7 @@ int drmMarkBufs(int fd, double low, double high) drm_buf_info_t info; int i; - info.count = 0; - info.list = NULL; + memclear(info); if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return -EINVAL; @@ -1114,6 +1120,7 @@ int drmFreeBufs(int fd, int count, int *list) { drm_buf_free_t request; + memclear(request); request.count = count; request.list = list; if (drmIoctl(fd, DRM_IOCTL_FREE_BUFS, &request)) @@ -1202,8 +1209,7 @@ drmBufInfoPtr drmGetBufInfo(int fd) drmBufInfoPtr retval; int i; - info.count = 0; - info.list = NULL; + memclear(info); if (drmIoctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return NULL; @@ -1253,9 +1259,7 @@ drmBufMapPtr drmMapBufs(int fd) drmBufMapPtr retval; int i; - bufs.count = 0; - bufs.list = NULL; - bufs.virtual = NULL; + memclear(bufs); if (drmIoctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) return NULL; @@ -1371,6 +1375,7 @@ int drmGetLock(int fd, drm_context_t context, drmLockFlags flags) { drm_lock_t lock; + memclear(lock); lock.context = context; lock.flags = 0; if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; @@ -1401,8 +1406,8 @@ int drmUnlock(int fd, drm_context_t context) { drm_lock_t lock; + memclear(lock); lock.context = context; - lock.flags = 0; return drmIoctl(fd, DRM_IOCTL_UNLOCK, &lock); } @@ -1413,8 +1418,7 @@ drm_context_t *drmGetReservedContextList(int fd, int *count) drm_context_t * retval; int i; - res.count = 0; - res.contexts = NULL; + memclear(res); if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL; @@ -1467,7 +1471,7 @@ int drmCreateContext(int fd, drm_context_t *handle) { drm_ctx_t ctx; - ctx.flags = 0; /* Modified with functions below */ + memclear(ctx); if (drmIoctl(fd, DRM_IOCTL_ADD_CTX, &ctx)) return -errno; *handle = ctx.handle; @@ -1478,6 +1482,7 @@ int drmSwitchToContext(int fd, drm_context_t context) { drm_ctx_t ctx; + memclear(ctx); ctx.handle = context; if (drmIoctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx)) return -errno; @@ -1494,8 +1499,8 @@ int drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags) * X server (which promises to maintain hardware context), or in the * client-side library when buffers are swapped on behalf of two threads. */ + memclear(ctx); ctx.handle = context; - ctx.flags = 0; if (flags & DRM_CONTEXT_PRESERVED) ctx.flags |= _DRM_CONTEXT_PRESERVED; if (flags & DRM_CONTEXT_2DONLY) @@ -1510,6 +1515,7 @@ int drmGetContextFlags(int fd, drm_context_t context, { drm_ctx_t ctx; + memclear(ctx); ctx.handle = context; if (drmIoctl(fd, DRM_IOCTL_GET_CTX, &ctx)) return -errno; @@ -1541,6 +1547,8 @@ int drmGetContextFlags(int fd, drm_context_t context, int drmDestroyContext(int fd, drm_context_t handle) { drm_ctx_t ctx; + + memclear(ctx); ctx.handle = handle; if (drmIoctl(fd, DRM_IOCTL_RM_CTX, &ctx)) return -errno; @@ -1550,6 +1558,8 @@ int drmDestroyContext(int fd, drm_context_t handle) int drmCreateDrawable(int fd, drm_drawable_t *handle) { drm_draw_t draw; + + memclear(draw); if (drmIoctl(fd, DRM_IOCTL_ADD_DRAW, &draw)) return -errno; *handle = draw.handle; @@ -1559,6 +1569,8 @@ int drmCreateDrawable(int fd, drm_drawable_t *handle) int drmDestroyDrawable(int fd, drm_drawable_t handle) { drm_draw_t draw; + + memclear(draw); draw.handle = handle; if (drmIoctl(fd, DRM_IOCTL_RM_DRAW, &draw)) return -errno; @@ -1571,6 +1583,7 @@ int drmUpdateDrawableInfo(int fd, drm_drawable_t handle, { drm_update_draw_t update; + memclear(update); update.handle = handle; update.type = type; update.num = num; @@ -1636,6 +1649,7 @@ int drmAgpEnable(int fd, unsigned long mode) { drm_agp_mode_t m; + memclear(mode); m.mode = mode; if (drmIoctl(fd, DRM_IOCTL_AGP_ENABLE, &m)) return -errno; @@ -1664,9 +1678,9 @@ int drmAgpAlloc(int fd, unsigned long size, unsigned long type, { drm_agp_buffer_t b; + memclear(b); *handle = DRM_AGP_NO_HANDLE; b.size = size; - b.handle = 0; b.type = type; if (drmIoctl(fd, DRM_IOCTL_AGP_ALLOC, &b)) return -errno; @@ -1693,7 +1707,7 @@ int drmAgpFree(int fd, drm_handle_t handle) { drm_agp_buffer_t b; - b.size = 0; + memclear(b); b.handle = handle; if (drmIoctl(fd, DRM_IOCTL_AGP_FREE, &b)) return -errno; @@ -1718,6 +1732,7 @@ int drmAgpBind(int fd, drm_handle_t handle, unsigned long offset) { drm_agp_binding_t b; + memclear(b); b.handle = handle; b.offset = offset; if (drmIoctl(fd, DRM_IOCTL_AGP_BIND, &b)) @@ -1742,8 +1757,8 @@ int drmAgpUnbind(int fd, drm_handle_t handle) { drm_agp_binding_t b; + memclear(b); b.handle = handle; - b.offset = 0; if (drmIoctl(fd, DRM_IOCTL_AGP_UNBIND, &b)) return -errno; return 0; @@ -1765,6 +1780,8 @@ int drmAgpVersionMajor(int fd) { drm_agp_info_t i; + memclear(i); + if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno; return i.agp_version_major; @@ -1786,6 +1803,8 @@ int drmAgpVersionMinor(int fd) { drm_agp_info_t i; + memclear(i); + if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno; return i.agp_version_minor; @@ -1807,6 +1826,8 @@ unsigned long drmAgpGetMode(int fd) { drm_agp_info_t i; + memclear(i); + if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; return i.mode; @@ -1828,6 +1849,8 @@ unsigned long drmAgpBase(int fd) { drm_agp_info_t i; + memclear(i); + if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; return i.aperture_base; @@ -1849,6 +1872,8 @@ unsigned long drmAgpSize(int fd) { drm_agp_info_t i; + memclear(i); + if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; return i.aperture_size; @@ -1870,6 +1895,8 @@ unsigned long drmAgpMemoryUsed(int fd) { drm_agp_info_t i; + memclear(i); + if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; return i.memory_used; @@ -1891,6 +1918,8 @@ unsigned long drmAgpMemoryAvail(int fd) { drm_agp_info_t i; + memclear(i); + if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; return i.memory_allowed; @@ -1912,6 +1941,8 @@ unsigned int drmAgpVendorId(int fd) { drm_agp_info_t i; + memclear(i); + if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; return i.id_vendor; @@ -1933,6 +1964,8 @@ unsigned int drmAgpDeviceId(int fd) { drm_agp_info_t i; + memclear(i); + if (drmIoctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; return i.id_device; @@ -1942,9 +1975,10 @@ int drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle) { drm_scatter_gather_t sg; + memclear(sg); + *handle = 0; sg.size = size; - sg.handle = 0; if (drmIoctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) return -errno; *handle = sg.handle; @@ -1955,7 +1989,7 @@ int drmScatterGatherFree(int fd, drm_handle_t handle) { drm_scatter_gather_t sg; - sg.size = 0; + memclear(sg); sg.handle = handle; if (drmIoctl(fd, DRM_IOCTL_SG_FREE, &sg)) return -errno; @@ -2046,6 +2080,7 @@ int drmCtlInstHandler(int fd, int irq) { drm_control_t ctl; + memclear(ctl); ctl.func = DRM_INST_HANDLER; ctl.irq = irq; if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl)) @@ -2069,6 +2104,7 @@ int drmCtlUninstHandler(int fd) { drm_control_t ctl; + memclear(ctl); ctl.func = DRM_UNINST_HANDLER; ctl.irq = 0; if (drmIoctl(fd, DRM_IOCTL_CONTROL, &ctl)) @@ -2080,8 +2116,8 @@ int drmFinish(int fd, int context, drmLockFlags flags) { drm_lock_t lock; + memclear(lock); lock.context = context; - lock.flags = 0; if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; @@ -2111,6 +2147,7 @@ int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum) { drm_irq_busid_t p; + memclear(p); p.busnum = busnum; p.devnum = devnum; p.funcnum = funcnum; @@ -2153,6 +2190,7 @@ int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, { drm_ctx_priv_map_t map; + memclear(map); map.ctx_id = ctx_id; map.handle = (void *)(uintptr_t)handle; @@ -2166,6 +2204,7 @@ int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, { drm_ctx_priv_map_t map; + memclear(map); map.ctx_id = ctx_id; if (drmIoctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map)) @@ -2182,6 +2221,7 @@ int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size, { drm_map_t map; + memclear(map); map.offset = idx; if (drmIoctl(fd, DRM_IOCTL_GET_MAP, &map)) return -errno; @@ -2199,6 +2239,7 @@ int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid, { drm_client_t client; + memclear(client); client.idx = idx; if (drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client)) return -errno; @@ -2215,6 +2256,7 @@ int drmGetStats(int fd, drmStatsT *stats) drm_stats_t s; unsigned i; + memclear(s); if (drmIoctl(fd, DRM_IOCTL_GET_STATS, &s)) return -errno; @@ -2352,6 +2394,7 @@ int drmSetInterfaceVersion(int fd, drmSetVersion *version) int retcode = 0; drm_set_version_t sv; + memclear(sv); sv.drm_di_major = version->drm_di_major; sv.drm_di_minor = version->drm_di_minor; sv.drm_dd_major = version->drm_dd_major; @@ -2383,12 +2426,11 @@ int drmSetInterfaceVersion(int fd, drmSetVersion *version) */ int drmCommandNone(int fd, unsigned long drmCommandIndex) { - void *data = NULL; /* dummy */ unsigned long request; request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex); - if (drmIoctl(fd, request, data)) { + if (drmIoctl(fd, request, NULL)) { return -errno; } return 0; @@ -2543,12 +2585,12 @@ void drmCloseOnce(int fd) int drmSetMaster(int fd) { - return drmIoctl(fd, DRM_IOCTL_SET_MASTER, 0); + return drmIoctl(fd, DRM_IOCTL_SET_MASTER, NULL); } int drmDropMaster(int fd) { - return drmIoctl(fd, DRM_IOCTL_DROP_MASTER, 0); + return drmIoctl(fd, DRM_IOCTL_DROP_MASTER, NULL); } char *drmGetDeviceNameFromFd(int fd) commit 80834b377e1b25c2d56c59a1984451b29eae6501 Author: Daniel Vetter <dan...@ff...> Date: Wed Feb 11 12:30:04 2015 +0100 drm: use drmIoctl everywhere Well just core drm. All the other callers in there that still use direct calls to ioctl have some custom retry logic already, so should be good already. All the other offenders (tests, freedreno/kgsl, ...) don't really matter (e.g. kgsl is the blob library and so not a drm thing) or are again special exceptions with their own retry loops. Reviewed-by: Emil Velikov <emi...@gm...> Reviewed-by: Rob Clark <rob...@gm...> Signed-off-by: Daniel Vetter <dan...@in...> diff --git a/xf86drm.c b/xf86drm.c index fb673b5..263d683 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -2543,12 +2543,12 @@ void drmCloseOnce(int fd) int drmSetMaster(int fd) { - return ioctl(fd, DRM_IOCTL_SET_MASTER, 0); + return drmIoctl(fd, DRM_IOCTL_SET_MASTER, 0); } int drmDropMaster(int fd) { - return ioctl(fd, DRM_IOCTL_DROP_MASTER, 0); + return drmIoctl(fd, DRM_IOCTL_DROP_MASTER, 0); } char *drmGetDeviceNameFromFd(int fd) commit 7e0460c6d4b509983307f3106ad56c6622c0c7f2 Author: Daniel Vetter <dan...@ff...> Date: Wed Feb 11 12:03:12 2015 +0100 xf86drmMode: Unconditionally clear ioctl structs We really have to do this to avoid surprises when extending the ABI later on. Especially when growing the structures. Reviewed-by: Emil Velikov <emi...@gm...> Reviewed-by: Rob Clark <rob...@gm...> Signed-off-by: Daniel Vetter <dan...@in...> diff --git a/xf86drmMode.c b/xf86drmMode.c index e3e599b..9ea8fe7 100644 --- a/xf86drmMode.c +++ b/xf86drmMode.c @@ -61,7 +61,7 @@ #define VG(x) #endif -#define VG_CLEAR(s) VG(memset(&s, 0, sizeof(s))) +#define memclear(s) memset(&s, 0, sizeof(s)) #define U642VOID(x) ((void *)(unsigned long)(x)) #define VOID2U64(x) ((uint64_t)(unsigned long)(x)) @@ -164,7 +164,7 @@ drmModeResPtr drmModeGetResources(int fd) drmModeResPtr r = 0; retry: - memset(&res, 0, sizeof(struct drm_mode_card_res)); + memclear(res); if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) return 0; @@ -259,7 +259,7 @@ int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, struct drm_mode_fb_cmd f; int ret; - VG_CLEAR(f); + memclear(f); f.width = width; f.height = height; f.pitch = pitch; @@ -282,6 +282,7 @@ int drmModeAddFB2(int fd, uint32_t width, uint32_t height, struct drm_mode_fb_cmd2 f; int ret; + memclear(f); f.width = width; f.height = height; f.pixel_format = pixel_format; @@ -300,8 +301,6 @@ int drmModeAddFB2(int fd, uint32_t width, uint32_t height, int drmModeRmFB(int fd, uint32_t bufferId) { return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId); - - } drmModeFBPtr drmModeGetFB(int fd, uint32_t buf) @@ -309,6 +308,7 @@ drmModeFBPtr drmModeGetFB(int fd, uint32_t buf) struct drm_mode_fb_cmd info; drmModeFBPtr r; + memclear(info); info.fb_id = buf; if (drmIoctl(fd, DRM_IOCTL_MODE_GETFB, &info)) @@ -331,8 +331,9 @@ drmModeFBPtr drmModeGetFB(int fd, uint32_t buf) int drmModeDirtyFB(int fd, uint32_t bufferId, drmModeClipPtr clips, uint32_t num_clips) { - struct drm_mode_fb_dirty_cmd dirty = { 0 }; + struct drm_mode_fb_dirty_cmd dirty; + memclear(dirty); dirty.fb_id = bufferId; dirty.clips_ptr = VOID2U64(clips); dirty.num_clips = num_clips; @@ -350,7 +351,7 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) struct drm_mode_crtc crtc; drmModeCrtcPtr r; - VG_CLEAR(crtc); + memclear(crtc); crtc.crtc_id = crtcId; if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc)) @@ -384,7 +385,7 @@ int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, { struct drm_mode_crtc crtc; - VG_CLEAR(crtc); + memclear(crtc); crtc.x = x; crtc.y = y; crtc.crtc_id = crtcId; @@ -394,8 +395,7 @@ int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, if (mode) { memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo)); crtc.mode_valid = 1; - } else - crtc.mode_valid = 0; + } return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc); } @@ -408,6 +408,7 @@ int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width { struct drm_mode_cursor arg; + memclear(arg); arg.flags = DRM_MODE_CURSOR_BO; arg.crtc_id = crtcId; arg.width = width; @@ -421,6 +422,7 @@ int drmModeSetCursor2(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t widt { struct drm_mode_cursor2 arg; + memclear(arg); arg.flags = DRM_MODE_CURSOR_BO; arg.crtc_id = crtcId; arg.width = width; @@ -436,6 +438,7 @@ int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y) { struct drm_mode_cursor arg; + memclear(arg); arg.flags = DRM_MODE_CURSOR_MOVE; arg.crtc_id = crtcId; arg.x = x; @@ -452,11 +455,8 @@ drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id) struct drm_mode_get_encoder enc; drmModeEncoderPtr r = NULL; + memclear(enc); enc.encoder_id = encoder_id; - enc.crtc_id = 0; - enc.encoder_type = 0; - enc.possible_crtcs = 0; - enc.possible_clones = 0; if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc)) return 0; @@ -483,7 +483,7 @@ drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id) drmModeConnectorPtr r = NULL; retry: - memset(&conn, 0, sizeof(struct drm_mode_get_connector)); + memclear(conn); conn.connector_id = connector_id; if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) @@ -576,6 +576,7 @@ int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_inf { struct drm_mode_mode_cmd res; + memclear(res); memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); res.connector_id = connector_id; @@ -586,6 +587,7 @@ int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_inf { struct drm_mode_mode_cmd res; + memclear(res); memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); res.connector_id = connector_id; @@ -598,13 +600,8 @@ drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id) struct drm_mode_get_property prop; drmModePropertyPtr r; - VG_CLEAR(prop); + memclear(prop); prop.prop_id = property_id; - prop.count_enum_blobs = 0; - prop.count_values = 0; - prop.flags = 0; - prop.enum_blob_ptr = 0; - prop.values_ptr = 0; if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) return 0; @@ -667,8 +664,7 @@ drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id) struct drm_mode_get_blob blob; drmModePropertyBlobPtr r; - blob.length = 0; - blob.data = 0; + memclear(blob); blob.blob_id = blob_id; if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) @@ -708,6 +704,7 @@ int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property { struct drm_mode_connector_set_property osp; + memclear(osp); osp.connector_id = connector_id; osp.prop_id = property_id; osp.value = value; @@ -818,6 +815,7 @@ int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, { struct drm_mode_crtc_lut l; + memclear(l); l.crtc_id = crtc_id; l.gamma_size = size; l.red = VOID2U64(red); @@ -832,6 +830,7 @@ int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, { struct drm_mode_crtc_lut l; + memclear(l); l.crtc_id = crtc_id; l.gamma_size = size; l.red = VOID2U64(red); @@ -897,11 +896,11 @@ int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, { struct drm_mode_crtc_page_flip flip; + memclear(flip); flip.fb_id = fb_id; flip.crtc_id = crtc_id; flip.user_data = VOID2U64(user_data); flip.flags = flags; - flip.reserved = 0; return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip); } @@ -916,6 +915,7 @@ int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id, { struct drm_mode_set_plane s; + memclear(s); s.plane_id = plane_id; s.crtc_id = crtc_id; s.fb_id = fb_id; @@ -939,7 +939,7 @@ drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id) drmModePlanePtr r = 0; retry: - memset(&ovr, 0, sizeof(struct drm_mode_get_plane)); + memclear(ovr); ovr.plane_id = plane_id; if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANE, &ovr)) return 0; @@ -999,7 +999,7 @@ drmModePlaneResPtr drmModeGetPlaneResources(int fd) drmModePlaneResPtr r = 0; retry: - memset(&res, 0, sizeof(struct drm_mode_get_plane_res)); + memclear(res); if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &res)) return 0; @@ -1056,7 +1056,7 @@ drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd, uint32_t count; retry: - memset(&properties, 0, sizeof(struct drm_mode_obj_get_properties)); + memclear(properties); properties.obj_id = object_id; properties.obj_type = object_type; @@ -1122,6 +1122,7 @@ int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type, { struct drm_mode_obj_set_property prop; + memclear(prop); prop.value = value; prop.prop_id = property_id; prop.obj_id = object_id; commit eb7a5b6b04271af3b11b81baa8e18dc826b657dc Author: Daniel Vetter <dan...@ff...> Date: Wed Feb 11 11:59:52 2015 +0100 intel: Unconditionally clear ioctl structs We really have to do this to avoid surprises when extending the ABI later on. Especially when growing the structures. Reviewed-by: Emil Velikov <emi...@gm...> Reviewed-by: Rob Clark <rob...@gm...> Signed-off-by: Daniel Vetter <dan...@in...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index cf85bb8..78875fd 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -74,7 +74,7 @@ #define VG(x) #endif -#define VG_CLEAR(s) VG(memset(&s, 0, sizeof(s))) +#define memclear(s) memset(&s, 0, sizeof(s)) #define DBG(...) do { \ if (bufmgr_gem->bufmgr.debug) \ @@ -593,7 +593,7 @@ drm_intel_gem_bo_busy(drm_intel_bo *bo) if (bo_gem->reusable && bo_gem->idle) return false; - VG_CLEAR(busy); + memclear(busy); busy.handle = bo_gem->gem_handle; ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy); @@ -612,7 +612,7 @@ drm_intel_gem_bo_madvise_internal(drm_intel_bufmgr_gem *bufmgr_gem, { struct drm_i915_gem_madvise madv; - VG_CLEAR(madv); + memclear(madv); madv.handle = bo_gem->gem_handle; madv.madv = state; madv.retained = 1; @@ -741,7 +741,7 @@ retry: bo_gem->bo.size = bo_size; - VG_CLEAR(create); + memclear(create); create.size = bo_size; ret = drmIoctl(bufmgr_gem->fd, @@ -888,7 +888,7 @@ drm_intel_gem_bo_alloc_userptr(drm_intel_bufmgr *bufmgr, bo_gem->bo.size = size; - VG_CLEAR(userptr); + memclear(userptr); userptr.user_ptr = (__u64)((unsigned long)addr); userptr.user_size = size; userptr.flags = flags; @@ -972,7 +972,7 @@ drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr, } } - VG_CLEAR(open_arg); + memclear(open_arg); open_arg.name = handle; ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_OPEN, @@ -1017,7 +1017,7 @@ drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr, bo_gem->global_name = handle; bo_gem->reusable = false; - VG_CLEAR(get_tiling); + memclear(get_tiling); get_tiling.handle = bo_gem->gem_handle; ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_GET_TILING, @@ -1060,7 +1060,7 @@ drm_intel_gem_bo_free(drm_intel_bo *bo) } /* Close this object */ - VG_CLEAR(close); + memclear(close); close.handle = bo_gem->gem_handle; ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close); if (ret != 0) { @@ -1292,9 +1292,8 @@ static int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable) DBG("bo_map: %d (%s), map_count=%d\n", bo_gem->gem_handle, bo_gem->name, bo_gem->map_count); - VG_CLEAR(mmap_arg); + memclear(mmap_arg); mmap_arg.handle = bo_gem->gem_handle; - mmap_arg.offset = 0; mmap_arg.size = bo->size; ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MMAP, @@ -1316,7 +1315,7 @@ static int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable) bo_gem->mem_virtual); bo->virtual = bo_gem->mem_virtual; - VG_CLEAR(set_domain); + memclear(set_domain); set_domain.handle = bo_gem->gem_handle; set_domain.read_domains = I915_GEM_DOMAIN_CPU; if (write_enable) @@ -1362,7 +1361,7 @@ map_gtt(drm_intel_bo *bo) DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n", bo_gem->gem_handle, bo_gem->name, bo_gem->map_count); - VG_CLEAR(mmap_arg); + memclear(mmap_arg); mmap_arg.handle = bo_gem->gem_handle; /* Get the fake offset back... */ @@ -1430,7 +1429,7 @@ drm_intel_gem_bo_map_gtt(drm_intel_bo *bo) * tell it when we're about to use things if we had done * rendering and it still happens to be bound to the GTT. */ - VG_CLEAR(set_domain); + memclear(set_domain); set_domain.handle = bo_gem->gem_handle; set_domain.read_domains = I915_GEM_DOMAIN_GTT; set_domain.write_domain = I915_GEM_DOMAIN_GTT; @@ -1529,7 +1528,7 @@ static int drm_intel_gem_bo_unmap(drm_intel_bo *bo) * Unlike GTT set domains, this only does work if the * buffer should be scanout-related. */ - VG_CLEAR(sw_finish); + memclear(sw_finish); sw_finish.handle = bo_gem->gem_handle; ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SW_FINISH, @@ -1571,7 +1570,7 @@ drm_intel_gem_bo_subdata(drm_intel_bo *bo, unsigned long offset, if (bo_gem->is_userptr) return -EINVAL; - VG_CLEAR(pwrite); + memclear(pwrite); pwrite.handle = bo_gem->gem_handle; pwrite.offset = offset; pwrite.size = size; @@ -1596,7 +1595,7 @@ drm_intel_gem_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id) struct drm_i915_get_pipe_from_crtc_id get_pipe_from_crtc_id; int ret; - VG_CLEAR(get_pipe_from_crtc_id); + memclear(get_pipe_from_crtc_id); get_pipe_from_crtc_id.crtc_id = crtc_id; ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID, @@ -1626,7 +1625,7 @@ drm_intel_gem_bo_get_subdata(drm_intel_bo *bo, unsigned long offset, if (bo_gem->is_userptr) return -EINVAL; - VG_CLEAR(pread); + memclear(pread); pread.handle = bo_gem->gem_handle; pread.offset = offset; pread.size = size; @@ -1694,9 +1693,9 @@ drm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns) } } + memclear(wait); wait.bo_handle = bo_gem->gem_handle; wait.timeout_ns = timeout_ns; - wait.flags = 0; ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_WAIT, &wait); if (ret == -1) return -errno; @@ -1719,7 +1718,7 @@ drm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable) struct drm_i915_gem_set_domain set_domain; int ret; - VG_CLEAR(set_domain); + memclear(set_domain); set_domain.handle = bo_gem->gem_handle; set_domain.read_domains = I915_GEM_DOMAIN_GTT; set_domain.write_domain = write_enable ? I915_GEM_DOMAIN_GTT : 0; @@ -2339,7 +2338,7 @@ drm_intel_gem_bo_exec(drm_intel_bo *bo, int used, */ drm_intel_add_validate_buffer(bo); - VG_CLEAR(execbuf); + memclear(execbuf); execbuf.buffers_ptr = (uintptr_t) bufmgr_gem->exec_objects; execbuf.buffer_count = bufmgr_gem->exec_count; execbuf.batch_start_offset = 0; @@ -2426,7 +2425,7 @@ do_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx, */ drm_intel_add_validate_buffer2(bo, 0); - VG_CLEAR(execbuf); + memclear(execbuf); execbuf.buffers_ptr = (uintptr_t)bufmgr_gem->exec2_objects; execbuf.buffer_count = bufmgr_gem->exec_count; execbuf.batch_start_offset = 0; @@ -2517,7 +2516,7 @@ drm_intel_gem_bo_pin(drm_intel_bo *bo, uint32_t alignment) struct drm_i915_gem_pin pin; int ret; - VG_CLEAR(pin); + memclear(pin); pin.handle = bo_gem->gem_handle; pin.alignment = alignment; @@ -2540,7 +2539,7 @@ drm_intel_gem_bo_unpin(drm_intel_bo *bo) struct drm_i915_gem_unpin unpin; int ret; - VG_CLEAR(unpin); + memclear(unpin); unpin.handle = bo_gem->gem_handle; ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_UNPIN, &unpin); @@ -2696,7 +2695,7 @@ drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int s DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named); pthread_mutex_unlock(&bufmgr_gem->lock); - VG_CLEAR(get_tiling); + memclear(get_tiling); get_tiling.handle = bo_gem->gem_handle; ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_GET_TILING, @@ -2743,7 +2742,7 @@ drm_intel_gem_bo_flink(drm_intel_bo *bo, uint32_t * name) if (!bo_gem->global_name) { struct drm_gem_flink flink; - VG_CLEAR(flink); + memclear(flink); flink.handle = bo_gem->gem_handle; pthread_mutex_lock(&bufmgr_gem->lock); @@ -3078,7 +3077,7 @@ static int get_pci_device_id(drm_intel_bufmgr_gem *bufmgr_gem) { char *devid_override; - int devid; + int devid = 0; int ret; drm_i915_getparam_t gp; @@ -3090,8 +3089,7 @@ get_pci_device_id(drm_intel_bufmgr_gem *bufmgr_gem) } } - VG_CLEAR(devid); - VG_CLEAR(gp); + memclear(gp); gp.param = I915_PARAM_CHIPSET_ID; gp.value = &devid; ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); @@ -3204,7 +3202,7 @@ drm_intel_gem_context_create(drm_intel_bufmgr *bufmgr) if (!context) return NULL; - VG_CLEAR(create); + memclear(create); ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create); if (ret != 0) { DBG("DRM_IOCTL_I915_GEM_CONTEXT_CREATE failed: %s\n", @@ -3229,7 +3227,7 @@ drm_intel_gem_context_destroy(drm_intel_context *ctx) if (ctx == NULL) return; - VG_CLEAR(destroy); + memclear(destroy); bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr; destroy.ctx_id = ctx->ctx_id; @@ -3255,7 +3253,7 @@ drm_intel_get_reset_stats(drm_intel_context *ctx, if (ctx == NULL) return -EINVAL; - memset(&stats, 0, sizeof(stats)); + memclear(stats); bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr; stats.ctx_id = ctx->ctx_id; @@ -3285,7 +3283,7 @@ drm_intel_reg_read(drm_intel_bufmgr *bufmgr, struct drm_i915_reg_read reg_read; int ret; - VG_CLEAR(reg_read); + memclear(reg_read); reg_read.offset = offset; ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_REG_READ, ®_read); @@ -3390,7 +3388,7 @@ has_userptr(drm_intel_bufmgr_gem *bufmgr_gem) return false; } - memset(&userptr, 0, sizeof(userptr)); + memclear(userptr); userptr.user_ptr = (__u64)(unsigned long)ptr; userptr.user_size = pgsz; @@ -3405,6 +3403,7 @@ retry: return false; } + memclear(close_bo); close_bo.handle = userptr.handle; ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close_bo); free(ptr); @@ -3451,6 +3450,7 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size) goto exit; } + memclear(aperture); ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture); @@ -3500,7 +3500,7 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size) bufmgr_gem->gtt_size -= 256*1024*1024; } - VG_CLEAR(gp); + memclear(gp); gp.value = &tmp; gp.param = I915_PARAM_HAS_EXECBUF2; |
From: <eve...@ke...> - 2015-03-17 23:05:46
|
autogen.sh | 16 +++++-- configure.ac | 119 ++++++++++++++++++++++++++++------------------------------- 2 files changed, 69 insertions(+), 66 deletions(-) New commits: commit d20413a7ce5816abe1127ffffc5bcab82f268c16 Author: Emil Velikov <emi...@gm...> Date: Tue Mar 17 00:19:27 2015 +0000 configure.ac: error out if building freedreno_kgsl without freedreno The former is a subset of the latter. Error out early so the user is aware that they are doing something very wrong. Cc: Rob Clark <rob...@gm...> Signed-off-by: Emil Velikov <emi...@gm...> Reviewed-by: Rob Clark <rob...@gm...> diff --git a/configure.ac b/configure.ac index 7f76083..6e45fa8 100644 --- a/configure.ac +++ b/configure.ac @@ -321,6 +321,11 @@ if test "x$FREEDRENO" = xyes; then AC_DEFINE(HAVE_FREEDRENO, 1, [Have freedreno support]) fi +if test "x$FREEDRENO_KGSL" = xyes; then + if test "x$FREEDRENO" != xyes; then + AC_MSG_ERROR([Cannot enable freedreno KGSL interface if freedreno is disabled]) + fi +fi AM_CONDITIONAL(HAVE_FREEDRENO_KGSL, [test "x$FREEDRENO_KGSL" = xyes]) if test "x$FREEDRENO_KGSL" = xyes; then AC_DEFINE(HAVE_FREEDRENO_KGSL, 1, [Have freedreno support for KGSL kernel interface]) commit 648508518ef4f199eee58dbca8d6412af989fe71 Author: Emil Velikov <emi...@gm...> Date: Tue Mar 17 00:19:26 2015 +0000 configure.ac: fix help string copy/pasta The message "enabled on x86" was meant for the intel libdrm. Take the opportunity to mention how libkms is autodetected. Signed-off-by: Emil Velikov <emi...@gm...> diff --git a/configure.ac b/configure.ac index 414383c..7f76083 100644 --- a/configure.ac +++ b/configure.ac @@ -61,12 +61,12 @@ AC_ARG_ENABLE([udev], AC_ARG_ENABLE(libkms, AS_HELP_STRING([--disable-libkms], - [Disable KMS mm abstraction library (default: auto, enabled on x86]), + [Disable KMS mm abstraction library (default: auto, enabled on supported platforms)]), [LIBKMS=$enableval], [LIBKMS=auto]) AC_ARG_ENABLE(intel, AS_HELP_STRING([--disable-intel], - [Enable support for intel's KMS API (default: auto)]), + [Enable support for intel's KMS API (default: auto, enabled on x86)]), [INTEL=$enableval], [INTEL=auto]) AC_ARG_ENABLE(radeon, commit 0e4d5a3a460fd00358132fd4b2391a093c5fe8dd Author: Emil Velikov <emi...@gm...> Date: Tue Mar 17 00:19:25 2015 +0000 configure.ac: fix host_cpu/atomics detection Previous code was busted, as it wasn't checking directly for what it was meant to, and at the end changing the user's selection if host_cpu heuristics were involved. Simplify things by adding a macro that does the long message printing for us, and check for only what we need. This fixes commit 36cff14bb03(configure: omap, freedreno and tegra require atomics) which incorrectly assumed that the code was working fine, and effectively made impossible to enable freedreno due to it's host_cpu detection. Cc: Rob Clark <rob...@gm...> Signed-off-by: Emil Velikov <emi...@gm...> diff --git a/configure.ac b/configure.ac index 0b37cc7..414383c 100644 --- a/configure.ac +++ b/configure.ac @@ -215,65 +215,56 @@ if test "x$drm_cv_atomic_primitives" = "xlibatomic-ops"; then AC_DEFINE(HAVE_LIB_ATOMIC_OPS, 1, [Enable if you have libatomic-ops-dev installed]) fi -if test "x$INTEL" != "xno" -o \ - "x$RADEON" != "xno" -o \ - "x$NOUVEAU" != "xno" -o \ - "x$OMAP" != "xno" -o \ - "x$FREEDRENO" != "xno" -o \ - "x$TEGRA" != "xno"; then - if test "x$drm_cv_atomic_primitives" = "xnone"; then - if test "x$INTEL" != "xauto"; then - if test "x$INTEL" != "xno"; then - AC_MSG_ERROR([libdrm_intel depends upon atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package, or, failing both of those, disable support for Intel GPUs by passing --disable-intel to ./configure]) - fi - else - AC_MSG_WARN([Disabling libdrm_intel. It depends on atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package.]) - INTEL=no - fi - if test "x$RADEON" != "xauto"; then - if test "x$RADEON" != "xno"; then - AC_MSG_ERROR([libdrm_radeon depends upon atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package, or, failing both of those, disable support for Radeon GPUs by passing --disable-radeon to ./configure]) - fi - else - AC_MSG_WARN([Disabling libdrm_radeon. It depends on atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package.]) - RADEON=no - fi - if test "x$NOUVEAU" != "xauto"; then - if test "x$NOUVEAU" != "xno"; then - AC_MSG_ERROR([libdrm_nouveau depends upon atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package, or, failing both of those, disable support for NVIDIA GPUs by passing --disable-nouveau to ./configure]) - fi - else - AC_MSG_WARN([Disabling libdrm_nouveau. It depends on atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package.]) - NOUVEAU=no - fi - if test "x$OMAP" != "xauto"; then - AC_MSG_ERROR([libdrm_omap depends upon atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package, or, failing both of those, disable support for OMAP GPUs by passing --disable-omap-experimental-api to ./configure]) - fi - if test "x$FREEDRENO" != "xauto"; then - AC_MSG_ERROR([libdrm_freedreno depends upon atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package, or, failing both of those, disable support for QCOM's Adreno GPUs by passing --disable-freedreno to ./configure]) - fi - if test "x$TEGRA" != "xauto"; then - AC_MSG_ERROR([libdrm_tegra depends upon atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package, or, failing both of those, disable support for NVIDIA's Tegra GPUs by passing --disable-tegra-experimental-api to ./configure]) - fi - else - if test "x$INTEL" != "xno"; then - case $host_cpu in - i?86|x86_64) INTEL=yes ;; - *) INTEL=no ;; - esac - fi - if test "x$RADEON" != "xno"; then - RADEON=yes - fi - if test "x$NOUVEAU" != "xno"; then - NOUVEAU=yes - fi - if test "x$FREEDRENO" != "xno"; then - case $host_cpu in - arm*|aarch64) FREEDRENO=yes ;; - *) FREEDRENO=no ;; - esac - fi +dnl Print out the approapriate message considering the value set be the +dnl respective in $1. +dnl $1 - value to be evaluated. Eg. $INTEL, $NOUVEAU, ... +dnl $2 - libdrm shortname. Eg. intel, freedreno, ... +dnl $3 - GPU name/brand. Eg. Intel, NVIDIA Tegra, ... +dnl $4 - Configure switch. Eg. intel, omap-experimental-api, ... +AC_DEFUN([LIBDRM_ATOMICS_NOT_FOUND_MSG], [ + case "x$1" in + xyes) AC_MSG_ERROR([libdrm_$2 depends upon atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package, or, failing both of those, disable support for $3 GPUs by passing --disable-$4 to ./configure]) ;; + xauto) AC_MSG_WARN([Disabling $2. It depends on atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package.]) ;; + *) ;; + esac +]) + +if test "x$drm_cv_atomic_primitives" = "xnone"; then + LIBDRM_ATOMICS_NOT_FOUND_MSG($INTEL, intel, Intel, intel) + INTEL=no + + LIBDRM_ATOMICS_NOT_FOUND_MSG($RADEON, radeon, Radeon, radeon) + RADEON=no + + LIBDRM_ATOMICS_NOT_FOUND_MSG($NOUVEAU, nouveau, NVIDIA, nouveau) + NOUVEAU=no + + LIBDRM_ATOMICS_NOT_FOUND_MSG($OMAP, omap, OMAP, omap-experimental-api) + OMAP=no + + LIBDRM_ATOMICS_NOT_FOUND_MSG($FREEDRENO, freedreno, Qualcomm Adreno, freedreno) + FREEDRENO=no + + LIBDRM_ATOMICS_NOT_FOUND_MSG($TEGRA, tegra, NVIDIA Tegra, tegra-experimental-api) + TEGRA=no +else + if test "x$INTEL" = xauto; then + case $host_cpu in + i?86|x86_64) INTEL=yes ;; + *) INTEL=no ;; + esac + fi + if test "x$RADEON" = xauto; then + RADEON=yes + fi + if test "x$NOUVEAU" = xauto; then + NOUVEAU=yes + fi + if test "x$FREEDRENO" = xauto; then + case $host_cpu in + arm*|aarch64) FREEDRENO=yes ;; + *) FREEDRENO=no ;; + esac fi fi commit ffb1e285306ae58f2861debb615047ca384710ba Author: Emil Velikov <emi...@gm...> Date: Mon Mar 9 12:08:17 2015 +0000 autogen.sh: handle out-of-tree invokation Signed-off-by: Emil Velikov <emi...@gm...> diff --git a/autogen.sh b/autogen.sh index 30d679f..c896097 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,6 +1,14 @@ #! /bin/sh -test -n "$srcdir" || srcdir=`dirname "$0"` -test -n "$srcdir" || srcdir=. -autoreconf --force --install --verbose "$srcdir" -test -n "$NOCONFIGURE" || "$srcdir/configure" "$@" +srcdir=`dirname "$0"` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd "$srcdir" + +autoreconf --force --verbose --install || exit 1 +cd "$ORIGDIR" || exit $? + +if test -z "$NOCONFIGURE"; then + "$srcdir"/configure "$@" +fi commit d8ea64d90b222b468c292d2c107a41a64ad5ce43 Author: Emil Velikov <emi...@gm...> Date: Mon Mar 9 12:08:16 2015 +0000 configure: Stop using AM_MAINTAINER_MODE AM_MAINTAINER_MODE can be used to disable generation of rebuild rules. This is not something we want to condone/support, considering it can cause greater problems than the perceived benefits. Additionally the Automake manual leans towards avoiding the use of AM_MAINTAINER_MODE. http://www.gnu.org/software/automake/manual/html_node/maintainer_002dmode.html Signed-off-by: Emil Velikov <emi...@gm...> diff --git a/autogen.sh b/autogen.sh index 3f190ba..30d679f 100755 --- a/autogen.sh +++ b/autogen.sh @@ -3,4 +3,4 @@ test -n "$srcdir" || srcdir=`dirname "$0"` test -n "$srcdir" || srcdir=. autoreconf --force --install --verbose "$srcdir" -test -n "$NOCONFIGURE" || "$srcdir/configure" --enable-maintainer-mode "$@" +test -n "$NOCONFIGURE" || "$srcdir/configure" "$@" diff --git a/configure.ac b/configure.ac index 1fd0818..0b37cc7 100644 --- a/configure.ac +++ b/configure.ac @@ -30,7 +30,6 @@ AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([1.10 foreign dist-bzip2]) -AM_MAINTAINER_MODE([enable]) # Enable quiet compiles on automake 1.11. m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) |
From: <eve...@ke...> - 2016-01-26 22:07:56
|
configure.ac | 2 - tests/kms/kms-steal-crtc.c | 3 ++ tests/kms/kms-universal-planes.c | 3 ++ tests/kmstest/Makefile.am | 4 ++- tests/kmstest/main.c | 45 +++++++++++++++++++++++++-------------- tests/modetest/modetest.c | 7 ++++-- tests/proptest/proptest.c | 2 - tests/util/kms.c | 1 tests/vbltest/vbltest.c | 7 ++++-- 9 files changed, 51 insertions(+), 23 deletions(-) New commits: commit ff0c9caa8e1e076b82241304dfd19d5b3e2a2aec Author: Kylie McClain <so...@ex...> Date: Tue Jan 19 22:27:28 2016 -0500 tests: Include poll.h rather than sys/poll.h sys/poll.h is a non-standard location of the poll.h header, and is incorrect on non-glibc libcs. poll.h, however, is defined in SUS (v2) and is more portable. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93764 http://pubs.opengroup.org/onlinepubs/007908799/xsh/poll.h.html Signed-off-by: Emil Velikov <emi...@gm...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index b8aa94b..a5ac5bd 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -53,7 +53,7 @@ #include <string.h> #include <strings.h> #include <errno.h> -#include <sys/poll.h> +#include <poll.h> #include <sys/time.h> #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c index 97dd44d..3f6b803 100644 --- a/tests/vbltest/vbltest.c +++ b/tests/vbltest/vbltest.c @@ -35,7 +35,7 @@ #include <unistd.h> #include <string.h> #include <errno.h> -#include <sys/poll.h> +#include <poll.h> #include <sys/time.h> #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> commit 358615f416a8f3085a63c03a55564f71946083d1 Author: Khem Raj <raj...@gm...> Date: Wed Jan 20 05:35:11 2016 +0000 tests: Include sys/select.h Used in compliance with POSIX 2001/2008 Fixes errors e.g. error: implicit declaration of function 'select' and helps with missing definitions of FD_* defines v2: conditionally include sys/select.h, include in every test where needed. Signed-off-by: Khem Raj <raj...@gm...> Reviewed-by: Thierry Reding <thi...@gm...> (v1) Reviewed-by: Emil Velikov <emi...@gm...> diff --git a/configure.ac b/configure.ac index a09be61..4635d18 100644 --- a/configure.ac +++ b/configure.ac @@ -53,7 +53,7 @@ AC_USE_SYSTEM_EXTENSIONS AC_SYS_LARGEFILE AC_FUNC_ALLOCA -AC_CHECK_HEADERS([sys/mkdev.h sys/sysctl.h]) +AC_CHECK_HEADERS([sys/mkdev.h sys/sysctl.h sys/select.h]) # Initialize libtool LT_PREREQ([2.2]) diff --git a/tests/kms/kms-steal-crtc.c b/tests/kms/kms-steal-crtc.c index 2f7f327..497772e 100644 --- a/tests/kms/kms-steal-crtc.c +++ b/tests/kms/kms-steal-crtc.c @@ -31,6 +31,9 @@ #include <stdio.h> #include <string.h> #include <unistd.h> +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif #include <drm_fourcc.h> diff --git a/tests/kms/kms-universal-planes.c b/tests/kms/kms-universal-planes.c index 9151231..d8e5fc4 100644 --- a/tests/kms/kms-universal-planes.c +++ b/tests/kms/kms-universal-planes.c @@ -32,6 +32,9 @@ #include <stdio.h> #include <string.h> #include <unistd.h> +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif #include <drm_fourcc.h> #include "xf86drm.h" diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index f665240..b8aa94b 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -55,6 +55,9 @@ #include <errno.h> #include <sys/poll.h> #include <sys/time.h> +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif #include "xf86drm.h" #include "xf86drmMode.h" diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c index 4475b49..97dd44d 100644 --- a/tests/vbltest/vbltest.c +++ b/tests/vbltest/vbltest.c @@ -37,6 +37,9 @@ #include <errno.h> #include <sys/poll.h> #include <sys/time.h> +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif #include "xf86drm.h" #include "xf86drmMode.h" commit 1674147a149c2165a927a5d8eb0db4eee1f6a4e3 Author: Thierry Reding <tr...@nv...> Date: Tue Jan 5 15:21:23 2016 +0100 tests: util: Fixup util_open() parameter order util_open() takes a device parameter, followed by a module parameter. The existing tests used the drmOpen() function, which uses a different ordering of the parameters, and the old ordering was accidentally kept during the conversion. Signed-off-by: Thierry Reding <tr...@nv...> Reviewed-by: Emil Velikov <emi...@gm...> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 22e3e81..f665240 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -1603,7 +1603,7 @@ int main(int argc, char **argv) if (!args) encoders = connectors = crtcs = planes = framebuffers = 1; - dev.fd = util_open(module, device); + dev.fd = util_open(device, module); if (dev.fd < 0) return -1; diff --git a/tests/proptest/proptest.c b/tests/proptest/proptest.c index 24c6345..4bd0866 100644 --- a/tests/proptest/proptest.c +++ b/tests/proptest/proptest.c @@ -295,7 +295,7 @@ int main(int argc, char *argv[]) args = argc - optind; - fd = util_open(module, device); + fd = util_open(device, module); if (fd < 0) return 1; diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c index 1833321..4475b49 100644 --- a/tests/vbltest/vbltest.c +++ b/tests/vbltest/vbltest.c @@ -120,7 +120,7 @@ int main(int argc, char **argv) } } - fd = util_open(module, device); + fd = util_open(device, module); if (fd < 0) return 1; commit 2ad5ea780b3cca83ae4f531ae0b4159e802ef825 Author: Stefan Agner <st...@ag...> Date: Sat Dec 19 21:52:59 2015 -0800 tests: add fsl-dcu-drm to modules Signed-off-by: Stefan Agner <st...@ag...> Reviewed-by: Emil Velikov <emi...@gm...> diff --git a/tests/util/kms.c b/tests/util/kms.c index 57b0191..dcd5a8e 100644 --- a/tests/util/kms.c +++ b/tests/util/kms.c @@ -139,6 +139,7 @@ static const char * const modules[] = { "imx-drm", "rockchip", "atmel-hlcdc", + "fsl-dcu-drm", }; int util_open(const char *device, const char *module) commit 0caf58a6cb82327a3f6a53f05dea8e02f1412a05 Author: Stefan Agner <st...@ag...> Date: Sat Dec 19 21:52:58 2015 -0800 kmstest: Use util_open() Use the new util_open() helper instead of open-coding the method for finding a usable device. While at it, make the command-line interface more consistent with that of modetest by adding the -D and -M options. Signed-off-by: Stefan Agner <st...@ag...> v2: correctly use util_open() - swap device, module Signed-off-by: Emil Velikov <emi...@gm...> diff --git a/tests/kmstest/Makefile.am b/tests/kmstest/Makefile.am index fd21e61..100662e 100644 --- a/tests/kmstest/Makefile.am +++ b/tests/kmstest/Makefile.am @@ -2,6 +2,7 @@ AM_CFLAGS = \ $(WARN_CFLAGS)\ -I$(top_srcdir)/include/drm \ -I$(top_srcdir)/libkms/ \ + -I$(top_srcdir)/tests/ \ -I$(top_srcdir) if HAVE_INSTALL_TESTS @@ -17,7 +18,8 @@ kmstest_SOURCES = \ kmstest_LDADD = \ $(top_builddir)/libdrm.la \ - $(top_builddir)/libkms/libkms.la + $(top_builddir)/libkms/libkms.la \ + $(top_builddir)/tests/util/libutil.la run: kmstest ./kmstest diff --git a/tests/kmstest/main.c b/tests/kmstest/main.c index 120bc0f..a0e4ebb 100644 --- a/tests/kmstest/main.c +++ b/tests/kmstest/main.c @@ -25,12 +25,14 @@ * **************************************************************************/ - +#include <getopt.h> #include <stdio.h> #include <string.h> #include "xf86drm.h" #include "libkms.h" +#include "util/kms.h" + #define CHECK_RET_RETURN(ret, str) \ if (ret < 0) { \ printf("%s: %s (%s)\n", __func__, str, strerror(-ret)); \ @@ -56,26 +58,37 @@ static int test_bo(struct kms_driver *kms) return 0; } -static const char *drivers[] = { - "i915", - "radeon", - "nouveau", - "vmwgfx", - "exynos", - "amdgpu", - "imx-drm", - "rockchip", - "atmel-hlcdc", - NULL -}; +static void usage(const char *program) +{ + fprintf(stderr, "Usage: %s [options]\n", program); + fprintf(stderr, "\n"); + fprintf(stderr, " -D DEVICE open the given device\n"); + fprintf(stderr, " -M MODULE open the given module\n"); +} int main(int argc, char** argv) { + static const char optstr[] = "D:M:"; struct kms_driver *kms; - int ret, fd, i; + int c, fd, ret; + char *device = NULL; + char *module = NULL; + + while ((c = getopt(argc, argv, optstr)) != -1) { + switch (c) { + case 'D': + device = optarg; + break; + case 'M': + module = optarg; + break; + default: + usage(argv[0]); + return 0; + } + } - for (i = 0, fd = -1; fd < 0 && drivers[i]; i++) - fd = drmOpen(drivers[i], NULL); + fd = util_open(device, module); CHECK_RET_RETURN(fd, "Could not open device"); ret = kms_create(fd, &kms); |
From: <mat...@ke...> - 2016-11-14 18:45:02
|
amdgpu/Makefile.sources | 1 + configure.ac | 2 +- freedreno/freedreno-symbol-check | 1 + intel/Makefile.sources | 3 ++- intel/intel_bufmgr_gem.c | 30 +++++++++++++++++++++++++++++- 5 files changed, 34 insertions(+), 3 deletions(-) New commits: commit 8cf431271a8ad33c35859da2fb0387e6bccecd44 Author: Matt Turner <mat...@gm...> Date: Mon Nov 14 10:34:47 2016 -0800 Bump version for release diff --git a/configure.ac b/configure.ac index ac6b106..1c7a7fb 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_PREREQ([2.63]) AC_INIT([libdrm], - [2.4.71], + [2.4.72], [https://bugs.freedesktop.org/enter_bug.cgi?product=DRI], [libdrm]) commit b91bcbf6ab76c84a348b3e0bec0ee212e94a432a Author: Matt Turner <mat...@gm...> Date: Mon Nov 14 10:23:17 2016 -0800 freedreno: Add fd_ringbuffer_flush2 to symbol check. diff --git a/freedreno/freedreno-symbol-check b/freedreno/freedreno-symbol-check index 7b31a34..ad367fc 100755 --- a/freedreno/freedreno-symbol-check +++ b/freedreno/freedreno-symbol-check @@ -49,6 +49,7 @@ fd_ringbuffer_timestamp fd_ringmarker_del fd_ringmarker_dwords fd_ringmarker_flush +fd_ringbuffer_flush2 fd_ringmarker_mark fd_ringmarker_new EOF commit 01db192f974ead239c7122c04ef83e2cc9a8db50 Author: Matt Turner <mat...@gm...> Date: Mon Nov 14 10:16:27 2016 -0800 amdgpu: Add amdgpu_asic_id.h to Makefile.sources. diff --git a/amdgpu/Makefile.sources b/amdgpu/Makefile.sources index 0c0b9a9..487b9e0 100644 --- a/amdgpu/Makefile.sources +++ b/amdgpu/Makefile.sources @@ -1,4 +1,5 @@ LIBDRM_AMDGPU_FILES := \ + amdgpu_asic_id.h \ amdgpu_bo.c \ amdgpu_cs.c \ amdgpu_device.c \ commit 51002c0440b0e410efa3845f2633826aad7f3aa3 Author: Matt Turner <mat...@gm...> Date: Mon Nov 14 10:13:22 2016 -0800 intel: Add uthash.h to Makefile.sources. diff --git a/intel/Makefile.sources b/intel/Makefile.sources index 7b2272c..6947ab7 100644 --- a/intel/Makefile.sources +++ b/intel/Makefile.sources @@ -6,7 +6,8 @@ LIBDRM_INTEL_FILES := \ intel_decode.c \ intel_chipset.h \ mm.c \ - mm.h + mm.h \ + uthash.h LIBDRM_INTEL_H_FILES := \ intel_bufmgr.h \ commit 319108f9475f0165c9b4885efc8cf3b7e042b7fb Author: Neil Roberts <ne...@li...> Date: Mon Nov 9 16:27:52 2015 +0100 intel: Allow some codenames in INTEL_DEVID_OVERRIDE As well as allowing a hexadecimal PCI ID number, the INTEL_DEVID_OVERRIDE environment variable can now contain one of a few short codenames. The codenames are stored in a small table to map them to a corresponding PCI ID. This makes it easier to use without having to look up the PCI IDs manually. The PCI IDs used are the same as those chosen for the -p option of run.c in shader-db but SKL has been added as well. Reviewed-by: Matt Turner <mat...@gm...> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index 1792796..15c79b3 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -3060,6 +3060,34 @@ drm_intel_bufmgr_gem_set_vma_cache_size(drm_intel_bufmgr *bufmgr, int limit) drm_intel_gem_bo_purge_vma_cache(bufmgr_gem); } +static int +parse_devid_override(const char *devid_override) +{ + static const struct { + const char *name; + int pci_id; + } name_map[] = { + { "brw", PCI_CHIP_I965_GM }, + { "g4x", PCI_CHIP_GM45_GM }, + { "ilk", PCI_CHIP_ILD_G }, + { "snb", PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS }, + { "ivb", PCI_CHIP_IVYBRIDGE_S_GT2 }, + { "hsw", PCI_CHIP_HASWELL_CRW_E_GT3 }, + { "byt", PCI_CHIP_VALLEYVIEW_3 }, + { "bdw", 0x1620 | BDW_ULX }, + { "skl", PCI_CHIP_SKYLAKE_DT_GT2 }, + { "kbl", PCI_CHIP_KABYLAKE_DT_GT2 }, + }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(name_map); i++) { + if (!strcmp(name_map[i].name, devid_override)) + return name_map[i].pci_id; + } + + return strtod(devid_override, NULL); +} + /** * Get the PCI ID for the device. This can be overridden by setting the * INTEL_DEVID_OVERRIDE environment variable to the desired ID. @@ -3076,7 +3104,7 @@ get_pci_device_id(drm_intel_bufmgr_gem *bufmgr_gem) devid_override = getenv("INTEL_DEVID_OVERRIDE"); if (devid_override) { bufmgr_gem->no_exec = true; - return strtod(devid_override, NULL); + return parse_devid_override(devid_override); } } |
From: <ta...@ke...> - 2017-01-20 15:34:52
|
tests/drmdevice.c | 37 +++ xf86drm.c | 619 +++++++++++++++++++++++++++++++++++++++++++++++------- xf86drm.h | 41 +++ 3 files changed, 621 insertions(+), 76 deletions(-) New commits: commit 5403cb39c124c444babec51bd4499971cd86ccfa Author: Thierry Reding <tr...@nv...> Date: Wed Jan 18 08:29:23 2017 +0100 xf86drm: Reuse sysfs_uevent_get() Recent patches for USB, platform and host1x bus support introduced the sysfs_uevent_get() function that provides a generic way of parsing the sysfs uevent file that is associated with each device in Linux. Open-coded variants of this still exist in other places, so make those reuse the new function to remove some code duplication. Reviewed-by: Emil Velikov <emi...@gm...> Signed-off-by: Thierry Reding <tr...@nv...> diff --git a/xf86drm.c b/xf86drm.c index 89181c8..88f86ed 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -2971,32 +2971,21 @@ static int drmParseSubsystemType(int maj, int min) static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info) { #ifdef __linux__ - char path[PATH_MAX + 1]; - char data[512 + 1]; - char *str; - int domain, bus, dev, func; - int fd, ret; + unsigned int domain, bus, dev, func; + char path[PATH_MAX + 1], *value; + int num; - snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/uevent", maj, min); - fd = open(path, O_RDONLY); - if (fd < 0) - return -errno; + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); - ret = read(fd, data, sizeof(data)-1); - close(fd); - if (ret < 0) - return -errno; - data[ret] = '\0'; + value = sysfs_uevent_get(path, "PCI_SLOT_NAME"); + if (!value) + return -ENOENT; -#define TAG "PCI_SLOT_NAME=" - str = strstr(data, TAG); - if (str == NULL) - return -EINVAL; + num = sscanf(value, "%04x:%02x:%02x.%1u", &domain, &bus, &dev, &func); + free(value); - if (sscanf(str, TAG "%04x:%02x:%02x.%1u", - &domain, &bus, &dev, &func) != 4) + if (num != 4) return -EINVAL; -#undef TAG info->domain = domain; info->bus = bus; @@ -4084,13 +4073,8 @@ char *drmGetDeviceNameFromFd2(int fd) { #ifdef __linux__ struct stat sbuf; - char *device_name = NULL; + char path[PATH_MAX + 1], *value; unsigned int maj, min; - FILE *f; - char buf[512]; - static const char match[9] = "\nDEVNAME="; - size_t expected = 1; - if (fstat(fd, &sbuf)) return NULL; @@ -4101,30 +4085,16 @@ char *drmGetDeviceNameFromFd2(int fd) if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) return NULL; - snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/uevent", maj, min); - if (!(f = fopen(buf, "r"))) - return NULL; - - while (expected < sizeof(match)) { - int c = getc(f); + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d", maj, min); - if (c == EOF) { - fclose(f); - return NULL; - } else if (c == match[expected] ) - expected++; - else - expected = 0; - } + value = sysfs_uevent_get(path, "DEVNAME"); + if (!value) + return NULL; - strcpy(buf, "/dev/"); - if (fgets(buf + 5, sizeof(buf) - 5, f)) { - buf[strcspn(buf, "\n")] = '\0'; - device_name = strdup(buf); - } + snprintf(path, sizeof(path), "/dev/%s", value); + free(value); - fclose(f); - return device_name; + return strdup(path); #else struct stat sbuf; char node[PATH_MAX + 1]; commit 13b99f2a898a67320499e538303a689a270bb7f4 Author: Thierry Reding <tr...@nv...> Date: Thu Jan 12 22:07:28 2017 +0100 tests/drmdevice: Add USB, platform and host1x support Extend the drmdevice test with support for the newly added USB, platform and host1x busses. Reviewed-by: Emil Velikov <emi...@gm...> Signed-off-by: Thierry Reding <tr...@nv...> diff --git a/tests/drmdevice.c b/tests/drmdevice.c index 8c4f091..9dd5098 100644 --- a/tests/drmdevice.c +++ b/tests/drmdevice.c @@ -62,6 +62,43 @@ print_device_info(drmDevicePtr device, int i, bool print_revision) else printf("\t\t\trevision_id\tIGNORED\n"); + } else if (device->bustype == DRM_BUS_USB) { + printf("\t\tusb\n"); + printf("\t\t\tbus\t%03u\n", device->businfo.usb->bus); + printf("\t\t\tdev\t%03u\n", device->businfo.usb->dev); + + printf("\tdeviceinfo\n"); + printf("\t\tusb\n"); + printf("\t\t\tvendor\t%04x\n", device->deviceinfo.usb->vendor); + printf("\t\t\tproduct\t%04x\n", device->deviceinfo.usb->product); + } else if (device->bustype == DRM_BUS_PLATFORM) { + char **compatible = device->deviceinfo.platform->compatible; + + printf("\t\tplatform\n"); + printf("\t\t\tfullname\t%s\n", device->businfo.platform->fullname); + + printf("\tdeviceinfo\n"); + printf("\t\tplatform\n"); + printf("\t\t\tcompatible\n"); + + while (*compatible) { + printf("\t\t\t\t%s\n", *compatible); + compatible++; + } + } else if (device->bustype == DRM_BUS_HOST1X) { + char **compatible = device->deviceinfo.platform->compatible; + + printf("\t\thost1x\n"); + printf("\t\t\tfullname\t%s\n", device->businfo.host1x->fullname); + + printf("\tdeviceinfo\n"); + printf("\t\tplatform\n"); + printf("\t\t\tcompatible\n"); + + while (*compatible) { + printf("\t\t\t\t%s\n", *compatible); + compatible++; + } } else { printf("Unknown/unhandled bustype\n"); } commit 7b1f37f474d6bdf09b0a7f17bdb89398dbcf0c74 Author: Thierry Reding <tr...@nv...> Date: Wed Dec 21 17:59:04 2016 +0100 xf86drm: Add platform and host1x bus support ARM SoCs usually have their DRM/KMS devices on the platform bus, so add support for that to enable these devices to be used with the drmDevice infrastructure. NVIDIA Tegra SoCs have an additional level in the hierarchy and DRM/KMS devices can also be on the host1x bus. This is mostly equivalent to the platform bus. v4: - continue on error to process platform or host1x device v3: - guard Linux-specific sysfs parsing code with #ifdef __linux__ v2: - be careful not to overflow the full name - read compatible strings into device info Reviewed-by: Emil Velikov <emi...@gm...> Signed-off-by: Thierry Reding <tr...@nv...> diff --git a/xf86drm.c b/xf86drm.c index 58e9ce0..89181c8 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -2953,6 +2953,12 @@ static int drmParseSubsystemType(int maj, int min) if (strncmp(name, "/usb", 4) == 0) return DRM_BUS_USB; + if (strncmp(name, "/platform", 9) == 0) + return DRM_BUS_PLATFORM; + + if (strncmp(name, "/host1x", 7) == 0) + return DRM_BUS_HOST1X; + return -EINVAL; #elif defined(__OpenBSD__) return DRM_BUS_PCI; @@ -3043,6 +3049,12 @@ static int drmCompareBusInfo(drmDevicePtr a, drmDevicePtr b) case DRM_BUS_USB: return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo)); + case DRM_BUS_PLATFORM: + return memcmp(a->businfo.platform, b->businfo.platform, sizeof(drmPlatformBusInfo)); + + case DRM_BUS_HOST1X: + return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo)); + default: break; } @@ -3187,11 +3199,55 @@ static int drmParsePciDeviceInfo(int maj, int min, #endif } +static void drmFreePlatformDevice(drmDevicePtr device) +{ + if (device->deviceinfo.platform) { + if (device->deviceinfo.platform->compatible) { + char **compatible = device->deviceinfo.platform->compatible; + + while (*compatible) { + free(*compatible); + compatible++; + } + + free(device->deviceinfo.platform->compatible); + } + } +} + +static void drmFreeHost1xDevice(drmDevicePtr device) +{ + if (device->deviceinfo.host1x) { + if (device->deviceinfo.host1x->compatible) { + char **compatible = device->deviceinfo.host1x->compatible; + + while (*compatible) { + free(*compatible); + compatible++; + } + + free(device->deviceinfo.host1x->compatible); + } + } +} + void drmFreeDevice(drmDevicePtr *device) { if (device == NULL) return; + if (*device) { + switch ((*device)->bustype) { + case DRM_BUS_PLATFORM: + drmFreePlatformDevice(*device); + break; + + case DRM_BUS_HOST1X: + drmFreeHost1xDevice(*device); + break; + } + } + free(*device); *device = NULL; } @@ -3393,6 +3449,220 @@ free_device: return ret; } +static int drmParsePlatformBusInfo(int maj, int min, drmPlatformBusInfoPtr info) +{ +#ifdef __linux__ + char path[PATH_MAX + 1], *name; + + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); + + name = sysfs_uevent_get(path, "OF_FULLNAME"); + if (!name) + return -ENOENT; + + strncpy(info->fullname, name, DRM_PLATFORM_DEVICE_NAME_LEN); + info->fullname[DRM_PLATFORM_DEVICE_NAME_LEN - 1] = '\0'; + free(name); + + return 0; +#else +#warning "Missing implementation of drmParsePlatformBusInfo" + return -EINVAL; +#endif +} + +static int drmParsePlatformDeviceInfo(int maj, int min, + drmPlatformDeviceInfoPtr info) +{ +#ifdef __linux__ + char path[PATH_MAX + 1], *value; + unsigned int count, i; + int err; + + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); + + value = sysfs_uevent_get(path, "OF_COMPATIBLE_N"); + if (!value) + return -ENOENT; + + sscanf(value, "%u", &count); + free(value); + + info->compatible = calloc(count + 1, sizeof(*info->compatible)); + if (!info->compatible) + return -ENOMEM; + + for (i = 0; i < count; i++) { + value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i); + if (!value) { + err = -ENOENT; + goto free; + } + + info->compatible[i] = value; + } + + return 0; + +free: + while (i--) + free(info->compatible[i]); + + free(info->compatible); + return err; +#else +#warning "Missing implementation of drmParsePlatformDeviceInfo" + return -EINVAL; +#endif +} + +static int drmProcessPlatformDevice(drmDevicePtr *device, + const char *node, int node_type, + int maj, int min, bool fetch_deviceinfo, + uint32_t flags) +{ + drmDevicePtr dev; + char *ptr; + int ret; + + dev = drmDeviceAlloc(node_type, node, sizeof(drmPlatformBusInfo), + sizeof(drmPlatformDeviceInfo), &ptr); + if (!dev) + return -ENOMEM; + + dev->bustype = DRM_BUS_PLATFORM; + + dev->businfo.platform = (drmPlatformBusInfoPtr)ptr; + + ret = drmParsePlatformBusInfo(maj, min, dev->businfo.platform); + if (ret < 0) + goto free_device; + + if (fetch_deviceinfo) { + ptr += sizeof(drmPlatformBusInfo); + dev->deviceinfo.platform = (drmPlatformDeviceInfoPtr)ptr; + + ret = drmParsePlatformDeviceInfo(maj, min, dev->deviceinfo.platform); + if (ret < 0) + goto free_device; + } + + *device = dev; + + return 0; + +free_device: + free(dev); + return ret; +} + +static int drmParseHost1xBusInfo(int maj, int min, drmHost1xBusInfoPtr info) +{ +#ifdef __linux__ + char path[PATH_MAX + 1], *name; + + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); + + name = sysfs_uevent_get(path, "OF_FULLNAME"); + if (!name) + return -ENOENT; + + strncpy(info->fullname, name, DRM_HOST1X_DEVICE_NAME_LEN); + info->fullname[DRM_HOST1X_DEVICE_NAME_LEN - 1] = '\0'; + free(name); + + return 0; +#else +#warning "Missing implementation of drmParseHost1xBusInfo" + return -EINVAL; +#endif +} + +static int drmParseHost1xDeviceInfo(int maj, int min, + drmHost1xDeviceInfoPtr info) +{ +#ifdef __linux__ + char path[PATH_MAX + 1], *value; + unsigned int count, i; + int err; + + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); + + value = sysfs_uevent_get(path, "OF_COMPATIBLE_N"); + if (!value) + return -ENOENT; + + sscanf(value, "%u", &count); + free(value); + + info->compatible = calloc(count + 1, sizeof(*info->compatible)); + if (!info->compatible) + return -ENOMEM; + + for (i = 0; i < count; i++) { + value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i); + if (!value) { + err = -ENOENT; + goto free; + } + + info->compatible[i] = value; + } + + return 0; + +free: + while (i--) + free(info->compatible[i]); + + free(info->compatible); + return err; +#else +#warning "Missing implementation of drmParseHost1xDeviceInfo" + return -EINVAL; +#endif +} + +static int drmProcessHost1xDevice(drmDevicePtr *device, + const char *node, int node_type, + int maj, int min, bool fetch_deviceinfo, + uint32_t flags) +{ + drmDevicePtr dev; + char *ptr; + int ret; + + dev = drmDeviceAlloc(node_type, node, sizeof(drmHost1xBusInfo), + sizeof(drmHost1xDeviceInfo), &ptr); + if (!dev) + return -ENOMEM; + + dev->bustype = DRM_BUS_HOST1X; + + dev->businfo.host1x = (drmHost1xBusInfoPtr)ptr; + + ret = drmParseHost1xBusInfo(maj, min, dev->businfo.host1x); + if (ret < 0) + goto free_device; + + if (fetch_deviceinfo) { + ptr += sizeof(drmHost1xBusInfo); + dev->deviceinfo.host1x = (drmHost1xDeviceInfoPtr)ptr; + + ret = drmParseHost1xDeviceInfo(maj, min, dev->deviceinfo.host1x); + if (ret < 0) + goto free_device; + } + + *device = dev; + + return 0; + +free_device: + free(dev); + return ret; +} + /* Consider devices located on the same bus as duplicate and fold the respective * entries into a single one. * @@ -3576,6 +3846,20 @@ int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device) break; + case DRM_BUS_PLATFORM: + ret = drmProcessPlatformDevice(&d, node, node_type, maj, min, true, flags); + if (ret) + continue; + + break; + + case DRM_BUS_HOST1X: + ret = drmProcessHost1xDevice(&d, node, node_type, maj, min, true, flags); + if (ret) + continue; + + break; + default: continue; } @@ -3716,6 +4000,22 @@ int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices) break; + case DRM_BUS_PLATFORM: + ret = drmProcessPlatformDevice(&device, node, node_type, maj, min, + devices != NULL, flags); + if (ret) + goto free_devices; + + break; + + case DRM_BUS_HOST1X: + ret = drmProcessHost1xDevice(&device, node, node_type, maj, min, + devices != NULL, flags); + if (ret) + goto free_devices; + + break; + default: continue; } diff --git a/xf86drm.h b/xf86drm.h index 65d5321..0d92701 100644 --- a/xf86drm.h +++ b/xf86drm.h @@ -766,8 +766,10 @@ extern int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle); extern char *drmGetPrimaryDeviceNameFromFd(int fd); extern char *drmGetRenderDeviceNameFromFd(int fd); -#define DRM_BUS_PCI 0 -#define DRM_BUS_USB 1 +#define DRM_BUS_PCI 0 +#define DRM_BUS_USB 1 +#define DRM_BUS_PLATFORM 2 +#define DRM_BUS_HOST1X 3 typedef struct _drmPciBusInfo { uint16_t domain; @@ -794,6 +796,26 @@ typedef struct _drmUsbDeviceInfo { uint16_t product; } drmUsbDeviceInfo, *drmUsbDeviceInfoPtr; +#define DRM_PLATFORM_DEVICE_NAME_LEN 512 + +typedef struct _drmPlatformBusInfo { + char fullname[DRM_PLATFORM_DEVICE_NAME_LEN]; +} drmPlatformBusInfo, *drmPlatformBusInfoPtr; + +typedef struct _drmPlatformDeviceInfo { + char **compatible; /* NULL terminated list of compatible strings */ +} drmPlatformDeviceInfo, *drmPlatformDeviceInfoPtr; + +#define DRM_HOST1X_DEVICE_NAME_LEN 512 + +typedef struct _drmHost1xBusInfo { + char fullname[DRM_HOST1X_DEVICE_NAME_LEN]; +} drmHost1xBusInfo, *drmHost1xBusInfoPtr; + +typedef struct _drmHost1xDeviceInfo { + char **compatible; /* NULL terminated list of compatible strings */ +} drmHost1xDeviceInfo, *drmHost1xDeviceInfoPtr; + typedef struct _drmDevice { char **nodes; /* DRM_NODE_MAX sized array */ int available_nodes; /* DRM_NODE_* bitmask */ @@ -801,10 +823,14 @@ typedef struct _drmDevice { union { drmPciBusInfoPtr pci; drmUsbBusInfoPtr usb; + drmPlatformBusInfoPtr platform; + drmHost1xBusInfoPtr host1x; } businfo; union { drmPciDeviceInfoPtr pci; drmUsbDeviceInfoPtr usb; + drmPlatformDeviceInfoPtr platform; + drmHost1xDeviceInfoPtr host1x; } deviceinfo; } drmDevice, *drmDevicePtr; commit f8484ccbd12ba33ea5b3895efb7a39d986271be0 Author: Thierry Reding <thi...@gm...> Date: Thu Dec 22 00:39:36 2016 +0100 xf86drm: Add USB support Allow DRM/KMS devices hosted on USB to be detected by the drmDevice infrastructure. v4: - continue on error to process USB devices v3: - guard Linux-specific sysfs parsing code with #ifdef __linux__ v2: - make sysfs_uevent_get() more flexible using a format string Reviewed-by: Emil Velikov <emi...@gm...> Signed-off-by: Thierry Reding <thi...@gm...> diff --git a/xf86drm.c b/xf86drm.c index 7766bfe..58e9ce0 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -2886,6 +2886,50 @@ char *drmGetRenderDeviceNameFromFd(int fd) return drmGetMinorNameForFD(fd, DRM_NODE_RENDER); } +#ifdef __linux__ +static char * DRM_PRINTFLIKE(2, 3) +sysfs_uevent_get(const char *path, const char *fmt, ...) +{ + char filename[PATH_MAX + 1], *key, *line = NULL, *value = NULL; + size_t size = 0, len; + ssize_t num; + va_list ap; + FILE *fp; + + va_start(ap, fmt); + num = vasprintf(&key, fmt, ap); + va_end(ap); + len = num; + + snprintf(filename, sizeof(filename), "%s/uevent", path); + + fp = fopen(filename, "r"); + if (!fp) { + free(key); + return NULL; + } + + while ((num = getline(&line, &size, fp)) >= 0) { + if ((strncmp(line, key, len) == 0) && (line[len] == '=')) { + char *start = line + len + 1, *end = line + num - 1; + + if (*end != '\n') + end++; + + value = strndup(start, end - start); + break; + } + } + + free(line); + fclose(fp); + + free(key); + + return value; +} +#endif + static int drmParseSubsystemType(int maj, int min) { #ifdef __linux__ @@ -2906,6 +2950,9 @@ static int drmParseSubsystemType(int maj, int min) if (strncmp(name, "/pci", 4) == 0) return DRM_BUS_PCI; + if (strncmp(name, "/usb", 4) == 0) + return DRM_BUS_USB; + return -EINVAL; #elif defined(__OpenBSD__) return DRM_BUS_PCI; @@ -2992,6 +3039,10 @@ static int drmCompareBusInfo(drmDevicePtr a, drmDevicePtr b) switch (a->bustype) { case DRM_BUS_PCI: return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo)); + + case DRM_BUS_USB: + return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo)); + default: break; } @@ -3235,6 +3286,113 @@ free_device: return ret; } +static int drmParseUsbBusInfo(int maj, int min, drmUsbBusInfoPtr info) +{ +#ifdef __linux__ + char path[PATH_MAX + 1], *value; + unsigned int bus, dev; + int ret; + + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); + + value = sysfs_uevent_get(path, "BUSNUM"); + if (!value) + return -ENOENT; + + ret = sscanf(value, "%03u", &bus); + free(value); + + if (ret <= 0) + return -errno; + + value = sysfs_uevent_get(path, "DEVNUM"); + if (!value) + return -ENOENT; + + ret = sscanf(value, "%03u", &dev); + free(value); + + if (ret <= 0) + return -errno; + + info->bus = bus; + info->dev = dev; + + return 0; +#else +#warning "Missing implementation of drmParseUsbBusInfo" + return -EINVAL; +#endif +} + +static int drmParseUsbDeviceInfo(int maj, int min, drmUsbDeviceInfoPtr info) +{ +#ifdef __linux__ + char path[PATH_MAX + 1], *value; + unsigned int vendor, product; + int ret; + + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); + + value = sysfs_uevent_get(path, "PRODUCT"); + if (!value) + return -ENOENT; + + ret = sscanf(value, "%x/%x", &vendor, &product); + free(value); + + if (ret <= 0) + return -errno; + + info->vendor = vendor; + info->product = product; + + return 0; +#else +#warning "Missing implementation of drmParseUsbDeviceInfo" + return -EINVAL; +#endif +} + +static int drmProcessUsbDevice(drmDevicePtr *device, const char *node, + int node_type, int maj, int min, + bool fetch_deviceinfo, uint32_t flags) +{ + drmDevicePtr dev; + char *ptr; + int ret; + + dev = drmDeviceAlloc(node_type, node, sizeof(drmUsbBusInfo), + sizeof(drmUsbDeviceInfo), &ptr); + if (!dev) + return -ENOMEM; + + dev->bustype = DRM_BUS_USB; + + dev->businfo.usb = (drmUsbBusInfoPtr)ptr; + + ret = drmParseUsbBusInfo(maj, min, dev->businfo.usb); + if (ret < 0) + goto free_device; + + if (fetch_deviceinfo) { + ptr += sizeof(drmUsbBusInfo); + dev->deviceinfo.usb = (drmUsbDeviceInfoPtr)ptr; + + ret = drmParseUsbDeviceInfo(maj, min, dev->deviceinfo.usb); + if (ret < 0) + goto free_device; + } + + *device = dev; + + return 0; + +free_device: + free(dev); + return ret; +} + /* Consider devices located on the same bus as duplicate and fold the respective * entries into a single one. * @@ -3410,6 +3568,14 @@ int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device) continue; break; + + case DRM_BUS_USB: + ret = drmProcessUsbDevice(&d, node, node_type, maj, min, true, flags); + if (ret) + continue; + + break; + default: continue; } @@ -3541,6 +3707,15 @@ int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices) continue; break; + + case DRM_BUS_USB: + ret = drmProcessUsbDevice(&device, node, node_type, maj, min, + devices != NULL, flags); + if (ret) + goto free_devices; + + break; + default: continue; } diff --git a/xf86drm.h b/xf86drm.h index b340fc4..65d5321 100644 --- a/xf86drm.h +++ b/xf86drm.h @@ -767,6 +767,7 @@ extern char *drmGetPrimaryDeviceNameFromFd(int fd); extern char *drmGetRenderDeviceNameFromFd(int fd); #define DRM_BUS_PCI 0 +#define DRM_BUS_USB 1 typedef struct _drmPciBusInfo { uint16_t domain; @@ -783,15 +784,27 @@ typedef struct _drmPciDeviceInfo { uint8_t revision_id; } drmPciDeviceInfo, *drmPciDeviceInfoPtr; +typedef struct _drmUsbBusInfo { + uint8_t bus; + uint8_t dev; +} drmUsbBusInfo, *drmUsbBusInfoPtr; + +typedef struct _drmUsbDeviceInfo { + uint16_t vendor; + uint16_t product; +} drmUsbDeviceInfo, *drmUsbDeviceInfoPtr; + typedef struct _drmDevice { char **nodes; /* DRM_NODE_MAX sized array */ int available_nodes; /* DRM_NODE_* bitmask */ int bustype; union { drmPciBusInfoPtr pci; + drmUsbBusInfoPtr usb; } businfo; union { drmPciDeviceInfoPtr pci; + drmUsbDeviceInfoPtr usb; } deviceinfo; } drmDevice, *drmDevicePtr; commit 2e57bba870399926e1a0d0be3f4918a0a8432474 Author: Thierry Reding <tr...@nv...> Date: Wed Dec 21 17:54:48 2016 +0100 xf86drm: Factor out drmDeviceAlloc() Subsequent patches will add support for other bus types to drmDevice and they will duplicate a lot of the code to allocate a drmDevice. Factor out the common code so it can be reused. Reviewed-by: Emil Velikov <emi...@gm...> Signed-off-by: Thierry Reding <tr...@nv...> diff --git a/xf86drm.c b/xf86drm.c index 7b78dc6..7766bfe 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -3157,57 +3157,81 @@ void drmFreeDevices(drmDevicePtr devices[], int count) drmFreeDevice(&devices[i]); } +static drmDevicePtr drmDeviceAlloc(unsigned int type, const char *node, + size_t bus_size, size_t device_size, + char **ptrp) +{ + size_t max_node_length, extra, size; + drmDevicePtr device; + unsigned int i; + char *ptr; + + max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *)); + extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length); + + size = sizeof(*device) + extra + bus_size + device_size; + + device = calloc(1, size); + if (!device) + return NULL; + + device->available_nodes = 1 << type; + + ptr = (char *)device + sizeof(*device); + device->nodes = (char **)ptr; + + ptr += DRM_NODE_MAX * sizeof(void *); + + for (i = 0; i < DRM_NODE_MAX; i++) { + device->nodes[i] = ptr; + ptr += max_node_length; + } + + memcpy(device->nodes[type], node, max_node_length); + + *ptrp = ptr; + + return device; +} + static int drmProcessPciDevice(drmDevicePtr *device, const char *node, int node_type, int maj, int min, bool fetch_deviceinfo, uint32_t flags) { - const int max_node_str = ALIGN(drmGetMaxNodeName(), sizeof(void *)); - int ret, i; + drmDevicePtr dev; char *addr; + int ret; - *device = calloc(1, sizeof(drmDevice) + - (DRM_NODE_MAX * (sizeof(void *) + max_node_str)) + - sizeof(drmPciBusInfo) + - sizeof(drmPciDeviceInfo)); - if (!*device) + dev = drmDeviceAlloc(node_type, node, sizeof(drmPciBusInfo), + sizeof(drmPciDeviceInfo), &addr); + if (!dev) return -ENOMEM; - addr = (char*)*device; + dev->bustype = DRM_BUS_PCI; - (*device)->bustype = DRM_BUS_PCI; - (*device)->available_nodes = 1 << node_type; + dev->businfo.pci = (drmPciBusInfoPtr)addr; - addr += sizeof(drmDevice); - (*device)->nodes = (char**)addr; - - addr += DRM_NODE_MAX * sizeof(void *); - for (i = 0; i < DRM_NODE_MAX; i++) { - (*device)->nodes[i] = addr; - addr += max_node_str; - } - memcpy((*device)->nodes[node_type], node, max_node_str); - - (*device)->businfo.pci = (drmPciBusInfoPtr)addr; - - ret = drmParsePciBusInfo(maj, min, (*device)->businfo.pci); + ret = drmParsePciBusInfo(maj, min, dev->businfo.pci); if (ret) goto free_device; // Fetch the device info if the user has requested it if (fetch_deviceinfo) { addr += sizeof(drmPciBusInfo); - (*device)->deviceinfo.pci = (drmPciDeviceInfoPtr)addr; + dev->deviceinfo.pci = (drmPciDeviceInfoPtr)addr; - ret = drmParsePciDeviceInfo(maj, min, (*device)->deviceinfo.pci, flags); + ret = drmParsePciDeviceInfo(maj, min, dev->deviceinfo.pci, flags); if (ret) goto free_device; } + + *device = dev; + return 0; free_device: - free(*device); - *device = NULL; + free(dev); return ret; } |