Skip to content

Commit

Permalink
drm/nouveau: Rework tile region handling.
Browse files Browse the repository at this point in the history
The point is to share more code between the PFB/PGRAPH tile region
hooks, and give the hardware specific functions a chance to allocate
per-region resources.

Signed-off-by: Francisco Jerez <currojerez@riseup.net>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Francisco Jerez authored and Ben Skeggs committed Dec 3, 2010
1 parent e419cf0 commit a5cf68b
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 160 deletions.
11 changes: 4 additions & 7 deletions drivers/gpu/drm/nouveau/nouveau_bo.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
if (unlikely(nvbo->gem))
DRM_ERROR("bo %p still attached to GEM object\n", bo);

if (nvbo->tile)
nv10_mem_expire_tiling(dev, nvbo->tile, NULL);

nv10_mem_put_tile_region(dev, nvbo->tile, NULL);
kfree(nvbo);
}

Expand Down Expand Up @@ -792,7 +790,8 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem,

} else if (dev_priv->card_type >= NV_10) {
*new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size,
nvbo->tile_mode);
nvbo->tile_mode,
nvbo->tile_flags);
}

return 0;
Expand All @@ -808,9 +807,7 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo,

if (dev_priv->card_type >= NV_10 &&
dev_priv->card_type < NV_50) {
if (*old_tile)
nv10_mem_expire_tiling(dev, *old_tile, bo->sync_obj);

nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj);
*old_tile = new_tile;
}
}
Expand Down
59 changes: 34 additions & 25 deletions drivers/gpu/drm/nouveau/nouveau_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,11 @@ struct nouveau_grctx;
#define NV50_VM_VRAM_NR (NV50_VM_MAX_VRAM / NV50_VM_BLOCK)

struct nouveau_tile_reg {
struct nouveau_fence *fence;
uint32_t addr;
uint32_t size;
bool used;
uint32_t addr;
uint32_t limit;
uint32_t pitch;
struct nouveau_fence *fence;
};

struct nouveau_bo {
Expand Down Expand Up @@ -309,8 +310,11 @@ struct nouveau_fb_engine {
int (*init)(struct drm_device *dev);
void (*takedown)(struct drm_device *dev);

void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr,
uint32_t size, uint32_t pitch);
void (*init_tile_region)(struct drm_device *dev, int i,
uint32_t addr, uint32_t size,
uint32_t pitch, uint32_t flags);
void (*set_tile_region)(struct drm_device *dev, int i);
void (*free_tile_region)(struct drm_device *dev, int i);
};

struct nouveau_fifo_engine {
Expand Down Expand Up @@ -356,8 +360,7 @@ struct nouveau_pgraph_engine {
int (*unload_context)(struct drm_device *);
void (*tlb_flush)(struct drm_device *dev);

void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr,
uint32_t size, uint32_t pitch);
void (*set_tile_region)(struct drm_device *dev, int i);
};

