From 8665b666c7e2ecdee7d27e1ad540910a0223ba6d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 23 Apr 2008 11:22:59 -0700 Subject: Move mmfs.h userland interface to shared-core. --- shared-core/mmfs.h | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 shared-core/mmfs.h (limited to 'shared-core') diff --git a/shared-core/mmfs.h b/shared-core/mmfs.h new file mode 100644 index 00000000..4cad3bdc --- /dev/null +++ b/shared-core/mmfs.h @@ -0,0 +1,139 @@ +/* + * 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 + * + */ + +/** @file mmfs.h + * This file provides ioctl and ioctl argument definitions for using the + * mmfs device. + */ + +#ifdef __KERNEL__ +#include "mmfs_drv.h" +#endif /* __KERNEL__ */ + +#define MMFS_DEVICE_PATH "/dev/mmfs" +/* XXX: Choose non-experimental major */ +#define MMFS_DEVICE_MAJOR 246 + +struct mmfs_alloc_args { + /** + * Requested size for the object. + * + * The (page-aligned) allocated size for the object will be returned. + */ + uint32_t size; + /** Returned handle for the object. */ + uint32_t handle; +}; + +struct mmfs_unreference_args { + /** Handle of the object to be unreferenced. */ + uint32_t handle; +}; + +struct mmfs_link_args { + /** Handle for the object being given a name. */ + uint32_t handle; + /** Requested file name to export the object under. */ + char *name; + /** Requested file mode to export the object under. */ + mode_t mode; +}; + +struct mmfs_pread_args { + /** Handle for the object being read. */ + uint32_t handle; + /** Offset into the object to read from */ + off_t offset; + /** Length of data to read */ + size_t size; + /** Pointer to write the data into. */ + void *data; +}; + +struct mmfs_pwrite_args { + /** Handle for the object being written to. */ + uint32_t handle; + /** Offset into the object to write to */ + off_t offset; + /** Length of data to write */ + size_t size; + /** Pointer to read the data from. */ + void *data; +}; + +struct mmfs_mmap_args { + /** Handle for the object being mapped. */ + uint32_t handle; + /** Offset in the object to map. */ + off_t offset; + /** + * Length of data to map. + * + * The value will be page-aligned. + */ + size_t size; + /** Returned pointer the data was mapped at */ + void *addr; +}; + +/** + * \name Ioctls Definitions + */ +/* @{ */ + +#define MMFS_IOCTL_BASE 'm' +#define MMFS_IO(nr) _IO(MMFS_IOCTL_BASE, nr) +#define MMFS_IOR(nr,type) _IOR(MMFS_IOCTL_BASE, nr, type) +#define MMFS_IOW(nr,type) _IOW(MMFS_IOCTL_BASE, nr, type) +#define MMFS_IOWR(nr,type) _IOWR(MMFS_IOCTL_BASE, nr, type) + +/** This ioctl allocates an object and returns a handle referencing it. */ +#define MMFS_IOCTL_ALLOC MMFS_IOWR(0x00, struct mmfs_alloc_args) + +/** + * This ioctl releases the reference on the handle returned from + * MMFS_IOCTL_ALLOC. + */ +#define MMFS_IOCTL_UNREFERENCE MMFS_IOR(0x01, struct mmfs_unreference_args) + +/** + * This ioctl creates a file in the mmfs filesystem representing an object. + * + * XXX: Need a way to get handle from fd or name. + */ +#define MMFS_IOCTL_LINK MMFS_IOWR(0x02, struct mmfs_link_args) + +/** This ioctl copies data from an object into a user address. */ +#define MMFS_IOCTL_PREAD MMFS_IOWR(0x03, struct mmfs_pread_args) + +/** This ioctl copies data from a user address into an object. */ +#define MMFS_IOCTL_PWRITE MMFS_IOWR(0x04, struct mmfs_pwrite_args) + +/** This ioctl maps data from the object into the user address space. */ +#define MMFS_IOCTL_MMAP MMFS_IOWR(0x05, struct mmfs_mmap_args) + +/* }@ */ -- cgit v1.2.3 From c1fec43b553ea93460b58995a1229e84d8bb45b4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 23 Apr 2008 11:32:31 -0700 Subject: Extend the mmfs basic test to do a couple of ioctls. --- shared-core/mmfs.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'shared-core') diff --git a/shared-core/mmfs.h b/shared-core/mmfs.h index 4cad3bdc..bc7e991f 100644 --- a/shared-core/mmfs.h +++ b/shared-core/mmfs.h @@ -25,6 +25,8 @@ * */ +#include + /** @file mmfs.h * This file provides ioctl and ioctl argument definitions for using the * mmfs device. -- cgit v1.2.3 From 8c741ed54e1be63528e79222b600f37506c6d6d2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 23 Apr 2008 13:06:58 -0700 Subject: Add pread/pwrite ioctls to mmfs. --- shared-core/mmfs.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/mmfs.h b/shared-core/mmfs.h index bc7e991f..e0a4f25b 100644 --- a/shared-core/mmfs.h +++ b/shared-core/mmfs.h @@ -25,7 +25,12 @@ * */ -#include +#ifdef __linux__ +#include +#else +#include +#include +#endif /** @file mmfs.h * This file provides ioctl and ioctl argument definitions for using the -- cgit v1.2.3 From dabd056bf34b389585b618cf03a297877505f06b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 29 Apr 2008 13:30:44 -0700 Subject: Move mmfs ioctls into the DRM. Untested. --- shared-core/drm.h | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'shared-core') diff --git a/shared-core/drm.h b/shared-core/drm.h index 5981dcb8..caa3dbd1 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -960,6 +960,69 @@ struct drm_mm_info_arg { uint64_t p_size; }; + +struct drm_mm_alloc_args { + /** + * Requested size for the object. + * + * The (page-aligned) allocated size for the object will be returned. + */ + uint32_t size; + /** Returned handle for the object. */ + uint32_t handle; +}; + +struct drm_mm_unreference_args { + /** Handle of the object to be unreferenced. */ + uint32_t handle; +}; + +struct drm_mm_link_args { + /** Handle for the object being given a name. */ + uint32_t handle; + /** Requested file name to export the object under. */ + char *name; + /** Requested file mode to export the object under. */ + mode_t mode; +}; + +struct drm_mm_pread_args { + /** Handle for the object being read. */ + uint32_t handle; + /** Offset into the object to read from */ + off_t offset; + /** Length of data to read */ + size_t size; + /** Pointer to write the data into. */ + void *data; +}; + +struct drm_mm_pwrite_args { + /** Handle for the object being written to. */ + uint32_t handle; + /** Offset into the object to write to */ + off_t offset; + /** Length of data to write */ + size_t size; + /** Pointer to read the data from. */ + void *data; +}; + +struct drm_mm_mmap_args { + /** Handle for the object being mapped. */ + uint32_t handle; + /** Offset in the object to map. */ + off_t offset; + /** + * Length of data to map. + * + * The value will be page-aligned. + */ + size_t size; + /** Returned pointer the data was mapped at */ + void *addr; +}; + /** * \name Ioctls Definitions */ @@ -980,6 +1043,11 @@ struct drm_mm_info_arg { #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) #define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) #define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) +#define DRM_IOCTL_MM_ALLOC DRM_IOWR(0x09, struct drm_mm_alloc_args) +#define DRM_IOCTL_MM_UNREFERENCE DRM_IOW(0x0a, struct drm_mm_unreference_args) +#define DRM_IOCTL_MM_PREAD DRM_IOW(0x0b, struct drm_mm_pread_args) +#define DRM_IOCTL_MM_PWRITE DRM_IOW(0x0c, struct drm_mm_pwrite_args) +#define DRM_IOCTL_MM_MMAP DRM_IOWR(0x0d, struct drm_mm_mmap_args) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) -- cgit v1.2.3 From 81ba8ded7e01b21e600069977e496017c8966d66 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 29 Apr 2008 13:47:12 -0700 Subject: Remove the remainder of the mmfs device. --- shared-core/mmfs.h | 146 ----------------------------------------------------- 1 file changed, 146 deletions(-) delete mode 100644 shared-core/mmfs.h (limited to 'shared-core') diff --git a/shared-core/mmfs.h b/shared-core/mmfs.h deleted file mode 100644 index e0a4f25b..00000000 --- a/shared-core/mmfs.h +++ /dev/null @@ -1,146 +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 - * - */ - -#ifdef __linux__ -#include -#else -#include -#include -#endif - -/** @file mmfs.h - * This file provides ioctl and ioctl argument definitions for using the - * mmfs device. - */ - -#ifdef __KERNEL__ -#include "mmfs_drv.h" -#endif /* __KERNEL__ */ - -#define MMFS_DEVICE_PATH "/dev/mmfs" -/* XXX: Choose non-experimental major */ -#define MMFS_DEVICE_MAJOR 246 - -struct mmfs_alloc_args { - /** - * Requested size for the object. - * - * The (page-aligned) allocated size for the object will be returned. - */ - uint32_t size; - /** Returned handle for the object. */ - uint32_t handle; -}; - -struct mmfs_unreference_args { - /** Handle of the object to be unreferenced. */ - uint32_t handle; -}; - -struct mmfs_link_args { - /** Handle for the object being given a name. */ - uint32_t handle; - /** Requested file name to export the object under. */ - char *name; - /** Requested file mode to export the object under. */ - mode_t mode; -}; - -struct mmfs_pread_args { - /** Handle for the object being read. */ - uint32_t handle; - /** Offset into the object to read from */ - off_t offset; - /** Length of data to read */ - size_t size; - /** Pointer to write the data into. */ - void *data; -}; - -struct mmfs_pwrite_args { - /** Handle for the object being written to. */ - uint32_t handle; - /** Offset into the object to write to */ - off_t offset; - /** Length of data to write */ - size_t size; - /** Pointer to read the data from. */ - void *data; -}; - -struct mmfs_mmap_args { - /** Handle for the object being mapped. */ - uint32_t handle; - /** Offset in the object to map. */ - off_t offset; - /** - * Length of data to map. - * - * The value will be page-aligned. - */ - size_t size; - /** Returned pointer the data was mapped at */ - void *addr; -}; - -/** - * \name Ioctls Definitions - */ -/* @{ */ - -#define MMFS_IOCTL_BASE 'm' -#define MMFS_IO(nr) _IO(MMFS_IOCTL_BASE, nr) -#define MMFS_IOR(nr,type) _IOR(MMFS_IOCTL_BASE, nr, type) -#define MMFS_IOW(nr,type) _IOW(MMFS_IOCTL_BASE, nr, type) -#define MMFS_IOWR(nr,type) _IOWR(MMFS_IOCTL_BASE, nr, type) - -/** This ioctl allocates an object and returns a handle referencing it. */ -#define MMFS_IOCTL_ALLOC MMFS_IOWR(0x00, struct mmfs_alloc_args) - -/** - * This ioctl releases the reference on the handle returned from - * MMFS_IOCTL_ALLOC. - */ -#define MMFS_IOCTL_UNREFERENCE MMFS_IOR(0x01, struct mmfs_unreference_args) - -/** - * This ioctl creates a file in the mmfs filesystem representing an object. - * - * XXX: Need a way to get handle from fd or name. - */ -#define MMFS_IOCTL_LINK MMFS_IOWR(0x02, struct mmfs_link_args) - -/** This ioctl copies data from an object into a user address. */ -#define MMFS_IOCTL_PREAD MMFS_IOWR(0x03, struct mmfs_pread_args) - -/** This ioctl copies data from a user address into an object. */ -#define MMFS_IOCTL_PWRITE MMFS_IOWR(0x04, struct mmfs_pwrite_args) - -/** This ioctl maps data from the object into the user address space. */ -#define MMFS_IOCTL_MMAP MMFS_IOWR(0x05, struct mmfs_mmap_args) - -/* }@ */ -- cgit v1.2.3 From 1a8406795052e3ec49e400465f3211d04fd9dd86 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 30 Apr 2008 16:03:15 -0700 Subject: Hacking towards hooking up execbuffer. --- shared-core/i915_dma.c | 2 ++ shared-core/i915_drm.h | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++ shared-core/i915_drv.h | 9 ++++++ 3 files changed, 96 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 7ccd185c..6c6fd435 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1124,6 +1124,8 @@ struct drm_ioctl_desc i915_ioctls[] = { #ifdef I915_HAVE_BUFFER DRM_IOCTL_DEF(DRM_I915_EXECBUFFER, i915_execbuffer, DRM_AUTH), #endif + DRM_IOCTL_DEF(DRM_I915_MM_INIT, intel_mm_init_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_MM_EXECBUFFER, intel_mm_execbuffer, DRM_AUTH), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index de463614..1a70010b 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -176,6 +176,8 @@ typedef struct drm_i915_sarea { #define DRM_I915_MMIO 0x10 #define DRM_I915_HWS_ADDR 0x11 #define DRM_I915_EXECBUFFER 0x12 +#define DRM_I915_MM_INIT 0x13 +#define DRM_I915_MM_EXECBUFFER 0x14 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -195,6 +197,8 @@ typedef struct drm_i915_sarea { #define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) #define DRM_IOCTL_I915_MMIO DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_MMIO, drm_i915_mmio) #define DRM_IOCTL_I915_EXECBUFFER DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_EXECBUFFER, struct drm_i915_execbuffer) +#define DRM_IOCTL_I915_MM_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_MM_INIT, struct drm_i915_mm_init) +#define DRM_IOCTL_I915_MM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_MM_INIT, struct drm_i915_mm_execbuffer) /* Asynchronous page flipping: */ @@ -394,4 +398,85 @@ struct drm_i915_execbuffer { struct drm_fence_arg fence_arg; }; +struct drm_i915_mm_init { + /** + * Beginning offset in the GTT to be managed by the DRM memory + * manager. + */ + off_t gtt_start; + /** + * Ending offset in the GTT to be managed by the DRM memory + * manager. + */ + off_t gtt_end; +}; + +struct drm_i915_relocation_entry { + /** + * Handle of the buffer being pointed to by this relocation entry. + * + * It's appealing to make this be an index into the mm_validate_entry + * list to refer to the buffer, but handle lookup should be O(1) anyway, + * and prevents O(n) search in userland to find what that index is. + */ + uint32_t target_buffer; + + /** Offset in the buffer the relocation entry will be written into */ + uint32_t offset; + + /** + * Value to be added to the offset of the target buffer to make up + * the relocation entry. + */ + uint32_t delta; + + /** + * Offset value of the target buffer that the relocation entry was last + * written as. + * + * If the buffer has the same offset as last time, we can skip syncing + * and writing the relocation. This value is written back out by + * the execbuffer ioctl when the relocation is written. + */ + uint32_t presumed_offset; +}; + +struct drm_i915_mm_validate_entry { + /** + * User's handle for a buffer to be bound into the GTT for this + * operation. + */ + uint32_t buffer_handle; + /** + * Returned value of the updated offset of the buffer, for future + * presumed_offset writes. + */ + uint32_t buffer_offset; + /** List of relocations to be performed on this buffer */ + struct drm_i915_relocation_entry *relocs; + uint32_t relocation_count; +}; + +struct drm_i915_mm_execbuffer { + /** + * List of buffers to be validated wit their relocations to be + * performend on them. + * + * These buffers must be listed in an order such that all relocations + * a buffer is performing refer to buffers that have already appeared + * in the validate list. + */ + struct drm_i915_mm_validate_entry *buffers; + uint32_t buffer_count; + + /** Offset in the batchbuffer to start execution from. */ + uint32_t batch_start_offset; + /** Bytes used in batchbuffer from batch_start_offset */ + uint32_t batch_len; + uint32_t DR1; + uint32_t DR4; + uint32_t num_cliprects; + struct drm_clip_rect *cliprects; +}; + #endif /* _I915_DRM_H_ */ diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 412a2594..0c6ec588 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -241,6 +241,10 @@ typedef struct drm_i915_private { u8 saveDACMASK; u8 saveDACDATA[256*3]; /* 256 3-byte colors */ u8 saveCR[36]; + + struct { + struct drm_memrange gtt_space; + } mm; } drm_i915_private_t; enum intel_chip_family { @@ -329,6 +333,11 @@ void i915_flush_ttm(struct drm_ttm *ttm); /* i915_execbuf.c */ int i915_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv); +/* i915_mm.c */ +int intel_mm_init_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int intel_mm_execbuffer(struct drm_device *dev, void *data, + struct drm_file *file_priv); #endif -- cgit v1.2.3 From 2140e102f942edf7982cee2a3f00caf234551687 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 1 May 2008 11:39:06 -0700 Subject: checkpoint: rename to GEM and a few more i915 bits. --- shared-core/drm.h | 22 +++++++++++----------- shared-core/i915_dma.c | 4 ++-- shared-core/i915_drm.h | 20 ++++++++++---------- shared-core/i915_drv.h | 20 +++++++++++++++++--- 4 files changed, 40 insertions(+), 26 deletions(-) (limited to 'shared-core') diff --git a/shared-core/drm.h b/shared-core/drm.h index caa3dbd1..d79fa5f8 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -961,7 +961,7 @@ struct drm_mm_info_arg { }; -struct drm_mm_alloc_args { +struct drm_gem_alloc_args { /** * Requested size for the object. * @@ -972,12 +972,12 @@ struct drm_mm_alloc_args { uint32_t handle; }; -struct drm_mm_unreference_args { +struct drm_gem_unreference_args { /** Handle of the object to be unreferenced. */ uint32_t handle; }; -struct drm_mm_link_args { +struct drm_gem_link_args { /** Handle for the object being given a name. */ uint32_t handle; /** Requested file name to export the object under. */ @@ -986,7 +986,7 @@ struct drm_mm_link_args { mode_t mode; }; -struct drm_mm_pread_args { +struct drm_gem_pread_args { /** Handle for the object being read. */ uint32_t handle; /** Offset into the object to read from */ @@ -997,7 +997,7 @@ struct drm_mm_pread_args { void *data; }; -struct drm_mm_pwrite_args { +struct drm_gem_pwrite_args { /** Handle for the object being written to. */ uint32_t handle; /** Offset into the object to write to */ @@ -1008,7 +1008,7 @@ struct drm_mm_pwrite_args { void *data; }; -struct drm_mm_mmap_args { +struct drm_gem_mmap_args { /** Handle for the object being mapped. */ uint32_t handle; /** Offset in the object to map. */ @@ -1043,11 +1043,11 @@ struct drm_mm_mmap_args { #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) #define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) #define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) -#define DRM_IOCTL_MM_ALLOC DRM_IOWR(0x09, struct drm_mm_alloc_args) -#define DRM_IOCTL_MM_UNREFERENCE DRM_IOW(0x0a, struct drm_mm_unreference_args) -#define DRM_IOCTL_MM_PREAD DRM_IOW(0x0b, struct drm_mm_pread_args) -#define DRM_IOCTL_MM_PWRITE DRM_IOW(0x0c, struct drm_mm_pwrite_args) -#define DRM_IOCTL_MM_MMAP DRM_IOWR(0x0d, struct drm_mm_mmap_args) +#define DRM_IOCTL_GEM_ALLOC DRM_IOWR(0x09, struct drm_gem_alloc_args) +#define DRM_IOCTL_GEM_UNREFERENCE DRM_IOW(0x0a, struct drm_gem_unreference_args) +#define DRM_IOCTL_GEM_PREAD DRM_IOW(0x0b, struct drm_gem_pread_args) +#define DRM_IOCTL_GEM_PWRITE DRM_IOW(0x0c, struct drm_gem_pwrite_args) +#define DRM_IOCTL_GEM_MMAP DRM_IOWR(0x0d, struct drm_gem_mmap_args) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 6c6fd435..821b2a95 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1124,8 +1124,8 @@ struct drm_ioctl_desc i915_ioctls[] = { #ifdef I915_HAVE_BUFFER DRM_IOCTL_DEF(DRM_I915_EXECBUFFER, i915_execbuffer, DRM_AUTH), #endif - DRM_IOCTL_DEF(DRM_I915_MM_INIT, intel_mm_init_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_MM_EXECBUFFER, intel_mm_execbuffer, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 1a70010b..4c241fc5 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -176,8 +176,8 @@ typedef struct drm_i915_sarea { #define DRM_I915_MMIO 0x10 #define DRM_I915_HWS_ADDR 0x11 #define DRM_I915_EXECBUFFER 0x12 -#define DRM_I915_MM_INIT 0x13 -#define DRM_I915_MM_EXECBUFFER 0x14 +#define DRM_I915_GEM_INIT 0x13 +#define DRM_I915_GEM_EXECBUFFER 0x14 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -197,8 +197,8 @@ typedef struct drm_i915_sarea { #define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) #define DRM_IOCTL_I915_MMIO DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_MMIO, drm_i915_mmio) #define DRM_IOCTL_I915_EXECBUFFER DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_EXECBUFFER, struct drm_i915_execbuffer) -#define DRM_IOCTL_I915_MM_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_MM_INIT, struct drm_i915_mm_init) -#define DRM_IOCTL_I915_MM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_MM_INIT, struct drm_i915_mm_execbuffer) +#define DRM_IOCTL_I915_MM_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init) +#define DRM_IOCTL_I915_MM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_execbuffer) /* Asynchronous page flipping: */ @@ -398,7 +398,7 @@ struct drm_i915_execbuffer { struct drm_fence_arg fence_arg; }; -struct drm_i915_mm_init { +struct drm_i915_gem_init { /** * Beginning offset in the GTT to be managed by the DRM memory * manager. @@ -411,7 +411,7 @@ struct drm_i915_mm_init { off_t gtt_end; }; -struct drm_i915_relocation_entry { +struct drm_i915_gem_relocation_entry { /** * Handle of the buffer being pointed to by this relocation entry. * @@ -441,7 +441,7 @@ struct drm_i915_relocation_entry { uint32_t presumed_offset; }; -struct drm_i915_mm_validate_entry { +struct drm_i915_gem_validate_entry { /** * User's handle for a buffer to be bound into the GTT for this * operation. @@ -453,11 +453,11 @@ struct drm_i915_mm_validate_entry { */ uint32_t buffer_offset; /** List of relocations to be performed on this buffer */ - struct drm_i915_relocation_entry *relocs; + struct drm_i915_gem_relocation_entry *relocs; uint32_t relocation_count; }; -struct drm_i915_mm_execbuffer { +struct drm_i915_gem_execbuffer { /** * List of buffers to be validated wit their relocations to be * performend on them. @@ -466,7 +466,7 @@ struct drm_i915_mm_execbuffer { * a buffer is performing refer to buffers that have already appeared * in the validate list. */ - struct drm_i915_mm_validate_entry *buffers; + struct drm_i915_gem_validate_entry *buffers; uint32_t buffer_count; /** Offset in the batchbuffer to start execution from. */ diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 0c6ec588..7913f48b 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -254,6 +254,18 @@ enum intel_chip_family { CHIP_I965 = 0x08, }; +/** driver private structure attached to each drm_gem_object */ +struct drm_i915_gem_object { + /** Current offset of the object in GTT space, if any. */ + uint32_t gtt_offset; + + /** Boolean whether this object has a valid gtt offset. */ + int gtt_bound; + + /** How many users have pinned this object in GTT space */ + int pin_count; +}; + extern struct drm_ioctl_desc i915_ioctls[]; extern int i915_max_ioctl; @@ -333,11 +345,13 @@ void i915_flush_ttm(struct drm_ttm *ttm); /* i915_execbuf.c */ int i915_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv); -/* i915_mm.c */ -int intel_mm_init_ioctl(struct drm_device *dev, void *data, +/* i915_gem.c */ +int i915_gem_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -int intel_mm_execbuffer(struct drm_device *dev, void *data, +int i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv); +int i915_gem_init_object(struct drm_device *dev, struct drm_gem_object *obj); +void i915_gem_free_object(struct drm_device *dev, struct drm_gem_object *obj); #endif -- cgit v1.2.3 From 5af87acbc2025b9f72d51b30f176e9c3909695ac Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 1 May 2008 14:20:44 -0700 Subject: checkpoint: gtt binding written. --- shared-core/i915_drv.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 7913f48b..431fc433 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -256,7 +256,19 @@ enum intel_chip_family { /** driver private structure attached to each drm_gem_object */ struct drm_i915_gem_object { - /** Current offset of the object in GTT space, if any. */ + /** Current space allocated to this object in the GTT, if any. */ + struct drm_memrange_node *gtt_space; + + /** AGP memory structure for our GTT binding. */ + DRM_AGP_MEM *agp_mem; + + struct page **page_list; + + /** + * Current offset of the object in GTT space. + * + * This is the same as gtt_space->start + */ uint32_t gtt_offset; /** Boolean whether this object has a valid gtt offset. */ -- cgit v1.2.3 From ccd1bae0f676490a88240c62f02e072d2cf3b030 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 1 May 2008 15:22:21 -0700 Subject: checkpoint: relocations support. --- shared-core/i915_drm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 4c241fc5..52d1f31f 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -419,7 +419,7 @@ struct drm_i915_gem_relocation_entry { * list to refer to the buffer, but handle lookup should be O(1) anyway, * and prevents O(n) search in userland to find what that index is. */ - uint32_t target_buffer; + uint32_t target_handle; /** Offset in the buffer the relocation entry will be written into */ uint32_t offset; -- cgit v1.2.3 From 793549116ee6e9202fc7e474bd382eb19ffeb87f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 1 May 2008 15:40:02 -0700 Subject: Add pin/unpin object ioctls for gem. --- shared-core/i915_dma.c | 2 ++ shared-core/i915_drm.h | 22 ++++++++++++++++++++-- shared-core/i915_drv.h | 4 ++++ 3 files changed, 26 insertions(+), 2 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 821b2a95..73f843c8 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1126,6 +1126,8 @@ struct drm_ioctl_desc i915_ioctls[] = { #endif DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 52d1f31f..4d113e4c 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -178,6 +178,8 @@ typedef struct drm_i915_sarea { #define DRM_I915_EXECBUFFER 0x12 #define DRM_I915_GEM_INIT 0x13 #define DRM_I915_GEM_EXECBUFFER 0x14 +#define DRM_I915_GEM_PIN 0x15 +#define DRM_I915_GEM_UNPIN 0x16 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -197,8 +199,10 @@ typedef struct drm_i915_sarea { #define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) #define DRM_IOCTL_I915_MMIO DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_MMIO, drm_i915_mmio) #define DRM_IOCTL_I915_EXECBUFFER DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_EXECBUFFER, struct drm_i915_execbuffer) -#define DRM_IOCTL_I915_MM_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init) -#define DRM_IOCTL_I915_MM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_execbuffer) +#define DRM_IOCTL_I915_GEM_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init) +#define DRM_IOCTL_I915_GEM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer) +#define DRM_IOCTL_I915_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin) +#define DRM_IOCTL_I915_GEM_UNPIN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin) /* Asynchronous page flipping: */ @@ -479,4 +483,18 @@ struct drm_i915_gem_execbuffer { struct drm_clip_rect *cliprects; }; +struct drm_i915_gem_pin { + /** Handle of the buffer to be pinned. */ + uint32_t handle; + + /** Returned GTT offset of the buffer. */ + uint64_t offset; +}; + +struct drm_i915_gem_unpin { + /** Handle of the buffer to be unpinned. */ + uint32_t handle; +}; + + #endif /* _I915_DRM_H_ */ diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 431fc433..801ac99e 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -362,6 +362,10 @@ int i915_gem_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv); +int i915_gem_pin_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int i915_gem_unpin_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); int i915_gem_init_object(struct drm_device *dev, struct drm_gem_object *obj); void i915_gem_free_object(struct drm_device *dev, struct drm_gem_object *obj); -- cgit v1.2.3 From d2529d13961f0df00754393e1ad9b72da5e998a4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 1 May 2008 16:27:03 -0700 Subject: Remove _args from gem ioctl argument structure tags. --- shared-core/drm.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'shared-core') diff --git a/shared-core/drm.h b/shared-core/drm.h index d79fa5f8..6d62af6a 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -961,7 +961,7 @@ struct drm_mm_info_arg { }; -struct drm_gem_alloc_args { +struct drm_gem_alloc { /** * Requested size for the object. * @@ -972,12 +972,12 @@ struct drm_gem_alloc_args { uint32_t handle; }; -struct drm_gem_unreference_args { +struct drm_gem_unreference { /** Handle of the object to be unreferenced. */ uint32_t handle; }; -struct drm_gem_link_args { +struct drm_gem_link { /** Handle for the object being given a name. */ uint32_t handle; /** Requested file name to export the object under. */ @@ -986,7 +986,7 @@ struct drm_gem_link_args { mode_t mode; }; -struct drm_gem_pread_args { +struct drm_gem_pread { /** Handle for the object being read. */ uint32_t handle; /** Offset into the object to read from */ @@ -997,7 +997,7 @@ struct drm_gem_pread_args { void *data; }; -struct drm_gem_pwrite_args { +struct drm_gem_pwrite { /** Handle for the object being written to. */ uint32_t handle; /** Offset into the object to write to */ @@ -1008,7 +1008,7 @@ struct drm_gem_pwrite_args { void *data; }; -struct drm_gem_mmap_args { +struct drm_gem_mmap { /** Handle for the object being mapped. */ uint32_t handle; /** Offset in the object to map. */ @@ -1042,12 +1042,12 @@ struct drm_gem_mmap_args { #define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client) #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) #define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) -#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) -#define DRM_IOCTL_GEM_ALLOC DRM_IOWR(0x09, struct drm_gem_alloc_args) -#define DRM_IOCTL_GEM_UNREFERENCE DRM_IOW(0x0a, struct drm_gem_unreference_args) -#define DRM_IOCTL_GEM_PREAD DRM_IOW(0x0b, struct drm_gem_pread_args) -#define DRM_IOCTL_GEM_PWRITE DRM_IOW(0x0c, struct drm_gem_pwrite_args) -#define DRM_IOCTL_GEM_MMAP DRM_IOWR(0x0d, struct drm_gem_mmap_args) +#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) +#define DRM_IOCTL_GEM_ALLOC DRM_IOWR(0x09, struct drm_gem_alloc) +#define DRM_IOCTL_GEM_UNREFERENCE DRM_IOW(0x0a, struct drm_gem_unreference) +#define DRM_IOCTL_GEM_PREAD DRM_IOW(0x0b, struct drm_gem_pread) +#define DRM_IOCTL_GEM_PWRITE DRM_IOW(0x0c, struct drm_gem_pwrite) +#define DRM_IOCTL_GEM_MMAP DRM_IOWR(0x0d, struct drm_gem_mmap) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) -- cgit v1.2.3 From 7d5f783eca3302ec7efa164e2980c75e5e591585 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 1 May 2008 16:38:37 -0700 Subject: Make GEM object handles be nonzero. --- shared-core/drm.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/drm.h b/shared-core/drm.h index 6d62af6a..1f49cbb0 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -968,7 +968,11 @@ struct drm_gem_alloc { * The (page-aligned) allocated size for the object will be returned. */ uint32_t size; - /** Returned handle for the object. */ + /** + * Returned handle for the object. + * + * Object handles are nonzero. + */ uint32_t handle; }; -- cgit v1.2.3 From 30efad5113944681c1abd6452e10355c105e9c39 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 1 May 2008 20:31:16 -0700 Subject: Fix gem ioctls to be 32/64-bit clean. mixed 32/64 bit systems need 'special' help for ioctl where the user-space and kernel-space datatypes differ. Fixing the datatypes to be the same size, and align the same way for both 32 and 64-bit ppc and x86 environments will elimiante the need to have magic 32/64-bit ioctl translation code. --- shared-core/drm.h | 28 +++++++++++++++++----------- shared-core/i915_drm.h | 21 ++++++++++++--------- 2 files changed, 29 insertions(+), 20 deletions(-) (limited to 'shared-core') diff --git a/shared-core/drm.h b/shared-core/drm.h index 1f49cbb0..90c23fa7 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -967,25 +967,28 @@ struct drm_gem_alloc { * * The (page-aligned) allocated size for the object will be returned. */ - uint32_t size; + uint64_t size; /** * Returned handle for the object. * * Object handles are nonzero. */ uint32_t handle; + uint32_t pad; }; struct drm_gem_unreference { /** Handle of the object to be unreferenced. */ uint32_t handle; + uint32_t pad; }; struct drm_gem_link { /** Handle for the object being given a name. */ uint32_t handle; + uint32_t pad; /** Requested file name to export the object under. */ - char *name; + uint64_t name_ptr; /* char *, but pointers are not 32/64 compatible */ /** Requested file mode to export the object under. */ mode_t mode; }; @@ -993,38 +996,41 @@ struct drm_gem_link { struct drm_gem_pread { /** Handle for the object being read. */ uint32_t handle; + uint32_t pad; /** Offset into the object to read from */ - off_t offset; + uint64_t offset; /** Length of data to read */ - size_t size; + uint64_t size; /** Pointer to write the data into. */ - void *data; + uint64_t data_ptr; /* void *, but pointers are not 32/64 compatible */ }; struct drm_gem_pwrite { /** Handle for the object being written to. */ uint32_t handle; + uint32_t pad; /** Offset into the object to write to */ - off_t offset; + uint64_t offset; /** Length of data to write */ - size_t size; + uint64_t size; /** Pointer to read the data from. */ - void *data; + uint64_t data_ptr; /* void *, but pointers are not 32/64 compatible */ }; struct drm_gem_mmap { /** Handle for the object being mapped. */ uint32_t handle; + uint32_t pad; /** Offset in the object to map. */ - off_t offset; + uint64_t offset; /** * Length of data to map. * * The value will be page-aligned. */ - size_t size; + uint64_t size; /** Returned pointer the data was mapped at */ - void *addr; + uint64_t addr_ptr; /* void *, but pointers are not 32/64 compatible */ }; /** diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 4d113e4c..91461c41 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -407,12 +407,12 @@ struct drm_i915_gem_init { * Beginning offset in the GTT to be managed by the DRM memory * manager. */ - off_t gtt_start; + uint64_t gtt_start; /** * Ending offset in the GTT to be managed by the DRM memory * manager. */ - off_t gtt_end; + uint64_t gtt_end; }; struct drm_i915_gem_relocation_entry { @@ -425,15 +425,15 @@ struct drm_i915_gem_relocation_entry { */ uint32_t target_handle; - /** Offset in the buffer the relocation entry will be written into */ - uint32_t offset; - /** * Value to be added to the offset of the target buffer to make up * the relocation entry. */ uint32_t delta; + /** Offset in the buffer the relocation entry will be written into */ + uint64_t offset; + /** * Offset value of the target buffer that the relocation entry was last * written as. @@ -442,7 +442,7 @@ struct drm_i915_gem_relocation_entry { * and writing the relocation. This value is written back out by * the execbuffer ioctl when the relocation is written. */ - uint32_t presumed_offset; + uint64_t presumed_offset; }; struct drm_i915_gem_validate_entry { @@ -457,8 +457,9 @@ struct drm_i915_gem_validate_entry { */ uint32_t buffer_offset; /** List of relocations to be performed on this buffer */ - struct drm_i915_gem_relocation_entry *relocs; + uint64_t relocs_ptr; /* struct drm_i915_gem_relocation_entry *relocs */ uint32_t relocation_count; + uint32_t pad; }; struct drm_i915_gem_execbuffer { @@ -470,7 +471,7 @@ struct drm_i915_gem_execbuffer { * a buffer is performing refer to buffers that have already appeared * in the validate list. */ - struct drm_i915_gem_validate_entry *buffers; + uint64_t buffers_ptr; /* struct drm_i915_gem_validate_entry *buffers */ uint32_t buffer_count; /** Offset in the batchbuffer to start execution from. */ @@ -480,12 +481,13 @@ struct drm_i915_gem_execbuffer { uint32_t DR1; uint32_t DR4; uint32_t num_cliprects; - struct drm_clip_rect *cliprects; + uint64_t cliprects_ptr; /* struct drm_clip_rect *cliprects */ }; struct drm_i915_gem_pin { /** Handle of the buffer to be pinned. */ uint32_t handle; + uint32_t pad; /** Returned GTT offset of the buffer. */ uint64_t offset; @@ -494,6 +496,7 @@ struct drm_i915_gem_pin { struct drm_i915_gem_unpin { /** Handle of the buffer to be unpinned. */ uint32_t handle; + uint32_t pad; }; -- cgit v1.2.3 From 0d547c9ed92c0183f2c727496154baa2849f326e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 1 May 2008 20:41:55 -0700 Subject: Add alignment to all aperture allocation requests. When pinning buffers, or using execbuffer, allow the application to specify the necessary aperture allocation alignment constraints. --- shared-core/i915_drm.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 91461c41..0c64e866 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -451,15 +451,18 @@ struct drm_i915_gem_validate_entry { * operation. */ uint32_t buffer_handle; + + /** List of relocations to be performed on this buffer */ + uint32_t relocation_count; + uint64_t relocs_ptr; /* struct drm_i915_gem_relocation_entry *relocs */ + + /** Required alignment in graphics aperture */ + uint64_t alignment; /** * Returned value of the updated offset of the buffer, for future * presumed_offset writes. */ - uint32_t buffer_offset; - /** List of relocations to be performed on this buffer */ - uint64_t relocs_ptr; /* struct drm_i915_gem_relocation_entry *relocs */ - uint32_t relocation_count; - uint32_t pad; + uint64_t buffer_offset; }; struct drm_i915_gem_execbuffer { @@ -488,6 +491,9 @@ struct drm_i915_gem_pin { /** Handle of the buffer to be pinned. */ uint32_t handle; uint32_t pad; + + /** alignment required within the aperture */ + uint64_t alignment; /** Returned GTT offset of the buffer. */ uint64_t offset; -- cgit v1.2.3 From 5b5b68ffd220f43d4da35ac475b8a3dd91ebbfa7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 2 May 2008 10:34:46 -0700 Subject: Fix nouveau warning when returning pointers in uint64_t objects. --- shared-core/nouveau_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 555955d4..9e79d3bc 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -614,7 +614,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, struct drm_file * break; case NOUVEAU_GETPARAM_PCI_PHYSICAL: if ( dev -> sg ) - getparam->value=(uint64_t) dev->sg->virtual; + getparam->value=(uint64_t) (uintptr_t) dev->sg->virtual; else { DRM_ERROR("Requested PCIGART address, while no PCIGART was created\n"); -- cgit v1.2.3 From 49e8e3372afcf5fab9ffef5691d87ad8bc19599a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 2 May 2008 10:36:00 -0700 Subject: Remove drm_driver argument to functions taking drm_gem_object. Now that drm_gem_object has a drm_driver * in it, functions don't need both parameters. --- shared-core/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 801ac99e..0ebfedca 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -366,8 +366,8 @@ int i915_gem_pin_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_unpin_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -int i915_gem_init_object(struct drm_device *dev, struct drm_gem_object *obj); -void i915_gem_free_object(struct drm_device *dev, struct drm_gem_object *obj); +int i915_gem_init_object(struct drm_gem_object *obj); +void i915_gem_free_object(struct drm_gem_object *obj); #endif -- cgit v1.2.3 From 39e20bcd5f4bf9fedac80188fda2e9fcab2f0360 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 2 May 2008 12:28:49 -0700 Subject: Add name/open ioctls, separate handle and pointer ref counts. Names are just another unique integer set (from another idr object). Names are removed when the user refernces (handles) are all destroyed -- this required that handles for objects be counted separately from internal kernel references (so that we can tell when the handles are all gone). --- shared-core/drm.h | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'shared-core') diff --git a/shared-core/drm.h b/shared-core/drm.h index 90c23fa7..0e8da7b9 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -983,16 +983,6 @@ struct drm_gem_unreference { uint32_t pad; }; -struct drm_gem_link { - /** Handle for the object being given a name. */ - uint32_t handle; - uint32_t pad; - /** Requested file name to export the object under. */ - uint64_t name_ptr; /* char *, but pointers are not 32/64 compatible */ - /** Requested file mode to export the object under. */ - mode_t mode; -}; - struct drm_gem_pread { /** Handle for the object being read. */ uint32_t handle; @@ -1033,6 +1023,25 @@ struct drm_gem_mmap { uint64_t addr_ptr; /* void *, but pointers are not 32/64 compatible */ }; +struct drm_gem_name { + /** Handle for the object being named */ + uint32_t handle; + + /** Returned global name */ + uint32_t name; +}; + +struct drm_gem_open { + /** Name of object being opened */ + uint32_t name; + + /** Returned handle for the object */ + uint32_t handle; + + /** Returned size of the object */ + uint64_t size; +}; + /** * \name Ioctls Definitions */ @@ -1058,6 +1067,8 @@ struct drm_gem_mmap { #define DRM_IOCTL_GEM_PREAD DRM_IOW(0x0b, struct drm_gem_pread) #define DRM_IOCTL_GEM_PWRITE DRM_IOW(0x0c, struct drm_gem_pwrite) #define DRM_IOCTL_GEM_MMAP DRM_IOWR(0x0d, struct drm_gem_mmap) +#define DRM_IOCTL_GEM_NAME DRM_IOWR(0x0e, struct drm_gem_name) +#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0f, struct drm_gem_open) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) -- cgit v1.2.3 From b6f173c4300e90be9bdd3b24003b800afd8819c5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 5 May 2008 10:51:49 -0700 Subject: Add i915_dispatch_gem_execbuffer (broken). This function submits a gem-based execbuffer to the ring. It doesn't work yet. --- shared-core/i915_dma.c | 6 +++--- shared-core/i915_drv.h | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 73f843c8..4bf37325 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -458,9 +458,9 @@ static int i915_emit_cmds(struct drm_device *dev, int __user *buffer, return 0; } -static int i915_emit_box(struct drm_device * dev, - struct drm_clip_rect __user * boxes, - int i, int DR1, int DR4) +int i915_emit_box(struct drm_device * dev, + struct drm_clip_rect __user * boxes, + int i, int DR1, int DR4) { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_clip_rect box; diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 0ebfedca..c6d86584 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -299,6 +299,10 @@ extern int i915_dispatch_batchbuffer(struct drm_device * dev, drm_i915_batchbuffer_t * batch); extern int i915_quiescent(struct drm_device *dev); +int i915_emit_box(struct drm_device * dev, + struct drm_clip_rect __user * boxes, + int i, int DR1, int DR4); + /* i915_irq.c */ extern int i915_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv); -- cgit v1.2.3 From 4511e6cd80b4c47a142db48727753da8d0898857 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 5 May 2008 11:27:06 -0700 Subject: Correct execbuffer offset. Add memory barrier and chipset flush. --- shared-core/i915_dma.c | 1 + 1 file changed, 1 insertion(+) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 4bf37325..f23e2a36 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -470,6 +470,7 @@ int i915_emit_box(struct drm_device * dev, return -EFAULT; } + DRM_INFO ("box %d,%d - %d,%d\n", box.x1, box.y1, box.x2, box.y2); if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { DRM_ERROR("Bad box %d,%d..%d,%d\n", box.x1, box.y1, box.x2, box.y2); -- cgit v1.2.3 From d59a9300ec2ec5d6dc606f847a7589c197994793 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 5 May 2008 14:32:01 -0700 Subject: Remove some debug messages. --- shared-core/i915_dma.c | 1 - 1 file changed, 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index f23e2a36..4bf37325 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -470,7 +470,6 @@ int i915_emit_box(struct drm_device * dev, return -EFAULT; } - DRM_INFO ("box %d,%d - %d,%d\n", box.x1, box.y1, box.x2, box.y2); if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { DRM_ERROR("Bad box %d,%d..%d,%d\n", box.x1, box.y1, box.x2, box.y2); -- cgit v1.2.3 From ed6657fa8e7977b19bb836782ac8e87f0f703cef Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 5 May 2008 22:09:34 -0700 Subject: Monitor ACTHD register while polling for idle ring. When batch buffers are executing, the ring may be stuck for a long time. Monitor the ACTHD pointer which will show if the execution engine is actually hung. --- shared-core/i915_dma.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 4bf37325..d881a231 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -41,10 +41,14 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_ring_buffer_t *ring = &(dev_priv->ring); u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR; + u32 acthd_reg = IS_I965G(dev) ? I965REG_ACTHD : I915REG_ACTHD; + u32 last_acthd = I915_READ(acthd_reg); + u32 acthd; int i; - for (i = 0; i < 10000; i++) { + for (i = 0; i < 100000; i++) { ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR; + acthd = I915_READ(acthd_reg); ring->space = ring->head - (ring->tail + 8); if (ring->space < 0) ring->space += ring->Size; @@ -54,8 +58,12 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) if (ring->head != last_head) i = 0; + if (acthd != last_acthd) + i = 0; + last_head = ring->head; - DRM_UDELAY(1); + last_acthd = acthd; + DRM_UDELAY(10); } return -EBUSY; @@ -714,9 +722,19 @@ void i915_dispatch_flip(struct drm_device * dev, int planes, int sync) int i915_quiescent(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; + int ret; i915_kernel_lost_context(dev); - return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__); + ret = i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__); + if (ret) + { + i915_kernel_lost_context (dev); + DRM_ERROR ("not quiescent head %08x tail %08x space %08x\n", + dev_priv->ring.head, + dev_priv->ring.tail, + dev_priv->ring.space); + } + return ret; } static int i915_flush_ioctl(struct drm_device *dev, void *data, -- cgit v1.2.3 From 91cba3ae17eb34d1836164f86c13a2a8e08c2a29 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 5 May 2008 22:10:02 -0700 Subject: Dump last batch buffer when hardware lockup is detected. --- shared-core/i915_drv.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index c6d86584..6c06ff5c 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -544,6 +544,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define I915REG_INT_MASK_R 0x020a8 #define I915REG_INT_ENABLE_R 0x020a0 #define I915REG_INSTPM 0x020c0 +#define I965REG_ACTHD 0x02074 +#define I915REG_ACTHD 0x020C8 #define PIPEADSL 0x70000 #define PIPEBDSL 0x71000 -- cgit v1.2.3 From d2373b2a341868882208bb4297ab4f2f51302031 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 6 May 2008 13:28:26 -0700 Subject: GEM: Use irq-based fencing rather than syncing and evicting every exec. --- shared-core/i915_dma.c | 2 ++ shared-core/i915_drv.h | 10 ++++++++++ shared-core/i915_irq.c | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index d881a231..0601b89c 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1051,6 +1051,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ret = drm_addmap(dev, base, size, _DRM_REGISTERS, _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio_map); + INIT_LIST_HEAD(&dev_priv->mm.gtt_lru); + #ifdef __linux__ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) intel_init_chipset_flush_compat(dev); diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 6c06ff5c..bd6fa188 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -244,6 +244,8 @@ typedef struct drm_i915_private { struct { struct drm_memrange gtt_space; + /** LRU List of unpinned objects in the GTT. */ + struct list_head gtt_lru; } mm; } drm_i915_private_t; @@ -256,8 +258,12 @@ enum intel_chip_family { /** driver private structure attached to each drm_gem_object */ struct drm_i915_gem_object { + struct drm_gem_object *obj; + /** Current space allocated to this object in the GTT, if any. */ struct drm_memrange_node *gtt_space; + /** This object's place on the GTT LRU list */ + struct list_head gtt_lru_entry; /** AGP memory structure for our GTT binding. */ DRM_AGP_MEM *agp_mem; @@ -276,6 +282,9 @@ struct drm_i915_gem_object { /** How many users have pinned this object in GTT space */ int pin_count; + + /** Breadcrumb of last rendering to the buffer. */ + uint32_t last_rendering_cookie; }; extern struct drm_ioctl_desc i915_ioctls[]; @@ -318,6 +327,7 @@ extern int i915_vblank_pipe_set(struct drm_device *dev, void *data, extern int i915_vblank_pipe_get(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int i915_emit_irq(struct drm_device * dev); +extern int i915_wait_irq(struct drm_device * dev, int irq_nr); extern int i915_enable_vblank(struct drm_device *dev, int crtc); extern void i915_disable_vblank(struct drm_device *dev, int crtc); extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc); diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 785008d4..b17e2408 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -545,7 +545,7 @@ void i915_user_irq_off(drm_i915_private_t *dev_priv) } -static int i915_wait_irq(struct drm_device * dev, int irq_nr) +int i915_wait_irq(struct drm_device * dev, int irq_nr) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int ret = 0; -- cgit v1.2.3 From 631e86c5c4ad9b2cdd40749ea3b351204a362c80 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 6 May 2008 14:43:49 -0700 Subject: Start coding up memory domains --- shared-core/drm.h | 29 ++++++++++++++++++++++------- shared-core/i915_drm.h | 27 +++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 7 deletions(-) (limited to 'shared-core') diff --git a/shared-core/drm.h b/shared-core/drm.h index 0e8da7b9..f1430f59 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -1042,6 +1042,19 @@ struct drm_gem_open { uint64_t size; }; +struct drm_gem_set_domain { + /** Handle for the object */ + uint32_t handle; + + /** New read domains */ + uint32_t read_domains; + + /** New write domain */ + uint32_t write_domain; +}; + +#define DRM_GEM_DOMAIN_CPU 0x00000001 + /** * \name Ioctls Definitions */ @@ -1062,13 +1075,6 @@ struct drm_gem_open { #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) #define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) #define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) -#define DRM_IOCTL_GEM_ALLOC DRM_IOWR(0x09, struct drm_gem_alloc) -#define DRM_IOCTL_GEM_UNREFERENCE DRM_IOW(0x0a, struct drm_gem_unreference) -#define DRM_IOCTL_GEM_PREAD DRM_IOW(0x0b, struct drm_gem_pread) -#define DRM_IOCTL_GEM_PWRITE DRM_IOW(0x0c, struct drm_gem_pwrite) -#define DRM_IOCTL_GEM_MMAP DRM_IOWR(0x0d, struct drm_gem_mmap) -#define DRM_IOCTL_GEM_NAME DRM_IOWR(0x0e, struct drm_gem_name) -#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0f, struct drm_gem_open) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) @@ -1117,6 +1123,15 @@ struct drm_gem_open { #define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw) +#define DRM_IOCTL_GEM_ALLOC DRM_IOWR(0x09, struct drm_gem_alloc) +#define DRM_IOCTL_GEM_UNREFERENCE DRM_IOW (0x0a, struct drm_gem_unreference) +#define DRM_IOCTL_GEM_PREAD DRM_IOW (0x0b, struct drm_gem_pread) +#define DRM_IOCTL_GEM_PWRITE DRM_IOW (0x0c, struct drm_gem_pwrite) +#define DRM_IOCTL_GEM_MMAP DRM_IOWR(0x0d, struct drm_gem_mmap) +#define DRM_IOCTL_GEM_NAME DRM_IOWR(0x0e, struct drm_gem_name) +#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0f, struct drm_gem_open) +#define DRM_IOCTL_GEM_SET_DOMAIN DRM_IOW (0xb7, struct drm_gem_set_domain) + #define DRM_IOCTL_MM_INIT DRM_IOWR(0xc0, struct drm_mm_init_arg) #define DRM_IOCTL_MM_TAKEDOWN DRM_IOWR(0xc1, struct drm_mm_type_arg) #define DRM_IOCTL_MM_LOCK DRM_IOWR(0xc2, struct drm_mm_type_arg) diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 0c64e866..302fc646 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -445,6 +445,28 @@ struct drm_i915_gem_relocation_entry { uint64_t presumed_offset; }; +/** + * Intel memory domains + * + * Most of these just align with the various caches in + * the system and are used to flush and invalidate as + * objects end up cached in different domains. + * + * STOLEN is a domain for the stolen memory portion of the + * address space; those pages are accessible only through the + * GTT and, hence, look a lot like VRAM on a discrete card. + * We'll allow programs to move objects into stolen memory + * mostly as a way to demonstrate the VRAM capabilities of this + * API + */ + +/* 0x00000001 is DRM_GEM_DOMAIN_CPU */ +#define DRM_GEM_DOMAIN_I915_RENDER 0x00000002 /* Render cache, used by 2D and 3D drawing */ +#define DRM_GEM_DOMAIN_I915_SAMPLER 0x00000004 /* Sampler cache, used by texture engine */ +#define DRM_GEM_DOMAIN_I915_COMMAND 0x00000008 /* Command queue, used to load batch buffers */ +#define DRM_GEM_DOMAIN_I915_INSTRUCTION 0x00000010 /* Instruction cache, used by shader programs */ +#define DRM_GEM_DOMAIN_I915_STOLEN 0x00000020 /* Stolen memory, needed by some objects */ + struct drm_i915_gem_validate_entry { /** * User's handle for a buffer to be bound into the GTT for this @@ -458,6 +480,11 @@ struct drm_i915_gem_validate_entry { /** Required alignment in graphics aperture */ uint64_t alignment; + + /** Memory domains used in this execbuffer run */ + uint32_t read_domains; + uint32_t write_domain; + /** * Returned value of the updated offset of the buffer, for future * presumed_offset writes. -- cgit v1.2.3 From 6a6c37af9ecaabfe1399a1300cadaff730767013 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 6 May 2008 21:59:06 -0700 Subject: [intel-GEM] ref count objects in gtt-lru. If objects on the lru aren't ref counted, they'll get pulled from the gtt as soon as they are freed. This change does cause objects to get stuck in the gtt until they're forced out by new requests. The lru should get cleaned when the irq occurs. --- shared-core/i915_drv.h | 1 + 1 file changed, 1 insertion(+) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index bd6fa188..daa77f72 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -262,6 +262,7 @@ struct drm_i915_gem_object { /** Current space allocated to this object in the GTT, if any. */ struct drm_memrange_node *gtt_space; + /** This object's place on the GTT LRU list */ struct list_head gtt_lru_entry; -- cgit v1.2.3 From 5f5f01ed91f5ad50f2b38e11740a30441ac845a4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 7 May 2008 12:46:06 -0700 Subject: GEM: Extend cache domain stuff for 965. One of our MI_FLUSH bits is reserved on 965, being always implied, and there's a vertex cache that was forgotten. --- shared-core/i915_drm.h | 1 + 1 file changed, 1 insertion(+) (limited to 'shared-core') diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 302fc646..8c3cd646 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -466,6 +466,7 @@ struct drm_i915_gem_relocation_entry { #define DRM_GEM_DOMAIN_I915_COMMAND 0x00000008 /* Command queue, used to load batch buffers */ #define DRM_GEM_DOMAIN_I915_INSTRUCTION 0x00000010 /* Instruction cache, used by shader programs */ #define DRM_GEM_DOMAIN_I915_STOLEN 0x00000020 /* Stolen memory, needed by some objects */ +#define DRM_GEM_DOMAIN_I915_VERTEX 0x00000040 /* Vertex address cache */ struct drm_i915_gem_validate_entry { /** -- cgit v1.2.3 From 9af4c497433398fa4576a7c1c31036448cf4f24c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 8 May 2008 10:44:02 -0700 Subject: [intel-gem] Move domains to relocation records. add set_domain ioctl. Domain information is about buffer relationships, not buffer contents. That means a relocation contains the domain information as it knows how the source buffer references the target buffer. This also adds the set_domain ioctl so that user space can move buffers to the cpu domain. --- shared-core/i915_drm.h | 28 +++++++++++++++------------- shared-core/i915_drv.h | 3 +++ 2 files changed, 18 insertions(+), 13 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 8c3cd646..d71447e6 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -443,6 +443,20 @@ struct drm_i915_gem_relocation_entry { * the execbuffer ioctl when the relocation is written. */ uint64_t presumed_offset; + + /** + * Target memory domains read by this operation. + */ + uint32_t read_domains; + + /** + * Target memory domains written by this operation. + * + * Note that only one domain may be written by the whole + * execbuffer operation, so that where there are conflicts, + * the application will get -EINVAL back. + */ + uint32_t write_domain; }; /** @@ -451,13 +465,6 @@ struct drm_i915_gem_relocation_entry { * Most of these just align with the various caches in * the system and are used to flush and invalidate as * objects end up cached in different domains. - * - * STOLEN is a domain for the stolen memory portion of the - * address space; those pages are accessible only through the - * GTT and, hence, look a lot like VRAM on a discrete card. - * We'll allow programs to move objects into stolen memory - * mostly as a way to demonstrate the VRAM capabilities of this - * API */ /* 0x00000001 is DRM_GEM_DOMAIN_CPU */ @@ -465,8 +472,7 @@ struct drm_i915_gem_relocation_entry { #define DRM_GEM_DOMAIN_I915_SAMPLER 0x00000004 /* Sampler cache, used by texture engine */ #define DRM_GEM_DOMAIN_I915_COMMAND 0x00000008 /* Command queue, used to load batch buffers */ #define DRM_GEM_DOMAIN_I915_INSTRUCTION 0x00000010 /* Instruction cache, used by shader programs */ -#define DRM_GEM_DOMAIN_I915_STOLEN 0x00000020 /* Stolen memory, needed by some objects */ -#define DRM_GEM_DOMAIN_I915_VERTEX 0x00000040 /* Vertex address cache */ +#define DRM_GEM_DOMAIN_I915_VERTEX 0x00000020 /* Vertex address cache */ struct drm_i915_gem_validate_entry { /** @@ -482,10 +488,6 @@ struct drm_i915_gem_validate_entry { /** Required alignment in graphics aperture */ uint64_t alignment; - /** Memory domains used in this execbuffer run */ - uint32_t read_domains; - uint32_t write_domain; - /** * Returned value of the updated offset of the buffer, for future * presumed_offset writes. diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index daa77f72..96257ab6 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -383,6 +383,9 @@ int i915_gem_unpin_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_init_object(struct drm_gem_object *obj); void i915_gem_free_object(struct drm_gem_object *obj); +int i915_gem_set_domain_ioctl (struct drm_gem_object *obj, + uint32_t read_domains, + uint32_t write_domain); #endif -- cgit v1.2.3 From 1e26ca44c9f3e8a1a30652aa860b405e0248aae1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 9 May 2008 12:18:09 -0700 Subject: [gem] API cleanup. allocate->create unreference->close name->flink Make the API names a bit more consistent. --- shared-core/drm.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'shared-core') diff --git a/shared-core/drm.h b/shared-core/drm.h index f1430f59..7b69a634 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -961,7 +961,7 @@ struct drm_mm_info_arg { }; -struct drm_gem_alloc { +struct drm_gem_create { /** * Requested size for the object. * @@ -977,8 +977,8 @@ struct drm_gem_alloc { uint32_t pad; }; -struct drm_gem_unreference { - /** Handle of the object to be unreferenced. */ +struct drm_gem_close { + /** Handle of the object to be closed. */ uint32_t handle; uint32_t pad; }; @@ -1023,7 +1023,7 @@ struct drm_gem_mmap { uint64_t addr_ptr; /* void *, but pointers are not 32/64 compatible */ }; -struct drm_gem_name { +struct drm_gem_flink { /** Handle for the object being named */ uint32_t handle; @@ -1123,12 +1123,12 @@ struct drm_gem_set_domain { #define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw) -#define DRM_IOCTL_GEM_ALLOC DRM_IOWR(0x09, struct drm_gem_alloc) -#define DRM_IOCTL_GEM_UNREFERENCE DRM_IOW (0x0a, struct drm_gem_unreference) +#define DRM_IOCTL_GEM_CREATE DRM_IOWR(0x09, struct drm_gem_create) +#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x0a, struct drm_gem_close) #define DRM_IOCTL_GEM_PREAD DRM_IOW (0x0b, struct drm_gem_pread) #define DRM_IOCTL_GEM_PWRITE DRM_IOW (0x0c, struct drm_gem_pwrite) #define DRM_IOCTL_GEM_MMAP DRM_IOWR(0x0d, struct drm_gem_mmap) -#define DRM_IOCTL_GEM_NAME DRM_IOWR(0x0e, struct drm_gem_name) +#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0e, struct drm_gem_flink) #define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0f, struct drm_gem_open) #define DRM_IOCTL_GEM_SET_DOMAIN DRM_IOW (0xb7, struct drm_gem_set_domain) -- cgit v1.2.3 From c5c59eab809604e4d0d4d1dc71fc11186d0220f8 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 9 May 2008 14:34:20 -0700 Subject: GEM: Separate the LRU into execution list and LRU list. Now, the LRU list has objects that are completely done rendering and ready to kick out, while the execution list has things with active rendering, which have associated cookies and reference counts on them. --- shared-core/i915_dma.c | 2 ++ shared-core/i915_drv.h | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 0601b89c..24f361e0 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1052,6 +1052,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio_map); INIT_LIST_HEAD(&dev_priv->mm.gtt_lru); + INIT_LIST_HEAD(&dev_priv->mm.execution_list); #ifdef __linux__ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) @@ -1093,6 +1094,7 @@ void i915_driver_lastclose(struct drm_device * dev) dev_priv->val_bufs = NULL; } #endif + i915_gem_lastclose(dev); if (drm_getsarea(dev) && dev_priv->sarea_priv) i915_do_cleanup_pageflip(dev); diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 96257ab6..413fca89 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -244,7 +244,12 @@ typedef struct drm_i915_private { struct { struct drm_memrange gtt_space; - /** LRU List of unpinned objects in the GTT. */ + /** + * List of objects currently involved in rendering from the + * ringbuffer. + */ + struct list_head execution_list; + /** LRU List of non-executing objects still in the GTT. */ struct list_head gtt_lru; } mm; } drm_i915_private_t; @@ -386,7 +391,7 @@ void i915_gem_free_object(struct drm_gem_object *obj); int i915_gem_set_domain_ioctl (struct drm_gem_object *obj, uint32_t read_domains, uint32_t write_domain); - +void i915_gem_lastclose(struct drm_device *dev); #endif #ifdef __linux__ -- cgit v1.2.3 From a37ac493da1730436028ecc79a38513380ce15d0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 10 May 2008 21:04:18 -0700 Subject: [intel-GEM] Clean up GEM ioctl naming. Rename 'validate_entry' to 'exec_object', then clean up some field names in structures (renaming buffer_offset to just offset, for example). --- shared-core/i915_drm.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index d71447e6..5f7cefeb 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -474,12 +474,12 @@ struct drm_i915_gem_relocation_entry { #define DRM_GEM_DOMAIN_I915_INSTRUCTION 0x00000010 /* Instruction cache, used by shader programs */ #define DRM_GEM_DOMAIN_I915_VERTEX 0x00000020 /* Vertex address cache */ -struct drm_i915_gem_validate_entry { +struct drm_i915_gem_exec_object { /** * User's handle for a buffer to be bound into the GTT for this * operation. */ - uint32_t buffer_handle; + uint32_t handle; /** List of relocations to be performed on this buffer */ uint32_t relocation_count; @@ -489,10 +489,10 @@ struct drm_i915_gem_validate_entry { uint64_t alignment; /** - * Returned value of the updated offset of the buffer, for future + * Returned value of the updated offset of the object, for future * presumed_offset writes. */ - uint64_t buffer_offset; + uint64_t offset; }; struct drm_i915_gem_execbuffer { -- cgit v1.2.3 From ff39db099b9ca6c8feee68101a2269345b7bd798 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 11 May 2008 00:10:16 -0700 Subject: [GEM] Make pread/pwrite manage memory domains. No luck with movnti though. pread and pwrite must update the memory domains to ensure consistency with the GPU. At some point, it should be possible to avoid clflush through this path, but that isn't working for me. --- shared-core/i915_drv.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 413fca89..78c5d3df 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -391,6 +391,8 @@ void i915_gem_free_object(struct drm_gem_object *obj); int i915_gem_set_domain_ioctl (struct drm_gem_object *obj, uint32_t read_domains, uint32_t write_domain); +int i915_gem_flush_pwrite(struct drm_gem_object *obj, + uint64_t offset, uint64_t size); void i915_gem_lastclose(struct drm_device *dev); #endif -- cgit v1.2.3 From 7e7ea313c4a38370194290d05697bdb6a746669d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 12 May 2008 13:03:16 -0700 Subject: [intel] When polling for ring space, sleep for a lot longer (10ms) If the ring is full, the engine will surely be running for more than 10ms. --- shared-core/i915_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 24f361e0..cf2dfeb6 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -63,7 +63,7 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) last_head = ring->head; last_acthd = acthd; - DRM_UDELAY(10); + msleep_interruptible (10); } return -EBUSY; -- cgit v1.2.3 From f650d7240a5b6eea8e605734f1211c20727c21d7 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 12 May 2008 12:55:36 -0700 Subject: [GEM] Typo (and thinking) fixes in drm-gem.txt and doxygen. --- shared-core/i915_drm.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 5f7cefeb..b50471f3 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -420,8 +420,9 @@ struct drm_i915_gem_relocation_entry { * Handle of the buffer being pointed to by this relocation entry. * * It's appealing to make this be an index into the mm_validate_entry - * list to refer to the buffer, but handle lookup should be O(1) anyway, - * and prevents O(n) search in userland to find what that index is. + * list to refer to the buffer, but this allows the driver to create + * a relocation list for state buffers and not re-write it per + * exec using the buffer. */ uint32_t target_handle; @@ -497,7 +498,7 @@ struct drm_i915_gem_exec_object { struct drm_i915_gem_execbuffer { /** - * List of buffers to be validated wit their relocations to be + * List of buffers to be validated with their relocations to be * performend on them. * * These buffers must be listed in an order such that all relocations -- cgit v1.2.3 From 3ab152da66f6c7bcc68a13efcf4a62800354f13b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 15 May 2008 09:37:49 -0700 Subject: [gem] Rename the GTT LRU lists to active (executing) and inactive (idle). --- shared-core/i915_dma.c | 4 ++-- shared-core/i915_drv.h | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index cf2dfeb6..0e832057 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1051,8 +1051,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ret = drm_addmap(dev, base, size, _DRM_REGISTERS, _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio_map); - INIT_LIST_HEAD(&dev_priv->mm.gtt_lru); - INIT_LIST_HEAD(&dev_priv->mm.execution_list); + INIT_LIST_HEAD(&dev_priv->mm.active_list); + INIT_LIST_HEAD(&dev_priv->mm.inactive_list); #ifdef __linux__ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 78c5d3df..51c6bb59 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -248,9 +248,9 @@ typedef struct drm_i915_private { * List of objects currently involved in rendering from the * ringbuffer. */ - struct list_head execution_list; + struct list_head active_list; /** LRU List of non-executing objects still in the GTT. */ - struct list_head gtt_lru; + struct list_head inactive_list; } mm; } drm_i915_private_t; @@ -267,9 +267,9 @@ struct drm_i915_gem_object { /** Current space allocated to this object in the GTT, if any. */ struct drm_memrange_node *gtt_space; - - /** This object's place on the GTT LRU list */ - struct list_head gtt_lru_entry; + + /** This object's place on the active or inactive lists */ + struct list_head list; /** AGP memory structure for our GTT binding. */ DRM_AGP_MEM *agp_mem; -- cgit v1.2.3 From 7dced2f33a952ad12aafb7a3e34747156020a3ae Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 15 May 2008 11:21:11 -0700 Subject: [gem] Hold dev->struct_mutex to protect structure data. --- shared-core/i915_drv.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 51c6bb59..296e1823 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -388,9 +388,9 @@ int i915_gem_unpin_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_init_object(struct drm_gem_object *obj); void i915_gem_free_object(struct drm_gem_object *obj); -int i915_gem_set_domain_ioctl (struct drm_gem_object *obj, - uint32_t read_domains, - uint32_t write_domain); +int i915_gem_set_domain(struct drm_gem_object *obj, + uint32_t read_domains, + uint32_t write_domain); int i915_gem_flush_pwrite(struct drm_gem_object *obj, uint64_t offset, uint64_t size); void i915_gem_lastclose(struct drm_device *dev); -- cgit v1.2.3 From 6c3ac484b049681f9f3e692f9a6238ed122a8191 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 20 May 2008 10:48:36 -0700 Subject: [gem] Clean up active/inactive list handling using helper functions. Additionally, a boolean active field is added to indicate which list an object is on, rather than smashing last_rendering_cookie to 0 to show inactive. This will help with flush-reduction later on, and makes the code clearer. --- shared-core/i915_drv.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 296e1823..870726c5 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -247,9 +247,18 @@ typedef struct drm_i915_private { /** * List of objects currently involved in rendering from the * ringbuffer. + * + * A reference is held on the buffer while on this list. */ struct list_head active_list; - /** LRU List of non-executing objects still in the GTT. */ + /** + * LRU List of non-executing objects still in the GTT. + * There may still be dirty cachelines that need to be flushed + * before unbind. + * A reference is not held on the buffer while on this list, + * as merely being GTT-bound shouldn't prevent its being + * freed, and we'll pull it off the list in the free path. + */ struct list_head inactive_list; } mm; } drm_i915_private_t; @@ -271,6 +280,13 @@ struct drm_i915_gem_object { /** This object's place on the active or inactive lists */ struct list_head list; + /** + * This is set if the object is on the active list + * (has pending rendering), and is not set if it's on inactive (ready + * to be unbound). + */ + int active; + /** AGP memory structure for our GTT binding. */ DRM_AGP_MEM *agp_mem; -- cgit v1.2.3 From ab36a6f983107971890e81473452b3f0313fb692 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 20 May 2008 10:52:24 -0700 Subject: [gem] Rename sequence numbers from "cookie" to "seqno" --- shared-core/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 870726c5..79c607bc 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -306,7 +306,7 @@ struct drm_i915_gem_object { int pin_count; /** Breadcrumb of last rendering to the buffer. */ - uint32_t last_rendering_cookie; + uint32_t last_rendering_seqno; }; extern struct drm_ioctl_desc i915_ioctls[]; -- cgit v1.2.3 From af8e087157ef5034fa12d93202037f87da61355d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 20 May 2008 14:03:27 -0700 Subject: [gem] Use a separate sequence number field from classic/ttm This lets us get some qualities we desire, such as using the full 32-bit range (except zero), avoiding DRM_WAIT_ON, and a 1:1 mapping of active sequence numbers to request structs, which will be used soon for throttling and interrupt-driven list cleanup. --- shared-core/i915_dma.c | 4 +++- shared-core/i915_drv.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 0e832057..30ba8c65 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -524,7 +524,7 @@ void i915_emit_breadcrumb(struct drm_device *dev) BEGIN_LP_RING(4); OUT_RING(CMD_STORE_DWORD_IDX); - OUT_RING(20); + OUT_RING(5 << STORE_DWORD_INDEX_SHIFT); OUT_RING(dev_priv->counter); OUT_RING(0); ADVANCE_LP_RING(); @@ -1053,6 +1053,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) INIT_LIST_HEAD(&dev_priv->mm.active_list); INIT_LIST_HEAD(&dev_priv->mm.inactive_list); + INIT_LIST_HEAD(&dev_priv->mm.request_list); + dev_priv->mm.next_gem_seqno = 1; #ifdef __linux__ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 79c607bc..ef41b433 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -260,6 +260,14 @@ typedef struct drm_i915_private { * freed, and we'll pull it off the list in the free path. */ struct list_head inactive_list; + + /** + * List of breadcrumbs associated with GPU requests currently + * outstanding. + */ + struct list_head request_list; + + uint32_t next_gem_seqno; } mm; } drm_i915_private_t; @@ -309,6 +317,23 @@ struct drm_i915_gem_object { uint32_t last_rendering_seqno; }; +/** + * Request queue structure. + * + * The request queue allows us to note sequence numbers that have been emitted + * and may be associated with active buffers to be retired. + * + * By keeping this list, we can avoid having to do questionable + * sequence-number comparisons on buffer last_rendering_seqnos, and associate + * an emission time with seqnos for tracking how far ahead of the GPU we are. + */ +struct drm_i915_gem_request { + /** GEM sequence number associated with this request. */ + uint32_t seqno; + + struct list_head list; +}; + extern struct drm_ioctl_desc i915_ioctls[]; extern int i915_max_ioctl; @@ -506,7 +531,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23)) #define CMD_REPORT_HEAD (7<<23) #define CMD_STORE_DWORD_IMM ((0x20<<23) | (0x1 << 22) | 0x1) +/** + * Stores a 32-bit integer to the status page at the dword index given. + */ #define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1) +# define STORE_DWORD_INDEX_SHIFT 2 + #define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1) #define CMD_MI_FLUSH (0x04 << 23) @@ -855,7 +885,22 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1) #define READ_BREADCRUMB(dev_priv) (((volatile u32*)(dev_priv->hw_status_page))[5]) + +/** + * Reads a dword out of the status page, which is written to from the command + * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or + * MI_STORE_DATA_IMM. + * + * The following dwords have a reserved meaning: + * 0: ISR copy, updated when an ISR bit not set in the HWSTAM changes. + * 4: ring 0 head pointer + * 5: ring 1 head pointer (915-class) + * 6: ring 2 head pointer (915-class) + * + * The area from dword 0x10 to 0x3ff is available for driver usage. + */ #define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg]) +#define I915_GEM_HWS_INDEX 0x10 #define BLC_PWM_CTL 0x61254 #define BACKLIGHT_MODULATION_FREQ_SHIFT (17) -- cgit v1.2.3 From d6f796857780fc54641047e2aa4e7091376928eb Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 20 May 2008 16:27:05 -0700 Subject: [gem] Replace ring throttling hack with actual time measurement. --- shared-core/i915_drv.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index ef41b433..e3f280d5 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -331,6 +331,9 @@ struct drm_i915_gem_request { /** GEM sequence number associated with this request. */ uint32_t seqno; + /** Time at which this request was emitted, in jiffies. */ + unsigned long emitted_jiffies; + struct list_head list; }; -- cgit v1.2.3 From 5e662f90d1143de53db866e2b8a94f1bfbe5fc51 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 14 May 2008 15:13:14 -0700 Subject: [gem] Release GEM buffers from work task scheduled from IRQ. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are now 3 lists. Active is buffers currently in the ringbuffer. Flushing is not in the ringbuffer, but needs a flush before unbinding. Inactive is as before. This prevents object_free → unbind → wait_rendering → object_reference and a kernel oops about weird refcounting. This also avoids an synchronous extra flush and wait when freeing a buffer which had a write_domain set (such as a temporary rendered to and then from using the 2d engine). It will sit around on the flushing list until the appropriate flush gets emitted, or we need the GTT space for another operation. --- shared-core/i915_dma.c | 4 ++++ shared-core/i915_drv.h | 30 +++++++++++++++++++++++++----- shared-core/i915_irq.c | 23 +++++++++++++++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 30ba8c65..fa73cd29 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1043,6 +1043,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) memset(dev_priv, 0, sizeof(drm_i915_private_t)); dev->dev_private = (void *)dev_priv; + dev_priv->dev = dev; /* Add register map (needed for suspend/resume) */ base = drm_get_resource_start(dev, mmio_bar); @@ -1052,8 +1053,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio_map); INIT_LIST_HEAD(&dev_priv->mm.active_list); + INIT_LIST_HEAD(&dev_priv->mm.flushing_list); INIT_LIST_HEAD(&dev_priv->mm.inactive_list); INIT_LIST_HEAD(&dev_priv->mm.request_list); + INIT_WORK(&dev_priv->user_interrupt_task, + i915_user_interrupt_handler); dev_priv->mm.next_gem_seqno = 1; #ifdef __linux__ diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index e3f280d5..029c39a0 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -101,6 +101,8 @@ typedef struct _drm_i915_vbl_swap { } drm_i915_vbl_swap_t; typedef struct drm_i915_private { + struct drm_device *dev; + drm_local_map_t *sarea; drm_local_map_t *mmio_map; @@ -244,6 +246,7 @@ typedef struct drm_i915_private { struct { struct drm_memrange gtt_space; + /** * List of objects currently involved in rendering from the * ringbuffer. @@ -251,10 +254,20 @@ typedef struct drm_i915_private { * A reference is held on the buffer while on this list. */ struct list_head active_list; + /** - * LRU List of non-executing objects still in the GTT. - * There may still be dirty cachelines that need to be flushed - * before unbind. + * List of objects which are not in the ringbuffer but which + * still have a write_domain which needs to be flushed before + * unbinding. + * + * A reference is held on the buffer while on this list. + */ + struct list_head flushing_list; + + /** + * LRU list of objects which are not in the ringbuffer and + * are ready to unbind, but are still in the GTT. + * * A reference is not held on the buffer while on this list, * as merely being GTT-bound shouldn't prevent its being * freed, and we'll pull it off the list in the free path. @@ -269,6 +282,8 @@ typedef struct drm_i915_private { uint32_t next_gem_seqno; } mm; + + struct work_struct user_interrupt_task; } drm_i915_private_t; enum intel_chip_family { @@ -285,11 +300,11 @@ struct drm_i915_gem_object { /** Current space allocated to this object in the GTT, if any. */ struct drm_memrange_node *gtt_space; - /** This object's place on the active or inactive lists */ + /** This object's place on the active/flushing/inactive lists */ struct list_head list; /** - * This is set if the object is on the active list + * This is set if the object is on the active or flushing lists * (has pending rendering), and is not set if it's on inactive (ready * to be unbound). */ @@ -334,6 +349,9 @@ struct drm_i915_gem_request { /** Time at which this request was emitted, in jiffies. */ unsigned long emitted_jiffies; + /** Cache domains that were flushed at the start of the request. */ + uint32_t flush_domains; + struct list_head list; }; @@ -385,6 +403,7 @@ extern int i915_vblank_swap(struct drm_device *dev, void *data, struct drm_file *file_priv); extern void i915_user_irq_on(drm_i915_private_t *dev_priv); extern void i915_user_irq_off(drm_i915_private_t *dev_priv); +extern void i915_user_interrupt_handler(struct work_struct *work); /* i915_mem.c */ extern int i915_mem_alloc(struct drm_device *dev, void *data, @@ -438,6 +457,7 @@ int i915_gem_set_domain(struct drm_gem_object *obj, int i915_gem_flush_pwrite(struct drm_gem_object *obj, uint64_t offset, uint64_t size); void i915_gem_lastclose(struct drm_device *dev); +void i915_gem_retire_requests(struct drm_device *dev); #endif #ifdef __linux__ diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index b17e2408..02191316 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -436,6 +436,28 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane) return count; } +/** + * Handler for user interrupts in process context (able to sleep, do VFS + * operations, etc. + * + * If another IRQ comes in while we're in this handler, it will still get put + * on the queue again to be rerun when we finish. + */ +void +i915_user_interrupt_handler(struct work_struct *work) +{ + drm_i915_private_t *dev_priv; + struct drm_device *dev; + + dev_priv = container_of(work, drm_i915_private_t, + user_interrupt_task); + dev = dev_priv->dev; + + mutex_lock(&dev->struct_mutex); + i915_gem_retire_requests(dev); + mutex_unlock(&dev->struct_mutex); +} + irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@ -493,6 +515,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) DRM_WAKEUP(&dev_priv->irq_queue); #ifdef I915_HAVE_FENCE i915_fence_handler(dev); + schedule_work(&dev_priv->user_interrupt_task); #endif } -- cgit v1.2.3 From a51c3a76ff415104426493a97ac686ccfe3f3926 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 May 2008 10:48:32 -0700 Subject: [intel] Add debug code to verify the cached ring tail pointer. Recording the tail pointer in a local variable improves performance, but if someone messes up and fails to reload at the right time, the driver will write commands to the wrong part of the ring and scramble execution badly. This change (available by setting I915_RING_VALIDATE to 1) checks to make sure the cached tail pointer matches the hardware tail pointer at each ring buffer addition, calling BUG_ON when that's not true. --- shared-core/i915_dma.c | 24 ++++++++++++++++++++++++ shared-core/i915_drv.h | 10 ++++++++++ 2 files changed, 34 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index fa73cd29..1fc617d1 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -69,6 +69,30 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) return -EBUSY; } +#if I915_RING_VALIDATE +/** + * Validate the cached ring tail value + * + * If the X server writes to the ring and DRM doesn't + * reload the head and tail pointers, it will end up writing + * data to the wrong place in the ring, causing havoc. + */ +void i915_ring_validate(struct drm_device *dev, const char *func, int line) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_ring_buffer_t *ring = &(dev_priv->ring); + u32 tail = I915_READ(LP_RING+RING_TAIL) & HEAD_ADDR; + u32 head = I915_READ(LP_RING+RING_HEAD) & HEAD_ADDR; + + if (tail != ring->tail) { + DRM_ERROR("%s:%d head sw %x, hw %x. tail sw %x hw %x\n", + func, line, + ring->head, head, ring->tail, tail); + BUG_ON(1); + } +} +#endif + void i915_kernel_lost_context(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 029c39a0..e217b789 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -473,14 +473,23 @@ extern void intel_fini_chipset_flush_compat(struct drm_device *dev); #define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, (reg), (val)) #define I915_VERBOSE 0 +#define I915_RING_VALIDATE 0 #define RING_LOCALS unsigned int outring, ringmask, outcount; \ volatile char *virt; +#if I915_RING_VALIDATE +void i915_ring_validate(struct drm_device *dev, const char *func, int line); +#define I915_RING_DO_VALIDATE(dev) i915_ring_validate(dev, __FUNCTION__, __LINE__) +#else +#define I915_RING_DO_VALIDATE(dev) +#endif + #define BEGIN_LP_RING(n) do { \ if (I915_VERBOSE) \ DRM_DEBUG("BEGIN_LP_RING(%d)\n", \ (n)); \ + I915_RING_DO_VALIDATE(dev); \ if (dev_priv->ring.space < (n)*4) \ i915_wait_ring(dev, (n)*4, __FUNCTION__); \ outcount = 0; \ @@ -499,6 +508,7 @@ extern void intel_fini_chipset_flush_compat(struct drm_device *dev); #define ADVANCE_LP_RING() do { \ if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring); \ + I915_RING_DO_VALIDATE(dev); \ dev_priv->ring.tail = outring; \ dev_priv->ring.space -= outcount * 4; \ I915_WRITE(LP_RING + RING_TAIL, outring); \ -- cgit v1.2.3 From 7cf3fd29fe058a0bfc2ba7e889d1b360398be161 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 25 May 2008 20:45:20 -0700 Subject: [intel-gem] Add DRM_I915_GEM_BUSY ioctl to check for idle buffers. This new ioctl returns whether re-using the buffer would force a wait. --- shared-core/i915_dma.c | 1 + shared-core/i915_drm.h | 9 +++++++++ shared-core/i915_drv.h | 2 ++ 3 files changed, 12 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 1fc617d1..76cd45f1 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1180,6 +1180,7 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH), DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index b50471f3..a8e09e72 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -180,6 +180,7 @@ typedef struct drm_i915_sarea { #define DRM_I915_GEM_EXECBUFFER 0x14 #define DRM_I915_GEM_PIN 0x15 #define DRM_I915_GEM_UNPIN 0x16 +#define DRM_I915_GEM_BUSY 0x17 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -203,6 +204,7 @@ typedef struct drm_i915_sarea { #define DRM_IOCTL_I915_GEM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer) #define DRM_IOCTL_I915_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin) #define DRM_IOCTL_I915_GEM_UNPIN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin) +#define DRM_IOCTL_I915_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy) /* Asynchronous page flipping: */ @@ -536,5 +538,12 @@ struct drm_i915_gem_unpin { uint32_t pad; }; +struct drm_i915_gem_busy { + /** Handle of the buffer to check for busy */ + uint32_t handle; + + /** Return busy status (1 if busy, 0 if idle) */ + uint32_t busy; +}; #endif /* _I915_DRM_H_ */ diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index e217b789..04e149a9 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -449,6 +449,8 @@ int i915_gem_pin_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_unpin_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int i915_gem_busy_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); int i915_gem_init_object(struct drm_gem_object *obj); void i915_gem_free_object(struct drm_gem_object *obj); int i915_gem_set_domain(struct drm_gem_object *obj, -- cgit v1.2.3 From d434b64f6a760d85295e32298a9a1f3624ee1b69 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 May 2008 03:25:16 -0700 Subject: [i915] leave interrupts masked off when not in use. The interrupt enable register cannot be used to temporarily disable interrupts, instead use the interrupt mask register. Note that this change means that a pile of buffers will be left stuck on the chip as the final interrupts will not be recognized to come and drain things. --- shared-core/i915_drv.h | 2 +- shared-core/i915_irq.c | 74 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 51 insertions(+), 25 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 04e149a9..fee6d436 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -131,7 +131,7 @@ typedef struct drm_i915_private { DRM_SPINTYPE user_irq_lock; int user_irq_refcount; int fence_irq_on; - uint32_t irq_enable_reg; + uint32_t irq_mask_reg; int irq_enabled; #ifdef I915_HAVE_FENCE diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 02191316..fbfc5f46 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -508,7 +508,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) if (dev_priv->sarea_priv) dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); - I915_WRITE(I915REG_INT_IDENTITY_R, iir); + I915_WRITE(I915REG_INT_IDENTITY_R, iir | I915_USER_INTERRUPT); (void) I915_READ(I915REG_INT_IDENTITY_R); /* Flush posted write */ if (iir & I915_USER_INTERRUPT) { @@ -550,8 +550,9 @@ void i915_user_irq_on(drm_i915_private_t *dev_priv) { DRM_SPINLOCK(&dev_priv->user_irq_lock); if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){ - dev_priv->irq_enable_reg |= I915_USER_INTERRUPT; - I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + dev_priv->irq_mask_reg &= ~I915_USER_INTERRUPT; + I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); + (void) I915_READ (I915REG_INT_ENABLE_R); } DRM_SPINUNLOCK(&dev_priv->user_irq_lock); @@ -560,9 +561,11 @@ void i915_user_irq_on(drm_i915_private_t *dev_priv) void i915_user_irq_off(drm_i915_private_t *dev_priv) { DRM_SPINLOCK(&dev_priv->user_irq_lock); + BUG_ON(dev_priv->user_irq_refcount <= 0); if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { - // dev_priv->irq_enable_reg &= ~USER_INT_FLAG; - // I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + dev_priv->irq_mask_reg |= I915_USER_INTERRUPT; + I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); + (void) I915_READ(I915REG_INT_MASK_R); } DRM_SPINUNLOCK(&dev_priv->user_irq_lock); } @@ -642,16 +645,17 @@ int i915_enable_vblank(struct drm_device *dev, int plane) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int pipe = i915_get_pipe(dev, plane); u32 pipestat_reg = 0; + u32 mask_reg = 0; u32 pipestat; switch (pipe) { case 0: pipestat_reg = I915REG_PIPEASTAT; - dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; + mask_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; break; case 1: pipestat_reg = I915REG_PIPEBSTAT; - dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; + mask_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; break; default: DRM_ERROR("tried to enable vblank on non-existent pipe %d\n", @@ -677,7 +681,11 @@ int i915_enable_vblank(struct drm_device *dev, int plane) I915_VBLANK_INTERRUPT_STATUS); I915_WRITE(pipestat_reg, pipestat); } - I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + DRM_SPINLOCK(&dev_priv->user_irq_lock); + dev_priv->irq_mask_reg &= ~mask_reg; + I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); + I915_READ(I915REG_INT_MASK_R); + DRM_SPINUNLOCK(&dev_priv->user_irq_lock); return 0; } @@ -687,16 +695,17 @@ void i915_disable_vblank(struct drm_device *dev, int plane) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int pipe = i915_get_pipe(dev, plane); u32 pipestat_reg = 0; + u32 mask_reg = 0; u32 pipestat; switch (pipe) { case 0: pipestat_reg = I915REG_PIPEASTAT; - dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; + mask_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; break; case 1: pipestat_reg = I915REG_PIPEBSTAT; - dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; + mask_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; break; default: DRM_ERROR("tried to disable vblank on non-existent pipe %d\n", @@ -704,7 +713,11 @@ void i915_disable_vblank(struct drm_device *dev, int plane) break; } - I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + DRM_SPINLOCK(&dev_priv->user_irq_lock); + dev_priv->irq_mask_reg |= mask_reg; + I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); + (void) I915_READ (I915REG_INT_MASK_R); + DRM_SPINUNLOCK(&dev_priv->user_irq_lock); if (pipestat_reg) { pipestat = I915_READ (pipestat_reg); @@ -716,6 +729,7 @@ void i915_disable_vblank(struct drm_device *dev, int plane) pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS | I915_VBLANK_INTERRUPT_STATUS); I915_WRITE(pipestat_reg, pipestat); + (void) I915_READ(pipestat_reg); } } @@ -723,12 +737,27 @@ static void i915_enable_interrupt (struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - dev_priv->irq_enable_reg |= I915_USER_INTERRUPT; - - I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + dev_priv->irq_mask_reg = (I915_USER_INTERRUPT | + I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT); + I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); + I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_mask_reg); + (void) I915_READ (I915REG_INT_ENABLE_R); dev_priv->irq_enabled = 1; } +static void i915_disable_interrupt (struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + + I915_WRITE(I915REG_HWSTAM, 0xffffffff); + I915_WRITE(I915REG_INT_MASK_R, 0xffffffff); + I915_WRITE(I915REG_INT_ENABLE_R, 0); + I915_WRITE(I915REG_INT_IDENTITY_R, 0xffffffff); + (void) I915_READ (I915REG_INT_IDENTITY_R); + dev_priv->irq_enabled = 0; +} + /* Set the vblank monitor pipe */ int i915_vblank_pipe_set(struct drm_device *dev, void *data, @@ -934,9 +963,11 @@ void i915_driver_irq_preinstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - I915_WRITE16(I915REG_HWSTAM, 0xeffe); - I915_WRITE16(I915REG_INT_MASK_R, 0x0); - I915_WRITE16(I915REG_INT_ENABLE_R, 0x0); + I915_WRITE(I915REG_HWSTAM, 0xffff); + I915_WRITE(I915REG_INT_ENABLE_R, 0x0); + I915_WRITE(I915REG_INT_MASK_R, 0xffffffff); + I915_WRITE(I915REG_INT_IDENTITY_R, 0xffffffff); + (void) I915_READ(I915REG_INT_IDENTITY_R); } int i915_driver_irq_postinstall(struct drm_device * dev) @@ -950,7 +981,7 @@ int i915_driver_irq_postinstall(struct drm_device * dev) DRM_SPININIT(&dev_priv->user_irq_lock, "userirq"); dev_priv->user_irq_refcount = 0; - dev_priv->irq_enable_reg = 0; + dev_priv->irq_mask_reg = 0; ret = drm_vblank_init(dev, num_pipes); if (ret) @@ -977,15 +1008,10 @@ void i915_driver_irq_uninstall(struct drm_device * dev) if (!dev_priv) return; - dev_priv->irq_enabled = 0; - I915_WRITE(I915REG_HWSTAM, 0xffffffff); - I915_WRITE(I915REG_INT_MASK_R, 0xffffffff); - I915_WRITE(I915REG_INT_ENABLE_R, 0x0); + i915_disable_interrupt (dev); temp = I915_READ(I915REG_PIPEASTAT); I915_WRITE(I915REG_PIPEASTAT, temp); temp = I915_READ(I915REG_PIPEBSTAT); I915_WRITE(I915REG_PIPEBSTAT, temp); - temp = I915_READ(I915REG_INT_IDENTITY_R); - I915_WRITE(I915REG_INT_IDENTITY_R, temp); } -- cgit v1.2.3 From e10502002f0ebb2b56b19384b2f2eae7a7a84512 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 27 May 2008 17:50:39 -0700 Subject: [intel-gem] Replace idlelock usage with real lock acquisition. --- shared-core/i915_drv.h | 1 + 1 file changed, 1 insertion(+) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index fee6d436..76bc6bee 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -454,6 +454,7 @@ int i915_gem_busy_ioctl(struct drm_device *dev, void *data, int i915_gem_init_object(struct drm_gem_object *obj); void i915_gem_free_object(struct drm_gem_object *obj); int i915_gem_set_domain(struct drm_gem_object *obj, + struct drm_file *file_priv, uint32_t read_domains, uint32_t write_domain); int i915_gem_flush_pwrite(struct drm_gem_object *obj, -- cgit v1.2.3 From 84162ccb7dc0286336292ac7f8e80678bfc11804 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Jun 2008 13:49:21 -0700 Subject: Ignore X server provided mmio address --- shared-core/i915_dma.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index a948834a..37c822cf 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -214,14 +214,6 @@ static int i915_initialize(struct drm_device * dev, return -EINVAL; } - if (init->mmio_offset != 0) - dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); - if (!dev_priv->mmio_map) { - i915_dma_cleanup(dev); - DRM_ERROR("can not find mmio map!\n"); - return -EINVAL; - } - #ifdef I915_HAVE_BUFFER dev_priv->max_validate_buffers = I915_MAX_VALIDATE_BUFFERS; #endif @@ -323,11 +315,6 @@ static int i915_dma_resume(struct drm_device * dev) return -EINVAL; } - if (!dev_priv->mmio_map) { - DRM_ERROR("can not find mmio map!\n"); - return -EINVAL; - } - if (dev_priv->ring.map.handle == NULL) { DRM_ERROR("can not ioremap virtual address for" " ring buffer\n"); -- cgit v1.2.3 From 5f5badb26f761eec87b951ce1b7b3a51a5060c50 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Jun 2008 14:09:57 -0700 Subject: [intel] Allocate hardware status page at driver load time I couldn't get the re-allocated HWS to work on my 965GM, so I just gave up and made it persist across the lifetime of the driver instead. --- shared-core/i915_dma.c | 80 +++++++++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 30 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 37c822cf..1ea5c28e 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -69,6 +69,44 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) return -EBUSY; } +int i915_init_hardware_status(struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + /* Program Hardware Status Page */ + dev_priv->status_page_dmah = + drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); + + if (!dev_priv->status_page_dmah) { + DRM_ERROR("Can not allocate hardware status page\n"); + return -ENOMEM; + } + dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; + dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; + + memset(dev_priv->hw_status_page, 0, PAGE_SIZE); + + I915_WRITE(0x02080, dev_priv->dma_status_page); + DRM_DEBUG("Enabled hardware status page\n"); + return 0; +} + +void i915_free_hardware_status(struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + if (dev_priv->status_page_dmah) { + drm_pci_free(dev, dev_priv->status_page_dmah); + dev_priv->status_page_dmah = NULL; + /* Need to rewrite hardware status page */ + I915_WRITE(0x02080, 0x1ffff000); + } + + if (dev_priv->status_gfx_addr) { + dev_priv->status_gfx_addr = 0; + drm_core_ioremapfree(&dev_priv->hws_map, dev); + I915_WRITE(0x02080, 0x1ffff000); + } +} + #if I915_RING_VALIDATE /** * Validate the cached ring tail value @@ -122,18 +160,8 @@ static int i915_dma_cleanup(struct drm_device * dev) dev_priv->ring.map.size = 0; } - if (dev_priv->status_page_dmah) { - drm_pci_free(dev, dev_priv->status_page_dmah); - dev_priv->status_page_dmah = NULL; - /* Need to rewrite hardware status page */ - I915_WRITE(0x02080, 0x1ffff000); - } - - if (dev_priv->status_gfx_addr) { - dev_priv->status_gfx_addr = 0; - drm_core_ioremapfree(&dev_priv->hws_map, dev); - I915_WRITE(0x02080, 0x1ffff000); - } + if (I915_NEED_GFX_HWS(dev)) + i915_free_hardware_status(dev); return 0; } @@ -269,24 +297,6 @@ static int i915_initialize(struct drm_device * dev, */ dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A; - /* Program Hardware Status Page */ - if (!I915_NEED_GFX_HWS(dev)) { - dev_priv->status_page_dmah = - drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); - - if (!dev_priv->status_page_dmah) { - i915_dma_cleanup(dev); - DRM_ERROR("Can not allocate hardware status page\n"); - return -ENOMEM; - } - dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; - dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; - - memset(dev_priv->hw_status_page, 0, PAGE_SIZE); - - I915_WRITE(0x02080, dev_priv->dma_status_page); - } - DRM_DEBUG("Enabled hardware status page\n"); #ifdef I915_HAVE_BUFFER mutex_init(&dev_priv->cmdbuf_mutex); #endif @@ -1078,6 +1088,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) #endif #endif + /* Init HWS + */ + if (!I915_NEED_GFX_HWS(dev)) { + ret = i915_init_hardware_status(dev); + if(ret) + return ret; + } + return ret; } @@ -1095,6 +1113,8 @@ int i915_driver_unload(struct drm_device *dev) intel_fini_chipset_flush_compat(dev); #endif #endif + i915_free_hardware_status(dev); + return 0; } -- cgit v1.2.3 From 56a96841d01d112d7d4adfebb572016398551ba8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Jun 2008 12:57:01 -0700 Subject: [intel-gem] Add explicit throttle ioctl Instead of throttling and execbuffer time, have the application ask to throttle explicitly. This allows the throttle to happen less often, and without holding the DRM lock. --- shared-core/i915_dma.c | 1 + shared-core/i915_drm.h | 2 ++ shared-core/i915_drv.h | 2 ++ 3 files changed, 5 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 1ea5c28e..6e188f08 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1189,6 +1189,7 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 4712ea4f..0fa292d0 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -181,6 +181,7 @@ typedef struct drm_i915_sarea { #define DRM_I915_GEM_PIN 0x15 #define DRM_I915_GEM_UNPIN 0x16 #define DRM_I915_GEM_BUSY 0x17 +#define DRM_I915_GEM_THROTTLE 0x18 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -205,6 +206,7 @@ typedef struct drm_i915_sarea { #define DRM_IOCTL_I915_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin) #define DRM_IOCTL_I915_GEM_UNPIN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin) #define DRM_IOCTL_I915_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy) +#define DRM_IOCTL_I915_GEM_THROTTLE DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE) /* Asynchronous page flipping: */ diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index d646177b..33fb7ca9 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -451,6 +451,8 @@ int i915_gem_unpin_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_busy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int i915_gem_throttle_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); int i915_gem_init_object(struct drm_gem_object *obj); void i915_gem_free_object(struct drm_gem_object *obj); int i915_gem_set_domain(struct drm_gem_object *obj, -- cgit v1.2.3 From a708106c77f74f146722fba35eae772fb554ee9a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Jun 2008 12:58:41 -0700 Subject: [intel] free the hardware status page at driver_unload This goes with the other hardware status page patch. --- shared-core/i915_dma.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 6e188f08..c0ddeae0 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1103,8 +1103,9 @@ int i915_driver_unload(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - if (dev_priv->mmio_map) - drm_rmmap(dev, dev_priv->mmio_map); + i915_free_hardware_status(dev); + + drm_rmmap(dev, dev_priv->mmio_map); drm_free(dev->dev_private, sizeof(drm_i915_private_t), DRM_MEM_DRIVER); @@ -1113,8 +1114,6 @@ int i915_driver_unload(struct drm_device *dev) intel_fini_chipset_flush_compat(dev); #endif #endif - i915_free_hardware_status(dev); - return 0; } -- cgit v1.2.3 From 9f46c6935d154743162c6239903a4a9e443907bc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Jun 2008 12:59:52 -0700 Subject: [intel-gem] Use timers to retire requests periodically. Without the user IRQ running constantly, there's no wakeup when the ring empties to go retire requests and free buffers. Use a 1 second timer to make that happen more often. --- shared-core/i915_dma.c | 5 +++++ shared-core/i915_drv.h | 12 ++++++++++++ 2 files changed, 17 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index c0ddeae0..f6465bf6 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1078,6 +1078,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) INIT_LIST_HEAD(&dev_priv->mm.flushing_list); INIT_LIST_HEAD(&dev_priv->mm.inactive_list); INIT_LIST_HEAD(&dev_priv->mm.request_list); + dev_priv->mm.retire_timer.function = i915_gem_retire_timeout; + dev_priv->mm.retire_timer.data = (unsigned long) dev; + init_timer_deferrable (&dev_priv->mm.retire_timer); + INIT_WORK(&dev_priv->mm.retire_task, + i915_gem_retire_handler); INIT_WORK(&dev_priv->user_interrupt_task, i915_user_interrupt_handler); dev_priv->mm.next_gem_seqno = 1; diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 33fb7ca9..55af6552 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -280,6 +280,16 @@ typedef struct drm_i915_private { */ struct list_head request_list; + /** + * We leave the user IRQ off as much as possible, + * but this means that requests will finish and never + * be retired once the system goes idle. Set a timer to + * fire periodically while the ring is running. When it + * fires, go retire requests. + */ + struct timer_list retire_timer; + struct work_struct retire_task; + uint32_t next_gem_seqno; } mm; @@ -463,6 +473,8 @@ int i915_gem_flush_pwrite(struct drm_gem_object *obj, uint64_t offset, uint64_t size); void i915_gem_lastclose(struct drm_device *dev); void i915_gem_retire_requests(struct drm_device *dev); +void i915_gem_retire_timeout(unsigned long data); +void i915_gem_retire_handler(struct work_struct *work); #endif #ifdef __linux__ -- cgit v1.2.3 From 6cd0ef06a6c2bdcede166d9a2d0434e58e4a01f2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Jun 2008 13:26:03 -0700 Subject: [intel] remove settable use_mi_batchbuffer_start The driver can know what hardware requires MI_BATCH_BUFFER vs MI_BATCH_BUFFER_START; there's no reason to let user mode configure this. --- shared-core/i915_dma.c | 22 ++++++++-------------- shared-core/i915_drv.h | 1 - 2 files changed, 8 insertions(+), 15 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index f6465bf6..e5c6d0c4 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -285,9 +285,6 @@ static int i915_initialize(struct drm_device * dev, /* We are using separate values as placeholders for mechanisms for * private backbuffer/depthbuffer usage. */ - dev_priv->use_mi_batchbuffer_start = 0; - if (IS_I965G(dev)) /* 965 doesn't support older method */ - dev_priv->use_mi_batchbuffer_start = 1; /* Allow hardware batchbuffers unless told otherwise. */ @@ -639,7 +636,14 @@ int i915_dispatch_batchbuffer(struct drm_device * dev, return ret; } - if (dev_priv->use_mi_batchbuffer_start) { + if (IS_I830(dev) || IS_845G(dev)) { + BEGIN_LP_RING(4); + OUT_RING(MI_BATCH_BUFFER); + OUT_RING(batch->start | MI_BATCH_NON_SECURE); + OUT_RING(batch->start + batch->used - 4); + OUT_RING(0); + ADVANCE_LP_RING(); + } else { BEGIN_LP_RING(2); if (IS_I965G(dev)) { OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965); @@ -649,14 +653,6 @@ int i915_dispatch_batchbuffer(struct drm_device * dev, OUT_RING(batch->start | MI_BATCH_NON_SECURE); } ADVANCE_LP_RING(); - - } else { - BEGIN_LP_RING(4); - OUT_RING(MI_BATCH_BUFFER); - OUT_RING(batch->start | MI_BATCH_NON_SECURE); - OUT_RING(batch->start + batch->used - 4); - OUT_RING(0); - ADVANCE_LP_RING(); } } @@ -930,8 +926,6 @@ static int i915_setparam(struct drm_device *dev, void *data, switch (param->param) { case I915_SETPARAM_USE_MI_BATCHBUFFER_START: - if (!IS_I965G(dev)) - dev_priv->use_mi_batchbuffer_start = param->value; break; case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY: dev_priv->tex_lru_log_granularity = param->value; diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 55af6552..8acef0ca 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -117,7 +117,6 @@ typedef struct drm_i915_private { drm_local_map_t hws_map; unsigned int cpp; - int use_mi_batchbuffer_start; wait_queue_head_t irq_queue; atomic_t irq_received; -- cgit v1.2.3 From 2150da5d1a57d25d0f4bc39bb6c883d410f586d1 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 10 Jun 2008 15:30:23 -0700 Subject: [gem] Manage the ringbuffer from the kernel in the GEM case. This requires that the X Server use the execbuf interface for buffer submission, as it no longer has direct access to the ring. This is therefore a flag day for the gem interface. This also adds enter/leavevt ioctls for use by the X Server. These would get stubbed out in a modesetting implementation, but are required while in an environment where the device's state is only managed by the DRM while X has the VT. --- shared-core/i915_dma.c | 36 +++++++++++++++++++----------------- shared-core/i915_drm.h | 4 ++++ shared-core/i915_drv.h | 19 +++++++++++++++++-- shared-core/i915_irq.c | 5 +++++ 4 files changed, 45 insertions(+), 19 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index e5c6d0c4..4243b4e9 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -255,27 +255,27 @@ static int i915_initialize(struct drm_device * dev, dev_priv->sarea_priv = NULL; } - dev_priv->ring.Start = init->ring_start; - dev_priv->ring.End = init->ring_end; - dev_priv->ring.Size = init->ring_size; - dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; + if (init->ring_size != 0) { + dev_priv->ring.Size = init->ring_size; + dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; - dev_priv->ring.map.offset = init->ring_start; - dev_priv->ring.map.size = init->ring_size; - dev_priv->ring.map.type = 0; - dev_priv->ring.map.flags = 0; - dev_priv->ring.map.mtrr = 0; + dev_priv->ring.map.offset = init->ring_start; + dev_priv->ring.map.size = init->ring_size; + dev_priv->ring.map.type = 0; + dev_priv->ring.map.flags = 0; + dev_priv->ring.map.mtrr = 0; - drm_core_ioremap(&dev_priv->ring.map, dev); + drm_core_ioremap(&dev_priv->ring.map, dev); - if (dev_priv->ring.map.handle == NULL) { - i915_dma_cleanup(dev); - DRM_ERROR("can not ioremap virtual address for" - " ring buffer\n"); - return -ENOMEM; - } + if (dev_priv->ring.map.handle == NULL) { + i915_dma_cleanup(dev); + DRM_ERROR("can not ioremap virtual address for" + " ring buffer\n"); + return -ENOMEM; + } - dev_priv->ring.virtual_start = dev_priv->ring.map.handle; + dev_priv->ring.virtual_start = dev_priv->ring.map.handle; + } dev_priv->cpp = init->cpp; @@ -1188,6 +1188,8 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 0fa292d0..ce01640a 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -182,6 +182,8 @@ typedef struct drm_i915_sarea { #define DRM_I915_GEM_UNPIN 0x16 #define DRM_I915_GEM_BUSY 0x17 #define DRM_I915_GEM_THROTTLE 0x18 +#define DRM_I915_GEM_ENTERVT 0x19 +#define DRM_I915_GEM_LEAVEVT 0x20 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -207,6 +209,8 @@ typedef struct drm_i915_sarea { #define DRM_IOCTL_I915_GEM_UNPIN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin) #define DRM_IOCTL_I915_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy) #define DRM_IOCTL_I915_GEM_THROTTLE DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE) +#define DRM_IOCTL_I915_GEM_ENTERVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT) +#define DRM_IOCTL_I915_GEM_LEAVEVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT) /* Asynchronous page flipping: */ diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 8acef0ca..3a22ae3c 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -74,14 +74,13 @@ struct drm_i915_validate_buffer; typedef struct _drm_i915_ring_buffer { int tail_mask; - unsigned long Start; - unsigned long End; unsigned long Size; u8 *virtual_start; int head; int tail; int space; drm_local_map_t map; + struct drm_gem_object *ring_obj; } drm_i915_ring_buffer_t; struct mem_block { @@ -290,6 +289,16 @@ typedef struct drm_i915_private { struct work_struct retire_task; uint32_t next_gem_seqno; + + /** + * Flag if the X Server, and thus DRM, is not currently in + * control of the device. + * + * This is set between LeaveVT and EnterVT. It needs to be + * replaced with a semaphore. It also needs to be + * transitioned away from for kernel modesetting. + */ + int suspended; } mm; struct work_struct user_interrupt_task; @@ -462,8 +471,14 @@ int i915_gem_busy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_throttle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int i915_gem_entervt_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); int i915_gem_init_object(struct drm_gem_object *obj); void i915_gem_free_object(struct drm_gem_object *obj); +int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment); +void i915_gem_object_unpin(struct drm_gem_object *obj); int i915_gem_set_domain(struct drm_gem_object *obj, struct drm_file *file_priv, uint32_t read_domains, diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 37d85f40..077af1ab 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -575,6 +575,11 @@ int i915_wait_irq(struct drm_device * dev, int irq_nr) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int ret = 0; + if (!dev_priv) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr, READ_BREADCRUMB(dev_priv)); -- cgit v1.2.3 From 62a3be962f1915d17813ecbfc9544232908b44e4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 10 Jun 2008 23:10:33 -0700 Subject: [intel] Fix BUG_ON trigger in irq masking if you did on/off with irqs disabled. --- shared-core/i915_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 077af1ab..0125f8b3 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -560,7 +560,7 @@ void i915_user_irq_on(drm_i915_private_t *dev_priv) void i915_user_irq_off(drm_i915_private_t *dev_priv) { DRM_SPINLOCK(&dev_priv->user_irq_lock); - BUG_ON(dev_priv->user_irq_refcount <= 0); + BUG_ON(dev_priv->irq_enabled && dev_priv->user_irq_refcount <= 0); if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { dev_priv->irq_mask_reg |= I915_USER_INTERRUPT; I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); -- cgit v1.2.3 From 2655005762b8915d5f44d1d1ee7e6c2eb34841d7 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 11 Jun 2008 14:42:40 -0700 Subject: [gem] Move potentially device-specific ioctls to the intel driver. This is the create (may want location flags), pread/pwrite/mmap (performance tuning hints), and set_domain (will 32 bits be enough for everyone?) ioctls. Left in the generic set are just flink/open/close. The 2D driver must be updated for this change, and API but not ABI is broken for 3D. The driver version is bumped to mark this. --- shared-core/drm.h | 83 ++-------------------------------------- shared-core/i915_dma.c | 5 +++ shared-core/i915_drm.h | 101 ++++++++++++++++++++++++++++++++++++++++++++----- shared-core/i915_drv.h | 20 ++++++---- 4 files changed, 113 insertions(+), 96 deletions(-) (limited to 'shared-core') diff --git a/shared-core/drm.h b/shared-core/drm.h index 2373a22e..6012ef21 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -959,69 +959,12 @@ struct drm_mm_info_arg { uint64_t p_size; }; - -struct drm_gem_create { - /** - * Requested size for the object. - * - * The (page-aligned) allocated size for the object will be returned. - */ - uint64_t size; - /** - * Returned handle for the object. - * - * Object handles are nonzero. - */ - uint32_t handle; - uint32_t pad; -}; - struct drm_gem_close { /** Handle of the object to be closed. */ uint32_t handle; uint32_t pad; }; -struct drm_gem_pread { - /** Handle for the object being read. */ - uint32_t handle; - uint32_t pad; - /** Offset into the object to read from */ - uint64_t offset; - /** Length of data to read */ - uint64_t size; - /** Pointer to write the data into. */ - uint64_t data_ptr; /* void *, but pointers are not 32/64 compatible */ -}; - -struct drm_gem_pwrite { - /** Handle for the object being written to. */ - uint32_t handle; - uint32_t pad; - /** Offset into the object to write to */ - uint64_t offset; - /** Length of data to write */ - uint64_t size; - /** Pointer to read the data from. */ - uint64_t data_ptr; /* void *, but pointers are not 32/64 compatible */ -}; - -struct drm_gem_mmap { - /** Handle for the object being mapped. */ - uint32_t handle; - uint32_t pad; - /** Offset in the object to map. */ - uint64_t offset; - /** - * Length of data to map. - * - * The value will be page-aligned. - */ - uint64_t size; - /** Returned pointer the data was mapped at */ - uint64_t addr_ptr; /* void *, but pointers are not 32/64 compatible */ -}; - struct drm_gem_flink { /** Handle for the object being named */ uint32_t handle; @@ -1041,19 +984,6 @@ struct drm_gem_open { uint64_t size; }; -struct drm_gem_set_domain { - /** Handle for the object */ - uint32_t handle; - - /** New read domains */ - uint32_t read_domains; - - /** New write domain */ - uint32_t write_domain; -}; - -#define DRM_GEM_DOMAIN_CPU 0x00000001 - /** * \name Ioctls Definitions */ @@ -1075,6 +1005,10 @@ struct drm_gem_set_domain { #define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) #define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) +#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close) +#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink) +#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open) + #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) #define DRM_IOCTL_BLOCK DRM_IOWR(0x12, struct drm_block) @@ -1122,15 +1056,6 @@ struct drm_gem_set_domain { #define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw) -#define DRM_IOCTL_GEM_CREATE DRM_IOWR(0x09, struct drm_gem_create) -#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x0a, struct drm_gem_close) -#define DRM_IOCTL_GEM_PREAD DRM_IOW (0x0b, struct drm_gem_pread) -#define DRM_IOCTL_GEM_PWRITE DRM_IOW (0x0c, struct drm_gem_pwrite) -#define DRM_IOCTL_GEM_MMAP DRM_IOWR(0x0d, struct drm_gem_mmap) -#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0e, struct drm_gem_flink) -#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0f, struct drm_gem_open) -#define DRM_IOCTL_GEM_SET_DOMAIN DRM_IOW (0xb7, struct drm_gem_set_domain) - #define DRM_IOCTL_MM_INIT DRM_IOWR(0xc0, struct drm_mm_init_arg) #define DRM_IOCTL_MM_TAKEDOWN DRM_IOWR(0xc1, struct drm_mm_type_arg) #define DRM_IOCTL_MM_LOCK DRM_IOWR(0xc2, struct drm_mm_type_arg) diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 4243b4e9..7e4de18b 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1190,6 +1190,11 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, 0), + DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0), + DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0), + DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0), + DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index ce01640a..fe47708d 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -183,7 +183,12 @@ typedef struct drm_i915_sarea { #define DRM_I915_GEM_BUSY 0x17 #define DRM_I915_GEM_THROTTLE 0x18 #define DRM_I915_GEM_ENTERVT 0x19 -#define DRM_I915_GEM_LEAVEVT 0x20 +#define DRM_I915_GEM_LEAVEVT 0x1a +#define DRM_I915_GEM_CREATE 0x1b +#define DRM_I915_GEM_PREAD 0x1c +#define DRM_I915_GEM_PWRITE 0x1d +#define DRM_I915_GEM_MMAP 0x1e +#define DRM_I915_GEM_SET_DOMAIN 0x1f #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -211,6 +216,11 @@ typedef struct drm_i915_sarea { #define DRM_IOCTL_I915_GEM_THROTTLE DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE) #define DRM_IOCTL_I915_GEM_ENTERVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT) #define DRM_IOCTL_I915_GEM_LEAVEVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT) +#define DRM_IOCTL_I915_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create) +#define DRM_IOCTL_I915_GEM_PREAD DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread) +#define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite) +#define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap) +#define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain) /* Asynchronous page flipping: */ @@ -424,6 +434,73 @@ struct drm_i915_gem_init { uint64_t gtt_end; }; +struct drm_i915_gem_create { + /** + * Requested size for the object. + * + * The (page-aligned) allocated size for the object will be returned. + */ + uint64_t size; + /** + * Returned handle for the object. + * + * Object handles are nonzero. + */ + uint32_t handle; + uint32_t pad; +}; + +struct drm_i915_gem_pread { + /** Handle for the object being read. */ + uint32_t handle; + uint32_t pad; + /** Offset into the object to read from */ + uint64_t offset; + /** Length of data to read */ + uint64_t size; + /** Pointer to write the data into. */ + uint64_t data_ptr; /* void *, but pointers are not 32/64 compatible */ +}; + +struct drm_i915_gem_pwrite { + /** Handle for the object being written to. */ + uint32_t handle; + uint32_t pad; + /** Offset into the object to write to */ + uint64_t offset; + /** Length of data to write */ + uint64_t size; + /** Pointer to read the data from. */ + uint64_t data_ptr; /* void *, but pointers are not 32/64 compatible */ +}; + +struct drm_i915_gem_mmap { + /** Handle for the object being mapped. */ + uint32_t handle; + uint32_t pad; + /** Offset in the object to map. */ + uint64_t offset; + /** + * Length of data to map. + * + * The value will be page-aligned. + */ + uint64_t size; + /** Returned pointer the data was mapped at */ + uint64_t addr_ptr; /* void *, but pointers are not 32/64 compatible */ +}; + +struct drm_i915_gem_set_domain { + /** Handle for the object */ + uint32_t handle; + + /** New read domains */ + uint32_t read_domains; + + /** New write domain */ + uint32_t write_domain; +}; + struct drm_i915_gem_relocation_entry { /** * Handle of the buffer being pointed to by this relocation entry. @@ -469,20 +546,26 @@ struct drm_i915_gem_relocation_entry { uint32_t write_domain; }; -/** +/** @{ * Intel memory domains * * Most of these just align with the various caches in * the system and are used to flush and invalidate as * objects end up cached in different domains. */ - -/* 0x00000001 is DRM_GEM_DOMAIN_CPU */ -#define DRM_GEM_DOMAIN_I915_RENDER 0x00000002 /* Render cache, used by 2D and 3D drawing */ -#define DRM_GEM_DOMAIN_I915_SAMPLER 0x00000004 /* Sampler cache, used by texture engine */ -#define DRM_GEM_DOMAIN_I915_COMMAND 0x00000008 /* Command queue, used to load batch buffers */ -#define DRM_GEM_DOMAIN_I915_INSTRUCTION 0x00000010 /* Instruction cache, used by shader programs */ -#define DRM_GEM_DOMAIN_I915_VERTEX 0x00000020 /* Vertex address cache */ +/** CPU cache */ +#define I915_GEM_DOMAIN_CPU 0x00000001 +/** Render cache, used by 2D and 3D drawing */ +#define I915_GEM_DOMAIN_RENDER 0x00000002 +/** Sampler cache, used by texture engine */ +#define I915_GEM_DOMAIN_SAMPLER 0x00000004 +/** Command queue, used to load batch buffers */ +#define I915_GEM_DOMAIN_COMMAND 0x00000008 +/** Instruction cache, used by shader programs */ +#define I915_GEM_DOMAIN_INSTRUCTION 0x00000010 +/** Vertex address cache */ +#define I915_GEM_DOMAIN_VERTEX 0x00000020 +/** @} */ struct drm_i915_gem_exec_object { /** diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 3a22ae3c..9c9925b5 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -37,7 +37,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20080312" +#define DRIVER_DATE "20080611" #if defined(__linux__) #define I915_HAVE_FENCE @@ -61,7 +61,7 @@ */ #define DRIVER_MAJOR 1 #if defined(I915_HAVE_FENCE) && defined(I915_HAVE_BUFFER) -#define DRIVER_MINOR 13 +#define DRIVER_MINOR 14 #else #define DRIVER_MINOR 6 #endif @@ -461,6 +461,16 @@ int i915_execbuffer(struct drm_device *dev, void *data, /* i915_gem.c */ int i915_gem_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int i915_gem_create_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int i915_gem_pread_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int i915_gem_mmap_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); int i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_pin_ioctl(struct drm_device *dev, void *data, @@ -479,12 +489,6 @@ int i915_gem_init_object(struct drm_gem_object *obj); void i915_gem_free_object(struct drm_gem_object *obj); int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment); void i915_gem_object_unpin(struct drm_gem_object *obj); -int i915_gem_set_domain(struct drm_gem_object *obj, - struct drm_file *file_priv, - uint32_t read_domains, - uint32_t write_domain); -int i915_gem_flush_pwrite(struct drm_gem_object *obj, - uint64_t offset, uint64_t size); void i915_gem_lastclose(struct drm_device *dev); void i915_gem_retire_requests(struct drm_device *dev); void i915_gem_retire_timeout(unsigned long data); -- cgit v1.2.3 From 846d792ac10c4b2738bb5ff59e56df168b9921ff Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 11 Jun 2008 15:51:17 -0700 Subject: [gem] Another round of cleanups from checkpatch.pl --- shared-core/i915_drm.h | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index fe47708d..f16dc99f 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -573,11 +573,15 @@ struct drm_i915_gem_exec_object { * operation. */ uint32_t handle; - - /** List of relocations to be performed on this buffer */ + + /** Number of relocations to be performed on this buffer */ uint32_t relocation_count; - uint64_t relocs_ptr; /* struct drm_i915_gem_relocation_entry *relocs */ - + /** + * Pointer to array of struct drm_i915_gem_relocation_entry containing + * the relocations to be performed in this buffer. + */ + uint64_t relocs_ptr; + /** Required alignment in graphics aperture */ uint64_t alignment; @@ -593,11 +597,13 @@ struct drm_i915_gem_execbuffer { * List of buffers to be validated with their relocations to be * performend on them. * + * This is a pointer to an array of struct drm_i915_gem_validate_entry. + * * These buffers must be listed in an order such that all relocations * a buffer is performing refer to buffers that have already appeared * in the validate list. */ - uint64_t buffers_ptr; /* struct drm_i915_gem_validate_entry *buffers */ + uint64_t buffers_ptr; uint32_t buffer_count; /** Offset in the batchbuffer to start execution from. */ @@ -614,7 +620,7 @@ struct drm_i915_gem_pin { /** Handle of the buffer to be pinned. */ uint32_t handle; uint32_t pad; - + /** alignment required within the aperture */ uint64_t alignment; @@ -631,7 +637,7 @@ struct drm_i915_gem_unpin { struct drm_i915_gem_busy { /** Handle of the buffer to check for busy */ uint32_t handle; - + /** Return busy status (1 if busy, 0 if idle) */ uint32_t busy; }; -- cgit v1.2.3 From cc74ac359053e95fd79d7011a2e18defcefb5c19 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 12 Jun 2008 10:56:37 -0700 Subject: Don't clear USER_INTERRUPT if we're not handling it. This fixes a regression from commit d434b64f6a760d85295e32298a9a1f3624ee1b69 which could cause us to fail to wake up for user interrupts if we lost a race. --- shared-core/i915_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 0125f8b3..39da8143 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -507,7 +507,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) if (dev_priv->sarea_priv) dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); - I915_WRITE(I915REG_INT_IDENTITY_R, iir | I915_USER_INTERRUPT); + I915_WRITE(I915REG_INT_IDENTITY_R, iir); (void) I915_READ(I915REG_INT_IDENTITY_R); /* Flush posted write */ if (iir & I915_USER_INTERRUPT) { -- cgit v1.2.3 From 0558d99c01c38e24e97b57ef55f66bb94a92e157 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 13 Jun 2008 09:53:36 -0700 Subject: [gem] Remove the interrupt handler for retiring requests. This was insufficient once we started masking interrupts to only when someone was waiting for them (and would thus retire requests themselves). It was replaced by the retire_timer. --- shared-core/i915_dma.c | 2 -- shared-core/i915_drv.h | 3 --- shared-core/i915_irq.c | 23 ----------------------- 3 files changed, 28 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 7e4de18b..667a6ac0 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1077,8 +1077,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) init_timer_deferrable (&dev_priv->mm.retire_timer); INIT_WORK(&dev_priv->mm.retire_task, i915_gem_retire_handler); - INIT_WORK(&dev_priv->user_interrupt_task, - i915_user_interrupt_handler); dev_priv->mm.next_gem_seqno = 1; #ifdef __linux__ diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 9c9925b5..5af9a964 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -300,8 +300,6 @@ typedef struct drm_i915_private { */ int suspended; } mm; - - struct work_struct user_interrupt_task; } drm_i915_private_t; enum intel_chip_family { @@ -421,7 +419,6 @@ extern int i915_vblank_swap(struct drm_device *dev, void *data, struct drm_file *file_priv); extern void i915_user_irq_on(drm_i915_private_t *dev_priv); extern void i915_user_irq_off(drm_i915_private_t *dev_priv); -extern void i915_user_interrupt_handler(struct work_struct *work); /* i915_mem.c */ extern int i915_mem_alloc(struct drm_device *dev, void *data, diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 39da8143..6daf2918 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -435,28 +435,6 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane) return count; } -/** - * Handler for user interrupts in process context (able to sleep, do VFS - * operations, etc. - * - * If another IRQ comes in while we're in this handler, it will still get put - * on the queue again to be rerun when we finish. - */ -void -i915_user_interrupt_handler(struct work_struct *work) -{ - drm_i915_private_t *dev_priv; - struct drm_device *dev; - - dev_priv = container_of(work, drm_i915_private_t, - user_interrupt_task); - dev = dev_priv->dev; - - mutex_lock(&dev->struct_mutex); - i915_gem_retire_requests(dev); - mutex_unlock(&dev->struct_mutex); -} - irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@ -514,7 +492,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) DRM_WAKEUP(&dev_priv->irq_queue); #ifdef I915_HAVE_FENCE i915_fence_handler(dev); - schedule_work(&dev_priv->user_interrupt_task); #endif } -- cgit v1.2.3 From df4ef348c8a48cead807a42fcd315f7e422aa156 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 13 Jun 2008 10:47:33 -0700 Subject: Fix i915_wait_irq in the presence of interrupt masking. In the short-circuit code for the breadcrumb already being new enough, we need to update the sarea_priv copy of the breadcrumb just as if we had waited. Otherwise userland error checking will notice that we returned too early based on its wrong information, and call wait_irq again (leading to spinning until someone else comes along and updates the sarea_priv). This bug was hidden when we had interrupt masking disabled, such as in master, since the interrupt handler would update sarea_priv. --- shared-core/i915_irq.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 6daf2918..cfa9320e 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -560,8 +560,12 @@ int i915_wait_irq(struct drm_device * dev, int irq_nr) DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr, READ_BREADCRUMB(dev_priv)); - if (READ_BREADCRUMB(dev_priv) >= irq_nr) + if (READ_BREADCRUMB(dev_priv) >= irq_nr) { + if (dev_priv->sarea_priv) + dev_priv->sarea_priv->last_dispatch = + READ_BREADCRUMB(dev_priv); return 0; + } i915_user_irq_on(dev_priv); DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, -- cgit v1.2.3 From 462af73149b9286a74b95b9cda5e4224ebe0dd87 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Jun 2008 09:19:30 -0700 Subject: [intel-gem] Use a delayed_work instead of a timer + work_struct We want request retirement to occur about once a second when the request queue is non-empty. This was done with a timer that queued a work_struct, using a delayed_work instead makes a lot more sense. --- shared-core/i915_dma.c | 7 ++----- shared-core/i915_drv.h | 9 +++++---- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 667a6ac0..669f1e4e 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1072,11 +1072,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) INIT_LIST_HEAD(&dev_priv->mm.flushing_list); INIT_LIST_HEAD(&dev_priv->mm.inactive_list); INIT_LIST_HEAD(&dev_priv->mm.request_list); - dev_priv->mm.retire_timer.function = i915_gem_retire_timeout; - dev_priv->mm.retire_timer.data = (unsigned long) dev; - init_timer_deferrable (&dev_priv->mm.retire_timer); - INIT_WORK(&dev_priv->mm.retire_task, - i915_gem_retire_handler); + INIT_DELAYED_WORK(&dev_priv->mm.retire_work, + i915_gem_retire_work_handler); dev_priv->mm.next_gem_seqno = 1; #ifdef __linux__ diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 5af9a964..5cc6e680 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -285,8 +285,7 @@ typedef struct drm_i915_private { * fire periodically while the ring is running. When it * fires, go retire requests. */ - struct timer_list retire_timer; - struct work_struct retire_task; + struct delayed_work retire_work; uint32_t next_gem_seqno; @@ -488,8 +487,7 @@ int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment); void i915_gem_object_unpin(struct drm_gem_object *obj); void i915_gem_lastclose(struct drm_device *dev); void i915_gem_retire_requests(struct drm_device *dev); -void i915_gem_retire_timeout(unsigned long data); -void i915_gem_retire_handler(struct work_struct *work); +void i915_gem_retire_work_handler(struct work_struct *work); #endif #ifdef __linux__ @@ -915,6 +913,9 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define XY_SRC_COPY_BLT_SRC_TILED (1<<15) #define XY_SRC_COPY_BLT_DST_TILED (1<<11) +#define MI_NOOP (0) +#define MI_NOOP_ENABLE_NOPID (1 << 22) +#define MI_NOOP_ID_MASK ((1 << 22) - 1) #define MI_BATCH_BUFFER ((0x30<<23)|1) #define MI_BATCH_BUFFER_START (0x31<<23) -- cgit v1.2.3 From 5957470ca3be6c0225985f74b1511401e02c014b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jun 2008 18:19:19 -0700 Subject: [intel] Restructure irq to pend all work until after iir write. The interrupt identity register must be writen before any work occurs lest we drop an interrupt on the floor. This patch just shuffles code around to make sure that IIR is written as early as possible. --- shared-core/i915_irq.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index cfa9320e..58781a4a 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -440,7 +440,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) struct drm_device *dev = (struct drm_device *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 iir; - u32 pipea_stats, pipeb_stats; + u32 pipea_stats = 0, pipeb_stats = 0; int vblank = 0; iir = I915_READ(I915REG_INT_IDENTITY_R); @@ -463,31 +463,19 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) */ if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) { pipea_stats = I915_READ(I915REG_PIPEASTAT); - if (pipea_stats & (I915_START_VBLANK_INTERRUPT_STATUS| - I915_VBLANK_INTERRUPT_STATUS)) - { - vblank++; - drm_handle_vblank(dev, i915_get_plane(dev, 0)); - } I915_WRITE(I915REG_PIPEASTAT, pipea_stats); } if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) { pipeb_stats = I915_READ(I915REG_PIPEBSTAT); - if (pipeb_stats & (I915_START_VBLANK_INTERRUPT_STATUS| - I915_VBLANK_INTERRUPT_STATUS)) - { - vblank++; - drm_handle_vblank(dev, i915_get_plane(dev, 1)); - } I915_WRITE(I915REG_PIPEBSTAT, pipeb_stats); } + I915_WRITE(I915REG_INT_IDENTITY_R, iir); + (void) I915_READ(I915REG_INT_IDENTITY_R); /* Flush posted writes */ + if (dev_priv->sarea_priv) dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); - I915_WRITE(I915REG_INT_IDENTITY_R, iir); - (void) I915_READ(I915REG_INT_IDENTITY_R); /* Flush posted write */ - if (iir & I915_USER_INTERRUPT) { DRM_WAKEUP(&dev_priv->irq_queue); #ifdef I915_HAVE_FENCE @@ -495,6 +483,16 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) #endif } + if (pipea_stats & (I915_START_VBLANK_INTERRUPT_STATUS| + I915_VBLANK_INTERRUPT_STATUS)) { + vblank = 1; + drm_handle_vblank(dev, i915_get_plane(dev, 0)); + } + if (pipeb_stats & (I915_START_VBLANK_INTERRUPT_STATUS| + I915_VBLANK_INTERRUPT_STATUS)) { + vblank = 1; + drm_handle_vblank(dev, i915_get_plane(dev, 1)); + } if (vblank) { if (dev_priv->swaps_pending > 0) drm_locked_tasklet(dev, i915_vblank_tasklet); @@ -526,9 +524,11 @@ void i915_user_irq_on(drm_i915_private_t *dev_priv) { DRM_SPINLOCK(&dev_priv->user_irq_lock); if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){ - dev_priv->irq_mask_reg &= ~I915_USER_INTERRUPT; - I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); - (void) I915_READ (I915REG_INT_ENABLE_R); + if ((dev_priv->irq_mask_reg & I915_USER_INTERRUPT) != 0) { + dev_priv->irq_mask_reg &= ~I915_USER_INTERRUPT; + I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); + (void) I915_READ (I915REG_INT_MASK_R); + } } DRM_SPINUNLOCK(&dev_priv->user_irq_lock); @@ -539,9 +539,11 @@ void i915_user_irq_off(drm_i915_private_t *dev_priv) DRM_SPINLOCK(&dev_priv->user_irq_lock); BUG_ON(dev_priv->irq_enabled && dev_priv->user_irq_refcount <= 0); if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { - dev_priv->irq_mask_reg |= I915_USER_INTERRUPT; - I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); - (void) I915_READ(I915REG_INT_MASK_R); + if ((dev_priv->irq_mask_reg & I915_USER_INTERRUPT) == 0) { + dev_priv->irq_mask_reg |= I915_USER_INTERRUPT; + I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); + (void) I915_READ(I915REG_INT_MASK_R); + } } DRM_SPINUNLOCK(&dev_priv->user_irq_lock); } -- cgit v1.2.3 From 3762c9ea6754763694b1de4df3acd9dc37247f87 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Jun 2008 10:27:39 -0700 Subject: [intel] Enable MSI for i915 IRQ --- shared-core/i915_irq.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 58781a4a..9ba5b00a 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -33,6 +33,13 @@ #define MAX_NOPID ((u32)~0) +/* + * These are the interrupts used by the driver + */ +#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT | \ + I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) + /** * i915_get_pipe - return the the pipe associated with a given plane * @dev: DRM device @@ -443,6 +450,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) u32 pipea_stats = 0, pipeb_stats = 0; int vblank = 0; + if (dev->pdev->msi_enabled) + I915_WRITE(I915REG_INT_ENABLE_R, 0); iir = I915_READ(I915REG_INT_IDENTITY_R); #if 0 DRM_DEBUG("flag=%08x\n", iir); @@ -454,6 +463,9 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) I915_READ(I915REG_INT_ENABLE_R), I915_READ(I915REG_PIPEASTAT), I915_READ(I915REG_PIPEBSTAT)); + if (dev->pdev->msi_enabled) + I915_WRITE(I915REG_INT_ENABLE_R, + I915_INTERRUPT_ENABLE_MASK); return IRQ_NONE; } @@ -498,6 +510,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) drm_locked_tasklet(dev, i915_vblank_tasklet); } + if (dev->pdev->msi_enabled) + I915_WRITE(I915REG_INT_ENABLE_R, I915_INTERRUPT_ENABLE_MASK); return IRQ_HANDLED; } @@ -724,11 +738,9 @@ static void i915_enable_interrupt (struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - dev_priv->irq_mask_reg = (I915_USER_INTERRUPT | - I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT); + dev_priv->irq_mask_reg = I915_INTERRUPT_ENABLE_MASK; I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); - I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_mask_reg); + I915_WRITE(I915REG_INT_ENABLE_R, I915_INTERRUPT_ENABLE_MASK); (void) I915_READ (I915REG_INT_ENABLE_R); dev_priv->irq_enabled = 1; } -- cgit v1.2.3 From ced9ebf64543b4d64a38feee3293040af953acc0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Jun 2008 12:06:13 -0700 Subject: [intel-gem] throttle based on frames rather than time. Reduces jitter. Record the last execbuffer sequence for each client. Record that sequence in the throttle ioctl as the 'throttle sequence'. Wait for the last throttle sequence in the throttle ioctl. --- shared-core/i915_dma.c | 26 ++++++++++++++++++++++++++ shared-core/i915_drv.h | 10 ++++++++++ 2 files changed, 36 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 669f1e4e..2157c594 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1149,12 +1149,38 @@ void i915_driver_lastclose(struct drm_device * dev) i915_dma_cleanup(dev); } +int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv) +{ + struct drm_i915_file_private *i915_file_priv; + + DRM_DEBUG("\n"); + i915_file_priv = (struct drm_i915_file_private *) + drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES); + + if (!i915_file_priv) + return -ENOMEM; + + file_priv->driver_priv = i915_file_priv; + + i915_file_priv->mm.last_gem_seqno = 0; + i915_file_priv->mm.last_gem_throttle_seqno = 0; + + return 0; +} + void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) { drm_i915_private_t *dev_priv = dev->dev_private; i915_mem_release(dev, file_priv, dev_priv->agp_heap); } +void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) +{ + struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv; + + drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES); +} + struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH), diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 5cc6e680..334bc43f 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -301,6 +301,13 @@ typedef struct drm_i915_private { } mm; } drm_i915_private_t; +struct drm_i915_file_private { + struct { + uint32_t last_gem_seqno; + uint32_t last_gem_throttle_seqno; + } mm; +}; + enum intel_chip_family { CHIP_I8XX = 0x01, CHIP_I9XX = 0x02, @@ -378,8 +385,11 @@ extern void i915_kernel_lost_context(struct drm_device * dev); extern int i915_driver_load(struct drm_device *, unsigned long flags); extern int i915_driver_unload(struct drm_device *); extern void i915_driver_lastclose(struct drm_device * dev); +extern int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv); extern void i915_driver_preclose(struct drm_device *dev, struct drm_file *file_priv); +extern void i915_driver_postclose(struct drm_device *dev, + struct drm_file *file_priv); extern int i915_driver_device_is_agp(struct drm_device * dev); extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -- cgit v1.2.3 From c847271179da382af52a6874e2edec586b88af75 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 16 Jun 2008 13:09:31 -0700 Subject: [linux] Use the device's irq for handler setup instead of stale dev->irq. This fixes registration when MSI is set up after the stub function fills in dev->irq. Otherwise /proc/interrupts would report attachment to the fasteoi interrupt. dev->irq is still exposed (and updated at IRQ setup) for the drivers that use it for whatever reason. --- shared-core/i915_dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 2157c594..2db6be07 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -150,7 +150,7 @@ static int i915_dma_cleanup(struct drm_device * dev) * may not have been called from userspace and after dev_private * is freed, it's too late. */ - if (dev->irq) + if (dev->irq_enabled) drm_irq_uninstall(dev); if (dev_priv->ring.virtual_start) { @@ -889,7 +889,7 @@ static int i915_getparam(struct drm_device *dev, void *data, switch (param->param) { case I915_PARAM_IRQ_ACTIVE: - value = dev->irq ? 1 : 0; + value = dev->irq_enabled ? 1 : 0; break; case I915_PARAM_ALLOW_BATCHBUFFER: value = dev_priv->allow_batchbuffer ? 1 : 0; -- cgit v1.2.3 From 52e5d24fae4af6f2f4a5304a516c8c5ab347a11b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 20 Jun 2008 00:19:42 -0700 Subject: [intel-gem] Add DRM_IOCTL_I915_GEM_SW_FINISH to flag CPU writes When a software fallback has completed, usermode must notify the kernel so that any scanout buffers can be synchronized. This ioctl should be called whenever a fallback completes to flush CPU and chipset caches. --- shared-core/i915_dma.c | 1 + shared-core/i915_drm.h | 9 +++++++++ shared-core/i915_drv.h | 2 ++ 3 files changed, 12 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 2db6be07..6ee3d19f 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1216,6 +1216,7 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0), + DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index f16dc99f..fde474d7 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -189,6 +189,7 @@ typedef struct drm_i915_sarea { #define DRM_I915_GEM_PWRITE 0x1d #define DRM_I915_GEM_MMAP 0x1e #define DRM_I915_GEM_SET_DOMAIN 0x1f +#define DRM_I915_GEM_SW_FINISH 0x20 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -221,6 +222,7 @@ typedef struct drm_i915_sarea { #define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite) #define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap) #define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain) +#define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish) /* Asynchronous page flipping: */ @@ -501,6 +503,11 @@ struct drm_i915_gem_set_domain { uint32_t write_domain; }; +struct drm_i915_gem_sw_finish { + /** Handle for the object */ + uint32_t handle; +}; + struct drm_i915_gem_relocation_entry { /** * Handle of the buffer being pointed to by this relocation entry. @@ -565,6 +572,8 @@ struct drm_i915_gem_relocation_entry { #define I915_GEM_DOMAIN_INSTRUCTION 0x00000010 /** Vertex address cache */ #define I915_GEM_DOMAIN_VERTEX 0x00000020 +/** GTT domain - aperture and scanout */ +#define I915_GEM_DOMAIN_GTT 0x00000040 /** @} */ struct drm_i915_gem_exec_object { diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 334bc43f..4d8a40d4 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -477,6 +477,8 @@ int i915_gem_mmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); int i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_pin_ioctl(struct drm_device *dev, void *data, -- cgit v1.2.3 From 918420deefb978d4e572121b4273d717bdbfde8e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 20 Jun 2008 00:21:37 -0700 Subject: [intel-gem] Use shmem_getpage instead of find_or_create_page find_or_create_page doesn't quite set up pages correctly; any newly created pages aren't hooked into the shmem object quite right; user space mmaps of those pages end up mapping pages full of zeros which then get written to the real pages inappropriately. This patch requires that the kernel export shmem_getpage. --- shared-core/i915_drv.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 4d8a40d4..94e80cda 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -332,6 +332,12 @@ struct drm_i915_gem_object { */ int active; + /** + * This is set if the object has been written to since last bound + * to the GTT + */ + int dirty; + /** AGP memory structure for our GTT binding. */ DRM_AGP_MEM *agp_mem; -- cgit v1.2.3 From 71b1623e22c54d42837840a1d0479127a5049caf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 20 Jun 2008 21:07:46 -0700 Subject: [intel-gem] Add intel-specific /proc entries to help monitor gem operation This adds gem_active, gem_flushing, gem_inactive, gem_request and gem_seqno entries to monitor gem operation and help debug issues. --- shared-core/i915_drv.h | 13 +++++++++++++ shared-core/i915_irq.c | 1 + 2 files changed, 14 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 94e80cda..87776504 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -289,6 +289,16 @@ typedef struct drm_i915_private { uint32_t next_gem_seqno; + /** + * Waiting sequence number, if any + */ + uint32_t waiting_gem_seqno; + + /** + * Last seq seen at irq time + */ + uint32_t irq_gem_seqno; + /** * Flag if the X Server, and thus DRM, is not currently in * control of the device. @@ -499,11 +509,14 @@ int i915_gem_entervt_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int i915_gem_proc_init(struct drm_minor *minor); +void i915_gem_proc_cleanup(struct drm_minor *minor); int i915_gem_init_object(struct drm_gem_object *obj); void i915_gem_free_object(struct drm_gem_object *obj); int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment); void i915_gem_object_unpin(struct drm_gem_object *obj); void i915_gem_lastclose(struct drm_device *dev); +uint32_t i915_get_gem_seqno(struct drm_device *dev); void i915_gem_retire_requests(struct drm_device *dev); void i915_gem_retire_work_handler(struct work_struct *work); #endif diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 9ba5b00a..767181c2 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -489,6 +489,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); if (iir & I915_USER_INTERRUPT) { + dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev); DRM_WAKEUP(&dev_priv->irq_queue); #ifdef I915_HAVE_FENCE i915_fence_handler(dev); -- cgit v1.2.3 From 33114e4a1167ac79cb53043e77c16cc7fe40a640 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 21 Jun 2008 00:12:21 -0700 Subject: [intel] Count received interrupts Another patch adds this to a /proc/dri file for debugging and monitoring. --- shared-core/i915_drv.h | 1 - shared-core/i915_irq.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 87776504..9f500330 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -119,7 +119,6 @@ typedef struct drm_i915_private { wait_queue_head_t irq_queue; atomic_t irq_received; - atomic_t irq_emitted; int tex_lru_log_granularity; int allow_batchbuffer; diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 767181c2..c0abcbdd 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -456,6 +456,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) #if 0 DRM_DEBUG("flag=%08x\n", iir); #endif + atomic_inc(&dev_priv->irq_received); if (iir == 0) { DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n", iir, @@ -963,6 +964,7 @@ void i915_driver_irq_preinstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + atomic_set(&dev_priv->irq_received, 0); I915_WRITE(I915REG_HWSTAM, 0xffff); I915_WRITE(I915REG_INT_ENABLE_R, 0x0); I915_WRITE(I915REG_INT_MASK_R, 0xffffffff); -- cgit v1.2.3 From a369bf0e575697308690f532576caf652e42b4cb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 21 Jun 2008 00:33:07 -0700 Subject: [intel] Use IMR instead of IER to pend interrupts during ISR Noting that the interrupt mask register was more reliable than the interrupt enable register for managing interrupts in user_irq_on/user_irq_off, this patch replaces the remaining IER frobbing with IMR instead. The test which exposes IER related failures is: $ glxgears & glxgears & glxgears (reposition the glxgears windows away from the upper left corner) $ while :; do x11perf -rect100 -reps 800 -repeat 1; sleep 1; done & $ while :; do runoa; runet; done & --- shared-core/i915_irq.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index c0abcbdd..a55497a8 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -451,7 +451,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) int vblank = 0; if (dev->pdev->msi_enabled) - I915_WRITE(I915REG_INT_ENABLE_R, 0); + I915_WRITE(I915REG_INT_MASK_R, ~0); iir = I915_READ(I915REG_INT_IDENTITY_R); #if 0 DRM_DEBUG("flag=%08x\n", iir); @@ -464,9 +464,11 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) I915_READ(I915REG_INT_ENABLE_R), I915_READ(I915REG_PIPEASTAT), I915_READ(I915REG_PIPEBSTAT)); - if (dev->pdev->msi_enabled) - I915_WRITE(I915REG_INT_ENABLE_R, - I915_INTERRUPT_ENABLE_MASK); + if (dev->pdev->msi_enabled) { + I915_WRITE(I915REG_INT_MASK_R, + dev_priv->irq_mask_reg); + (void) I915_READ(I915REG_INT_MASK_R); + } return IRQ_NONE; } @@ -484,6 +486,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) } I915_WRITE(I915REG_INT_IDENTITY_R, iir); + if (dev->pdev->msi_enabled) + I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); (void) I915_READ(I915REG_INT_IDENTITY_R); /* Flush posted writes */ if (dev_priv->sarea_priv) @@ -512,8 +516,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) drm_locked_tasklet(dev, i915_vblank_tasklet); } - if (dev->pdev->msi_enabled) - I915_WRITE(I915REG_INT_ENABLE_R, I915_INTERRUPT_ENABLE_MASK); return IRQ_HANDLED; } @@ -543,6 +545,7 @@ void i915_user_irq_on(drm_i915_private_t *dev_priv) if ((dev_priv->irq_mask_reg & I915_USER_INTERRUPT) != 0) { dev_priv->irq_mask_reg &= ~I915_USER_INTERRUPT; I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); + I915_WRITE(I915REG_INT_IDENTITY_R, I915_USER_INTERRUPT); (void) I915_READ (I915REG_INT_MASK_R); } } @@ -740,7 +743,7 @@ static void i915_enable_interrupt (struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - dev_priv->irq_mask_reg = I915_INTERRUPT_ENABLE_MASK; + dev_priv->irq_mask_reg = ~0; I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); I915_WRITE(I915REG_INT_ENABLE_R, I915_INTERRUPT_ENABLE_MASK); (void) I915_READ (I915REG_INT_ENABLE_R); -- cgit v1.2.3 From ed73651d47a5f95c3436207144b70811366e4edd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Jun 2008 10:16:35 -0700 Subject: [intel-gem] Recover resources from wedged hardware. Clean up queues, free objects. On the next entervt, unmark the hardware to let the user try again (presumably after resetting the chip). Someday we'll automatically recover... --- shared-core/i915_drv.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 9f500330..0df5af9c 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -307,6 +307,15 @@ typedef struct drm_i915_private { * transitioned away from for kernel modesetting. */ int suspended; + + /** + * Flag if the hardware appears to be wedged. + * + * This is set when attempts to idle the device timeout. + * It prevents command submission from occuring and makes + * every pending request fail + */ + int wedged; } mm; } drm_i915_private_t; -- cgit v1.2.3 From e36da6a133328a4cf9c98d9347c87dc3c3a12d16 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 24 Jun 2008 13:08:04 -0700 Subject: [intel] Create functions to enable/disable interrupts This shares common code sequences for managing the interrupt register bits --- shared-core/i915_irq.c | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index a55497a8..710b2896 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -40,6 +40,26 @@ I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) +static inline void +i915_enable_irq(drm_i915_private_t *dev_priv, uint32_t mask) +{ + if ((dev_priv->irq_mask_reg & mask) != 0) { + dev_priv->irq_mask_reg &= ~mask; + I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); + (void) I915_READ(I915REG_INT_MASK_R); + } +} + +static inline void +i915_disable_irq(drm_i915_private_t *dev_priv, uint32_t mask) +{ + if ((dev_priv->irq_mask_reg & mask) != mask) { + dev_priv->irq_mask_reg |= mask; + I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); + (void) I915_READ(I915REG_INT_MASK_R); + } +} + /** * i915_get_pipe - return the the pipe associated with a given plane * @dev: DRM device @@ -541,29 +561,17 @@ int i915_emit_irq(struct drm_device *dev) void i915_user_irq_on(drm_i915_private_t *dev_priv) { DRM_SPINLOCK(&dev_priv->user_irq_lock); - if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){ - if ((dev_priv->irq_mask_reg & I915_USER_INTERRUPT) != 0) { - dev_priv->irq_mask_reg &= ~I915_USER_INTERRUPT; - I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); - I915_WRITE(I915REG_INT_IDENTITY_R, I915_USER_INTERRUPT); - (void) I915_READ (I915REG_INT_MASK_R); - } - } + if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)) + i915_enable_irq(dev_priv, I915_USER_INTERRUPT); DRM_SPINUNLOCK(&dev_priv->user_irq_lock); - } void i915_user_irq_off(drm_i915_private_t *dev_priv) { DRM_SPINLOCK(&dev_priv->user_irq_lock); BUG_ON(dev_priv->irq_enabled && dev_priv->user_irq_refcount <= 0); - if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { - if ((dev_priv->irq_mask_reg & I915_USER_INTERRUPT) == 0) { - dev_priv->irq_mask_reg |= I915_USER_INTERRUPT; - I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); - (void) I915_READ(I915REG_INT_MASK_R); - } - } + if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) + i915_disable_irq(dev_priv, I915_USER_INTERRUPT); DRM_SPINUNLOCK(&dev_priv->user_irq_lock); } @@ -688,9 +696,7 @@ int i915_enable_vblank(struct drm_device *dev, int plane) I915_WRITE(pipestat_reg, pipestat); } DRM_SPINLOCK(&dev_priv->user_irq_lock); - dev_priv->irq_mask_reg &= ~mask_reg; - I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); - I915_READ(I915REG_INT_MASK_R); + i915_enable_irq(dev_priv, mask_reg); DRM_SPINUNLOCK(&dev_priv->user_irq_lock); return 0; @@ -720,9 +726,7 @@ void i915_disable_vblank(struct drm_device *dev, int plane) } DRM_SPINLOCK(&dev_priv->user_irq_lock); - dev_priv->irq_mask_reg |= mask_reg; - I915_WRITE(I915REG_INT_MASK_R, dev_priv->irq_mask_reg); - (void) I915_READ (I915REG_INT_MASK_R); + i915_disable_irq(dev_priv, mask_reg); DRM_SPINUNLOCK(&dev_priv->user_irq_lock); if (pipestat_reg) { -- cgit v1.2.3 From d250a55fc6a726a8bfaf4f871eeb09c895a9ba51 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 24 Jun 2008 13:39:25 -0700 Subject: [intel] Get vblank pipe from irq_mask_reg instead of hardware enable reg With the interrupt enable/disable using only the mask register, it was wrong to use the enable register to detect which pipes had vblank detection turned on. Also, as we keep a local copy of the mask register around, and MSI machines smack the hardware during the interrupt handler, it is more efficient and more correct to use the local copy. --- shared-core/i915_irq.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 710b2896..f09ae5f7 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -794,14 +794,15 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data, { drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_vblank_pipe_t *pipe = data; - u16 flag; + u32 flag = 0; if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } - flag = I915_READ(I915REG_INT_ENABLE_R); + if (dev_priv->irq_enabled) + flag = ~dev_priv->irq_mask_reg; pipe->pipe = 0; if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) pipe->pipe |= DRM_I915_VBLANK_PIPE_A; -- cgit v1.2.3 From a0474be4e78d678eb615b37aad355effb955ee19 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 11 Jul 2008 14:47:33 -0700 Subject: intel-gem: Add two new ioctls for managing tiling on objects. Various chips have exciting interactions between the CPU and the GPU's different ways of accessing interleaved memory, so we need some kernel assistance in determining how it works. Only fully tested on GM965 so far. --- shared-core/i915_dma.c | 10 +++----- shared-core/i915_drm.h | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ shared-core/i915_drv.h | 29 +++++++++++++++++++++++ 3 files changed, 96 insertions(+), 7 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 6ee3d19f..c9a9d800 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1068,13 +1068,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ret = drm_addmap(dev, base, size, _DRM_REGISTERS, _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio_map); - INIT_LIST_HEAD(&dev_priv->mm.active_list); - INIT_LIST_HEAD(&dev_priv->mm.flushing_list); - INIT_LIST_HEAD(&dev_priv->mm.inactive_list); - INIT_LIST_HEAD(&dev_priv->mm.request_list); - INIT_DELAYED_WORK(&dev_priv->mm.retire_work, - i915_gem_retire_work_handler); - dev_priv->mm.next_gem_seqno = 1; + i915_gem_load(dev); #ifdef __linux__ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) @@ -1217,6 +1211,8 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0), + DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0), + DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index fde474d7..9feffeb5 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -190,6 +190,8 @@ typedef struct drm_i915_sarea { #define DRM_I915_GEM_MMAP 0x1e #define DRM_I915_GEM_SET_DOMAIN 0x1f #define DRM_I915_GEM_SW_FINISH 0x20 +#define DRM_I915_GEM_SET_TILING 0x21 +#define DRM_I915_GEM_GET_TILING 0x22 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -223,6 +225,8 @@ typedef struct drm_i915_sarea { #define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap) #define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain) #define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish) +#define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling) +#define DRM_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling) /* Asynchronous page flipping: */ @@ -651,4 +655,64 @@ struct drm_i915_gem_busy { uint32_t busy; }; +#define I915_TILING_NONE 0 +#define I915_TILING_X 1 +#define I915_TILING_Y 2 + +#define I915_BIT_6_SWIZZLE_NONE 0 +#define I915_BIT_6_SWIZZLE_9 1 +#define I915_BIT_6_SWIZZLE_9_10 2 +#define I915_BIT_6_SWIZZLE_9_11 3 +#define I915_BIT_6_SWIZZLE_9_10_11 4 +/* Not seen by userland */ +#define I915_BIT_6_SWIZZLE_UNKNOWN 5 + +struct drm_i915_gem_set_tiling { + /** Handle of the buffer to have its tiling state updated */ + uint32_t handle; + + /** + * Tiling mode for the object (I915_TILING_NONE, I915_TILING_X, + * I915_TILING_Y). + * + * This value is to be set on request, and will be updated by the + * kernel on successful return with the actual chosen tiling layout. + * + * The tiling mode may be demoted to I915_TILING_NONE when the system + * has bit 6 swizzling that can't be managed correctly by GEM. + * + * Buffer contents become undefined when changing tiling_mode. + */ + uint32_t tiling_mode; + + /** + * Stride in bytes for the object when in I915_TILING_X or + * I915_TILING_Y. + */ + uint32_t stride; + + /** + * Returned address bit 6 swizzling required for CPU access through + * mmap mapping. + */ + uint32_t swizzle_mode; +}; + +struct drm_i915_gem_get_tiling { + /** Handle of the buffer to get tiling state for. */ + uint32_t handle; + + /** + * Current tiling mode for the object (I915_TILING_NONE, I915_TILING_X, + * I915_TILING_Y). + */ + uint32_t tiling_mode; + + /** + * Returned address bit 6 swizzling required for CPU access through + * mmap mapping. + */ + uint32_t swizzle_mode; +}; + #endif /* _I915_DRM_H_ */ diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 0df5af9c..a9a431c4 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -316,6 +316,11 @@ typedef struct drm_i915_private { * every pending request fail */ int wedged; + + /** Bit 6 swizzling required for X tiling */ + uint32_t bit_6_swizzle_x; + /** Bit 6 swizzling required for Y tiling */ + uint32_t bit_6_swizzle_y; } mm; } drm_i915_private_t; @@ -376,6 +381,9 @@ struct drm_i915_gem_object { /** Breadcrumb of last rendering to the buffer. */ uint32_t last_rendering_seqno; + + /** Current tiling mode for the object. */ + uint32_t tiling_mode; }; /** @@ -517,6 +525,11 @@ int i915_gem_entervt_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int i915_gem_set_tiling(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int i915_gem_get_tiling(struct drm_device *dev, void *data, + struct drm_file *file_priv); +void i915_gem_load(struct drm_device *dev); int i915_gem_proc_init(struct drm_minor *minor); void i915_gem_proc_cleanup(struct drm_minor *minor); int i915_gem_init_object(struct drm_gem_object *obj); @@ -529,6 +542,9 @@ void i915_gem_retire_requests(struct drm_device *dev); void i915_gem_retire_work_handler(struct work_struct *work); #endif +/* i915_gem_tiling.c */ +void i915_gem_detect_bit_6_swizzle(struct drm_device *dev); + #ifdef __linux__ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) extern void intel_init_chipset_flush_compat(struct drm_device *dev); @@ -585,6 +601,19 @@ void i915_ring_validate(struct drm_device *dev, const char *func, int line); extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); +/* MCH MMIO space */ +/** 915-945 and GM965 MCH register controlling DRAM channel access */ +#define DCC 0x200 +#define DCC_ADDRESSING_MODE_SINGLE_CHANNEL (0 << 0) +#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC (1 << 0) +#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED (2 << 0) +#define DCC_ADDRESSING_MODE_MASK (3 << 0) +#define DCC_CHANNEL_XOR_DISABLE (1 << 10) + +/** 965 MCH register controlling DRAM channel configuration */ +#define CHDECMISC 0x111 +#define CHDECMISC_FLEXMEMORY (1 << 1) + /* Extended config space */ #define LBB 0xf4 -- cgit v1.2.3 From 67d15215660407b07265c37d60ea5cac8930cef9 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 1 Jul 2008 12:31:37 -0700 Subject: intel-gem: Set up HWS when it needs a vaddr during GEM init. This requires an updated 2D driver to not try to set it up as well. --- shared-core/i915_drv.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index a9a431c4..c57c292f 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -114,6 +114,7 @@ typedef struct drm_i915_private { uint32_t counter; unsigned int status_gfx_addr; drm_local_map_t hws_map; + struct drm_gem_object *hws_obj; unsigned int cpp; @@ -854,6 +855,11 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define RING_VALID 0x00000001 #define RING_INVALID 0x00000000 +/* Hardware status page address */ +#define HWS_PGA 0x2080 +#define HWS_ADDRESS_MASK 0xfffff000 +#define HWS_START_ADDRES_SHIFT 4 + /* Instruction parser error reg: */ #define IPEIR 0x2088 -- cgit v1.2.3 From 04ae66db1c517264cddc786be962fdd393c9c8ac Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sat, 26 Jul 2008 19:51:58 -0700 Subject: intel-gem: Move debug-only functions to a separate file. --- shared-core/i915_drv.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index c57c292f..99416e8d 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -72,6 +72,14 @@ struct drm_i915_validate_buffer; #endif +#define WATCH_COHERENCY 0 +#define WATCH_BUF 0 +#define WATCH_EXEC 0 +#define WATCH_LRU 0 +#define WATCH_RELOC 0 +#define WATCH_INACTIVE 0 +#define WATCH_PWRITE 0 + typedef struct _drm_i915_ring_buffer { int tail_mask; unsigned long Size; @@ -541,11 +549,25 @@ void i915_gem_lastclose(struct drm_device *dev); uint32_t i915_get_gem_seqno(struct drm_device *dev); void i915_gem_retire_requests(struct drm_device *dev); void i915_gem_retire_work_handler(struct work_struct *work); +void i915_gem_clflush_object(struct drm_gem_object *obj); #endif /* i915_gem_tiling.c */ void i915_gem_detect_bit_6_swizzle(struct drm_device *dev); +/* i915_gem_debug.c */ +void i915_gem_dump_object(struct drm_gem_object *obj, int len, + const char *where, uint32_t mark); +#if WATCH_INACTIVE +void i915_verify_inactive(struct drm_device *dev, char *file, int line); +#else +#define i915_verify_inactive(dev,file,line) +#endif +void i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle); +void i915_gem_dump_object(struct drm_gem_object *obj, int len, + const char *where, uint32_t mark); +void i915_dump_lru(struct drm_device *dev, const char *where); + #ifdef __linux__ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) extern void intel_init_chipset_flush_compat(struct drm_device *dev); -- cgit v1.2.3 From f85fd1b42dc2d77266007c02144d4f4f524e4157 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sat, 26 Jul 2008 19:28:14 -0700 Subject: intel-gem: Speed up tiled readpixels by tracking which pages have been flushed. This is around 3x or so speedup, since we would read wide rows at a time, and clflush each tile 8 times as a result. We'll want code related to this anyway when we do fault-based per-page clflushing for sw fallbacks. --- shared-core/i915_drv.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 99416e8d..7bb9e5bb 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -393,6 +393,12 @@ struct drm_i915_gem_object { /** Current tiling mode for the object. */ uint32_t tiling_mode; + + /** + * Flagging of which individual pages are valid in GEM_DOMAIN_CPU when + * GEM_DOMAIN_CPU is not in the object's read domain. + */ + uint8_t *page_cpu_valid; }; /** -- cgit v1.2.3 From 487c42bd42d93304278abce03b36c935bdc83284 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 28 Jul 2008 11:45:22 -0700 Subject: intel-gem: Another checkpatch.pl pass. --- shared-core/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 7bb9e5bb..50319373 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -294,14 +294,14 @@ typedef struct drm_i915_private { * fires, go retire requests. */ struct delayed_work retire_work; - + uint32_t next_gem_seqno; /** * Waiting sequence number, if any */ uint32_t waiting_gem_seqno; - + /** * Last seq seen at irq time */ -- cgit v1.2.3 From 0e49e49c9f8fdbe77740c1bdcc0cb4102d26bf7a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 28 Jul 2008 23:14:11 -0700 Subject: intel: Fix typo in unused register definition name. --- shared-core/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 9d3a37df..3cd57c21 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -887,7 +887,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define ACTHD_I965 0x02074 #define HWS_PGA 0x02080 #define HWS_ADDRESS_MASK 0xfffff000 -#define HWS_START_ADDRES_SHIFT 4 +#define HWS_START_ADDRESS_SHIFT 4 #define IPEIR 0x02088 #define NOPID 0x02094 #define HWSTAM 0x02098 -- cgit v1.2.3 From 33c8e03787308c2b86a4f724ba7ce4dc43918b6a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 30 Jul 2008 11:22:48 -0700 Subject: Revert "Rename drm_mm.c and its fuctions to drm_memrange." This reverts commit 3ad8db2071d30c198403e605f2726fc5c3e46bfd. We ended up not needing that namespace, and I'd rather not have the churn for producing diffs. --- shared-core/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 3cd57c21..0ebdab0c 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -277,7 +277,7 @@ typedef struct drm_i915_private { u8 saveCR[37]; struct { - struct drm_memrange gtt_space; + struct drm_mm gtt_space; /** * List of objects currently involved in rendering from the @@ -378,7 +378,7 @@ struct drm_i915_gem_object { struct drm_gem_object *obj; /** Current space allocated to this object in the GTT, if any. */ - struct drm_memrange_node *gtt_space; + struct drm_mm_node *gtt_space; /** This object's place on the active/flushing/inactive lists */ struct list_head list; -- cgit v1.2.3 From ccbaad52f79162a77d98d0dde00681b1dbf14165 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 30 Jul 2008 14:10:36 -0700 Subject: intel-gem: Replace version bump signalling GEM with I915_PARAM_HAS_GEM. --- shared-core/i915_dma.c | 3 +++ shared-core/i915_drm.h | 1 + shared-core/i915_drv.h | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 1f9fa4f7..13ba5b3f 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -900,6 +900,9 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_CHIPSET_ID: value = dev->pci_device; break; + case I915_PARAM_HAS_GEM: + value = 1; + break; default: DRM_ERROR("Unknown parameter %d\n", param->param); return -EINVAL; diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 9feffeb5..2801687c 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -280,6 +280,7 @@ typedef struct drm_i915_irq_wait { #define I915_PARAM_ALLOW_BATCHBUFFER 2 #define I915_PARAM_LAST_DISPATCH 3 #define I915_PARAM_CHIPSET_ID 4 +#define I915_PARAM_HAS_GEM 5 typedef struct drm_i915_getparam { int param; diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 0ebdab0c..fe52845e 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -37,7 +37,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20080611" +#define DRIVER_DATE "20080730" #if defined(__linux__) #define I915_HAVE_FENCE @@ -61,7 +61,7 @@ */ #define DRIVER_MAJOR 1 #if defined(I915_HAVE_FENCE) && defined(I915_HAVE_BUFFER) -#define DRIVER_MINOR 14 +#define DRIVER_MINOR 13 #else #define DRIVER_MINOR 6 #endif -- cgit v1.2.3