Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 228596
b: refs/heads/master
c: 573a2a3
h: refs/heads/master
v: v3
  • Loading branch information
Ben Skeggs committed Dec 8, 2010
1 parent 4f066b2 commit ed10345
Show file tree
Hide file tree
Showing 9 changed files with 651 additions and 123 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 937c3471cc8b7ef8f9e382d9e4ec232db151ea7b
refs/heads/master: 573a2a37e8648a3249426c816f51e7ef50f6f73e
5 changes: 3 additions & 2 deletions trunk/drivers/gpu/drm/nouveau/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \
nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \
nouveau_display.o nouveau_connector.o nouveau_fbcon.o \
nouveau_dp.o nouveau_ramht.o \
nouveau_dp.o nouveau_ramht.o nouveau_mm.o \
nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \
nv04_timer.o \
nv04_mc.o nv40_mc.o nv50_mc.o \
Expand All @@ -26,7 +26,8 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \
nv10_gpio.o nv50_gpio.o \
nv50_calc.o \
nv04_pm.o nv50_pm.o nva3_pm.o
nv04_pm.o nv50_pm.o nva3_pm.o \
nv50_vram.o

nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
Expand Down
43 changes: 5 additions & 38 deletions trunk/drivers/gpu/drm/nouveau/nouveau_bo.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,42 +57,7 @@ nouveau_bo_fixup_align(struct drm_device *dev,
{
struct drm_nouveau_private *dev_priv = dev->dev_private;

/*
* Some of the tile_flags have a periodic structure of N*4096 bytes,
* align to to that as well as the page size. Align the size to the
* appropriate boundaries. This does imply that sizes are rounded up
* 3-7 pages, so be aware of this and do not waste memory by allocating
* many small buffers.
*/
if (dev_priv->card_type == NV_50) {
uint32_t block_size = dev_priv->vram_size >> 15;
int i;

switch (tile_flags) {
case 0x1800:
case 0x2800:
case 0x4800:
case 0x7a00:
if (is_power_of_2(block_size)) {
for (i = 1; i < 10; i++) {
*align = 12 * i * block_size;
if (!(*align % 65536))
break;
}
} else {
for (i = 1; i < 10; i++) {
*align = 8 * i * block_size;
if (!(*align % 65536))
break;
}
}
*size = roundup(*size, *align);
break;
default:
break;
}

} else {
if (dev_priv->card_type < NV_50) {
if (tile_mode) {
if (dev_priv->chipset >= 0x40) {
*align = 65536;
Expand All @@ -115,7 +80,6 @@ nouveau_bo_fixup_align(struct drm_device *dev,

/* ALIGN works only on powers of two. */
*size = roundup(*size, PAGE_SIZE);

if (dev_priv->card_type == NV_50) {
*size = roundup(*size, 65536);
*align = max(65536, *align);
Expand Down Expand Up @@ -422,7 +386,10 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
man->default_caching = TTM_PL_FLAG_CACHED;
break;
case TTM_PL_VRAM:
man->func = &ttm_bo_manager_func;
if (dev_priv->card_type == NV_50)
man->func = &nouveau_vram_manager;
else
man->func = &ttm_bo_manager_func;
man->flags = TTM_MEMTYPE_FLAG_FIXED |
TTM_MEMTYPE_FLAG_MAPPABLE;
man->available_caching = TTM_PL_FLAG_UNCACHED |
Expand Down
10 changes: 10 additions & 0 deletions trunk/drivers/gpu/drm/nouveau/nouveau_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ struct nouveau_grctx;
#define NV50_VM_BLOCK (512*1024*1024ULL)
#define NV50_VM_VRAM_NR (NV50_VM_MAX_VRAM / NV50_VM_BLOCK)

struct nouveau_vram {
struct drm_device *dev;

struct list_head regions;
u32 memtype;
u64 offset;
u64 size;
};

struct nouveau_tile_reg {
bool used;
uint32_t addr;
Expand Down Expand Up @@ -821,6 +830,7 @@ extern int nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt,
uint64_t phys);
extern void nv50_mem_vm_unbind(struct drm_device *, uint64_t virt,
uint32_t size);
extern const struct ttm_mem_type_manager_func nouveau_vram_manager;

/* nouveau_notifier.c */
extern int nouveau_notifier_init_channel(struct nouveau_channel *);
Expand Down
201 changes: 119 additions & 82 deletions trunk/drivers/gpu/drm/nouveau/nouveau_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

#include "nouveau_drv.h"
#include "nouveau_pm.h"
#include "nouveau_mm.h"

/*
* NV10-NV40 tiling helpers
Expand Down Expand Up @@ -333,61 +334,6 @@ nouveau_mem_detect_nforce(struct drm_device *dev)
return 0;
}

static void
nv50_vram_preinit(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
int i, parts, colbits, rowbitsa, rowbitsb, banks;
u64 rowsize, predicted;
u32 r0, r4, rt, ru;

r0 = nv_rd32(dev, 0x100200);
r4 = nv_rd32(dev, 0x100204);
rt = nv_rd32(dev, 0x100250);
ru = nv_rd32(dev, 0x001540);
NV_DEBUG(dev, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru);

for (i = 0, parts = 0; i < 8; i++) {
if (ru & (0x00010000 << i))
parts++;
}

colbits = (r4 & 0x0000f000) >> 12;
rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
banks = ((r4 & 0x01000000) ? 8 : 4);

rowsize = parts * banks * (1 << colbits) * 8;
predicted = rowsize << rowbitsa;
if (r0 & 0x00000004)
predicted += rowsize << rowbitsb;

if (predicted != dev_priv->vram_size) {
NV_WARN(dev, "memory controller reports %dMiB VRAM\n",
(u32)(dev_priv->vram_size >> 20));
NV_WARN(dev, "we calculated %dMiB VRAM\n",
(u32)(predicted >> 20));
}

dev_priv->vram_rblock_size = rowsize >> 12;
if (rt & 1)
dev_priv->vram_rblock_size *= 3;

NV_DEBUG(dev, "rblock %lld bytes\n",
(u64)dev_priv->vram_rblock_size << 12);
}

static void
nvaa_vram_preinit(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;

/* To our knowledge, there's no large scale reordering of pages
* that occurs on IGP chipsets.
*/
dev_priv->vram_rblock_size = 1;
}

static int
nouveau_mem_detect(struct drm_device *dev)
{
Expand All @@ -404,22 +350,8 @@ nouveau_mem_detect(struct drm_device *dev)
dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK;
} else
if (dev_priv->card_type < NV_C0) {
dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA);
dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32;
dev_priv->vram_size &= 0xffffffff00ll;

switch (dev_priv->chipset) {
case 0xaa:
case 0xac:
case 0xaf:
dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10);
dev_priv->vram_sys_base <<= 12;
nvaa_vram_preinit(dev);
break;
default:
nv50_vram_preinit(dev);
break;
}
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);
Expand Down Expand Up @@ -568,10 +500,6 @@ nouveau_mem_vram_init(struct drm_device *dev)
if (ret)
return ret;

ret = nouveau_mem_detect(dev);
if (ret)
return ret;

dev_priv->fb_phys = pci_resource_start(dev->pdev, 1);

ret = nouveau_ttm_global_init(dev_priv);
Expand All @@ -587,13 +515,6 @@ nouveau_mem_vram_init(struct drm_device *dev)
return ret;
}

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))
dev_priv->fb_mappable_pages =
pci_resource_len(dev->pdev, 1);
dev_priv->fb_mappable_pages >>= PAGE_SHIFT;

/* reserve space at end of VRAM for PRAMIN */
if (dev_priv->chipset == 0x40 || dev_priv->chipset == 0x47 ||
dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b)
Expand All @@ -604,6 +525,17 @@ 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);
if (ret)
return ret;

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))
dev_priv->fb_mappable_pages = pci_resource_len(dev->pdev, 1);
dev_priv->fb_mappable_pages >>= PAGE_SHIFT;

dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram;
dev_priv->fb_aper_free = dev_priv->fb_available_size;

Expand Down Expand Up @@ -820,3 +752,108 @@ nouveau_mem_timing_fini(struct drm_device *dev)

kfree(mem->timing);
}

static int
nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size)
{
struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
struct nouveau_mm *mm;
u32 b_size;
int ret;

p_size = (p_size << PAGE_SHIFT) >> 12;
b_size = dev_priv->vram_rblock_size >> 12;

ret = nouveau_mm_init(&mm, 0, p_size, b_size);
if (ret)
return ret;

man->priv = mm;
return 0;
}

static int
nouveau_vram_manager_fini(struct ttm_mem_type_manager *man)
{
struct nouveau_mm *mm = man->priv;
int ret;

ret = nouveau_mm_fini(&mm);
if (ret)
return ret;

man->priv = NULL;
return 0;
}

static void
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 drm_device *dev = dev_priv->dev;

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

static int
nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
struct ttm_buffer_object *bo,
struct ttm_placement *placement,
struct ttm_mem_reg *mem)
{
struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
struct drm_device *dev = dev_priv->dev;
struct nouveau_bo *nvbo = nouveau_bo(bo);
struct nouveau_vram *vram;
int ret;

ret = nv50_vram_new(dev, mem->num_pages << PAGE_SHIFT, 65536, 0,
(nvbo->tile_flags >> 8) & 0x7f, &vram);
if (ret)
return ret;

mem->mm_node = vram;
mem->start = vram->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] = {};
int i;

mutex_lock(&mm->mutex);
list_for_each_entry(r, &mm->nodes, nl_entry) {
printk(KERN_DEBUG "%s %s-%d: 0x%010llx 0x%010llx\n",
prefix, r->free ? "free" : "used", r->type,
((u64)r->offset << 12),
(((u64)r->offset + r->length) << 12));
total += r->length;
ttotal[r->type] += r->length;
if (r->free)
tfree[r->type] += r->length;
else
tused[r->type] += r->length;
}
mutex_unlock(&mm->mutex);

printk(KERN_DEBUG "%s total: 0x%010llx\n", prefix, total << 12);
for (i = 0; i < 3; i++) {
printk(KERN_DEBUG "%s type %d: 0x%010llx, "
"used 0x%010llx, free 0x%010llx\n", prefix,
i, ttotal[i] << 12, tused[i] << 12, tfree[i] << 12);
}
}

const struct ttm_mem_type_manager_func nouveau_vram_manager = {
nouveau_vram_manager_init,
nouveau_vram_manager_fini,
nouveau_vram_manager_new,
nouveau_vram_manager_del,
nouveau_vram_manager_debug
};
Loading

0 comments on commit ed10345

Please sign in to comment.