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_drv.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'shared-core/i915_drv.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/i915_drv.h | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'shared-core/i915_drv.h') 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/i915_drv.h') 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 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_drv.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'shared-core/i915_drv.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 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/i915_drv.h') 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 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_drv.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'shared-core/i915_drv.h') 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 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/i915_drv.h') 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_drv.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'shared-core/i915_drv.h') 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); -- 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/i915_drv.h') 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 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_drv.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'shared-core/i915_drv.h') 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 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_drv.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'shared-core/i915_drv.h') 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 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/i915_drv.h') 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 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_drv.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'shared-core/i915_drv.h') 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/i915_drv.h') 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/i915_drv.h') 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/i915_drv.h') 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_drv.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'shared-core/i915_drv.h') 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/i915_drv.h') 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_drv.h | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'shared-core/i915_drv.h') 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__ -- 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_drv.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'shared-core/i915_drv.h') 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_drv.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'shared-core/i915_drv.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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core/i915_drv.h') 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 -- 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/i915_drv.h') 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 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_drv.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'shared-core/i915_drv.h') 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 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_drv.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'shared-core/i915_drv.h') 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_drv.h | 1 - 1 file changed, 1 deletion(-) (limited to 'shared-core/i915_drv.h') 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