diff --git a/packages/linux/patches/linux-2.6.36-rc7-git5-drm_nouveau_upstream-20101014.diff b/packages/linux/patches/110-linux-2.6.36-drm_nouveau_upstream-20101022.diff similarity index 73% rename from packages/linux/patches/linux-2.6.36-rc7-git5-drm_nouveau_upstream-20101014.diff rename to packages/linux/patches/110-linux-2.6.36-drm_nouveau_upstream-20101022.diff index b229daa65d..31f946ebaf 100644 --- a/packages/linux/patches/linux-2.6.36-rc7-git5-drm_nouveau_upstream-20101014.diff +++ b/packages/linux/patches/110-linux-2.6.36-drm_nouveau_upstream-20101022.diff @@ -1,6 +1,6 @@ -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/Kconfig linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/Kconfig ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/Kconfig 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/Kconfig 2010-10-15 02:04:44.280991202 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/Kconfig linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/Kconfig +--- linux-2.6.36/drivers/gpu/drm/nouveau/Kconfig 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/Kconfig 2010-10-22 23:59:52.455453201 +0200 @@ -10,6 +10,7 @@ select FB select FRAMEBUFFER_CONSOLE if !EMBEDDED @@ -9,9 +9,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/Kconfig linux-2.6.36-rc7.pat help Choose this option for open-source nVidia support. -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/Makefile linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/Makefile ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/Makefile 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/Makefile 2010-10-15 02:04:44.281991214 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/Makefile linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/Makefile +--- linux-2.6.36/drivers/gpu/drm/nouveau/Makefile 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/Makefile 2010-10-22 23:59:52.455453201 +0200 @@ -9,7 +9,8 @@ nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ @@ -22,7 +22,15 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/Makefile linux-2.6.36-rc7.pa nv04_timer.o \ nv04_mc.o nv40_mc.o nv50_mc.o \ nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ -@@ -23,7 +24,8 @@ +@@ -17,13 +18,15 @@ + nv04_graph.o nv10_graph.o nv20_graph.o \ + nv40_graph.o nv50_graph.o nvc0_graph.o \ + nv40_grctx.o nv50_grctx.o \ ++ nv84_crypt.o \ + nv04_instmem.o nv50_instmem.o nvc0_instmem.o \ +- nv50_crtc.o nv50_dac.o nv50_sor.o \ ++ nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \ + nv50_cursor.o nv50_display.o nv50_fbcon.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 \ nv10_gpio.o nv50_gpio.o \ @@ -32,9 +40,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/Makefile linux-2.6.36-rc7.pa nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_acpi.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_acpi.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_acpi.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_acpi.c 2010-10-15 02:04:44.288991301 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_acpi.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_acpi.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_acpi.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_acpi.c 2010-10-22 23:59:52.463453300 +0200 @@ -292,6 +292,6 @@ if (ret < 0) return ret; @@ -43,9 +51,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_acpi.c linux-2.6.36- + nv_connector->edid = kmemdup(edid, EDID_LENGTH, GFP_KERNEL); return 0; } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bios.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_bios.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bios.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_bios.c 2010-10-15 02:04:44.310991574 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_bios.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_bios.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.c 2010-10-22 23:59:52.469453373 +0200 @@ -43,9 +43,6 @@ #define BIOSLOG(sip, fmt, arg...) NV_DEBUG(sip->dev, fmt, ##arg) #define LOG_OLD_VALUE(x) @@ -593,9 +601,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bios.c linux-2.6.36- ret = nouveau_run_vbios_init(dev); if (ret) -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bios.h linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_bios.h ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bios.h 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_bios.h 2010-10-15 02:04:44.320991698 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_bios.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.h +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_bios.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.h 2010-10-22 23:59:52.472453412 +0200 @@ -34,6 +34,20 @@ #define DCB_LOC_ON_CHIP 0 @@ -664,9 +672,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bios.h linux-2.6.36- uint8_t chip_version; -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_bo.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bo.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_bo.c 2010-10-15 02:04:44.322991724 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_bo.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_bo.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_bo.c 2010-10-22 23:59:52.473453424 +0200 @@ -36,21 +36,6 @@ #include #include @@ -765,7 +773,13 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.36-rc } u16 -@@ -404,7 +415,10 @@ +@@ -399,14 +410,19 @@ + man->default_caching = TTM_PL_FLAG_CACHED; + break; + case TTM_PL_VRAM: ++ man->func = &ttm_bo_manager_func; + man->flags = TTM_MEMTYPE_FLAG_FIXED | + TTM_MEMTYPE_FLAG_MAPPABLE; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; @@ -776,24 +790,21 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.36-rc + man->gpu_offset = 0; break; case TTM_PL_TT: ++ man->func = &ttm_bo_manager_func; switch (dev_priv->gart_info.type) { -@@ -469,19 +483,26 @@ + case NOUVEAU_GART_AGP: + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; +@@ -469,19 +485,19 @@ if (ret) return ret; - ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, - evict || (nvbo->channel && - nvbo->channel != chan), -+ if (nvbo->channel) { -+ ret = nouveau_fence_sync(fence, nvbo->channel); -+ if (ret) -+ goto out; -+ } -+ + ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, evict, no_wait_reserve, no_wait_gpu, new_mem); -+out: - nouveau_fence_unref((void *)&fence); +- nouveau_fence_unref((void *)&fence); ++ nouveau_fence_unref(&fence); return ret; } @@ -810,7 +821,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.36-rc if (mem->mem_type == TTM_PL_TT) return NvDmaGART; return NvDmaVRAM; -@@ -493,87 +514,191 @@ +@@ -493,87 +509,191 @@ } static int @@ -835,12 +846,14 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.36-rc - if (!chan || nvbo->tile_flags || nvbo->no_vm) - chan = dev_priv->channel; - - src_offset = old_mem->mm_node->start << PAGE_SHIFT; - dst_offset = new_mem->mm_node->start << PAGE_SHIFT; +- src_offset = old_mem->mm_node->start << PAGE_SHIFT; +- dst_offset = new_mem->mm_node->start << PAGE_SHIFT; - if (chan != dev_priv->channel) { - if (old_mem->mem_type == TTM_PL_TT) - src_offset += dev_priv->vm_gart_base; - else ++ src_offset = old_mem->start << PAGE_SHIFT; ++ dst_offset = new_mem->start << PAGE_SHIFT; + if (!nvbo->no_vm) { + if (old_mem->mem_type == TTM_PL_VRAM) src_offset += dev_priv->vm_vram_base; @@ -956,8 +969,8 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.36-rc +nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, + struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) +{ -+ u32 src_offset = old_mem->mm_node->start << PAGE_SHIFT; -+ u32 dst_offset = new_mem->mm_node->start << PAGE_SHIFT; ++ u32 src_offset = old_mem->start << PAGE_SHIFT; ++ u32 dst_offset = new_mem->start << PAGE_SHIFT; + u32 page_count = new_mem->num_pages; + int ret; + @@ -1048,7 +1061,41 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.36-rc } static int -@@ -674,7 +799,8 @@ +@@ -606,12 +726,7 @@ + + ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); + out: +- if (tmp_mem.mm_node) { +- spin_lock(&bo->bdev->glob->lru_lock); +- drm_mm_put_block(tmp_mem.mm_node); +- spin_unlock(&bo->bdev->glob->lru_lock); +- } +- ++ ttm_bo_mem_put(bo, &tmp_mem); + return ret; + } + +@@ -644,12 +759,7 @@ + goto out; + + out: +- if (tmp_mem.mm_node) { +- spin_lock(&bo->bdev->glob->lru_lock); +- drm_mm_put_block(tmp_mem.mm_node); +- spin_unlock(&bo->bdev->glob->lru_lock); +- } +- ++ ttm_bo_mem_put(bo, &tmp_mem); + return ret; + } + +@@ -669,12 +779,13 @@ + return 0; + } + +- offset = new_mem->mm_node->start << PAGE_SHIFT; ++ offset = new_mem->start << PAGE_SHIFT; + if (dev_priv->card_type == NV_50) { ret = nv50_mem_vm_bind_linear(dev, offset + dev_priv->vm_vram_base, @@ -1058,7 +1105,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.36-rc offset); if (ret) return ret; -@@ -719,12 +845,6 @@ +@@ -719,12 +830,6 @@ if (ret) return ret; @@ -1071,7 +1118,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.36-rc /* Fake bo copy. */ if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { BUG_ON(bo->mem.mm_node != NULL); -@@ -733,6 +853,12 @@ +@@ -733,6 +838,12 @@ goto out; } @@ -1084,7 +1131,24 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.36-rc /* Hardware assisted copy. */ if (new_mem->mem_type == TTM_PL_SYSTEM) ret = nouveau_bo_move_flipd(bo, evict, intr, no_wait_reserve, no_wait_gpu, new_mem); -@@ -808,7 +934,27 @@ +@@ -783,14 +894,14 @@ + case TTM_PL_TT: + #if __OS_HAS_AGP + if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { +- mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; ++ mem->bus.offset = mem->start << PAGE_SHIFT; + mem->bus.base = dev_priv->gart_info.aper_base; + mem->bus.is_iomem = true; + } + #endif + break; + case TTM_PL_VRAM: +- mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; ++ mem->bus.offset = mem->start << PAGE_SHIFT; + mem->bus.base = pci_resource_start(dev->pdev, 1); + mem->bus.is_iomem = true; + break; +@@ -808,7 +919,39 @@ static int nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) { @@ -1102,7 +1166,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.36-rc + } + + /* make sure bo is in mappable vram */ -+ if (bo->mem.mm_node->start + bo->mem.num_pages < dev_priv->fb_mappable_pages) ++ if (bo->mem.start + bo->mem.num_pages < dev_priv->fb_mappable_pages) + return 0; + + @@ -1110,12 +1174,41 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.36-rc + nvbo->placement.lpfn = dev_priv->fb_mappable_pages; + nouveau_bo_placement_set(nvbo, TTM_PL_VRAM, 0); + return ttm_bo_validate(bo, &nvbo->placement, false, true, false); ++} ++ ++void ++nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) ++{ ++ spin_lock(&nvbo->bo.lock); ++ __nouveau_fence_unref(&nvbo->bo.sync_obj); ++ ++ if (likely(fence)) ++ nvbo->bo.sync_obj = nouveau_fence_ref(fence); ++ ++ spin_unlock(&nvbo->bo.lock); } struct ttm_bo_driver nouveau_bo_driver = { -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_calc.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_calc.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_calc.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_calc.c 2010-10-15 02:04:44.323991737 +0200 +@@ -818,11 +961,11 @@ + .evict_flags = nouveau_bo_evict_flags, + .move = nouveau_bo_move, + .verify_access = nouveau_bo_verify_access, +- .sync_obj_signaled = nouveau_fence_signalled, +- .sync_obj_wait = nouveau_fence_wait, +- .sync_obj_flush = nouveau_fence_flush, +- .sync_obj_unref = nouveau_fence_unref, +- .sync_obj_ref = nouveau_fence_ref, ++ .sync_obj_signaled = __nouveau_fence_signalled, ++ .sync_obj_wait = __nouveau_fence_wait, ++ .sync_obj_flush = __nouveau_fence_flush, ++ .sync_obj_unref = __nouveau_fence_unref, ++ .sync_obj_ref = __nouveau_fence_ref, + .fault_reserve_notify = &nouveau_ttm_fault_reserve_notify, + .io_mem_reserve = &nouveau_ttm_io_mem_reserve, + .io_mem_free = &nouveau_ttm_io_mem_free, +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_calc.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_calc.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_calc.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_calc.c 2010-10-22 23:59:52.474453436 +0200 @@ -198,8 +198,8 @@ struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv_fifo_info fifo_data; @@ -1153,27 +1246,48 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_calc.c linux-2.6.36- } static int -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_channel.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_channel.c 2010-10-15 02:04:44.326991773 +0200 -@@ -70,14 +70,8 @@ - chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT; - } - +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_channel.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_channel.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_channel.c 2010-10-22 23:59:52.475453448 +0200 +@@ -48,14 +48,14 @@ + dev_priv->gart_info.aper_size, + NV_DMA_ACCESS_RO, &pushbuf, + NULL); +- chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT; ++ chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; + } else + if (dev_priv->card_type != NV_04) { + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, + dev_priv->fb_available_size, + NV_DMA_ACCESS_RO, + NV_DMA_TARGET_VIDMEM, &pushbuf); +- chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT; ++ chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; + } else { + /* NV04 cmdbuf hack, from original ddx.. not sure of it's + * exact reason for existing :) PCI access to cmdbuf in +@@ -67,17 +67,11 @@ + dev_priv->fb_available_size, + NV_DMA_ACCESS_RO, + NV_DMA_TARGET_PCI, &pushbuf); +- chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT; +- } +- - ret = nouveau_gpuobj_ref_add(dev, chan, 0, pushbuf, &chan->pushbuf); - if (ret) { - NV_ERROR(dev, "Error referencing pushbuf ctxdma: %d\n", ret); - if (pushbuf != dev_priv->gart_info.sg_ctxdma) - nouveau_gpuobj_del(dev, &pushbuf); - return ret; -- } -- ++ chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; + } + + nouveau_gpuobj_ref(pushbuf, &chan->pushbuf); + nouveau_gpuobj_ref(NULL, &pushbuf); return 0; } -@@ -113,53 +107,54 @@ +@@ -113,53 +107,56 @@ int nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, struct drm_file *file_priv, @@ -1208,7 +1322,8 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. + chan->vram_handle = vram_handle; + chan->gart_handle = gart_handle; + -+ atomic_set(&chan->refcount, 1); ++ kref_init(&chan->ref); ++ atomic_set(&chan->users, 1); + mutex_init(&chan->mutex); + mutex_lock(&chan->mutex); + @@ -1216,7 +1331,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. + spin_lock_irqsave(&dev_priv->channels.lock, flags); + for (chan->id = 0; chan->id < pfifo->channels; chan->id++) { + if (!dev_priv->channels.ptr[chan->id]) { -+ dev_priv->channels.ptr[chan->id] = chan; ++ nouveau_channel_ref(chan, &dev_priv->channels.ptr[chan->id]); break; + } } @@ -1238,6 +1353,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. - chan = dev_priv->fifos[channel]; + NV_DEBUG(dev, "initialising channel %d\n", chan->id); INIT_LIST_HEAD(&chan->nvsw.vbl_wait); ++ INIT_LIST_HEAD(&chan->nvsw.flip); INIT_LIST_HEAD(&chan->fence.pending); - chan->dev = dev; - chan->id = channel; @@ -1257,7 +1373,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. return ret; } -@@ -167,18 +162,18 @@ +@@ -167,18 +164,18 @@ /* Locate channel's user control regs */ if (dev_priv->card_type < NV_40) @@ -1280,7 +1396,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. return -ENOMEM; } chan->user_put = 0x40; -@@ -188,15 +183,15 @@ +@@ -188,15 +185,15 @@ ret = nouveau_notifier_init_channel(chan); if (ret) { NV_ERROR(dev, "ntfy %d\n", ret); @@ -1299,7 +1415,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. return ret; } -@@ -204,7 +199,7 @@ +@@ -204,7 +201,7 @@ ret = nouveau_channel_pushbuf_ctxdma_init(chan); if (ret) { NV_ERROR(dev, "pbctxdma %d\n", ret); @@ -1308,13 +1424,20 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. return ret; } -@@ -214,14 +209,14 @@ +@@ -212,16 +209,18 @@ + pfifo->reassign(dev, false); + /* Create a graphics context for new channel */ - ret = pgraph->create_context(chan); - if (ret) { +- ret = pgraph->create_context(chan); +- if (ret) { - nouveau_channel_free(chan); -+ nouveau_channel_put(&chan); - return ret; +- return ret; ++ if (dev_priv->card_type < NV_50) { ++ ret = pgraph->create_context(chan); ++ if (ret) { ++ nouveau_channel_put(&chan); ++ return ret; ++ } } /* Construct inital RAMFC for new channel */ @@ -1325,7 +1448,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. return ret; } -@@ -229,35 +224,72 @@ +@@ -229,130 +228,187 @@ ret = nouveau_dma_init(chan); if (!ret) @@ -1347,35 +1470,42 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. -/* stops a fifo */ +struct nouveau_channel * ++nouveau_channel_get_unlocked(struct nouveau_channel *ref) ++{ ++ struct nouveau_channel *chan = NULL; ++ ++ if (likely(ref && atomic_inc_not_zero(&ref->users))) ++ nouveau_channel_ref(ref, &chan); ++ ++ return chan; ++} ++ ++struct nouveau_channel * +nouveau_channel_get(struct drm_device *dev, struct drm_file *file_priv, int id) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *chan = ERR_PTR(-ENODEV); ++ struct nouveau_channel *chan; + unsigned long flags; + + spin_lock_irqsave(&dev_priv->channels.lock, flags); -+ chan = dev_priv->channels.ptr[id]; ++ chan = nouveau_channel_get_unlocked(dev_priv->channels.ptr[id]); ++ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + -+ if (unlikely(!chan || atomic_read(&chan->refcount) == 0)) { -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); ++ if (unlikely(!chan)) + return ERR_PTR(-EINVAL); -+ } + + if (unlikely(file_priv && chan->file_priv != file_priv)) { -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); ++ nouveau_channel_put_unlocked(&chan); + return ERR_PTR(-EINVAL); + } + -+ atomic_inc(&chan->refcount); -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); -+ + mutex_lock(&chan->mutex); + return chan; +} + void -nouveau_channel_free(struct nouveau_channel *chan) -+nouveau_channel_put(struct nouveau_channel **pchan) ++nouveau_channel_put_unlocked(struct nouveau_channel **pchan) { + struct nouveau_channel *chan = *pchan; struct drm_device *dev = chan->dev; @@ -1383,30 +1513,36 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; ++ struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt; unsigned long flags; int ret; - NV_INFO(dev, "%s: freeing fifo %d\n", __func__, chan->id); -+ /* unlock the channel */ -+ mutex_unlock(&chan->mutex); -+ + /* decrement the refcount, and we're done if there's still refs */ -+ if (likely(!atomic_dec_and_test(&chan->refcount))) { -+ *pchan = NULL; ++ if (likely(!atomic_dec_and_test(&chan->users))) { ++ nouveau_channel_ref(NULL, pchan); + return; + } + /* noone wants the channel anymore */ + NV_DEBUG(dev, "freeing channel %d\n", chan->id); nouveau_debugfs_channel_fini(chan); -+ *pchan = NULL; - /* Give outstanding push buffers a chance to complete */ + /* give it chance to idle */ nouveau_fence_update(chan); if (chan->fence.sequence != chan->fence.sequence_ack) { struct nouveau_fence *fence = NULL; -@@ -272,13 +304,13 @@ + + ret = nouveau_fence_new(chan, &fence, true); + if (ret == 0) { +- ret = nouveau_fence_wait(fence, NULL, false, false); +- nouveau_fence_unref((void *)&fence); ++ ret = nouveau_fence_wait(fence, false, false); ++ nouveau_fence_unref(&fence); + } + + if (ret) NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id); } @@ -1422,20 +1558,48 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. + /* boot it off the hardware */ pfifo->reassign(dev, false); - /* We want to give pgraph a chance to idle and get rid of all potential -@@ -307,9 +339,17 @@ +- /* We want to give pgraph a chance to idle and get rid of all potential +- * errors. We need to do this before the lock, otherwise the irq handler +- * is unable to process them. ++ /* We want to give pgraph a chance to idle and get rid of all ++ * potential errors. We need to do this without the context ++ * switch lock held, otherwise the irq handler is unable to ++ * process them. + */ + if (pgraph->channel(dev) == chan) + nouveau_wait_for_idle(dev); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +- spin_lock_irqsave(&dev_priv->context_switch_lock, flags); +- +- pgraph->fifo_access(dev, false); +- if (pgraph->channel(dev) == chan) +- pgraph->unload_context(dev); +- pgraph->destroy_context(chan); +- pgraph->fifo_access(dev, true); +- +- if (pfifo->channel_id(dev) == chan->id) { +- pfifo->disable(dev); +- pfifo->unload_context(dev); +- pfifo->enable(dev); +- } ++ /* destroy the engine specific contexts */ + pfifo->destroy_context(chan); ++ pgraph->destroy_context(chan); ++ if (pcrypt->destroy_context) ++ pcrypt->destroy_context(chan); -- /* Release the channel's resources */ -- nouveau_gpuobj_ref_del(dev, &chan->pushbuf); + pfifo->reassign(dev, true); + +- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + /* aside from its resources, the channel should now be dead, + * remove it from the channel list + */ + spin_lock_irqsave(&dev_priv->channels.lock, flags); -+ dev_priv->channels.ptr[chan->id] = NULL; ++ nouveau_channel_ref(NULL, &dev_priv->channels.ptr[chan->id]); + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); -+ + +- /* Release the channel's resources */ +- nouveau_gpuobj_ref_del(dev, &chan->pushbuf); + /* destroy any resources the channel owned */ + nouveau_gpuobj_ref(NULL, &chan->pushbuf); if (chan->pushbuf_bo) { @@ -1443,7 +1607,25 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. nouveau_bo_unpin(chan->pushbuf_bo); nouveau_bo_ref(NULL, &chan->pushbuf_bo); } -@@ -318,7 +358,6 @@ + nouveau_gpuobj_channel_takedown(chan); + nouveau_notifier_takedown_channel(chan); ++ ++ nouveau_channel_ref(NULL, pchan); ++} ++ ++void ++nouveau_channel_put(struct nouveau_channel **pchan) ++{ ++ mutex_unlock(&(*pchan)->mutex); ++ nouveau_channel_put_unlocked(pchan); ++} ++ ++static void ++nouveau_channel_del(struct kref *ref) ++{ ++ struct nouveau_channel *chan = ++ container_of(ref, struct nouveau_channel, ref); ++ if (chan->user) iounmap(chan->user); @@ -1451,7 +1633,22 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. kfree(chan); } -@@ -328,31 +367,20 @@ ++void ++nouveau_channel_ref(struct nouveau_channel *chan, ++ struct nouveau_channel **pchan) ++{ ++ if (chan) ++ kref_get(&chan->ref); ++ ++ if (*pchan) ++ kref_put(&(*pchan)->ref, nouveau_channel_del); ++ ++ *pchan = chan; ++} ++ + /* cleans up all the fifos from file_priv */ + void + nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->engine; @@ -1467,7 +1664,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. - if (chan && chan->file_priv == file_priv) - nouveau_channel_free(chan); -+ atomic_dec(&chan->refcount); ++ atomic_dec(&chan->users); + nouveau_channel_put(&chan); } } @@ -1489,7 +1686,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. /*********************************** * ioctls wrapping the functions -@@ -400,24 +428,26 @@ +@@ -400,24 +456,26 @@ /* Named memory object area */ ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem, &init->notifier_handle); @@ -1500,7 +1697,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. - return 0; + if (ret == 0) -+ atomic_inc(&chan->refcount); /* userspace reference */ ++ atomic_inc(&chan->users); /* userspace reference */ + nouveau_channel_put(&chan); + return ret; } @@ -1519,12 +1716,12 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. + return PTR_ERR(chan); - nouveau_channel_free(chan); -+ atomic_dec(&chan->refcount); ++ atomic_dec(&chan->users); + nouveau_channel_put(&chan); return 0; } -@@ -426,18 +456,18 @@ +@@ -426,18 +484,18 @@ ***********************************/ struct drm_ioctl_desc nouveau_ioctls[] = { @@ -1555,9 +1752,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. }; int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls); -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_connector.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_connector.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_connector.c 2010-10-15 02:04:44.327991785 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_connector.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.c 2010-10-22 23:59:52.476453460 +0200 @@ -76,6 +76,22 @@ return NULL; } @@ -1618,7 +1815,32 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2. static void nouveau_connector_set_encoder(struct drm_connector *connector, struct nouveau_encoder *nv_encoder) -@@ -225,6 +271,12 @@ +@@ -167,6 +213,24 @@ + } + } + ++static bool ++nouveau_connector_poll_allowed(struct drm_connector *connector) ++{ ++ struct drm_device *dev = connector->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct drm_crtc *crtc; ++ bool spare_crtc = false; ++ ++ if (dev_priv->card_type >= NV_50) { ++ return true; ++ } else { ++ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) ++ spare_crtc |= !crtc->enabled; ++ ++ return spare_crtc; ++ } ++} ++ + static enum drm_connector_status + nouveau_connector_detect(struct drm_connector *connector, bool force) + { +@@ -225,11 +289,18 @@ return connector_status_connected; } @@ -1631,7 +1853,14 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2. detect_analog: nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); if (!nv_encoder && !nouveau_tv_disable) -@@ -589,11 +641,28 @@ + nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); +- if (nv_encoder) { ++ if (nv_encoder && ++ (force || nouveau_connector_poll_allowed(connector))) { + struct drm_encoder *encoder = to_drm_encoder(nv_encoder); + struct drm_encoder_helper_funcs *helper = + encoder->helper_private; +@@ -589,11 +660,28 @@ return ret; } @@ -1661,7 +1890,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2. struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; struct drm_encoder *encoder = to_drm_encoder(nv_encoder); -@@ -611,11 +680,9 @@ +@@ -611,11 +699,9 @@ max_clock = 400000; break; case OUTPUT_TMDS: @@ -1676,7 +1905,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2. break; case OUTPUT_ANALOG: max_clock = nv_encoder->dcb->crtconf.maxfreq; -@@ -630,7 +697,7 @@ +@@ -630,7 +716,7 @@ else max_clock = nv_encoder->dp.link_nr * 162000; @@ -1685,20 +1914,94 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2. break; default: BUG_ON(1); -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_connector.h linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_connector.h ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_connector.h 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_connector.h 2010-10-15 02:04:44.329991810 +0200 -@@ -55,4 +55,7 @@ - void - nouveau_connector_set_polling(struct drm_connector *); +@@ -657,44 +743,6 @@ + return NULL; + } +-void +-nouveau_connector_set_polling(struct drm_connector *connector) +-{ +- struct drm_device *dev = connector->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct drm_crtc *crtc; +- bool spare_crtc = false; +- +- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) +- spare_crtc |= !crtc->enabled; +- +- connector->polled = 0; +- +- switch (connector->connector_type) { +- case DRM_MODE_CONNECTOR_VGA: +- case DRM_MODE_CONNECTOR_TV: +- if (dev_priv->card_type >= NV_50 || +- (nv_gf4_disp_arch(dev) && spare_crtc)) +- connector->polled = DRM_CONNECTOR_POLL_CONNECT; +- break; +- +- case DRM_MODE_CONNECTOR_DVII: +- case DRM_MODE_CONNECTOR_DVID: +- case DRM_MODE_CONNECTOR_HDMIA: +- case DRM_MODE_CONNECTOR_DisplayPort: +- case DRM_MODE_CONNECTOR_eDP: +- if (dev_priv->card_type >= NV_50) +- connector->polled = DRM_CONNECTOR_POLL_HPD; +- else if (connector->connector_type == DRM_MODE_CONNECTOR_DVID || +- spare_crtc) +- connector->polled = DRM_CONNECTOR_POLL_CONNECT; +- break; +- +- default: +- break; +- } +-} +- + static const struct drm_connector_helper_funcs + nouveau_connector_helper_funcs = { + .get_modes = nouveau_connector_get_modes, +@@ -825,6 +873,9 @@ + case DCB_CONNECTOR_TV_1: + case DCB_CONNECTOR_TV_3: + nv_connector->scaling_mode = DRM_MODE_SCALE_NONE; ++ ++ if (nv_gf4_disp_arch(dev)) ++ connector->polled = DRM_CONNECTOR_POLL_CONNECT; + break; + default: + nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN; +@@ -836,11 +887,14 @@ + dev->mode_config.dithering_mode_property, + nv_connector->use_dithering ? + DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF); ++ ++ if (dev_priv->card_type >= NV_50) ++ connector->polled = DRM_CONNECTOR_POLL_HPD; ++ else ++ connector->polled = DRM_CONNECTOR_POLL_CONNECT; + break; + } + +- nouveau_connector_set_polling(connector); +- + drm_sysfs_connector_add(connector); + dcb->drm = connector; + return dcb->drm; +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_connector.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.h +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_connector.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.h 2010-10-22 23:59:52.477453472 +0200 +@@ -52,7 +52,7 @@ + struct drm_connector * + nouveau_connector_create(struct drm_device *, int index); + +-void +-nouveau_connector_set_polling(struct drm_connector *); +int +nouveau_connector_bpp(struct drm_connector *); -+ + #endif /* __NOUVEAU_CONNECTOR_H__ */ -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_debugfs.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_debugfs.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_debugfs.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_debugfs.c 2010-10-15 02:04:44.330991823 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_debugfs.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_debugfs.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_debugfs.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_debugfs.c 2010-10-22 23:59:52.478453484 +0200 @@ -157,7 +157,23 @@ return 0; } @@ -1723,9 +2026,230 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_debugfs.c linux-2.6. { "chipset", nouveau_debugfs_chipset_info, 0, NULL }, { "memory", nouveau_debugfs_memory_info, 0, NULL }, { "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL }, -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_dma.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_dma.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_dma.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_dma.c 2010-10-15 02:04:44.331991836 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_display.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_display.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_display.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_display.c 2010-10-22 23:59:52.479453496 +0200 +@@ -29,6 +29,9 @@ + #include "nouveau_drv.h" + #include "nouveau_fb.h" + #include "nouveau_fbcon.h" ++#include "nouveau_hw.h" ++#include "nouveau_crtc.h" ++#include "nouveau_dma.h" + + static void + nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) +@@ -104,3 +107,207 @@ + .output_poll_changed = nouveau_fbcon_output_poll_changed, + }; + ++int ++nouveau_vblank_enable(struct drm_device *dev, int crtc) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ if (dev_priv->card_type >= NV_50) ++ nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, 0, ++ NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc)); ++ else ++ NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, ++ NV_PCRTC_INTR_0_VBLANK); ++ ++ return 0; ++} ++ ++void ++nouveau_vblank_disable(struct drm_device *dev, int crtc) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ if (dev_priv->card_type >= NV_50) ++ nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, ++ NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0); ++ else ++ NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0); ++} ++ ++static int ++nouveau_page_flip_reserve(struct nouveau_bo *old_bo, ++ struct nouveau_bo *new_bo) ++{ ++ int ret; ++ ++ ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM); ++ if (ret) ++ return ret; ++ ++ ret = ttm_bo_reserve(&new_bo->bo, false, false, false, 0); ++ if (ret) ++ goto fail; ++ ++ ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0); ++ if (ret) ++ goto fail_unreserve; ++ ++ return 0; ++ ++fail_unreserve: ++ ttm_bo_unreserve(&new_bo->bo); ++fail: ++ nouveau_bo_unpin(new_bo); ++ return ret; ++} ++ ++static void ++nouveau_page_flip_unreserve(struct nouveau_bo *old_bo, ++ struct nouveau_bo *new_bo, ++ struct nouveau_fence *fence) ++{ ++ nouveau_bo_fence(new_bo, fence); ++ ttm_bo_unreserve(&new_bo->bo); ++ ++ nouveau_bo_fence(old_bo, fence); ++ ttm_bo_unreserve(&old_bo->bo); ++ ++ nouveau_bo_unpin(old_bo); ++} ++ ++static int ++nouveau_page_flip_emit(struct nouveau_channel *chan, ++ struct nouveau_bo *old_bo, ++ struct nouveau_bo *new_bo, ++ struct nouveau_page_flip_state *s, ++ struct nouveau_fence **pfence) ++{ ++ struct drm_device *dev = chan->dev; ++ unsigned long flags; ++ int ret; ++ ++ /* Queue it to the pending list */ ++ spin_lock_irqsave(&dev->event_lock, flags); ++ list_add_tail(&s->head, &chan->nvsw.flip); ++ spin_unlock_irqrestore(&dev->event_lock, flags); ++ ++ /* Synchronize with the old framebuffer */ ++ ret = nouveau_fence_sync(old_bo->bo.sync_obj, chan); ++ if (ret) ++ goto fail; ++ ++ /* Emit the pageflip */ ++ ret = RING_SPACE(chan, 2); ++ if (ret) ++ goto fail; ++ ++ BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); ++ OUT_RING(chan, 0); ++ FIRE_RING(chan); ++ ++ ret = nouveau_fence_new(chan, pfence, true); ++ if (ret) ++ goto fail; ++ ++ return 0; ++fail: ++ spin_lock_irqsave(&dev->event_lock, flags); ++ list_del(&s->head); ++ spin_unlock_irqrestore(&dev->event_lock, flags); ++ return ret; ++} ++ ++int ++nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, ++ struct drm_pending_vblank_event *event) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo; ++ struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; ++ struct nouveau_page_flip_state *s; ++ struct nouveau_channel *chan; ++ struct nouveau_fence *fence; ++ int ret; ++ ++ if (dev_priv->engine.graph.accel_blocked) ++ return -ENODEV; ++ ++ s = kzalloc(sizeof(*s), GFP_KERNEL); ++ if (!s) ++ return -ENOMEM; ++ ++ /* Don't let the buffers go away while we flip */ ++ ret = nouveau_page_flip_reserve(old_bo, new_bo); ++ if (ret) ++ goto fail_free; ++ ++ /* Initialize a page flip struct */ ++ *s = (struct nouveau_page_flip_state) ++ { { }, s->event, nouveau_crtc(crtc)->index, ++ fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y, ++ new_bo->bo.offset }; ++ ++ /* Choose the channel the flip will be handled in */ ++ chan = nouveau_fence_channel(new_bo->bo.sync_obj); ++ if (!chan) ++ chan = nouveau_channel_get_unlocked(dev_priv->channel); ++ mutex_lock(&chan->mutex); ++ ++ /* Emit a page flip */ ++ ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); ++ nouveau_channel_put(&chan); ++ if (ret) ++ goto fail_unreserve; ++ ++ /* Update the crtc struct and cleanup */ ++ crtc->fb = fb; ++ ++ nouveau_page_flip_unreserve(old_bo, new_bo, fence); ++ nouveau_fence_unref(&fence); ++ return 0; ++ ++fail_unreserve: ++ nouveau_page_flip_unreserve(old_bo, new_bo, NULL); ++fail_free: ++ kfree(s); ++ return ret; ++} ++ ++int ++nouveau_finish_page_flip(struct nouveau_channel *chan, ++ struct nouveau_page_flip_state *ps) ++{ ++ struct drm_device *dev = chan->dev; ++ struct nouveau_page_flip_state *s; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dev->event_lock, flags); ++ ++ if (list_empty(&chan->nvsw.flip)) { ++ NV_ERROR(dev, "Unexpected pageflip in channel %d.\n", chan->id); ++ spin_unlock_irqrestore(&dev->event_lock, flags); ++ return -EINVAL; ++ } ++ ++ s = list_first_entry(&chan->nvsw.flip, ++ struct nouveau_page_flip_state, head); ++ if (s->event) { ++ struct drm_pending_vblank_event *e = s->event; ++ struct timeval now; ++ ++ do_gettimeofday(&now); ++ e->event.sequence = 0; ++ e->event.tv_sec = now.tv_sec; ++ e->event.tv_usec = now.tv_usec; ++ list_add_tail(&e->base.link, &e->base.file_priv->event_list); ++ wake_up_interruptible(&e->base.file_priv->event_wait); ++ } ++ ++ list_del(&s->head); ++ *ps = *s; ++ kfree(s); ++ ++ spin_unlock_irqrestore(&dev->event_lock, flags); ++ return 0; ++} +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_dma.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_dma.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.c 2010-10-22 23:59:52.480453509 +0200 @@ -28,6 +28,7 @@ #include "drm.h" #include "nouveau_drv.h" @@ -1800,9 +2324,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_dma.c linux-2.6.36-r } return 0; -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_dma.h linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_dma.h ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_dma.h 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_dma.h 2010-10-15 02:04:44.333991860 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_dma.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.h +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_dma.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.h 2010-10-22 23:59:52.495453696 +0200 @@ -72,6 +72,7 @@ NvGdiRect = 0x8000000c, NvImageBlit = 0x8000000d, @@ -1811,9 +2335,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_dma.h linux-2.6.36-r /* G80+ display objects */ NvEvoVRAM = 0x01000000, -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_dp.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_dp.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_dp.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_dp.c 2010-10-15 02:04:44.334991872 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_dp.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_dp.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_dp.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_dp.c 2010-10-22 23:59:52.495453696 +0200 @@ -317,7 +317,8 @@ return false; @@ -1848,9 +2372,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_dp.c linux-2.6.36-rc NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n", nv_rd32(dev, NV50_AUXCH_CTRL(index))); ret = -EBUSY; -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_drv.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_drv.c 2010-10-15 02:04:44.336991898 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_drv.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.c 2010-10-22 23:59:52.496453708 +0200 @@ -31,13 +31,14 @@ #include "nouveau_hw.h" #include "nouveau_fb.h" @@ -1880,7 +2404,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.36-r MODULE_PARM_DESC(override_conntype, "Ignore DCB connector type"); int nouveau_override_conntype = 0; module_param_named(override_conntype, nouveau_override_conntype, int, 0400); -@@ -102,6 +107,14 @@ +@@ -102,6 +107,18 @@ int nouveau_reg_debug; module_param_named(reg_debug, nouveau_reg_debug, int, 0600); @@ -1891,11 +2415,15 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.36-r +MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)\n"); +int nouveau_perflvl_wr; +module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); ++ ++MODULE_PARM_DESC(msi, "Enable MSI (default: off)\n"); ++int nouveau_msi; ++module_param_named(msi, nouveau_msi, int, 0400); + int nouveau_fbpercrtc; #if 0 module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400); -@@ -182,9 +195,8 @@ +@@ -182,15 +199,14 @@ for (i = 0; i < pfifo->channels; i++) { struct nouveau_fence *fence = NULL; @@ -1907,7 +2435,15 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.36-r continue; ret = nouveau_fence_new(chan, &fence, true); -@@ -271,6 +283,8 @@ + if (ret == 0) { +- ret = nouveau_fence_wait(fence, NULL, false, false); +- nouveau_fence_unref((void *)&fence); ++ ret = nouveau_fence_wait(fence, false, false); ++ nouveau_fence_unref(&fence); + } + + if (ret) { +@@ -271,6 +287,8 @@ if (ret) return ret; @@ -1916,7 +2452,15 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.36-r if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { ret = nouveau_mem_init_agp(dev); if (ret) { -@@ -298,7 +312,7 @@ +@@ -285,6 +303,7 @@ + engine->timer.init(dev); + engine->fb.init(dev); + engine->graph.init(dev); ++ engine->crypt.init(dev); + engine->fifo.init(dev); + + NV_INFO(dev, "Restoring GPU objects...\n"); +@@ -298,7 +317,7 @@ int j; for (i = 0; i < dev_priv->engine.fifo.channels; i++) { @@ -1925,7 +2469,25 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.36-r if (!chan || !chan->pushbuf_bo) continue; -@@ -434,6 +448,12 @@ +@@ -378,6 +397,9 @@ + .irq_postinstall = nouveau_irq_postinstall, + .irq_uninstall = nouveau_irq_uninstall, + .irq_handler = nouveau_irq_handler, ++ .get_vblank_counter = drm_vblank_count, ++ .enable_vblank = nouveau_vblank_enable, ++ .disable_vblank = nouveau_vblank_disable, + .reclaim_buffers = drm_core_reclaim_buffers, + .get_map_ofs = drm_core_get_map_ofs, + .get_reg_ofs = drm_core_get_reg_ofs, +@@ -390,6 +412,7 @@ + .mmap = nouveau_ttm_mmap, + .poll = drm_poll, + .fasync = drm_fasync, ++ .read = drm_read, + #if defined(CONFIG_COMPAT) + .compat_ioctl = nouveau_compat_ioctl, + #endif +@@ -434,6 +457,12 @@ if (!nouveau_modeset) return 0; @@ -1938,9 +2500,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.36-r nouveau_register_dsm_handler(); return drm_init(&driver); } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_drv.h ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_drv.h 2010-10-15 02:04:44.340991947 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.h +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_drv.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.h 2010-10-22 23:59:52.499453744 +0200 @@ -96,10 +96,12 @@ struct nouveau_tile_reg *tile; @@ -1955,8 +2517,17 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r static inline struct nouveau_bo * nouveau_bo(struct ttm_buffer_object *bo) { -@@ -133,22 +135,24 @@ - #define NVOBJ_ENGINE_DISPLAY 2 +@@ -130,25 +132,32 @@ + + #define NVOBJ_ENGINE_SW 0 + #define NVOBJ_ENGINE_GR 1 +-#define NVOBJ_ENGINE_DISPLAY 2 ++#define NVOBJ_ENGINE_PPP 2 ++#define NVOBJ_ENGINE_COPY 3 ++#define NVOBJ_ENGINE_VP 4 ++#define NVOBJ_ENGINE_CRYPT 5 ++#define NVOBJ_ENGINE_BSP 6 ++#define NVOBJ_ENGINE_DISPLAY 0xcafe0001 #define NVOBJ_ENGINE_INT 0xdeadbeef -#define NVOBJ_FLAG_ALLOW_NO_REFS (1 << 0) @@ -1985,7 +2556,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r uint32_t engine; uint32_t class; -@@ -157,20 +161,13 @@ +@@ -157,20 +166,24 @@ void *priv; }; @@ -1997,19 +2568,28 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r - - struct nouveau_channel *channel; - int handle; --}; -- ++struct nouveau_page_flip_state { ++ struct list_head head; ++ struct drm_pending_vblank_event *event; ++ int crtc, bpp, pitch, x, y; ++ uint64_t offset; + }; + struct nouveau_channel { struct drm_device *dev; int id; -+ atomic_t refcount; ++ /* references to the channel data structure */ ++ struct kref ref; ++ /* users of the hardware channel resources, the hardware ++ * context will be kicked off when it reaches zero. */ ++ atomic_t users; + struct mutex mutex; + /* owner of this fifo */ struct drm_file *file_priv; /* mapping of the fifo itself */ -@@ -192,33 +189,32 @@ +@@ -192,33 +205,33 @@ } fence; /* DMA push buffer */ @@ -2034,6 +2614,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r /* XXX may be merge 2 pointers as private data ??? */ - struct nouveau_gpuobj_ref *ramin_grctx; + struct nouveau_gpuobj *ramin_grctx; ++ struct nouveau_gpuobj *crypt_ctx; void *pgraph_ctx; /* NV50 VM */ @@ -2055,7 +2636,24 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r /* GPU object info for stuff used in-kernel (mm_enabled) */ uint32_t m2mf_ntfy; -@@ -296,7 +292,7 @@ +@@ -247,6 +260,7 @@ + uint32_t vblsem_offset; + uint32_t vblsem_rval; + struct list_head vbl_wait; ++ struct list_head flip; + } nvsw; + + struct { +@@ -265,7 +279,7 @@ + void (*resume)(struct drm_device *dev); + + int (*populate)(struct drm_device *, struct nouveau_gpuobj *, +- uint32_t *size); ++ u32 *size, u32 align); + void (*clear)(struct drm_device *, struct nouveau_gpuobj *); + int (*bind)(struct drm_device *, struct nouveau_gpuobj *); + int (*unbind)(struct drm_device *, struct nouveau_gpuobj *); +@@ -296,7 +310,7 @@ struct nouveau_fifo_engine { int channels; @@ -2064,7 +2662,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r int cur_playlist; int (*init)(struct drm_device *); -@@ -305,7 +301,6 @@ +@@ -305,7 +319,6 @@ void (*disable)(struct drm_device *); void (*enable)(struct drm_device *); bool (*reassign)(struct drm_device *, bool enable); @@ -2072,7 +2670,26 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r bool (*cache_pull)(struct drm_device *dev, bool enable); int (*channel_id)(struct drm_device *); -@@ -334,7 +329,7 @@ +@@ -316,25 +329,13 @@ + int (*unload_context)(struct drm_device *); + }; + +-struct nouveau_pgraph_object_method { +- int id; +- int (*exec)(struct nouveau_channel *chan, int grclass, int mthd, +- uint32_t data); +-}; +- +-struct nouveau_pgraph_object_class { +- int id; +- bool software; +- struct nouveau_pgraph_object_method *methods; +-}; +- + struct nouveau_pgraph_engine { +- struct nouveau_pgraph_object_class *grclass; + bool accel_blocked; ++ bool registered; int grctx_size; /* NV2x/NV3x context table (0x400780) */ @@ -2081,7 +2698,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r int (*init)(struct drm_device *); void (*takedown)(struct drm_device *); -@@ -369,6 +364,92 @@ +@@ -369,6 +370,101 @@ void (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on); }; @@ -2170,19 +2787,29 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r + int (*fanspeed_set)(struct drm_device *, int fanspeed); + int (*temp_get)(struct drm_device *); +}; ++ ++struct nouveau_crypt_engine { ++ bool registered; ++ ++ int (*init)(struct drm_device *); ++ void (*takedown)(struct drm_device *); ++ int (*create_context)(struct nouveau_channel *); ++ void (*destroy_context)(struct nouveau_channel *); ++}; + struct nouveau_engine { struct nouveau_instmem_engine instmem; struct nouveau_mc_engine mc; -@@ -378,6 +459,7 @@ +@@ -378,6 +474,8 @@ struct nouveau_fifo_engine fifo; struct nouveau_display_engine display; struct nouveau_gpio_engine gpio; + struct nouveau_pm_engine pm; ++ struct nouveau_crypt_engine crypt; }; struct nouveau_pll_vals { -@@ -409,13 +491,13 @@ +@@ -409,13 +507,13 @@ }; struct nv04_crtc_reg { @@ -2198,7 +2825,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r /* PCRTC regs */ uint32_t fb_start; -@@ -463,43 +545,9 @@ +@@ -463,43 +561,9 @@ }; struct nv04_mode_state { @@ -2243,7 +2870,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r }; enum nouveau_card_type { -@@ -522,8 +570,14 @@ +@@ -522,11 +586,20 @@ int flags; void __iomem *mmio; @@ -2256,10 +2883,16 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r + bool ramin_available; + struct drm_mm ramin_heap; + struct list_head gpuobj_list; ++ struct list_head classes; struct nouveau_bo *vga_ram; -@@ -540,8 +594,16 @@ ++ /* interrupt handling */ ++ bool msi_enabled; + struct workqueue_struct *wq; + struct work_struct irq_work; + struct work_struct hpd_work; +@@ -540,8 +613,16 @@ atomic_t validate_sequence; } ttm; @@ -2278,7 +2911,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r struct nouveau_engine engine; struct nouveau_channel *channel; -@@ -550,15 +612,11 @@ +@@ -550,15 +631,11 @@ spinlock_t context_switch_lock; /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ @@ -2298,7 +2931,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r struct { enum { -@@ -576,14 +634,12 @@ +@@ -576,14 +653,12 @@ } gart_info; /* nv10-nv40 tiling regions */ @@ -2315,7 +2948,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r uint64_t fb_phys; uint64_t fb_available_size; -@@ -600,10 +656,6 @@ +@@ -600,10 +675,6 @@ struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; int vm_vram_pt_nr; @@ -2326,7 +2959,15 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r struct nvbios vbios; struct nv04_mode_state mode_reg; -@@ -634,6 +686,12 @@ +@@ -619,6 +690,7 @@ + struct backlight_device *backlight; + + struct nouveau_channel *evo; ++ u32 evo_alloc; + struct { + struct dcb_entry *dcb; + u16 script; +@@ -634,6 +706,12 @@ }; static inline struct drm_nouveau_private * @@ -2339,7 +2980,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r nouveau_bdev(struct ttm_bo_device *bd) { return container_of(bd, struct drm_nouveau_private, ttm.bdev); -@@ -658,18 +716,8 @@ +@@ -658,18 +736,8 @@ return 0; } @@ -2359,7 +3000,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r extern int nouveau_duallink; extern int nouveau_uscript_lvds; extern int nouveau_uscript_tmds; -@@ -683,7 +731,10 @@ +@@ -683,7 +751,11 @@ extern int nouveau_ignorelid; extern int nouveau_nofbaccel; extern int nouveau_noaccel; @@ -2367,10 +3008,11 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r extern int nouveau_override_conntype; +extern char *nouveau_perflvl; +extern int nouveau_perflvl_wr; ++extern int nouveau_msi; extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state); extern int nouveau_pci_resume(struct pci_dev *pdev); -@@ -704,8 +755,10 @@ +@@ -704,8 +776,10 @@ extern int nouveau_card_init(struct drm_device *); /* nouveau_mem.c */ @@ -2383,7 +3025,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r 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 *); -@@ -737,19 +790,18 @@ +@@ -737,46 +811,54 @@ extern struct drm_ioctl_desc nouveau_ioctls[]; extern int nouveau_max_ioctl; extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *); @@ -2395,10 +3037,27 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r uint32_t fb_ctxdma, uint32_t tt_ctxdma); -extern void nouveau_channel_free(struct nouveau_channel *); +extern struct nouveau_channel * ++nouveau_channel_get_unlocked(struct nouveau_channel *); ++extern struct nouveau_channel * +nouveau_channel_get(struct drm_device *, struct drm_file *, int id); ++extern void nouveau_channel_put_unlocked(struct nouveau_channel **); +extern void nouveau_channel_put(struct nouveau_channel **); ++extern void nouveau_channel_ref(struct nouveau_channel *chan, ++ struct nouveau_channel **pchan); /* nouveau_object.c */ ++#define NVOBJ_CLASS(d,c,e) do { \ ++ int ret = nouveau_gpuobj_class_new((d), (c), NVOBJ_ENGINE_##e); \ ++ if (ret) \ ++ return ret; \ ++} while(0) ++ ++#define NVOBJ_MTHD(d,c,m,e) do { \ ++ int ret = nouveau_gpuobj_mthd_new((d), (c), (m), (e)); \ ++ if (ret) \ ++ return ret; \ ++} while(0) ++ extern int nouveau_gpuobj_early_init(struct drm_device *); extern int nouveau_gpuobj_init(struct drm_device *); extern void nouveau_gpuobj_takedown(struct drm_device *); @@ -2406,7 +3065,14 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r extern int nouveau_gpuobj_suspend(struct drm_device *dev); extern void nouveau_gpuobj_suspend_cleanup(struct drm_device *dev); extern void nouveau_gpuobj_resume(struct drm_device *dev); -@@ -759,24 +811,11 @@ ++extern int nouveau_gpuobj_class_new(struct drm_device *, u32 class, u32 eng); ++extern int nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd, ++ int (*exec)(struct nouveau_channel *, ++ u32 class, u32 mthd, u32 data)); ++extern int nouveau_gpuobj_mthd_call(struct nouveau_channel *, u32, u32, u32); + extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, + uint32_t vram_h, uint32_t tt_h); + extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *); extern int nouveau_gpuobj_new(struct drm_device *, struct nouveau_channel *, uint32_t size, int align, uint32_t flags, struct nouveau_gpuobj **); @@ -2436,7 +3102,24 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class, uint64_t offset, uint64_t size, int access, int target, struct nouveau_gpuobj **); -@@ -879,6 +918,7 @@ +@@ -786,14 +868,14 @@ + uint32_t *o_ret); + extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class, + struct nouveau_gpuobj **); +-extern int nouveau_gpuobj_sw_new(struct nouveau_channel *, int class, +- struct nouveau_gpuobj **); + extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data, + struct drm_file *); + extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data, + struct drm_file *); + + /* nouveau_irq.c */ ++extern int nouveau_irq_init(struct drm_device *); ++extern void nouveau_irq_fini(struct drm_device *); + extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); + extern void nouveau_irq_preinstall(struct drm_device *); + extern int nouveau_irq_postinstall(struct drm_device *); +@@ -879,6 +961,7 @@ enum dcb_gpio_tag); extern struct dcb_connector_table_entry * nouveau_bios_connector_entry(struct drm_device *, int index); @@ -2444,7 +3127,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r extern int get_pll_limits(struct drm_device *, uint32_t limit_match, struct pll_lims *); extern int nouveau_bios_run_display_table(struct drm_device *, -@@ -925,6 +965,10 @@ +@@ -925,6 +1008,10 @@ 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); @@ -2455,7 +3138,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r /* nv50_fb.c */ extern int nv50_fb_init(struct drm_device *); -@@ -939,7 +983,6 @@ +@@ -939,7 +1026,6 @@ extern void nv04_fifo_disable(struct drm_device *); extern void nv04_fifo_enable(struct drm_device *); extern bool nv04_fifo_reassign(struct drm_device *, bool); @@ -2463,7 +3146,22 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r extern bool nv04_fifo_cache_pull(struct drm_device *, bool); extern int nv04_fifo_channel_id(struct drm_device *); extern int nv04_fifo_create_context(struct nouveau_channel *); -@@ -977,7 +1020,6 @@ +@@ -951,14 +1037,12 @@ + extern int nv10_fifo_init(struct drm_device *); + extern int nv10_fifo_channel_id(struct drm_device *); + extern int nv10_fifo_create_context(struct nouveau_channel *); +-extern void nv10_fifo_destroy_context(struct nouveau_channel *); + extern int nv10_fifo_load_context(struct nouveau_channel *); + extern int nv10_fifo_unload_context(struct drm_device *); + + /* nv40_fifo.c */ + extern int nv40_fifo_init(struct drm_device *); + extern int nv40_fifo_create_context(struct nouveau_channel *); +-extern void nv40_fifo_destroy_context(struct nouveau_channel *); + extern int nv40_fifo_load_context(struct nouveau_channel *); + extern int nv40_fifo_unload_context(struct drm_device *); + +@@ -977,7 +1061,6 @@ extern void nvc0_fifo_disable(struct drm_device *); extern void nvc0_fifo_enable(struct drm_device *); extern bool nvc0_fifo_reassign(struct drm_device *, bool); @@ -2471,11 +3169,96 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r extern bool nvc0_fifo_cache_pull(struct drm_device *, bool); extern int nvc0_fifo_channel_id(struct drm_device *); extern int nvc0_fifo_create_context(struct nouveau_channel *); -@@ -1165,19 +1207,24 @@ +@@ -986,7 +1069,6 @@ + extern int nvc0_fifo_unload_context(struct drm_device *); + + /* nv04_graph.c */ +-extern struct nouveau_pgraph_object_class nv04_graph_grclass[]; + extern int nv04_graph_init(struct drm_device *); + extern void nv04_graph_takedown(struct drm_device *); + extern void nv04_graph_fifo_access(struct drm_device *, bool); +@@ -996,9 +1078,10 @@ + extern int nv04_graph_load_context(struct nouveau_channel *); + extern int nv04_graph_unload_context(struct drm_device *); + extern void nv04_graph_context_switch(struct drm_device *); ++extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data); + + /* nv10_graph.c */ +-extern struct nouveau_pgraph_object_class nv10_graph_grclass[]; + extern int nv10_graph_init(struct drm_device *); + extern void nv10_graph_takedown(struct drm_device *); + extern struct nouveau_channel *nv10_graph_channel(struct drm_device *); +@@ -1011,8 +1094,6 @@ + uint32_t, uint32_t); + + /* nv20_graph.c */ +-extern struct nouveau_pgraph_object_class nv20_graph_grclass[]; +-extern struct nouveau_pgraph_object_class nv30_graph_grclass[]; + extern int nv20_graph_create_context(struct nouveau_channel *); + extern void nv20_graph_destroy_context(struct nouveau_channel *); + extern int nv20_graph_load_context(struct nouveau_channel *); +@@ -1024,7 +1105,6 @@ + uint32_t, uint32_t); + + /* nv40_graph.c */ +-extern struct nouveau_pgraph_object_class nv40_graph_grclass[]; + extern int nv40_graph_init(struct drm_device *); + extern void nv40_graph_takedown(struct drm_device *); + extern struct nouveau_channel *nv40_graph_channel(struct drm_device *); +@@ -1037,7 +1117,6 @@ + uint32_t, uint32_t); + + /* nv50_graph.c */ +-extern struct nouveau_pgraph_object_class nv50_graph_grclass[]; + extern int nv50_graph_init(struct drm_device *); + extern void nv50_graph_takedown(struct drm_device *); + extern void nv50_graph_fifo_access(struct drm_device *, bool); +@@ -1059,13 +1138,19 @@ + extern int nvc0_graph_load_context(struct nouveau_channel *); + extern int nvc0_graph_unload_context(struct drm_device *); + ++/* nv84_crypt.c */ ++extern int nv84_crypt_init(struct drm_device *dev); ++extern void nv84_crypt_fini(struct drm_device *dev); ++extern int nv84_crypt_create_context(struct nouveau_channel *); ++extern void nv84_crypt_destroy_context(struct nouveau_channel *); ++ + /* nv04_instmem.c */ + extern int nv04_instmem_init(struct drm_device *); + extern void nv04_instmem_takedown(struct drm_device *); + extern int nv04_instmem_suspend(struct drm_device *); + extern void nv04_instmem_resume(struct drm_device *); + extern int nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, +- uint32_t *size); ++ u32 *size, u32 align); + extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); + extern int nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); + extern int nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); +@@ -1077,7 +1162,7 @@ + extern int nv50_instmem_suspend(struct drm_device *); + extern void nv50_instmem_resume(struct drm_device *); + extern int nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, +- uint32_t *size); ++ u32 *size, u32 align); + extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); + extern int nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); + extern int nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); +@@ -1091,7 +1176,7 @@ + extern int nvc0_instmem_suspend(struct drm_device *); + extern void nvc0_instmem_resume(struct drm_device *); + extern int nvc0_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, +- uint32_t *size); ++ u32 *size, u32 align); + extern void nvc0_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); + extern int nvc0_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); + extern int nvc0_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); +@@ -1165,22 +1250,51 @@ extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); -extern int nouveau_bo_sync_gpu(struct nouveau_bo *, struct nouveau_channel *); ++extern void nouveau_bo_fence(struct nouveau_bo *, struct nouveau_fence *); /* nouveau_fence.c */ struct nouveau_fence; @@ -2493,13 +3276,59 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r + void (*work)(void *priv, bool signalled), + void *priv); struct nouveau_channel *nouveau_fence_channel(struct nouveau_fence *); - extern bool nouveau_fence_signalled(void *obj, void *arg); - extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); +-extern bool nouveau_fence_signalled(void *obj, void *arg); +-extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); +-extern int nouveau_fence_flush(void *obj, void *arg); +-extern void nouveau_fence_unref(void **obj); +-extern void *nouveau_fence_ref(void *obj); ++ ++extern bool __nouveau_fence_signalled(void *obj, void *arg); ++extern int __nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); ++extern int __nouveau_fence_flush(void *obj, void *arg); ++extern void __nouveau_fence_unref(void **obj); ++extern void *__nouveau_fence_ref(void *obj); ++ ++static inline bool nouveau_fence_signalled(struct nouveau_fence *obj) ++{ ++ return __nouveau_fence_signalled(obj, NULL); ++} ++static inline int ++nouveau_fence_wait(struct nouveau_fence *obj, bool lazy, bool intr) ++{ ++ return __nouveau_fence_wait(obj, NULL, lazy, intr); ++} +extern int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *); - extern int nouveau_fence_flush(void *obj, void *arg); - extern void nouveau_fence_unref(void **obj); - extern void *nouveau_fence_ref(void *obj); -@@ -1255,12 +1302,11 @@ ++static inline int nouveau_fence_flush(struct nouveau_fence *obj) ++{ ++ return __nouveau_fence_flush(obj, NULL); ++} ++static inline void nouveau_fence_unref(struct nouveau_fence **obj) ++{ ++ __nouveau_fence_unref((void **)obj); ++} ++static inline struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *obj) ++{ ++ return __nouveau_fence_ref(obj); ++} + + /* nouveau_gem.c */ + extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, +@@ -1200,6 +1314,14 @@ + extern int nouveau_gem_ioctl_info(struct drm_device *, void *, + struct drm_file *); + ++/* nouveau_display.c */ ++int nouveau_vblank_enable(struct drm_device *dev, int crtc); ++void nouveau_vblank_disable(struct drm_device *dev, int crtc); ++int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, ++ struct drm_pending_vblank_event *event); ++int nouveau_finish_page_flip(struct nouveau_channel *, ++ struct nouveau_page_flip_state *); ++ + /* nv10_gpio.c */ + int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); + int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); +@@ -1255,12 +1377,11 @@ iowrite32_native(val, dev_priv->mmio + reg); } @@ -2515,7 +3344,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r } static inline u8 nv_rd08(struct drm_device *dev, unsigned reg) -@@ -1275,7 +1321,7 @@ +@@ -1275,7 +1396,7 @@ iowrite8(val, dev_priv->mmio + reg); } @@ -2524,7 +3353,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r nouveau_wait_until(dev, 2000000000ULL, (reg), (mask), (val)) /* PRAMIN access */ -@@ -1292,17 +1338,8 @@ +@@ -1292,17 +1413,8 @@ } /* object access */ @@ -2544,7 +3373,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r /* * Logging -@@ -1403,6 +1440,7 @@ +@@ -1403,9 +1515,11 @@ #define NV_SW_SEMAPHORE_OFFSET 0x00000064 #define NV_SW_SEMAPHORE_ACQUIRE 0x00000068 #define NV_SW_SEMAPHORE_RELEASE 0x0000006c @@ -2552,9 +3381,13 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.36-r #define NV_SW_DMA_VBLSEM 0x0000018c #define NV_SW_VBLSEM_OFFSET 0x00000400 #define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404 -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_encoder.h linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_encoder.h ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_encoder.h 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_encoder.h 2010-10-15 02:04:44.343991985 +0200 + #define NV_SW_VBLSEM_RELEASE 0x00000408 ++#define NV_SW_PAGE_FLIP 0x00000500 + + #endif /* __NOUVEAU_DRV_H__ */ +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_encoder.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_encoder.h +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_encoder.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_encoder.h 2010-10-22 23:59:52.501453768 +0200 @@ -55,6 +55,7 @@ int dpcd_version; int link_nr; @@ -2563,9 +3396,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_encoder.h linux-2.6. } dp; }; }; -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_fbcon.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2010-10-15 02:00:52.945120028 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2010-10-15 02:04:44.345992009 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2010-10-22 23:59:52.502453781 +0200 @@ -49,6 +49,96 @@ #include "nouveau_fbcon.h" #include "nouveau_dma.h" @@ -2783,9 +3616,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-2.6.36 vga_switcheroo_client_fb_set(dev->pdev, info); return 0; -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fbcon.h linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_fbcon.h ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fbcon.h 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_fbcon.h 2010-10-15 02:04:44.348992046 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_fbcon.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.h +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_fbcon.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.h 2010-10-22 23:59:52.503453794 +0200 @@ -40,13 +40,13 @@ void nouveau_fbcon_restore(void); @@ -2806,9 +3639,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fbcon.h linux-2.6.36 int nv50_fbcon_accel_init(struct fb_info *info); void nouveau_fbcon_gpu_lockup(struct fb_info *info); -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_fence.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fence.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_fence.c 2010-10-15 02:04:44.350992072 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_fence.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_fence.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_fence.c 2010-10-22 23:59:52.504453807 +0200 @@ -28,9 +28,11 @@ #include "drm.h" @@ -2838,7 +3671,14 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.36 }; static inline struct nouveau_fence * -@@ -59,14 +70,13 @@ +@@ -53,20 +64,20 @@ + struct nouveau_fence *fence = + container_of(ref, struct nouveau_fence, refcount); + ++ nouveau_channel_ref(NULL, &fence->channel); + kfree(fence); + } + void nouveau_fence_update(struct nouveau_channel *chan) { @@ -2856,7 +3696,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.36 sequence = nvchan_rd32(chan, 0x48); else sequence = atomic_read(&chan->fence.last_sequence_irq); -@@ -75,12 +85,14 @@ +@@ -75,12 +86,14 @@ goto out; chan->fence.sequence_ack = sequence; @@ -2874,7 +3714,30 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.36 kref_put(&fence->refcount, nouveau_fence_del); if (sequence == chan->fence.sequence_ack) -@@ -121,8 +133,8 @@ +@@ -101,13 +114,13 @@ + if (!fence) + return -ENOMEM; + kref_init(&fence->refcount); +- fence->channel = chan; ++ nouveau_channel_ref(chan, &fence->channel); + + if (emit) + ret = nouveau_fence_emit(fence); + + if (ret) +- nouveau_fence_unref((void *)&fence); ++ nouveau_fence_unref(&fence); + *pfence = fence; + return ret; + } +@@ -115,14 +128,14 @@ + struct nouveau_channel * + nouveau_fence_channel(struct nouveau_fence *fence) + { +- return fence ? fence->channel : NULL; ++ return fence ? nouveau_channel_get_unlocked(fence->channel) : NULL; + } + int nouveau_fence_emit(struct nouveau_fence *fence) { @@ -2884,7 +3747,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.36 int ret; ret = RING_SPACE(chan, 2); -@@ -143,7 +155,7 @@ +@@ -143,7 +156,7 @@ list_add_tail(&fence->entry, &chan->fence.pending); spin_unlock(&chan->fence.lock); @@ -2893,10 +3756,11 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.36 OUT_RING(chan, fence->sequence); FIRE_RING(chan); -@@ -151,6 +163,25 @@ +@@ -151,7 +164,26 @@ } void +-nouveau_fence_unref(void **sync_obj) +nouveau_fence_work(struct nouveau_fence *fence, + void (*work)(void *priv, bool signalled), + void *priv) @@ -2916,10 +3780,45 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.36 +} + +void - nouveau_fence_unref(void **sync_obj) ++__nouveau_fence_unref(void **sync_obj) { struct nouveau_fence *fence = nouveau_fence(*sync_obj); -@@ -213,6 +244,177 @@ + +@@ -161,7 +193,7 @@ + } + + void * +-nouveau_fence_ref(void *sync_obj) ++__nouveau_fence_ref(void *sync_obj) + { + struct nouveau_fence *fence = nouveau_fence(sync_obj); + +@@ -170,7 +202,7 @@ + } + + bool +-nouveau_fence_signalled(void *sync_obj, void *sync_arg) ++__nouveau_fence_signalled(void *sync_obj, void *sync_arg) + { + struct nouveau_fence *fence = nouveau_fence(sync_obj); + struct nouveau_channel *chan = fence->channel; +@@ -183,13 +215,13 @@ + } + + int +-nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) ++__nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) + { + unsigned long timeout = jiffies + (3 * DRM_HZ); + int ret = 0; + + while (1) { +- if (nouveau_fence_signalled(sync_obj, sync_arg)) ++ if (__nouveau_fence_signalled(sync_obj, sync_arg)) + break; + + if (time_after_eq(jiffies, timeout)) { +@@ -213,33 +245,311 @@ return ret; } @@ -3047,29 +3946,31 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.36 + + kref_get(&sema->ref); + nouveau_fence_work(fence, semaphore_work, sema); -+ nouveau_fence_unref((void *)&fence); ++ nouveau_fence_unref(&fence); + + return 0; +} + -+int + int +-nouveau_fence_flush(void *sync_obj, void *sync_arg) +nouveau_fence_sync(struct nouveau_fence *fence, + struct nouveau_channel *wchan) +{ + struct nouveau_channel *chan = nouveau_fence_channel(fence); + struct drm_device *dev = wchan->dev; + struct nouveau_semaphore *sema; -+ int ret; ++ int ret = 0; + -+ if (likely(!fence || chan == wchan || -+ nouveau_fence_signalled(fence, NULL))) -+ return 0; ++ if (likely(!chan || chan == wchan || ++ nouveau_fence_signalled(fence))) ++ goto out; + + sema = alloc_semaphore(dev); + if (!sema) { + /* Early card or broken userspace, fall back to + * software sync. */ -+ return nouveau_fence_wait(fence, NULL, false, false); ++ ret = nouveau_fence_wait(fence, true, false); ++ goto out; + } + + /* try to take chan's mutex, if we can't take it right away @@ -3077,27 +3978,32 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.36 + * order issues + */ + if (!mutex_trylock(&chan->mutex)) { -+ free_semaphore(&sema->ref); -+ return nouveau_fence_wait(fence, NULL, false, false); ++ ret = nouveau_fence_wait(fence, true, false); ++ goto out_unref; + } + + /* Make wchan wait until it gets signalled */ + ret = emit_semaphore(wchan, NV_SW_SEMAPHORE_ACQUIRE, sema); + if (ret) -+ goto out; ++ goto out_unlock; + + /* Signal the semaphore from chan */ + ret = emit_semaphore(chan, NV_SW_SEMAPHORE_RELEASE, sema); ++ ++out_unlock: + mutex_unlock(&chan->mutex); -+out: ++out_unref: + kref_put(&sema->ref, free_semaphore); ++out: ++ if (chan) ++ nouveau_channel_put_unlocked(&chan); + return ret; +} + - int - nouveau_fence_flush(void *sync_obj, void *sync_arg) ++int ++__nouveau_fence_flush(void *sync_obj, void *sync_arg) { -@@ -220,26 +422,123 @@ + return 0; } int @@ -3110,7 +4016,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.36 + int ret; + + /* Create an NV_SW object for various sync purposes */ -+ ret = nouveau_gpuobj_sw_new(chan, NV_SW, &obj); ++ ret = nouveau_gpuobj_gr_new(chan, NV_SW, &obj); + if (ret) + return ret; + @@ -3164,10 +4070,11 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.36 { - struct list_head *entry, *tmp; - struct nouveau_fence *fence; -- ++ struct nouveau_fence *tmp, *fence; + - list_for_each_safe(entry, tmp, &chan->fence.pending) { - fence = list_entry(entry, struct nouveau_fence, entry); -+ struct nouveau_fence *tmp, *fence; ++ spin_lock(&chan->fence.lock); + list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { fence->signalled = true; @@ -3178,6 +4085,8 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.36 + kref_put(&fence->refcount, nouveau_fence_del); } ++ ++ spin_unlock(&chan->fence.lock); } +int @@ -3228,9 +4137,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.36 + nouveau_bo_ref(NULL, &dev_priv->fence.bo); + } +} -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_gem.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_gem.c 2010-10-15 02:04:44.352992096 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_gem.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_gem.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_gem.c 2010-10-22 23:59:52.506453832 +0200 @@ -48,9 +48,6 @@ return; nvbo->gem = NULL; @@ -3317,7 +4226,24 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36-r if (ret) return ret; -@@ -293,14 +299,15 @@ +@@ -225,15 +231,8 @@ + + list_for_each_safe(entry, tmp, list) { + nvbo = list_entry(entry, struct nouveau_bo, entry); +- if (likely(fence)) { +- struct nouveau_fence *prev_fence; + +- spin_lock(&nvbo->bo.lock); +- prev_fence = nvbo->bo.sync_obj; +- nvbo->bo.sync_obj = nouveau_fence_ref(fence); +- spin_unlock(&nvbo->bo.lock); +- nouveau_fence_unref((void *)&prev_fence); +- } ++ nouveau_bo_fence(nvbo, fence); + + if (unlikely(nvbo->validate_mapped)) { + ttm_bo_kunmap(&nvbo->kmap); +@@ -293,14 +292,15 @@ return -EINVAL; } @@ -3338,7 +4264,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36-r return ret; } goto retry; -@@ -325,25 +332,6 @@ +@@ -325,25 +325,6 @@ validate_fini(op, NULL); return -EINVAL; } @@ -3364,7 +4290,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36-r } return 0; -@@ -362,7 +350,7 @@ +@@ -362,7 +343,7 @@ list_for_each_entry(nvbo, list, entry) { struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; @@ -3373,7 +4299,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36-r if (unlikely(ret)) { NV_ERROR(dev, "fail pre-validate sync\n"); return ret; -@@ -378,14 +366,15 @@ +@@ -378,14 +359,15 @@ nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan; ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, @@ -3392,7 +4318,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36-r if (unlikely(ret)) { NV_ERROR(dev, "fail post-validate sync\n"); return ret; -@@ -433,13 +422,15 @@ +@@ -433,13 +415,15 @@ ret = validate_init(chan, file_priv, pbbo, nr_buffers, op); if (unlikely(ret)) { @@ -3410,7 +4336,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36-r validate_fini(op, NULL); return ret; } -@@ -447,7 +438,8 @@ +@@ -447,7 +431,8 @@ ret = validate_list(chan, &op->gart_list, pbbo, user_buffers); if (unlikely(ret < 0)) { @@ -3420,7 +4346,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36-r validate_fini(op, NULL); return ret; } -@@ -455,7 +447,8 @@ +@@ -455,7 +440,8 @@ ret = validate_list(chan, &op->both_list, pbbo, user_buffers); if (unlikely(ret < 0)) { @@ -3430,7 +4356,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36-r validate_fini(op, NULL); return ret; } -@@ -579,7 +572,9 @@ +@@ -579,7 +565,9 @@ struct nouveau_fence *fence = NULL; int i, j, ret = 0, do_reloc = 0; @@ -3441,7 +4367,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36-r req->vram_available = dev_priv->fb_aper_free; req->gart_available = dev_priv->gart_info.aper_free; -@@ -589,28 +584,34 @@ +@@ -589,28 +577,34 @@ if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) { NV_ERROR(dev, "pushbuf push count exceeds limit: %d max %d\n", req->nr_push, NOUVEAU_GEM_MAX_PUSH); @@ -3477,7 +4403,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36-r return PTR_ERR(bo); } -@@ -633,7 +634,8 @@ +@@ -633,7 +627,8 @@ ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers, req->nr_buffers, &op, &do_reloc); if (ret) { @@ -3487,7 +4413,16 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36-r goto out; } -@@ -744,6 +746,7 @@ +@@ -726,7 +721,7 @@ + + out: + validate_fini(&op, fence); +- nouveau_fence_unref((void**)&fence); ++ nouveau_fence_unref(&fence); + kfree(bo); + kfree(push); + +@@ -744,6 +739,7 @@ req->suffix1 = 0x00000000; } @@ -3495,7 +4430,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36-r return ret; } -@@ -775,26 +778,9 @@ +@@ -775,26 +771,9 @@ return -ENOENT; nvbo = nouveau_gem_object(gem); @@ -3525,7 +4460,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36-r drm_gem_object_unreference_unlocked(gem); return ret; } -@@ -803,26 +789,7 @@ +@@ -803,26 +782,7 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -3553,9 +4488,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.36-r } int -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_grctx.h linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_grctx.h ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_grctx.h 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_grctx.h 2010-10-15 02:04:44.354992121 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_grctx.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_grctx.h +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_grctx.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_grctx.h 2010-10-22 23:59:52.510453880 +0200 @@ -126,7 +126,7 @@ reg = (reg - 0x00400000) / 4; reg = (reg - ctx->ctxprog_reg) + ctx->ctxvals_base; @@ -3565,9 +4500,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_grctx.h linux-2.6.36 } #endif -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_hw.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_hw.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_hw.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_hw.c 2010-10-15 02:04:44.356992146 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_hw.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_hw.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_hw.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_hw.c 2010-10-22 23:59:52.511453892 +0200 @@ -305,7 +305,7 @@ bool mpll = Preg == 0x4020; uint32_t oldPval = nvReadMC(dev, Preg); @@ -3682,6 +4617,15 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_hw.c linux-2.6.36-rc rd_cio_state(dev, head, regp, NV_CIO_CRE_49); rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); +@@ -957,7 +953,7 @@ + NVWriteCRTC(dev, head, NV_PCRTC_850, regp->crtc_850); + + reg900 = NVReadRAMDAC(dev, head, NV_PRAMDAC_900); +- if (regp->crtc_cfg == NV_PCRTC_CONFIG_START_ADDRESS_HSYNC) ++ if (regp->crtc_cfg == NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC) + NVWriteRAMDAC(dev, head, NV_PRAMDAC_900, reg900 | 0x10000); + else + NVWriteRAMDAC(dev, head, NV_PRAMDAC_900, reg900 & ~0x10000); @@ -976,10 +972,11 @@ wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); @@ -3696,9 +4640,50 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_hw.c linux-2.6.36-rc wr_cio_state(dev, head, regp, NV_CIO_CRE_49); wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_i2c.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_i2c.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_i2c.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_i2c.c 2010-10-15 02:04:44.357992158 +0200 +@@ -1020,8 +1017,9 @@ + + NVWriteCRTC(dev, head, NV_PCRTC_START, regp->fb_start); + +- /* Setting 1 on this value gives you interrupts for every vblank period. */ +- NVWriteCRTC(dev, head, NV_PCRTC_INTR_EN_0, 0); ++ /* Enable vblank interrupts. */ ++ NVWriteCRTC(dev, head, NV_PCRTC_INTR_EN_0, ++ (dev->vblank_enabled[head] ? 1 : 0)); + NVWriteCRTC(dev, head, NV_PCRTC_INTR_0, NV_PCRTC_INTR_0_VBLANK); + } + +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_hw.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_hw.h +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_hw.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_hw.h 2010-10-22 23:59:52.512453904 +0200 +@@ -416,6 +416,25 @@ + } + + static inline void ++nv_set_crtc_base(struct drm_device *dev, int head, uint32_t offset) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ NVWriteCRTC(dev, head, NV_PCRTC_START, offset); ++ ++ if (dev_priv->card_type == NV_04) { ++ /* ++ * Hilarious, the 24th bit doesn't want to stick to ++ * PCRTC_START... ++ */ ++ int cre_heb = NVReadVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX); ++ ++ NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX, ++ (cre_heb & ~0x40) | ((offset >> 18) & 0x40)); ++ } ++} ++ ++static inline void + nv_show_cursor(struct drm_device *dev, int head, bool show) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_i2c.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_i2c.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_i2c.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_i2c.c 2010-10-22 23:59:52.513453917 +0200 @@ -299,7 +299,10 @@ int @@ -3721,9 +4706,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_i2c.c linux-2.6.36-r NV_INFO(dev, "Detected %s: %s\n", what, info[i].type); return i; } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_i2c.h linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_i2c.h ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_i2c.h 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_i2c.h 2010-10-15 02:04:44.359992183 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_i2c.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_i2c.h +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_i2c.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_i2c.h 2010-10-22 23:59:52.513453917 +0200 @@ -44,7 +44,10 @@ struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index); bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); @@ -3736,9 +4721,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_i2c.h linux-2.6.36-r extern const struct i2c_algorithm nouveau_dp_i2c_algo; -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_irq.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_irq.c 2010-10-15 02:04:44.361992209 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_irq.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_irq.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_irq.c 2010-10-22 23:59:52.516453956 +0200 @@ -35,12 +35,20 @@ #include "nouveau_drm.h" #include "nouveau_drv.h" @@ -3760,9 +4745,51 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r void nouveau_irq_preinstall(struct drm_device *dev) { -@@ -99,35 +107,49 @@ +@@ -59,8 +67,13 @@ + int + nouveau_irq_postinstall(struct drm_device *dev) + { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ + /* Master enable */ + nv_wr32(dev, NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE); ++ if (dev_priv->msi_enabled) ++ nv_wr08(dev, 0x00088068, 0xff); ++ + return 0; } +@@ -71,63 +84,50 @@ + nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); + } + +-static int +-nouveau_call_method(struct nouveau_channel *chan, int class, int mthd, int data) +-{ +- struct drm_nouveau_private *dev_priv = chan->dev->dev_private; +- struct nouveau_pgraph_object_method *grm; +- struct nouveau_pgraph_object_class *grc; +- +- grc = dev_priv->engine.graph.grclass; +- while (grc->id) { +- if (grc->id == class) +- break; +- grc++; +- } +- +- if (grc->id != class || !grc->methods) +- return -ENOENT; +- +- grm = grc->methods; +- while (grm->id) { +- if (grm->id == mthd) +- return grm->exec(chan, class, mthd, data); +- grm++; +- } +- +- return -ENOENT; +-} +- static bool -nouveau_fifo_swmthd(struct nouveau_channel *chan, uint32_t addr, uint32_t data) +nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data) @@ -3810,8 +4837,8 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r - nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_rd32(dev, - NV04_PFIFO_CACHE1_ENGINE) & ~(0xf << subc * 4)); - return true; -+ if (!nouveau_call_method(chan, chan->sw_subchannel[subc], -+ mthd, data)) ++ if (!nouveau_gpuobj_mthd_call(chan, chan->sw_subchannel[subc], ++ mthd, data)) + handled = true; + break; } @@ -3830,7 +4857,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r } static void -@@ -140,14 +162,11 @@ +@@ -140,14 +140,11 @@ reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1; while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) { @@ -3845,7 +4872,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r get = nv_rd32(dev, NV03_PFIFO_CACHE1_GET); if (status & NV_PFIFO_INTR_CACHE_ERROR) { -@@ -174,7 +193,7 @@ +@@ -174,7 +171,7 @@ NV40_PFIFO_CACHE1_DATA(ptr)); } @@ -3854,7 +4881,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d " "Mthd 0x%04x Data 0x%08x\n", chid, (mthd >> 13) & 7, mthd & 0x1ffc, -@@ -200,16 +219,47 @@ +@@ -200,16 +197,47 @@ } if (status & NV_PFIFO_INTR_DMA_PUSHER) { @@ -3910,7 +4937,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r } if (status & NV_PFIFO_INTR_SEMAPHORE) { -@@ -226,9 +276,18 @@ +@@ -226,9 +254,18 @@ nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); } @@ -3931,7 +4958,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r nv_wr32(dev, NV03_PFIFO_INTR_0, status); status = 0; } -@@ -342,6 +401,8 @@ +@@ -342,6 +379,8 @@ nouveau_graph_chid_from_grctx(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -3940,7 +4967,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r uint32_t inst; int i; -@@ -351,27 +412,29 @@ +@@ -351,27 +390,29 @@ if (dev_priv->card_type < NV_50) { inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 4; @@ -3976,7 +5003,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r } -@@ -393,7 +456,8 @@ +@@ -393,7 +434,8 @@ else channel = nouveau_graph_chid_from_grctx(dev); @@ -3986,10 +5013,11 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r NV_ERROR(dev, "AIII, invalid/inactive channel id %d\n", channel); return -EINVAL; } -@@ -476,14 +540,19 @@ +@@ -476,14 +518,20 @@ struct nouveau_pgraph_trap *trap) { struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_channel *chan; + unsigned long flags; + int ret = -EINVAL; @@ -4001,8 +5029,8 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r + if (trap->channel > 0 && + trap->channel < dev_priv->engine.fifo.channels && + dev_priv->channels.ptr[trap->channel]) { -+ ret = nouveau_call_method(dev_priv->channels.ptr[trap->channel], -+ trap->class, trap->mthd, trap->data); ++ chan = dev_priv->channels.ptr[trap->channel]; ++ ret = nouveau_gpuobj_mthd_call(chan, trap->class, trap->mthd, trap->data); + } + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); @@ -4012,7 +5040,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r } static inline void -@@ -505,13 +574,6 @@ +@@ -505,13 +553,6 @@ nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap); } @@ -4026,7 +5054,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r static inline void nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource) -@@ -605,40 +667,6 @@ +@@ -605,40 +646,6 @@ nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); } @@ -4067,7 +5095,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r static struct nouveau_enum_names nv50_mp_exec_error_names[] = { { 3, "STACK_UNDERFLOW" }, -@@ -711,7 +739,7 @@ +@@ -711,7 +718,7 @@ tps++; switch (type) { case 6: /* texture error... unknown for now */ @@ -4076,7 +5104,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r if (display) { NV_ERROR(dev, "magic set %d:\n", i); for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) -@@ -734,7 +762,7 @@ +@@ -734,7 +741,7 @@ uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); @@ -4085,7 +5113,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r /* 2d engine destination */ if (ustatus & 0x00000010) { if (display) { -@@ -817,7 +845,7 @@ +@@ -817,7 +824,7 @@ /* Known to be triggered by screwed up NOTIFY and COND... */ if (ustatus & 0x00000001) { @@ -4094,7 +5122,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r nv_wr32(dev, 0x400500, 0); if (nv_rd32(dev, 0x400808) & 0x80000000) { if (display) { -@@ -842,7 +870,7 @@ +@@ -842,7 +849,7 @@ ustatus &= ~0x00000001; } if (ustatus & 0x00000002) { @@ -4103,7 +5131,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r nv_wr32(dev, 0x400500, 0); if (nv_rd32(dev, 0x40084c) & 0x80000000) { if (display) { -@@ -884,15 +912,15 @@ +@@ -884,15 +891,15 @@ NV_INFO(dev, "PGRAPH_TRAP_M2MF - no ustatus?\n"); } if (ustatus & 0x00000001) { @@ -4122,7 +5150,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r ustatus &= ~0x00000004; } NV_INFO (dev, "PGRAPH_TRAP_M2MF - %08x %08x %08x %08x\n", -@@ -917,7 +945,7 @@ +@@ -917,7 +924,7 @@ NV_INFO(dev, "PGRAPH_TRAP_VFETCH - no ustatus?\n"); } if (ustatus & 0x00000001) { @@ -4131,7 +5159,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r NV_INFO (dev, "PGRAPH_TRAP_VFETCH_FAULT - %08x %08x %08x %08x\n", nv_rd32(dev, 0x400c00), nv_rd32(dev, 0x400c08), -@@ -939,7 +967,7 @@ +@@ -939,7 +946,7 @@ NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - no ustatus?\n"); } if (ustatus & 0x00000001) { @@ -4140,7 +5168,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r NV_INFO (dev, "PGRAPH_TRAP_STRMOUT_FAULT - %08x %08x %08x %08x\n", nv_rd32(dev, 0x401804), nv_rd32(dev, 0x401808), -@@ -964,7 +992,7 @@ +@@ -964,7 +971,7 @@ NV_INFO(dev, "PGRAPH_TRAP_CCACHE - no ustatus?\n"); } if (ustatus & 0x00000001) { @@ -4149,7 +5177,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r NV_INFO (dev, "PGRAPH_TRAP_CCACHE_FAULT - %08x %08x %08x %08x %08x %08x %08x\n", nv_rd32(dev, 0x405800), nv_rd32(dev, 0x405804), -@@ -986,7 +1014,7 @@ +@@ -986,7 +993,7 @@ * remaining, so try to handle it anyway. Perhaps related to that * unknown DMA slot on tesla? */ if (status & 0x20) { @@ -4158,9 +5186,86 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.36-r ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff; if (display) NV_INFO(dev, "PGRAPH_TRAP_UNKC04 - Unhandled ustatus 0x%08x\n", ustatus); -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_mem.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_mem.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_mem.c 2010-10-15 02:04:44.363992233 +0200 +@@ -1192,11 +1199,15 @@ + static void + nouveau_crtc_irq_handler(struct drm_device *dev, int crtc) + { +- if (crtc & 1) ++ if (crtc & 1) { + nv_wr32(dev, NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK); ++ drm_handle_vblank(dev, 0); ++ } + +- if (crtc & 2) ++ if (crtc & 2) { + nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK); ++ drm_handle_vblank(dev, 1); ++ } + } + + irqreturn_t +@@ -1227,6 +1238,22 @@ + status &= ~NV_PMC_INTR_0_PGRAPH_PENDING; + } + ++ if (status & 0x00004000) { ++ u32 stat = nv_rd32(dev, 0x102130); ++ u32 mthd = nv_rd32(dev, 0x102190); ++ u32 data = nv_rd32(dev, 0x102194); ++ u32 inst = nv_rd32(dev, 0x102188) & 0x7fffffff; ++ ++ NV_INFO(dev, "PCRYPT_INTR: 0x%08x 0x%08x 0x%08x 0x%08x\n", ++ stat, mthd, data, inst); ++ nv_wr32(dev, 0x102130, stat); ++ nv_wr32(dev, 0x10200c, 0x10); ++ ++ nv50_fb_vm_trap(dev, nouveau_ratelimit(), "PCRYPT"); ++ status &= ~0x00004000; ++ ++ } ++ + if (status & NV_PMC_INTR_0_CRTCn_PENDING) { + nouveau_crtc_irq_handler(dev, (status>>24)&3); + status &= ~NV_PMC_INTR_0_CRTCn_PENDING; +@@ -1244,5 +1271,35 @@ + + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + ++ if (dev_priv->msi_enabled) ++ nv_wr08(dev, 0x00088068, 0xff); ++ + return IRQ_HANDLED; + } ++ ++int ++nouveau_irq_init(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ int ret; ++ ++ if (nouveau_msi != 0 && dev_priv->card_type >= NV_50) { ++ ret = pci_enable_msi(dev->pdev); ++ if (ret == 0) { ++ NV_INFO(dev, "enabled MSI\n"); ++ dev_priv->msi_enabled = true; ++ } ++ } ++ ++ return drm_irq_install(dev); ++} ++ ++void ++nouveau_irq_fini(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ drm_irq_uninstall(dev); ++ if (dev_priv->msi_enabled) ++ pci_disable_msi(dev->pdev); ++} +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_mem.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_mem.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_mem.c 2010-10-22 23:59:52.517453968 +0200 @@ -33,7 +33,9 @@ #include "drmP.h" #include "drm.h" @@ -4181,11 +5286,12 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6.36-r tile->addr = addr; tile->size = size; tile->used = !!pitch; - nouveau_fence_unref((void **)&tile->fence); - +- nouveau_fence_unref((void **)&tile->fence); +- - if (!pfifo->cache_flush(dev)) - return; -- ++ nouveau_fence_unref(&tile->fence); + pfifo->reassign(dev, false); - pfifo->cache_flush(dev); pfifo->cache_pull(dev, false); @@ -4214,7 +5320,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6.36-r - if (tile[i].fence && - !nouveau_fence_signalled(tile[i].fence, NULL)) + if (tile->fence && -+ !nouveau_fence_signalled(tile->fence, NULL)) ++ !nouveau_fence_signalled(tile->fence)) /* Pending tile region. */ continue; @@ -4697,9 +5803,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6.36-r + + kfree(mem->timing); +} -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_notifier.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_notifier.c 2010-10-15 02:00:53.004120745 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_notifier.c 2010-10-15 02:04:44.365992257 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_notifier.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_notifier.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_notifier.c 2010-10-22 23:59:52.528454104 +0200 @@ -28,6 +28,7 @@ #include "drmP.h" #include "drm.h" @@ -4708,6 +5814,15 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-2.6 int nouveau_notifier_init_channel(struct nouveau_channel *chan) +@@ -112,7 +113,7 @@ + return -ENOMEM; + } + +- offset = chan->notifier_bo->bo.mem.mm_node->start << PAGE_SHIFT; ++ offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; + if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) { + target = NV_DMA_TARGET_VIDMEM; + } else @@ -146,11 +147,11 @@ nobj->dtor = nouveau_notifier_gpuobj_dtor; nobj->priv = mem; @@ -4740,18 +5855,95 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-2.6 + nouveau_channel_put(&chan); + return ret; } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_object.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_object.c 2010-10-15 02:04:44.369992308 +0200 -@@ -34,6 +34,7 @@ +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_object.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_object.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_object.c 2010-10-22 23:59:52.531454140 +0200 +@@ -34,6 +34,84 @@ #include "drm.h" #include "nouveau_drv.h" #include "nouveau_drm.h" +#include "nouveau_ramht.h" ++ ++struct nouveau_gpuobj_method { ++ struct list_head head; ++ u32 mthd; ++ int (*exec)(struct nouveau_channel *, u32 class, u32 mthd, u32 data); ++}; ++ ++struct nouveau_gpuobj_class { ++ struct list_head head; ++ struct list_head methods; ++ u32 id; ++ u32 engine; ++}; ++ ++int ++nouveau_gpuobj_class_new(struct drm_device *dev, u32 class, u32 engine) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpuobj_class *oc; ++ ++ oc = kzalloc(sizeof(*oc), GFP_KERNEL); ++ if (!oc) ++ return -ENOMEM; ++ ++ INIT_LIST_HEAD(&oc->methods); ++ oc->id = class; ++ oc->engine = engine; ++ list_add(&oc->head, &dev_priv->classes); ++ return 0; ++} ++ ++int ++nouveau_gpuobj_mthd_new(struct drm_device *dev, u32 class, u32 mthd, ++ int (*exec)(struct nouveau_channel *, u32, u32, u32)) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpuobj_method *om; ++ struct nouveau_gpuobj_class *oc; ++ ++ list_for_each_entry(oc, &dev_priv->classes, head) { ++ if (oc->id == class) ++ goto found; ++ } ++ ++ return -EINVAL; ++ ++found: ++ om = kzalloc(sizeof(*om), GFP_KERNEL); ++ if (!om) ++ return -ENOMEM; ++ ++ om->mthd = mthd; ++ om->exec = exec; ++ list_add(&om->head, &oc->methods); ++ return 0; ++} ++ ++int ++nouveau_gpuobj_mthd_call(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) ++{ ++ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; ++ struct nouveau_gpuobj_method *om; ++ struct nouveau_gpuobj_class *oc; ++ ++ list_for_each_entry(oc, &dev_priv->classes, head) { ++ if (oc->id != class) ++ continue; ++ ++ list_for_each_entry(om, &oc->methods, head) { ++ if (om->mthd == mthd) ++ return om->exec(chan, class, mthd, data); ++ } ++ } ++ ++ return -ENOENT; ++} /* NVidia uses context objects to drive drawing operations. -@@ -65,137 +66,6 @@ +@@ -65,137 +143,6 @@ The key into the hash table depends on the object handle and channel id and is given as: */ @@ -4889,7 +6081,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 int nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, -@@ -205,7 +75,7 @@ +@@ -205,7 +152,7 @@ struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->engine; struct nouveau_gpuobj *gpuobj; @@ -4898,7 +6090,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 int ret; NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n", -@@ -218,69 +88,102 @@ +@@ -218,69 +165,102 @@ if (!gpuobj) return -ENOMEM; NV_DEBUG(dev, "gpuobj %p\n", gpuobj); @@ -4933,8 +6125,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 NV_DEBUG(dev, "global heap\n"); - pramin = &dev_priv->ramin_heap; +- ret = engine->instmem.populate(dev, gpuobj, &size); + /* allocate backing pages, sets vinst */ - ret = engine->instmem.populate(dev, gpuobj, &size); ++ ret = engine->instmem.populate(dev, gpuobj, &size, align); if (ret) { - nouveau_gpuobj_del(dev, &gpuobj); + nouveau_gpuobj_ref(NULL, &gpuobj); @@ -4950,10 +6143,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 + do { + if (drm_mm_pre_get(&dev_priv->ramin_heap)) + return -ENOMEM; - -- if (!gpuobj->im_pramin) { -- nouveau_gpuobj_del(dev, &gpuobj); -- return -ENOMEM; ++ + spin_lock(&dev_priv->ramin_lock); + ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, + align, 0); @@ -4962,7 +6152,10 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 + nouveau_gpuobj_ref(NULL, &gpuobj); + return ret; + } -+ + +- if (!gpuobj->im_pramin) { +- nouveau_gpuobj_del(dev, &gpuobj); +- return -ENOMEM; + ramin = drm_mm_get_block_atomic(ramin, size, align); + spin_unlock(&dev_priv->ramin_lock); + } while (ramin == NULL); @@ -5034,7 +6227,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 return 0; } -@@ -288,18 +191,12 @@ +@@ -288,18 +268,13 @@ nouveau_gpuobj_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -5051,26 +6244,31 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 - return ret; - } + INIT_LIST_HEAD(&dev_priv->gpuobj_list); ++ INIT_LIST_HEAD(&dev_priv->classes); + spin_lock_init(&dev_priv->ramin_lock); + dev_priv->ramin_base = ~0; return 0; } -@@ -311,297 +208,89 @@ +@@ -308,300 +283,103 @@ + nouveau_gpuobj_takedown(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpuobj_method *om, *tm; ++ struct nouveau_gpuobj_class *oc, *tc; NV_DEBUG(dev, "\n"); - nouveau_gpuobj_del(dev, &dev_priv->ramht); -+ BUG_ON(!list_empty(&dev_priv->gpuobj_list)); - } - +-} +- -void -nouveau_gpuobj_late_takedown(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gpuobj = NULL; - struct list_head *entry, *tmp; - +- - NV_DEBUG(dev, "\n"); - - list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) { @@ -5080,11 +6278,21 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 - gpuobj, gpuobj->refcount); - gpuobj->refcount = 0; - nouveau_gpuobj_del(dev, &gpuobj); -- } --} -- ++ list_for_each_entry_safe(oc, tc, &dev_priv->classes, head) { ++ list_for_each_entry_safe(om, tm, &oc->methods, head) { ++ list_del(&om->head); ++ kfree(om); ++ } ++ list_del(&oc->head); ++ kfree(oc); + } ++ ++ BUG_ON(!list_empty(&dev_priv->gpuobj_list)); + } + -int -nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) ++ +static void +nouveau_gpuobj_del(struct kref *ref) { @@ -5139,8 +6347,8 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 - *pgpuobj = NULL; kfree(gpuobj); - return 0; --} -- + } + -static int -nouveau_gpuobj_instance_get(struct drm_device *dev, - struct nouveau_channel *chan, @@ -5288,8 +6496,8 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 - } - - return 0; - } - +-} +- -int -nouveau_gpuobj_ref_find(struct nouveau_channel *chan, uint32_t handle, - struct nouveau_gpuobj_ref **ref_ret) @@ -5392,7 +6600,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 return 0; } -@@ -685,14 +374,12 @@ +@@ -685,14 +463,12 @@ adjust = offset & 0x00000fff; frame = offset & ~0x00000fff; @@ -5413,7 +6621,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 } else { uint64_t limit = offset + size - 1; uint32_t flags0, flags5; -@@ -705,12 +392,12 @@ +@@ -705,12 +481,12 @@ flags5 = 0x00080000; } @@ -5432,7 +6640,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 } instmem->flush(dev); -@@ -741,7 +428,7 @@ +@@ -741,7 +517,7 @@ *o_ret = 0; } else if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA) { @@ -5441,7 +6649,93 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 if (offset & ~0xffffffffULL) { NV_ERROR(dev, "obj offset exceeds 32-bits\n"); return -EINVAL; -@@ -829,25 +516,25 @@ +@@ -808,76 +584,117 @@ + entry[5]: + set to 0? + */ ++static int ++nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, ++ struct nouveau_gpuobj **gpuobj_ret) ++{ ++ struct drm_nouveau_private *dev_priv; ++ struct nouveau_gpuobj *gpuobj; ++ ++ if (!chan || !gpuobj_ret || *gpuobj_ret != NULL) ++ return -EINVAL; ++ dev_priv = chan->dev->dev_private; ++ ++ gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); ++ if (!gpuobj) ++ return -ENOMEM; ++ gpuobj->dev = chan->dev; ++ gpuobj->engine = NVOBJ_ENGINE_SW; ++ gpuobj->class = class; ++ kref_init(&gpuobj->refcount); ++ gpuobj->cinst = 0x40; ++ ++ spin_lock(&dev_priv->ramin_lock); ++ list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); ++ spin_unlock(&dev_priv->ramin_lock); ++ *gpuobj_ret = gpuobj; ++ return 0; ++} ++ + int + nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, + struct nouveau_gpuobj **gpuobj) + { ++ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct drm_device *dev = chan->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpuobj_class *oc; + int ret; + + NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class); + ++ list_for_each_entry(oc, &dev_priv->classes, head) { ++ if (oc->id == class) ++ goto found; ++ } ++ ++ NV_ERROR(dev, "illegal object class: 0x%x\n", class); ++ return -EINVAL; ++ ++found: ++ if (oc->engine == NVOBJ_ENGINE_SW) ++ return nouveau_gpuobj_sw_new(chan, class, gpuobj); ++ ++ switch (oc->engine) { ++ case NVOBJ_ENGINE_GR: ++ if (dev_priv->chipset >= NV_50 && !chan->ramin_grctx) { ++ struct nouveau_pgraph_engine *pgraph = ++ &dev_priv->engine.graph; ++ ++ ret = pgraph->create_context(chan); ++ if (ret) ++ return ret; ++ } ++ break; ++ case NVOBJ_ENGINE_CRYPT: ++ if (!chan->crypt_ctx) { ++ struct nouveau_crypt_engine *pcrypt = ++ &dev_priv->engine.crypt; ++ ++ ret = pcrypt->create_context(chan); ++ if (ret) ++ return ret; ++ } ++ break; ++ } ++ + ret = nouveau_gpuobj_new(dev, chan, + nouveau_gpuobj_class_instmem_size(dev, class), + 16, + NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, + gpuobj); + if (ret) { +- NV_ERROR(dev, "Error creating gpuobj: %d\n", ret); ++ NV_ERROR(dev, "error creating gpuobj: %d\n", ret); + return ret; } if (dev_priv->card_type >= NV_50) { @@ -5475,23 +6769,39 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 #endif } } -@@ -873,10 +560,15 @@ - gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); - if (!gpuobj) - return -ENOMEM; -+ gpuobj->dev = chan->dev; - gpuobj->engine = NVOBJ_ENGINE_SW; - gpuobj->class = class; -+ kref_init(&gpuobj->refcount); -+ gpuobj->cinst = 0x40; + } + dev_priv->engine.instmem.flush(dev); -+ spin_lock(&dev_priv->ramin_lock); - list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); -+ spin_unlock(&dev_priv->ramin_lock); - *gpuobj_ret = gpuobj; +- (*gpuobj)->engine = NVOBJ_ENGINE_GR; +- (*gpuobj)->class = class; +- return 0; +-} +- +-int +-nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, +- struct nouveau_gpuobj **gpuobj_ret) +-{ +- struct drm_nouveau_private *dev_priv; +- struct nouveau_gpuobj *gpuobj; +- +- if (!chan || !gpuobj_ret || *gpuobj_ret != NULL) +- return -EINVAL; +- dev_priv = chan->dev->dev_private; +- +- gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); +- if (!gpuobj) +- return -ENOMEM; +- gpuobj->engine = NVOBJ_ENGINE_SW; +- gpuobj->class = class; +- +- list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); +- *gpuobj_ret = gpuobj; ++ (*gpuobj)->engine = oc->engine; ++ (*gpuobj)->class = oc->id; return 0; } -@@ -886,7 +578,6 @@ + +@@ -886,7 +703,6 @@ { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -5499,7 +6809,16 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 uint32_t size; uint32_t base; int ret; -@@ -911,18 +602,16 @@ +@@ -894,7 +710,7 @@ + NV_DEBUG(dev, "ch%d\n", chan->id); + + /* Base amount for object storage (4KiB enough?) */ +- size = 0x1000; ++ size = 0x2000; + base = 0; + + /* PGRAPH context */ +@@ -911,18 +727,16 @@ size += 0x1000; } @@ -5521,7 +6840,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 return ret; } -@@ -939,8 +628,6 @@ +@@ -939,8 +753,6 @@ struct nouveau_gpuobj *vram = NULL, *tt = NULL; int ret, i; @@ -5530,7 +6849,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); /* Allocate a chunk of memory for per-channel object storage */ -@@ -956,41 +643,38 @@ +@@ -956,41 +768,38 @@ * locations determined during init. */ if (dev_priv->card_type >= NV_50) { @@ -5594,7 +6913,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 } instmem->flush(dev); -@@ -998,15 +682,17 @@ +@@ -998,15 +807,17 @@ /* RAMHT */ if (dev_priv->card_type < NV_50) { @@ -5619,7 +6938,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 if (ret) return ret; } -@@ -1023,24 +709,32 @@ +@@ -1023,24 +834,32 @@ } } else { ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, @@ -5658,7 +6977,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 } else if (dev_priv->gart_info.type != NOUVEAU_GART_NONE) { ret = nouveau_gpuobj_gart_dma_new(chan, 0, -@@ -1056,9 +750,10 @@ +@@ -1056,9 +875,10 @@ return ret; } @@ -5671,7 +6990,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 return ret; } -@@ -1070,33 +765,23 @@ +@@ -1070,33 +890,23 @@ { struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct drm_device *dev = chan->dev; @@ -5711,7 +7030,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 } int -@@ -1117,17 +802,17 @@ +@@ -1117,17 +927,17 @@ } list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) { @@ -5733,7 +7052,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 } return 0; -@@ -1172,8 +857,8 @@ +@@ -1172,8 +982,8 @@ if (!gpuobj->im_backing_suspend) continue; @@ -5744,7 +7063,15 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 dev_priv->engine.instmem.flush(dev); } -@@ -1191,8 +876,6 @@ +@@ -1183,70 +993,101 @@ + int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_grobj_alloc *init = data; +- struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; +- struct nouveau_pgraph_object_class *grc; + struct nouveau_gpuobj *gr = NULL; struct nouveau_channel *chan; int ret; @@ -5753,26 +7080,33 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 if (init->handle == ~0) return -EINVAL; -@@ -1208,45 +891,96 @@ - return -EPERM; +- grc = pgraph->grclass; +- while (grc->id) { +- if (grc->id == init->class) +- break; +- grc++; +- } ++ chan = nouveau_channel_get(dev, file_priv, init->channel); ++ if (IS_ERR(chan)) ++ return PTR_ERR(chan); + +- if (!grc->id) { +- NV_ERROR(dev, "Illegal object class: 0x%x\n", init->class); +- return -EPERM; ++ if (nouveau_ramht_find(chan, init->handle)) { ++ ret = -EEXIST; ++ goto out; } - if (nouveau_gpuobj_ref_find(chan, init->handle, NULL) == 0) - return -EEXIST; -+ chan = nouveau_channel_get(dev, file_priv, init->channel); -+ if (IS_ERR(chan)) -+ return PTR_ERR(chan); -+ -+ if (nouveau_ramht_find(chan, init->handle)) { -+ ret = -EEXIST; -+ goto out; -+ } - - if (!grc->software) - ret = nouveau_gpuobj_gr_new(chan, grc->id, &gr); - else - ret = nouveau_gpuobj_sw_new(chan, grc->id, &gr); - +- if (!grc->software) +- ret = nouveau_gpuobj_gr_new(chan, grc->id, &gr); +- else +- ret = nouveau_gpuobj_sw_new(chan, grc->id, &gr); +- ++ ret = nouveau_gpuobj_gr_new(chan, init->class, &gr); if (ret) { NV_ERROR(dev, "Error creating object: %d (%d/0x%08x)\n", ret, init->channel, init->handle); @@ -5865,9 +7199,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 + + nv_wi32(dev, gpuobj->pinst + offset, val); } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_perf.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_perf.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_perf.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_perf.c 2010-10-15 02:04:44.372992344 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_perf.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_perf.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_perf.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_perf.c 2010-10-22 23:59:52.532454152 +0200 @@ -0,0 +1,205 @@ +/* + * Copyright 2010 Red Hat Inc. @@ -6074,9 +7408,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_perf.c linux-2.6.36- +nouveau_perf_fini(struct drm_device *dev) +{ +} -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_pm.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_pm.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_pm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_pm.c 2010-10-15 02:04:44.377992406 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_pm.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_pm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.c 2010-10-22 23:59:52.533454164 +0200 @@ -0,0 +1,548 @@ +/* + * Copyright 2010 Red Hat Inc. @@ -6626,9 +7960,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_pm.c linux-2.6.36-rc + pm->cur = &pm->boot; + nouveau_pm_perflvl_set(dev, perflvl); +} -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_pm.h linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_pm.h ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_pm.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_pm.h 2010-10-15 02:04:44.379992432 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_pm.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.h +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_pm.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.h 2010-10-22 23:59:52.534454177 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright 2010 Red Hat Inc. @@ -6704,9 +8038,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_pm.h linux-2.6.36-rc +int nv84_temp_get(struct drm_device *dev); + +#endif -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_ramht.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_ramht.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_ramht.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_ramht.c 2010-10-15 02:04:44.381992457 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_ramht.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_ramht.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.c 2010-10-22 23:59:52.534454177 +0200 @@ -0,0 +1,307 @@ +/* + * Copyright 2010 Red Hat Inc. @@ -6824,7 +8158,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_ramht.c linux-2.6.36 + (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); + } else { + if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { -+ ctx = (gpuobj->cinst << 10) | 2; ++ ctx = (gpuobj->cinst << 10) | chan->id; + } else { + ctx = (gpuobj->cinst >> 4) | + ((gpuobj->engine << @@ -7015,9 +8349,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_ramht.c linux-2.6.36 + } + *ptr = ref; +} -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_ramht.h linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_ramht.h ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_ramht.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_ramht.h 2010-10-15 02:04:44.382992469 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_ramht.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.h +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_ramht.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.h 2010-10-22 23:59:52.535454190 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright 2010 Red Hat Inc. @@ -7074,10 +8408,18 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_ramht.h linux-2.6.36 +nouveau_ramht_find(struct nouveau_channel *chan, u32 handle); + +#endif -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_reg.h linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_reg.h ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_reg.h 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_reg.h 2010-10-15 02:04:44.385992505 +0200 -@@ -551,6 +551,8 @@ +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_reg.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_reg.h +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_reg.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_reg.h 2010-10-22 23:59:52.536454203 +0200 +@@ -332,6 +332,7 @@ + #define NV04_PGRAPH_BSWIZZLE5 0x004006A0 + #define NV03_PGRAPH_STATUS 0x004006B0 + #define NV04_PGRAPH_STATUS 0x00400700 ++# define NV40_PGRAPH_STATUS_SYNC_STALL 0x00004000 + #define NV04_PGRAPH_TRAPPED_ADDR 0x00400704 + #define NV04_PGRAPH_TRAPPED_DATA 0x00400708 + #define NV04_PGRAPH_SURFACE 0x0040070C +@@ -551,6 +552,8 @@ #define NV10_PFIFO_CACHE1_DMA_SUBROUTINE 0x0000324C #define NV03_PFIFO_CACHE1_PULL0 0x00003240 #define NV04_PFIFO_CACHE1_PULL0 0x00003250 @@ -7086,7 +8428,82 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_reg.h linux-2.6.36-r #define NV03_PFIFO_CACHE1_PULL1 0x00003250 #define NV04_PFIFO_CACHE1_PULL1 0x00003254 #define NV04_PFIFO_CACHE1_HASH 0x00003258 -@@ -785,15 +787,12 @@ +@@ -712,31 +715,32 @@ + #define NV50_PDISPLAY_INTR_1_CLK_UNK10 0x00000010 + #define NV50_PDISPLAY_INTR_1_CLK_UNK20 0x00000020 + #define NV50_PDISPLAY_INTR_1_CLK_UNK40 0x00000040 +-#define NV50_PDISPLAY_INTR_EN 0x0061002c +-#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC 0x0000000c +-#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(n) (1 << ((n) + 2)) +-#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_0 0x00000004 +-#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_1 0x00000008 +-#define NV50_PDISPLAY_INTR_EN_CLK_UNK10 0x00000010 +-#define NV50_PDISPLAY_INTR_EN_CLK_UNK20 0x00000020 +-#define NV50_PDISPLAY_INTR_EN_CLK_UNK40 0x00000040 ++#define NV50_PDISPLAY_INTR_EN_0 0x00610028 ++#define NV50_PDISPLAY_INTR_EN_1 0x0061002c ++#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC 0x0000000c ++#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(n) (1 << ((n) + 2)) ++#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_0 0x00000004 ++#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_1 0x00000008 ++#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 0x00000010 ++#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 0x00000020 ++#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK40 0x00000040 + #define NV50_PDISPLAY_UNK30_CTRL 0x00610030 + #define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK0 0x00000200 + #define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK1 0x00000400 + #define NV50_PDISPLAY_UNK30_CTRL_PENDING 0x80000000 +-#define NV50_PDISPLAY_TRAPPED_ADDR 0x00610080 +-#define NV50_PDISPLAY_TRAPPED_DATA 0x00610084 +-#define NV50_PDISPLAY_CHANNEL_STAT(i) ((i) * 0x10 + 0x00610200) +-#define NV50_PDISPLAY_CHANNEL_STAT_DMA 0x00000010 +-#define NV50_PDISPLAY_CHANNEL_STAT_DMA_DISABLED 0x00000000 +-#define NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED 0x00000010 +-#define NV50_PDISPLAY_CHANNEL_DMA_CB(i) ((i) * 0x10 + 0x00610204) +-#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION 0x00000002 +-#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM 0x00000000 +-#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_SYSTEM 0x00000002 +-#define NV50_PDISPLAY_CHANNEL_DMA_CB_VALID 0x00000001 +-#define NV50_PDISPLAY_CHANNEL_UNK2(i) ((i) * 0x10 + 0x00610208) +-#define NV50_PDISPLAY_CHANNEL_UNK3(i) ((i) * 0x10 + 0x0061020c) ++#define NV50_PDISPLAY_TRAPPED_ADDR(i) ((i) * 0x08 + 0x00610080) ++#define NV50_PDISPLAY_TRAPPED_DATA(i) ((i) * 0x08 + 0x00610084) ++#define NV50_PDISPLAY_EVO_CTRL(i) ((i) * 0x10 + 0x00610200) ++#define NV50_PDISPLAY_EVO_CTRL_DMA 0x00000010 ++#define NV50_PDISPLAY_EVO_CTRL_DMA_DISABLED 0x00000000 ++#define NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED 0x00000010 ++#define NV50_PDISPLAY_EVO_DMA_CB(i) ((i) * 0x10 + 0x00610204) ++#define NV50_PDISPLAY_EVO_DMA_CB_LOCATION 0x00000002 ++#define NV50_PDISPLAY_EVO_DMA_CB_LOCATION_VRAM 0x00000000 ++#define NV50_PDISPLAY_EVO_DMA_CB_LOCATION_SYSTEM 0x00000002 ++#define NV50_PDISPLAY_EVO_DMA_CB_VALID 0x00000001 ++#define NV50_PDISPLAY_EVO_UNK2(i) ((i) * 0x10 + 0x00610208) ++#define NV50_PDISPLAY_EVO_HASH_TAG(i) ((i) * 0x10 + 0x0061020c) + + #define NV50_PDISPLAY_CURSOR 0x00610270 + #define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i) ((i) * 0x10 + 0x00610270) +@@ -744,15 +748,11 @@ + #define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS 0x00030000 + #define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE 0x00010000 + +-#define NV50_PDISPLAY_CTRL_STATE 0x00610300 +-#define NV50_PDISPLAY_CTRL_STATE_PENDING 0x80000000 +-#define NV50_PDISPLAY_CTRL_STATE_METHOD 0x00001ffc +-#define NV50_PDISPLAY_CTRL_STATE_ENABLE 0x00000001 +-#define NV50_PDISPLAY_CTRL_VAL 0x00610304 +-#define NV50_PDISPLAY_UNK_380 0x00610380 +-#define NV50_PDISPLAY_RAM_AMOUNT 0x00610384 +-#define NV50_PDISPLAY_UNK_388 0x00610388 +-#define NV50_PDISPLAY_UNK_38C 0x0061038c ++#define NV50_PDISPLAY_PIO_CTRL 0x00610300 ++#define NV50_PDISPLAY_PIO_CTRL_PENDING 0x80000000 ++#define NV50_PDISPLAY_PIO_CTRL_MTHD 0x00001ffc ++#define NV50_PDISPLAY_PIO_CTRL_ENABLED 0x00000001 ++#define NV50_PDISPLAY_PIO_DATA 0x00610304 + + #define NV50_PDISPLAY_CRTC_P(i, r) ((i) * 0x540 + NV50_PDISPLAY_CRTC_##r) + #define NV50_PDISPLAY_CRTC_C(i, r) (4 + (i) * 0x540 + NV50_PDISPLAY_CRTC_##r) +@@ -785,15 +785,12 @@ #define NV50_PDISPLAY_DAC_MODE_CTRL_C(i) (0x00610b5c + (i) * 0x8) #define NV50_PDISPLAY_SOR_MODE_CTRL_P(i) (0x00610b70 + (i) * 0x8) #define NV50_PDISPLAY_SOR_MODE_CTRL_C(i) (0x00610b74 + (i) * 0x8) @@ -7104,9 +8521,21 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_reg.h linux-2.6.36-r #define NV50_PDISPLAY_CRTC_CLK 0x00614000 #define NV50_PDISPLAY_CRTC_CLK_CTRL1(i) ((i) * 0x800 + 0x614100) -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_sgdma.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2010-10-15 02:04:44.387992531 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_sgdma.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2010-10-22 23:59:52.538454228 +0200 +@@ -95,9 +95,9 @@ + struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; + unsigned i, j, pte; + +- NV_DEBUG(dev, "pg=0x%lx\n", mem->mm_node->start); ++ NV_DEBUG(dev, "pg=0x%lx\n", mem->start); + +- pte = nouveau_sgdma_pte(nvbe->dev, mem->mm_node->start << PAGE_SHIFT); ++ pte = nouveau_sgdma_pte(nvbe->dev, mem->start << PAGE_SHIFT); + nvbe->pte_start = pte; + for (i = 0; i < nvbe->nr_pages; i++) { + dma_addr_t dma_offset = nvbe->pages[i]; @@ -105,11 +105,13 @@ uint32_t offset_h = upper_32_bits(dma_offset); @@ -7145,7 +8574,20 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.36 } dma_offset += NV_CTXDMA_PAGE_SIZE; -@@ -230,7 +234,6 @@ +@@ -220,7 +224,11 @@ + int i, ret; + + if (dev_priv->card_type < NV_50) { +- aper_size = (64 * 1024 * 1024); ++ if(dev_priv->card_type < NV_40) { ++ aper_size = (64 * 1024 * 1024); ++ } else { ++ aper_size = (512 * 1024 * 1024); ++ } + obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4; + obj_size += 8; /* ctxdma header */ + } else { +@@ -230,7 +238,6 @@ } ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, @@ -7153,7 +8595,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.36 NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, &gpuobj); if (ret) { -@@ -239,9 +242,9 @@ +@@ -239,9 +246,9 @@ } dev_priv->gart_info.sg_dummy_page = @@ -7165,7 +8607,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.36 return -ENOMEM; } -@@ -250,29 +253,34 @@ +@@ -250,29 +257,34 @@ pci_map_page(pdev, dev_priv->gart_info.sg_dummy_page, 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); if (pci_dma_mapping_error(pdev, dev_priv->gart_info.sg_dummy_bus)) { @@ -7212,7 +8654,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.36 } } dev_priv->engine.instmem.flush(dev); -@@ -298,7 +306,7 @@ +@@ -298,7 +310,7 @@ dev_priv->gart_info.sg_dummy_bus = 0; } @@ -7221,7 +8663,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.36 } int -@@ -308,9 +316,9 @@ +@@ -308,9 +320,9 @@ struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; int pte; @@ -7233,9 +8675,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.36 return 0; } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_state.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_state.c 2010-10-15 02:04:44.389992556 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_state.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_state.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_state.c 2010-10-22 23:59:52.540454252 +0200 @@ -35,6 +35,8 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" @@ -7245,7 +8687,15 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 #include "nv50_display.h" static void nouveau_stub_takedown(struct drm_device *dev) {} -@@ -78,7 +80,6 @@ +@@ -63,7 +65,6 @@ + engine->timer.takedown = nv04_timer_takedown; + engine->fb.init = nv04_fb_init; + engine->fb.takedown = nv04_fb_takedown; +- engine->graph.grclass = nv04_graph_grclass; + engine->graph.init = nv04_graph_init; + engine->graph.takedown = nv04_graph_takedown; + engine->graph.fifo_access = nv04_graph_fifo_access; +@@ -78,7 +79,6 @@ engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; @@ -7253,17 +8703,27 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv04_fifo_channel_id; engine->fifo.create_context = nv04_fifo_create_context; -@@ -95,6 +96,9 @@ +@@ -95,6 +95,11 @@ engine->gpio.get = NULL; engine->gpio.set = NULL; engine->gpio.irq_enable = NULL; + engine->pm.clock_get = nv04_pm_clock_get; + engine->pm.clock_pre = nv04_pm_clock_pre; + engine->pm.clock_set = nv04_pm_clock_set; ++ engine->crypt.init = nouveau_stub_init; ++ engine->crypt.takedown = nouveau_stub_takedown; break; case 0x10: engine->instmem.init = nv04_instmem_init; -@@ -130,7 +134,6 @@ +@@ -114,7 +119,6 @@ + engine->fb.init = nv10_fb_init; + engine->fb.takedown = nv10_fb_takedown; + engine->fb.set_region_tiling = nv10_fb_set_region_tiling; +- engine->graph.grclass = nv10_graph_grclass; + engine->graph.init = nv10_graph_init; + engine->graph.takedown = nv10_graph_takedown; + engine->graph.channel = nv10_graph_channel; +@@ -130,11 +134,10 @@ engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; @@ -7271,17 +8731,32 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv10_fifo_create_context; -@@ -147,6 +150,9 @@ +- engine->fifo.destroy_context = nv10_fifo_destroy_context; ++ engine->fifo.destroy_context = nv04_fifo_destroy_context; + engine->fifo.load_context = nv10_fifo_load_context; + engine->fifo.unload_context = nv10_fifo_unload_context; + engine->display.early_init = nv04_display_early_init; +@@ -147,6 +150,11 @@ engine->gpio.get = nv10_gpio_get; engine->gpio.set = nv10_gpio_set; engine->gpio.irq_enable = NULL; + engine->pm.clock_get = nv04_pm_clock_get; + engine->pm.clock_pre = nv04_pm_clock_pre; + engine->pm.clock_set = nv04_pm_clock_set; ++ engine->crypt.init = nouveau_stub_init; ++ engine->crypt.takedown = nouveau_stub_takedown; break; case 0x20: engine->instmem.init = nv04_instmem_init; -@@ -182,7 +188,6 @@ +@@ -166,7 +174,6 @@ + engine->fb.init = nv10_fb_init; + engine->fb.takedown = nv10_fb_takedown; + engine->fb.set_region_tiling = nv10_fb_set_region_tiling; +- engine->graph.grclass = nv20_graph_grclass; + engine->graph.init = nv20_graph_init; + engine->graph.takedown = nv20_graph_takedown; + engine->graph.channel = nv10_graph_channel; +@@ -182,11 +189,10 @@ engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; @@ -7289,17 +8764,32 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv10_fifo_create_context; -@@ -199,6 +204,9 @@ +- engine->fifo.destroy_context = nv10_fifo_destroy_context; ++ engine->fifo.destroy_context = nv04_fifo_destroy_context; + engine->fifo.load_context = nv10_fifo_load_context; + engine->fifo.unload_context = nv10_fifo_unload_context; + engine->display.early_init = nv04_display_early_init; +@@ -199,6 +205,11 @@ engine->gpio.get = nv10_gpio_get; engine->gpio.set = nv10_gpio_set; engine->gpio.irq_enable = NULL; + engine->pm.clock_get = nv04_pm_clock_get; + engine->pm.clock_pre = nv04_pm_clock_pre; + engine->pm.clock_set = nv04_pm_clock_set; ++ engine->crypt.init = nouveau_stub_init; ++ engine->crypt.takedown = nouveau_stub_takedown; break; case 0x30: engine->instmem.init = nv04_instmem_init; -@@ -234,7 +242,6 @@ +@@ -218,7 +229,6 @@ + engine->fb.init = nv30_fb_init; + engine->fb.takedown = nv30_fb_takedown; + engine->fb.set_region_tiling = nv10_fb_set_region_tiling; +- engine->graph.grclass = nv30_graph_grclass; + engine->graph.init = nv30_graph_init; + engine->graph.takedown = nv20_graph_takedown; + engine->graph.fifo_access = nv04_graph_fifo_access; +@@ -234,11 +244,10 @@ engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; @@ -7307,7 +8797,12 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv10_fifo_create_context; -@@ -251,6 +258,11 @@ +- engine->fifo.destroy_context = nv10_fifo_destroy_context; ++ engine->fifo.destroy_context = nv04_fifo_destroy_context; + engine->fifo.load_context = nv10_fifo_load_context; + engine->fifo.unload_context = nv10_fifo_unload_context; + engine->display.early_init = nv04_display_early_init; +@@ -251,6 +260,13 @@ engine->gpio.get = nv10_gpio_get; engine->gpio.set = nv10_gpio_set; engine->gpio.irq_enable = NULL; @@ -7316,10 +8811,20 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 + engine->pm.clock_set = nv04_pm_clock_set; + engine->pm.voltage_get = nouveau_voltage_gpio_get; + engine->pm.voltage_set = nouveau_voltage_gpio_set; ++ engine->crypt.init = nouveau_stub_init; ++ engine->crypt.takedown = nouveau_stub_takedown; break; case 0x40: case 0x60: -@@ -287,7 +299,6 @@ +@@ -271,7 +287,6 @@ + engine->fb.init = nv40_fb_init; + engine->fb.takedown = nv40_fb_takedown; + engine->fb.set_region_tiling = nv40_fb_set_region_tiling; +- engine->graph.grclass = nv40_graph_grclass; + engine->graph.init = nv40_graph_init; + engine->graph.takedown = nv40_graph_takedown; + engine->graph.fifo_access = nv04_graph_fifo_access; +@@ -287,11 +302,10 @@ engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; @@ -7327,7 +8832,12 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv40_fifo_create_context; -@@ -304,6 +315,12 @@ +- engine->fifo.destroy_context = nv40_fifo_destroy_context; ++ engine->fifo.destroy_context = nv04_fifo_destroy_context; + engine->fifo.load_context = nv40_fifo_load_context; + engine->fifo.unload_context = nv40_fifo_unload_context; + engine->display.early_init = nv04_display_early_init; +@@ -304,6 +318,14 @@ engine->gpio.get = nv10_gpio_get; engine->gpio.set = nv10_gpio_set; engine->gpio.irq_enable = NULL; @@ -7337,27 +8847,43 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 + engine->pm.voltage_get = nouveau_voltage_gpio_get; + engine->pm.voltage_set = nouveau_voltage_gpio_set; + engine->pm.temp_get = nv40_temp_get; ++ engine->crypt.init = nouveau_stub_init; ++ engine->crypt.takedown = nouveau_stub_takedown; break; case 0x50: case 0x80: /* gotta love NVIDIA's consistency.. */ -@@ -358,6 +375,27 @@ +@@ -328,7 +350,6 @@ + engine->timer.takedown = nv04_timer_takedown; + engine->fb.init = nv50_fb_init; + engine->fb.takedown = nv50_fb_takedown; +- engine->graph.grclass = nv50_graph_grclass; + engine->graph.init = nv50_graph_init; + engine->graph.takedown = nv50_graph_takedown; + engine->graph.fifo_access = nv50_graph_fifo_access; +@@ -358,6 +379,50 @@ engine->gpio.get = nv50_gpio_get; engine->gpio.set = nv50_gpio_set; engine->gpio.irq_enable = nv50_gpio_irq_enable; + switch (dev_priv->chipset) { -+ case 0xa3: -+ case 0xa5: -+ case 0xa8: -+ case 0xaf: -+ engine->pm.clock_get = nva3_pm_clock_get; -+ engine->pm.clock_pre = nva3_pm_clock_pre; -+ engine->pm.clock_set = nva3_pm_clock_set; -+ break; -+ default: ++ case 0x84: ++ case 0x86: ++ case 0x92: ++ case 0x94: ++ case 0x96: ++ case 0x98: ++ case 0xa0: ++ case 0xaa: ++ case 0xac: ++ case 0x50: + engine->pm.clock_get = nv50_pm_clock_get; + engine->pm.clock_pre = nv50_pm_clock_pre; + engine->pm.clock_set = nv50_pm_clock_set; + break; ++ default: ++ engine->pm.clock_get = nva3_pm_clock_get; ++ engine->pm.clock_pre = nva3_pm_clock_pre; ++ engine->pm.clock_set = nva3_pm_clock_set; ++ break; + } + engine->pm.voltage_get = nouveau_voltage_gpio_get; + engine->pm.voltage_set = nouveau_voltage_gpio_set; @@ -7365,10 +8891,44 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 + engine->pm.temp_get = nv84_temp_get; + else + engine->pm.temp_get = nv40_temp_get; ++ switch (dev_priv->chipset) { ++ case 0x84: ++ case 0x86: ++ case 0x92: ++ case 0x94: ++ case 0x96: ++ case 0xa0: ++ engine->crypt.init = nv84_crypt_init; ++ engine->crypt.takedown = nv84_crypt_fini; ++ engine->crypt.create_context = nv84_crypt_create_context; ++ engine->crypt.destroy_context = nv84_crypt_destroy_context; ++ break; ++ default: ++ engine->crypt.init = nouveau_stub_init; ++ engine->crypt.takedown = nouveau_stub_takedown; ++ break; ++ } break; case 0xC0: engine->instmem.init = nvc0_instmem_init; -@@ -437,16 +475,14 @@ +@@ -376,7 +441,6 @@ + engine->timer.takedown = nv04_timer_takedown; + engine->fb.init = nvc0_fb_init; + engine->fb.takedown = nvc0_fb_takedown; +- engine->graph.grclass = NULL; //nvc0_graph_grclass; + engine->graph.init = nvc0_graph_init; + engine->graph.takedown = nvc0_graph_takedown; + engine->graph.fifo_access = nvc0_graph_fifo_access; +@@ -406,6 +470,8 @@ + engine->gpio.get = nv50_gpio_get; + engine->gpio.set = nv50_gpio_set; + engine->gpio.irq_enable = nv50_gpio_irq_enable; ++ engine->crypt.init = nouveau_stub_init; ++ engine->crypt.takedown = nouveau_stub_takedown; + break; + default: + NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); +@@ -437,16 +503,14 @@ nouveau_card_init_channel(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -7387,7 +8947,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, 0, dev_priv->vram_size, NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, -@@ -454,28 +490,27 @@ +@@ -454,28 +518,27 @@ if (ret) goto out_err; @@ -7423,7 +8983,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 return ret; } -@@ -522,6 +557,7 @@ +@@ -522,6 +585,7 @@ if (ret) goto out; engine = &dev_priv->engine; @@ -7431,7 +8991,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 spin_lock_init(&dev_priv->context_switch_lock); /* Make the CRTCs and I2C buses accessible */ -@@ -534,35 +570,28 @@ +@@ -534,35 +598,28 @@ if (ret) goto out_display_early; @@ -7475,7 +9035,41 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 /* PGPIO */ ret = engine->gpio.init(dev); -@@ -611,9 +640,13 @@ +@@ -587,33 +644,39 @@ + if (ret) + goto out_fb; + ++ /* PCRYPT */ ++ ret = engine->crypt.init(dev); ++ if (ret) ++ goto out_graph; ++ + /* PFIFO */ + ret = engine->fifo.init(dev); + if (ret) +- goto out_graph; ++ goto out_crypt; + } + + ret = engine->display.create(dev); + if (ret) + goto out_fifo; + +- /* this call irq_preinstall, register irq handler and +- * call irq_postinstall +- */ +- ret = drm_irq_install(dev); ++ ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1); + if (ret) +- goto out_display; ++ goto out_vblank; + +- ret = drm_vblank_init(dev, 0); ++ ret = nouveau_irq_init(dev); + if (ret) +- goto out_irq; ++ goto out_vblank; + /* what about PVIDEO/PCRTC/PRAMDAC etc? */ if (!engine->graph.accel_blocked) { @@ -7490,16 +9084,29 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 } ret = nouveau_backlight_init(dev); -@@ -624,6 +657,8 @@ +@@ -624,13 +687,19 @@ drm_kms_helper_poll_init(dev); return 0; +out_fence: + nouveau_fence_fini(dev); out_irq: - drm_irq_uninstall(dev); - out_display: -@@ -642,16 +677,16 @@ +- drm_irq_uninstall(dev); +-out_display: ++ nouveau_irq_fini(dev); ++out_vblank: ++ drm_vblank_cleanup(dev); + engine->display.destroy(dev); + out_fifo: + if (!nouveau_noaccel) + engine->fifo.takedown(dev); ++out_crypt: ++ if (!nouveau_noaccel) ++ engine->crypt.takedown(dev); + out_graph: + if (!nouveau_noaccel) + engine->graph.takedown(dev); +@@ -642,16 +711,16 @@ engine->gpio.takedown(dev); out_mc: engine->mc.takedown(dev); @@ -7523,7 +9130,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 nouveau_bios_takedown(dev); out_display_early: engine->display.late_takedown(dev); -@@ -667,9 +702,9 @@ +@@ -667,13 +736,14 @@ nouveau_backlight_exit(dev); @@ -7532,11 +9139,16 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 - dev_priv->channel = NULL; + if (!engine->graph.accel_blocked) { + nouveau_fence_fini(dev); -+ nouveau_channel_put(&dev_priv->channel); ++ nouveau_channel_put_unlocked(&dev_priv->channel); } if (!nouveau_noaccel) { -@@ -686,15 +721,15 @@ + engine->fifo.takedown(dev); ++ engine->crypt.takedown(dev); + engine->graph.takedown(dev); + } + engine->fb.takedown(dev); +@@ -686,15 +756,16 @@ ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); mutex_unlock(&dev->struct_mutex); @@ -7549,24 +9161,29 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 + nouveau_gpuobj_takedown(dev); + nouveau_mem_vram_fini(dev); - drm_irq_uninstall(dev); +- drm_irq_uninstall(dev); ++ nouveau_irq_fini(dev); ++ drm_vblank_cleanup(dev); - nouveau_gpuobj_late_takedown(dev); + nouveau_pm_fini(dev); nouveau_bios_takedown(dev); vga_client_register(dev->pdev, NULL, NULL, NULL); -@@ -1006,6 +1041,9 @@ +@@ -1006,6 +1077,12 @@ case NOUVEAU_GETPARAM_PTIMER_TIME: getparam->value = dev_priv->engine.timer.read(dev); break; + case NOUVEAU_GETPARAM_HAS_BO_USAGE: + getparam->value = 1; ++ break; ++ case NOUVEAU_GETPARAM_HAS_PAGEFLIP: ++ getparam->value = (dev_priv->card_type < NV_50); + break; case NOUVEAU_GETPARAM_GRAPH_UNITS: /* NV40 and NV50 versions are quite different, but register * address is the same. User is supposed to know the card -@@ -1016,7 +1054,7 @@ +@@ -1016,7 +1093,7 @@ } /* FALLTHRU */ default: @@ -7575,7 +9192,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 return -EINVAL; } -@@ -1031,7 +1069,7 @@ +@@ -1031,7 +1108,7 @@ switch (setparam->param) { default: @@ -7584,18 +9201,24 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.36 return -EINVAL; } -@@ -1057,7 +1095,7 @@ +@@ -1057,7 +1134,13 @@ /* Waits for PGRAPH to go completely idle */ bool nouveau_wait_for_idle(struct drm_device *dev) { - if (!nv_wait(NV04_PGRAPH_STATUS, 0xffffffff, 0x00000000)) { -+ if (!nv_wait(dev, NV04_PGRAPH_STATUS, 0xffffffff, 0x00000000)) { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ uint32_t mask = ~0; ++ ++ if (dev_priv->card_type == NV_40) ++ mask &= ~NV40_PGRAPH_STATUS_SYNC_STALL; ++ ++ if (!nv_wait(dev, NV04_PGRAPH_STATUS, mask, 0)) { NV_ERROR(dev, "PGRAPH idle timed out with status 0x%08x\n", nv_rd32(dev, NV04_PGRAPH_STATUS)); return false; -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_temp.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_temp.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_temp.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_temp.c 2010-10-15 02:04:44.391992580 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_temp.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_temp.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_temp.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_temp.c 2010-10-22 23:59:52.546454326 +0200 @@ -0,0 +1,309 @@ +/* + * Copyright 2010 PathScale inc. @@ -7906,9 +9529,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_temp.c linux-2.6.36- +{ + +} -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_volt.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_volt.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_volt.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nouveau_volt.c 2010-10-15 02:04:44.392992593 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_volt.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_volt.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nouveau_volt.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nouveau_volt.c 2010-10-22 23:59:52.547454339 +0200 @@ -0,0 +1,212 @@ +/* + * Copyright 2010 Red Hat Inc. @@ -8122,9 +9745,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nouveau_volt.c linux-2.6.36- + + kfree(volt->level); +} -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_crtc.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_crtc.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_crtc.c 2010-10-15 02:04:44.394992618 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_crtc.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_crtc.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_crtc.c 2010-10-22 23:59:52.550454376 +0200 @@ -109,7 +109,7 @@ struct nouveau_pll_vals *pv = ®p->pllvals; struct pll_lims pll_lim; @@ -8134,7 +9757,38 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.36-rc7 return; /* NM2 == 0 is used to determine single stage mode on two stage plls */ -@@ -718,6 +718,7 @@ +@@ -157,7 +157,6 @@ + { + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct drm_device *dev = crtc->dev; +- struct drm_connector *connector; + unsigned char seq1 = 0, crtc17 = 0; + unsigned char crtc1A; + +@@ -212,10 +211,6 @@ + NVVgaSeqReset(dev, nv_crtc->index, false); + + NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A); +- +- /* Update connector polling modes */ +- list_for_each_entry(connector, &dev->mode_config.connector_list, head) +- nouveau_connector_set_polling(connector); + } + + static bool +@@ -555,7 +550,10 @@ + if (dev_priv->card_type >= NV_30) + regp->gpio_ext = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT); + +- regp->crtc_cfg = NV_PCRTC_CONFIG_START_ADDRESS_HSYNC; ++ if (dev_priv->card_type >= NV_10) ++ regp->crtc_cfg = NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC; ++ else ++ regp->crtc_cfg = NV04_PCRTC_CONFIG_START_ADDRESS_HSYNC; + + /* Some misc regs */ + if (dev_priv->card_type == NV_40) { +@@ -718,6 +716,7 @@ drm_crtc_cleanup(crtc); @@ -8142,7 +9796,16 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.36-rc7 nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); kfree(nv_crtc); } -@@ -826,7 +827,7 @@ +@@ -815,7 +814,7 @@ + /* Update the framebuffer location. */ + regp->fb_start = nv_crtc->fb.offset & ~3; + regp->fb_start += (y * drm_fb->pitch) + (x * drm_fb->bits_per_pixel / 8); +- NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_START, regp->fb_start); ++ nv_set_crtc_base(dev, nv_crtc->index, regp->fb_start); + + /* Update the arbitration parameters. */ + nouveau_calc_arb(dev, crtc->mode.clock, drm_fb->bits_per_pixel, +@@ -826,7 +825,7 @@ crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FF_INDEX); crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FFLWM__INDEX); @@ -8151,9 +9814,17 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.36-rc7 regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8; crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47); } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_dac.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_dac.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_dac.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_dac.c 2010-10-15 02:04:44.396992642 +0200 +@@ -952,6 +951,7 @@ + .cursor_move = nv04_crtc_cursor_move, + .gamma_set = nv_crtc_gamma_set, + .set_config = drm_crtc_helper_set_config, ++ .page_flip = nouveau_crtc_page_flip, + .destroy = nv_crtc_destroy, + }; + +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_dac.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_dac.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_dac.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_dac.c 2010-10-22 23:59:52.552454400 +0200 @@ -291,6 +291,8 @@ msleep(5); @@ -8186,9 +9857,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_dac.c linux-2.6.36-rc7. static void nv04_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_dfp.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_dfp.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_dfp.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_dfp.c 2010-10-15 02:04:44.398992668 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_dfp.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_dfp.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_dfp.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_dfp.c 2010-10-22 23:59:52.553454412 +0200 @@ -104,6 +104,8 @@ } /* don't inadvertently turn it on when state written later */ @@ -8270,9 +9941,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_dfp.c linux-2.6.36-rc7. if (type < 0) return; -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_fbcon.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_fbcon.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_fbcon.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_fbcon.c 2010-10-15 02:04:44.399992681 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_fbcon.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_fbcon.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_fbcon.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_fbcon.c 2010-10-22 23:59:52.554454424 +0200 @@ -25,54 +25,42 @@ #include "drmP.h" #include "nouveau_drv.h" @@ -8420,9 +10091,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_fbcon.c linux-2.6.36-rc } int -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_fifo.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_fifo.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_fifo.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_fifo.c 2010-10-15 02:04:44.401992705 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_fifo.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_fifo.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_fifo.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_fifo.c 2010-10-22 23:59:52.555454436 +0200 @@ -27,8 +27,9 @@ #include "drmP.h" #include "drm.h" @@ -8523,16 +10194,39 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_fifo.c linux-2.6.36-rc7 RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | -@@ -161,7 +155,7 @@ - nv_wr32(dev, NV04_PFIFO_MODE, - nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); +@@ -157,11 +151,28 @@ + nv04_fifo_destroy_context(struct nouveau_channel *chan) + { + struct drm_device *dev = chan->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; ++ unsigned long flags; + +- nv_wr32(dev, NV04_PFIFO_MODE, +- nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ pfifo->reassign(dev, false); ++ ++ /* Unload the context if it's the currently active one */ ++ if (pfifo->channel_id(dev) == chan->id) { ++ pfifo->disable(dev); ++ pfifo->unload_context(dev); ++ pfifo->enable(dev); ++ } ++ ++ /* Keep it from being rescheduled */ ++ nv_mask(dev, NV04_PFIFO_MODE, 1 << chan->id, 0); ++ ++ pfifo->reassign(dev, true); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - nouveau_gpuobj_ref_del(dev, &chan->ramfc); ++ /* Free the channel resources */ + nouveau_gpuobj_ref(NULL, &chan->ramfc); } static void -@@ -214,7 +208,7 @@ +@@ -214,7 +225,7 @@ if (chid < 0 || chid >= dev_priv->engine.fifo.channels) return 0; @@ -8541,7 +10235,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_fifo.c linux-2.6.36-rc7 if (!chan) { NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid); return -EINVAL; -@@ -264,10 +258,10 @@ +@@ -264,10 +275,10 @@ struct drm_nouveau_private *dev_priv = dev->dev_private; nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | @@ -8556,7 +10250,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_fifo.c linux-2.6.36-rc7 } static void -@@ -295,7 +289,7 @@ +@@ -295,7 +306,7 @@ pfifo->reassign(dev, true); for (i = 0; i < dev_priv->engine.fifo.channels; i++) { @@ -8565,10 +10259,20 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_fifo.c linux-2.6.36-rc7 uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_graph.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_graph.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_graph.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_graph.c 2010-10-15 02:04:44.402992717 +0200 -@@ -357,7 +357,7 @@ +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_graph.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_graph.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_graph.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_graph.c 2010-10-22 23:59:52.557454462 +0200 +@@ -26,6 +26,9 @@ + #include "drm.h" + #include "nouveau_drm.h" + #include "nouveau_drv.h" ++#include "nouveau_hw.h" ++ ++static int nv04_graph_register(struct drm_device *dev); + + static uint32_t nv04_graph_ctx_regs[] = { + 0x0040053c, +@@ -357,7 +360,7 @@ if (chid >= dev_priv->engine.fifo.channels) return NULL; @@ -8577,7 +10281,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_graph.c linux-2.6.36-rc } void -@@ -376,7 +376,7 @@ +@@ -376,7 +379,7 @@ /* Load context for next channel */ chid = dev_priv->engine.fifo.channel_id(dev); @@ -8586,9 +10290,742 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_graph.c linux-2.6.36-rc if (chan) nv04_graph_load_context(chan); -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_instmem.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_instmem.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_instmem.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_instmem.c 2010-10-15 02:04:44.404992741 +0200 +@@ -412,10 +415,25 @@ + + void nv04_graph_destroy_context(struct nouveau_channel *chan) + { ++ struct drm_device *dev = chan->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct graph_state *pgraph_ctx = chan->pgraph_ctx; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ pgraph->fifo_access(dev, false); ++ ++ /* Unload the context if it's the currently active one */ ++ if (pgraph->channel(dev) == chan) ++ pgraph->unload_context(dev); + ++ /* Free the context resources */ + kfree(pgraph_ctx); + chan->pgraph_ctx = NULL; ++ ++ pgraph->fifo_access(dev, true); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + } + + int nv04_graph_load_context(struct nouveau_channel *chan) +@@ -468,12 +486,17 @@ + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t tmp; ++ int ret; + + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & + ~NV_PMC_ENABLE_PGRAPH); + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | + NV_PMC_ENABLE_PGRAPH); + ++ ret = nv04_graph_register(dev); ++ if (ret) ++ return ret; ++ + /* Enable PGRAPH interrupts */ + nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF); + nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); +@@ -524,13 +547,27 @@ + } + + static int +-nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_set_ref(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + atomic_set(&chan->fence.last_sequence_irq, data); + return 0; + } + ++int ++nv04_graph_mthd_page_flip(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) ++{ ++ struct drm_device *dev = chan->dev; ++ struct nouveau_page_flip_state s; ++ ++ if (!nouveau_finish_page_flip(chan, &s)) ++ nv_set_crtc_base(dev, s.crtc, ++ s.offset + s.y * s.pitch + s.x * s.bpp / 8); ++ ++ return 0; ++} ++ + /* + * Software methods, why they are needed, and how they all work: + * +@@ -606,12 +643,12 @@ + */ + + static void +-nv04_graph_set_ctx1(struct nouveau_channel *chan, uint32_t mask, uint32_t value) ++nv04_graph_set_ctx1(struct nouveau_channel *chan, u32 mask, u32 value) + { + struct drm_device *dev = chan->dev; +- uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; ++ u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; + int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; +- uint32_t tmp; ++ u32 tmp; + + tmp = nv_ri32(dev, instance); + tmp &= ~mask; +@@ -623,11 +660,11 @@ + } + + static void +-nv04_graph_set_ctx_val(struct nouveau_channel *chan, uint32_t mask, uint32_t value) ++nv04_graph_set_ctx_val(struct nouveau_channel *chan, u32 mask, u32 value) + { + struct drm_device *dev = chan->dev; +- uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; +- uint32_t tmp, ctx1; ++ u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; ++ u32 tmp, ctx1; + int class, op, valid = 1; + + ctx1 = nv_ri32(dev, instance); +@@ -672,13 +709,13 @@ + } + + static int +-nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_set_operation(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + if (data > 5) + return 1; + /* Old versions of the objects only accept first three operations. */ +- if (data > 2 && grclass < 0x40) ++ if (data > 2 && class < 0x40) + return 1; + nv04_graph_set_ctx1(chan, 0x00038000, data << 15); + /* changing operation changes set of objects needed for validation */ +@@ -687,8 +724,8 @@ + } + + static int +-nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + uint32_t min = data & 0xffff, max; + uint32_t w = data >> 16; +@@ -706,8 +743,8 @@ + } + + static int +-nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + uint32_t min = data & 0xffff, max; + uint32_t w = data >> 16; +@@ -725,8 +762,8 @@ + } + + static int +-nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: +@@ -742,8 +779,8 @@ + } + + static int +-nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: +@@ -763,8 +800,8 @@ + } + + static int +-nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: +@@ -778,8 +815,8 @@ + } + + static int +-nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: +@@ -793,8 +830,8 @@ + } + + static int +-nv04_graph_mthd_bind_rop(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_bind_rop(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: +@@ -808,8 +845,8 @@ + } + + static int +-nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: +@@ -823,8 +860,8 @@ + } + + static int +-nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: +@@ -838,8 +875,8 @@ + } + + static int +-nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: +@@ -853,8 +890,8 @@ + } + + static int +-nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: +@@ -868,8 +905,8 @@ + } + + static int +-nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: +@@ -883,8 +920,8 @@ + } + + static int +-nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: +@@ -898,8 +935,8 @@ + } + + static int +-nv04_graph_mthd_bind_clip(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_bind_clip(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: +@@ -913,8 +950,8 @@ + } + + static int +-nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + switch (nv_ri32(chan->dev, data << 4) & 0xff) { + case 0x30: +@@ -930,194 +967,260 @@ + return 1; + } + +-static struct nouveau_pgraph_object_method nv04_graph_mthds_sw[] = { +- { 0x0150, nv04_graph_mthd_set_ref }, +- {} +-}; +- +-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_gdirect[] = { +- { 0x0184, nv04_graph_mthd_bind_nv01_patt }, +- { 0x0188, nv04_graph_mthd_bind_rop }, +- { 0x018c, nv04_graph_mthd_bind_beta1 }, +- { 0x0190, nv04_graph_mthd_bind_surf_dst }, +- { 0x02fc, nv04_graph_mthd_set_operation }, +- {}, +-}; +- +-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_gdirect[] = { +- { 0x0188, nv04_graph_mthd_bind_nv04_patt }, +- { 0x018c, nv04_graph_mthd_bind_rop }, +- { 0x0190, nv04_graph_mthd_bind_beta1 }, +- { 0x0194, nv04_graph_mthd_bind_beta4 }, +- { 0x0198, nv04_graph_mthd_bind_surf2d }, +- { 0x02fc, nv04_graph_mthd_set_operation }, +- {}, +-}; +- +-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_imageblit[] = { +- { 0x0184, nv04_graph_mthd_bind_chroma }, +- { 0x0188, nv04_graph_mthd_bind_clip }, +- { 0x018c, nv04_graph_mthd_bind_nv01_patt }, +- { 0x0190, nv04_graph_mthd_bind_rop }, +- { 0x0194, nv04_graph_mthd_bind_beta1 }, +- { 0x0198, nv04_graph_mthd_bind_surf_dst }, +- { 0x019c, nv04_graph_mthd_bind_surf_src }, +- { 0x02fc, nv04_graph_mthd_set_operation }, +- {}, +-}; +- +-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_imageblit_ifc[] = { +- { 0x0184, nv04_graph_mthd_bind_chroma }, +- { 0x0188, nv04_graph_mthd_bind_clip }, +- { 0x018c, nv04_graph_mthd_bind_nv04_patt }, +- { 0x0190, nv04_graph_mthd_bind_rop }, +- { 0x0194, nv04_graph_mthd_bind_beta1 }, +- { 0x0198, nv04_graph_mthd_bind_beta4 }, +- { 0x019c, nv04_graph_mthd_bind_surf2d }, +- { 0x02fc, nv04_graph_mthd_set_operation }, +- {}, +-}; +- +-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_iifc[] = { +- { 0x0188, nv04_graph_mthd_bind_chroma }, +- { 0x018c, nv04_graph_mthd_bind_clip }, +- { 0x0190, nv04_graph_mthd_bind_nv04_patt }, +- { 0x0194, nv04_graph_mthd_bind_rop }, +- { 0x0198, nv04_graph_mthd_bind_beta1 }, +- { 0x019c, nv04_graph_mthd_bind_beta4 }, +- { 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf }, +- { 0x03e4, nv04_graph_mthd_set_operation }, +- {}, +-}; +- +-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_ifc[] = { +- { 0x0184, nv04_graph_mthd_bind_chroma }, +- { 0x0188, nv04_graph_mthd_bind_clip }, +- { 0x018c, nv04_graph_mthd_bind_nv01_patt }, +- { 0x0190, nv04_graph_mthd_bind_rop }, +- { 0x0194, nv04_graph_mthd_bind_beta1 }, +- { 0x0198, nv04_graph_mthd_bind_surf_dst }, +- { 0x02fc, nv04_graph_mthd_set_operation }, +- {}, +-}; +- +-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_sifc[] = { +- { 0x0184, nv04_graph_mthd_bind_chroma }, +- { 0x0188, nv04_graph_mthd_bind_nv01_patt }, +- { 0x018c, nv04_graph_mthd_bind_rop }, +- { 0x0190, nv04_graph_mthd_bind_beta1 }, +- { 0x0194, nv04_graph_mthd_bind_surf_dst }, +- { 0x02fc, nv04_graph_mthd_set_operation }, +- {}, +-}; +- +-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_sifc[] = { +- { 0x0184, nv04_graph_mthd_bind_chroma }, +- { 0x0188, nv04_graph_mthd_bind_nv04_patt }, +- { 0x018c, nv04_graph_mthd_bind_rop }, +- { 0x0190, nv04_graph_mthd_bind_beta1 }, +- { 0x0194, nv04_graph_mthd_bind_beta4 }, +- { 0x0198, nv04_graph_mthd_bind_surf2d }, +- { 0x02fc, nv04_graph_mthd_set_operation }, +- {}, +-}; +- +-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_sifm[] = { +- { 0x0188, nv04_graph_mthd_bind_nv01_patt }, +- { 0x018c, nv04_graph_mthd_bind_rop }, +- { 0x0190, nv04_graph_mthd_bind_beta1 }, +- { 0x0194, nv04_graph_mthd_bind_surf_dst }, +- { 0x0304, nv04_graph_mthd_set_operation }, +- {}, +-}; +- +-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_sifm[] = { +- { 0x0188, nv04_graph_mthd_bind_nv04_patt }, +- { 0x018c, nv04_graph_mthd_bind_rop }, +- { 0x0190, nv04_graph_mthd_bind_beta1 }, +- { 0x0194, nv04_graph_mthd_bind_beta4 }, +- { 0x0198, nv04_graph_mthd_bind_surf2d_swzsurf }, +- { 0x0304, nv04_graph_mthd_set_operation }, +- {}, +-}; ++static int ++nv04_graph_register(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; + +-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_shape[] = { +- { 0x0184, nv04_graph_mthd_bind_clip }, +- { 0x0188, nv04_graph_mthd_bind_nv01_patt }, +- { 0x018c, nv04_graph_mthd_bind_rop }, +- { 0x0190, nv04_graph_mthd_bind_beta1 }, +- { 0x0194, nv04_graph_mthd_bind_surf_dst }, +- { 0x02fc, nv04_graph_mthd_set_operation }, +- {}, +-}; ++ if (dev_priv->engine.graph.registered) ++ return 0; + +-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_shape[] = { +- { 0x0184, nv04_graph_mthd_bind_clip }, +- { 0x0188, nv04_graph_mthd_bind_nv04_patt }, +- { 0x018c, nv04_graph_mthd_bind_rop }, +- { 0x0190, nv04_graph_mthd_bind_beta1 }, +- { 0x0194, nv04_graph_mthd_bind_beta4 }, +- { 0x0198, nv04_graph_mthd_bind_surf2d }, +- { 0x02fc, nv04_graph_mthd_set_operation }, +- {}, +-}; ++ /* dvd subpicture */ ++ NVOBJ_CLASS(dev, 0x0038, GR); + +-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_tex_tri[] = { +- { 0x0188, nv04_graph_mthd_bind_clip }, +- { 0x018c, nv04_graph_mthd_bind_surf_color }, +- { 0x0190, nv04_graph_mthd_bind_surf_zeta }, +- {}, +-}; ++ /* m2mf */ ++ NVOBJ_CLASS(dev, 0x0039, GR); + +-static struct nouveau_pgraph_object_method nv04_graph_mthds_surf3d[] = { +- { 0x02f8, nv04_graph_mthd_surf3d_clip_h }, +- { 0x02fc, nv04_graph_mthd_surf3d_clip_v }, +- {}, +-}; ++ /* nv03 gdirect */ ++ NVOBJ_CLASS(dev, 0x004b, GR); ++ NVOBJ_MTHD (dev, 0x004b, 0x0184, nv04_graph_mthd_bind_nv01_patt); ++ NVOBJ_MTHD (dev, 0x004b, 0x0188, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x004b, 0x018c, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x004b, 0x0190, nv04_graph_mthd_bind_surf_dst); ++ NVOBJ_MTHD (dev, 0x004b, 0x02fc, nv04_graph_mthd_set_operation); ++ ++ /* nv04 gdirect */ ++ NVOBJ_CLASS(dev, 0x004a, GR); ++ NVOBJ_MTHD (dev, 0x004a, 0x0188, nv04_graph_mthd_bind_nv04_patt); ++ NVOBJ_MTHD (dev, 0x004a, 0x018c, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x004a, 0x0190, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x004a, 0x0194, nv04_graph_mthd_bind_beta4); ++ NVOBJ_MTHD (dev, 0x004a, 0x0198, nv04_graph_mthd_bind_surf2d); ++ NVOBJ_MTHD (dev, 0x004a, 0x02fc, nv04_graph_mthd_set_operation); ++ ++ /* nv01 imageblit */ ++ NVOBJ_CLASS(dev, 0x001f, GR); ++ NVOBJ_MTHD (dev, 0x001f, 0x0184, nv04_graph_mthd_bind_chroma); ++ NVOBJ_MTHD (dev, 0x001f, 0x0188, nv04_graph_mthd_bind_clip); ++ NVOBJ_MTHD (dev, 0x001f, 0x018c, nv04_graph_mthd_bind_nv01_patt); ++ NVOBJ_MTHD (dev, 0x001f, 0x0190, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x001f, 0x0194, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x001f, 0x0198, nv04_graph_mthd_bind_surf_dst); ++ NVOBJ_MTHD (dev, 0x001f, 0x019c, nv04_graph_mthd_bind_surf_src); ++ NVOBJ_MTHD (dev, 0x001f, 0x02fc, nv04_graph_mthd_set_operation); ++ ++ /* nv04 imageblit */ ++ NVOBJ_CLASS(dev, 0x005f, GR); ++ NVOBJ_MTHD (dev, 0x005f, 0x0184, nv04_graph_mthd_bind_chroma); ++ NVOBJ_MTHD (dev, 0x005f, 0x0188, nv04_graph_mthd_bind_clip); ++ NVOBJ_MTHD (dev, 0x005f, 0x018c, nv04_graph_mthd_bind_nv04_patt); ++ NVOBJ_MTHD (dev, 0x005f, 0x0190, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x005f, 0x0194, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x005f, 0x0198, nv04_graph_mthd_bind_beta4); ++ NVOBJ_MTHD (dev, 0x005f, 0x019c, nv04_graph_mthd_bind_surf2d); ++ NVOBJ_MTHD (dev, 0x005f, 0x02fc, nv04_graph_mthd_set_operation); ++ ++ /* nv04 iifc */ ++ NVOBJ_CLASS(dev, 0x0060, GR); ++ NVOBJ_MTHD (dev, 0x0060, 0x0188, nv04_graph_mthd_bind_chroma); ++ NVOBJ_MTHD (dev, 0x0060, 0x018c, nv04_graph_mthd_bind_clip); ++ NVOBJ_MTHD (dev, 0x0060, 0x0190, nv04_graph_mthd_bind_nv04_patt); ++ NVOBJ_MTHD (dev, 0x0060, 0x0194, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x0060, 0x0198, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x0060, 0x019c, nv04_graph_mthd_bind_beta4); ++ NVOBJ_MTHD (dev, 0x0060, 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf); ++ NVOBJ_MTHD (dev, 0x0060, 0x03e4, nv04_graph_mthd_set_operation); ++ ++ /* nv05 iifc */ ++ NVOBJ_CLASS(dev, 0x0064, GR); ++ ++ /* nv01 ifc */ ++ NVOBJ_CLASS(dev, 0x0021, GR); ++ NVOBJ_MTHD (dev, 0x0021, 0x0184, nv04_graph_mthd_bind_chroma); ++ NVOBJ_MTHD (dev, 0x0021, 0x0188, nv04_graph_mthd_bind_clip); ++ NVOBJ_MTHD (dev, 0x0021, 0x018c, nv04_graph_mthd_bind_nv01_patt); ++ NVOBJ_MTHD (dev, 0x0021, 0x0190, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x0021, 0x0194, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x0021, 0x0198, nv04_graph_mthd_bind_surf_dst); ++ NVOBJ_MTHD (dev, 0x0021, 0x02fc, nv04_graph_mthd_set_operation); ++ ++ /* nv04 ifc */ ++ NVOBJ_CLASS(dev, 0x0061, GR); ++ NVOBJ_MTHD (dev, 0x0061, 0x0184, nv04_graph_mthd_bind_chroma); ++ NVOBJ_MTHD (dev, 0x0061, 0x0188, nv04_graph_mthd_bind_clip); ++ NVOBJ_MTHD (dev, 0x0061, 0x018c, nv04_graph_mthd_bind_nv04_patt); ++ NVOBJ_MTHD (dev, 0x0061, 0x0190, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x0061, 0x0194, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x0061, 0x0198, nv04_graph_mthd_bind_beta4); ++ NVOBJ_MTHD (dev, 0x0061, 0x019c, nv04_graph_mthd_bind_surf2d); ++ NVOBJ_MTHD (dev, 0x0061, 0x02fc, nv04_graph_mthd_set_operation); ++ ++ /* nv05 ifc */ ++ NVOBJ_CLASS(dev, 0x0065, GR); ++ ++ /* nv03 sifc */ ++ NVOBJ_CLASS(dev, 0x0036, GR); ++ NVOBJ_MTHD (dev, 0x0036, 0x0184, nv04_graph_mthd_bind_chroma); ++ NVOBJ_MTHD (dev, 0x0036, 0x0188, nv04_graph_mthd_bind_nv01_patt); ++ NVOBJ_MTHD (dev, 0x0036, 0x018c, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x0036, 0x0190, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x0036, 0x0194, nv04_graph_mthd_bind_surf_dst); ++ NVOBJ_MTHD (dev, 0x0036, 0x02fc, nv04_graph_mthd_set_operation); ++ ++ /* nv04 sifc */ ++ NVOBJ_CLASS(dev, 0x0076, GR); ++ NVOBJ_MTHD (dev, 0x0076, 0x0184, nv04_graph_mthd_bind_chroma); ++ NVOBJ_MTHD (dev, 0x0076, 0x0188, nv04_graph_mthd_bind_nv04_patt); ++ NVOBJ_MTHD (dev, 0x0076, 0x018c, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x0076, 0x0190, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x0076, 0x0194, nv04_graph_mthd_bind_beta4); ++ NVOBJ_MTHD (dev, 0x0076, 0x0198, nv04_graph_mthd_bind_surf2d); ++ NVOBJ_MTHD (dev, 0x0076, 0x02fc, nv04_graph_mthd_set_operation); ++ ++ /* nv05 sifc */ ++ NVOBJ_CLASS(dev, 0x0066, GR); ++ ++ /* nv03 sifm */ ++ NVOBJ_CLASS(dev, 0x0037, GR); ++ NVOBJ_MTHD (dev, 0x0037, 0x0188, nv04_graph_mthd_bind_nv01_patt); ++ NVOBJ_MTHD (dev, 0x0037, 0x018c, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x0037, 0x0190, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x0037, 0x0194, nv04_graph_mthd_bind_surf_dst); ++ NVOBJ_MTHD (dev, 0x0037, 0x0304, nv04_graph_mthd_set_operation); ++ ++ /* nv04 sifm */ ++ NVOBJ_CLASS(dev, 0x0077, GR); ++ NVOBJ_MTHD (dev, 0x0077, 0x0188, nv04_graph_mthd_bind_nv04_patt); ++ NVOBJ_MTHD (dev, 0x0077, 0x018c, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x0077, 0x0190, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x0077, 0x0194, nv04_graph_mthd_bind_beta4); ++ NVOBJ_MTHD (dev, 0x0077, 0x0198, nv04_graph_mthd_bind_surf2d_swzsurf); ++ NVOBJ_MTHD (dev, 0x0077, 0x0304, nv04_graph_mthd_set_operation); ++ ++ /* null */ ++ NVOBJ_CLASS(dev, 0x0030, GR); ++ ++ /* surf2d */ ++ NVOBJ_CLASS(dev, 0x0042, GR); ++ ++ /* rop */ ++ NVOBJ_CLASS(dev, 0x0043, GR); ++ ++ /* beta1 */ ++ NVOBJ_CLASS(dev, 0x0012, GR); ++ ++ /* beta4 */ ++ NVOBJ_CLASS(dev, 0x0072, GR); ++ ++ /* cliprect */ ++ NVOBJ_CLASS(dev, 0x0019, GR); ++ ++ /* nv01 pattern */ ++ NVOBJ_CLASS(dev, 0x0018, GR); ++ ++ /* nv04 pattern */ ++ NVOBJ_CLASS(dev, 0x0044, GR); ++ ++ /* swzsurf */ ++ NVOBJ_CLASS(dev, 0x0052, GR); ++ ++ /* surf3d */ ++ NVOBJ_CLASS(dev, 0x0053, GR); ++ NVOBJ_MTHD (dev, 0x0053, 0x02f8, nv04_graph_mthd_surf3d_clip_h); ++ NVOBJ_MTHD (dev, 0x0053, 0x02fc, nv04_graph_mthd_surf3d_clip_v); ++ ++ /* nv03 tex_tri */ ++ NVOBJ_CLASS(dev, 0x0048, GR); ++ NVOBJ_MTHD (dev, 0x0048, 0x0188, nv04_graph_mthd_bind_clip); ++ NVOBJ_MTHD (dev, 0x0048, 0x018c, nv04_graph_mthd_bind_surf_color); ++ NVOBJ_MTHD (dev, 0x0048, 0x0190, nv04_graph_mthd_bind_surf_zeta); ++ ++ /* tex_tri */ ++ NVOBJ_CLASS(dev, 0x0054, GR); ++ ++ /* multitex_tri */ ++ NVOBJ_CLASS(dev, 0x0055, GR); ++ ++ /* nv01 chroma */ ++ NVOBJ_CLASS(dev, 0x0017, GR); ++ ++ /* nv04 chroma */ ++ NVOBJ_CLASS(dev, 0x0057, GR); ++ ++ /* surf_dst */ ++ NVOBJ_CLASS(dev, 0x0058, GR); ++ ++ /* surf_src */ ++ NVOBJ_CLASS(dev, 0x0059, GR); ++ ++ /* surf_color */ ++ NVOBJ_CLASS(dev, 0x005a, GR); ++ ++ /* surf_zeta */ ++ NVOBJ_CLASS(dev, 0x005b, GR); ++ ++ /* nv01 line */ ++ NVOBJ_CLASS(dev, 0x001c, GR); ++ NVOBJ_MTHD (dev, 0x001c, 0x0184, nv04_graph_mthd_bind_clip); ++ NVOBJ_MTHD (dev, 0x001c, 0x0188, nv04_graph_mthd_bind_nv01_patt); ++ NVOBJ_MTHD (dev, 0x001c, 0x018c, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x001c, 0x0190, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x001c, 0x0194, nv04_graph_mthd_bind_surf_dst); ++ NVOBJ_MTHD (dev, 0x001c, 0x02fc, nv04_graph_mthd_set_operation); ++ ++ /* nv04 line */ ++ NVOBJ_CLASS(dev, 0x005c, GR); ++ NVOBJ_MTHD (dev, 0x005c, 0x0184, nv04_graph_mthd_bind_clip); ++ NVOBJ_MTHD (dev, 0x005c, 0x0188, nv04_graph_mthd_bind_nv04_patt); ++ NVOBJ_MTHD (dev, 0x005c, 0x018c, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x005c, 0x0190, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x005c, 0x0194, nv04_graph_mthd_bind_beta4); ++ NVOBJ_MTHD (dev, 0x005c, 0x0198, nv04_graph_mthd_bind_surf2d); ++ NVOBJ_MTHD (dev, 0x005c, 0x02fc, nv04_graph_mthd_set_operation); ++ ++ /* nv01 tri */ ++ NVOBJ_CLASS(dev, 0x001d, GR); ++ NVOBJ_MTHD (dev, 0x001d, 0x0184, nv04_graph_mthd_bind_clip); ++ NVOBJ_MTHD (dev, 0x001d, 0x0188, nv04_graph_mthd_bind_nv01_patt); ++ NVOBJ_MTHD (dev, 0x001d, 0x018c, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x001d, 0x0190, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x001d, 0x0194, nv04_graph_mthd_bind_surf_dst); ++ NVOBJ_MTHD (dev, 0x001d, 0x02fc, nv04_graph_mthd_set_operation); ++ ++ /* nv04 tri */ ++ NVOBJ_CLASS(dev, 0x005d, GR); ++ NVOBJ_MTHD (dev, 0x005d, 0x0184, nv04_graph_mthd_bind_clip); ++ NVOBJ_MTHD (dev, 0x005d, 0x0188, nv04_graph_mthd_bind_nv04_patt); ++ NVOBJ_MTHD (dev, 0x005d, 0x018c, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x005d, 0x0190, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x005d, 0x0194, nv04_graph_mthd_bind_beta4); ++ NVOBJ_MTHD (dev, 0x005d, 0x0198, nv04_graph_mthd_bind_surf2d); ++ NVOBJ_MTHD (dev, 0x005d, 0x02fc, nv04_graph_mthd_set_operation); ++ ++ /* nv01 rect */ ++ NVOBJ_CLASS(dev, 0x001e, GR); ++ NVOBJ_MTHD (dev, 0x001e, 0x0184, nv04_graph_mthd_bind_clip); ++ NVOBJ_MTHD (dev, 0x001e, 0x0188, nv04_graph_mthd_bind_nv01_patt); ++ NVOBJ_MTHD (dev, 0x001e, 0x018c, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x001e, 0x0190, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x001e, 0x0194, nv04_graph_mthd_bind_surf_dst); ++ NVOBJ_MTHD (dev, 0x001e, 0x02fc, nv04_graph_mthd_set_operation); ++ ++ /* nv04 rect */ ++ NVOBJ_CLASS(dev, 0x005e, GR); ++ NVOBJ_MTHD (dev, 0x005e, 0x0184, nv04_graph_mthd_bind_clip); ++ NVOBJ_MTHD (dev, 0x005e, 0x0188, nv04_graph_mthd_bind_nv04_patt); ++ NVOBJ_MTHD (dev, 0x005e, 0x018c, nv04_graph_mthd_bind_rop); ++ NVOBJ_MTHD (dev, 0x005e, 0x0190, nv04_graph_mthd_bind_beta1); ++ NVOBJ_MTHD (dev, 0x005e, 0x0194, nv04_graph_mthd_bind_beta4); ++ NVOBJ_MTHD (dev, 0x005e, 0x0198, nv04_graph_mthd_bind_surf2d); ++ NVOBJ_MTHD (dev, 0x005e, 0x02fc, nv04_graph_mthd_set_operation); ++ ++ /* nvsw */ ++ NVOBJ_CLASS(dev, 0x506e, SW); ++ NVOBJ_MTHD (dev, 0x506e, 0x0150, nv04_graph_mthd_set_ref); ++ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); + +-struct nouveau_pgraph_object_class nv04_graph_grclass[] = { +- { 0x0038, false, NULL }, /* dvd subpicture */ +- { 0x0039, false, NULL }, /* m2mf */ +- { 0x004b, false, nv04_graph_mthds_nv03_gdirect }, /* nv03 gdirect */ +- { 0x004a, false, nv04_graph_mthds_nv04_gdirect }, /* nv04 gdirect */ +- { 0x001f, false, nv04_graph_mthds_nv01_imageblit }, /* nv01 imageblit */ +- { 0x005f, false, nv04_graph_mthds_nv04_imageblit_ifc }, /* nv04 imageblit */ +- { 0x0060, false, nv04_graph_mthds_nv04_iifc }, /* nv04 iifc */ +- { 0x0064, false, NULL }, /* nv05 iifc */ +- { 0x0021, false, nv04_graph_mthds_nv01_ifc }, /* nv01 ifc */ +- { 0x0061, false, nv04_graph_mthds_nv04_imageblit_ifc }, /* nv04 ifc */ +- { 0x0065, false, NULL }, /* nv05 ifc */ +- { 0x0036, false, nv04_graph_mthds_nv03_sifc }, /* nv03 sifc */ +- { 0x0076, false, nv04_graph_mthds_nv04_sifc }, /* nv04 sifc */ +- { 0x0066, false, NULL }, /* nv05 sifc */ +- { 0x0037, false, nv04_graph_mthds_nv03_sifm }, /* nv03 sifm */ +- { 0x0077, false, nv04_graph_mthds_nv04_sifm }, /* nv04 sifm */ +- { 0x0030, false, NULL }, /* null */ +- { 0x0042, false, NULL }, /* surf2d */ +- { 0x0043, false, NULL }, /* rop */ +- { 0x0012, false, NULL }, /* beta1 */ +- { 0x0072, false, NULL }, /* beta4 */ +- { 0x0019, false, NULL }, /* cliprect */ +- { 0x0018, false, NULL }, /* nv01 pattern */ +- { 0x0044, false, NULL }, /* nv04 pattern */ +- { 0x0052, false, NULL }, /* swzsurf */ +- { 0x0053, false, nv04_graph_mthds_surf3d }, /* surf3d */ +- { 0x0048, false, nv04_graph_mthds_nv03_tex_tri }, /* nv03 tex_tri */ +- { 0x0054, false, NULL }, /* tex_tri */ +- { 0x0055, false, NULL }, /* multitex_tri */ +- { 0x0017, false, NULL }, /* nv01 chroma */ +- { 0x0057, false, NULL }, /* nv04 chroma */ +- { 0x0058, false, NULL }, /* surf_dst */ +- { 0x0059, false, NULL }, /* surf_src */ +- { 0x005a, false, NULL }, /* surf_color */ +- { 0x005b, false, NULL }, /* surf_zeta */ +- { 0x001c, false, nv04_graph_mthds_nv01_shape }, /* nv01 line */ +- { 0x005c, false, nv04_graph_mthds_nv04_shape }, /* nv04 line */ +- { 0x001d, false, nv04_graph_mthds_nv01_shape }, /* nv01 tri */ +- { 0x005d, false, nv04_graph_mthds_nv04_shape }, /* nv04 tri */ +- { 0x001e, false, nv04_graph_mthds_nv01_shape }, /* nv01 rect */ +- { 0x005e, false, nv04_graph_mthds_nv04_shape }, /* nv04 rect */ +- { 0x506e, true, nv04_graph_mthds_sw }, +- {} ++ dev_priv->engine.graph.registered = true; ++ return 0; + }; +- +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_instmem.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_instmem.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_instmem.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_instmem.c 2010-10-22 23:59:52.558454475 +0200 @@ -1,6 +1,7 @@ #include "drmP.h" #include "drm.h" @@ -8745,7 +11182,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_instmem.c linux-2.6.36- int -nv04_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, uint32_t *sz) +nv04_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, -+ uint32_t *sz) ++ u32 *size, u32 align) { - if (gpuobj->im_backing) - return -EINVAL; @@ -8785,9 +11222,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_instmem.c linux-2.6.36- return 0; } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_pm.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_pm.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_pm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_pm.c 2010-10-15 02:04:44.405992754 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_pm.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_pm.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_pm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_pm.c 2010-10-22 23:59:52.558454475 +0200 @@ -0,0 +1,81 @@ +/* + * Copyright 2010 Red Hat Inc. @@ -8870,9 +11307,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_pm.c linux-2.6.36-rc7.p + kfree(state); +} + -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_tv.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_tv.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_tv.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv04_tv.c 2010-10-15 02:04:44.407992780 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv04_tv.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_tv.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv04_tv.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv04_tv.c 2010-10-22 23:59:52.559454487 +0200 @@ -49,8 +49,8 @@ int nv04_tv_identify(struct drm_device *dev, int i2c_index) @@ -8899,9 +11336,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv04_tv.c linux-2.6.36-rc7.p NVWriteVgaCrtc(dev, head, NV_CIO_CRE_LCD__INDEX, state->CRTC[NV_CIO_CRE_LCD__INDEX]); -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv10_fifo.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv10_fifo.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv10_fifo.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv10_fifo.c 2010-10-15 02:04:44.408992792 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv10_fifo.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv10_fifo.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv10_fifo.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv10_fifo.c 2010-10-22 23:59:52.560454499 +0200 @@ -27,8 +27,9 @@ #include "drmP.h" #include "drm.h" @@ -8931,16 +11368,25 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv10_fifo.c linux-2.6.36-rc7 nv_wi32(dev, fc + 20, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | -@@ -80,7 +81,7 @@ - nv_wr32(dev, NV04_PFIFO_MODE, - nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); - -- nouveau_gpuobj_ref_del(dev, &chan->ramfc); -+ nouveau_gpuobj_ref(NULL, &chan->ramfc); +@@ -72,17 +73,6 @@ + return 0; } +-void +-nv10_fifo_destroy_context(struct nouveau_channel *chan) +-{ +- struct drm_device *dev = chan->dev; +- +- nv_wr32(dev, NV04_PFIFO_MODE, +- nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); +- +- nouveau_gpuobj_ref_del(dev, &chan->ramfc); +-} +- static void -@@ -202,14 +203,14 @@ + nv10_fifo_do_load_context(struct drm_device *dev, int chid) + { +@@ -202,14 +192,14 @@ struct drm_nouveau_private *dev_priv = dev->dev_private; nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | @@ -8960,7 +11406,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv10_fifo.c linux-2.6.36-rc7 (1 << 16) /* 64 Bytes entry*/); /* XXX nvidia blob set bit 18, 21,23 for nv20 & nv30 */ } -@@ -240,7 +241,7 @@ +@@ -240,7 +230,7 @@ pfifo->reassign(dev, true); for (i = 0; i < dev_priv->engine.fifo.channels; i++) { @@ -8969,10 +11415,19 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv10_fifo.c linux-2.6.36-rc7 uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv10_graph.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv10_graph.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv10_graph.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv10_graph.c 2010-10-15 02:04:44.410992816 +0200 -@@ -802,8 +802,8 @@ +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv10_graph.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv10_graph.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv10_graph.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv10_graph.c 2010-10-22 23:59:52.561454511 +0200 +@@ -27,6 +27,8 @@ + #include "nouveau_drm.h" + #include "nouveau_drv.h" + ++static int nv10_graph_register(struct drm_device *); ++ + #define NV10_FIFO_NUMBER 32 + + struct pipe_state { +@@ -802,8 +804,8 @@ /* Load context for next channel */ chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; @@ -8983,7 +11438,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv10_graph.c linux-2.6.36-rc nv10_graph_load_context(chan); pgraph->fifo_access(dev, true); -@@ -833,7 +833,7 @@ +@@ -833,7 +835,7 @@ if (chid >= dev_priv->engine.fifo.channels) return NULL; @@ -8992,9 +11447,160 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv10_graph.c linux-2.6.36-rc } int nv10_graph_create_context(struct nouveau_channel *chan) -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv17_tv.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv17_tv.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv17_tv.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv17_tv.c 2010-10-15 02:04:44.412992842 +0200 +@@ -875,10 +877,25 @@ + + void nv10_graph_destroy_context(struct nouveau_channel *chan) + { ++ struct drm_device *dev = chan->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct graph_state *pgraph_ctx = chan->pgraph_ctx; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ pgraph->fifo_access(dev, false); + ++ /* Unload the context if it's the currently active one */ ++ if (pgraph->channel(dev) == chan) ++ pgraph->unload_context(dev); ++ ++ /* Free the context resources */ + kfree(pgraph_ctx); + chan->pgraph_ctx = NULL; ++ ++ pgraph->fifo_access(dev, true); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + } + + void +@@ -899,13 +916,17 @@ + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t tmp; +- int i; ++ int ret, i; + + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & + ~NV_PMC_ENABLE_PGRAPH); + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | + NV_PMC_ENABLE_PGRAPH); + ++ ret = nv10_graph_register(dev); ++ if (ret) ++ return ret; ++ + nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + +@@ -951,8 +972,8 @@ + } + + static int +-nv17_graph_mthd_lma_window(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv17_graph_mthd_lma_window(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + struct drm_device *dev = chan->dev; + struct graph_state *ctx = chan->pgraph_ctx; +@@ -1031,8 +1052,8 @@ + } + + static int +-nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +@@ -1050,35 +1071,52 @@ + return 0; + } + +-static struct nouveau_pgraph_object_method nv17_graph_celsius_mthds[] = { +- { 0x1638, nv17_graph_mthd_lma_window }, +- { 0x163c, nv17_graph_mthd_lma_window }, +- { 0x1640, nv17_graph_mthd_lma_window }, +- { 0x1644, nv17_graph_mthd_lma_window }, +- { 0x1658, nv17_graph_mthd_lma_enable }, +- {} +-}; ++static int ++nv10_graph_register(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; + +-struct nouveau_pgraph_object_class nv10_graph_grclass[] = { +- { 0x0030, false, NULL }, /* null */ +- { 0x0039, false, NULL }, /* m2mf */ +- { 0x004a, false, NULL }, /* gdirect */ +- { 0x005f, false, NULL }, /* imageblit */ +- { 0x009f, false, NULL }, /* imageblit (nv12) */ +- { 0x008a, false, NULL }, /* ifc */ +- { 0x0089, false, NULL }, /* sifm */ +- { 0x0062, false, NULL }, /* surf2d */ +- { 0x0043, false, NULL }, /* rop */ +- { 0x0012, false, NULL }, /* beta1 */ +- { 0x0072, false, NULL }, /* beta4 */ +- { 0x0019, false, NULL }, /* cliprect */ +- { 0x0044, false, NULL }, /* pattern */ +- { 0x0052, false, NULL }, /* swzsurf */ +- { 0x0093, false, NULL }, /* surf3d */ +- { 0x0094, false, NULL }, /* tex_tri */ +- { 0x0095, false, NULL }, /* multitex_tri */ +- { 0x0056, false, NULL }, /* celcius (nv10) */ +- { 0x0096, false, NULL }, /* celcius (nv11) */ +- { 0x0099, false, nv17_graph_celsius_mthds }, /* celcius (nv17) */ +- {} +-}; ++ if (dev_priv->engine.graph.registered) ++ return 0; ++ ++ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ ++ NVOBJ_CLASS(dev, 0x0030, GR); /* null */ ++ NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ ++ NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ ++ NVOBJ_CLASS(dev, 0x005f, GR); /* imageblit */ ++ NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ ++ NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ ++ NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ ++ NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ ++ NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ ++ NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ ++ NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ ++ NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ ++ NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ ++ NVOBJ_CLASS(dev, 0x0052, GR); /* swzsurf */ ++ NVOBJ_CLASS(dev, 0x0093, GR); /* surf3d */ ++ NVOBJ_CLASS(dev, 0x0094, GR); /* tex_tri */ ++ NVOBJ_CLASS(dev, 0x0095, GR); /* multitex_tri */ ++ ++ /* celcius */ ++ if (dev_priv->chipset <= 0x10) { ++ NVOBJ_CLASS(dev, 0x0056, GR); ++ } else ++ if (dev_priv->chipset < 0x17 || dev_priv->chipset == 0x1a) { ++ NVOBJ_CLASS(dev, 0x0096, GR); ++ } else { ++ NVOBJ_CLASS(dev, 0x0099, GR); ++ NVOBJ_MTHD (dev, 0x0099, 0x1638, nv17_graph_mthd_lma_window); ++ NVOBJ_MTHD (dev, 0x0099, 0x163c, nv17_graph_mthd_lma_window); ++ NVOBJ_MTHD (dev, 0x0099, 0x1640, nv17_graph_mthd_lma_window); ++ NVOBJ_MTHD (dev, 0x0099, 0x1644, nv17_graph_mthd_lma_window); ++ NVOBJ_MTHD (dev, 0x0099, 0x1658, nv17_graph_mthd_lma_enable); ++ } ++ ++ /* nvsw */ ++ NVOBJ_CLASS(dev, 0x506e, SW); ++ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); ++ ++ dev_priv->engine.graph.registered = true; ++ return 0; ++} +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv17_tv.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv17_tv.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv17_tv.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv17_tv.c 2010-10-22 23:59:52.562454523 +0200 @@ -193,55 +193,56 @@ } } @@ -9155,9 +11761,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv17_tv.c linux-2.6.36-rc7.p /* Set the DACCLK register */ dacclk = (NVReadRAMDAC(dev, 0, dacclk_off) & ~0x30) | 0x1; -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv17_tv.h linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv17_tv.h ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv17_tv.h 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv17_tv.h 2010-10-15 02:04:44.414992866 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv17_tv.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv17_tv.h +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv17_tv.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv17_tv.h 2010-10-22 23:59:52.563454535 +0200 @@ -127,7 +127,8 @@ /* TV hardware access functions */ @@ -9193,9 +11799,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv17_tv.h linux-2.6.36-rc7.p + nv_write_tv_enc(dev, 0x##reg, state->tv_enc[0x##reg]) #endif -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv17_tv_modes.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv17_tv_modes.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv17_tv_modes.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv17_tv_modes.c 2010-10-15 02:04:44.415992878 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv17_tv_modes.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv17_tv_modes.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv17_tv_modes.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv17_tv_modes.c 2010-10-22 23:59:52.564454547 +0200 @@ -336,12 +336,17 @@ struct filter_params *p = &fparams[k][j]; @@ -9287,10 +11893,18 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv17_tv_modes.c linux-2.6.36 regs->fp_horiz_regs[FP_VALID_START] = hmargin; regs->fp_horiz_regs[FP_VALID_END] = output_mode->hdisplay - hmargin - 1; -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv20_graph.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv20_graph.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv20_graph.c 2010-10-15 02:04:44.418992917 +0200 -@@ -37,49 +37,49 @@ +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv20_graph.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv20_graph.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv20_graph.c 2010-10-22 23:59:52.568454598 +0200 +@@ -32,54 +32,57 @@ + #define NV34_GRCTX_SIZE (18140) + #define NV35_36_GRCTX_SIZE (22396) + ++static int nv20_graph_register(struct drm_device *); ++static int nv30_graph_register(struct drm_device *); ++ + static void + nv20_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) { int i; @@ -9375,7 +11989,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36-rc } static void -@@ -87,58 +87,58 @@ +@@ -87,58 +90,58 @@ { int i; @@ -9478,7 +12092,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36-rc } static void -@@ -146,49 +146,49 @@ +@@ -146,49 +149,49 @@ { int i; @@ -9563,7 +12177,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36-rc } static void -@@ -196,57 +196,57 @@ +@@ -196,57 +199,57 @@ { int i; @@ -9661,7 +12275,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36-rc } static void -@@ -254,57 +254,57 @@ +@@ -254,57 +257,57 @@ { int i; @@ -9759,7 +12373,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36-rc } static void -@@ -312,57 +312,57 @@ +@@ -312,57 +315,57 @@ { int i; @@ -9857,7 +12471,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36-rc } int -@@ -372,7 +372,7 @@ +@@ -372,7 +375,7 @@ struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *); @@ -9866,7 +12480,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36-rc int ret; switch (dev_priv->chipset) { -@@ -403,21 +403,19 @@ +@@ -403,21 +406,19 @@ BUG_ON(1); } @@ -9894,20 +12508,32 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36-rc return 0; } -@@ -428,10 +426,8 @@ +@@ -427,11 +428,21 @@ + struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ pgraph->fifo_access(dev, false); - if (chan->ramin_grctx) - nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); -- ++ /* Unload the context if it's the currently active one */ ++ if (pgraph->channel(dev) == chan) ++ pgraph->unload_context(dev); + - nv_wo32(dev, pgraph->ctx_table->gpuobj, chan->id, 0); -+ nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); ++ pgraph->fifo_access(dev, true); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); ++ ++ /* Free the context resources */ + nv_wo32(pgraph->ctx_table, chan->id * 4, 0); ++ nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); } int -@@ -442,7 +438,7 @@ +@@ -442,7 +453,7 @@ if (!chan->ramin_grctx) return -EINVAL; @@ -9916,7 +12542,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36-rc nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER, -@@ -465,7 +461,7 @@ +@@ -465,7 +476,7 @@ chan = pgraph->channel(dev); if (!chan) return 0; @@ -9925,7 +12551,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36-rc nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER, -@@ -552,15 +548,15 @@ +@@ -552,18 +563,24 @@ if (!pgraph->ctx_table) { /* Create Context Pointer Table */ @@ -9945,7 +12571,16 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36-rc nv20_graph_rdi(dev); -@@ -646,7 +642,7 @@ ++ ret = nv20_graph_register(dev); ++ if (ret) { ++ nouveau_gpuobj_ref(NULL, &pgraph->ctx_table); ++ return ret; ++ } ++ + nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); + nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + +@@ -646,7 +663,7 @@ struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; @@ -9954,7 +12589,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36-rc } int -@@ -681,15 +677,15 @@ +@@ -681,15 +698,21 @@ if (!pgraph->ctx_table) { /* Create Context Pointer Table */ @@ -9968,15 +12603,148 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.36-rc return ret; } ++ ret = nv30_graph_register(dev); ++ if (ret) { ++ nouveau_gpuobj_ref(NULL, &pgraph->ctx_table); ++ return ret; ++ } ++ nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, - pgraph->ctx_table->instance >> 4); + pgraph->ctx_table->pinst >> 4); nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv40_fifo.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv40_fifo.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv40_fifo.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv40_fifo.c 2010-10-15 02:04:44.420992941 +0200 +@@ -748,46 +771,84 @@ + return 0; + } + +-struct nouveau_pgraph_object_class nv20_graph_grclass[] = { +- { 0x0030, false, NULL }, /* null */ +- { 0x0039, false, NULL }, /* m2mf */ +- { 0x004a, false, NULL }, /* gdirect */ +- { 0x009f, false, NULL }, /* imageblit (nv12) */ +- { 0x008a, false, NULL }, /* ifc */ +- { 0x0089, false, NULL }, /* sifm */ +- { 0x0062, false, NULL }, /* surf2d */ +- { 0x0043, false, NULL }, /* rop */ +- { 0x0012, false, NULL }, /* beta1 */ +- { 0x0072, false, NULL }, /* beta4 */ +- { 0x0019, false, NULL }, /* cliprect */ +- { 0x0044, false, NULL }, /* pattern */ +- { 0x009e, false, NULL }, /* swzsurf */ +- { 0x0096, false, NULL }, /* celcius */ +- { 0x0097, false, NULL }, /* kelvin (nv20) */ +- { 0x0597, false, NULL }, /* kelvin (nv25) */ +- {} +-}; +- +-struct nouveau_pgraph_object_class nv30_graph_grclass[] = { +- { 0x0030, false, NULL }, /* null */ +- { 0x0039, false, NULL }, /* m2mf */ +- { 0x004a, false, NULL }, /* gdirect */ +- { 0x009f, false, NULL }, /* imageblit (nv12) */ +- { 0x008a, false, NULL }, /* ifc */ +- { 0x038a, false, NULL }, /* ifc (nv30) */ +- { 0x0089, false, NULL }, /* sifm */ +- { 0x0389, false, NULL }, /* sifm (nv30) */ +- { 0x0062, false, NULL }, /* surf2d */ +- { 0x0362, false, NULL }, /* surf2d (nv30) */ +- { 0x0043, false, NULL }, /* rop */ +- { 0x0012, false, NULL }, /* beta1 */ +- { 0x0072, false, NULL }, /* beta4 */ +- { 0x0019, false, NULL }, /* cliprect */ +- { 0x0044, false, NULL }, /* pattern */ +- { 0x039e, false, NULL }, /* swzsurf */ +- { 0x0397, false, NULL }, /* rankine (nv30) */ +- { 0x0497, false, NULL }, /* rankine (nv35) */ +- { 0x0697, false, NULL }, /* rankine (nv34) */ +- {} +-}; ++static int ++nv20_graph_register(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ if (dev_priv->engine.graph.registered) ++ return 0; + ++ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ ++ NVOBJ_CLASS(dev, 0x0030, GR); /* null */ ++ NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ ++ NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ ++ NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ ++ NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ ++ NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ ++ NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ ++ NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ ++ NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ ++ NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ ++ NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ ++ NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ ++ NVOBJ_CLASS(dev, 0x009e, GR); /* swzsurf */ ++ NVOBJ_CLASS(dev, 0x0096, GR); /* celcius */ ++ ++ /* kelvin */ ++ if (dev_priv->chipset < 0x25) ++ NVOBJ_CLASS(dev, 0x0097, GR); ++ else ++ NVOBJ_CLASS(dev, 0x0597, GR); ++ ++ /* nvsw */ ++ NVOBJ_CLASS(dev, 0x506e, SW); ++ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); ++ ++ dev_priv->engine.graph.registered = true; ++ return 0; ++} ++ ++static int ++nv30_graph_register(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ if (dev_priv->engine.graph.registered) ++ return 0; ++ ++ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ ++ NVOBJ_CLASS(dev, 0x0030, GR); /* null */ ++ NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ ++ NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ ++ NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ ++ NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ ++ NVOBJ_CLASS(dev, 0x038a, GR); /* ifc (nv30) */ ++ NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ ++ NVOBJ_CLASS(dev, 0x0389, GR); /* sifm (nv30) */ ++ NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ ++ NVOBJ_CLASS(dev, 0x0362, GR); /* surf2d (nv30) */ ++ NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ ++ NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ ++ NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ ++ NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ ++ NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ ++ NVOBJ_CLASS(dev, 0x039e, GR); /* swzsurf */ ++ ++ /* rankine */ ++ if (0x00000003 & (1 << (dev_priv->chipset & 0x0f))) ++ NVOBJ_CLASS(dev, 0x0397, GR); ++ else ++ if (0x00000010 & (1 << (dev_priv->chipset & 0x0f))) ++ NVOBJ_CLASS(dev, 0x0697, GR); ++ else ++ if (0x000001e0 & (1 << (dev_priv->chipset & 0x0f))) ++ NVOBJ_CLASS(dev, 0x0497, GR); ++ ++ /* nvsw */ ++ NVOBJ_CLASS(dev, 0x506e, SW); ++ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); ++ ++ dev_priv->engine.graph.registered = true; ++ return 0; ++} +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv40_fifo.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv40_fifo.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv40_fifo.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv40_fifo.c 2010-10-22 23:59:52.569454611 +0200 @@ -27,8 +27,9 @@ #include "drmP.h" #include "nouveau_drv.h" @@ -10015,17 +12783,26 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv40_fifo.c linux-2.6.36-rc7 nv_wi32(dev, fc + 60, 0x0001FFFF); /* enable the fifo dma operation */ -@@ -77,8 +78,7 @@ - nv_wr32(dev, NV04_PFIFO_MODE, - nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); - -- if (chan->ramfc) -- nouveau_gpuobj_ref_del(dev, &chan->ramfc); -+ nouveau_gpuobj_ref(NULL, &chan->ramfc); +@@ -69,18 +70,6 @@ + return 0; } +-void +-nv40_fifo_destroy_context(struct nouveau_channel *chan) +-{ +- struct drm_device *dev = chan->dev; +- +- nv_wr32(dev, NV04_PFIFO_MODE, +- nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); +- +- if (chan->ramfc) +- nouveau_gpuobj_ref_del(dev, &chan->ramfc); +-} +- static void -@@ -241,9 +241,9 @@ + nv40_fifo_do_load_context(struct drm_device *dev, int chid) + { +@@ -241,9 +230,9 @@ struct drm_nouveau_private *dev_priv = dev->dev_private; nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | @@ -10038,7 +12815,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv40_fifo.c linux-2.6.36-rc7 switch (dev_priv->chipset) { case 0x47: -@@ -271,7 +271,7 @@ +@@ -271,7 +260,7 @@ nv_wr32(dev, 0x2230, 0); nv_wr32(dev, NV40_PFIFO_RAMFC, ((dev_priv->vram_size - 512 * 1024 + @@ -10047,7 +12824,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv40_fifo.c linux-2.6.36-rc7 break; } } -@@ -301,7 +301,7 @@ +@@ -301,7 +290,7 @@ pfifo->reassign(dev, true); for (i = 0; i < dev_priv->engine.fifo.channels; i++) { @@ -10056,10 +12833,19 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv40_fifo.c linux-2.6.36-rc7 uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv40_graph.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv40_graph.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv40_graph.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv40_graph.c 2010-10-15 02:04:44.421992953 +0200 -@@ -42,10 +42,10 @@ +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv40_graph.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv40_graph.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv40_graph.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv40_graph.c 2010-10-22 23:59:52.570454623 +0200 +@@ -29,6 +29,8 @@ + #include "nouveau_drv.h" + #include "nouveau_grctx.h" + ++static int nv40_graph_register(struct drm_device *); ++ + struct nouveau_channel * + nv40_graph_channel(struct drm_device *dev) + { +@@ -42,10 +44,10 @@ inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4; for (i = 0; i < dev_priv->engine.fifo.channels; i++) { @@ -10072,7 +12858,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv40_graph.c linux-2.6.36-rc return chan; } -@@ -61,27 +61,25 @@ +@@ -61,27 +63,41 @@ struct nouveau_grctx ctx = {}; int ret; @@ -10101,11 +12887,27 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv40_graph.c linux-2.6.36-rc nv40_graph_destroy_context(struct nouveau_channel *chan) { - nouveau_gpuobj_ref_del(chan->dev, &chan->ramin_grctx); ++ struct drm_device *dev = chan->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ pgraph->fifo_access(dev, false); ++ ++ /* Unload the context if it's the currently active one */ ++ if (pgraph->channel(dev) == chan) ++ pgraph->unload_context(dev); ++ ++ pgraph->fifo_access(dev, true); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); ++ ++ /* Free the context resources */ + nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); } static int -@@ -135,7 +133,7 @@ +@@ -135,7 +151,7 @@ if (!chan->ramin_grctx) return -EINVAL; @@ -10114,9 +12916,92 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv40_graph.c linux-2.6.36-rc ret = nv40_graph_transfer_context(dev, inst, 0); if (ret) -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv40_grctx.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv40_grctx.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv40_grctx.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv40_grctx.c 2010-10-15 02:04:44.425993003 +0200 +@@ -234,7 +250,7 @@ + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + struct nouveau_grctx ctx = {}; + uint32_t vramsz, *cp; +- int i, j; ++ int ret, i, j; + + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & + ~NV_PMC_ENABLE_PGRAPH); +@@ -258,6 +274,10 @@ + + kfree(cp); + ++ ret = nv40_graph_register(dev); ++ if (ret) ++ return ret; ++ + /* No context present currently */ + nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); + +@@ -394,24 +414,42 @@ + { + } + +-struct nouveau_pgraph_object_class nv40_graph_grclass[] = { +- { 0x0030, false, NULL }, /* null */ +- { 0x0039, false, NULL }, /* m2mf */ +- { 0x004a, false, NULL }, /* gdirect */ +- { 0x009f, false, NULL }, /* imageblit (nv12) */ +- { 0x008a, false, NULL }, /* ifc */ +- { 0x0089, false, NULL }, /* sifm */ +- { 0x3089, false, NULL }, /* sifm (nv40) */ +- { 0x0062, false, NULL }, /* surf2d */ +- { 0x3062, false, NULL }, /* surf2d (nv40) */ +- { 0x0043, false, NULL }, /* rop */ +- { 0x0012, false, NULL }, /* beta1 */ +- { 0x0072, false, NULL }, /* beta4 */ +- { 0x0019, false, NULL }, /* cliprect */ +- { 0x0044, false, NULL }, /* pattern */ +- { 0x309e, false, NULL }, /* swzsurf */ +- { 0x4097, false, NULL }, /* curie (nv40) */ +- { 0x4497, false, NULL }, /* curie (nv44) */ +- {} +-}; ++static int ++nv40_graph_register(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; + ++ if (dev_priv->engine.graph.registered) ++ return 0; ++ ++ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ ++ NVOBJ_CLASS(dev, 0x0030, GR); /* null */ ++ NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ ++ NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ ++ NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ ++ NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ ++ NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ ++ NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */ ++ NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ ++ NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */ ++ NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ ++ NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ ++ NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ ++ NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ ++ NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ ++ NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */ ++ ++ /* curie */ ++ if (dev_priv->chipset >= 0x60 || ++ 0x00005450 & (1 << (dev_priv->chipset & 0x0f))) ++ NVOBJ_CLASS(dev, 0x4497, GR); ++ else ++ NVOBJ_CLASS(dev, 0x4097, GR); ++ ++ /* nvsw */ ++ NVOBJ_CLASS(dev, 0x506e, SW); ++ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); ++ ++ dev_priv->engine.graph.registered = true; ++ return 0; ++} +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv40_grctx.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv40_grctx.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv40_grctx.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv40_grctx.c 2010-10-22 23:59:52.571454635 +0200 @@ -596,13 +596,13 @@ offset += 0x0280/4; @@ -10134,9 +13019,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv40_grctx.c linux-2.6.36-rc } } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_calc.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_calc.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_calc.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_calc.c 2010-10-15 02:04:44.426993016 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_calc.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_calc.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_calc.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_calc.c 2010-10-22 23:59:52.572454647 +0200 @@ -51,24 +51,28 @@ int *N, int *fN, int *M, int *P) { @@ -10172,10 +13057,20 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_calc.c linux-2.6.36-rc7 fb_div.full = dfixed_div(fb_div, a); /* *N = floor(fb_div); */ -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_crtc.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_crtc.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_crtc.c 2010-10-15 02:04:44.428993040 +0200 -@@ -266,15 +266,10 @@ +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_crtc.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_crtc.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_crtc.c 2010-10-22 23:59:52.573454659 +0200 +@@ -104,8 +104,7 @@ + OUT_RING(evo, nv_crtc->lut.depth == 8 ? + NV50_EVO_CRTC_CLUT_MODE_OFF : + NV50_EVO_CRTC_CLUT_MODE_ON); +- OUT_RING(evo, (nv_crtc->lut.nvbo->bo.mem.mm_node->start << +- PAGE_SHIFT) >> 8); ++ OUT_RING(evo, (nv_crtc->lut.nvbo->bo.mem.start << PAGE_SHIFT) >> 8); + if (dev_priv->chipset != 0x50) { + BEGIN_RING(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); + OUT_RING(evo, NvEvoVRAM); +@@ -266,15 +265,10 @@ { struct drm_nouveau_private *dev_priv = dev->dev_private; struct pll_lims pll; @@ -10193,7 +13088,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.36-rc7 if (ret) return ret; -@@ -286,11 +281,11 @@ +@@ -286,11 +280,11 @@ NV_DEBUG(dev, "pclk %d out %d NM1 %d %d NM2 %d %d P %d\n", pclk, ret, N1, M1, N2, M2, P); @@ -10210,7 +13105,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.36-rc7 } else if (dev_priv->chipset < NV_C0) { ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); -@@ -300,10 +295,10 @@ +@@ -300,10 +294,10 @@ NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n", pclk, ret, N1, N2, M1, P); @@ -10225,7 +13120,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.36-rc7 } else { ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); if (ret <= 0) -@@ -312,9 +307,9 @@ +@@ -312,9 +306,9 @@ NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n", pclk, ret, N1, N2, M1, P); @@ -10238,7 +13133,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.36-rc7 } return 0; -@@ -338,7 +333,9 @@ +@@ -338,7 +332,9 @@ nv50_cursor_fini(nv_crtc); @@ -10248,6 +13143,14 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.36-rc7 nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); kfree(nv_crtc->mode); kfree(nv_crtc); +@@ -441,6 +437,7 @@ + .cursor_move = nv50_crtc_cursor_move, + .gamma_set = nv50_crtc_gamma_set, + .set_config = drm_crtc_helper_set_config, ++ .page_flip = nouveau_crtc_page_flip, + .destroy = nv50_crtc_destroy, + }; + @@ -536,7 +533,7 @@ } @@ -10266,9 +13169,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.36-rc7 else OUT_RING(evo, format); -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_cursor.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_cursor.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_cursor.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_cursor.c 2010-10-15 02:04:44.429993052 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_cursor.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_cursor.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_cursor.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_cursor.c 2010-10-22 23:59:52.574454671 +0200 @@ -147,7 +147,7 @@ NV_DEBUG_KMS(dev, "\n"); @@ -10278,9 +13181,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_cursor.c linux-2.6.36-r NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_dac.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_dac.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_dac.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_dac.c 2010-10-15 02:04:44.430993065 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_dac.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_dac.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_dac.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_dac.c 2010-10-22 23:59:52.574454671 +0200 @@ -79,7 +79,7 @@ nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), @@ -10299,44 +13202,49 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_dac.c linux-2.6.36-rc7. NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) { NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_display.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_display.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_display.c 2010-10-15 02:04:44.433993102 +0200 -@@ -30,8 +30,22 @@ +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_display.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_display.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_display.c 2010-10-22 23:59:52.576454695 +0200 +@@ -30,154 +30,20 @@ #include "nouveau_connector.h" #include "nouveau_fb.h" #include "nouveau_fbcon.h" +#include "nouveau_ramht.h" #include "drm_crtc_helper.h" -+static inline int -+nv50_sor_nr(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->chipset < 0x90 || -+ dev_priv->chipset == 0x92 || -+ dev_priv->chipset == 0xa0) -+ return 2; -+ -+ return 4; -+} -+ - static void - nv50_evo_channel_del(struct nouveau_channel **pchan) - { -@@ -42,6 +56,7 @@ - *pchan = NULL; - - nouveau_gpuobj_channel_takedown(chan); -+ nouveau_bo_unmap(chan->pushbuf_bo); - nouveau_bo_ref(NULL, &chan->pushbuf_bo); - - if (chan->user) -@@ -65,23 +80,23 @@ - return ret; - obj->engine = NVOBJ_ENGINE_DISPLAY; - +-static void +-nv50_evo_channel_del(struct nouveau_channel **pchan) +-{ +- struct nouveau_channel *chan = *pchan; +- +- if (!chan) +- return; +- *pchan = NULL; +- +- nouveau_gpuobj_channel_takedown(chan); +- nouveau_bo_ref(NULL, &chan->pushbuf_bo); +- +- if (chan->user) +- iounmap(chan->user); +- +- kfree(chan); +-} +- +-static int +-nv50_evo_dmaobj_new(struct nouveau_channel *evo, uint32_t class, uint32_t name, +- uint32_t tile_flags, uint32_t magic_flags, +- uint32_t offset, uint32_t limit) +-{ +- struct drm_nouveau_private *dev_priv = evo->dev->dev_private; +- struct drm_device *dev = evo->dev; +- struct nouveau_gpuobj *obj = NULL; +- int ret; +- +- ret = nouveau_gpuobj_new(dev, evo, 6*4, 32, 0, &obj); +- if (ret) +- return ret; +- obj->engine = NVOBJ_ENGINE_DISPLAY; +- - ret = nouveau_gpuobj_ref_add(dev, evo, name, obj, NULL); - if (ret) { - nouveau_gpuobj_del(dev, &obj); @@ -10348,83 +13256,150 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.36- - nv_wo32(dev, obj, 2, offset); - nv_wo32(dev, obj, 3, 0x00000000); - nv_wo32(dev, obj, 4, 0x00000000); -+ nv_wo32(obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); -+ nv_wo32(obj, 4, limit); -+ nv_wo32(obj, 8, offset); -+ nv_wo32(obj, 12, 0x00000000); -+ nv_wo32(obj, 16, 0x00000000); - if (dev_priv->card_type < NV_C0) +- if (dev_priv->card_type < NV_C0) - nv_wo32(dev, obj, 5, 0x00010000); -+ nv_wo32(obj, 20, 0x00010000); - else +- else - nv_wo32(dev, obj, 5, 0x00020000); -+ nv_wo32(obj, 20, 0x00020000); - dev_priv->engine.instmem.flush(dev); - -+ ret = nouveau_ramht_insert(evo, name, obj); -+ nouveau_gpuobj_ref(NULL, &obj); -+ if (ret) { -+ return ret; -+ } -+ - return 0; - } - -@@ -89,6 +104,7 @@ - nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) +- dev_priv->engine.instmem.flush(dev); +- +- return 0; +-} +- +-static int +-nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) ++static inline int ++nv50_sor_nr(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj *ramht = NULL; - struct nouveau_channel *chan; - int ret; - -@@ -102,32 +118,35 @@ - chan->user_get = 4; - chan->user_put = 0; - +- struct nouveau_channel *chan; +- int ret; +- +- chan = kzalloc(sizeof(struct nouveau_channel), GFP_KERNEL); +- if (!chan) +- return -ENOMEM; +- *pchan = chan; +- +- chan->id = -1; +- chan->dev = dev; +- chan->user_get = 4; +- chan->user_put = 0; +- - INIT_LIST_HEAD(&chan->ramht_refs); - - ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 32768, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin); -+ ret = nouveau_gpuobj_new(dev, NULL, 32768, 0x1000, -+ NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin); - if (ret) { - NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); - nv50_evo_channel_del(pchan); - return ret; - } - +- if (ret) { +- NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); +- nv50_evo_channel_del(pchan); +- return ret; +- } +- - ret = drm_mm_init(&chan->ramin_heap, - chan->ramin->gpuobj->im_pramin->start, 32768); -+ ret = drm_mm_init(&chan->ramin_heap, 0, 32768); - if (ret) { - NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); - nv50_evo_channel_del(pchan); - return ret; - } - +- if (ret) { +- NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); +- nv50_evo_channel_del(pchan); +- return ret; +- } +- - ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 4096, 16, - 0, &chan->ramht); -+ ret = nouveau_gpuobj_new(dev, chan, 4096, 16, 0, &ramht); - if (ret) { - NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); - nv50_evo_channel_del(pchan); - return ret; - } +- if (ret) { +- NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); +- nv50_evo_channel_del(pchan); +- return ret; +- } +- +- if (dev_priv->chipset != 0x50) { +- ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB16, 0x70, 0x19, +- 0, 0xffffffff); +- if (ret) { +- nv50_evo_channel_del(pchan); +- return ret; +- } +- +- +- ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB32, 0x7a, 0x19, +- 0, 0xffffffff); +- if (ret) { +- nv50_evo_channel_del(pchan); +- return ret; +- } +- } +- +- ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoVRAM, 0, 0x19, +- 0, dev_priv->vram_size); +- if (ret) { +- nv50_evo_channel_del(pchan); +- return ret; +- } +- +- ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, +- false, true, &chan->pushbuf_bo); +- if (ret == 0) +- ret = nouveau_bo_pin(chan->pushbuf_bo, TTM_PL_FLAG_VRAM); +- if (ret) { +- NV_ERROR(dev, "Error creating EVO DMA push buffer: %d\n", ret); +- nv50_evo_channel_del(pchan); +- return ret; +- } -+ ret = nouveau_ramht_new(dev, ramht, &chan->ramht); -+ nouveau_gpuobj_ref(NULL, &ramht); -+ if (ret) { -+ nv50_evo_channel_del(pchan); -+ return ret; -+ } +- ret = nouveau_bo_map(chan->pushbuf_bo); +- if (ret) { +- NV_ERROR(dev, "Error mapping EVO DMA push buffer: %d\n", ret); +- nv50_evo_channel_del(pchan); +- return ret; +- } ++ if (dev_priv->chipset < 0x90 || ++ dev_priv->chipset == 0x92 || ++ dev_priv->chipset == 0xa0) ++ return 2; + +- chan->user = ioremap(pci_resource_start(dev->pdev, 0) + +- NV50_PDISPLAY_USER(0), PAGE_SIZE); +- if (!chan->user) { +- NV_ERROR(dev, "Error mapping EVO control regs.\n"); +- nv50_evo_channel_del(pchan); +- return -ENOMEM; +- } +- +- return 0; ++ return 4; + } + + int +@@ -195,17 +61,16 @@ + nv50_display_init(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- struct nouveau_channel *evo = dev_priv->evo; + struct drm_connector *connector; +- uint32_t val, ram_amount; +- uint64_t start; ++ struct nouveau_channel *evo; + int ret, i; ++ u32 val; + + NV_DEBUG_KMS(dev, "\n"); + + nv_wr32(dev, 0x00610184, nv_rd32(dev, 0x00614004)); + - if (dev_priv->chipset != 0x50) { - ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB16, 0x70, 0x19, - 0, 0xffffffff); -@@ -227,11 +246,11 @@ + /* + * I think the 0x006101XX range is some kind of main control area + * that enables things. +@@ -221,17 +86,20 @@ + val = nv_rd32(dev, 0x0061610c + (i * 0x800)); + nv_wr32(dev, 0x0061019c + (i * 0x10), val); + } ++ + /* DAC */ + for (i = 0; i < 3; i++) { + val = nv_rd32(dev, 0x0061a000 + (i * 0x800)); nv_wr32(dev, 0x006101d0 + (i * 0x04), val); } ++ /* SOR */ - for (i = 0; i < 4; i++) { + for (i = 0; i < nv50_sor_nr(dev); i++) { @@ -10432,11 +13407,29 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.36- nv_wr32(dev, 0x006101e0 + (i * 0x04), val); } - /* Something not yet in use, tv-out maybe. */ ++ + /* EXT */ for (i = 0; i < 3; i++) { val = nv_rd32(dev, 0x0061e000 + (i * 0x800)); nv_wr32(dev, 0x006101f0 + (i * 0x04), val); -@@ -260,7 +279,7 @@ +@@ -243,24 +111,13 @@ + nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(i), 0x00000001); + } + +- /* This used to be in crtc unblank, but seems out of place there. */ +- nv_wr32(dev, NV50_PDISPLAY_UNK_380, 0); +- /* RAM is clamped to 256 MiB. */ +- ram_amount = dev_priv->vram_size; +- NV_DEBUG_KMS(dev, "ram_amount %d\n", ram_amount); +- if (ram_amount > 256*1024*1024) +- ram_amount = 256*1024*1024; +- nv_wr32(dev, NV50_PDISPLAY_RAM_AMOUNT, ram_amount - 1); +- nv_wr32(dev, NV50_PDISPLAY_UNK_388, 0x150000); +- nv_wr32(dev, NV50_PDISPLAY_UNK_38C, 0); +- + /* The precise purpose is unknown, i suspect it has something to do + * with text mode. + */ if (nv_rd32(dev, NV50_PDISPLAY_INTR_1) & 0x100) { nv_wr32(dev, NV50_PDISPLAY_INTR_1, 0x100); nv_wr32(dev, 0x006194e8, nv_rd32(dev, 0x006194e8) & ~1); @@ -10445,18 +13438,40 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.36- NV_ERROR(dev, "timeout: (0x6194e8 & 2) != 0\n"); NV_ERROR(dev, "0x6194e8 = 0x%08x\n", nv_rd32(dev, 0x6194e8)); -@@ -291,7 +310,8 @@ +@@ -268,39 +125,9 @@ + } + } - nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, NV50_PDISPLAY_CTRL_STATE_ENABLE); - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1000b03); +- /* taken from nv bug #12637, attempts to un-wedge the hw if it's +- * stuck in some unspecified state +- */ +- start = ptimer->read(dev); +- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x2b00); +- while ((val = nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))) & 0x1e0000) { +- if ((val & 0x9f0000) == 0x20000) +- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), +- val | 0x800000); +- +- if ((val & 0x3f0000) == 0x30000) +- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), +- val | 0x200000); +- +- if (ptimer->read(dev) - start > 1000000000ULL) { +- NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) != 0\n"); +- NV_ERROR(dev, "0x610200 = 0x%08x\n", val); +- return -EBUSY; +- } +- } +- +- nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, NV50_PDISPLAY_CTRL_STATE_ENABLE); +- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1000b03); - if (!nv_wait(NV50_PDISPLAY_CHANNEL_STAT(0), 0x40000000, 0x40000000)) { -+ if (!nv_wait(dev, NV50_PDISPLAY_CHANNEL_STAT(0), -+ 0x40000000, 0x40000000)) { - NV_ERROR(dev, "timeout: (0x610200 & 0x40000000) == 0x40000000\n"); - NV_ERROR(dev, "0x610200 = 0x%08x\n", - nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); -@@ -300,7 +320,7 @@ - +- NV_ERROR(dev, "timeout: (0x610200 & 0x40000000) == 0x40000000\n"); +- NV_ERROR(dev, "0x610200 = 0x%08x\n", +- nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); +- return -EBUSY; +- } +- for (i = 0; i < 2; i++) { nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000); - if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), @@ -10464,7 +13479,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.36- NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", -@@ -310,7 +330,7 @@ +@@ -310,7 +137,7 @@ nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON); @@ -10473,25 +13488,67 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.36- NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE)) { NV_ERROR(dev, "timeout: " -@@ -321,7 +341,7 @@ +@@ -321,39 +148,31 @@ } } - nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->instance >> 8) | 9); ++ nv_wr32(dev, NV50_PDISPLAY_PIO_CTRL, 0x00000000); ++ nv_mask(dev, NV50_PDISPLAY_INTR_0, 0x00000000, 0x00000000); ++ nv_wr32(dev, NV50_PDISPLAY_INTR_EN_0, 0x00000000); ++ nv_mask(dev, NV50_PDISPLAY_INTR_1, 0x00000000, 0x00000000); ++ nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, ++ NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 | ++ NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 | ++ NV50_PDISPLAY_INTR_EN_1_CLK_UNK40); ++ ++ /* enable hotplug interrupts */ ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { ++ struct nouveau_connector *conn = nouveau_connector(connector); ++ ++ if (conn->dcb->gpio_tag == 0xff) ++ continue; + +- /* initialise fifo */ +- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_DMA_CB(0), +- ((evo->pushbuf_bo->bo.mem.mm_node->start << PAGE_SHIFT) >> 8) | +- NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM | +- NV50_PDISPLAY_CHANNEL_DMA_CB_VALID); +- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK2(0), 0x00010000); +- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK3(0), 0x00000002); +- if (!nv_wait(0x610200, 0x80000000, 0x00000000)) { +- NV_ERROR(dev, "timeout: (0x610200 & 0x80000000) == 0\n"); +- NV_ERROR(dev, "0x610200 = 0x%08x\n", nv_rd32(dev, 0x610200)); +- return -EBUSY; +- } +- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), +- (nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0)) & ~0x00000003) | +- NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED); +- nv_wr32(dev, NV50_PDISPLAY_USER_PUT(0), 0); +- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x01000003 | +- NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED); +- nv_wr32(dev, 0x610300, nv_rd32(dev, 0x610300) & ~1); +- +- evo->dma.max = (4096/4) - 2; +- evo->dma.put = 0; +- evo->dma.cur = evo->dma.put; +- evo->dma.free = evo->dma.max - evo->dma.cur; ++ pgpio->irq_enable(dev, conn->dcb->gpio_tag, true); ++ } + +- ret = RING_SPACE(evo, NOUVEAU_DMA_SKIPS); ++ ret = nv50_evo_init(dev); + if (ret) + return ret; ++ evo = dev_priv->evo; + +- for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) +- OUT_RING(evo, 0); + nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); - /* initialise fifo */ - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_DMA_CB(0), -@@ -330,7 +350,7 @@ - NV50_PDISPLAY_CHANNEL_DMA_CB_VALID); - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK2(0), 0x00010000); - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK3(0), 0x00000002); -- if (!nv_wait(0x610200, 0x80000000, 0x00000000)) { -+ if (!nv_wait(dev, 0x610200, 0x80000000, 0x00000000)) { - NV_ERROR(dev, "timeout: (0x610200 & 0x80000000) == 0\n"); - NV_ERROR(dev, "0x610200 = 0x%08x\n", nv_rd32(dev, 0x610200)); - return -EBUSY; -@@ -370,7 +390,7 @@ + ret = RING_SPACE(evo, 11); + if (ret) +@@ -370,24 +189,9 @@ BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1); OUT_RING(evo, 0); FIRE_RING(evo); @@ -10499,8 +13556,25 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.36- + if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2)) NV_ERROR(dev, "evo pushbuf stalled\n"); - /* enable clock change interrupts. */ -@@ -424,7 +444,7 @@ +- /* enable clock change interrupts. */ +- nv_wr32(dev, 0x610028, 0x00010001); +- nv_wr32(dev, NV50_PDISPLAY_INTR_EN, (NV50_PDISPLAY_INTR_EN_CLK_UNK10 | +- NV50_PDISPLAY_INTR_EN_CLK_UNK20 | +- NV50_PDISPLAY_INTR_EN_CLK_UNK40)); +- +- /* enable hotplug interrupts */ +- list_for_each_entry(connector, &dev->mode_config.connector_list, head) { +- struct nouveau_connector *conn = nouveau_connector(connector); +- +- if (conn->dcb->gpio_tag == 0xff) +- continue; +- +- pgpio->irq_enable(dev, conn->dcb->gpio_tag, true); +- } + + return 0; + } +@@ -424,7 +228,7 @@ continue; nv_wr32(dev, NV50_PDISPLAY_INTR_1, mask); @@ -10509,24 +13583,104 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.36- NV_ERROR(dev, "timeout: (0x610024 & 0x%08x) == " "0x%08x\n", mask, mask); NV_ERROR(dev, "0x610024 = 0x%08x\n", -@@ -434,14 +454,14 @@ - - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0); - nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, 0); -- if (!nv_wait(NV50_PDISPLAY_CHANNEL_STAT(0), 0x1e0000, 0)) { -+ if (!nv_wait(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1e0000, 0)) { - NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) == 0\n"); - NV_ERROR(dev, "0x610200 = 0x%08x\n", - nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); +@@ -432,16 +236,10 @@ + } } +- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0); +- nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, 0); +- if (!nv_wait(NV50_PDISPLAY_CHANNEL_STAT(0), 0x1e0000, 0)) { +- NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) == 0\n"); +- NV_ERROR(dev, "0x610200 = 0x%08x\n", +- nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); +- } ++ nv50_evo_fini(dev); + for (i = 0; i < 3; i++) { - if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_STATE(i), + if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_STATE(i), NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", i); NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", i, -@@ -710,7 +730,7 @@ +@@ -450,7 +248,7 @@ + } + + /* disable interrupts. */ +- nv_wr32(dev, NV50_PDISPLAY_INTR_EN, 0x00000000); ++ nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, 0x00000000); + + /* disable hotplug interrupts */ + nv_wr32(dev, 0xe054, 0xffffffff); +@@ -488,13 +286,6 @@ + + dev->mode_config.fb_base = dev_priv->fb_phys; + +- /* Create EVO channel */ +- ret = nv50_evo_channel_new(dev, &dev_priv->evo); +- if (ret) { +- NV_ERROR(dev, "Error creating EVO channel: %d\n", ret); +- return ret; +- } +- + /* Create CRTC objects */ + for (i = 0; i < 2; i++) + nv50_crtc_create(dev, i); +@@ -549,14 +340,11 @@ + void + nv50_display_destroy(struct drm_device *dev) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- + NV_DEBUG_KMS(dev, "\n"); + + drm_mode_config_cleanup(dev); + + nv50_display_disable(dev); +- nv50_evo_channel_del(&dev_priv->evo); + } + + static u16 +@@ -640,32 +428,29 @@ + nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *chan; +- struct list_head *entry, *tmp; +- +- list_for_each_safe(entry, tmp, &dev_priv->vbl_waiting) { +- chan = list_entry(entry, struct nouveau_channel, nvsw.vbl_wait); ++ struct nouveau_channel *chan, *tmp; + ++ list_for_each_entry_safe(chan, tmp, &dev_priv->vbl_waiting, ++ nvsw.vbl_wait) { + nouveau_bo_wr32(chan->notifier_bo, chan->nvsw.vblsem_offset, + chan->nvsw.vblsem_rval); + list_del(&chan->nvsw.vbl_wait); ++ drm_vblank_put(dev, crtc); + } ++ ++ drm_handle_vblank(dev, crtc); + } + + static void + nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr) + { +- intr &= NV50_PDISPLAY_INTR_1_VBLANK_CRTC; +- + if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_0) + nv50_display_vblank_crtc_handler(dev, 0); + + if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_1) + nv50_display_vblank_crtc_handler(dev, 1); + +- nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev, +- NV50_PDISPLAY_INTR_EN) & ~intr); +- nv_wr32(dev, NV50_PDISPLAY_INTR_1, intr); ++ nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_VBLANK_CRTC); + } + + static void +@@ -710,7 +495,7 @@ or = i; } @@ -10535,7 +13689,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.36- if (dev_priv->chipset < 0x90 || dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0) -@@ -841,7 +861,7 @@ +@@ -841,7 +626,7 @@ or = i; } @@ -10544,9 +13698,400 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.36- if (dev_priv->chipset < 0x90 || dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0) -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_fb.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_fb.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_fb.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_fb.c 2010-10-15 02:04:44.435993127 +0200 +@@ -991,16 +776,23 @@ + static void + nv50_display_error_handler(struct drm_device *dev) + { +- uint32_t addr, data; ++ u32 channels = (nv_rd32(dev, NV50_PDISPLAY_INTR_0) & 0x001f0000) >> 16; ++ u32 addr, data; ++ int chid; ++ ++ for (chid = 0; chid < 5; chid++) { ++ if (!(channels & (1 << chid))) ++ continue; ++ ++ nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000 << chid); ++ addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid)); ++ data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA(chid)); ++ NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x " ++ "(0x%04x 0x%02x)\n", chid, ++ addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf); + +- nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000); +- addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR); +- data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA); +- +- NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x (0x%04x 0x%02x)\n", +- 0, addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf); +- +- nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000); ++ nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid), 0x90000000); ++ } + } + + void +@@ -1086,9 +878,9 @@ + if (!intr0 && !(intr1 & ~delayed)) + break; + +- if (intr0 & 0x00010000) { ++ if (intr0 & 0x001f0000) { + nv50_display_error_handler(dev); +- intr0 &= ~0x00010000; ++ intr0 &= ~0x001f0000; + } + + if (intr1 & NV50_PDISPLAY_INTR_1_VBLANK_CRTC) { +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_evo.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_evo.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_evo.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_evo.c 2010-10-22 23:59:52.577454708 +0200 +@@ -0,0 +1,318 @@ ++/* ++ * 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" ++#include "nouveau_ramht.h" ++ ++static void ++nv50_evo_channel_del(struct nouveau_channel **pevo) ++{ ++ struct drm_nouveau_private *dev_priv; ++ struct nouveau_channel *evo = *pevo; ++ ++ if (!evo) ++ return; ++ *pevo = NULL; ++ ++ dev_priv = evo->dev->dev_private; ++ dev_priv->evo_alloc &= ~(1 << evo->id); ++ ++ nouveau_gpuobj_channel_takedown(evo); ++ nouveau_bo_unmap(evo->pushbuf_bo); ++ nouveau_bo_ref(NULL, &evo->pushbuf_bo); ++ ++ if (evo->user) ++ iounmap(evo->user); ++ ++ kfree(evo); ++} ++ ++int ++nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 class, u32 name, ++ u32 tile_flags, u32 magic_flags, u32 offset, u32 limit) ++{ ++ struct drm_nouveau_private *dev_priv = evo->dev->dev_private; ++ struct drm_device *dev = evo->dev; ++ struct nouveau_gpuobj *obj = NULL; ++ int ret; ++ ++ ret = nouveau_gpuobj_new(dev, dev_priv->evo, 6*4, 32, 0, &obj); ++ if (ret) ++ return ret; ++ obj->engine = NVOBJ_ENGINE_DISPLAY; ++ ++ nv_wo32(obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); ++ nv_wo32(obj, 4, limit); ++ 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); ++ dev_priv->engine.instmem.flush(dev); ++ ++ ret = nouveau_ramht_insert(evo, name, obj); ++ nouveau_gpuobj_ref(NULL, &obj); ++ if (ret) { ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ++nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_channel *evo; ++ int ret; ++ ++ evo = kzalloc(sizeof(struct nouveau_channel), GFP_KERNEL); ++ if (!evo) ++ return -ENOMEM; ++ *pevo = evo; ++ ++ for (evo->id = 0; evo->id < 5; evo->id++) { ++ if (dev_priv->evo_alloc & (1 << evo->id)) ++ continue; ++ ++ dev_priv->evo_alloc |= (1 << evo->id); ++ break; ++ } ++ ++ if (evo->id == 5) { ++ kfree(evo); ++ return -ENODEV; ++ } ++ ++ evo->dev = dev; ++ evo->user_get = 4; ++ evo->user_put = 0; ++ ++ ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, ++ false, true, &evo->pushbuf_bo); ++ if (ret == 0) ++ ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM); ++ if (ret) { ++ NV_ERROR(dev, "Error creating EVO DMA push buffer: %d\n", ret); ++ nv50_evo_channel_del(pevo); ++ return ret; ++ } ++ ++ ret = nouveau_bo_map(evo->pushbuf_bo); ++ if (ret) { ++ NV_ERROR(dev, "Error mapping EVO DMA push buffer: %d\n", ret); ++ nv50_evo_channel_del(pevo); ++ return ret; ++ } ++ ++ evo->user = ioremap(pci_resource_start(dev->pdev, 0) + ++ NV50_PDISPLAY_USER(evo->id), PAGE_SIZE); ++ if (!evo->user) { ++ NV_ERROR(dev, "Error mapping EVO control regs.\n"); ++ nv50_evo_channel_del(pevo); ++ return -ENOMEM; ++ } ++ ++ /* bind primary evo channel's ramht to the channel */ ++ if (dev_priv->evo && evo != dev_priv->evo) ++ nouveau_ramht_ref(dev_priv->evo->ramht, &evo->ramht, NULL); ++ ++ return 0; ++} ++ ++static int ++nv50_evo_channel_init(struct nouveau_channel *evo) ++{ ++ struct drm_device *dev = evo->dev; ++ int id = evo->id, ret, i; ++ u64 pushbuf = evo->pushbuf_bo->bo.mem.start << PAGE_SHIFT; ++ u32 tmp; ++ ++ tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)); ++ if ((tmp & 0x009f0000) == 0x00020000) ++ nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00800000); ++ ++ tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)); ++ if ((tmp & 0x003f0000) == 0x00030000) ++ nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00600000); ++ ++ /* initialise fifo */ ++ nv_wr32(dev, NV50_PDISPLAY_EVO_DMA_CB(id), pushbuf >> 8 | ++ NV50_PDISPLAY_EVO_DMA_CB_LOCATION_VRAM | ++ NV50_PDISPLAY_EVO_DMA_CB_VALID); ++ nv_wr32(dev, NV50_PDISPLAY_EVO_UNK2(id), 0x00010000); ++ nv_wr32(dev, NV50_PDISPLAY_EVO_HASH_TAG(id), id); ++ nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), NV50_PDISPLAY_EVO_CTRL_DMA, ++ NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED); ++ ++ nv_wr32(dev, NV50_PDISPLAY_USER_PUT(id), 0x00000000); ++ nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x01000003 | ++ NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED); ++ if (!nv_wait(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x80000000, 0x00000000)) { ++ NV_ERROR(dev, "EvoCh %d init timeout: 0x%08x\n", id, ++ nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id))); ++ return -EBUSY; ++ } ++ ++ /* enable error reporting on the channel */ ++ nv_mask(dev, 0x610028, 0x00000000, 0x00010001 << id); ++ ++ evo->dma.max = (4096/4) - 2; ++ evo->dma.put = 0; ++ evo->dma.cur = evo->dma.put; ++ evo->dma.free = evo->dma.max - evo->dma.cur; ++ ++ ret = RING_SPACE(evo, NOUVEAU_DMA_SKIPS); ++ if (ret) ++ return ret; ++ ++ for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) ++ OUT_RING(evo, 0); ++ ++ return 0; ++} ++ ++static void ++nv50_evo_channel_fini(struct nouveau_channel *evo) ++{ ++ struct drm_device *dev = evo->dev; ++ int id = evo->id; ++ ++ nv_mask(dev, 0x610028, 0x00010001 << id, 0x00000000); ++ nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x00001010, 0x00001000); ++ nv_wr32(dev, NV50_PDISPLAY_INTR_0, (1 << id)); ++ nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x00000003, 0x00000000); ++ if (!nv_wait(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x001e0000, 0x00000000)) { ++ NV_ERROR(dev, "EvoCh %d takedown timeout: 0x%08x\n", id, ++ nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id))); ++ } ++} ++ ++static int ++nv50_evo_create(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpuobj *ramht = NULL; ++ struct nouveau_channel *evo; ++ int ret; ++ ++ /* create primary evo channel, the one we use for modesetting ++ * purporses ++ */ ++ ret = nv50_evo_channel_new(dev, &dev_priv->evo); ++ if (ret) ++ return ret; ++ evo = dev_priv->evo; ++ ++ /* setup object management on it, any other evo channel will ++ * use this also as there's no per-channel support on the ++ * hardware ++ */ ++ ret = nouveau_gpuobj_new(dev, NULL, 32768, 65536, ++ NVOBJ_FLAG_ZERO_ALLOC, &evo->ramin); ++ if (ret) { ++ NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); ++ nv50_evo_channel_del(&dev_priv->evo); ++ return ret; ++ } ++ ++ ret = drm_mm_init(&evo->ramin_heap, 0, 32768); ++ if (ret) { ++ NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); ++ nv50_evo_channel_del(&dev_priv->evo); ++ return ret; ++ } ++ ++ ret = nouveau_gpuobj_new(dev, evo, 4096, 16, 0, &ramht); ++ if (ret) { ++ NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); ++ nv50_evo_channel_del(&dev_priv->evo); ++ return ret; ++ } ++ ++ ret = nouveau_ramht_new(dev, ramht, &evo->ramht); ++ nouveau_gpuobj_ref(NULL, &ramht); ++ if (ret) { ++ nv50_evo_channel_del(&dev_priv->evo); ++ return ret; ++ } ++ ++ /* create some default objects for the scanout memtypes we support */ ++ if (dev_priv->chipset != 0x50) { ++ ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB16, 0x70, 0x19, ++ 0, 0xffffffff); ++ if (ret) { ++ nv50_evo_channel_del(&dev_priv->evo); ++ return ret; ++ } ++ ++ ++ ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0x7a, 0x19, ++ 0, 0xffffffff); ++ 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; ++ } ++ ++ return 0; ++} ++ ++int ++nv50_evo_init(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ int ret; ++ ++ if (!dev_priv->evo) { ++ ret = nv50_evo_create(dev); ++ if (ret) ++ return ret; ++ } ++ ++ return nv50_evo_channel_init(dev_priv->evo); ++} ++ ++void ++nv50_evo_fini(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ if (dev_priv->evo) { ++ nv50_evo_channel_fini(dev_priv->evo); ++ nv50_evo_channel_del(&dev_priv->evo); ++ } ++} +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_evo.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_evo.h +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_evo.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_evo.h 2010-10-22 23:59:52.577454708 +0200 +@@ -24,6 +24,15 @@ + * + */ + ++#ifndef __NV50_EVO_H__ ++#define __NV50_EVO_H__ ++ ++int nv50_evo_init(struct drm_device *dev); ++void nv50_evo_fini(struct drm_device *dev); ++int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 class, u32 name, ++ u32 tile_flags, u32 magic_flags, ++ u32 offset, u32 limit); ++ + #define NV50_EVO_UPDATE 0x00000080 + #define NV50_EVO_UNK84 0x00000084 + #define NV50_EVO_UNK84_NOTIFY 0x40000000 +@@ -111,3 +120,4 @@ + #define NV50_EVO_CRTC_SCALE_RES1 0x000008d8 + #define NV50_EVO_CRTC_SCALE_RES2 0x000008dc + ++#endif +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_fb.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_fb.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_fb.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_fb.c 2010-10-22 23:59:52.588454844 +0200 @@ -20,6 +20,7 @@ case 0x50: nv_wr32(dev, 0x100c90, 0x0707ff); @@ -10602,9 +14147,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_fb.c linux-2.6.36-rc7.p + trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, + trap[0], ch, chinst); +} -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_fbcon.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_fbcon.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_fbcon.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_fbcon.c 2010-10-15 02:04:44.436993140 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_fbcon.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_fbcon.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_fbcon.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_fbcon.c 2010-10-22 23:59:52.589454857 +0200 @@ -1,28 +1,21 @@ #include "drmP.h" #include "nouveau_drv.h" @@ -10749,9 +14294,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_fbcon.c linux-2.6.36-rc if (ret) return ret; -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_fifo.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_fifo.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_fifo.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_fifo.c 2010-10-15 02:04:44.439993176 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_fifo.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_fifo.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_fifo.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_fifo.c 2010-10-22 23:59:52.590454870 +0200 @@ -27,13 +27,14 @@ #include "drmP.h" #include "drm.h" @@ -10942,15 +14487,28 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_fifo.c linux-2.6.36-rc7 } dev_priv->engine.instmem.flush(dev); -@@ -293,12 +292,13 @@ +@@ -293,12 +292,26 @@ nv50_fifo_destroy_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; - struct nouveau_gpuobj_ref *ramfc = chan->ramfc; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + struct nouveau_gpuobj *ramfc = NULL; ++ unsigned long flags; NV_DEBUG(dev, "ch%d\n", chan->id); ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ pfifo->reassign(dev, false); ++ ++ /* Unload the context if it's the currently active one */ ++ if (pfifo->channel_id(dev) == chan->id) { ++ pfifo->disable(dev); ++ pfifo->unload_context(dev); ++ pfifo->enable(dev); ++ } ++ /* This will ensure the channel is seen as disabled. */ - chan->ramfc = NULL; + nouveau_gpuobj_ref(chan->ramfc, &ramfc); @@ -10958,18 +14516,22 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_fifo.c linux-2.6.36-rc7 nv50_fifo_channel_disable(dev, chan->id); /* Dummy channel, also used on ch 127 */ -@@ -306,8 +306,8 @@ +@@ -306,8 +319,12 @@ nv50_fifo_channel_disable(dev, 127); nv50_fifo_playlist_update(dev); - nouveau_gpuobj_ref_del(dev, &ramfc); - nouveau_gpuobj_ref_del(dev, &chan->cache); ++ pfifo->reassign(dev, true); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); ++ ++ /* Free the channel resources */ + nouveau_gpuobj_ref(NULL, &ramfc); + nouveau_gpuobj_ref(NULL, &chan->cache); } int -@@ -315,63 +315,63 @@ +@@ -315,63 +332,63 @@ { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -11076,7 +14638,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_fifo.c linux-2.6.36-rc7 } nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16)); -@@ -393,68 +393,69 @@ +@@ -393,68 +410,69 @@ if (chid < 1 || chid >= dev_priv->engine.fifo.channels - 1) return 0; @@ -11192,19 +14754,41 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_fifo.c linux-2.6.36-rc7 } dev_priv->engine.instmem.flush(dev); -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_graph.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_graph.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_graph.c 2010-10-15 02:04:44.441993202 +0200 -@@ -27,7 +27,7 @@ +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_graph.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_graph.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_graph.c 2010-10-22 23:59:52.591454883 +0200 +@@ -27,8 +27,12 @@ #include "drmP.h" #include "drm.h" #include "nouveau_drv.h" - +#include "nouveau_ramht.h" #include "nouveau_grctx.h" ++#include "nouveau_dma.h" ++#include "nv50_evo.h" ++ ++static int nv50_graph_register(struct drm_device *); static void -@@ -181,7 +181,7 @@ + nv50_graph_init_reset(struct drm_device *dev) +@@ -145,12 +149,15 @@ + nv50_graph_init_reset(dev); + nv50_graph_init_regs__nv(dev); + nv50_graph_init_regs(dev); +- nv50_graph_init_intr(dev); + + ret = nv50_graph_init_ctxctl(dev); + if (ret) + return ret; + ++ ret = nv50_graph_register(dev); ++ if (ret) ++ return ret; ++ nv50_graph_init_intr(dev); + return 0; + } + +@@ -181,7 +188,7 @@ /* Be sure we're not in the middle of a context switch or bad things * will happen, such as unloading the wrong pgraph context. */ @@ -11213,7 +14797,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.36-rc NV_ERROR(dev, "Ctxprog is still running\n"); inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR); -@@ -190,9 +190,9 @@ +@@ -190,9 +197,9 @@ inst = (inst & NV50_PGRAPH_CTXCTL_CUR_INSTANCE) << 12; for (i = 0; i < dev_priv->engine.fifo.channels; i++) { @@ -11225,7 +14809,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.36-rc return chan; } -@@ -204,36 +204,34 @@ +@@ -204,36 +211,34 @@ { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -11241,7 +14825,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.36-rc - ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size, - 0x1000, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx); -+ ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 0x1000, ++ ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 0, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx); if (ret) @@ -11275,7 +14859,13 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.36-rc dev_priv->engine.instmem.flush(dev); return 0; -@@ -248,14 +246,14 @@ +@@ -244,18 +249,29 @@ + { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; ++ unsigned long flags; NV_DEBUG(dev, "ch%d\n", chan->id); @@ -11283,17 +14873,26 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.36-rc + if (!chan->ramin) return; ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ pgraph->fifo_access(dev, false); ++ ++ if (pgraph->channel(dev) == chan) ++ pgraph->unload_context(dev); ++ for (i = hdr; i < hdr + 24; i += 4) - nv_wo32(dev, chan->ramin->gpuobj, i/4, 0); + nv_wo32(chan->ramin, i, 0); dev_priv->engine.instmem.flush(dev); - nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); ++ pgraph->fifo_access(dev, true); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); ++ + nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); } static int -@@ -282,7 +280,7 @@ +@@ -282,7 +298,7 @@ int nv50_graph_load_context(struct nouveau_channel *chan) { @@ -11302,9 +14901,14 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.36-rc NV_DEBUG(chan->dev, "ch%d\n", chan->id); return nv50_graph_do_load_context(chan->dev, inst); -@@ -327,15 +325,16 @@ - nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +@@ -324,25 +340,26 @@ + } + + static int +-nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) { - struct nouveau_gpuobj_ref *ref = NULL; + struct nouveau_gpuobj *gpuobj; @@ -11323,9 +14927,138 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.36-rc chan->nvsw.vblsem_offset = ~0; return 0; } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_grctx.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_grctx.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_grctx.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_grctx.c 2010-10-15 02:04:44.448993289 +0200 + + static int +-nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + if (nouveau_notifier_offset(chan->nvsw.vblsem, &data)) + return -ERANGE; +@@ -352,16 +369,16 @@ + } + + static int +-nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + chan->nvsw.vblsem_rval = data; + return 0; + } + + static int +-nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan, int grclass, +- int mthd, uint32_t data) ++nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) + { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +@@ -369,37 +386,69 @@ + if (!chan->nvsw.vblsem || chan->nvsw.vblsem_offset == ~0 || data > 1) + return -EINVAL; + +- if (!(nv_rd32(dev, NV50_PDISPLAY_INTR_EN) & +- NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data))) { +- nv_wr32(dev, NV50_PDISPLAY_INTR_1, +- NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(data)); +- nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev, +- NV50_PDISPLAY_INTR_EN) | +- NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data)); ++ drm_vblank_get(dev, data); ++ list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting); ++ return 0; ++} ++ ++static int ++nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) ++{ ++ struct nouveau_page_flip_state s; ++ ++ if (!nouveau_finish_page_flip(chan, &s)) { ++ /* XXX - Do something here */ + } + +- list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting); + return 0; + } + +-static struct nouveau_pgraph_object_method nv50_graph_nvsw_methods[] = { +- { 0x018c, nv50_graph_nvsw_dma_vblsem }, +- { 0x0400, nv50_graph_nvsw_vblsem_offset }, +- { 0x0404, nv50_graph_nvsw_vblsem_release_val }, +- { 0x0408, nv50_graph_nvsw_vblsem_release }, +- {} +-}; +- +-struct nouveau_pgraph_object_class nv50_graph_grclass[] = { +- { 0x506e, true, nv50_graph_nvsw_methods }, /* nvsw */ +- { 0x0030, false, NULL }, /* null */ +- { 0x5039, false, NULL }, /* m2mf */ +- { 0x502d, false, NULL }, /* 2d */ +- { 0x50c0, false, NULL }, /* compute */ +- { 0x85c0, false, NULL }, /* compute (nva3, nva5, nva8) */ +- { 0x5097, false, NULL }, /* tesla (nv50) */ +- { 0x8297, false, NULL }, /* tesla (nv8x/nv9x) */ +- { 0x8397, false, NULL }, /* tesla (nva0, nvaa, nvac) */ +- { 0x8597, false, NULL }, /* tesla (nva3, nva5, nva8) */ +- {} +-}; ++static int ++nv50_graph_register(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ if (dev_priv->engine.graph.registered) ++ return 0; ++ ++ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ ++ NVOBJ_MTHD (dev, 0x506e, 0x018c, nv50_graph_nvsw_dma_vblsem); ++ NVOBJ_MTHD (dev, 0x506e, 0x0400, nv50_graph_nvsw_vblsem_offset); ++ NVOBJ_MTHD (dev, 0x506e, 0x0404, nv50_graph_nvsw_vblsem_release_val); ++ NVOBJ_MTHD (dev, 0x506e, 0x0408, nv50_graph_nvsw_vblsem_release); ++ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv50_graph_nvsw_mthd_page_flip); ++ ++ NVOBJ_CLASS(dev, 0x0030, GR); /* null */ ++ NVOBJ_CLASS(dev, 0x5039, GR); /* m2mf */ ++ NVOBJ_CLASS(dev, 0x502d, GR); /* 2d */ ++ NVOBJ_CLASS(dev, 0x50c0, GR); /* compute */ ++ NVOBJ_CLASS(dev, 0x85c0, GR); /* compute (nva3, nva5, nva8) */ ++ ++ /* tesla */ ++ if (dev_priv->chipset == 0x50) ++ NVOBJ_CLASS(dev, 0x5097, GR); /* tesla (nv50) */ ++ else ++ if (dev_priv->chipset < 0xa0) ++ NVOBJ_CLASS(dev, 0x8297, GR); /* tesla (nv8x/nv9x) */ ++ else { ++ switch (dev_priv->chipset) { ++ case 0xa0: ++ case 0xaa: ++ case 0xac: ++ NVOBJ_CLASS(dev, 0x8397, GR); ++ break; ++ case 0xa3: ++ case 0xa5: ++ case 0xa8: ++ NVOBJ_CLASS(dev, 0x8597, GR); ++ break; ++ case 0xaf: ++ NVOBJ_CLASS(dev, 0x8697, GR); ++ break; ++ } ++ } ++ ++ dev_priv->engine.graph.registered = true; ++ return 0; ++} +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_grctx.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_grctx.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_grctx.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_grctx.c 2010-10-22 23:59:52.597454955 +0200 @@ -103,6 +103,9 @@ #include "nouveau_drv.h" #include "nouveau_grctx.h" @@ -15135,9 +18868,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_grctx.c linux-2.6.36-rc if ((ctx->ctxvals_pos-offset)/8 > size) size = (ctx->ctxvals_pos-offset)/8; } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_instmem.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_instmem.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_instmem.c 2010-10-15 02:04:44.451993326 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_instmem.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_instmem.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_instmem.c 2010-10-22 23:59:52.601455006 +0200 @@ -32,39 +32,87 @@ struct nv50_instmem_priv { uint32_t save1700[5]; /* 0x1700->0x1710 */ @@ -15639,15 +19372,31 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6.36- NV50_PUNK_BAR3_CTXDMA_VALID); for (i = 0; i < 8; i++) -@@ -381,7 +329,7 @@ +@@ -374,19 +322,19 @@ + + int + nv50_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, +- uint32_t *sz) ++ u32 *size, u32 align) + { + int ret; + if (gpuobj->im_backing) return -EINVAL; - *sz = ALIGN(*sz, NV50_INSTMEM_PAGE_SIZE); -+ *sz = ALIGN(*sz, 4096); - if (*sz == 0) +- if (*sz == 0) ++ *size = ALIGN(*size, 4096); ++ if (*size == 0) return -EINVAL; +- ret = nouveau_bo_new(dev, NULL, *sz, 0, TTM_PL_FLAG_VRAM, 0, 0x0000, +- true, false, &gpuobj->im_backing); ++ ret = nouveau_bo_new(dev, NULL, *size, align, TTM_PL_FLAG_VRAM, ++ 0, 0x0000, true, false, &gpuobj->im_backing); + if (ret) { + NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret); + return ret; @@ -399,9 +347,7 @@ return ret; } @@ -15655,7 +19404,7 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6.36- - gpuobj->im_backing_start = gpuobj->im_backing->bo.mem.mm_node->start; - gpuobj->im_backing_start <<= PAGE_SHIFT; - -+ gpuobj->vinst = gpuobj->im_backing->bo.mem.mm_node->start << PAGE_SHIFT; ++ gpuobj->vinst = gpuobj->im_backing->bo.mem.start << PAGE_SHIFT; return 0; } @@ -15743,9 +19492,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6.36- NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_pm.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_pm.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_pm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_pm.c 2010-10-15 02:04:44.452993338 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_pm.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_pm.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_pm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_pm.c 2010-10-22 23:59:52.602455019 +0200 @@ -0,0 +1,131 @@ +/* + * Copyright 2010 Red Hat Inc. @@ -15878,9 +19627,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_pm.c linux-2.6.36-rc7.p + kfree(state); +} + -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_sor.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_sor.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_sor.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nv50_sor.c 2010-10-15 02:04:44.454993362 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv50_sor.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_sor.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv50_sor.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv50_sor.c 2010-10-22 23:59:52.603455031 +0200 @@ -92,7 +92,7 @@ } @@ -15899,9 +19648,117 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nv50_sor.c linux-2.6.36-rc7. NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", or); NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", or, -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nva3_pm.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nva3_pm.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nva3_pm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nva3_pm.c 2010-10-15 02:04:44.456993388 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nv84_crypt.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv84_crypt.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nv84_crypt.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nv84_crypt.c 2010-10-22 23:59:52.604455043 +0200 +@@ -0,0 +1,104 @@ ++/* ++ * 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" ++ ++int ++nv84_crypt_create_context(struct nouveau_channel *chan) ++{ ++ struct drm_device *dev = chan->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpuobj *ramin = chan->ramin; ++ int ret; ++ ++ NV_DEBUG(dev, "ch%d\n", chan->id); ++ ++ ret = nouveau_gpuobj_new(dev, chan, 256, 0, ++ NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, ++ &chan->crypt_ctx); ++ if (ret) ++ return ret; ++ ++ nv_wo32(ramin, 0xa0, 0x00190000); ++ nv_wo32(ramin, 0xa4, chan->crypt_ctx->vinst + 0xff); ++ nv_wo32(ramin, 0xa8, chan->crypt_ctx->vinst); ++ nv_wo32(ramin, 0xac, 0); ++ nv_wo32(ramin, 0xb0, 0); ++ nv_wo32(ramin, 0xb4, 0); ++ ++ dev_priv->engine.instmem.flush(dev); ++ return 0; ++} ++ ++void ++nv84_crypt_destroy_context(struct nouveau_channel *chan) ++{ ++ struct drm_device *dev = chan->dev; ++ u32 inst; ++ ++ if (!chan->ramin) ++ return; ++ ++ inst = (chan->ramin->vinst >> 12); ++ inst |= 0x80000000; ++ ++ /* mark context as invalid if still on the hardware, not ++ * doing this causes issues the next time PCRYPT is used, ++ * unsurprisingly :) ++ */ ++ nv_wr32(dev, 0x10200c, 0x00000000); ++ if (nv_rd32(dev, 0x102188) == inst) ++ nv_mask(dev, 0x102188, 0x80000000, 0x00000000); ++ if (nv_rd32(dev, 0x10218c) == inst) ++ nv_mask(dev, 0x10218c, 0x80000000, 0x00000000); ++ nv_wr32(dev, 0x10200c, 0x00000010); ++ ++ nouveau_gpuobj_ref(NULL, &chan->crypt_ctx); ++} ++ ++int ++nv84_crypt_init(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt; ++ ++ if (!pcrypt->registered) { ++ NVOBJ_CLASS(dev, 0x74c1, CRYPT); ++ pcrypt->registered = true; ++ } ++ ++ nv_mask(dev, 0x000200, 0x00004000, 0x00000000); ++ nv_mask(dev, 0x000200, 0x00004000, 0x00004000); ++ nv_wr32(dev, 0x102130, 0xffffffff); ++ nv_wr32(dev, 0x102140, 0xffffffbf); ++ nv_wr32(dev, 0x10200c, 0x00000010); ++ return 0; ++} ++ ++void ++nv84_crypt_fini(struct drm_device *dev) ++{ ++ nv_wr32(dev, 0x102140, 0x00000000); ++} +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nva3_pm.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nva3_pm.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nva3_pm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nva3_pm.c 2010-10-22 23:59:52.604455043 +0200 @@ -0,0 +1,95 @@ +/* + * Copyright 2010 Red Hat Inc. @@ -15998,9 +19855,9 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nva3_pm.c linux-2.6.36-rc7.p + kfree(state); +} + -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nvc0_fifo.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nvc0_fifo.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nvc0_fifo.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nvc0_fifo.c 2010-10-15 02:04:44.457993401 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nvc0_fifo.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nvc0_fifo.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nvc0_fifo.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nvc0_fifo.c 2010-10-22 23:59:52.605455055 +0200 @@ -43,12 +43,6 @@ } @@ -16014,16 +19871,36 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nvc0_fifo.c linux-2.6.36-rc7 nvc0_fifo_cache_pull(struct drm_device *dev, bool enable) { return false; -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nvc0_instmem.c linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nvc0_instmem.c ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nvc0_instmem.c 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nvc0_instmem.c 2010-10-15 02:04:44.458993413 +0200 +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nvc0_instmem.c linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nvc0_instmem.c +--- linux-2.6.36/drivers/gpu/drm/nouveau/nvc0_instmem.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nvc0_instmem.c 2010-10-22 23:59:52.605455055 +0200 +@@ -28,7 +28,7 @@ + + int + nvc0_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, +- uint32_t *size) ++ u32 *size, u32 align) + { + int ret; + +@@ -36,8 +36,8 @@ + if (*size == 0) + return -EINVAL; + +- ret = nouveau_bo_new(dev, NULL, *size, 0, TTM_PL_FLAG_VRAM, 0, 0x0000, +- true, false, &gpuobj->im_backing); ++ ret = nouveau_bo_new(dev, NULL, *size, align, TTM_PL_FLAG_VRAM, ++ 0, 0x0000, true, false, &gpuobj->im_backing); + if (ret) { + NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret); + return ret; @@ -50,8 +50,7 @@ return ret; } - gpuobj->im_backing_start = gpuobj->im_backing->bo.mem.mm_node->start; - gpuobj->im_backing_start <<= PAGE_SHIFT; -+ gpuobj->vinst = gpuobj->im_backing->bo.mem.mm_node->start << PAGE_SHIFT; ++ gpuobj->vinst = gpuobj->im_backing->bo.mem.start << PAGE_SHIFT; return 0; } @@ -16061,10 +19938,20 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nvc0_instmem.c linux-2.6.36- return 0; } -diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nvreg.h linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nvreg.h ---- linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nvreg.h 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/gpu/drm/nouveau/nvreg.h 2010-10-15 02:04:44.460993437 +0200 -@@ -263,6 +263,7 @@ +diff -Naur linux-2.6.36/drivers/gpu/drm/nouveau/nvreg.h linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nvreg.h +--- linux-2.6.36/drivers/gpu/drm/nouveau/nvreg.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/nouveau/nvreg.h 2010-10-22 23:59:52.606455067 +0200 +@@ -153,7 +153,8 @@ + #define NV_PCRTC_START 0x00600800 + #define NV_PCRTC_CONFIG 0x00600804 + # define NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA (1 << 0) +-# define NV_PCRTC_CONFIG_START_ADDRESS_HSYNC (2 << 0) ++# define NV04_PCRTC_CONFIG_START_ADDRESS_HSYNC (4 << 0) ++# define NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC (2 << 0) + #define NV_PCRTC_CURSOR_CONFIG 0x00600810 + # define NV_PCRTC_CURSOR_CONFIG_ENABLE_ENABLE (1 << 0) + # define NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE (1 << 4) +@@ -263,6 +264,7 @@ # define NV_CIO_CRE_HCUR_ADDR1_ADR 7:2 # define NV_CIO_CRE_LCD__INDEX 0x33 # define NV_CIO_CRE_LCD_LCD_SELECT 0:0 @@ -16072,18 +19959,625 @@ diff -Naur linux-2.6.36-rc7/drivers/gpu/drm/nouveau/nvreg.h linux-2.6.36-rc7.pat # define NV_CIO_CRE_DDC0_STATUS__INDEX 0x36 # define NV_CIO_CRE_DDC0_WR__INDEX 0x37 # define NV_CIO_CRE_ILACE__INDEX 0x39 /* interlace */ -diff -Naur linux-2.6.36-rc7/include/drm/nouveau_drm.h linux-2.6.36-rc7.patch/include/drm/nouveau_drm.h ---- linux-2.6.36-rc7/include/drm/nouveau_drm.h 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/include/drm/nouveau_drm.h 2010-10-15 02:04:44.518994158 +0200 -@@ -80,6 +80,7 @@ +diff -Naur linux-2.6.36/drivers/gpu/drm/radeon/radeon_object.c linux-2.6.36.nouveau/drivers/gpu/drm/radeon/radeon_object.c +--- linux-2.6.36/drivers/gpu/drm/radeon/radeon_object.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/radeon/radeon_object.c 2010-10-22 23:59:52.618455215 +0200 +@@ -435,7 +435,7 @@ + + out: + radeon_set_surface_reg(rdev, i, bo->tiling_flags, bo->pitch, +- bo->tbo.mem.mm_node->start << PAGE_SHIFT, ++ bo->tbo.mem.start << PAGE_SHIFT, + bo->tbo.num_pages << PAGE_SHIFT); + return 0; + } +@@ -532,7 +532,7 @@ + rdev = rbo->rdev; + if (bo->mem.mem_type == TTM_PL_VRAM) { + size = bo->mem.num_pages << PAGE_SHIFT; +- offset = bo->mem.mm_node->start << PAGE_SHIFT; ++ offset = bo->mem.start << PAGE_SHIFT; + if ((offset + size) > rdev->mc.visible_vram_size) { + /* hurrah the memory is not visible ! */ + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM); +@@ -540,7 +540,7 @@ + r = ttm_bo_validate(bo, &rbo->placement, false, true, false); + if (unlikely(r != 0)) + return r; +- offset = bo->mem.mm_node->start << PAGE_SHIFT; ++ offset = bo->mem.start << PAGE_SHIFT; + /* this should not happen */ + if ((offset + size) > rdev->mc.visible_vram_size) + return -EINVAL; +diff -Naur linux-2.6.36/drivers/gpu/drm/radeon/radeon_ttm.c linux-2.6.36.nouveau/drivers/gpu/drm/radeon/radeon_ttm.c +--- linux-2.6.36/drivers/gpu/drm/radeon/radeon_ttm.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/radeon/radeon_ttm.c 2010-10-22 23:59:52.618455215 +0200 +@@ -152,6 +152,7 @@ + man->default_caching = TTM_PL_FLAG_CACHED; + break; + case TTM_PL_TT: ++ man->func = &ttm_bo_manager_func; + man->gpu_offset = rdev->mc.gtt_start; + man->available_caching = TTM_PL_MASK_CACHING; + man->default_caching = TTM_PL_FLAG_CACHED; +@@ -173,6 +174,7 @@ + break; + case TTM_PL_VRAM: + /* "On-card" video ram */ ++ man->func = &ttm_bo_manager_func; + man->gpu_offset = rdev->mc.vram_start; + man->flags = TTM_MEMTYPE_FLAG_FIXED | + TTM_MEMTYPE_FLAG_MAPPABLE; +@@ -246,8 +248,8 @@ + if (unlikely(r)) { + return r; + } +- old_start = old_mem->mm_node->start << PAGE_SHIFT; +- new_start = new_mem->mm_node->start << PAGE_SHIFT; ++ old_start = old_mem->start << PAGE_SHIFT; ++ new_start = new_mem->start << PAGE_SHIFT; + + switch (old_mem->mem_type) { + case TTM_PL_VRAM: +@@ -326,14 +328,7 @@ + } + r = ttm_bo_move_ttm(bo, true, no_wait_reserve, no_wait_gpu, new_mem); + out_cleanup: +- if (tmp_mem.mm_node) { +- struct ttm_bo_global *glob = rdev->mman.bdev.glob; +- +- spin_lock(&glob->lru_lock); +- drm_mm_put_block(tmp_mem.mm_node); +- spin_unlock(&glob->lru_lock); +- return r; +- } ++ ttm_bo_mem_put(bo, &tmp_mem); + return r; + } + +@@ -372,14 +367,7 @@ + goto out_cleanup; + } + out_cleanup: +- if (tmp_mem.mm_node) { +- struct ttm_bo_global *glob = rdev->mman.bdev.glob; +- +- spin_lock(&glob->lru_lock); +- drm_mm_put_block(tmp_mem.mm_node); +- spin_unlock(&glob->lru_lock); +- return r; +- } ++ ttm_bo_mem_put(bo, &tmp_mem); + return r; + } + +@@ -449,14 +437,14 @@ + #if __OS_HAS_AGP + if (rdev->flags & RADEON_IS_AGP) { + /* RADEON_IS_AGP is set only if AGP is active */ +- mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; ++ mem->bus.offset = mem->start << PAGE_SHIFT; + mem->bus.base = rdev->mc.agp_base; + mem->bus.is_iomem = !rdev->ddev->agp->cant_use_aperture; + } + #endif + break; + case TTM_PL_VRAM: +- mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; ++ mem->bus.offset = mem->start << PAGE_SHIFT; + /* check if it's visible */ + if ((mem->bus.offset + mem->bus.size) > rdev->mc.visible_vram_size) + return -EINVAL; +@@ -699,7 +687,7 @@ + int r; + + gtt = container_of(backend, struct radeon_ttm_backend, backend); +- gtt->offset = bo_mem->mm_node->start << PAGE_SHIFT; ++ gtt->offset = bo_mem->start << PAGE_SHIFT; + if (!gtt->num_pages) { + WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n", gtt->num_pages, bo_mem, backend); + } +@@ -798,9 +786,9 @@ + radeon_mem_types_list[i].show = &radeon_mm_dump_table; + radeon_mem_types_list[i].driver_features = 0; + if (i == 0) +- radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_VRAM].manager; ++ radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_VRAM].priv; + else +- radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_TT].manager; ++ radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_TT].priv; + + } + /* Add ttm page pool to debugfs */ +diff -Naur linux-2.6.36/drivers/gpu/drm/ttm/Makefile linux-2.6.36.nouveau/drivers/gpu/drm/ttm/Makefile +--- linux-2.6.36/drivers/gpu/drm/ttm/Makefile 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/ttm/Makefile 2010-10-22 23:59:52.620455239 +0200 +@@ -4,6 +4,7 @@ + ccflags-y := -Iinclude/drm + ttm-y := ttm_agp_backend.o ttm_memory.o ttm_tt.o ttm_bo.o \ + ttm_bo_util.o ttm_bo_vm.o ttm_module.o \ +- ttm_object.o ttm_lock.o ttm_execbuf_util.o ttm_page_alloc.o ++ ttm_object.o ttm_lock.o ttm_execbuf_util.o ttm_page_alloc.o \ ++ ttm_bo_manager.o + + obj-$(CONFIG_DRM_TTM) += ttm.o +diff -Naur linux-2.6.36/drivers/gpu/drm/ttm/ttm_agp_backend.c linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_agp_backend.c +--- linux-2.6.36/drivers/gpu/drm/ttm/ttm_agp_backend.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_agp_backend.c 2010-10-22 23:59:52.621455252 +0200 +@@ -74,6 +74,7 @@ + { + struct ttm_agp_backend *agp_be = + container_of(backend, struct ttm_agp_backend, backend); ++ struct drm_mm_node *node = bo_mem->mm_node; + struct agp_memory *mem = agp_be->mem; + int cached = (bo_mem->placement & TTM_PL_FLAG_CACHED); + int ret; +@@ -81,7 +82,7 @@ + mem->is_flushed = 1; + mem->type = (cached) ? AGP_USER_CACHED_MEMORY : AGP_USER_MEMORY; + +- ret = agp_bind_memory(mem, bo_mem->mm_node->start); ++ ret = agp_bind_memory(mem, node->start); + if (ret) + printk(KERN_ERR TTM_PFX "AGP Bind memory failed.\n"); + +diff -Naur linux-2.6.36/drivers/gpu/drm/ttm/ttm_bo.c linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_bo.c +--- linux-2.6.36/drivers/gpu/drm/ttm/ttm_bo.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_bo.c 2010-10-23 00:04:39.844020281 +0200 +@@ -84,11 +84,8 @@ + man->available_caching); + printk(KERN_ERR TTM_PFX " default_caching: 0x%08X\n", + man->default_caching); +- if (mem_type != TTM_PL_SYSTEM) { +- spin_lock(&bdev->glob->lru_lock); +- drm_mm_debug_table(&man->manager, TTM_PFX); +- spin_unlock(&bdev->glob->lru_lock); +- } ++ if (mem_type != TTM_PL_SYSTEM) ++ (*man->func->debug)(man, TTM_PFX); + } + + static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, +@@ -421,7 +418,7 @@ + + if (bo->mem.mm_node) { + spin_lock(&bo->lock); +- bo->offset = (bo->mem.mm_node->start << PAGE_SHIFT) + ++ bo->offset = (bo->mem.start << PAGE_SHIFT) + + bdev->man[bo->mem.mem_type].gpu_offset; + bo->cur_placement = bo->mem.placement; + spin_unlock(&bo->lock); +@@ -467,11 +464,7 @@ + spin_lock(&glob->lru_lock); + } + +- if (bo->mem.mm_node) { +- drm_mm_put_block(bo->mem.mm_node); +- bo->mem.mm_node = NULL; +- } +- ++ ttm_bo_mem_put(bo, &bo->mem); + atomic_set(&bo->reserved, 0); + wake_up_all(&bo->event_queue); + spin_unlock(&glob->lru_lock); +@@ -680,7 +673,6 @@ + bool no_wait_reserve, bool no_wait_gpu) + { + struct ttm_bo_device *bdev = bo->bdev; +- struct ttm_bo_global *glob = bo->glob; + struct ttm_mem_reg evict_mem; + struct ttm_placement placement; + int ret = 0; +@@ -726,12 +718,7 @@ + if (ret) { + if (ret != -ERESTARTSYS) + printk(KERN_ERR TTM_PFX "Buffer eviction failed\n"); +- spin_lock(&glob->lru_lock); +- if (evict_mem.mm_node) { +- drm_mm_put_block(evict_mem.mm_node); +- evict_mem.mm_node = NULL; +- } +- spin_unlock(&glob->lru_lock); ++ ttm_bo_mem_put(bo, &evict_mem); + goto out; + } + bo->evicted = true; +@@ -792,41 +779,14 @@ + return ret; + } + +-static int ttm_bo_man_get_node(struct ttm_buffer_object *bo, +- struct ttm_mem_type_manager *man, +- struct ttm_placement *placement, +- struct ttm_mem_reg *mem, +- struct drm_mm_node **node) ++void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem) + { +- struct ttm_bo_global *glob = bo->glob; +- unsigned long lpfn; +- int ret; ++ struct ttm_mem_type_manager *man = &bo->bdev->man[mem->mem_type]; + +- lpfn = placement->lpfn; +- if (!lpfn) +- lpfn = man->size; +- *node = NULL; +- do { +- ret = drm_mm_pre_get(&man->manager); +- if (unlikely(ret)) +- return ret; +- +- spin_lock(&glob->lru_lock); +- *node = drm_mm_search_free_in_range(&man->manager, +- mem->num_pages, mem->page_alignment, +- placement->fpfn, lpfn, 1); +- if (unlikely(*node == NULL)) { +- spin_unlock(&glob->lru_lock); +- return 0; +- } +- *node = drm_mm_get_block_atomic_range(*node, mem->num_pages, +- mem->page_alignment, +- placement->fpfn, +- lpfn); +- spin_unlock(&glob->lru_lock); +- } while (*node == NULL); +- return 0; ++ if (mem->mm_node) ++ (*man->func->put_node)(man, mem); + } ++EXPORT_SYMBOL(ttm_bo_mem_put); + + /** + * Repeatedly evict memory from the LRU for @mem_type until we create enough +@@ -843,14 +803,13 @@ + struct ttm_bo_device *bdev = bo->bdev; + struct ttm_bo_global *glob = bdev->glob; + struct ttm_mem_type_manager *man = &bdev->man[mem_type]; +- struct drm_mm_node *node; + int ret; + + do { +- ret = ttm_bo_man_get_node(bo, man, placement, mem, &node); ++ ret = (*man->func->get_node)(man, bo, placement, mem); + if (unlikely(ret != 0)) + return ret; +- if (node) ++ if (mem->mm_node) + break; + spin_lock(&glob->lru_lock); + if (list_empty(&man->lru)) { +@@ -863,9 +822,8 @@ + if (unlikely(ret != 0)) + return ret; + } while (1); +- if (node == NULL) ++ if (mem->mm_node == NULL) + return -ENOMEM; +- mem->mm_node = node; + mem->mem_type = mem_type; + return 0; + } +@@ -939,7 +897,6 @@ + bool type_found = false; + bool type_ok = false; + bool has_erestartsys = false; +- struct drm_mm_node *node = NULL; + int i, ret; + + mem->mm_node = NULL; +@@ -973,17 +930,15 @@ + + if (man->has_type && man->use_type) { + type_found = true; +- ret = ttm_bo_man_get_node(bo, man, placement, mem, +- &node); ++ ret = (*man->func->get_node)(man, bo, placement, mem); + if (unlikely(ret)) + return ret; + } +- if (node) ++ if (mem->mm_node) + break; + } + +- if ((type_ok && (mem_type == TTM_PL_SYSTEM)) || node) { +- mem->mm_node = node; ++ if ((type_ok && (mem_type == TTM_PL_SYSTEM)) || mem->mm_node) { + mem->mem_type = mem_type; + mem->placement = cur_flags; + return 0; +@@ -1053,7 +1008,6 @@ + bool interruptible, bool no_wait_reserve, + bool no_wait_gpu) + { +- struct ttm_bo_global *glob = bo->glob; + int ret = 0; + struct ttm_mem_reg mem; + +@@ -1081,11 +1035,8 @@ + goto out_unlock; + ret = ttm_bo_handle_move_mem(bo, &mem, false, interruptible, no_wait_reserve, no_wait_gpu); + out_unlock: +- if (ret && mem.mm_node) { +- spin_lock(&glob->lru_lock); +- drm_mm_put_block(mem.mm_node); +- spin_unlock(&glob->lru_lock); +- } ++ if (ret && mem.mm_node) ++ ttm_bo_mem_put(bo, &mem); + return ret; + } + +@@ -1093,11 +1044,10 @@ + struct ttm_mem_reg *mem) + { + int i; +- struct drm_mm_node *node = mem->mm_node; + +- if (node && placement->lpfn != 0 && +- (node->start < placement->fpfn || +- node->start + node->size > placement->lpfn)) ++ if (mem->mm_node && placement->lpfn != 0 && ++ (mem->start < placement->fpfn || ++ mem->start + mem->num_pages > placement->lpfn)) + return -1; + + for (i = 0; i < placement->num_placement; i++) { +@@ -1341,7 +1291,6 @@ + + int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) + { +- struct ttm_bo_global *glob = bdev->glob; + struct ttm_mem_type_manager *man; + int ret = -EINVAL; + +@@ -1364,13 +1313,7 @@ + if (mem_type > 0) { + ttm_bo_force_list_clean(bdev, mem_type, false); + +- spin_lock(&glob->lru_lock); +- if (drm_mm_clean(&man->manager)) +- drm_mm_takedown(&man->manager); +- else +- ret = -EBUSY; +- +- spin_unlock(&glob->lru_lock); ++ ret = (*man->func->takedown)(man); + } + + return ret; +@@ -1421,6 +1364,7 @@ + ret = bdev->driver->init_mem_type(bdev, type, man); + if (ret) + return ret; ++ man->bdev = bdev; + + ret = 0; + if (type != TTM_PL_SYSTEM) { +@@ -1430,7 +1374,8 @@ + type); + return ret; + } +- ret = drm_mm_init(&man->manager, 0, p_size); ++ ++ ret = (*man->func->init)(man, p_size); + if (ret) + return ret; + } +diff -Naur linux-2.6.36/drivers/gpu/drm/ttm/ttm_bo_manager.c linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_bo_manager.c +--- linux-2.6.36/drivers/gpu/drm/ttm/ttm_bo_manager.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_bo_manager.c 2010-10-22 23:59:52.632455388 +0200 +@@ -0,0 +1,148 @@ ++/************************************************************************** ++ * ++ * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA ++ * All Rights Reserved. ++ * ++ * 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, sub license, 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 (including the ++ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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: Thomas Hellstrom ++ */ ++ ++#include "ttm/ttm_module.h" ++#include "ttm/ttm_bo_driver.h" ++#include "ttm/ttm_placement.h" ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man, ++ struct ttm_buffer_object *bo, ++ struct ttm_placement *placement, ++ struct ttm_mem_reg *mem) ++{ ++ struct ttm_bo_global *glob = man->bdev->glob; ++ struct drm_mm *mm = man->priv; ++ struct drm_mm_node *node = NULL; ++ unsigned long lpfn; ++ int ret; ++ ++ lpfn = placement->lpfn; ++ if (!lpfn) ++ lpfn = man->size; ++ do { ++ ret = drm_mm_pre_get(mm); ++ if (unlikely(ret)) ++ return ret; ++ ++ spin_lock(&glob->lru_lock); ++ node = drm_mm_search_free_in_range(mm, ++ mem->num_pages, mem->page_alignment, ++ placement->fpfn, lpfn, 1); ++ if (unlikely(node == NULL)) { ++ spin_unlock(&glob->lru_lock); ++ return 0; ++ } ++ node = drm_mm_get_block_atomic_range(node, mem->num_pages, ++ mem->page_alignment, ++ placement->fpfn, ++ lpfn); ++ spin_unlock(&glob->lru_lock); ++ } while (node == NULL); ++ ++ mem->mm_node = node; ++ mem->start = node->start; ++ return 0; ++} ++ ++static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man, ++ struct ttm_mem_reg *mem) ++{ ++ struct ttm_bo_global *glob = man->bdev->glob; ++ ++ if (mem->mm_node) { ++ spin_lock(&glob->lru_lock); ++ drm_mm_put_block(mem->mm_node); ++ spin_unlock(&glob->lru_lock); ++ mem->mm_node = NULL; ++ } ++} ++ ++static int ttm_bo_man_init(struct ttm_mem_type_manager *man, ++ unsigned long p_size) ++{ ++ struct drm_mm *mm; ++ int ret; ++ ++ mm = kzalloc(sizeof(*mm), GFP_KERNEL); ++ if (!mm) ++ return -ENOMEM; ++ ++ ret = drm_mm_init(mm, 0, p_size); ++ if (ret) { ++ kfree(mm); ++ return ret; ++ } ++ ++ man->priv = mm; ++ return 0; ++} ++ ++static int ttm_bo_man_takedown(struct ttm_mem_type_manager *man) ++{ ++ struct ttm_bo_global *glob = man->bdev->glob; ++ struct drm_mm *mm = man->priv; ++ int ret = 0; ++ ++ spin_lock(&glob->lru_lock); ++ if (drm_mm_clean(mm)) { ++ drm_mm_takedown(mm); ++ kfree(mm); ++ man->priv = NULL; ++ } else ++ ret = -EBUSY; ++ spin_unlock(&glob->lru_lock); ++ return ret; ++} ++ ++static void ttm_bo_man_debug(struct ttm_mem_type_manager *man, ++ const char *prefix) ++{ ++ struct ttm_bo_global *glob = man->bdev->glob; ++ struct drm_mm *mm = man->priv; ++ ++ spin_lock(&glob->lru_lock); ++ drm_mm_debug_table(mm, prefix); ++ spin_unlock(&glob->lru_lock); ++} ++ ++const struct ttm_mem_type_manager_func ttm_bo_manager_func = { ++ ttm_bo_man_init, ++ ttm_bo_man_takedown, ++ ttm_bo_man_get_node, ++ ttm_bo_man_put_node, ++ ttm_bo_man_debug ++}; ++EXPORT_SYMBOL(ttm_bo_manager_func); +diff -Naur linux-2.6.36/drivers/gpu/drm/ttm/ttm_bo_util.c linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_bo_util.c +--- linux-2.6.36/drivers/gpu/drm/ttm/ttm_bo_util.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/ttm/ttm_bo_util.c 2010-10-22 23:59:52.632455388 +0200 +@@ -39,14 +39,7 @@ + + void ttm_bo_free_old_node(struct ttm_buffer_object *bo) + { +- struct ttm_mem_reg *old_mem = &bo->mem; +- +- if (old_mem->mm_node) { +- spin_lock(&bo->glob->lru_lock); +- drm_mm_put_block(old_mem->mm_node); +- spin_unlock(&bo->glob->lru_lock); +- } +- old_mem->mm_node = NULL; ++ ttm_bo_mem_put(bo, &bo->mem); + } + + int ttm_bo_move_ttm(struct ttm_buffer_object *bo, +@@ -263,8 +256,7 @@ + dir = 1; + + if ((old_mem->mem_type == new_mem->mem_type) && +- (new_mem->mm_node->start < +- old_mem->mm_node->start + old_mem->mm_node->size)) { ++ (new_mem->start < old_mem->start + old_mem->size)) { + dir = -1; + add = new_mem->num_pages - 1; + } +diff -Naur linux-2.6.36/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c linux-2.6.36.nouveau/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +--- linux-2.6.36/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c 2010-10-22 23:59:52.633455401 +0200 +@@ -147,6 +147,7 @@ + break; + case TTM_PL_VRAM: + /* "On-card" video ram */ ++ man->func = &ttm_bo_manager_func; + man->gpu_offset = 0; + man->flags = TTM_MEMTYPE_FLAG_FIXED | TTM_MEMTYPE_FLAG_MAPPABLE; + man->available_caching = TTM_PL_MASK_CACHING; +@@ -203,7 +204,7 @@ + /* System memory */ + return 0; + case TTM_PL_VRAM: +- mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; ++ mem->bus.offset = mem->start << PAGE_SHIFT; + mem->bus.base = dev_priv->vram_start; + mem->bus.is_iomem = true; + break; +diff -Naur linux-2.6.36/include/drm/nouveau_drm.h linux-2.6.36.nouveau/include/drm/nouveau_drm.h +--- linux-2.6.36/include/drm/nouveau_drm.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/include/drm/nouveau_drm.h 2010-10-22 23:59:52.634455414 +0200 +@@ -80,6 +80,8 @@ #define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 #define NOUVEAU_GETPARAM_GRAPH_UNITS 13 #define NOUVEAU_GETPARAM_PTIMER_TIME 14 +#define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 ++#define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16 struct drm_nouveau_getparam { uint64_t param; uint64_t value; -@@ -95,6 +96,12 @@ +@@ -95,6 +97,12 @@ #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) #define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3) @@ -16096,7 +20590,7 @@ diff -Naur linux-2.6.36-rc7/include/drm/nouveau_drm.h linux-2.6.36-rc7.patch/inc struct drm_nouveau_gem_info { uint32_t handle; uint32_t domain; -@@ -164,7 +171,6 @@ +@@ -164,7 +172,6 @@ }; #define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001 @@ -16104,3 +20598,73 @@ diff -Naur linux-2.6.36-rc7/include/drm/nouveau_drm.h linux-2.6.36-rc7.patch/inc #define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004 struct drm_nouveau_gem_cpu_prep { uint32_t handle; +diff -Naur linux-2.6.36/include/drm/ttm/ttm_bo_api.h linux-2.6.36.nouveau/include/drm/ttm/ttm_bo_api.h +--- linux-2.6.36/include/drm/ttm/ttm_bo_api.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/include/drm/ttm/ttm_bo_api.h 2010-10-22 23:59:52.634455414 +0200 +@@ -102,7 +102,8 @@ + */ + + struct ttm_mem_reg { +- struct drm_mm_node *mm_node; ++ void *mm_node; ++ unsigned long start; + unsigned long size; + unsigned long num_pages; + uint32_t page_alignment; +diff -Naur linux-2.6.36/include/drm/ttm/ttm_bo_driver.h linux-2.6.36.nouveau/include/drm/ttm/ttm_bo_driver.h +--- linux-2.6.36/include/drm/ttm/ttm_bo_driver.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36.nouveau/include/drm/ttm/ttm_bo_driver.h 2010-10-22 23:59:52.636455439 +0200 +@@ -203,7 +203,22 @@ + * It's set up by the ttm_bo_driver::init_mem_type method. + */ + ++struct ttm_mem_type_manager; ++ ++struct ttm_mem_type_manager_func { ++ int (*init)(struct ttm_mem_type_manager *man, unsigned long p_size); ++ int (*takedown)(struct ttm_mem_type_manager *man); ++ int (*get_node)(struct ttm_mem_type_manager *man, ++ struct ttm_buffer_object *bo, ++ struct ttm_placement *placement, ++ struct ttm_mem_reg *mem); ++ void (*put_node)(struct ttm_mem_type_manager *man, ++ struct ttm_mem_reg *mem); ++ void (*debug)(struct ttm_mem_type_manager *man, const char *prefix); ++}; ++ + struct ttm_mem_type_manager { ++ struct ttm_bo_device *bdev; + + /* + * No protection. Constant from start. +@@ -222,8 +237,8 @@ + * TODO: Consider one lru_lock per ttm_mem_type_manager. + * Plays ill with list removal, though. + */ +- +- struct drm_mm manager; ++ const struct ttm_mem_type_manager_func *func; ++ void *priv; + struct list_head lru; + }; + +@@ -649,6 +664,10 @@ + struct ttm_mem_reg *mem, + bool interruptible, + bool no_wait_reserve, bool no_wait_gpu); ++ ++extern void ttm_bo_mem_put(struct ttm_buffer_object *bo, ++ struct ttm_mem_reg *mem); ++ + /** + * ttm_bo_wait_for_cpu + * +@@ -891,6 +910,8 @@ + */ + extern pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp); + ++extern const struct ttm_mem_type_manager_func ttm_bo_manager_func; ++ + #if (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE))) + #define TTM_HAS_AGP + #include