Skip to content

Commit

Permalink
drm/i915: Implement GPU semaphores for inter-ring synchronisation on SNB
Browse files Browse the repository at this point in the history
The bulk of the change is to convert the growing list of rings into an
array so that the relationship between the rings and the semaphore sync
registers can be easily computed.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
  • Loading branch information
Chris Wilson committed Dec 5, 2010
1 parent 340479a commit 1ec14ad
Show file tree
Hide file tree
Showing 14 changed files with 648 additions and 439 deletions.
75 changes: 30 additions & 45 deletions drivers/gpu/drm/i915/i915_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,32 +339,32 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
return ret;

count = 0;
if (!list_empty(&dev_priv->render_ring.request_list)) {
if (!list_empty(&dev_priv->ring[RCS].request_list)) {
seq_printf(m, "Render requests:\n");
list_for_each_entry(gem_request,
&dev_priv->render_ring.request_list,
&dev_priv->ring[RCS].request_list,
list) {
seq_printf(m, " %d @ %d\n",
gem_request->seqno,
(int) (jiffies - gem_request->emitted_jiffies));
}
count++;
}
if (!list_empty(&dev_priv->bsd_ring.request_list)) {
if (!list_empty(&dev_priv->ring[VCS].request_list)) {
seq_printf(m, "BSD requests:\n");
list_for_each_entry(gem_request,
&dev_priv->bsd_ring.request_list,
&dev_priv->ring[VCS].request_list,
list) {
seq_printf(m, " %d @ %d\n",
gem_request->seqno,
(int) (jiffies - gem_request->emitted_jiffies));
}
count++;
}
if (!list_empty(&dev_priv->blt_ring.request_list)) {
if (!list_empty(&dev_priv->ring[BCS].request_list)) {
seq_printf(m, "BLT requests:\n");
list_for_each_entry(gem_request,
&dev_priv->blt_ring.request_list,
&dev_priv->ring[BCS].request_list,
list) {
seq_printf(m, " %d @ %d\n",
gem_request->seqno,
Expand Down Expand Up @@ -398,15 +398,14 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
int ret;
int ret, i;

ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
return ret;

i915_ring_seqno_info(m, &dev_priv->render_ring);
i915_ring_seqno_info(m, &dev_priv->bsd_ring);
i915_ring_seqno_info(m, &dev_priv->blt_ring);
for (i = 0; i < I915_NUM_RINGS; i++)
i915_ring_seqno_info(m, &dev_priv->ring[i]);

mutex_unlock(&dev->struct_mutex);

Expand All @@ -419,7 +418,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
int ret;
int ret, i;

ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
Expand Down Expand Up @@ -458,9 +457,8 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
}
seq_printf(m, "Interrupts received: %d\n",
atomic_read(&dev_priv->irq_received));
i915_ring_seqno_info(m, &dev_priv->render_ring);
i915_ring_seqno_info(m, &dev_priv->bsd_ring);
i915_ring_seqno_info(m, &dev_priv->blt_ring);
for (i = 0; i < I915_NUM_RINGS; i++)
i915_ring_seqno_info(m, &dev_priv->ring[i]);
mutex_unlock(&dev->struct_mutex);

return 0;
Expand Down Expand Up @@ -503,13 +501,7 @@ static int i915_hws_info(struct seq_file *m, void *data)
volatile u32 *hws;
int i;

switch ((uintptr_t)node->info_ent->data) {
case RING_RENDER: ring = &dev_priv->render_ring; break;
case RING_BSD: ring = &dev_priv->bsd_ring; break;
case RING_BLT: ring = &dev_priv->blt_ring; break;
default: return -EINVAL;
}

ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
hws = (volatile u32 *)ring->status_page.page_addr;
if (hws == NULL)
return 0;
Expand Down Expand Up @@ -569,17 +561,11 @@ static int i915_ringbuffer_data(struct seq_file *m, void *data)
struct intel_ring_buffer *ring;
int ret;

switch ((uintptr_t)node->info_ent->data) {
case RING_RENDER: ring = &dev_priv->render_ring; break;
case RING_BSD: ring = &dev_priv->bsd_ring; break;
case RING_BLT: ring = &dev_priv->blt_ring; break;
default: return -EINVAL;
}

ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
return ret;

ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
if (!ring->obj) {
seq_printf(m, "No ringbuffer setup\n");
} else {
Expand All @@ -603,21 +589,20 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring;

switch ((uintptr_t)node->info_ent->data) {
case RING_RENDER: ring = &dev_priv->render_ring; break;
case RING_BSD: ring = &dev_priv->bsd_ring; break;
case RING_BLT: ring = &dev_priv->blt_ring; break;
default: return -EINVAL;
}

ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
if (ring->size == 0)
return 0;
return 0;

seq_printf(m, "Ring %s:\n", ring->name);
seq_printf(m, " Head : %08x\n", I915_READ_HEAD(ring) & HEAD_ADDR);
seq_printf(m, " Tail : %08x\n", I915_READ_TAIL(ring) & TAIL_ADDR);
seq_printf(m, " Size : %08x\n", ring->size);
seq_printf(m, " Active : %08x\n", intel_ring_get_active_head(ring));
seq_printf(m, " NOPID : %08x\n", I915_READ_NOPID(ring));
if (IS_GEN6(dev)) {
seq_printf(m, " Sync 0 : %08x\n", I915_READ_SYNC_0(ring));
seq_printf(m, " Sync 1 : %08x\n", I915_READ_SYNC_1(ring));
}
seq_printf(m, " Control : %08x\n", I915_READ_CTL(ring));
seq_printf(m, " Start : %08x\n", I915_READ_START(ring));

Expand Down Expand Up @@ -1177,15 +1162,15 @@ static struct drm_info_list i915_debugfs_list[] = {
{"i915_gem_seqno", i915_gem_seqno_info, 0},
{"i915_gem_fence_regs", i915_gem_fence_regs_info, 0},
{"i915_gem_interrupt", i915_interrupt_info, 0},
{"i915_gem_hws", i915_hws_info, 0, (void *)RING_RENDER},
{"i915_gem_hws_blt", i915_hws_info, 0, (void *)RING_BLT},
{"i915_gem_hws_bsd", i915_hws_info, 0, (void *)RING_BSD},
{"i915_ringbuffer_data", i915_ringbuffer_data, 0, (void *)RING_RENDER},
{"i915_ringbuffer_info", i915_ringbuffer_info, 0, (void *)RING_RENDER},
{"i915_bsd_ringbuffer_data", i915_ringbuffer_data, 0, (void *)RING_BSD},
{"i915_bsd_ringbuffer_info", i915_ringbuffer_info, 0, (void *)RING_BSD},
{"i915_blt_ringbuffer_data", i915_ringbuffer_data, 0, (void *)RING_BLT},
{"i915_blt_ringbuffer_info", i915_ringbuffer_info, 0, (void *)RING_BLT},
{"i915_gem_hws", i915_hws_info, 0, (void *)RCS},
{"i915_gem_hws_blt", i915_hws_info, 0, (void *)BCS},
{"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS},
{"i915_ringbuffer_data", i915_ringbuffer_data, 0, (void *)RCS},
{"i915_ringbuffer_info", i915_ringbuffer_info, 0, (void *)RCS},
{"i915_bsd_ringbuffer_data", i915_ringbuffer_data, 0, (void *)VCS},
{"i915_bsd_ringbuffer_info", i915_ringbuffer_info, 0, (void *)VCS},
{"i915_blt_ringbuffer_data", i915_ringbuffer_data, 0, (void *)BCS},
{"i915_blt_ringbuffer_info", i915_ringbuffer_info, 0, (void *)BCS},
{"i915_batchbuffers", i915_batchbuffer_info, 0},
{"i915_error_state", i915_error_state, 0},
{"i915_rstdby_delays", i915_rstdby_delays, 0},
Expand Down
60 changes: 31 additions & 29 deletions drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
static int i915_init_phys_hws(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring = LP_RING(dev_priv);

/* Program Hardware Status Page */
dev_priv->status_page_dmah =
drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE);
Expand All @@ -57,11 +59,10 @@ static int i915_init_phys_hws(struct drm_device *dev)
DRM_ERROR("Can not allocate hardware status page\n");
return -ENOMEM;
}
dev_priv->render_ring.status_page.page_addr
= dev_priv->status_page_dmah->vaddr;
ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;

memset(dev_priv->render_ring.status_page.page_addr, 0, PAGE_SIZE);
memset(ring->status_page.page_addr, 0, PAGE_SIZE);

if (INTEL_INFO(dev)->gen >= 4)
dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) &
Expand All @@ -79,13 +80,15 @@ static int i915_init_phys_hws(struct drm_device *dev)
static void i915_free_hws(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring = LP_RING(dev_priv);

if (dev_priv->status_page_dmah) {
drm_pci_free(dev, dev_priv->status_page_dmah);
dev_priv->status_page_dmah = NULL;
}

if (dev_priv->render_ring.status_page.gfx_addr) {
dev_priv->render_ring.status_page.gfx_addr = 0;
if (ring->status_page.gfx_addr) {
ring->status_page.gfx_addr = 0;
drm_core_ioremapfree(&dev_priv->hws_map, dev);
}

Expand All @@ -97,7 +100,7 @@ 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;
struct intel_ring_buffer *ring = LP_RING(dev_priv);

/*
* We should never lose context on the ring with modesetting
Expand All @@ -123,6 +126,8 @@ void i915_kernel_lost_context(struct drm_device * dev)
static int i915_dma_cleanup(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
int i;

/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed, it's too late.
Expand All @@ -131,9 +136,8 @@ static int i915_dma_cleanup(struct drm_device * dev)
drm_irq_uninstall(dev);

mutex_lock(&dev->struct_mutex);
intel_cleanup_ring_buffer(&dev_priv->render_ring);
intel_cleanup_ring_buffer(&dev_priv->bsd_ring);
intel_cleanup_ring_buffer(&dev_priv->blt_ring);
for (i = 0; i < I915_NUM_RINGS; i++)
intel_cleanup_ring_buffer(&dev_priv->ring[i]);
mutex_unlock(&dev->struct_mutex);

/* Clear the HWS virtual address at teardown */
Expand All @@ -147,6 +151,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
struct intel_ring_buffer *ring = LP_RING(dev_priv);

master_priv->sarea = drm_getsarea(dev);
if (master_priv->sarea) {
Expand All @@ -157,32 +162,32 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
}

if (init->ring_size != 0) {
if (dev_priv->render_ring.obj != NULL) {
if (ring->obj != NULL) {
i915_dma_cleanup(dev);
DRM_ERROR("Client tried to initialize ringbuffer in "
"GEM mode\n");
return -EINVAL;
}

dev_priv->render_ring.size = init->ring_size;
ring->size = init->ring_size;

dev_priv->render_ring.map.offset = init->ring_start;
dev_priv->render_ring.map.size = init->ring_size;
dev_priv->render_ring.map.type = 0;
dev_priv->render_ring.map.flags = 0;
dev_priv->render_ring.map.mtrr = 0;
ring->map.offset = init->ring_start;
ring->map.size = init->ring_size;
ring->map.type = 0;
ring->map.flags = 0;
ring->map.mtrr = 0;

drm_core_ioremap_wc(&dev_priv->render_ring.map, dev);
drm_core_ioremap_wc(&ring->map, dev);

if (dev_priv->render_ring.map.handle == NULL) {
if (ring->map.handle == NULL) {
i915_dma_cleanup(dev);
DRM_ERROR("can not ioremap virtual address for"
" ring buffer\n");
return -ENOMEM;
}
}

dev_priv->render_ring.virtual_start = dev_priv->render_ring.map.handle;
ring->virtual_start = ring->map.handle;

dev_priv->cpp = init->cpp;
dev_priv->back_offset = init->back_offset;
Expand All @@ -201,12 +206,10 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
static int i915_dma_resume(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
struct intel_ring_buffer *ring = LP_RING(dev_priv);

struct intel_ring_buffer *ring;
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");
Expand Down Expand Up @@ -326,7 +329,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, ret;

if ((dwords+1) * sizeof(int) >= dev_priv->render_ring.size - 8)
if ((dwords+1) * sizeof(int) >= LP_RING(dev_priv)->size - 8)
return -EINVAL;

for (i = 0; i < dwords;) {
Expand Down Expand Up @@ -565,13 +568,12 @@ static int i915_dispatch_flip(struct drm_device * dev)
return 0;
}

static int i915_quiescent(struct drm_device * dev)
static int i915_quiescent(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring = LP_RING(dev->dev_private);

i915_kernel_lost_context(dev);
return intel_wait_ring_buffer(&dev_priv->render_ring,
dev_priv->render_ring.size - 8);
return intel_wait_ring_buffer(ring, ring->size - 8);
}

static int i915_flush_ioctl(struct drm_device *dev, void *data,
Expand Down Expand Up @@ -828,7 +830,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
{
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_hws_addr_t *hws = data;
struct intel_ring_buffer *ring = &dev_priv->render_ring;
struct intel_ring_buffer *ring = LP_RING(dev_priv);

if (!I915_NEED_GFX_HWS(dev))
return -EINVAL;
Expand Down Expand Up @@ -1978,7 +1980,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->irq_lock);
spin_lock_init(&dev_priv->error_lock);
dev_priv->trace_irq_seqno = 0;

Expand Down
6 changes: 3 additions & 3 deletions drivers/gpu/drm/i915/i915_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,11 +487,11 @@ int i915_reset(struct drm_device *dev, u8 flags)
!dev_priv->mm.suspended) {
dev_priv->mm.suspended = 0;

dev_priv->render_ring.init(&dev_priv->render_ring);
dev_priv->ring[RCS].init(&dev_priv->ring[RCS]);
if (HAS_BSD(dev))
dev_priv->bsd_ring.init(&dev_priv->bsd_ring);
dev_priv->ring[VCS].init(&dev_priv->ring[VCS]);
if (HAS_BLT(dev))
dev_priv->blt_ring.init(&dev_priv->blt_ring);
dev_priv->ring[BCS].init(&dev_priv->ring[BCS]);

mutex_unlock(&dev->struct_mutex);
drm_irq_uninstall(dev);
Expand Down
Loading

0 comments on commit 1ec14ad

Please sign in to comment.