struct nouveau_display_engine {
Expand Down Expand Up @@ -668,7 +671,10 @@ struct drm_nouveau_private {
} gart_info;

/* nv10-nv40 tiling regions */
struct nouveau_tile_reg tile[NOUVEAU_MAX_TILE_NR];
struct {
struct nouveau_tile_reg reg[NOUVEAU_MAX_TILE_NR];
spinlock_t lock;
} tile;

/* VRAM/fb configuration */
uint64_t vram_size;
Expand Down Expand Up @@ -798,13 +804,12 @@ extern void nouveau_mem_gart_fini(struct drm_device *);
extern int nouveau_mem_init_agp(struct drm_device *);
extern int nouveau_mem_reset_agp(struct drm_device *);
extern void nouveau_mem_close(struct drm_device *);
extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev,
uint32_t addr,
uint32_t size,
uint32_t pitch);
extern void nv10_mem_expire_tiling(struct drm_device *dev,
struct nouveau_tile_reg *tile,
struct nouveau_fence *fence);
extern struct nouveau_tile_reg *nv10_mem_set_tiling(
struct drm_device *dev, uint32_t addr, uint32_t size,
uint32_t pitch, uint32_t flags);
extern void nv10_mem_put_tile_region(struct drm_device *dev,
struct nouveau_tile_reg *tile,
struct nouveau_fence *fence);
extern int nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt,
uint32_t size, uint32_t flags,
uint64_t phys);
Expand Down Expand Up @@ -1011,18 +1016,25 @@ extern void nv04_fb_takedown(struct drm_device *);
/* nv10_fb.c */
extern int nv10_fb_init(struct drm_device *);
extern void nv10_fb_takedown(struct drm_device *);
extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t,
uint32_t, uint32_t);
extern void nv10_fb_init_tile_region(struct drm_device *dev, int i,
uint32_t addr, uint32_t size,
uint32_t pitch, uint32_t flags);
extern void nv10_fb_set_tile_region(struct drm_device *dev, int i);
extern void nv10_fb_free_tile_region(struct drm_device *dev, int i);

/* nv30_fb.c */
extern int nv30_fb_init(struct drm_device *);
extern void nv30_fb_takedown(struct drm_device *);
extern void nv30_fb_init_tile_region(struct drm_device *dev, int i,
uint32_t addr, uint32_t size,
uint32_t pitch, uint32_t flags);
extern void nv30_fb_free_tile_region(struct drm_device *dev, int i);

/* nv40_fb.c */
extern int nv40_fb_init(struct drm_device *);
extern void nv40_fb_takedown(struct drm_device *);
extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t,
uint32_t, uint32_t);
extern void nv40_fb_set_tile_region(struct drm_device *dev, int i);

/* nv50_fb.c */
extern int nv50_fb_init(struct drm_device *);
extern void nv50_fb_takedown(struct drm_device *);
Expand Down Expand Up @@ -1102,8 +1114,7 @@ extern void nv10_graph_destroy_context(struct nouveau_channel *);
extern int nv10_graph_load_context(struct nouveau_channel *);
extern int nv10_graph_unload_context(struct drm_device *);
extern void nv10_graph_context_switch(struct drm_device *);
extern void nv10_graph_set_region_tiling(struct drm_device *, int, uint32_t,
uint32_t, uint32_t);
extern void nv10_graph_set_tile_region(struct drm_device *dev, int i);

/* nv20_graph.c */
extern int nv20_graph_create_context(struct nouveau_channel *);
Expand All @@ -1113,8 +1124,7 @@ extern int nv20_graph_unload_context(struct drm_device *);
extern int nv20_graph_init(struct drm_device *);
extern void nv20_graph_takedown(struct drm_device *);
extern int nv30_graph_init(struct drm_device *);
extern void nv20_graph_set_region_tiling(struct drm_device *, int, uint32_t,
uint32_t, uint32_t);
extern void nv20_graph_set_tile_region(struct drm_device *dev, int i);

/* nv40_graph.c */
extern int nv40_graph_init(struct drm_device *);
Expand All @@ -1125,8 +1135,7 @@ extern void nv40_graph_destroy_context(struct nouveau_channel *);
extern int nv40_graph_load_context(struct nouveau_channel *);
extern int nv40_graph_unload_context(struct drm_device *);
extern void nv40_grctx_init(struct nouveau_grctx *);
extern void nv40_graph_set_region_tiling(struct drm_device *, int, uint32_t,
uint32_t, uint32_t);
extern void nv40_graph_set_tile_region(struct drm_device *dev, int i);

/* nv50_graph.c */
extern int nv50_graph_init(struct drm_device *);
Expand Down
111 changes: 66 additions & 45 deletions drivers/gpu/drm/nouveau/nouveau_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,83 +42,104 @@
*/

