mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge remote branch 'nouveau/drm-nouveau-next' of /ssd/git/drm-nouveau-next into drm-core-next
* 'nouveau/drm-nouveau-next' of /ssd/git/drm-nouveau-next: drm/nvc0: accelerate ttm buffer moves drm/nvc0: initial support for tiled buffer objects drm/nvc0: implement fbcon acceleration drm/nvc0: implement pgraph engine hooks drm/nvc0: implement pfifo engine hooks drm/nvc0: implement fencing drm/nvc0: fix channel dma init paths drm/nvc0: skip dma object creation for drm channel drm/nvc0: implement channel structure initialisation drm/nvc0: gpuobj_new need only check validity and init the relevant engine drm/nvc0: reject the notifier_alloc ioctl drm/nvc0: create shared channel vm drm/nvc0: initial vm implementation, use for bar1/bar3 management drm/nvc0: import initial vm backend drm/nouveau: modify vm to accomodate dual page tables for nvc0 drm/nv50: add missing license header to nv50_fbcon.c drm/nv50: fix smatch warning in nv50_vram.c drm/nouveau: sizeof() vs ARRAY_SIZE()
This commit is contained in:
@@ -18,17 +18,19 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
|
||||
nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o nvc0_fifo.o \
|
||||
nv04_graph.o nv10_graph.o nv20_graph.o \
|
||||
nv40_graph.o nv50_graph.o nvc0_graph.o \
|
||||
nv40_grctx.o nv50_grctx.o \
|
||||
nv40_grctx.o nv50_grctx.o nvc0_grctx.o \
|
||||
nv84_crypt.o \
|
||||
nv04_instmem.o nv50_instmem.o nvc0_instmem.o \
|
||||
nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \
|
||||
nv50_cursor.o nv50_display.o nv50_fbcon.o \
|
||||
nv50_cursor.o nv50_display.o \
|
||||
nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
|
||||
nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \
|
||||
nv04_crtc.o nv04_display.o nv04_cursor.o \
|
||||
nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \
|
||||
nv10_gpio.o nv50_gpio.o \
|
||||
nv50_calc.o \
|
||||
nv04_pm.o nv50_pm.o nva3_pm.o \
|
||||
nv50_vram.o nv50_vm.o
|
||||
nv50_vram.o nvc0_vram.o \
|
||||
nv50_vm.o nvc0_vm.o
|
||||
|
||||
nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
|
||||
nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
|
||||
|
||||
@@ -413,7 +413,7 @@ 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:
|
||||
if (dev_priv->card_type == NV_50) {
|
||||
if (dev_priv->card_type >= NV_50) {
|
||||
man->func = &nouveau_vram_manager;
|
||||
man->io_reserve_fastpath = false;
|
||||
man->use_io_reserve_lru = true;
|
||||
@@ -514,6 +514,58 @@ nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo,
|
||||
return chan->vram_handle;
|
||||
}
|
||||
|
||||
static int
|
||||
nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
|
||||
struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
|
||||
struct nouveau_bo *nvbo = nouveau_bo(bo);
|
||||
u64 src_offset = old_mem->start << PAGE_SHIFT;
|
||||
u64 dst_offset = new_mem->start << PAGE_SHIFT;
|
||||
u32 page_count = new_mem->num_pages;
|
||||
int ret;
|
||||
|
||||
if (!nvbo->no_vm) {
|
||||
if (old_mem->mem_type == TTM_PL_VRAM)
|
||||
src_offset = nvbo->vma.offset;
|
||||
else
|
||||
src_offset += dev_priv->gart_info.aper_base;
|
||||
|
||||
if (new_mem->mem_type == TTM_PL_VRAM)
|
||||
dst_offset = nvbo->vma.offset;
|
||||
else
|
||||
dst_offset += dev_priv->gart_info.aper_base;
|
||||
}
|
||||
|
||||
page_count = new_mem->num_pages;
|
||||
while (page_count) {
|
||||
int line_count = (page_count > 2047) ? 2047 : page_count;
|
||||
|
||||
ret = RING_SPACE(chan, 12);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0238, 2);
|
||||
OUT_RING (chan, upper_32_bits(dst_offset));
|
||||
OUT_RING (chan, lower_32_bits(dst_offset));
|
||||
BEGIN_NVC0(chan, 2, NvSubM2MF, 0x030c, 6);
|
||||
OUT_RING (chan, upper_32_bits(src_offset));
|
||||
OUT_RING (chan, lower_32_bits(src_offset));
|
||||
OUT_RING (chan, PAGE_SIZE); /* src_pitch */
|
||||
OUT_RING (chan, PAGE_SIZE); /* dst_pitch */
|
||||
OUT_RING (chan, PAGE_SIZE); /* line_length */
|
||||
OUT_RING (chan, line_count);
|
||||
BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0300, 1);
|
||||
OUT_RING (chan, 0x00100110);
|
||||
|
||||
page_count -= line_count;
|
||||
src_offset += (PAGE_SIZE * line_count);
|
||||
dst_offset += (PAGE_SIZE * line_count);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
|
||||
struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
|
||||
@@ -690,7 +742,10 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
|
||||
if (dev_priv->card_type < NV_50)
|
||||
ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem);
|
||||
else
|
||||
if (dev_priv->card_type < NV_C0)
|
||||
ret = nv50_bo_move_m2mf(chan, bo, &bo->mem, new_mem);
|
||||
else
|
||||
ret = nvc0_bo_move_m2mf(chan, bo, &bo->mem, new_mem);
|
||||
if (ret == 0) {
|
||||
ret = nouveau_bo_move_accel_cleanup(chan, nvbo, evict,
|
||||
no_wait_reserve,
|
||||
@@ -901,6 +956,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
|
||||
case TTM_PL_VRAM:
|
||||
{
|
||||
struct nouveau_vram *vram = mem->mm_node;
|
||||
u8 page_shift;
|
||||
|
||||
if (!dev_priv->bar1_vm) {
|
||||
mem->bus.offset = mem->start << PAGE_SHIFT;
|
||||
@@ -909,8 +965,14 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
|
||||
break;
|
||||
}
|
||||
|
||||
ret = nouveau_vm_get(dev_priv->bar1_vm, mem->bus.size, 12,
|
||||
NV_MEM_ACCESS_RW, &vram->bar_vma);
|
||||
if (dev_priv->card_type == NV_C0)
|
||||
page_shift = vram->page_shift;
|
||||
else
|
||||
page_shift = 12;
|
||||
|
||||
ret = nouveau_vm_get(dev_priv->bar1_vm, mem->bus.size,
|
||||
page_shift, NV_MEM_ACCESS_RW,
|
||||
&vram->bar_vma);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -920,8 +982,9 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
|
||||
return ret;
|
||||
}
|
||||
|
||||
mem->bus.offset = vram->bar_vma.offset;
|
||||
mem->bus.offset -= 0x0020000000ULL;
|
||||
mem->bus.offset = vram->bar_vma.offset;
|
||||
if (dev_priv->card_type == NV_50) /*XXX*/
|
||||
mem->bus.offset -= 0x0020000000ULL;
|
||||
mem->bus.base = pci_resource_start(dev->pdev, 1);
|
||||
mem->bus.is_iomem = true;
|
||||
}
|
||||
|
||||
@@ -38,9 +38,14 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
|
||||
int ret;
|
||||
|
||||
if (dev_priv->card_type >= NV_50) {
|
||||
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
|
||||
(1ULL << 40), NV_MEM_ACCESS_RO,
|
||||
NV_MEM_TARGET_VM, &pushbuf);
|
||||
if (dev_priv->card_type < NV_C0) {
|
||||
ret = nouveau_gpuobj_dma_new(chan,
|
||||
NV_CLASS_DMA_IN_MEMORY, 0,
|
||||
(1ULL << 40),
|
||||
NV_MEM_ACCESS_RO,
|
||||
NV_MEM_TARGET_VM,
|
||||
&pushbuf);
|
||||
}
|
||||
chan->pushbuf_base = pb->bo.offset;
|
||||
} else
|
||||
if (pb->bo.mem.mem_type == TTM_PL_TT) {
|
||||
@@ -71,7 +76,7 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
|
||||
|
||||
nouveau_gpuobj_ref(pushbuf, &chan->pushbuf);
|
||||
nouveau_gpuobj_ref(NULL, &pushbuf);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct nouveau_bo *
|
||||
@@ -99,6 +104,13 @@ nouveau_channel_user_pushbuf_alloc(struct drm_device *dev)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = nouveau_bo_map(pushbuf);
|
||||
if (ret) {
|
||||
nouveau_bo_unpin(pushbuf);
|
||||
nouveau_bo_ref(NULL, &pushbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pushbuf;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ nouveau_dma_pre_init(struct nouveau_channel *chan)
|
||||
struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
|
||||
struct nouveau_bo *pushbuf = chan->pushbuf_bo;
|
||||
|
||||
if (dev_priv->card_type == NV_50) {
|
||||
if (dev_priv->card_type >= NV_50) {
|
||||
const int ib_size = pushbuf->bo.mem.size / 2;
|
||||
|
||||
chan->dma.ib_base = (pushbuf->bo.mem.size - ib_size) >> 2;
|
||||
@@ -61,6 +61,21 @@ nouveau_dma_init(struct nouveau_channel *chan)
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int ret, i;
|
||||
|
||||
if (dev_priv->card_type >= NV_C0) {
|
||||
ret = nouveau_gpuobj_gr_new(chan, 0x9039, 0x9039);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = RING_SPACE(chan, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0000, 1);
|
||||
OUT_RING (chan, 0x00009039);
|
||||
FIRE_RING (chan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */
|
||||
ret = nouveau_gpuobj_gr_new(chan, NvM2MF, dev_priv->card_type < NV_50 ?
|
||||
0x0039 : 0x5039);
|
||||
@@ -72,11 +87,6 @@ nouveau_dma_init(struct nouveau_channel *chan)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Map push buffer */
|
||||
ret = nouveau_bo_map(chan->pushbuf_bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Insert NOPS for NOUVEAU_DMA_SKIPS */
|
||||
ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS);
|
||||
if (ret)
|
||||
|
||||
@@ -77,7 +77,8 @@ enum {
|
||||
/* G80+ display objects */
|
||||
NvEvoVRAM = 0x01000000,
|
||||
NvEvoFB16 = 0x01000001,
|
||||
NvEvoFB32 = 0x01000002
|
||||
NvEvoFB32 = 0x01000002,
|
||||
NvEvoVRAM_LP = 0x01000003
|
||||
};
|
||||
|
||||
#define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039
|
||||
@@ -124,6 +125,12 @@ OUT_RING(struct nouveau_channel *chan, int data)
|
||||
extern void
|
||||
OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords);
|
||||
|
||||
static inline void
|
||||
BEGIN_NVC0(struct nouveau_channel *chan, int op, int subc, int mthd, int size)
|
||||
{
|
||||
OUT_RING(chan, (op << 28) | (size << 16) | (subc << 13) | (mthd >> 2));
|
||||
}
|
||||
|
||||
static inline void
|
||||
BEGIN_RING(struct nouveau_channel *chan, int subc, int mthd, int size)
|
||||
{
|
||||
|
||||
@@ -69,6 +69,7 @@ struct nouveau_vram {
|
||||
struct drm_device *dev;
|
||||
|
||||
struct nouveau_vma bar_vma;
|
||||
u8 page_shift;
|
||||
|
||||
struct list_head regions;
|
||||
u32 memtype;
|
||||
@@ -239,6 +240,7 @@ struct nouveau_channel {
|
||||
/* PFIFO context */
|
||||
struct nouveau_gpuobj *ramfc;
|
||||
struct nouveau_gpuobj *cache;
|
||||
void *fifo_priv;
|
||||
|
||||
/* PGRAPH context */
|
||||
/* XXX may be merge 2 pointers as private data ??? */
|
||||
@@ -336,6 +338,7 @@ struct nouveau_fb_engine {
|
||||
};
|
||||
|
||||
struct nouveau_fifo_engine {
|
||||
void *priv;
|
||||
int channels;
|
||||
|
||||
struct nouveau_gpuobj *playlist[2];
|
||||
@@ -362,6 +365,7 @@ struct nouveau_pgraph_engine {
|
||||
bool accel_blocked;
|
||||
bool registered;
|
||||
int grctx_size;
|
||||
void *priv;
|
||||
|
||||
/* NV2x/NV3x context table (0x400780) */
|
||||
struct nouveau_gpuobj *ctx_table;
|
||||
@@ -841,6 +845,9 @@ extern void nv10_mem_put_tile_region(struct drm_device *dev,
|
||||
struct nouveau_fence *fence);
|
||||
extern const struct ttm_mem_type_manager_func nouveau_vram_manager;
|
||||
|
||||
/* nvc0_vram.c */
|
||||
extern const struct ttm_mem_type_manager_func nvc0_vram_manager;
|
||||
|
||||
/* nouveau_notifier.c */
|
||||
extern int nouveau_notifier_init_channel(struct nouveau_channel *);
|
||||
extern void nouveau_notifier_takedown_channel(struct nouveau_channel *);
|
||||
@@ -1228,11 +1235,6 @@ extern int nvc0_instmem_init(struct drm_device *);
|
||||
extern void nvc0_instmem_takedown(struct drm_device *);
|
||||
extern int nvc0_instmem_suspend(struct drm_device *);
|
||||
extern void nvc0_instmem_resume(struct drm_device *);
|
||||
extern int nvc0_instmem_get(struct nouveau_gpuobj *, u32 size, u32 align);
|
||||
extern void nvc0_instmem_put(struct nouveau_gpuobj *);
|
||||
extern int nvc0_instmem_map(struct nouveau_gpuobj *);
|
||||
extern void nvc0_instmem_unmap(struct nouveau_gpuobj *);
|
||||
extern void nvc0_instmem_flush(struct drm_device *);
|
||||
|
||||
/* nv04_mc.c */
|
||||
extern int nv04_mc_init(struct drm_device *);
|
||||
|
||||
@@ -68,6 +68,8 @@ nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
|
||||
else
|
||||
if (dev_priv->card_type < NV_C0)
|
||||
ret = nv50_fbcon_fillrect(info, rect);
|
||||
else
|
||||
ret = nvc0_fbcon_fillrect(info, rect);
|
||||
mutex_unlock(&dev_priv->channel->mutex);
|
||||
}
|
||||
|
||||
@@ -98,6 +100,8 @@ nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image)
|
||||
else
|
||||
if (dev_priv->card_type < NV_C0)
|
||||
ret = nv50_fbcon_copyarea(info, image);
|
||||
else
|
||||
ret = nvc0_fbcon_copyarea(info, image);
|
||||
mutex_unlock(&dev_priv->channel->mutex);
|
||||
}
|
||||
|
||||
@@ -128,6 +132,8 @@ nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
|
||||
else
|
||||
if (dev_priv->card_type < NV_C0)
|
||||
ret = nv50_fbcon_imageblit(info, image);
|
||||
else
|
||||
ret = nvc0_fbcon_imageblit(info, image);
|
||||
mutex_unlock(&dev_priv->channel->mutex);
|
||||
}
|
||||
|
||||
@@ -163,10 +169,18 @@ nouveau_fbcon_sync(struct fb_info *info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
BEGIN_RING(chan, 0, 0x0104, 1);
|
||||
OUT_RING(chan, 0);
|
||||
BEGIN_RING(chan, 0, 0x0100, 1);
|
||||
OUT_RING(chan, 0);
|
||||
if (dev_priv->card_type >= NV_C0) {
|
||||
BEGIN_NVC0(chan, 2, NvSub2D, 0x010c, 1);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_NVC0(chan, 2, NvSub2D, 0x0100, 1);
|
||||
OUT_RING (chan, 0);
|
||||
} else {
|
||||
BEGIN_RING(chan, 0, 0x0104, 1);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_RING(chan, 0, 0x0100, 1);
|
||||
OUT_RING (chan, 0);
|
||||
}
|
||||
|
||||
nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy + 3, 0xffffffff);
|
||||
FIRE_RING(chan);
|
||||
mutex_unlock(&chan->mutex);
|
||||
@@ -370,6 +384,8 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
|
||||
else
|
||||
if (dev_priv->card_type < NV_C0)
|
||||
ret = nv50_fbcon_accel_init(info);
|
||||
else
|
||||
ret = nvc0_fbcon_accel_init(info);
|
||||
|
||||
if (ret == 0)
|
||||
info->fbops = &nouveau_fbcon_ops;
|
||||
|
||||
@@ -44,11 +44,17 @@ int nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
|
||||
int nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
|
||||
int nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
|
||||
int nv04_fbcon_accel_init(struct fb_info *info);
|
||||
|
||||
int nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
|
||||
int nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
|
||||
int nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
|
||||
int nv50_fbcon_accel_init(struct fb_info *info);
|
||||
|
||||
int nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
|
||||
int nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
|
||||
int nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
|
||||
int nvc0_fbcon_accel_init(struct fb_info *info);
|
||||
|
||||
void nouveau_fbcon_gpu_lockup(struct fb_info *info);
|
||||
|
||||
int nouveau_fbcon_init(struct drm_device *dev);
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
#include "nouveau_dma.h"
|
||||
|
||||
#define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10)
|
||||
#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17)
|
||||
#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17 && \
|
||||
nouveau_private(dev)->card_type < NV_C0)
|
||||
|
||||
struct nouveau_fence {
|
||||
struct nouveau_channel *channel;
|
||||
@@ -139,6 +140,7 @@ nouveau_fence_emit(struct nouveau_fence *fence)
|
||||
{
|
||||
struct nouveau_channel *chan = fence->channel;
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
ret = RING_SPACE(chan, 2);
|
||||
@@ -159,8 +161,15 @@ nouveau_fence_emit(struct nouveau_fence *fence)
|
||||
list_add_tail(&fence->entry, &chan->fence.pending);
|
||||
spin_unlock(&chan->fence.lock);
|
||||
|
||||
BEGIN_RING(chan, NvSubSw, USE_REFCNT(dev) ? 0x0050 : 0x0150, 1);
|
||||
OUT_RING(chan, fence->sequence);
|
||||
if (USE_REFCNT(dev)) {
|
||||
if (dev_priv->card_type < NV_C0)
|
||||
BEGIN_RING(chan, NvSubSw, 0x0050, 1);
|
||||
else
|
||||
BEGIN_NVC0(chan, 2, NvSubSw, 0x0050, 1);
|
||||
} else {
|
||||
BEGIN_RING(chan, NvSubSw, 0x0150, 1);
|
||||
}
|
||||
OUT_RING (chan, fence->sequence);
|
||||
FIRE_RING(chan);
|
||||
|
||||
return 0;
|
||||
@@ -445,11 +454,14 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = RING_SPACE(chan, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
BEGIN_RING(chan, NvSubSw, 0, 1);
|
||||
OUT_RING(chan, NvSw);
|
||||
/* we leave subchannel empty for nvc0 */
|
||||
if (dev_priv->card_type < NV_C0) {
|
||||
ret = RING_SPACE(chan, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
BEGIN_RING(chan, NvSubSw, 0, 1);
|
||||
OUT_RING(chan, NvSw);
|
||||
}
|
||||
|
||||
/* Create a DMA object for the shared cross-channel sync area. */
|
||||
if (USE_SEMA(dev)) {
|
||||
|
||||
@@ -255,9 +255,6 @@ 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 {
|
||||
dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20;
|
||||
dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
|
||||
}
|
||||
|
||||
if (dev_priv->vram_size)
|
||||
@@ -731,6 +728,10 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
node->page_shift = 12;
|
||||
if (nvbo->vma.node)
|
||||
node->page_shift = nvbo->vma.node->type;
|
||||
|
||||
mem->mm_node = node;
|
||||
mem->start = node->offset >> PAGE_SHIFT;
|
||||
return 0;
|
||||
|
||||
@@ -59,4 +59,9 @@ int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc,
|
||||
void nv50_vram_del(struct drm_device *, struct nouveau_vram **);
|
||||
bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags);
|
||||
|
||||
int nvc0_vram_init(struct drm_device *);
|
||||
int nvc0_vram_new(struct drm_device *, u64 size, u32 align, u32 ncmin,
|
||||
u32 memtype, struct nouveau_vram **);
|
||||
bool nvc0_vram_flags_valid(struct drm_device *, u32 tile_flags);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -164,10 +164,15 @@ int
|
||||
nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct drm_nouveau_notifierobj_alloc *na = data;
|
||||
struct nouveau_channel *chan;
|
||||
int ret;
|
||||
|
||||
/* completely unnecessary for these chipsets... */
|
||||
if (unlikely(dev_priv->card_type >= NV_C0))
|
||||
return -EINVAL;
|
||||
|
||||
chan = nouveau_channel_get(dev, file_priv, na->channel);
|
||||
if (IS_ERR(chan))
|
||||
return PTR_ERR(chan);
|
||||
|
||||
@@ -643,10 +643,13 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, u32 handle, int class)
|
||||
found:
|
||||
switch (oc->engine) {
|
||||
case NVOBJ_ENGINE_SW:
|
||||
ret = nouveau_gpuobj_sw_new(chan, class, &gpuobj);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto insert;
|
||||
if (dev_priv->card_type < NV_C0) {
|
||||
ret = nouveau_gpuobj_sw_new(chan, class, &gpuobj);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto insert;
|
||||
}
|
||||
break;
|
||||
case NVOBJ_ENGINE_GR:
|
||||
if (dev_priv->card_type >= NV_50 && !chan->ramin_grctx) {
|
||||
struct nouveau_pgraph_engine *pgraph =
|
||||
@@ -669,6 +672,10 @@ found:
|
||||
break;
|
||||
}
|
||||
|
||||
/* we're done if this is fermi */
|
||||
if (dev_priv->card_type >= NV_C0)
|
||||
return 0;
|
||||
|
||||
ret = nouveau_gpuobj_new(dev, chan,
|
||||
nouveau_gpuobj_class_instmem_size(dev, class),
|
||||
16,
|
||||
@@ -772,6 +779,25 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
|
||||
|
||||
NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
|
||||
|
||||
if (dev_priv->card_type == NV_C0) {
|
||||
struct nouveau_vm *vm = dev_priv->chan_vm;
|
||||
struct nouveau_vm_pgd *vpgd;
|
||||
|
||||
ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0,
|
||||
&chan->ramin);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nouveau_vm_ref(vm, &chan->vm, NULL);
|
||||
|
||||
vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head);
|
||||
nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst));
|
||||
nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst));
|
||||
nv_wo32(chan->ramin, 0x0208, 0xffffffff);
|
||||
nv_wo32(chan->ramin, 0x020c, 0x000000ff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocate a chunk of memory for per-channel object storage */
|
||||
ret = nouveau_gpuobj_channel_init_pramin(chan);
|
||||
if (ret) {
|
||||
@@ -779,7 +805,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* NV50/NVC0 VM
|
||||
/* NV50 VM
|
||||
* - Allocate per-channel page-directory
|
||||
* - Link with shared channel VM
|
||||
*/
|
||||
@@ -877,9 +903,6 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
|
||||
|
||||
NV_DEBUG(dev, "ch%d\n", chan->id);
|
||||
|
||||
if (!chan->ramht)
|
||||
return;
|
||||
|
||||
nouveau_ramht_ref(NULL, &chan->ramht, chan);
|
||||
|
||||
nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
|
||||
|
||||
@@ -464,11 +464,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->instmem.takedown = nvc0_instmem_takedown;
|
||||
engine->instmem.suspend = nvc0_instmem_suspend;
|
||||
engine->instmem.resume = nvc0_instmem_resume;
|
||||
engine->instmem.get = nvc0_instmem_get;
|
||||
engine->instmem.put = nvc0_instmem_put;
|
||||
engine->instmem.map = nvc0_instmem_map;
|
||||
engine->instmem.unmap = nvc0_instmem_unmap;
|
||||
engine->instmem.flush = nvc0_instmem_flush;
|
||||
engine->instmem.get = nv50_instmem_get;
|
||||
engine->instmem.put = nv50_instmem_put;
|
||||
engine->instmem.map = nv50_instmem_map;
|
||||
engine->instmem.unmap = nv50_instmem_unmap;
|
||||
engine->instmem.flush = nv84_instmem_flush;
|
||||
engine->mc.init = nv50_mc_init;
|
||||
engine->mc.takedown = nv50_mc_takedown;
|
||||
engine->timer.init = nv04_timer_init;
|
||||
@@ -509,8 +509,10 @@ 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;
|
||||
engine->vram.init = nvc0_vram_init;
|
||||
engine->vram.get = nvc0_vram_new;
|
||||
engine->vram.put = nv50_vram_del;
|
||||
engine->vram.flags_valid = nvc0_vram_flags_valid;
|
||||
break;
|
||||
default:
|
||||
NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
|
||||
@@ -550,6 +552,10 @@ nouveau_card_init_channel(struct drm_device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* no dma objects on fermi... */
|
||||
if (dev_priv->card_type >= NV_C0)
|
||||
goto out_done;
|
||||
|
||||
ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY,
|
||||
0, dev_priv->vram_size,
|
||||
NV_MEM_ACCESS_RW, NV_MEM_TARGET_VRAM,
|
||||
@@ -574,6 +580,7 @@ nouveau_card_init_channel(struct drm_device *dev)
|
||||
if (ret)
|
||||
goto out_err;
|
||||
|
||||
out_done:
|
||||
mutex_unlock(&dev_priv->channel->mutex);
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram)
|
||||
{
|
||||
struct nouveau_vm *vm = vma->vm;
|
||||
struct nouveau_mm_node *r;
|
||||
int big = vma->node->type != vm->spg_shift;
|
||||
u32 offset = vma->node->offset + (delta >> 12);
|
||||
u32 bits = vma->node->type - 12;
|
||||
u32 pde = (offset >> vm->pgt_bits) - vm->fpde;
|
||||
@@ -44,7 +45,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram)
|
||||
u32 num = r->length >> bits;
|
||||
|
||||
while (num) {
|
||||
struct nouveau_gpuobj *pgt = vm->pgt[pde].obj;
|
||||
struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big];
|
||||
|
||||
end = (pte + num);
|
||||
if (unlikely(end >= max))
|
||||
@@ -76,6 +77,7 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,
|
||||
dma_addr_t *list)
|
||||
{
|
||||
struct nouveau_vm *vm = vma->vm;
|
||||
int big = vma->node->type != vm->spg_shift;
|
||||
u32 offset = vma->node->offset + (delta >> 12);
|
||||
u32 bits = vma->node->type - 12;
|
||||
u32 num = length >> vma->node->type;
|
||||
@@ -85,7 +87,7 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,
|
||||
u32 end, len;
|
||||
|
||||
while (num) {
|
||||
struct nouveau_gpuobj *pgt = vm->pgt[pde].obj;
|
||||
struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big];
|
||||
|
||||
end = (pte + num);
|
||||
if (unlikely(end >= max))
|
||||
@@ -110,6 +112,7 @@ void
|
||||
nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length)
|
||||
{
|
||||
struct nouveau_vm *vm = vma->vm;
|
||||
int big = vma->node->type != vm->spg_shift;
|
||||
u32 offset = vma->node->offset + (delta >> 12);
|
||||
u32 bits = vma->node->type - 12;
|
||||
u32 num = length >> vma->node->type;
|
||||
@@ -119,7 +122,7 @@ nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length)
|
||||
u32 end, len;
|
||||
|
||||
while (num) {
|
||||
struct nouveau_gpuobj *pgt = vm->pgt[pde].obj;
|
||||
struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big];
|
||||
|
||||
end = (pte + num);
|
||||
if (unlikely(end >= max))
|
||||
@@ -146,7 +149,7 @@ nouveau_vm_unmap(struct nouveau_vma *vma)
|
||||
}
|
||||
|
||||
static void
|
||||
nouveau_vm_unmap_pgt(struct nouveau_vm *vm, u32 fpde, u32 lpde)
|
||||
nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde)
|
||||
{
|
||||
struct nouveau_vm_pgd *vpgd;
|
||||
struct nouveau_vm_pgt *vpgt;
|
||||
@@ -155,15 +158,15 @@ nouveau_vm_unmap_pgt(struct nouveau_vm *vm, u32 fpde, u32 lpde)
|
||||
|
||||
for (pde = fpde; pde <= lpde; pde++) {
|
||||
vpgt = &vm->pgt[pde - vm->fpde];
|
||||
if (--vpgt->refcount)
|
||||
if (--vpgt->refcount[big])
|
||||
continue;
|
||||
|
||||
list_for_each_entry(vpgd, &vm->pgd_list, head) {
|
||||
vm->unmap_pgt(vpgd->obj, pde);
|
||||
}
|
||||
pgt = vpgt->obj[big];
|
||||
vpgt->obj[big] = NULL;
|
||||
|
||||
pgt = vpgt->obj;
|
||||
vpgt->obj = NULL;
|
||||
list_for_each_entry(vpgd, &vm->pgd_list, head) {
|
||||
vm->map_pgt(vpgd->obj, pde, vpgt->obj);
|
||||
}
|
||||
|
||||
mutex_unlock(&vm->mm->mutex);
|
||||
nouveau_gpuobj_ref(NULL, &pgt);
|
||||
@@ -177,6 +180,7 @@ nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type)
|
||||
struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde];
|
||||
struct nouveau_vm_pgd *vpgd;
|
||||
struct nouveau_gpuobj *pgt;
|
||||
int big = (type != vm->spg_shift);
|
||||
u32 pgt_size;
|
||||
int ret;
|
||||
|
||||
@@ -191,19 +195,18 @@ nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type)
|
||||
return ret;
|
||||
|
||||
/* someone beat us to filling the PDE while we didn't have the lock */
|
||||
if (unlikely(vpgt->refcount++)) {
|
||||
if (unlikely(vpgt->refcount[big]++)) {
|
||||
mutex_unlock(&vm->mm->mutex);
|
||||
nouveau_gpuobj_ref(NULL, &pgt);
|
||||
mutex_lock(&vm->mm->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vpgt->obj[big] = pgt;
|
||||
list_for_each_entry(vpgd, &vm->pgd_list, head) {
|
||||
vm->map_pgt(vpgd->obj, type, pde, pgt);
|
||||
vm->map_pgt(vpgd->obj, pde, vpgt->obj);
|
||||
}
|
||||
|
||||
vpgt->page_shift = type;
|
||||
vpgt->obj = pgt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -227,16 +230,17 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift,
|
||||
lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits;
|
||||
for (pde = fpde; pde <= lpde; pde++) {
|
||||
struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde];
|
||||
int big = (vma->node->type != vm->spg_shift);
|
||||
|
||||
if (likely(vpgt->refcount)) {
|
||||
vpgt->refcount++;
|
||||
if (likely(vpgt->refcount[big])) {
|
||||
vpgt->refcount[big]++;
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = nouveau_vm_map_pgt(vm, pde, vma->node->type);
|
||||
if (ret) {
|
||||
if (pde != fpde)
|
||||
nouveau_vm_unmap_pgt(vm, fpde, pde - 1);
|
||||
nouveau_vm_unmap_pgt(vm, big, fpde, pde - 1);
|
||||
nouveau_mm_put(vm->mm, vma->node);
|
||||
mutex_unlock(&vm->mm->mutex);
|
||||
vma->node = NULL;
|
||||
@@ -263,21 +267,20 @@ nouveau_vm_put(struct nouveau_vma *vma)
|
||||
lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits;
|
||||
|
||||
mutex_lock(&vm->mm->mutex);
|
||||
nouveau_vm_unmap_pgt(vm, vma->node->type != vm->spg_shift, fpde, lpde);
|
||||
nouveau_mm_put(vm->mm, vma->node);
|
||||
vma->node = NULL;
|
||||
nouveau_vm_unmap_pgt(vm, fpde, lpde);
|
||||
mutex_unlock(&vm->mm->mutex);
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset,
|
||||
u8 pgt_bits, u8 spg_shift, u8 lpg_shift,
|
||||
struct nouveau_vm **pvm)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_vm *vm;
|
||||
u64 mm_length = (offset + length) - mm_offset;
|
||||
u32 block;
|
||||
u32 block, pgt_bits;
|
||||
int ret;
|
||||
|
||||
vm = kzalloc(sizeof(*vm), GFP_KERNEL);
|
||||
@@ -286,11 +289,40 @@ nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset,
|
||||
|
||||
if (dev_priv->card_type == NV_50) {
|
||||
vm->map_pgt = nv50_vm_map_pgt;
|
||||
vm->unmap_pgt = nv50_vm_unmap_pgt;
|
||||
vm->map = nv50_vm_map;
|
||||
vm->map_sg = nv50_vm_map_sg;
|
||||
vm->unmap = nv50_vm_unmap;
|
||||
vm->flush = nv50_vm_flush;
|
||||
vm->spg_shift = 12;
|
||||
vm->lpg_shift = 16;
|
||||
|
||||
pgt_bits = 29;
|
||||
block = (1 << pgt_bits);
|
||||
if (length < block)
|
||||
block = length;
|
||||
|
||||
} else
|
||||
if (dev_priv->card_type == NV_C0) {
|
||||
vm->map_pgt = nvc0_vm_map_pgt;
|
||||
vm->map = nvc0_vm_map;
|
||||
vm->map_sg = nvc0_vm_map_sg;
|
||||
vm->unmap = nvc0_vm_unmap;
|
||||
vm->flush = nvc0_vm_flush;
|
||||
vm->spg_shift = 12;
|
||||
vm->lpg_shift = 17;
|
||||
pgt_bits = 27;
|
||||
|
||||
/* Should be 4096 everywhere, this is a hack that's
|
||||
* currently necessary to avoid an elusive bug that
|
||||
* causes corruption when mixing small/large pages
|
||||
*/
|
||||
if (length < (1ULL << 40))
|
||||
block = 4096;
|
||||
else {
|
||||
block = (1 << pgt_bits);
|
||||
if (length < block)
|
||||
block = length;
|
||||
}
|
||||
} else {
|
||||
kfree(vm);
|
||||
return -ENOSYS;
|
||||
@@ -308,12 +340,6 @@ nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset,
|
||||
vm->dev = dev;
|
||||
vm->refcount = 1;
|
||||
vm->pgt_bits = pgt_bits - 12;
|
||||
vm->spg_shift = spg_shift;
|
||||
vm->lpg_shift = lpg_shift;
|
||||
|
||||
block = (1 << pgt_bits);
|
||||
if (length < block)
|
||||
block = length;
|
||||
|
||||
ret = nouveau_mm_init(&vm->mm, mm_offset >> 12, mm_length >> 12,
|
||||
block >> 12);
|
||||
@@ -342,16 +368,8 @@ nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd)
|
||||
nouveau_gpuobj_ref(pgd, &vpgd->obj);
|
||||
|
||||
mutex_lock(&vm->mm->mutex);
|
||||
for (i = vm->fpde; i <= vm->lpde; i++) {
|
||||
struct nouveau_vm_pgt *vpgt = &vm->pgt[i - vm->fpde];
|
||||
|
||||
if (!vpgt->obj) {
|
||||
vm->unmap_pgt(pgd, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
vm->map_pgt(pgd, vpgt->page_shift, i, vpgt->obj);
|
||||
}
|
||||
for (i = vm->fpde; i <= vm->lpde; i++)
|
||||
vm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj);
|
||||
list_add(&vpgd->head, &vm->pgd_list);
|
||||
mutex_unlock(&vm->mm->mutex);
|
||||
return 0;
|
||||
|
||||
@@ -31,9 +31,8 @@
|
||||
#include "nouveau_mm.h"
|
||||
|
||||
struct nouveau_vm_pgt {
|
||||
struct nouveau_gpuobj *obj;
|
||||
u32 page_shift;
|
||||
u32 refcount;
|
||||
struct nouveau_gpuobj *obj[2];
|
||||
u32 refcount[2];
|
||||
};
|
||||
|
||||
struct nouveau_vm_pgd {
|
||||
@@ -65,9 +64,8 @@ struct nouveau_vm {
|
||||
u8 spg_shift;
|
||||
u8 lpg_shift;
|
||||
|
||||
void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 type, u32 pde,
|
||||
struct nouveau_gpuobj *pgt);
|
||||
void (*unmap_pgt)(struct nouveau_gpuobj *pgd, u32 pde);
|
||||
void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde,
|
||||
struct nouveau_gpuobj *pgt[2]);
|
||||
void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *,
|
||||
struct nouveau_vram *, u32 pte, u32 cnt, u64 phys);
|
||||
void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *,
|
||||
@@ -78,7 +76,6 @@ struct nouveau_vm {
|
||||
|
||||
/* nouveau_vm.c */
|
||||
int nouveau_vm_new(struct drm_device *, u64 offset, u64 length, u64 mm_offset,
|
||||
u8 pgt_bits, u8 spg_shift, u8 lpg_shift,
|
||||
struct nouveau_vm **);
|
||||
int nouveau_vm_ref(struct nouveau_vm *, struct nouveau_vm **,
|
||||
struct nouveau_gpuobj *pgd);
|
||||
@@ -93,9 +90,8 @@ void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length,
|
||||
dma_addr_t *);
|
||||
|
||||
/* nv50_vm.c */
|
||||
void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 type, u32 pde,
|
||||
struct nouveau_gpuobj *pgt);
|
||||
void nv50_vm_unmap_pgt(struct nouveau_gpuobj *pgd, u32 pde);
|
||||
void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
|
||||
struct nouveau_gpuobj *pgt[2]);
|
||||
void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *,
|
||||
struct nouveau_vram *, u32 pte, u32 cnt, u64 phys);
|
||||
void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *,
|
||||
@@ -104,4 +100,14 @@ void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt);
|
||||
void nv50_vm_flush(struct nouveau_vm *);
|
||||
void nv50_vm_flush_engine(struct drm_device *, int engine);
|
||||
|
||||
/* nvc0_vm.c */
|
||||
void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
|
||||
struct nouveau_gpuobj *pgt[2]);
|
||||
void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *,
|
||||
struct nouveau_vram *, u32 pte, u32 cnt, u64 phys);
|
||||
void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *,
|
||||
u32 pte, dma_addr_t *, u32 cnt);
|
||||
void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt);
|
||||
void nvc0_vm_flush(struct nouveau_vm *);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -115,15 +115,16 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked)
|
||||
OUT_RING(evo, 0);
|
||||
BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1);
|
||||
if (dev_priv->chipset != 0x50)
|
||||
if (nv_crtc->fb.tile_flags == 0x7a00)
|
||||
if (nv_crtc->fb.tile_flags == 0x7a00 ||
|
||||
nv_crtc->fb.tile_flags == 0xfe00)
|
||||
OUT_RING(evo, NvEvoFB32);
|
||||
else
|
||||
if (nv_crtc->fb.tile_flags == 0x7000)
|
||||
OUT_RING(evo, NvEvoFB16);
|
||||
else
|
||||
OUT_RING(evo, NvEvoVRAM);
|
||||
OUT_RING(evo, NvEvoVRAM_LP);
|
||||
else
|
||||
OUT_RING(evo, NvEvoVRAM);
|
||||
OUT_RING(evo, NvEvoVRAM_LP);
|
||||
}
|
||||
|
||||
nv_crtc->fb.blanked = blanked;
|
||||
@@ -555,13 +556,14 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
|
||||
return ret;
|
||||
|
||||
BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1);
|
||||
if (nv_crtc->fb.tile_flags == 0x7a00)
|
||||
if (nv_crtc->fb.tile_flags == 0x7a00 ||
|
||||
nv_crtc->fb.tile_flags == 0xfe00)
|
||||
OUT_RING(evo, NvEvoFB32);
|
||||
else
|
||||
if (nv_crtc->fb.tile_flags == 0x7000)
|
||||
OUT_RING(evo, NvEvoFB16);
|
||||
else
|
||||
OUT_RING(evo, NvEvoVRAM);
|
||||
OUT_RING(evo, NvEvoVRAM_LP);
|
||||
}
|
||||
|
||||
ret = RING_SPACE(evo, 12);
|
||||
@@ -575,8 +577,10 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
|
||||
if (!nv_crtc->fb.tile_flags) {
|
||||
OUT_RING(evo, drm_fb->pitch | (1 << 20));
|
||||
} else {
|
||||
OUT_RING(evo, ((drm_fb->pitch / 4) << 4) |
|
||||
fb->nvbo->tile_mode);
|
||||
u32 tile_mode = fb->nvbo->tile_mode;
|
||||
if (dev_priv->card_type >= NV_C0)
|
||||
tile_mode >>= 4;
|
||||
OUT_RING(evo, ((drm_fb->pitch / 4) << 4) | tile_mode);
|
||||
}
|
||||
if (dev_priv->chipset == 0x50)
|
||||
OUT_RING(evo, (nv_crtc->fb.tile_flags << 8) | format);
|
||||
|
||||
@@ -53,7 +53,8 @@ nv50_evo_channel_del(struct nouveau_channel **pevo)
|
||||
|
||||
int
|
||||
nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 class, u32 name,
|
||||
u32 tile_flags, u32 magic_flags, u32 offset, u32 limit)
|
||||
u32 tile_flags, u32 magic_flags, u32 offset, u32 limit,
|
||||
u32 flags5)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = evo->dev->dev_private;
|
||||
struct drm_device *dev = evo->dev;
|
||||
@@ -70,10 +71,7 @@ nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 class, u32 name,
|
||||
nv_wo32(obj, 8, offset);
|
||||
nv_wo32(obj, 12, 0x00000000);
|
||||
nv_wo32(obj, 16, 0x00000000);
|
||||
if (dev_priv->card_type < NV_C0)
|
||||
nv_wo32(obj, 20, 0x00010000);
|
||||
else
|
||||
nv_wo32(obj, 20, 0x00020000);
|
||||
nv_wo32(obj, 20, flags5);
|
||||
dev_priv->engine.instmem.flush(dev);
|
||||
|
||||
ret = nouveau_ramht_insert(evo, name, obj);
|
||||
@@ -264,9 +262,31 @@ nv50_evo_create(struct drm_device *dev)
|
||||
}
|
||||
|
||||
/* create some default objects for the scanout memtypes we support */
|
||||
if (dev_priv->card_type >= NV_C0) {
|
||||
ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0xfe, 0x19,
|
||||
0, 0xffffffff, 0x00000000);
|
||||
if (ret) {
|
||||
nv50_evo_channel_del(&dev_priv->evo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19,
|
||||
0, dev_priv->vram_size, 0x00020000);
|
||||
if (ret) {
|
||||
nv50_evo_channel_del(&dev_priv->evo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19,
|
||||
0, dev_priv->vram_size, 0x00000000);
|
||||
if (ret) {
|
||||
nv50_evo_channel_del(&dev_priv->evo);
|
||||
return ret;
|
||||
}
|
||||
} else
|
||||
if (dev_priv->chipset != 0x50) {
|
||||
ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB16, 0x70, 0x19,
|
||||
0, 0xffffffff);
|
||||
0, 0xffffffff, 0x00010000);
|
||||
if (ret) {
|
||||
nv50_evo_channel_del(&dev_priv->evo);
|
||||
return ret;
|
||||
@@ -274,18 +294,25 @@ nv50_evo_create(struct drm_device *dev)
|
||||
|
||||
|
||||
ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0x7a, 0x19,
|
||||
0, 0xffffffff);
|
||||
0, 0xffffffff, 0x00010000);
|
||||
if (ret) {
|
||||
nv50_evo_channel_del(&dev_priv->evo);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19,
|
||||
0, dev_priv->vram_size);
|
||||
if (ret) {
|
||||
nv50_evo_channel_del(&dev_priv->evo);
|
||||
return ret;
|
||||
ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19,
|
||||
0, dev_priv->vram_size, 0x00010000);
|
||||
if (ret) {
|
||||
nv50_evo_channel_del(&dev_priv->evo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19,
|
||||
0, dev_priv->vram_size, 0x00010000);
|
||||
if (ret) {
|
||||
nv50_evo_channel_del(&dev_priv->evo);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
/*
|
||||
* Copyright 2010 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Ben Skeggs
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include "nouveau_dma.h"
|
||||
|
||||
@@ -151,20 +151,19 @@ nv50_instmem_init(struct drm_device *dev)
|
||||
|
||||
/* BAR3 */
|
||||
ret = nouveau_vm_new(dev, BAR3_VM_BASE, BAR3_VM_SIZE, BAR3_VM_BASE,
|
||||
29, 12, 16, &dev_priv->bar3_vm);
|
||||
&dev_priv->bar3_vm);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = nouveau_gpuobj_new(dev, NULL, (BAR3_VM_SIZE >> 12) * 8,
|
||||
0x1000, NVOBJ_FLAG_DONT_MAP |
|
||||
NVOBJ_FLAG_ZERO_ALLOC,
|
||||
&dev_priv->bar3_vm->pgt[0].obj);
|
||||
&dev_priv->bar3_vm->pgt[0].obj[0]);
|
||||
if (ret)
|
||||
goto error;
|
||||
dev_priv->bar3_vm->pgt[0].page_shift = 12;
|
||||
dev_priv->bar3_vm->pgt[0].refcount = 1;
|
||||
dev_priv->bar3_vm->pgt[0].refcount[0] = 1;
|
||||
|
||||
nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj);
|
||||
nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]);
|
||||
|
||||
ret = nv50_channel_new(dev, 128 * 1024, dev_priv->bar3_vm, &chan);
|
||||
if (ret)
|
||||
@@ -195,8 +194,7 @@ nv50_instmem_init(struct drm_device *dev)
|
||||
nv_wo32(chan->ramin, 0, tmp);
|
||||
|
||||
/* BAR1 */
|
||||
ret = nouveau_vm_new(dev, BAR1_VM_BASE, BAR1_VM_SIZE, BAR1_VM_BASE,
|
||||
29, 12, 16, &vm);
|
||||
ret = nouveau_vm_new(dev, BAR1_VM_BASE, BAR1_VM_SIZE, BAR1_VM_BASE, &vm);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
@@ -220,7 +218,7 @@ nv50_instmem_init(struct drm_device *dev)
|
||||
* to catch "NULL pointer" references
|
||||
*/
|
||||
ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL,
|
||||
29, 12, 16, &dev_priv->chan_vm);
|
||||
&dev_priv->chan_vm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -258,7 +256,7 @@ nv50_instmem_takedown(struct drm_device *dev)
|
||||
dev_priv->channels.ptr[127] = 0;
|
||||
nv50_channel_del(&dev_priv->channels.ptr[0]);
|
||||
|
||||
nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj);
|
||||
nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]);
|
||||
nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL);
|
||||
|
||||
if (dev_priv->ramin_heap.free_stack.next)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user