Skip to content

Commit

Permalink
drm/nouveau: kick vram functions out into an "engine"
Browse files Browse the repository at this point in the history
NVC0 will be able to share some of nv50's paths this way.  This also makes
it the card-specific vram code responsible for deciding if a given set
of tile_flags is valid, rather than duplicating the allowed types in
nv50_vram.c and nouveau_gem.c

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Ben Skeggs committed Dec 8, 2010
1 parent 34cf01b commit 60d2a88
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 51 deletions.
12 changes: 12 additions & 0 deletions drivers/gpu/drm/nouveau/nouveau_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,15 @@ struct nouveau_crypt_engine {
void (*tlb_flush)(struct drm_device *dev);
};

struct nouveau_vram_engine {
int (*init)(struct drm_device *);
int (*get)(struct drm_device *, u64, u32 align, u32 size_nc,
u32 type, struct nouveau_vram **);
void (*put)(struct drm_device *, struct nouveau_vram **);

bool (*flags_valid)(struct drm_device *, u32 tile_flags);
};

struct nouveau_engine {
struct nouveau_instmem_engine instmem;
struct nouveau_mc_engine mc;
Expand All @@ -512,6 +521,7 @@ struct nouveau_engine {
struct nouveau_gpio_engine gpio;
struct nouveau_pm_engine pm;
struct nouveau_crypt_engine crypt;
struct nouveau_vram_engine vram;
};

struct nouveau_pll_vals {
Expand Down Expand Up @@ -821,6 +831,8 @@ 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 int nouveau_mem_detect(struct drm_device *);
extern bool nouveau_mem_flags_valid(struct drm_device *, u32 tile_flags);
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);
Expand Down
30 changes: 3 additions & 27 deletions drivers/gpu/drm/nouveau/nouveau_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,32 +103,6 @@ nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep)
return 0;
}

static bool
nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;

if (dev_priv->card_type >= NV_50) {
switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) {
case 0x0000:
case 0x1800:
case 0x2800:
case 0x4800:
case 0x7000:
case 0x7400:
case 0x7a00:
case 0xe000:
return true;
}
} else {
if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK))
return true;
}

NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags);
return false;
}

int
nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
struct drm_file *file_priv)
Expand All @@ -150,8 +124,10 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
if (!flags || req->info.domain & NOUVEAU_GEM_DOMAIN_CPU)
flags |= TTM_PL_FLAG_SYSTEM;

if (!nouveau_gem_tile_flags_valid(dev, req->info.tile_flags))
if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) {
NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags);
return -EINVAL;
}

if (req->channel_hint) {
chan = nouveau_channel_get(dev, file_priv, req->channel_hint);
Expand Down
47 changes: 26 additions & 21 deletions drivers/gpu/drm/nouveau/nouveau_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ nouveau_mem_detect_nforce(struct drm_device *dev)
return 0;
}

static int
int
nouveau_mem_detect(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
Expand All @@ -255,26 +255,25 @@ nouveau_mem_detect(struct drm_device *dev)
if (dev_priv->card_type < NV_50) {
dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA);
dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK;
} else
if (dev_priv->card_type < NV_C0) {
if (nv50_vram_init(dev))
return -ENOMEM;
} else {
dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20;
dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
}

NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
if (dev_priv->vram_sys_base) {
NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
dev_priv->vram_sys_base);
}

if (dev_priv->vram_size)
return 0;
return -ENOMEM;
}

bool
nouveau_mem_flags_valid(struct drm_device *dev, u32 tile_flags)
{
if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK))
return true;

return false;
}

#if __OS_HAS_AGP
static unsigned long
get_agp_mode(struct drm_device *dev, unsigned long mode)
Expand Down Expand Up @@ -432,11 +431,16 @@ nouveau_mem_vram_init(struct drm_device *dev)
else
dev_priv->ramin_rsvd_vram = (512 * 1024);

/* initialise gpu-specific vram backend */
ret = nouveau_mem_detect(dev);
ret = dev_priv->engine.vram.init(dev);
if (ret)
return ret;

NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
if (dev_priv->vram_sys_base) {
NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
dev_priv->vram_sys_base);
}

dev_priv->fb_available_size = dev_priv->vram_size;
dev_priv->fb_mappable_pages = dev_priv->fb_available_size;
if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1))
Expand Down Expand Up @@ -698,9 +702,10 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man,
struct ttm_mem_reg *mem)
{
struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
struct drm_device *dev = dev_priv->dev;

nv50_vram_del(dev, (struct nouveau_vram **)&mem->mm_node);
vram->put(dev, (struct nouveau_vram **)&mem->mm_node);
}

static int
Expand All @@ -710,30 +715,30 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
struct ttm_mem_reg *mem)
{
struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
struct drm_device *dev = dev_priv->dev;
struct nouveau_bo *nvbo = nouveau_bo(bo);
struct nouveau_vram *vram;
struct nouveau_vram *node;
u32 size_nc = 0;
int ret;

if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG)
size_nc = 1 << nvbo->vma.node->type;

ret = nv50_vram_new(dev, mem->num_pages << PAGE_SHIFT,
mem->page_alignment << PAGE_SHIFT, size_nc,
(nvbo->tile_flags >> 8) & 0x7f, &vram);
ret = vram->get(dev, mem->num_pages << PAGE_SHIFT,
mem->page_alignment << PAGE_SHIFT, size_nc,
(nvbo->tile_flags >> 8) & 0xff, &node);
if (ret)
return ret;