static void
nv10_mem_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
uint32_t size, uint32_t pitch)
nv10_mem_update_tile_region(struct drm_device *dev,
struct nouveau_tile_reg *tile, uint32_t addr,
uint32_t size, uint32_t pitch, uint32_t flags)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
struct nouveau_tile_reg *tile = &dev_priv->tile[i];
int i = tile - dev_priv->tile.reg;
unsigned long save;

tile->addr = addr;
tile->size = size;
tile->used = !!pitch;
nouveau_fence_unref(&tile->fence);

if (tile->pitch)
pfb->free_tile_region(dev, i);

if (pitch)
pfb->init_tile_region(dev, i, addr, size, pitch, flags);

spin_lock_irqsave(&dev_priv->context_switch_lock, save);
pfifo->reassign(dev, false);
pfifo->cache_pull(dev, false);

nouveau_wait_for_idle(dev);

pgraph->set_region_tiling(dev, i, addr, size, pitch);
pfb->set_region_tiling(dev, i, addr, size, pitch);
pfb->set_tile_region(dev, i);
pgraph->set_tile_region(dev, i);

pfifo->cache_pull(dev, true);
pfifo->reassign(dev, true);
spin_unlock_irqrestore(&dev_priv->context_switch_lock, save);
}

struct nouveau_tile_reg *
nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size,
uint32_t pitch)
static struct nouveau_tile_reg *
nv10_mem_get_tile_region(struct drm_device *dev, int i)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
struct nouveau_tile_reg *found = NULL;
unsigned long i, flags;
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];

spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
spin_lock(&dev_priv->tile.lock);

for (i = 0; i < pfb->num_tiles; i++) {
struct nouveau_tile_reg *tile = &dev_priv->tile[i];

if (tile->used)
/* Tile region in use. */
continue;
if (!tile->used &&
(!tile->fence || nouveau_fence_signalled(tile->fence)))
tile->used = true;
else
tile = NULL;

if (tile->fence &&
!nouveau_fence_signalled(tile->fence))
/* Pending tile region. */
continue;
spin_unlock(&dev_priv->tile.lock);
return tile;
}

if (max(tile->addr, addr) <
min(tile->addr + tile->size, addr + size))
/* Kill an intersecting tile region. */
nv10_mem_set_region_tiling(dev, i, 0, 0, 0);
void
nv10_mem_put_tile_region(struct drm_device *dev, struct nouveau_tile_reg *tile,
struct nouveau_fence *fence)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;

if (pitch && !found) {
/* Free tile region. */
nv10_mem_set_region_tiling(dev, i, addr, size, pitch);
found = tile;
if (tile) {
spin_lock(&dev_priv->tile.lock);
if (fence) {
/* Mark it as pending. */
tile->fence = fence;
nouveau_fence_ref(fence);
}
}

spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);

return found;
tile->used = false;
spin_unlock(&dev_priv->tile.lock);
}
}

void
nv10_mem_expire_tiling(struct drm_device *dev, struct nouveau_tile_reg *tile,
struct nouveau_fence *fence)
struct nouveau_tile_reg *
nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size,
uint32_t pitch, uint32_t flags)
{
if (fence) {
/* Mark it as pending. */
tile->fence = fence;
nouveau_fence_ref(fence);
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
struct nouveau_tile_reg *tile, *found = NULL;
int i;

for (i = 0; i < pfb->num_tiles; i++) {
tile = nv10_mem_get_tile_region(dev, i);

if (pitch && !found) {
found = tile;
continue;

} else if (tile && tile->pitch) {
/* Kill an unused tile region. */
nv10_mem_update_tile_region(dev, tile, 0, 0, 0, 0);
}

nv10_mem_put_tile_region(dev, tile, NULL);
}

tile->used = false;
if (found)
nv10_mem_update_tile_region(dev, found, addr, size,
pitch, flags);
return found;
}

/*
Expand Down
Loading

0 comments on commit a5cf68b

Please sign in to comment.