From patchwork Fri Apr 2 05:30:49 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zou, Nanhai" X-Patchwork-Id: 90324 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o325WfDx003640 for ; Fri, 2 Apr 2010 05:33:16 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id F0FFD9EB35; Thu, 1 Apr 2010 22:32:27 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by gabe.freedesktop.org (Postfix) with ESMTP id 0336C9E9F4 for ; Thu, 1 Apr 2010 22:32:19 -0700 (PDT) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP; 01 Apr 2010 22:32:10 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.51,352,1267430400"; d="scan'208";a="609707778" Received: from pgsmsx603.gar.corp.intel.com ([10.221.43.87]) by orsmga001.jf.intel.com with ESMTP; 01 Apr 2010 22:32:04 -0700 Received: from shzsmsx502.ccr.corp.intel.com (10.239.4.97) by pgsmsx603.gar.corp.intel.com (10.221.43.87) with Microsoft SMTP Server (TLS) id 8.2.176.0; Fri, 2 Apr 2010 13:31:05 +0800 Received: from shzsmsx502.ccr.corp.intel.com ([10.239.4.97]) by shzsmsx502.ccr.corp.intel.com ([10.239.4.97]) with mapi; Fri, 2 Apr 2010 13:30:50 +0800 From: "Zou, Nanhai" To: "intel-gfx@lists.freedesktop.org" Date: Fri, 2 Apr 2010 13:30:49 +0800 Thread-Topic: [Patch 4/5] multiple ring buffer support, adapt the intel_ring_buffer with gem Thread-Index: AcrSJadUh1Hbsth3RMatwrwTjtuVFg== Message-ID: <32606542045FF34BA04F9D5BB0CB6BB5A532ABAA@shzsmsx502.ccr.corp.intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: yes X-MS-TNEF-Correlator: acceptlanguage: en-US MIME-Version: 1.0 Cc: "Anholt, Eric" Subject: [Intel-gfx] [Patch 4/5] multiple ring buffer support, adapt the intel_ring_buffer with gem X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Fri, 02 Apr 2010 05:33:17 +0000 (UTC) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 305d36c..1050bc9 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -76,7 +76,7 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) case ACTIVE_LIST: seq_printf(m, "Active:\n"); lock = &dev_priv->mm.active_list_lock; - head = &dev_priv->mm.active_list; + head = &dev_priv->render_ring.active_list; break; case INACTIVE_LIST: seq_printf(m, "Inactive:\n"); @@ -129,7 +129,7 @@ static int i915_gem_request_info(struct seq_file *m, void *data) struct drm_i915_gem_request *gem_request; seq_printf(m, "Request:\n"); - list_for_each_entry(gem_request, &dev_priv->mm.request_list, list) { + list_for_each_entry(gem_request, &dev_priv->render_ring.request_list, list) { seq_printf(m, " %d @ %d\n", gem_request->seqno, (int) (jiffies - gem_request->emitted_jiffies)); @@ -145,13 +145,13 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data) if (dev_priv->render_ring.status_page.page_addr != NULL) { seq_printf(m, "Current sequence: %d\n", - i915_get_gem_seqno(dev)); + i915_get_gem_seqno(dev, &dev_priv->render_ring)); } else { seq_printf(m, "Current sequence: hws uninitialized\n"); } seq_printf(m, "Waiter sequence: %d\n", - dev_priv->mm.waiting_gem_seqno); - seq_printf(m, "IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno); + dev_priv->render_ring.waiting_gem_seqno); + seq_printf(m, "IRQ sequence: %d\n", dev_priv->render_ring.irq_gem_seqno); return 0; } @@ -197,14 +197,14 @@ static int i915_interrupt_info(struct seq_file *m, void *data) atomic_read(&dev_priv->irq_received)); if (dev_priv->render_ring.status_page.page_addr != NULL) { seq_printf(m, "Current sequence: %d\n", - i915_get_gem_seqno(dev)); + i915_get_gem_seqno(dev, &dev_priv->render_ring)); } else { seq_printf(m, "Current sequence: hws uninitialized\n"); } seq_printf(m, "Waiter sequence: %d\n", - dev_priv->mm.waiting_gem_seqno); + dev_priv->render_ring.waiting_gem_seqno); seq_printf(m, "IRQ sequence: %d\n", - dev_priv->mm.irq_gem_seqno); + dev_priv->render_ring.irq_gem_seqno); return 0; } @@ -287,7 +287,7 @@ static int i915_batchbuffer_info(struct seq_file *m, void *data) spin_lock(&dev_priv->mm.active_list_lock); - list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) { + list_for_each_entry(obj_priv, &dev_priv->render_ring.active_list, list) { obj = obj_priv->obj; if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) { ret = i915_gem_object_get_pages(obj, 0); @@ -682,7 +682,7 @@ i915_wedged_write(struct file *filp, atomic_set(&dev_priv->mm.wedged, val); if (val) { - DRM_WAKEUP(&dev_priv->irq_queue); + DRM_WAKEUP(&dev_priv->render_ring.irq_queue); queue_work(dev_priv->wq, &dev_priv->error_work); } diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index ead4a29..9bc5ee9 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -39,6 +39,7 @@ #include #include + /** * Sets up the hardware status page for devices that need a physical address * in the register. @@ -61,7 +62,7 @@ static int i915_init_phys_hws(struct drm_device *dev) if (IS_I965G(dev)) dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) & - 0xf0; + 0xf0; I915_WRITE(HWS_PGA, dev_priv->dma_status_page); DRM_DEBUG_DRIVER("Enabled hardware status page\n"); @@ -80,8 +81,8 @@ static void i915_free_hws(struct drm_device *dev) dev_priv->status_page_dmah = NULL; } - if (dev_priv->status_gfx_addr) { - dev_priv->status_gfx_addr = 0; + if (dev_priv->render_ring.status_page.gfx_addr) { + dev_priv->render_ring.status_page.gfx_addr = 0; drm_core_ioremapfree(&dev_priv->hws_map, dev); } @@ -89,33 +90,6 @@ static void i915_free_hws(struct drm_device *dev) I915_WRITE(HWS_PGA, 0x1ffff000); } -void i915_kernel_lost_context(struct drm_device * dev) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_master_private *master_priv; - struct intel_ring_buffer *ring = &(dev_priv->render_ring); - - /* - * We should never lose context on the ring with modesetting - * as we don't expose it to userspace - */ - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return; - - ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; - ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR; - ring->space = ring->head - (ring->tail + 8); - if (ring->space < 0) - ring->space += ring->size; - - if (!dev->primary->master) - return; - - master_priv = dev->primary->master->driver_priv; - if (ring->head == ring->tail && master_priv->sarea_priv) - master_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY; -} - static int i915_dma_cleanup(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; @@ -127,8 +101,6 @@ static int i915_dma_cleanup(struct drm_device * dev) drm_irq_uninstall(dev); intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); - if (HAS_BSD(dev)) - intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); /* Clear the HWS virtual address at teardown */ if (I915_NEED_GFX_HWS(dev)) @@ -200,13 +172,11 @@ static int i915_dma_resume(struct drm_device * dev) DRM_DEBUG_DRIVER("%s\n", __func__); ring = &dev_priv->render_ring; - if (ring->map.handle == NULL) { DRM_ERROR("can not ioremap virtual address for" " ring buffer\n"); return -ENOMEM; } - /* Program Hardware Status Page */ if (!ring->status_page.page_addr) { DRM_ERROR("Can not find hardware status page\n"); @@ -214,11 +184,11 @@ static int i915_dma_resume(struct drm_device * dev) } DRM_DEBUG_DRIVER("hw status page @ %p\n", ring->status_page.page_addr); + if (ring->status_page.gfx_addr != 0) ring->setup_status_page(dev, ring); else I915_WRITE(HWS_PGA, dev_priv->dma_status_page); - DRM_DEBUG_DRIVER("Enabled hardware status page\n"); return 0; @@ -328,6 +298,7 @@ static int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords) { drm_i915_private_t *dev_priv = dev->dev_private; int i; + RING_LOCALS; if ((dwords+1) * sizeof(int) >= dev_priv->render_ring.size - 8) return -EINVAL; @@ -363,6 +334,7 @@ i915_emit_box(struct drm_device *dev, int i, int DR1, int DR4) { struct drm_clip_rect box = boxes[i]; + RING_LOCALS; if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { DRM_ERROR("Bad box %d,%d..%d,%d\n", @@ -399,6 +371,7 @@ static void i915_emit_breadcrumb(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; + RING_LOCALS; dev_priv->counter++; if (dev_priv->counter > 0x7FFFFFFFUL) @@ -427,8 +400,6 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev, return -EINVAL; } - i915_kernel_lost_context(dev); - count = nbox ? nbox : 1; for (i = 0; i < count; i++) { @@ -454,14 +425,13 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, { int nbox = batch->num_cliprects; int i = 0, count; + RING_LOCALS; if ((batch->start | batch->used) & 0x7) { DRM_ERROR("alignment"); return -EINVAL; } - i915_kernel_lost_context(dev); - count = nbox ? nbox : 1; for (i = 0; i < count; i++) { @@ -502,6 +472,7 @@ static int i915_dispatch_flip(struct drm_device * dev) drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; + RING_LOCALS; if (!master_priv->sarea_priv) return -EINVAL; @@ -511,8 +482,6 @@ static int i915_dispatch_flip(struct drm_device * dev) dev_priv->current_page, master_priv->sarea_priv->pf_current_page); - i915_kernel_lost_context(dev); - BEGIN_LP_RING(2); OUT_RING(MI_FLUSH | MI_READ_FLUSH); OUT_RING(0); @@ -553,7 +522,6 @@ static int i915_quiescent(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; - i915_kernel_lost_context(dev); return intel_wait_ring_buffer(dev, &dev_priv->render_ring, dev_priv->render_ring.size - 8); } @@ -835,9 +803,9 @@ static int i915_set_status_page(struct drm_device *dev, void *data, memset(ring->status_page.page_addr, 0, PAGE_SIZE); I915_WRITE(HWS_PGA, ring->status_page.gfx_addr); DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n", - ring->status_page.gfx_addr); + ring->status_page.gfx_addr); DRM_DEBUG_DRIVER("load hws at %p\n", - ring->status_page.page_addr); + ring->status_page.page_addr); return 0; } @@ -1612,9 +1580,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (!IS_I945G(dev) && !IS_I945GM(dev)) pci_enable_msi(dev->pdev); - spin_lock_init(&dev_priv->user_irq_lock); spin_lock_init(&dev_priv->error_lock); - dev_priv->user_irq_refcount = 0; dev_priv->trace_irq_seqno = 0; ret = drm_vblank_init(dev, I915_NUM_PIPE); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ae9c4b9..487b9e4 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -310,7 +310,9 @@ int i965_reset(struct drm_device *dev, u8 flags) /* * Clear request list */ - i915_gem_retire_requests(dev); + + /* XXX per ring clear */ + i915_gem_retire_requests(dev, &dev_priv->render_ring); if (need_display) i915_save_display(dev); @@ -359,6 +361,7 @@ int i965_reset(struct drm_device *dev, u8 flags) */ if (drm_core_check_feature(dev, DRIVER_MODESET) || !dev_priv->mm.suspended) { + struct intel_ring_buffer *ring = &dev_priv->render_ring; struct drm_gem_object *obj = ring->gem_object; @@ -376,15 +379,11 @@ int i965_reset(struct drm_device *dev, u8 flags) ((obj->size - 4096) & RING_NR_PAGES) | RING_NO_REPORT | RING_VALID); - if (!drm_core_check_feature(dev, DRIVER_MODESET)) - i915_kernel_lost_context(dev); - else { - ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; - ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR; - ring->space = ring->head - (ring->tail + 8); - if (ring->space < 0) - ring->space += ring->size; - } + ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; + ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR; + ring->space = ring->head - (ring->tail + 8); + if (ring->space < 0) + ring->space += ring->size; mutex_unlock(&dev->struct_mutex); drm_irq_uninstall(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8e638ca..9a8f4b3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -83,6 +83,11 @@ enum plane { #define I915_GEM_PHYS_OVERLAY_REGS 3 #define I915_MAX_PHYS_OBJECT (I915_GEM_PHYS_OVERLAY_REGS) +#define RENDER_RING (1<<0) +#define BLITTER_RING (1<<1) +#define BSD_RING (1<<2) +#define MFX_RING (1<<3) + struct drm_i915_gem_phys_object { int id; struct page **page_list; @@ -232,9 +237,10 @@ typedef struct drm_i915_private { void __iomem *regs; struct pci_dev *bridge_dev; + struct intel_ring_buffer render_ring; - struct intel_ring_buffer bsd_ring; + struct intel_ring_buffer bsd_ring; drm_dma_handle_t *status_page_dmah; dma_addr_t dma_status_page; @@ -252,12 +258,8 @@ typedef struct drm_i915_private { int current_page; int page_flipping; - wait_queue_head_t irq_queue; + //wait_queue_head_t irq_queue; atomic_t irq_received; - /** Protects user_irq_refcount and irq_mask_reg */ - spinlock_t user_irq_lock; - /** Refcount for i915_user_irq_get() versus i915_user_irq_put(). */ - int user_irq_refcount; u32 trace_irq_seqno; /** Cached value of IMR to avoid reads in updating the bitfield */ u32 irq_mask_reg; @@ -500,18 +502,7 @@ typedef struct drm_i915_private { */ struct list_head shrink_list; - /** - * List of objects currently involved in rendering from the - * ringbuffer. - * - * Includes buffers having the contents of their GPU caches - * flushed, not necessarily primitives. last_rendering_seqno - * represents when the rendering involved will be completed. - * - * A reference is held on the buffer while on this list. - */ spinlock_t active_list_lock; - struct list_head active_list; /** * List of objects which are not in the ringbuffer but which @@ -549,12 +540,6 @@ typedef struct drm_i915_private { struct list_head fence_list; /** - * List of breadcrumbs associated with GPU requests currently - * outstanding. - */ - 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 @@ -563,18 +548,6 @@ typedef struct drm_i915_private { */ 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 - */ - uint32_t irq_gem_seqno; - /** * Flag if the X Server, and thus DRM, is not currently in * control of the device. @@ -725,6 +698,9 @@ struct drm_i915_gem_object { */ int madv; + /* Which ring refers to is this object */ + struct intel_ring_buffer *ring; + /** * Number of crtcs where this object is currently the fb, but * will be page flipped away on the next vblank. When it @@ -744,6 +720,9 @@ struct drm_i915_gem_object { * an emission time with seqnos for tracking how far ahead of the GPU we are. */ struct drm_i915_gem_request { + /** On Which ring this request is generated */ + struct intel_ring_buffer *ring; + /** GEM sequence number associated with this request. */ uint32_t seqno; @@ -808,9 +787,7 @@ extern int i915_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int i915_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv); -void i915_user_irq_get(struct drm_device *dev); void i915_trace_irq_get(struct drm_device *dev, u32 seqno); -void i915_user_irq_put(struct drm_device *dev); extern void i915_enable_interrupt (struct drm_device *dev); extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); @@ -832,7 +809,6 @@ extern void i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask); extern void ironlake_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask); extern void ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask); - void i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); @@ -903,11 +879,11 @@ void i915_gem_object_unpin(struct drm_gem_object *obj); int i915_gem_object_unbind(struct drm_gem_object *obj); void i915_gem_release_mmap(struct drm_gem_object *obj); void i915_gem_lastclose(struct drm_device *dev); -uint32_t i915_get_gem_seqno(struct drm_device *dev); +uint32_t i915_get_gem_seqno(struct drm_device *dev, struct intel_ring_buffer *ring); bool i915_seqno_passed(uint32_t seq1, uint32_t seq2); int i915_gem_object_get_fence_reg(struct drm_gem_object *obj); int i915_gem_object_put_fence_reg(struct drm_gem_object *obj); -void i915_gem_retire_requests(struct drm_device *dev); +void i915_gem_retire_requests(struct drm_device *dev, struct intel_ring_buffer *ring); void i915_gem_retire_work_handler(struct work_struct *work); void i915_gem_clflush_object(struct drm_gem_object *obj); int i915_gem_object_set_domain(struct drm_gem_object *obj, @@ -918,9 +894,13 @@ void i915_gem_cleanup_ringbuffer(struct drm_device *dev); int i915_gem_do_init(struct drm_device *dev, unsigned long start, unsigned long end); int i915_gem_idle(struct drm_device *dev); -uint32_t i915_add_request(struct drm_device *dev, struct drm_file *file_priv, - uint32_t flush_domains); -int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible); +int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, + int interruptible, + struct intel_ring_buffer *ring); +uint32_t i915_add_request(struct drm_device *dev, + struct drm_file *file_priv, + uint32_t flush_domains, + struct intel_ring_buffer *ring); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write); @@ -1017,22 +997,23 @@ extern void g4x_disable_fbc(struct drm_device *dev); #define I915_VERBOSE 0 -#define RING_LOCALS volatile unsigned int *ring_virt__; +#define RING_LOCALS #define BEGIN_LP_RING(n) do { \ - drm_i915_private_t *dev_priv = dev->dev_private; \ - intel_begin_ring_buffer(dev, &dev_priv->render_ring, 4*(n)); \ + drm_i915_private_t *dev_priv = dev->dev_private; \ + intel_begin_ring_buffer(dev, &dev_priv->render_ring, 4*(n)); \ } while (0) + #define OUT_RING(x) do { \ - drm_i915_private_t *dev_priv = dev->dev_private; \ - intel_fill_ring_buffer(dev, &dev_priv->render_ring, x); \ -} while (0) + drm_i915_private_t *dev_priv = dev->dev_private; \ + intel_fill_ring_buffer(dev, &dev_priv->render_ring, x); \ +} while (0) #define ADVANCE_LP_RING() do { \ - drm_i915_private_t *dev_priv = dev->dev_private; \ - intel_advance_ring_buffer(dev, &dev_priv->render_ring); \ -} while(0) + drm_i915_private_t *dev_priv = dev->dev_private; \ + intel_advance_ring_buffer(dev, &dev_priv->render_ring); \ +} while (0) /** * Reads a dword out of the status page, which is written to from the command @@ -1049,7 +1030,7 @@ extern void g4x_disable_fbc(struct drm_device *dev); * * The area from dword 0x20 to 0x3ff is available for driver usage. */ -#define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->render_ring.status_page.page_addr))[reg]) +#define READ_HWSP(dev_priv, reg) intel_read_status_page(&dev_priv->render_ring, reg) #define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX) #define I915_GEM_HWS_INDEX 0x20 #define I915_BREADCRUMB_INDEX 0x21 @@ -1102,7 +1083,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); (dev)->pci_device == 0x2A42 || \ (dev)->pci_device == 0x2E42) -#define HAS_BSD(dev) (IS_IRONLAKE(dev) || IS_G4X(dev)) +#define HAS_BSD(dev) (IS_IRONLAKE(dev) || IS_G4X(dev)) #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fb99c28..febd694 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -55,6 +55,8 @@ static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *o struct drm_i915_gem_pwrite *args, struct drm_file *file_priv); + + static LIST_HEAD(shrink_list); static DEFINE_SPINLOCK(shrink_list_lock); @@ -1481,12 +1483,16 @@ i915_gem_object_put_pages(struct drm_gem_object *obj) } static void -i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno) +i915_gem_object_move_to_active(struct drm_gem_object *obj, + uint32_t seqno, struct intel_ring_buffer *ring) { struct drm_device *dev = obj->dev; drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj_priv = obj->driver_private; + BUG_ON(ring == NULL); + obj_priv->ring = ring; + /* Add a reference if we're newly entering the active list. */ if (!obj_priv->active) { drm_gem_object_reference(obj); @@ -1494,8 +1500,7 @@ i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno) } /* Move from whatever list we were on to the tail of execution. */ spin_lock(&dev_priv->mm.active_list_lock); - list_move_tail(&obj_priv->list, - &dev_priv->mm.active_list); + list_move_tail(&obj_priv->list, &ring->active_list); spin_unlock(&dev_priv->mm.active_list_lock); obj_priv->last_rendering_seqno = seqno; } @@ -1548,6 +1553,7 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj) BUG_ON(!list_empty(&obj_priv->gpu_write_list)); obj_priv->last_rendering_seqno = 0; + obj_priv->ring = NULL; if (obj_priv->active) { obj_priv->active = 0; drm_gem_object_unreference(obj); @@ -1557,7 +1563,8 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj) static void i915_gem_process_flushing_list(struct drm_device *dev, - uint32_t flush_domains, uint32_t seqno) + uint32_t flush_domains, uint32_t seqno, + struct intel_ring_buffer *ring) { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj_priv, *next; @@ -1568,12 +1575,12 @@ i915_gem_process_flushing_list(struct drm_device *dev, struct drm_gem_object *obj = obj_priv->obj; if ((obj->write_domain & flush_domains) == - obj->write_domain) { + obj->write_domain && obj_priv->ring->ring_flag == ring->ring_flag) { uint32_t old_write_domain = obj->write_domain; obj->write_domain = 0; list_del_init(&obj_priv->gpu_write_list); - i915_gem_object_move_to_active(obj, seqno); + i915_gem_object_move_to_active(obj, seqno, ring); /* update the fence lru list */ if (obj_priv->fence_reg != I915_FENCE_REG_NONE) @@ -1597,7 +1604,7 @@ i915_gem_process_flushing_list(struct drm_device *dev, */ uint32_t i915_add_request(struct drm_device *dev, struct drm_file *file_priv, - uint32_t flush_domains) + uint32_t flush_domains, struct intel_ring_buffer *ring) { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_file_private *i915_file_priv = NULL; @@ -1612,28 +1619,13 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv, if (request == NULL) return 0; - /* Grab the seqno we're going to make this request be, and bump the - * next (skipping 0 so it can be the reserved no-seqno value). - */ - seqno = dev_priv->mm.next_gem_seqno; - dev_priv->mm.next_gem_seqno++; - if (dev_priv->mm.next_gem_seqno == 0) - dev_priv->mm.next_gem_seqno++; - - BEGIN_LP_RING(4); - OUT_RING(MI_STORE_DWORD_INDEX); - OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - OUT_RING(seqno); - - OUT_RING(MI_USER_INTERRUPT); - ADVANCE_LP_RING(); - - DRM_DEBUG_DRIVER("%d\n", seqno); + seqno = ring->add_request(dev, ring, file_priv, flush_domains); request->seqno = seqno; + request->ring = ring; request->emitted_jiffies = jiffies; - was_empty = list_empty(&dev_priv->mm.request_list); - list_add_tail(&request->list, &dev_priv->mm.request_list); + was_empty = list_empty(&ring->request_list); + list_add_tail(&request->list, &ring->request_list); if (i915_file_priv) { list_add_tail(&request->client_list, &i915_file_priv->mm.request_list); @@ -1645,7 +1637,7 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv, * domain we're flushing with our flush. */ if (flush_domains != 0) - i915_gem_process_flushing_list(dev, flush_domains, seqno); + i915_gem_process_flushing_list(dev, flush_domains, seqno, ring); if (!dev_priv->mm.suspended) { mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); @@ -1662,18 +1654,16 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv, * before signalling the CPU */ static uint32_t -i915_retire_commands(struct drm_device *dev) +i915_retire_commands(struct drm_device *dev, struct intel_ring_buffer *ring) { - uint32_t cmd = MI_FLUSH | MI_NO_WRITE_FLUSH; uint32_t flush_domains = 0; /* The sampler always gets flushed on i965 (sigh) */ if (IS_I965G(dev)) flush_domains |= I915_GEM_DOMAIN_SAMPLER; - BEGIN_LP_RING(2); - OUT_RING(cmd); - OUT_RING(0); /* noop */ - ADVANCE_LP_RING(); + + ring->flush(dev, ring, + I915_GEM_DOMAIN_COMMAND, flush_domains); return flush_domains; } @@ -1693,11 +1683,11 @@ i915_gem_retire_request(struct drm_device *dev, * by the ringbuffer to the flushing/inactive lists as appropriate. */ spin_lock(&dev_priv->mm.active_list_lock); - while (!list_empty(&dev_priv->mm.active_list)) { + while (!list_empty(&request->ring->active_list)) { struct drm_gem_object *obj; struct drm_i915_gem_object *obj_priv; - obj_priv = list_first_entry(&dev_priv->mm.active_list, + obj_priv = list_first_entry(&request->ring->active_list, struct drm_i915_gem_object, list); obj = obj_priv->obj; @@ -1706,6 +1696,7 @@ i915_gem_retire_request(struct drm_device *dev, * list, then the oldest in the list must still be newer than * this seqno. */ + if (obj_priv->last_rendering_seqno != request->seqno) goto out; @@ -1744,38 +1735,36 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2) } uint32_t -i915_get_gem_seqno(struct drm_device *dev) +i915_get_gem_seqno(struct drm_device *dev, struct intel_ring_buffer *ring) { - drm_i915_private_t *dev_priv = dev->dev_private; - - return READ_HWSP(dev_priv, I915_GEM_HWS_INDEX); + return ring->get_gem_seqno(dev, ring); } /** * This function clears the request list as sequence numbers are passed. */ void -i915_gem_retire_requests(struct drm_device *dev) +i915_gem_retire_requests(struct drm_device *dev, struct intel_ring_buffer *ring) { drm_i915_private_t *dev_priv = dev->dev_private; uint32_t seqno; - if (!dev_priv->render_ring.status_page.page_addr || list_empty(&dev_priv->mm.request_list)) + if (!ring->status_page.page_addr || list_empty(&ring->request_list)) return; - seqno = i915_get_gem_seqno(dev); + seqno = ring->get_gem_seqno(dev, ring); - while (!list_empty(&dev_priv->mm.request_list)) { + while (!list_empty(&ring->request_list)) { struct drm_i915_gem_request *request; uint32_t retiring_seqno; - request = list_first_entry(&dev_priv->mm.request_list, + request = list_first_entry(&ring->request_list, struct drm_i915_gem_request, list); retiring_seqno = request->seqno; if (i915_seqno_passed(seqno, retiring_seqno) || - atomic_read(&dev_priv->mm.wedged)) { + atomic_read(&dev_priv->mm.wedged)) { i915_gem_retire_request(dev, request); list_del(&request->list); @@ -1787,7 +1776,7 @@ i915_gem_retire_requests(struct drm_device *dev) if (unlikely (dev_priv->trace_irq_seqno && i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) { - i915_user_irq_put(dev); + ring->user_irq_put(dev, ring); dev_priv->trace_irq_seqno = 0; } } @@ -1803,15 +1792,21 @@ i915_gem_retire_work_handler(struct work_struct *work) dev = dev_priv->dev; mutex_lock(&dev->struct_mutex); - i915_gem_retire_requests(dev); - if (!dev_priv->mm.suspended && - !list_empty(&dev_priv->mm.request_list)) + i915_gem_retire_requests(dev, &dev_priv->render_ring); + + if (HAS_BSD(dev)) + i915_gem_retire_requests(dev, &dev_priv->bsd_ring); + + if (!dev_priv->mm.suspended && + (!list_empty(&dev_priv->render_ring.request_list) || + (HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.request_list)))) queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); mutex_unlock(&dev->struct_mutex); } int -i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible) +i915_do_wait_request(struct drm_device *dev, uint32_t seqno, + int interruptible, struct intel_ring_buffer *ring) { drm_i915_private_t *dev_priv = dev->dev_private; u32 ier; @@ -1822,7 +1817,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible) if (atomic_read(&dev_priv->mm.wedged)) return -EIO; - if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) { + if (!i915_seqno_passed(ring->get_gem_seqno(dev, ring), seqno)) { if (HAS_PCH_SPLIT(dev)) ier = I915_READ(DEIER) | I915_READ(GTIER); else @@ -1836,19 +1831,19 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible) trace_i915_gem_request_wait_begin(dev, seqno); - dev_priv->mm.waiting_gem_seqno = seqno; - i915_user_irq_get(dev); + ring->waiting_gem_seqno = seqno; + ring->user_irq_get(dev, ring); if (interruptible) - ret = wait_event_interruptible(dev_priv->irq_queue, - i915_seqno_passed(i915_get_gem_seqno(dev), seqno) || + ret = wait_event_interruptible(ring->irq_queue, + i915_seqno_passed(ring->get_gem_seqno(dev, ring), seqno) || atomic_read(&dev_priv->mm.wedged)); else - wait_event(dev_priv->irq_queue, - i915_seqno_passed(i915_get_gem_seqno(dev), seqno) || + wait_event(ring->irq_queue, + i915_seqno_passed(ring->get_gem_seqno(dev, ring), seqno) || atomic_read(&dev_priv->mm.wedged)); - i915_user_irq_put(dev); - dev_priv->mm.waiting_gem_seqno = 0; + ring->user_irq_put(dev, ring); + ring->waiting_gem_seqno = 0; trace_i915_gem_request_wait_end(dev, seqno); } @@ -1857,7 +1852,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible) if (ret && ret != -ERESTARTSYS) DRM_ERROR("%s returns %d (awaiting %d at %d)\n", - __func__, ret, seqno, i915_get_gem_seqno(dev)); + __func__, ret, seqno, ring->get_gem_seqno(dev, ring)); /* Directly dispatch request retiring. While we have the work queue * to handle this, the waiter on a request often wants an associated @@ -1865,7 +1860,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible) * a separate wait queue to handle that. */ if (ret == 0) - i915_gem_retire_requests(dev); + i915_gem_retire_requests(dev, ring); return ret; } @@ -1875,9 +1870,9 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible) * request and object lists appropriately for that event. */ static int -i915_wait_request(struct drm_device *dev, uint32_t seqno) +i915_wait_request(struct drm_device *dev, uint32_t seqno, struct intel_ring_buffer *ring) { - return i915_do_wait_request(dev, seqno, 1); + return i915_do_wait_request(dev, seqno, 1, ring); } static void @@ -1889,14 +1884,27 @@ i915_gem_flush(struct drm_device *dev, if (flush_domains & I915_GEM_DOMAIN_CPU) drm_agp_chipset_flush(dev); - dev_priv->render_ring.flush(dev, &dev_priv->render_ring, + dev_priv->render_ring.flush(dev, &dev_priv->render_ring, invalidate_domains, flush_domains); if (HAS_BSD(dev)) - dev_priv->bsd_ring.flush(dev, &dev_priv->bsd_ring, - invalidate_domains, - flush_domains); + dev_priv->bsd_ring.flush(dev, &dev_priv->bsd_ring, + invalidate_domains, + flush_domains); +} + +static void +i915_gem_flush_ring(struct drm_device *dev, + uint32_t invalidate_domains, + uint32_t flush_domains, + struct intel_ring_buffer *ring) +{ + if (flush_domains & I915_GEM_DOMAIN_CPU) + drm_agp_chipset_flush(dev); + ring->flush(dev, ring, + invalidate_domains, + flush_domains); } /** @@ -1923,7 +1931,7 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj) DRM_INFO("%s: object %p wait for seqno %08x\n", __func__, obj, obj_priv->last_rendering_seqno); #endif - ret = i915_wait_request(dev, obj_priv->last_rendering_seqno); + ret = i915_wait_request(dev, obj_priv->last_rendering_seqno, obj_priv->ring); if (ret != 0) return ret; } @@ -2039,11 +2047,13 @@ i915_gpu_idle(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; bool lists_empty; - uint32_t seqno; + uint32_t seqno1, seqno2; + int ret; spin_lock(&dev_priv->mm.active_list_lock); lists_empty = list_empty(&dev_priv->mm.flushing_list) && - list_empty(&dev_priv->mm.active_list); + list_empty(&dev_priv->render_ring.active_list) && + (!HAS_BSD(dev) || list_empty(&dev_priv->bsd_ring.active_list)); spin_unlock(&dev_priv->mm.active_list_lock); if (lists_empty) @@ -2051,11 +2061,23 @@ i915_gpu_idle(struct drm_device *dev) /* Flush everything onto the inactive list. */ i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); - seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS); - if (seqno == 0) + seqno1 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS, &dev_priv->render_ring); + if (seqno1 == 0) return -ENOMEM; + ret = i915_wait_request(dev, seqno1, &dev_priv->render_ring); - return i915_wait_request(dev, seqno); + if (HAS_BSD(dev)) { + seqno2 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS, &dev_priv->bsd_ring); + if (seqno2 == 0) + return -ENOMEM; + + ret = i915_wait_request(dev, seqno2, &dev_priv->bsd_ring); + if (ret) + return ret; + } + + + return ret; } static int @@ -2068,7 +2090,8 @@ i915_gem_evict_everything(struct drm_device *dev) spin_lock(&dev_priv->mm.active_list_lock); lists_empty = (list_empty(&dev_priv->mm.inactive_list) && list_empty(&dev_priv->mm.flushing_list) && - list_empty(&dev_priv->mm.active_list)); + list_empty(&dev_priv->render_ring.active_list) && + (!HAS_BSD(dev) || list_empty(&dev_priv->bsd_ring.active_list))); spin_unlock(&dev_priv->mm.active_list_lock); if (lists_empty) @@ -2088,7 +2111,8 @@ i915_gem_evict_everything(struct drm_device *dev) spin_lock(&dev_priv->mm.active_list_lock); lists_empty = (list_empty(&dev_priv->mm.inactive_list) && list_empty(&dev_priv->mm.flushing_list) && - list_empty(&dev_priv->mm.active_list)); + list_empty(&dev_priv->render_ring.active_list) && + (!HAS_BSD(dev) || list_empty(&dev_priv->bsd_ring.active_list))); spin_unlock(&dev_priv->mm.active_list_lock); BUG_ON(!lists_empty); @@ -2103,7 +2127,10 @@ i915_gem_evict_something(struct drm_device *dev, int min_size) int ret; for (;;) { - i915_gem_retire_requests(dev); + i915_gem_retire_requests(dev, &dev_priv->render_ring); + + if (HAS_BSD(dev)) + i915_gem_retire_requests(dev, &dev_priv->bsd_ring); /* If there's an inactive buffer available now, grab it * and be done. @@ -2127,14 +2154,28 @@ i915_gem_evict_something(struct drm_device *dev, int min_size) * things, wait for the next to finish and hopefully leave us * a buffer to evict. */ - if (!list_empty(&dev_priv->mm.request_list)) { + if (!list_empty(&dev_priv->render_ring.request_list)) { + struct drm_i915_gem_request *request; + + request = list_first_entry(&dev_priv->render_ring.request_list, + struct drm_i915_gem_request, + list); + + ret = i915_wait_request(dev, request->seqno, request->ring); + if (ret) + return ret; + + continue; + } + + if (HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.request_list)) { struct drm_i915_gem_request *request; - request = list_first_entry(&dev_priv->mm.request_list, + request = list_first_entry(&dev_priv->bsd_ring.request_list, struct drm_i915_gem_request, list); - ret = i915_wait_request(dev, request->seqno); + ret = i915_wait_request(dev, request->seqno, request->ring); if (ret) return ret; @@ -2161,10 +2202,12 @@ i915_gem_evict_something(struct drm_device *dev, int min_size) if (obj != NULL) { uint32_t seqno; - i915_gem_flush(dev, + i915_gem_flush_ring(dev, + obj->write_domain, obj->write_domain, - obj->write_domain); - seqno = i915_add_request(dev, NULL, obj->write_domain); + obj_priv->ring); + seqno = i915_add_request(dev, NULL, obj->write_domain, + obj_priv->ring); if (seqno == 0) return -ENOMEM; continue; @@ -2690,6 +2733,7 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj) { struct drm_device *dev = obj->dev; uint32_t old_write_domain; + struct drm_i915_gem_object *obj_priv = obj->driver_private; if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) return; @@ -2697,7 +2741,7 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj) /* Queue the GPU write cache flushing we need. */ old_write_domain = obj->write_domain; i915_gem_flush(dev, 0, obj->write_domain); - (void) i915_add_request(dev, NULL, obj->write_domain); + (void) i915_add_request(dev, NULL, obj->write_domain, obj_priv->ring); BUG_ON(obj->write_domain); trace_i915_gem_object_change_domain(obj, @@ -2837,7 +2881,7 @@ i915_gem_object_set_to_display_plane(struct drm_gem_object *obj) DRM_INFO("%s: object %p wait for seqno %08x\n", __func__, obj, obj_priv->last_rendering_seqno); #endif - ret = i915_do_wait_request(dev, obj_priv->last_rendering_seqno, 0); + ret = i915_do_wait_request(dev, obj_priv->last_rendering_seqno, 0, obj_priv->ring); if (ret != 0) return ret; } @@ -3428,61 +3472,6 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, return 0; } -/** Dispatch a batchbuffer to the ring - */ -static int -i915_dispatch_gem_execbuffer(struct drm_device *dev, - struct drm_i915_gem_execbuffer2 *exec, - struct drm_clip_rect *cliprects, - uint64_t exec_offset) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - int nbox = exec->num_cliprects; - int i = 0, count; - uint32_t exec_start, exec_len; - - exec_start = (uint32_t) exec_offset + exec->batch_start_offset; - exec_len = (uint32_t) exec->batch_len; - - trace_i915_gem_request_submit(dev, dev_priv->mm.next_gem_seqno + 1); - - count = nbox ? nbox : 1; - - for (i = 0; i < count; i++) { - if (i < nbox) { - int ret = i915_emit_box(dev, cliprects, i, - exec->DR1, exec->DR4); - if (ret) - return ret; - } - - if (IS_I830(dev) || IS_845G(dev)) { - BEGIN_LP_RING(4); - OUT_RING(MI_BATCH_BUFFER); - OUT_RING(exec_start | MI_BATCH_NON_SECURE); - OUT_RING(exec_start + exec_len - 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); - OUT_RING(exec_start); - } else { - OUT_RING(MI_BATCH_BUFFER_START | - (2 << 6)); - OUT_RING(exec_start | MI_BATCH_NON_SECURE); - } - ADVANCE_LP_RING(); - } - } - - /* XXX breadcrumb */ - return 0; -} - /* Throttle our rendering by waiting until the ring has completed our requests * emitted over 20 msec ago. * @@ -3511,7 +3500,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv) if (time_after_eq(request->emitted_jiffies, recent_enough)) break; - ret = i915_wait_request(dev, request->seqno); + ret = i915_wait_request(dev, request->seqno, request->ring); if (ret != 0) break; } @@ -3668,6 +3657,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, uint32_t seqno, flush_domains, reloc_index; int pin_tries, flips; + struct intel_ring_buffer *ring = NULL; + u32 ring_flag; + #if WATCH_EXEC DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", (int) args->buffers_ptr, args->buffer_count, args->batch_len); @@ -3725,6 +3717,15 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, goto pre_mutex_err; } + if (args->flags & ON_BSD_RING) { + BUG_ON(!HAS_BSD(dev)); + ring = &dev_priv->bsd_ring; + ring_flag = ON_BSD_RING; + } else { + ring = &dev_priv->render_ring; + ring_flag = ON_RENDER_RING; + } + /* Look up object handles */ flips = 0; for (i = 0; i < args->buffer_count; i++) { @@ -3858,9 +3859,14 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, i915_gem_flush(dev, dev->invalidate_domains, dev->flush_domains); - if (dev->flush_domains & I915_GEM_GPU_DOMAINS) + if (dev->flush_domains & I915_GEM_GPU_DOMAINS) { (void)i915_add_request(dev, file_priv, - dev->flush_domains); + dev->flush_domains, &dev_priv->render_ring); + + if (HAS_BSD(dev)) + (void)i915_add_request(dev, file_priv, + dev->flush_domains, &dev_priv->bsd_ring); + } } for (i = 0; i < args->buffer_count; i++) { @@ -3897,7 +3903,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, #endif /* Exec the batchbuffer */ - ret = i915_dispatch_gem_execbuffer(dev, args, cliprects, exec_offset); + ret = ring->dispatch_gem_execbuffer(dev, ring, args, cliprects, exec_offset); if (ret) { DRM_ERROR("dispatch failed %d\n", ret); goto err; @@ -3907,7 +3913,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, * Ensure that the commands in the batch buffer are * finished before the interrupt fires */ - flush_domains = i915_retire_commands(dev); + flush_domains = i915_retire_commands(dev, ring); i915_verify_inactive(dev, __FILE__, __LINE__); @@ -3918,12 +3924,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, * *some* interrupts representing completion of buffers that we can * wait on when trying to clear up gtt space). */ - seqno = i915_add_request(dev, file_priv, flush_domains); + seqno = i915_add_request(dev, file_priv, flush_domains, ring); BUG_ON(seqno == 0); for (i = 0; i < args->buffer_count; i++) { struct drm_gem_object *obj = object_list[i]; + obj_priv = obj->driver_private; - i915_gem_object_move_to_active(obj, seqno); + i915_gem_object_move_to_active(obj, seqno, ring); #if WATCH_LRU DRM_INFO("%s: move to exec list %p\n", __func__, obj); #endif @@ -4035,7 +4042,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, exec2.DR4 = args->DR4; exec2.num_cliprects = args->num_cliprects; exec2.cliprects_ptr = args->cliprects_ptr; - exec2.flags = 0; + exec2.flags = ON_RENDER_RING; ret = i915_gem_do_execbuffer(dev, data, file_priv, &exec2, exec2_list); if (!ret) { @@ -4274,6 +4281,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, struct drm_i915_gem_busy *args = data; struct drm_gem_object *obj; struct drm_i915_gem_object *obj_priv; + drm_i915_private_t *dev_priv = dev->dev_private; obj = drm_gem_object_lookup(dev, file_priv, args->handle); if (obj == NULL) { @@ -4288,7 +4296,10 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, * actually unmasked, and our working set ends up being larger than * required. */ - i915_gem_retire_requests(dev); + i915_gem_retire_requests(dev, &dev_priv->render_ring); + + if (HAS_BSD(dev)) + i915_gem_retire_requests(dev, &dev_priv->bsd_ring); obj_priv = obj->driver_private; /* Don't count being on the flushing list against the object being @@ -4449,7 +4460,9 @@ i915_gem_idle(struct drm_device *dev) mutex_lock(&dev->struct_mutex); - if (dev_priv->mm.suspended || dev_priv->render_ring.gem_object == NULL) { + if (dev_priv->mm.suspended || + (dev_priv->render_ring.gem_object == NULL) || + (HAS_BSD(dev) && dev_priv->bsd_ring.gem_object == NULL)) { mutex_unlock(&dev->struct_mutex); return 0; } @@ -4476,7 +4489,7 @@ i915_gem_idle(struct drm_device *dev) dev_priv->mm.suspended = 1; del_timer(&dev_priv->hangcheck_timer); - i915_kernel_lost_context(dev); +// i915_kernel_lost_context(dev); i915_gem_cleanup_ringbuffer(dev); mutex_unlock(&dev->struct_mutex); @@ -4499,10 +4512,11 @@ i915_gem_init_ringbuffer(struct drm_device *dev) memset(dev_priv->render_ring.status_page.page_addr, 0, PAGE_SIZE); } ret = intel_init_ring_buffer(dev, &dev_priv->render_ring); - if (!ret && HAS_BSD(dev)) { + if (HAS_BSD(dev)) { dev_priv->bsd_ring = bsd_ring; ret = intel_init_ring_buffer(dev, &dev_priv->bsd_ring); } + return ret; } @@ -4510,10 +4524,10 @@ void i915_gem_cleanup_ringbuffer(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; + intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); - if (HAS_BSD(dev)) + if (HAS_BSD(dev)) intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); - } int @@ -4541,12 +4555,14 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, } spin_lock(&dev_priv->mm.active_list_lock); - BUG_ON(!list_empty(&dev_priv->mm.active_list)); + BUG_ON(!list_empty(&dev_priv->render_ring.active_list)); + BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.active_list)); spin_unlock(&dev_priv->mm.active_list_lock); BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); - BUG_ON(!list_empty(&dev_priv->mm.request_list)); + BUG_ON(!list_empty(&dev_priv->render_ring.request_list)); + BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.request_list)); mutex_unlock(&dev->struct_mutex); drm_irq_install(dev); @@ -4585,15 +4601,20 @@ i915_gem_load(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; spin_lock_init(&dev_priv->mm.active_list_lock); - INIT_LIST_HEAD(&dev_priv->mm.active_list); INIT_LIST_HEAD(&dev_priv->mm.flushing_list); INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list); INIT_LIST_HEAD(&dev_priv->mm.inactive_list); - INIT_LIST_HEAD(&dev_priv->mm.request_list); INIT_LIST_HEAD(&dev_priv->mm.fence_list); + INIT_LIST_HEAD(&dev_priv->render_ring.active_list); + INIT_LIST_HEAD(&dev_priv->render_ring.request_list); + + if (HAS_BSD(dev)) { + INIT_LIST_HEAD(&dev_priv->bsd_ring.active_list); + INIT_LIST_HEAD(&dev_priv->bsd_ring.request_list); + } + INIT_DELAYED_WORK(&dev_priv->mm.retire_work, i915_gem_retire_work_handler); - dev_priv->mm.next_gem_seqno = 1; spin_lock(&shrink_list_lock); list_add(&dev_priv->mm.shrink_list, &shrink_list); @@ -4856,8 +4877,10 @@ i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask) continue; spin_unlock(&shrink_list_lock); + i915_gem_retire_requests(dev, &dev_priv->render_ring); - i915_gem_retire_requests(dev); + if (HAS_BSD(dev)) + i915_gem_retire_requests(dev, &dev_priv->bsd_ring); list_for_each_entry_safe(obj_priv, next_obj, &dev_priv->mm.inactive_list, diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index e602614..db04075 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c @@ -106,12 +106,21 @@ i915_dump_lru(struct drm_device *dev, const char *where) DRM_INFO("active list %s {\n", where); spin_lock(&dev_priv->mm.active_list_lock); - list_for_each_entry(obj_priv, &dev_priv->mm.active_list, + list_for_each_entry(obj_priv, &dev_priv->render_ring.active_list, list) { DRM_INFO(" %p: %08x\n", obj_priv, obj_priv->last_rendering_seqno); } + + if (HAS_BSD(dev)) { + list_for_each_entry(obj_priv, &dev_priv->bsd_ring.active_list, + list) + { + DRM_INFO(" %p: %08x\n", obj_priv, + obj_priv->last_rendering_seqno); + } + } spin_unlock(&dev_priv->mm.active_list_lock); DRM_INFO("}\n"); DRM_INFO("flushing list %s {\n", where); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ada9a80..5d09e16 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -52,7 +52,7 @@ I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) /** Interrupts that we mask and unmask at runtime. */ -#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT) +#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT | I915_BSD_USER_INTERRUPT) #define I915_PIPE_VBLANK_STATUS (PIPE_START_VBLANK_INTERRUPT_STATUS |\ PIPE_VBLANK_INTERRUPT_STATUS) @@ -326,7 +326,7 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) int ret = IRQ_NONE; u32 de_iir, gt_iir, de_ier, pch_iir; struct drm_i915_master_private *master_priv; - + struct intel_ring_buffer *render_ring = &dev_priv->render_ring; /* disable master interrupt before clearing iir */ de_ier = I915_READ(DEIER); I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); @@ -349,14 +349,17 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) } if (gt_iir & GT_USER_INTERRUPT) { - u32 seqno = i915_get_gem_seqno(dev); - dev_priv->mm.irq_gem_seqno = seqno; + u32 seqno = render_ring->get_gem_seqno(dev, render_ring); + render_ring->irq_gem_seqno = seqno; trace_i915_gem_request_complete(dev, seqno); - DRM_WAKEUP(&dev_priv->irq_queue); + DRM_WAKEUP(&dev_priv->render_ring.irq_queue); dev_priv->hangcheck_count = 0; mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); } + if (gt_iir & GT_BSD_USER_INTERRUPT) + DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); + if (de_iir & DE_GSE) ironlake_opregion_gse_intr(dev); @@ -547,7 +550,6 @@ i915_ringbuffer_last_batch(struct drm_device *dev) return bbaddr; } - /** * i915_capture_error_state - capture an error record for later analysis * @dev: drm device @@ -579,7 +581,7 @@ static void i915_capture_error_state(struct drm_device *dev) return; } - error->seqno = i915_get_gem_seqno(dev); + error->seqno = i915_get_gem_seqno(dev, &dev_priv->render_ring); error->eir = I915_READ(EIR); error->pgtbl_er = I915_READ(PGTBL_ER); error->pipeastat = I915_READ(PIPEASTAT); @@ -607,7 +609,7 @@ static void i915_capture_error_state(struct drm_device *dev) batchbuffer[0] = NULL; batchbuffer[1] = NULL; count = 0; - list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) { + list_for_each_entry(obj_priv, &dev_priv->render_ring.active_list, list) { struct drm_gem_object *obj = obj_priv->obj; if (batchbuffer[0] == NULL && @@ -643,7 +645,7 @@ static void i915_capture_error_state(struct drm_device *dev) if (error->active_bo) { int i = 0; - list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) { + list_for_each_entry(obj_priv, &dev_priv->render_ring.active_list, list) { struct drm_gem_object *obj = obj_priv->obj; error->active_bo[i].size = obj->size; @@ -821,7 +823,7 @@ static void i915_handle_error(struct drm_device *dev, bool wedged) /* * Wakeup waiting processes so they don't hang */ - DRM_WAKEUP(&dev_priv->irq_queue); + DRM_WAKEUP(&dev_priv->render_ring.irq_queue); } queue_work(dev_priv->wq, &dev_priv->error_work); @@ -840,6 +842,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) unsigned long irqflags; int irq_received; int ret = IRQ_NONE; + struct intel_ring_buffer *render_ring = &dev_priv->render_ring; atomic_inc(&dev_priv->irq_received); @@ -864,7 +867,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) * It doesn't set the bit in iir again, but it still produces * interrupts (for non-MSI). */ - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + spin_lock_irqsave(&render_ring->user_irq_lock, irqflags); pipea_stats = I915_READ(PIPEASTAT); pipeb_stats = I915_READ(PIPEBSTAT); @@ -887,7 +890,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) I915_WRITE(PIPEBSTAT, pipeb_stats); irq_received = 1; } - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + spin_unlock_irqrestore(&render_ring->user_irq_lock, irqflags); if (!irq_received) break; @@ -920,14 +923,17 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) } if (iir & I915_USER_INTERRUPT) { - u32 seqno = i915_get_gem_seqno(dev); - dev_priv->mm.irq_gem_seqno = seqno; + u32 seqno = render_ring->get_gem_seqno(dev, render_ring); + render_ring->irq_gem_seqno = seqno; trace_i915_gem_request_complete(dev, seqno); - DRM_WAKEUP(&dev_priv->irq_queue); + DRM_WAKEUP(&dev_priv->render_ring.irq_queue); dev_priv->hangcheck_count = 0; mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); } + if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT)) + DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); + if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) intel_prepare_page_flip(dev, 0); @@ -975,8 +981,7 @@ static int i915_emit_irq(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; - - i915_kernel_lost_context(dev); + RING_LOCALS; DRM_DEBUG_DRIVER("\n"); @@ -996,43 +1001,13 @@ static int i915_emit_irq(struct drm_device * dev) return dev_priv->counter; } -void i915_user_irq_get(struct drm_device *dev) -{ - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); - if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) { - if (HAS_PCH_SPLIT(dev)) - ironlake_enable_graphics_irq(dev_priv, GT_USER_INTERRUPT); - else - i915_enable_irq(dev_priv, I915_USER_INTERRUPT); - } - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); -} - -void i915_user_irq_put(struct drm_device *dev) -{ - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); - BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0); - if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { - if (HAS_PCH_SPLIT(dev)) - ironlake_disable_graphics_irq(dev_priv, GT_USER_INTERRUPT); - else - i915_disable_irq(dev_priv, I915_USER_INTERRUPT); - } - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); -} - void i915_trace_irq_get(struct drm_device *dev, u32 seqno) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct intel_ring_buffer *render_ring = &dev_priv->render_ring; if (dev_priv->trace_irq_seqno == 0) - i915_user_irq_get(dev); + render_ring->user_irq_get(dev, render_ring); dev_priv->trace_irq_seqno = seqno; } @@ -1042,6 +1017,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; int ret = 0; + struct intel_ring_buffer *render_ring = &dev_priv->render_ring; DRM_DEBUG_DRIVER("irq_nr=%d breadcrumb=%d\n", irq_nr, READ_BREADCRUMB(dev_priv)); @@ -1055,10 +1031,10 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) if (master_priv->sarea_priv) master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; - i915_user_irq_get(dev); - DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, + render_ring->user_irq_get(dev, render_ring); + DRM_WAIT_ON(ret, dev_priv->render_ring.irq_queue, 3 * DRM_HZ, READ_BREADCRUMB(dev_priv) >= irq_nr); - i915_user_irq_put(dev); + render_ring->user_irq_put(dev, render_ring); if (ret == -EBUSY) { DRM_ERROR("EBUSY -- rec: %d emitted: %d\n", @@ -1126,7 +1102,7 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) if (!(pipeconf & PIPEACONF_ENABLE)) return -EINVAL; - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + spin_lock_irqsave(&dev_priv->render_ring.user_irq_lock, irqflags); if (HAS_PCH_SPLIT(dev)) ironlake_enable_display_irq(dev_priv, (pipe == 0) ? DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); @@ -1136,7 +1112,7 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) else i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + spin_unlock_irqrestore(&dev_priv->render_ring.user_irq_lock, irqflags); return 0; } @@ -1148,7 +1124,7 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + spin_lock_irqsave(&dev_priv->render_ring.user_irq_lock, irqflags); if (HAS_PCH_SPLIT(dev)) ironlake_disable_display_irq(dev_priv, (pipe == 0) ? DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); @@ -1156,7 +1132,7 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE | PIPE_START_VBLANK_INTERRUPT_ENABLE); - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + spin_unlock_irqrestore(&dev_priv->render_ring.user_irq_lock, irqflags); } void i915_enable_interrupt (struct drm_device *dev) @@ -1225,7 +1201,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, struct drm_i915_gem_request *i915_get_tail_request(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; - return list_entry(dev_priv->mm.request_list.prev, struct drm_i915_gem_request, list); + return list_entry(dev_priv->render_ring.request_list.prev, struct drm_i915_gem_request, list); } /** @@ -1250,12 +1226,16 @@ void i915_hangcheck_elapsed(unsigned long data) acthd = I915_READ(ACTHD_I965); /* If all work is done then ACTHD clearly hasn't advanced. */ - if (list_empty(&dev_priv->mm.request_list) || - i915_seqno_passed(i915_get_gem_seqno(dev), i915_get_tail_request(dev)->seqno)) { + if (list_empty(&dev_priv->render_ring.request_list) || + i915_seqno_passed(i915_get_gem_seqno(dev, &dev_priv->render_ring), i915_get_tail_request(dev)->seqno)) { dev_priv->hangcheck_count = 0; return; } + /* XXX fix later + * check other ring buffer + */ + if (dev_priv->last_acthd == acthd && dev_priv->hangcheck_count > 0) { DRM_ERROR("Hangcheck timer elapsed... GPU hung\n"); i915_handle_error(dev, true); @@ -1304,7 +1284,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev) /* enable kind of interrupts always enabled */ u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE; - u32 render_mask = GT_USER_INTERRUPT; + u32 render_mask = GT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT; u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG | SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; @@ -1381,7 +1361,10 @@ int i915_driver_irq_postinstall(struct drm_device *dev) u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; u32 error_mask; - DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); + DRM_INIT_WAITQUEUE(&dev_priv->render_ring.irq_queue); + + if (HAS_BSD(dev)) + DRM_INIT_WAITQUEUE(&dev_priv->bsd_ring.irq_queue); dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c index 7cc8410..393e468 100644 --- a/drivers/gpu/drm/i915/i915_opregion.c +++ b/drivers/gpu/drm/i915/i915_opregion.c @@ -328,9 +328,9 @@ void opregion_enable_asle(struct drm_device *dev) if (IS_MOBILE(dev)) { unsigned long irqflags; - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + spin_lock_irqsave(&dev_priv->render_ring.user_irq_lock, irqflags); intel_enable_asle(dev); - spin_unlock_irqrestore(&dev_priv->user_irq_lock, + spin_unlock_irqrestore(&dev_priv->render_ring.user_irq_lock, irqflags); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 6923846..67917ba 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -323,8 +323,8 @@ #define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT (1<<4) #define I915_DEBUG_INTERRUPT (1<<2) #define I915_USER_INTERRUPT (1<<1) +#define I915_BSD_USER_INTERRUPT (1<<25) #define I915_ASLE_INTERRUPT (1<<0) -#define I915_BSD_USER_INTERRUPT (1<<25) #define EIR 0x020b0 #define EMR 0x020b4 #define ESR 0x020b8 @@ -359,17 +359,17 @@ #define BB_ADDR 0x02140 /* 8 bytes */ #define GFX_FLSH_CNTL 0x02170 /* 915+ only */ + /* * BSD (bit stream decoder instruction and interrupt control register defines * (G4X and Ironlake only) */ - -#define BSD_RING_TAIL 0x04030 -#define BSD_RING_HEAD 0x04034 -#define BSD_RING_START 0x04038 -#define BSD_RING_CTL 0x0403c -#define BSD_RING_ACTHD 0x04074 -#define BSD_HWS_PGA 0x04080 +#define BSD_RING_TAIL 0x04030 +#define BSD_RING_HEAD 0x04034 +#define BSD_RING_START 0x04038 +#define BSD_RING_CTL 0x0403c +#define BSD_RING_ACTHD 0x04074 +#define BSD_HWS_PGA 0x04080 /* @@ -2293,8 +2293,7 @@ #define GT_SYNC_STATUS (1 << 2) #define GT_USER_INTERRUPT (1 << 0) -#define GT_BSD_USER_INTERRUPT (1 << 5) - +#define GT_BSD_USER_INTERRUPT (1 << 5) #define GTISR 0x44010 #define GTIMR 0x44014 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4a5b233..0e2c5da 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4219,6 +4219,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, unsigned long flags; int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC; int ret, pipesrc; + RING_LOCALS; work = kzalloc(sizeof *work, GFP_KERNEL); if (work == NULL) diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 77136e1..933e101 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -212,6 +212,9 @@ static int intel_overlay_on(struct intel_overlay *overlay) { struct drm_device *dev = overlay->dev; int ret; + drm_i915_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + BUG_ON(overlay->active); overlay->active = 1; @@ -224,11 +227,11 @@ static int intel_overlay_on(struct intel_overlay *overlay) OUT_RING(MI_NOOP); ADVANCE_LP_RING(); - overlay->last_flip_req = i915_add_request(dev, NULL, 0); + overlay->last_flip_req = i915_add_request(dev, NULL, 0, &dev_priv->render_ring); if (overlay->last_flip_req == 0) return -ENOMEM; - ret = i915_do_wait_request(dev, overlay->last_flip_req, 1); + ret = i915_do_wait_request(dev, overlay->last_flip_req, 1, &dev_priv->render_ring); if (ret != 0) return ret; @@ -245,6 +248,7 @@ static void intel_overlay_continue(struct intel_overlay *overlay, drm_i915_private_t *dev_priv = dev->dev_private; u32 flip_addr = overlay->flip_addr; u32 tmp; + RING_LOCALS; BUG_ON(!overlay->active); @@ -261,7 +265,7 @@ static void intel_overlay_continue(struct intel_overlay *overlay, OUT_RING(flip_addr); ADVANCE_LP_RING(); - overlay->last_flip_req = i915_add_request(dev, NULL, 0); + overlay->last_flip_req = i915_add_request(dev, NULL, 0, &dev_priv->render_ring); } static int intel_overlay_wait_flip(struct intel_overlay *overlay) @@ -270,9 +274,10 @@ static int intel_overlay_wait_flip(struct intel_overlay *overlay) drm_i915_private_t *dev_priv = dev->dev_private; int ret; u32 tmp; + RING_LOCALS; if (overlay->last_flip_req != 0) { - ret = i915_do_wait_request(dev, overlay->last_flip_req, 1); + ret = i915_do_wait_request(dev, overlay->last_flip_req, 1, &dev_priv->render_ring); if (ret == 0) { overlay->last_flip_req = 0; @@ -291,11 +296,11 @@ static int intel_overlay_wait_flip(struct intel_overlay *overlay) OUT_RING(MI_NOOP); ADVANCE_LP_RING(); - overlay->last_flip_req = i915_add_request(dev, NULL, 0); + overlay->last_flip_req = i915_add_request(dev, NULL, 0, &dev_priv->render_ring); if (overlay->last_flip_req == 0) return -ENOMEM; - ret = i915_do_wait_request(dev, overlay->last_flip_req, 1); + ret = i915_do_wait_request(dev, overlay->last_flip_req, 1, &dev_priv->render_ring); if (ret != 0) return ret; @@ -309,7 +314,9 @@ static int intel_overlay_off(struct intel_overlay *overlay) { u32 flip_addr = overlay->flip_addr; struct drm_device *dev = overlay->dev; + drm_i915_private_t *dev_priv = dev->dev_private; int ret; + RING_LOCALS; BUG_ON(!overlay->active); @@ -329,11 +336,11 @@ static int intel_overlay_off(struct intel_overlay *overlay) OUT_RING(MI_NOOP); ADVANCE_LP_RING(); - overlay->last_flip_req = i915_add_request(dev, NULL, 0); + overlay->last_flip_req = i915_add_request(dev, NULL, 0, &dev_priv->render_ring); if (overlay->last_flip_req == 0) return -ENOMEM; - ret = i915_do_wait_request(dev, overlay->last_flip_req, 1); + ret = i915_do_wait_request(dev, overlay->last_flip_req, 1, &dev_priv->render_ring); if (ret != 0) return ret; @@ -347,11 +354,11 @@ static int intel_overlay_off(struct intel_overlay *overlay) OUT_RING(MI_NOOP); ADVANCE_LP_RING(); - overlay->last_flip_req = i915_add_request(dev, NULL, 0); + overlay->last_flip_req = i915_add_request(dev, NULL, 0, &dev_priv->render_ring); if (overlay->last_flip_req == 0) return -ENOMEM; - ret = i915_do_wait_request(dev, overlay->last_flip_req, 1); + ret = i915_do_wait_request(dev, overlay->last_flip_req, 1, &dev_priv->render_ring); if (ret != 0) return ret; @@ -384,19 +391,21 @@ int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, { struct drm_device *dev = overlay->dev; struct drm_gem_object *obj; + drm_i915_private_t *dev_priv = dev->dev_private; u32 flip_addr; int ret; + RING_LOCALS; if (overlay->hw_wedged == HW_WEDGED) return -EIO; if (overlay->last_flip_req == 0) { - overlay->last_flip_req = i915_add_request(dev, NULL, 0); + overlay->last_flip_req = i915_add_request(dev, NULL, 0, &dev_priv->render_ring); if (overlay->last_flip_req == 0) return -ENOMEM; } - ret = i915_do_wait_request(dev, overlay->last_flip_req, interruptible); + ret = i915_do_wait_request(dev, overlay->last_flip_req, interruptible, &dev_priv->render_ring); if (ret != 0) return ret; @@ -420,12 +429,12 @@ int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, OUT_RING(MI_NOOP); ADVANCE_LP_RING(); - overlay->last_flip_req = i915_add_request(dev, NULL, 0); + overlay->last_flip_req = i915_add_request(dev, NULL, 0, &dev_priv->render_ring); if (overlay->last_flip_req == 0) return -ENOMEM; ret = i915_do_wait_request(dev, overlay->last_flip_req, - interruptible); + interruptible, &dev_priv->render_ring); if (ret != 0) return ret; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 8470999..aadb5b5 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -261,11 +261,63 @@ static void render_setup_status_page(struct drm_device *dev, (void)I915_READ(HWS_PGA); } -void + +static int +render_ring_dispatch_gem_execbuffer(struct drm_device *dev, + struct intel_ring_buffer *ring, + struct drm_i915_gem_execbuffer2 *exec, + struct drm_clip_rect *cliprects, + uint64_t exec_offset) +{ + int nbox = exec->num_cliprects; + int i = 0, count; + uint32_t exec_start, exec_len; + exec_start = (uint32_t) exec_offset + exec->batch_start_offset; + exec_len = (uint32_t) exec->batch_len; + + // trace_i915_gem_request_submit(dev, dev_priv->mm.next_gem_seqno + 1); + + count = nbox ? nbox : 1; + + for (i = 0; i < count; i++) { + if (i < nbox) { + int ret = i915_emit_box(dev, cliprects, i, + exec->DR1, exec->DR4); + if (ret) + return ret; + } + + if (IS_I830(dev) || IS_845G(dev)) { + intel_begin_ring_buffer (dev, ring, 4); + intel_fill_ring_buffer(dev, ring, MI_BATCH_BUFFER); + intel_fill_ring_buffer(dev, ring, exec_start | MI_BATCH_NON_SECURE); + intel_fill_ring_buffer(dev, ring, exec_start + exec_len - 4); + intel_fill_ring_buffer(dev, ring, 0); + } else { + intel_begin_ring_buffer (dev, ring, 4); + if (IS_I965G(dev)) { + intel_fill_ring_buffer(dev, ring, MI_BATCH_BUFFER_START | + (2 << 6) | MI_BATCH_NON_SECURE_I965); + intel_fill_ring_buffer(dev, ring, exec_start); + } else { + intel_fill_ring_buffer(dev, ring, MI_BATCH_BUFFER_START | + (2 << 6)); + intel_fill_ring_buffer(dev, ring, exec_start | MI_BATCH_NON_SECURE); + } + } + intel_advance_ring_buffer (dev, ring); + } + + /* XXX breadcrumb */ + return 0; +} + + +void bsd_ring_flush(struct drm_device *dev, struct intel_ring_buffer *ring, - u32 invalidate_domains, - u32 flush_domains) + u32 invalidate_domains, + u32 flush_domains) { intel_begin_ring_buffer (dev, ring, 8); intel_fill_ring_buffer (dev, ring, MI_FLUSH); @@ -298,7 +350,7 @@ static inline void bsd_ring_advance_ring(struct drm_device *dev, struct intel_ring_buffer *ring) { drm_i915_private_t *dev_priv = dev->dev_private; - I915_WRITE(BSD_RING_TAIL, ring->tail); + I915_WRITE(BSD_RING_TAIL, ring->tail); } static int init_bsd_ring(struct drm_device *dev, @@ -339,7 +391,7 @@ static int init_bsd_ring(struct drm_device *dev, I915_READ(BSD_RING_START)); } - I915_WRITE(BSD_RING_CTL, + I915_WRITE(BSD_RING_CTL, ((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES) | RING_NO_REPORT | RING_VALID); @@ -347,7 +399,7 @@ static int init_bsd_ring(struct drm_device *dev, return 0; } -static u32 +static u32 bsd_ring_add_request(struct drm_device *dev, struct intel_ring_buffer *ring, struct drm_file *file_priv, @@ -368,7 +420,7 @@ bsd_ring_add_request(struct drm_device *dev, } static void bsd_setup_status_page(struct drm_device *dev, - struct intel_ring_buffer *ring) + struct intel_ring_buffer *ring) { drm_i915_private_t *dev_priv = dev->dev_private; I915_WRITE(BSD_HWS_PGA, ring->status_page.gfx_addr); @@ -411,6 +463,42 @@ bsd_ring_put_user_irq(struct drm_device *dev, spin_unlock_irqrestore(&ring->user_irq_lock, irqflags); } +static int init_status_page(struct drm_device *dev, struct intel_ring_buffer *ring) +{ + struct drm_i915_gem_object *obj_priv; + struct drm_gem_object *obj; + int ret; + drm_i915_private_t *dev_priv = dev->dev_private; + + obj = drm_gem_object_alloc(dev, PAGE_SIZE*10); + if (obj == NULL) + return -ENOMEM; + + obj_priv = obj->driver_private; + obj_priv->agp_type = AGP_USER_CACHED_MEMORY; + + ret = i915_gem_object_pin(obj, PAGE_SIZE); + if (ret != 0) { + drm_gem_object_unreference(obj); + return ret; + } + + ring->status_page.gfx_addr = obj_priv->gtt_offset; + + ring->status_page.page_addr = kmap(obj_priv->pages[0]); + if (ring->status_page.page_addr == NULL) { + memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); + i915_gem_object_unpin(obj); + drm_gem_object_unreference(obj); + return -EINVAL; + } + ring->status_page.obj = obj; + memset(ring->status_page.page_addr, 0, PAGE_SIZE); + ring->setup_status_page(dev, ring); + DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", ring->name, ring->status_page.gfx_addr); + return 0; +} + static u32 bsd_ring_get_gem_seqno(struct drm_device *dev, struct intel_ring_buffer *ring) @@ -418,7 +506,7 @@ bsd_ring_get_gem_seqno(struct drm_device *dev, return intel_read_status_page(ring, I915_GEM_HWS_INDEX); } -static int +static int bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev, struct intel_ring_buffer *ring, struct drm_i915_gem_execbuffer2 *exec, @@ -435,57 +523,6 @@ bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev, return 0; } - -static int -render_ring_dispatch_gem_execbuffer(struct drm_device *dev, - struct intel_ring_buffer *ring, - struct drm_i915_gem_execbuffer2 *exec, - struct drm_clip_rect *cliprects, - uint64_t exec_offset) -{ - int nbox = exec->num_cliprects; - int i = 0, count; - uint32_t exec_start, exec_len; - exec_start = (uint32_t) exec_offset + exec->batch_start_offset; - exec_len = (uint32_t) exec->batch_len; - - // trace_i915_gem_request_submit(dev, dev_priv->mm.next_gem_seqno + 1); - - count = nbox ? nbox : 1; - - for (i = 0; i < count; i++) { - if (i < nbox) { - int ret = i915_emit_box(dev, cliprects, i, - exec->DR1, exec->DR4); - if (ret) - return ret; - } - - if (IS_I830(dev) || IS_845G(dev)) { - intel_begin_ring_buffer (dev, ring, 4); - intel_fill_ring_buffer(dev, ring, MI_BATCH_BUFFER); - intel_fill_ring_buffer(dev, ring, exec_start | MI_BATCH_NON_SECURE); - intel_fill_ring_buffer(dev, ring, exec_start + exec_len - 4); - intel_fill_ring_buffer(dev, ring, 0); - } else { - intel_begin_ring_buffer (dev, ring, 4); - if (IS_I965G(dev)) { - intel_fill_ring_buffer(dev, ring, MI_BATCH_BUFFER_START | - (2 << 6) | MI_BATCH_NON_SECURE_I965); - intel_fill_ring_buffer(dev, ring, exec_start); - } else { - intel_fill_ring_buffer(dev, ring, MI_BATCH_BUFFER_START | - (2 << 6)); - intel_fill_ring_buffer(dev, ring, exec_start | MI_BATCH_NON_SECURE); - } - } - intel_advance_ring_buffer (dev, ring); - } - - /* XXX breadcrumb */ - return 0; -} - static void cleanup_status_page(struct drm_device *dev, struct intel_ring_buffer *ring) { drm_i915_private_t *dev_priv = dev->dev_private; @@ -505,43 +542,6 @@ static void cleanup_status_page(struct drm_device *dev, struct intel_ring_buffer memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); } -static int init_status_page(struct drm_device *dev, struct intel_ring_buffer *ring) -{ - struct drm_i915_gem_object *obj_priv; - struct drm_gem_object *obj; - int ret; - drm_i915_private_t *dev_priv = dev->dev_private; - - obj = drm_gem_object_alloc(dev, PAGE_SIZE*10); - if (obj == NULL) - return -ENOMEM; - - obj_priv = obj->driver_private; - obj_priv->agp_type = AGP_USER_CACHED_MEMORY; - - ret = i915_gem_object_pin(obj, PAGE_SIZE); - if (ret != 0) { - drm_gem_object_unreference(obj); - return ret; - } - - ring->status_page.gfx_addr = obj_priv->gtt_offset; - - ring->status_page.page_addr = kmap(obj_priv->pages[0]); - if (ring->status_page.page_addr == NULL) { - memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); - i915_gem_object_unpin(obj); - drm_gem_object_unreference(obj); - return -EINVAL; - } - ring->status_page.obj = obj; - memset(ring->status_page.page_addr, 0, PAGE_SIZE); - ring->setup_status_page(dev, ring); - DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", ring->name, ring->status_page.gfx_addr); - return 0; -} - - int intel_init_ring_buffer(struct drm_device *dev, struct intel_ring_buffer *ring) { @@ -719,7 +719,6 @@ u32 intel_ring_get_seqno(struct drm_device *dev, return seqno; } -/* ring buffer for render engine */ struct intel_ring_buffer render_ring = { .name = "render ring", .ring_flag = ON_RENDER_RING, @@ -754,33 +753,32 @@ struct intel_ring_buffer render_ring = { /* ring buffer for bit-stream decoder */ struct intel_ring_buffer bsd_ring = { - .name = "bsd ring", - .ring_flag = ON_BSD_RING, - .size = 32 * PAGE_SIZE, - .alignment = PAGE_SIZE, - .virtual_start = NULL, - .dev = NULL, - .gem_object = NULL, - .head = 0, - .tail = 0, - .space = 0, - .next_seqno = 1, - .user_irq_refcount = 0, - .irq_gem_seqno = 0, - .waiting_gem_seqno = 0, - .setup_status_page = bsd_setup_status_page, - .init = init_bsd_ring, - .get_head = bsd_ring_get_head, - .get_tail = bsd_ring_get_tail, - .get_active_head = bsd_ring_get_active_head, - .advance_ring = bsd_ring_advance_ring, - .flush = bsd_ring_flush, - .add_request = bsd_ring_add_request, - .get_gem_seqno = bsd_ring_get_gem_seqno, - .user_irq_get = bsd_ring_get_user_irq, - .user_irq_put = bsd_ring_put_user_irq, + .name = "bsd ring", + .ring_flag = ON_BSD_RING, + .size = 32 * PAGE_SIZE, + .alignment = PAGE_SIZE, + .virtual_start = NULL, + .dev = NULL, + .gem_object = NULL, + .head = 0, + .tail = 0, + .space = 0, + .next_seqno = 1, + .user_irq_refcount = 0, + .irq_gem_seqno = 0, + .waiting_gem_seqno = 0, + .setup_status_page = bsd_setup_status_page, + .init = init_bsd_ring, + .get_head = bsd_ring_get_head, + .get_tail = bsd_ring_get_tail, + .get_active_head = bsd_ring_get_active_head, + .advance_ring = bsd_ring_advance_ring, + .flush = bsd_ring_flush, + .add_request = bsd_ring_add_request, + .get_gem_seqno = bsd_ring_get_gem_seqno, + .user_irq_get = bsd_ring_get_user_irq, + .user_irq_put = bsd_ring_put_user_irq, .dispatch_gem_execbuffer = bsd_ring_dispatch_gem_execbuffer, - .status_page = {NULL, 0, NULL}, - .map = {0,} + .status_page = {NULL, 0, NULL}, + .map = {0,} }; - diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 552ec11..d7dd7fd 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1373,10 +1373,10 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output) tv_dac = I915_READ(TV_DAC); /* Disable TV interrupts around load detect or we'll recurse */ - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + spin_lock_irqsave(&dev_priv->render_ring.user_irq_lock, irqflags); i915_disable_pipestat(dev_priv, 0, PIPE_HOTPLUG_INTERRUPT_ENABLE | PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + spin_unlock_irqrestore(&dev_priv->render_ring.user_irq_lock, irqflags); /* * Detect TV by polling) @@ -1427,10 +1427,10 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output) } /* Restore interrupt config */ - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + spin_lock_irqsave(&dev_priv->render_ring.user_irq_lock, irqflags); i915_enable_pipestat(dev_priv, 0, PIPE_HOTPLUG_INTERRUPT_ENABLE | PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + spin_unlock_irqrestore(&dev_priv->render_ring.user_irq_lock, irqflags); return type; }