mem->mm_node = vram;
mem->start = vram->offset >> PAGE_SHIFT;
mem->mm_node = node;
mem->start = node->offset >> PAGE_SHIFT;
return 0;
}

void
nouveau_vram_manager_debug(struct ttm_mem_type_manager *man, const char *prefix)
{
struct ttm_bo_global *glob = man->bdev->glob;
struct nouveau_mm *mm = man->priv;
struct nouveau_mm_node *r;
u64 total = 0, ttotal[3] = {}, tused[3] = {}, tfree[3] = {};
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/nouveau_mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,6 @@ int nv50_vram_init(struct drm_device *);
int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc,
u32 memtype, struct nouveau_vram **);
void nv50_vram_del(struct drm_device *, struct nouveau_vram **);
bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags);

#endif
16 changes: 16 additions & 0 deletions drivers/gpu/drm/nouveau/nouveau_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.clock_set = nv04_pm_clock_set;
engine->crypt.init = nouveau_stub_init;
engine->crypt.takedown = nouveau_stub_takedown;
engine->vram.init = nouveau_mem_detect;
engine->vram.flags_valid = nouveau_mem_flags_valid;
break;
case 0x10:
engine->instmem.init = nv04_instmem_init;
Expand Down Expand Up @@ -157,6 +159,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.clock_set = nv04_pm_clock_set;
engine->crypt.init = nouveau_stub_init;
engine->crypt.takedown = nouveau_stub_takedown;
engine->vram.init = nouveau_mem_detect;
engine->vram.flags_valid = nouveau_mem_flags_valid;
break;
case 0x20:
engine->instmem.init = nv04_instmem_init;
Expand Down Expand Up @@ -214,6 +218,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.clock_set = nv04_pm_clock_set;
engine->crypt.init = nouveau_stub_init;
engine->crypt.takedown = nouveau_stub_takedown;
engine->vram.init = nouveau_mem_detect;
engine->vram.flags_valid = nouveau_mem_flags_valid;
break;
case 0x30:
engine->instmem.init = nv04_instmem_init;
Expand Down Expand Up @@ -273,6 +279,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.voltage_set = nouveau_voltage_gpio_set;
engine->crypt.init = nouveau_stub_init;
engine->crypt.takedown = nouveau_stub_takedown;
engine->vram.init = nouveau_mem_detect;
engine->vram.flags_valid = nouveau_mem_flags_valid;
break;
case 0x40:
case 0x60:
Expand Down Expand Up @@ -334,6 +342,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.temp_get = nv40_temp_get;
engine->crypt.init = nouveau_stub_init;
engine->crypt.takedown = nouveau_stub_takedown;
engine->vram.init = nouveau_mem_detect;
engine->vram.flags_valid = nouveau_mem_flags_valid;
break;
case 0x50:
case 0x80: /* gotta love NVIDIA's consistency.. */
Expand Down Expand Up @@ -444,6 +454,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->crypt.takedown = nouveau_stub_takedown;
break;
}
engine->vram.init = nv50_vram_init;
engine->vram.get = nv50_vram_new;
engine->vram.put = nv50_vram_del;
engine->vram.flags_valid = nv50_vram_flags_valid;
break;
case 0xC0:
engine->instmem.init = nvc0_instmem_init;
Expand Down Expand Up @@ -495,6 +509,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->gpio.irq_enable = nv50_gpio_irq_enable;
engine->crypt.init = nouveau_stub_init;
engine->crypt.takedown = nouveau_stub_takedown;
engine->vram.init = nouveau_mem_detect;
engine->vram.flags_valid = nouveau_mem_flags_valid;
break;
default:
NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
Expand Down
9 changes: 6 additions & 3 deletions drivers/gpu/drm/nouveau/nv50_instmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
{
struct drm_device *dev = gpuobj->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
struct nv50_gpuobj_node *node = NULL;
int ret;

Expand All @@ -323,7 +324,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
size = (size + 4095) & ~4095;
align = max(align, (u32)4096);

ret = nv50_vram_new(dev, size, align, 0, 0, &node->vram);
ret = vram->get(dev, size, align, 0, 0, &node->vram);
if (ret) {
kfree(node);
return ret;
Expand All @@ -336,7 +337,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS,
&node->chan_vma);
if (ret) {
nv50_vram_del(dev, &node->vram);
vram->put(dev, &node->vram);
kfree(node);
return ret;
}
Expand All @@ -354,6 +355,8 @@ void
nv50_instmem_put(struct nouveau_gpuobj *gpuobj)
{
struct drm_device *dev = gpuobj->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
struct nv50_gpuobj_node *node;

node = gpuobj->node;
Expand All @@ -363,7 +366,7 @@ nv50_instmem_put(struct nouveau_gpuobj *gpuobj)
nouveau_vm_unmap(&node->chan_vma);
nouveau_vm_put(&node->chan_vma);
}
nv50_vram_del(dev, &node->vram);
vram->put(dev, &node->vram);
kfree(node);
}

Expand Down
10 changes: 10 additions & 0 deletions drivers/gpu/drm/nouveau/nv50_vram.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ static int types[0x80] = {
1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0
};

bool
nv50_vram_flags_valid(struct drm_device *dev, u32 tile_flags)
{
int type = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8;

if (likely(type < sizeof(types) && types[type]))
return true;
return false;
}

void
nv50_vram_del(struct drm_device *dev, struct nouveau_vram **pvram)
{
Expand Down

0 comments on commit 60d2a88

Please sign in to comment.