From a09169400f81b7d2a39f2025b8ee37bab77ed1de Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 26 Jun 2011 07:51:36 +0200 Subject: [PATCH 1/9] sqlite: update to sqlite-autoconf-3070700 Signed-off-by: Stephan Raue --- packages/databases/sqlite/meta | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/databases/sqlite/meta b/packages/databases/sqlite/meta index aba6fe9ad6..acc4e9b787 100644 --- a/packages/databases/sqlite/meta +++ b/packages/databases/sqlite/meta @@ -19,12 +19,12 @@ ################################################################################ PKG_NAME="sqlite" -PKG_VERSION="autoconf-3070603" +PKG_VERSION="autoconf-3070700" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="PublicDomain" PKG_SITE="http://www.sqlite.org/" -PKG_URL="http://www.hwaci.com/sw/sqlite/$PKG_NAME-$PKG_VERSION.tar.gz" +PKG_URL="http://sqlite.org/$PKG_NAME-$PKG_VERSION.tar.gz" PKG_DEPENDS="" PKG_BUILD_DEPENDS="toolchain" PKG_PRIORITY="optional" From 9073f6a1bddc7adbc5c730d462ac7e9c7a35e9b8 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 26 Jun 2011 07:52:28 +0200 Subject: [PATCH 2/9] freetype: update to freetype-2.4.5 Signed-off-by: Stephan Raue --- packages/print/freetype/meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/print/freetype/meta b/packages/print/freetype/meta index ba4e0d819f..b799da8547 100644 --- a/packages/print/freetype/meta +++ b/packages/print/freetype/meta @@ -19,7 +19,7 @@ ################################################################################ PKG_NAME="freetype" -PKG_VERSION="2.4.4" +PKG_VERSION="2.4.5" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" From 586b7ccc320adfba40a976b163370127168b6141 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 26 Jun 2011 09:08:16 +0200 Subject: [PATCH 3/9] xf86-video-nouveau: update to xf86-video-nouveau-ab89aa0 Signed-off-by: Stephan Raue --- packages/x11/driver/xf86-video-nouveau/meta | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/x11/driver/xf86-video-nouveau/meta b/packages/x11/driver/xf86-video-nouveau/meta index 1ee474aa30..eedab0625f 100644 --- a/packages/x11/driver/xf86-video-nouveau/meta +++ b/packages/x11/driver/xf86-video-nouveau/meta @@ -19,12 +19,12 @@ ################################################################################ PKG_NAME="xf86-video-nouveau" -PKG_VERSION="8378443" +PKG_VERSION="ab89aa0" PKG_REV="1" PKG_ARCH="i386 x86_64" PKG_LICENSE="OSS" PKG_SITE="http://www.x.org/" -PKG_URL="$OPENELEC_SRC/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_URL="$OPENELEC_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" PKG_DEPENDS="libXrandr libXrender libdrm libXext libpciaccess udev Mesa" PKG_BUILD_DEPENDS="toolchain util-macros libXrandr libXrender libdrm libXext libpciaccess udev Mesa xorg-server" PKG_PRIORITY="optional" From 3bdf8a25567328be1e3067c584d8a49f6a2f649d Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 26 Jun 2011 14:22:01 +0200 Subject: [PATCH 4/9] libdrm: depends on libpciaccess Signed-off-by: Stephan Raue --- packages/graphics/libdrm/meta | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/graphics/libdrm/meta b/packages/graphics/libdrm/meta index 0d6f1acc8b..33f5a84839 100644 --- a/packages/graphics/libdrm/meta +++ b/packages/graphics/libdrm/meta @@ -25,8 +25,8 @@ PKG_ARCH="any" PKG_LICENSE="GPL" PKG_SITE="http://dri.freedesktop.org" PKG_URL="http://dri.freedesktop.org/libdrm/$PKG_NAME-$PKG_VERSION.tar.bz2" -PKG_DEPENDS="udev" -PKG_BUILD_DEPENDS="toolchain libpthread-stubs udev" +PKG_DEPENDS="udev libpciaccess" +PKG_BUILD_DEPENDS="toolchain libpthread-stubs udev libpciaccess" PKG_PRIORITY="optional" PKG_SECTION="graphics" PKG_SHORTDESC="libdrm: Userspace interface to kernel DRM services" From e061f018ae921d6f1daeca422319dbea380963f4 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 26 Jun 2011 19:15:34 +0200 Subject: [PATCH 5/9] Mesa: update to Mesa-7.11-ac8f59b Signed-off-by: Stephan Raue --- config/options | 56 +++-- packages/graphics/Mesa/build | 54 ++--- packages/graphics/Mesa/meta | 10 +- .../Mesa/patches/Mesa-7.10.3-__atom.patch | 15 -- .../patches/Mesa-7.10.3-libdrm_nouveau.patch | 208 ------------------ .../Mesa/patches/Mesa-7.10.3-llvm_so.patch | 12 - .../patches/Mesa-7.10.3-llvmpipe_ld.patch | 12 - 7 files changed, 55 insertions(+), 312 deletions(-) delete mode 100644 packages/graphics/Mesa/patches/Mesa-7.10.3-__atom.patch delete mode 100644 packages/graphics/Mesa/patches/Mesa-7.10.3-libdrm_nouveau.patch delete mode 100644 packages/graphics/Mesa/patches/Mesa-7.10.3-llvm_so.patch delete mode 100644 packages/graphics/Mesa/patches/Mesa-7.10.3-llvmpipe_ld.patch diff --git a/config/options b/config/options index 90cd75b3fb..66106baf70 100644 --- a/config/options +++ b/config/options @@ -77,54 +77,74 @@ fi get_graphicdrivers() { if [ "$GRAPHIC_DRIVERS" = "all" ]; then - GRAPHIC_DRIVERS="i915 i965 r200 r300 r600 radeon nvidia vmware" + GRAPHIC_DRIVERS="i915 i965 r300 r600 nvidia vmware" fi for drv in $GRAPHIC_DRIVERS; do - [ "$drv" = "i915" ] && MESA_DRIVERS="$MESA_DRIVERS,i915" - [ "$drv" = "i965" ] && MESA_DRIVERS="$MESA_DRIVERS,i965" - [ "$drv" = "r200" ] && MESA_DRIVERS="$MESA_DRIVERS,r200" -# [ "$drv" = "r300" ] && MESA_DRIVERS="$MESA_DRIVERS,r300" -# [ "$drv" = "r600" ] && MESA_DRIVERS="$MESA_DRIVERS,r600" - [ "$drv" = "radeon" ] && MESA_DRIVERS="$MESA_DRIVERS,radeon" -# [ "$drv" = "nouveau" ] && MESA_DRIVERS="$MESA_DRIVERS,nouveau" - [ "$drv" = "omapfb" ] && MESA_DRIVERS="$MESA_DRIVERS,swrast" + if [ "$drv" = "fglrx" ]; then + DRI_DRIVERS="$DRI_DRIVERS" + GALLIUM_DRIVERS="$GALLIUM_DRIVERS" + XORG_DRIVERS="$XORG_DRIVERS fglrx" + COMPOSITE_SUPPORT="yes" + XINERAMA_SUPPORT="yes" +# LLVM_SUPPORT="yes" + fi - if [ "$drv" = "i915" -o "$drv" = "i965" ]; then + if [ "$drv" = "i915" ]; then + DRI_DRIVERS="$DRI_DRIVERS,i915" +# GALLIUM_DRIVERS="$GALLIUM_DRIVERS,i915" XORG_DRIVERS="$XORG_DRIVERS intel" # LLVM_SUPPORT="yes" fi - if [ "$drv" = "r200" -o "$drv" = "r300" -o "$drv" = "r600" -o "$drv" = "radeon" ]; then - XORG_DRIVERS="$XORG_DRIVERS ati" + if [ "$drv" = "i965" ]; then + DRI_DRIVERS="$DRI_DRIVERS,i965" +# GALLIUM_DRIVERS="$GALLIUM_DRIVERS,i965" + XORG_DRIVERS="$XORG_DRIVERS intel" # LLVM_SUPPORT="yes" fi if [ "$drv" = "nouveau" ]; then +# DRI_DRIVERS="$DRI_DRIVERS,nouveau" + GALLIUM_DRIVERS="$GALLIUM_DRIVERS,nouveau" XORG_DRIVERS="$XORG_DRIVERS nouveau" # LLVM_SUPPORT="yes" fi if [ "$drv" = "nvidia" ]; then + DRI_DRIVERS="$DRI_DRIVERS" + GALLIUM_DRIVERS="$GALLIUM_DRIVERS" XORG_DRIVERS="$XORG_DRIVERS nvidia" XINERAMA_SUPPORT="yes" - fi - - if [ "$drv" = "fglrx" ]; then - XORG_DRIVERS="$XORG_DRIVERS fglrx" - COMPOSITE_SUPPORT="yes" - XINERAMA_SUPPORT="yes" +# LLVM_SUPPORT="yes" fi if [ "$drv" = "omapfb" ]; then + DRI_DRIVERS="$DRI_DRIVERS,swrast" +# GALLIUM_DRIVERS="$GALLIUM_DRIVERS,swrast" XORG_DRIVERS="$XORG_DRIVERS ompafb" # LLVM_SUPPORT="yes" fi + if [ "$drv" = "r300" ]; then +# DRI_DRIVERS="$DRI_DRIVERS,r300" + GALLIUM_DRIVERS="$GALLIUM_DRIVERS,r300" + XORG_DRIVERS="$XORG_DRIVERS ati" +# LLVM_SUPPORT="yes" + fi + + if [ "$drv" = "r600" ]; then +# DRI_DRIVERS="$DRI_DRIVERS,r600" + GALLIUM_DRIVERS="$GALLIUM_DRIVERS,r600" + XORG_DRIVERS="$XORG_DRIVERS ati" +# LLVM_SUPPORT="yes" + fi + if [ "$drv" = "vmware" ]; then XINERAMA_SUPPORT="yes" # LLVM_SUPPORT="yes" fi + done } diff --git a/packages/graphics/Mesa/build b/packages/graphics/Mesa/build index 1fa5ad7532..45211cd7d6 100755 --- a/packages/graphics/Mesa/build +++ b/packages/graphics/Mesa/build @@ -32,48 +32,10 @@ get_graphicdrivers # TODO: LDFLAGS="" -MESA_CONFIG=" --disable-gallium --disable-gallium-nouveau --disable-gallium-i915 --disable-gallium-i965" -MESA_CONFIG="$MESA_CONFIG --disable-gallium-radeon --disable-gallium-r300 --disable-gallium-r600" -MESA_CONFIG="$MESA_CONFIG --disable-gallium-svga --disable-gallium-swrast" - if [ "$LLVM_SUPPORT" = "yes" ]; then export LLVM_CONFIG="$SYSROOT_PREFIX/usr/bin/llvm-config" - MESA_CONFIG="$MESA_CONFIG --enable-gallium --enable-gallium-llvm" fi -for drv in $GRAPHIC_DRIVERS; do - if [ "$drv" = i915 ]; then - MESA_CONFIG=`echo $MESA_CONFIG | sed -e 's/disable-gallium-i915/disable-gallium-i915/'` - # MESA_CONFIG="$MESA_CONFIG --with-state-trackers=dri,glx --enable-gallium" - fi - - if [ "$drv" = i965 ]; then - MESA_CONFIG=`echo $MESA_CONFIG | sed -e 's/disable-gallium-i965/disable-gallium-i965/'` - # MESA_CONFIG="$MESA_CONFIG --with-state-trackers=dri,glx --enable-gallium" - fi - - if [ "$drv" = r300 -o "$drv" = radeon ]; then - MESA_CONFIG=`echo $MESA_CONFIG | sed -e 's/disable-gallium-radeon/enable-gallium-radeon/'` - MESA_CONFIG=`echo $MESA_CONFIG | sed -e 's/disable-gallium-r300/enable-gallium-r300/'` - MESA_CONFIG="$MESA_CONFIG --with-state-trackers=dri,glx --enable-gallium" - fi - - if [ "$drv" = r600 ]; then - MESA_CONFIG=`echo $MESA_CONFIG | sed -e 's/disable-gallium-r600/enable-gallium-r600/'` - MESA_CONFIG="$MESA_CONFIG --with-state-trackers=dri,glx --enable-gallium" - fi - - if [ "$drv" = nouveau ]; then - MESA_CONFIG=`echo $MESA_CONFIG | sed -e 's/disable-gallium-nouveau/enable-gallium-nouveau/'` - MESA_CONFIG="$MESA_CONFIG --with-state-trackers=dri,glx --enable-gallium" - fi - - if [ "$drv" = vmware ]; then - MESA_CONFIG=`echo $MESA_CONFIG | sed -e 's/disable-gallium-svga/enable-gallium-svga/'` - MESA_CONFIG="$MESA_CONFIG --with-state-trackers=dri,glx --enable-gallium" - fi -done - cd $PKG_BUILD HOST_CC="$HOST_CC" \ @@ -99,11 +61,23 @@ DRI_DRIVER_SEARCH_DIR="$XORG_PATH_DRI" \ --disable-glut \ --disable-glw \ --disable-motif \ - $MESA_CONFIG \ + --with-gallium-drivers="$GALLIUM_DRIVERS" \ --with-driver="dri" \ - --with-dri-drivers="$MESA_DRIVERS" \ + --with-dri-drivers="$DRI_DRIVERS" \ --with-xorg-driver-dir="$XORG_PATH_DRIVERS" \ +make CC="$HOST_CC" \ + CXX="$HOST_CXX" \ + CFLAGS="$HOST_CFLAGS" \ + CXXFLAGS="$HOST_CXXFLAGS" \ + LDFLAGS="$HOST_LDFLAGS" \ + -C src/glsl builtin_compiler + +cp src/glsl/builtin_compiler $ROOT/$TOOLCHAIN/bin +make -C src/glsl clean + +sed -e "s#\.\/builtin_compiler#$ROOT/$TOOLCHAIN/bin/builtin_compiler#g" -i src/glsl/Makefile + make $MAKEINSTALL -C src/mesa diff --git a/packages/graphics/Mesa/meta b/packages/graphics/Mesa/meta index d4fb4d2537..4c46818de7 100644 --- a/packages/graphics/Mesa/meta +++ b/packages/graphics/Mesa/meta @@ -19,12 +19,13 @@ ################################################################################ PKG_NAME="Mesa" -PKG_VERSION="7.10.3" +PKG_VERSION="7.11-ac8f59b" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="OSS" PKG_SITE="http://www.mesa3d.org/" -PKG_URL="ftp://ftp.freedesktop.org/pub/mesa/$PKG_VERSION/MesaLib-$PKG_VERSION.tar.bz2" +#PKG_URL="ftp://ftp.freedesktop.org/pub/mesa/$PKG_VERSION/MesaLib-$PKG_VERSION.tar.bz2" +PKG_URL="$OPENELEC_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" PKG_DEPENDS="libXdamage libdrm expat libXext libXfixes libXxf86vm libxcb libX11" PKG_BUILD_DEPENDS="toolchain Python makedepend libxml2-host expat glproto dri2proto libdrm libXext libXdamage libXfixes libXxf86vm libxcb libX11" PKG_PRIORITY="optional" @@ -41,8 +42,3 @@ if [ "$LLVM_SUPPORT" = "yes" ]; then PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS llvm" PKG_DEPENDS="$PKG_DEPENDS llvm" fi - -if [ "$MESA_MASTER" = "yes" ]; then - PKG_VERSION="7.11-git2812b60" - PKG_URL="$OPENELEC_SRC/$PKG_NAME-$PKG_VERSION.tar.bz2" -fi diff --git a/packages/graphics/Mesa/patches/Mesa-7.10.3-__atom.patch b/packages/graphics/Mesa/patches/Mesa-7.10.3-__atom.patch deleted file mode 100644 index 1787a37369..0000000000 --- a/packages/graphics/Mesa/patches/Mesa-7.10.3-__atom.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/r200/r200_cmdbuf.c Mesa-7.10.1-new/src/mesa/drivers/dri/r200/r200_cmdbuf.c ---- Mesa-7.10.1-old/src/mesa/drivers/dri/r200/r200_cmdbuf.c 2011-03-02 17:30:39.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/r200/r200_cmdbuf.c 2011-03-02 17:31:59.000000000 -0800 -@@ -47,9 +47,8 @@ - */ - #define insert_at_tail_if(atom_list, atom) \ - do { \ -- struct radeon_state_atom* __atom = (atom); \ -- if (__atom->check) \ -- insert_at_tail((atom_list), __atom); \ -+ if ((atom)->check) \ -+ insert_at_tail((atom_list), (atom)); \ - } while(0) - - void r200SetUpAtomList( r200ContextPtr rmesa ) diff --git a/packages/graphics/Mesa/patches/Mesa-7.10.3-libdrm_nouveau.patch b/packages/graphics/Mesa/patches/Mesa-7.10.3-libdrm_nouveau.patch deleted file mode 100644 index 445e9170b3..0000000000 --- a/packages/graphics/Mesa/patches/Mesa-7.10.3-libdrm_nouveau.patch +++ /dev/null @@ -1,208 +0,0 @@ -diff -Naur Mesa-7.10.1-old/src/gallium/drivers/nv50/nv50_context.h Mesa-7.10.1-new/src/gallium/drivers/nv50/nv50_context.h ---- Mesa-7.10.1-old/src/gallium/drivers/nv50/nv50_context.h 2010-12-15 15:02:44.000000000 -0800 -+++ Mesa-7.10.1-new/src/gallium/drivers/nv50/nv50_context.h 2011-03-02 17:31:09.000000000 -0800 -@@ -15,6 +15,8 @@ - - #include "nouveau/nouveau_winsys.h" - #include "nouveau/nouveau_gldefs.h" -+/* Hack to silence warnings caused by nouveau/nouveau_stateobj.h using BEGIN_BIND marcro */ -+#include - #include "nouveau/nouveau_stateobj.h" - #include "nv50_reg.h" - -diff -Naur Mesa-7.10.1-old/src/gallium/drivers/nvfx/nv04_2d.c Mesa-7.10.1-new/src/gallium/drivers/nvfx/nv04_2d.c ---- Mesa-7.10.1-old/src/gallium/drivers/nvfx/nv04_2d.c 2011-01-25 15:52:45.000000000 -0800 -+++ Mesa-7.10.1-new/src/gallium/drivers/nvfx/nv04_2d.c 2011-03-02 17:31:09.000000000 -0800 -@@ -39,6 +39,7 @@ - #include - #include - #include -+#include - #include "nv04_2d.h" - - #include "nouveau/nv_object.xml.h" -diff -Naur Mesa-7.10.1-old/src/gallium/drivers/nvfx/nvfx_buffer.c Mesa-7.10.1-new/src/gallium/drivers/nvfx/nvfx_buffer.c ---- Mesa-7.10.1-old/src/gallium/drivers/nvfx/nvfx_buffer.c 2010-12-15 15:02:44.000000000 -0800 -+++ Mesa-7.10.1-new/src/gallium/drivers/nvfx/nvfx_buffer.c 2011-03-02 17:31:09.000000000 -0800 -@@ -1,4 +1,3 @@ -- - #include "util/u_inlines.h" - #include "util/u_memory.h" - #include "util/u_math.h" -diff -Naur Mesa-7.10.1-old/src/gallium/drivers/nvfx/nvfx_screen.c Mesa-7.10.1-new/src/gallium/drivers/nvfx/nvfx_screen.c ---- Mesa-7.10.1-old/src/gallium/drivers/nvfx/nvfx_screen.c 2011-01-25 15:52:45.000000000 -0800 -+++ Mesa-7.10.1-new/src/gallium/drivers/nvfx/nvfx_screen.c 2011-03-02 17:31:09.000000000 -0800 -@@ -10,6 +10,8 @@ - #include "nvfx_resource.h" - #include "nvfx_tex.h" - -+#include "nouveau/nv04_pushbuf.h" -+ - #define NV30_3D_CHIPSET_3X_MASK 0x00000003 - #define NV34_3D_CHIPSET_3X_MASK 0x00000010 - #define NV35_3D_CHIPSET_3X_MASK 0x000001e0 -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv04_driver.h Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv04_driver.h ---- Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv04_driver.h 2010-12-14 13:43:15.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv04_driver.h 2011-03-02 17:31:09.000000000 -0800 -@@ -28,6 +28,7 @@ - #define __NV04_DRIVER_H__ - - #include "nv04_context.h" -+#include "nv04_pushbuf.h" - - enum { - NOUVEAU_STATE_BLEND = NUM_NOUVEAU_STATE, -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv10_render.c Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv10_render.c ---- Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv10_render.c 2010-12-14 13:43:15.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv10_render.c 2011-03-02 17:31:09.000000000 -0800 -@@ -27,6 +27,7 @@ - #include "nouveau_driver.h" - #include "nouveau_context.h" - #include "nv10_3d.xml.h" -+#include "nv04_driver.h" - #include "nv10_driver.h" - - #define NUM_VERTEX_ATTRS 8 -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv10_state_fb.c Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv10_state_fb.c ---- Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv10_state_fb.c 2010-12-14 13:43:15.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv10_state_fb.c 2011-03-02 17:31:09.000000000 -0800 -@@ -30,6 +30,7 @@ - #include "nouveau_util.h" - #include "nv_object.xml.h" - #include "nv10_3d.xml.h" -+#include "nv04_driver.h" - #include "nv10_driver.h" - - static inline unsigned -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv10_state_frag.c Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv10_state_frag.c ---- Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv10_state_frag.c 2010-12-14 13:43:15.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv10_state_frag.c 2011-03-02 17:31:09.000000000 -0800 -@@ -30,6 +30,7 @@ - #include "nv10_3d.xml.h" - #include "nouveau_util.h" - #include "nv10_driver.h" -+#include "nv04_driver.h" - #include "nv20_driver.h" - - #define RC_IN_SHIFT_A 24 -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv10_state_polygon.c Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv10_state_polygon.c ---- Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv10_state_polygon.c 2010-12-14 13:43:15.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv10_state_polygon.c 2011-03-02 17:31:09.000000000 -0800 -@@ -29,6 +29,7 @@ - #include "nouveau_gldefs.h" - #include "nouveau_util.h" - #include "nv10_3d.xml.h" -+#include "nv04_driver.h" - #include "nv10_driver.h" - - void -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv10_state_raster.c Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv10_state_raster.c ---- Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv10_state_raster.c 2011-01-25 15:52:45.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv10_state_raster.c 2011-03-02 17:31:09.000000000 -0800 -@@ -29,6 +29,7 @@ - #include "nouveau_gldefs.h" - #include "nouveau_util.h" - #include "nv10_3d.xml.h" -+#include "nv04_driver.h" - #include "nv10_driver.h" - - void -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv10_state_tex.c Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv10_state_tex.c ---- Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv10_state_tex.c 2010-12-14 13:43:15.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv10_state_tex.c 2011-03-02 17:31:09.000000000 -0800 -@@ -30,6 +30,7 @@ - #include "nouveau_texture.h" - #include "nv10_3d.xml.h" - #include "nouveau_util.h" -+#include "nv04_driver.h" - #include "nv10_driver.h" - - void -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c ---- Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c 2010-12-14 13:43:15.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c 2011-03-02 17:31:09.000000000 -0800 -@@ -29,6 +29,7 @@ - #include "nouveau_gldefs.h" - #include "nouveau_util.h" - #include "nv10_3d.xml.h" -+#include "nv04_driver.h" - #include "nv10_driver.h" - - void -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv20_render.c Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv20_render.c ---- Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv20_render.c 2010-12-14 13:43:15.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv20_render.c 2011-03-02 17:31:09.000000000 -0800 -@@ -27,6 +27,7 @@ - #include "nouveau_driver.h" - #include "nouveau_context.h" - #include "nv20_3d.xml.h" -+#include "nv04_driver.h" - #include "nv20_driver.h" - - #define NUM_VERTEX_ATTRS 16 -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv20_state_fb.c Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv20_state_fb.c ---- Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv20_state_fb.c 2010-12-14 13:43:15.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv20_state_fb.c 2011-03-02 17:31:09.000000000 -0800 -@@ -30,6 +30,7 @@ - #include "nouveau_gldefs.h" - #include "nouveau_util.h" - #include "nv20_3d.xml.h" -+#include "nv04_driver.h" - #include "nv20_driver.h" - - static inline unsigned -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv20_state_frag.c Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv20_state_frag.c ---- Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv20_state_frag.c 2010-12-14 13:43:15.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv20_state_frag.c 2011-03-02 17:31:09.000000000 -0800 -@@ -28,6 +28,7 @@ - #include "nouveau_context.h" - #include "nv20_3d.xml.h" - #include "nv10_driver.h" -+#include "nv04_driver.h" - #include "nv20_driver.h" - - void -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv20_state_polygon.c Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv20_state_polygon.c ---- Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv20_state_polygon.c 2010-12-14 13:43:15.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv20_state_polygon.c 2011-03-02 17:31:09.000000000 -0800 -@@ -28,6 +28,7 @@ - #include "nouveau_context.h" - #include "nouveau_gldefs.h" - #include "nv20_3d.xml.h" -+#include "nv04_driver.h" - #include "nv20_driver.h" - - void -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv20_state_raster.c Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv20_state_raster.c ---- Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv20_state_raster.c 2010-12-14 13:43:15.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv20_state_raster.c 2011-03-02 17:31:09.000000000 -0800 -@@ -29,6 +29,7 @@ - #include "nouveau_gldefs.h" - #include "nouveau_util.h" - #include "nv20_3d.xml.h" -+#include "nv04_driver.h" - #include "nv20_driver.h" - - void -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv20_state_tex.c Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv20_state_tex.c ---- Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv20_state_tex.c 2010-12-14 13:43:15.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv20_state_tex.c 2011-03-02 17:31:09.000000000 -0800 -@@ -30,6 +30,7 @@ - #include "nouveau_texture.h" - #include "nv20_3d.xml.h" - #include "nouveau_util.h" -+#include "nv04_driver.h" - #include "nv20_driver.h" - - void -diff -Naur Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c ---- Mesa-7.10.1-old/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c 2010-12-14 13:43:15.000000000 -0800 -+++ Mesa-7.10.1-new/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c 2011-03-02 17:31:09.000000000 -0800 -@@ -29,6 +29,7 @@ - #include "nouveau_gldefs.h" - #include "nouveau_util.h" - #include "nv20_3d.xml.h" -+#include "nv04_driver.h" - #include "nv10_driver.h" - #include "nv20_driver.h" - diff --git a/packages/graphics/Mesa/patches/Mesa-7.10.3-llvm_so.patch b/packages/graphics/Mesa/patches/Mesa-7.10.3-llvm_so.patch deleted file mode 100644 index 8a924662ca..0000000000 --- a/packages/graphics/Mesa/patches/Mesa-7.10.3-llvm_so.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -Naur Mesa-7.10.2-old/configure.ac Mesa-7.10.2-new/configure.ac ---- Mesa-7.10.2-old/configure.ac 2011-02-11 14:49:47.000000000 -0800 -+++ Mesa-7.10.2-new/configure.ac 2011-05-05 16:31:18.000000000 -0700 -@@ -1551,7 +1551,7 @@ - if test "x$LLVM_CONFIG" != xno; then - LLVM_VERSION=`$LLVM_CONFIG --version` - LLVM_CFLAGS=`$LLVM_CONFIG --cppflags` -- LLVM_LIBS="`$LLVM_CONFIG --libs jit interpreter nativecodegen bitwriter` -lstdc++" -+ LLVM_LIBS="-lLLVM-$LLVM_VERSION -lstdc++" - - if test "x$HAS_UDIS86" != xno; then - LLVM_LIBS="$LLVM_LIBS -ludis86" diff --git a/packages/graphics/Mesa/patches/Mesa-7.10.3-llvmpipe_ld.patch b/packages/graphics/Mesa/patches/Mesa-7.10.3-llvmpipe_ld.patch deleted file mode 100644 index 1fa972db2e..0000000000 --- a/packages/graphics/Mesa/patches/Mesa-7.10.3-llvmpipe_ld.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -Naur Mesa-7.10.2-old/src/gallium/drivers/llvmpipe/Makefile Mesa-7.10.2-new/src/gallium/drivers/llvmpipe/Makefile ---- Mesa-7.10.2-old/src/gallium/drivers/llvmpipe/Makefile 2011-01-04 09:44:17.000000000 -0800 -+++ Mesa-7.10.2-new/src/gallium/drivers/llvmpipe/Makefile 2011-05-05 15:48:06.000000000 -0700 -@@ -71,7 +71,7 @@ - - LDFLAGS += $(LLVM_LDFLAGS) - LIBS += -L../../auxiliary/ -lgallium libllvmpipe.a $(LLVM_LIBS) $(GL_LIB_DEPS) --LD=g++ -+LD = $(CXX) - - $(PROGS): lp_test_main.o libllvmpipe.a - From d4169abec3465862afcd2f767f30206acc675f72 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Mon, 27 Jun 2011 08:18:07 +0200 Subject: [PATCH 6/9] linux: update nouveau upstream drm drivers Signed-off-by: Stephan Raue --- ...-110-drm_nouveau_upstream-20110626.1.patch | 8765 +++++++++++++++++ 1 file changed, 8765 insertions(+) create mode 100644 packages/linux/patches/linux-3.0-rc4-110-drm_nouveau_upstream-20110626.1.patch diff --git a/packages/linux/patches/linux-3.0-rc4-110-drm_nouveau_upstream-20110626.1.patch b/packages/linux/patches/linux-3.0-rc4-110-drm_nouveau_upstream-20110626.1.patch new file mode 100644 index 0000000000..10f3895146 --- /dev/null +++ b/packages/linux/patches/linux-3.0-rc4-110-drm_nouveau_upstream-20110626.1.patch @@ -0,0 +1,8765 @@ +diff -Naur linux-3.0-rc4/drivers/gpu/drm/drm_gem.c linux-3.0-rc4.nouveau/drivers/gpu/drm/drm_gem.c +--- linux-3.0-rc4/drivers/gpu/drm/drm_gem.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/drm_gem.c 2011-06-26 07:59:23.000000000 +0200 +@@ -210,6 +210,8 @@ + idr_remove(&filp->object_idr, handle); + spin_unlock(&filp->table_lock); + ++ if (dev->driver->gem_close_object) ++ dev->driver->gem_close_object(obj, filp); + drm_gem_object_handle_unreference_unlocked(obj); + + return 0; +@@ -226,7 +228,8 @@ + struct drm_gem_object *obj, + u32 *handlep) + { +- int ret; ++ struct drm_device *dev = obj->dev; ++ int ret; + + /* + * Get the user-visible handle using idr. +@@ -247,6 +250,15 @@ + return ret; + + drm_gem_object_handle_reference(obj); ++ ++ if (dev->driver->gem_open_object) { ++ ret = dev->driver->gem_open_object(obj, file_priv); ++ if (ret) { ++ drm_gem_handle_delete(file_priv, *handlep); ++ return ret; ++ } ++ } ++ + return 0; + } + EXPORT_SYMBOL(drm_gem_handle_create); +@@ -401,7 +413,12 @@ + static int + drm_gem_object_release_handle(int id, void *ptr, void *data) + { ++ struct drm_file *file_priv = data; + struct drm_gem_object *obj = ptr; ++ struct drm_device *dev = obj->dev; ++ ++ if (dev->driver->gem_close_object) ++ dev->driver->gem_close_object(obj, file_priv); + + drm_gem_object_handle_unreference_unlocked(obj); + +@@ -417,7 +434,7 @@ + drm_gem_release(struct drm_device *dev, struct drm_file *file_private) + { + idr_for_each(&file_private->object_idr, +- &drm_gem_object_release_handle, NULL); ++ &drm_gem_object_release_handle, file_private); + + idr_remove_all(&file_private->object_idr); + idr_destroy(&file_private->object_idr); +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/Makefile linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/Makefile +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/Makefile 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/Makefile 2011-06-26 07:59:23.000000000 +0200 +@@ -21,7 +21,7 @@ + nv40_grctx.o nv50_grctx.o nvc0_grctx.o \ + nv84_crypt.o \ + nva3_copy.o nvc0_copy.o \ +- nv40_mpeg.o nv50_mpeg.o \ ++ nv31_mpeg.o nv50_mpeg.o \ + nv04_instmem.o nv50_instmem.o nvc0_instmem.o \ + nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \ + nv50_cursor.o nv50_display.o \ +@@ -30,7 +30,7 @@ + nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \ + nv10_gpio.o nv50_gpio.o \ + nv50_calc.o \ +- nv04_pm.o nv50_pm.o nva3_pm.o \ ++ nv04_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \ + nv50_vram.o nvc0_vram.o \ + nv50_vm.o nvc0_vm.o + +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_bios.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_bios.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.c 2011-06-26 07:59:23.000000000 +0200 +@@ -135,13 +135,14 @@ + int i; + + if (dev_priv->card_type >= NV_50) { +- uint32_t vbios_vram = (nv_rd32(dev, 0x619f04) & ~0xff) << 8; +- +- if (!vbios_vram) +- vbios_vram = (nv_rd32(dev, 0x1700) << 16) + 0xf0000; ++ u64 addr = (u64)(nv_rd32(dev, 0x619f04) & 0xffffff00) << 8; ++ if (!addr) { ++ addr = (u64)nv_rd32(dev, 0x1700) << 16; ++ addr += 0xf0000; ++ } + + old_bar0_pramin = nv_rd32(dev, 0x1700); +- nv_wr32(dev, 0x1700, vbios_vram >> 16); ++ nv_wr32(dev, 0x1700, addr >> 16); + } + + /* bail if no rom signature */ +@@ -5186,7 +5187,7 @@ + load_table_ptr = ROM16(bios->data[bitentry->offset]); + + if (load_table_ptr == 0x0) { +- NV_ERROR(dev, "Pointer to BIT loadval table invalid\n"); ++ NV_DEBUG(dev, "Pointer to BIT loadval table invalid\n"); + return -EINVAL; + } + +@@ -6377,6 +6378,37 @@ + } + } + ++ /* Some other twisted XFX board (rhbz#694914) ++ * ++ * The DVI/VGA encoder combo that's supposed to represent the ++ * DVI-I connector actually point at two different ones, and ++ * the HDMI connector ends up paired with the VGA instead. ++ * ++ * Connector table is missing anything for VGA at all, pointing it ++ * an invalid conntab entry 2 so we figure it out ourself. ++ */ ++ if (nv_match_device(dev, 0x0615, 0x1682, 0x2605)) { ++ if (idx == 0) { ++ *conn = 0x02002300; /* VGA, connector 2 */ ++ *conf = 0x00000028; ++ } else ++ if (idx == 1) { ++ *conn = 0x01010312; /* DVI, connector 0 */ ++ *conf = 0x00020030; ++ } else ++ if (idx == 2) { ++ *conn = 0x04020310; /* VGA, connector 0 */ ++ *conf = 0x00000028; ++ } else ++ if (idx == 3) { ++ *conn = 0x02021322; /* HDMI, connector 1 */ ++ *conf = 0x00020010; ++ } else { ++ *conn = 0x0000000e; /* EOL */ ++ *conf = 0x00000000; ++ } ++ } ++ + return true; + } + +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_bo.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_bo.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_bo.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_bo.c 2011-06-26 07:59:23.000000000 +0200 +@@ -49,16 +49,12 @@ + DRM_ERROR("bo %p still attached to GEM object\n", bo); + + nv10_mem_put_tile_region(dev, nvbo->tile, NULL); +- if (nvbo->vma.node) { +- nouveau_vm_unmap(&nvbo->vma); +- nouveau_vm_put(&nvbo->vma); +- } + kfree(nvbo); + } + + static void + nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags, +- int *align, int *size, int *page_shift) ++ int *align, int *size) + { + struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); + +@@ -82,67 +78,51 @@ + } + } + } else { +- if (likely(dev_priv->chan_vm)) { +- if (!(flags & TTM_PL_FLAG_TT) && *size > 256 * 1024) +- *page_shift = dev_priv->chan_vm->lpg_shift; +- else +- *page_shift = dev_priv->chan_vm->spg_shift; +- } else { +- *page_shift = 12; +- } +- +- *size = roundup(*size, (1 << *page_shift)); +- *align = max((1 << *page_shift), *align); ++ *size = roundup(*size, (1 << nvbo->page_shift)); ++ *align = max((1 << nvbo->page_shift), *align); + } + + *size = roundup(*size, PAGE_SIZE); + } + + int +-nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, +- int size, int align, uint32_t flags, uint32_t tile_mode, +- uint32_t tile_flags, struct nouveau_bo **pnvbo) ++nouveau_bo_new(struct drm_device *dev, int size, int align, ++ uint32_t flags, uint32_t tile_mode, uint32_t tile_flags, ++ struct nouveau_bo **pnvbo) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_bo *nvbo; +- int ret = 0, page_shift = 0; ++ int ret; + + nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL); + if (!nvbo) + return -ENOMEM; + INIT_LIST_HEAD(&nvbo->head); + INIT_LIST_HEAD(&nvbo->entry); ++ INIT_LIST_HEAD(&nvbo->vma_list); + nvbo->tile_mode = tile_mode; + nvbo->tile_flags = tile_flags; + nvbo->bo.bdev = &dev_priv->ttm.bdev; + +- nouveau_bo_fixup_align(nvbo, flags, &align, &size, &page_shift); +- align >>= PAGE_SHIFT; +- +- if (dev_priv->chan_vm) { +- ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift, +- NV_MEM_ACCESS_RW, &nvbo->vma); +- if (ret) { +- kfree(nvbo); +- return ret; +- } ++ nvbo->page_shift = 12; ++ if (dev_priv->bar1_vm) { ++ if (!(flags & TTM_PL_FLAG_TT) && size > 256 * 1024) ++ nvbo->page_shift = dev_priv->bar1_vm->lpg_shift; + } + ++ nouveau_bo_fixup_align(nvbo, flags, &align, &size); + nvbo->bo.mem.num_pages = size >> PAGE_SHIFT; + nouveau_bo_placement_set(nvbo, flags, 0); + +- nvbo->channel = chan; + ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size, +- ttm_bo_type_device, &nvbo->placement, align, 0, +- false, NULL, size, nouveau_bo_del_ttm); ++ ttm_bo_type_device, &nvbo->placement, ++ align >> PAGE_SHIFT, 0, false, NULL, size, ++ nouveau_bo_del_ttm); + if (ret) { + /* ttm will call nouveau_bo_del_ttm if it fails.. */ + return ret; + } +- nvbo->channel = NULL; + +- if (nvbo->vma.node) +- nvbo->bo.offset = nvbo->vma.offset; + *pnvbo = nvbo; + return 0; + } +@@ -312,8 +292,6 @@ + if (ret) + return ret; + +- if (nvbo->vma.node) +- nvbo->bo.offset = nvbo->vma.offset; + return 0; + } + +@@ -440,7 +418,6 @@ + TTM_MEMTYPE_FLAG_CMA; + man->available_caching = TTM_PL_MASK_CACHING; + man->default_caching = TTM_PL_FLAG_CACHED; +- man->gpu_offset = dev_priv->gart_info.aper_base; + break; + default: + NV_ERROR(dev, "Unknown GART type: %d\n", +@@ -501,19 +478,12 @@ + nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, + struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) + { +- struct nouveau_mem *old_node = old_mem->mm_node; +- struct nouveau_mem *new_node = new_mem->mm_node; +- struct nouveau_bo *nvbo = nouveau_bo(bo); ++ struct nouveau_mem *node = old_mem->mm_node; ++ u64 src_offset = node->vma[0].offset; ++ u64 dst_offset = node->vma[1].offset; + u32 page_count = new_mem->num_pages; +- u64 src_offset, dst_offset; + int ret; + +- src_offset = old_node->tmp_vma.offset; +- if (new_node->tmp_vma.node) +- dst_offset = new_node->tmp_vma.offset; +- else +- dst_offset = nvbo->vma.offset; +- + page_count = new_mem->num_pages; + while (page_count) { + int line_count = (page_count > 2047) ? 2047 : page_count; +@@ -547,19 +517,13 @@ + nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, + struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) + { +- struct nouveau_mem *old_node = old_mem->mm_node; +- struct nouveau_mem *new_node = new_mem->mm_node; ++ struct nouveau_mem *node = old_mem->mm_node; + struct nouveau_bo *nvbo = nouveau_bo(bo); + u64 length = (new_mem->num_pages << PAGE_SHIFT); +- u64 src_offset, dst_offset; ++ u64 src_offset = node->vma[0].offset; ++ u64 dst_offset = node->vma[1].offset; + int ret; + +- src_offset = old_node->tmp_vma.offset; +- if (new_node->tmp_vma.node) +- dst_offset = new_node->tmp_vma.offset; +- else +- dst_offset = nvbo->vma.offset; +- + while (length) { + u32 amount, stride, height; + +@@ -695,6 +659,27 @@ + } + + static int ++nouveau_vma_getmap(struct nouveau_channel *chan, struct nouveau_bo *nvbo, ++ struct ttm_mem_reg *mem, struct nouveau_vma *vma) ++{ ++ struct nouveau_mem *node = mem->mm_node; ++ int ret; ++ ++ ret = nouveau_vm_get(chan->vm, mem->num_pages << PAGE_SHIFT, ++ node->page_shift, NV_MEM_ACCESS_RO, vma); ++ if (ret) ++ return ret; ++ ++ if (mem->mem_type == TTM_PL_VRAM) ++ nouveau_vm_map(vma, node); ++ else ++ nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT, ++ node, node->pages); ++ ++ return 0; ++} ++ ++static int + nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, + bool no_wait_reserve, bool no_wait_gpu, + struct ttm_mem_reg *new_mem) +@@ -711,31 +696,20 @@ + mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX); + } + +- /* create temporary vma for old memory, this will get cleaned +- * up after ttm destroys the ttm_mem_reg ++ /* create temporary vmas for the transfer and attach them to the ++ * old nouveau_mem node, these will get cleaned up after ttm has ++ * destroyed the ttm_mem_reg + */ + if (dev_priv->card_type >= NV_50) { + struct nouveau_mem *node = old_mem->mm_node; +- if (!node->tmp_vma.node) { +- u32 page_shift = nvbo->vma.node->type; +- if (old_mem->mem_type == TTM_PL_TT) +- page_shift = nvbo->vma.vm->spg_shift; +- +- ret = nouveau_vm_get(chan->vm, +- old_mem->num_pages << PAGE_SHIFT, +- page_shift, NV_MEM_ACCESS_RO, +- &node->tmp_vma); +- if (ret) +- goto out; +- } + +- if (old_mem->mem_type == TTM_PL_VRAM) +- nouveau_vm_map(&node->tmp_vma, node); +- else { +- nouveau_vm_map_sg(&node->tmp_vma, 0, +- old_mem->num_pages << PAGE_SHIFT, +- node, node->pages); +- } ++ ret = nouveau_vma_getmap(chan, nvbo, old_mem, &node->vma[0]); ++ if (ret) ++ goto out; ++ ++ ret = nouveau_vma_getmap(chan, nvbo, new_mem, &node->vma[1]); ++ if (ret) ++ goto out; + } + + if (dev_priv->card_type < NV_50) +@@ -762,7 +736,6 @@ + bool no_wait_reserve, bool no_wait_gpu, + struct ttm_mem_reg *new_mem) + { +- struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; + struct ttm_placement placement; + struct ttm_mem_reg tmp_mem; +@@ -782,23 +755,7 @@ + if (ret) + goto out; + +- if (dev_priv->card_type >= NV_50) { +- struct nouveau_bo *nvbo = nouveau_bo(bo); +- struct nouveau_mem *node = tmp_mem.mm_node; +- struct nouveau_vma *vma = &nvbo->vma; +- if (vma->node->type != vma->vm->spg_shift) +- vma = &node->tmp_vma; +- nouveau_vm_map_sg(vma, 0, tmp_mem.num_pages << PAGE_SHIFT, +- node, node->pages); +- } +- + ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, &tmp_mem); +- +- if (dev_priv->card_type >= NV_50) { +- struct nouveau_bo *nvbo = nouveau_bo(bo); +- nouveau_vm_unmap(&nvbo->vma); +- } +- + if (ret) + goto out; + +@@ -844,30 +801,22 @@ + static void + nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) + { +- struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct nouveau_mem *node = new_mem->mm_node; + struct nouveau_bo *nvbo = nouveau_bo(bo); +- struct nouveau_vma *vma = &nvbo->vma; +- struct nouveau_vm *vm = vma->vm; ++ struct nouveau_vma *vma; + +- if (dev_priv->card_type < NV_50) +- return; +- +- switch (new_mem->mem_type) { +- case TTM_PL_VRAM: +- nouveau_vm_map(vma, node); +- break; +- case TTM_PL_TT: +- if (vma->node->type != vm->spg_shift) { ++ list_for_each_entry(vma, &nvbo->vma_list, head) { ++ if (new_mem->mem_type == TTM_PL_VRAM) { ++ nouveau_vm_map(vma, new_mem->mm_node); ++ } else ++ if (new_mem->mem_type == TTM_PL_TT && ++ nvbo->page_shift == vma->vm->spg_shift) { ++ nouveau_vm_map_sg(vma, 0, new_mem-> ++ num_pages << PAGE_SHIFT, ++ node, node->pages); ++ } else { + nouveau_vm_unmap(vma); +- vma = &node->tmp_vma; + } +- nouveau_vm_map_sg(vma, 0, new_mem->num_pages << PAGE_SHIFT, +- node, node->pages); +- break; +- default: +- nouveau_vm_unmap(&nvbo->vma); +- break; + } + } + +@@ -1113,3 +1062,54 @@ + .io_mem_free = &nouveau_ttm_io_mem_free, + }; + ++struct nouveau_vma * ++nouveau_bo_vma_find(struct nouveau_bo *nvbo, struct nouveau_vm *vm) ++{ ++ struct nouveau_vma *vma; ++ list_for_each_entry(vma, &nvbo->vma_list, head) { ++ if (vma->vm == vm) ++ return vma; ++ } ++ ++ return NULL; ++} ++ ++int ++nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm, ++ struct nouveau_vma *vma) ++{ ++ const u32 size = nvbo->bo.mem.num_pages << PAGE_SHIFT; ++ struct nouveau_mem *node = nvbo->bo.mem.mm_node; ++ int ret; ++ ++ ret = nouveau_vm_get(vm, size, nvbo->page_shift, ++ NV_MEM_ACCESS_RW, vma); ++ if (ret) ++ return ret; ++ ++ if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) ++ nouveau_vm_map(vma, nvbo->bo.mem.mm_node); ++ else ++ if (nvbo->bo.mem.mem_type == TTM_PL_TT) ++ nouveau_vm_map_sg(vma, 0, size, node, node->pages); ++ ++ list_add_tail(&vma->head, &nvbo->vma_list); ++ vma->refcount = 1; ++ return 0; ++} ++ ++void ++nouveau_bo_vma_del(struct nouveau_bo *nvbo, struct nouveau_vma *vma) ++{ ++ if (vma->node) { ++ if (nvbo->bo.mem.mem_type != TTM_PL_SYSTEM) { ++ spin_lock(&nvbo->bo.bdev->fence_lock); ++ ttm_bo_wait(&nvbo->bo, false, false, false); ++ spin_unlock(&nvbo->bo.bdev->fence_lock); ++ nouveau_vm_unmap(vma); ++ } ++ ++ nouveau_vm_put(vma); ++ list_del(&vma->head); ++ } ++} +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_channel.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_channel.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_channel.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_channel.c 2011-06-26 07:59:23.000000000 +0200 +@@ -27,40 +27,63 @@ + #include "nouveau_drv.h" + #include "nouveau_drm.h" + #include "nouveau_dma.h" ++#include "nouveau_ramht.h" + + static int +-nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan) ++nouveau_channel_pushbuf_init(struct nouveau_channel *chan) + { ++ u32 mem = nouveau_vram_pushbuf ? TTM_PL_FLAG_VRAM : TTM_PL_FLAG_TT; + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_bo *pb = chan->pushbuf_bo; +- struct nouveau_gpuobj *pushbuf = NULL; +- int ret = 0; ++ int ret; ++ ++ /* allocate buffer object */ ++ ret = nouveau_bo_new(dev, 65536, 0, mem, 0, 0, &chan->pushbuf_bo); ++ if (ret) ++ goto out; ++ ++ ret = nouveau_bo_pin(chan->pushbuf_bo, mem); ++ if (ret) ++ goto out; ++ ++ ret = nouveau_bo_map(chan->pushbuf_bo); ++ if (ret) ++ goto out; + ++ /* create DMA object covering the entire memtype where the push ++ * buffer resides, userspace can submit its own push buffers from ++ * anywhere within the same memtype. ++ */ ++ chan->pushbuf_base = chan->pushbuf_bo->bo.offset; + if (dev_priv->card_type >= NV_50) { ++ ret = nouveau_bo_vma_add(chan->pushbuf_bo, chan->vm, ++ &chan->pushbuf_vma); ++ if (ret) ++ goto out; ++ + if (dev_priv->card_type < NV_C0) { + ret = nouveau_gpuobj_dma_new(chan, + NV_CLASS_DMA_IN_MEMORY, 0, + (1ULL << 40), + NV_MEM_ACCESS_RO, + NV_MEM_TARGET_VM, +- &pushbuf); ++ &chan->pushbuf); + } +- chan->pushbuf_base = pb->bo.offset; ++ chan->pushbuf_base = chan->pushbuf_vma.offset; + } else +- if (pb->bo.mem.mem_type == TTM_PL_TT) { ++ if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_TT) { + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, + dev_priv->gart_info.aper_size, + NV_MEM_ACCESS_RO, +- NV_MEM_TARGET_GART, &pushbuf); +- chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; ++ NV_MEM_TARGET_GART, ++ &chan->pushbuf); + } 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_MEM_ACCESS_RO, +- NV_MEM_TARGET_VRAM, &pushbuf); +- chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; ++ NV_MEM_TARGET_VRAM, ++ &chan->pushbuf); + } else { + /* NV04 cmdbuf hack, from original ddx.. not sure of it's + * exact reason for existing :) PCI access to cmdbuf in +@@ -70,47 +93,22 @@ + pci_resource_start(dev->pdev, 1), + dev_priv->fb_available_size, + NV_MEM_ACCESS_RO, +- NV_MEM_TARGET_PCI, &pushbuf); +- chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; ++ NV_MEM_TARGET_PCI, ++ &chan->pushbuf); + } + +- nouveau_gpuobj_ref(pushbuf, &chan->pushbuf); +- nouveau_gpuobj_ref(NULL, &pushbuf); +- return ret; +-} +- +-static struct nouveau_bo * +-nouveau_channel_user_pushbuf_alloc(struct drm_device *dev) +-{ +- struct nouveau_bo *pushbuf = NULL; +- int location, ret; +- +- if (nouveau_vram_pushbuf) +- location = TTM_PL_FLAG_VRAM; +- else +- location = TTM_PL_FLAG_TT; +- +- ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, &pushbuf); +- if (ret) { +- NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret); +- return NULL; +- } +- +- ret = nouveau_bo_pin(pushbuf, location); +- if (ret) { +- NV_ERROR(dev, "error pinning DMA push buffer: %d\n", ret); +- nouveau_bo_ref(NULL, &pushbuf); +- return NULL; +- } +- +- ret = nouveau_bo_map(pushbuf); ++out: + if (ret) { +- nouveau_bo_unpin(pushbuf); +- nouveau_bo_ref(NULL, &pushbuf); +- return NULL; ++ NV_ERROR(dev, "error initialising pushbuf: %d\n", ret); ++ nouveau_bo_vma_del(chan->pushbuf_bo, &chan->pushbuf_vma); ++ nouveau_gpuobj_ref(NULL, &chan->pushbuf); ++ if (chan->pushbuf_bo) { ++ nouveau_bo_unmap(chan->pushbuf_bo); ++ nouveau_bo_ref(NULL, &chan->pushbuf_bo); ++ } + } + +- return pushbuf; ++ return 0; + } + + /* allocates and initializes a fifo for user space consumption */ +@@ -121,6 +119,7 @@ + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; ++ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); + struct nouveau_channel *chan; + unsigned long flags; + int ret; +@@ -160,19 +159,14 @@ + INIT_LIST_HEAD(&chan->nvsw.flip); + INIT_LIST_HEAD(&chan->fence.pending); + +- /* Allocate DMA push buffer */ +- chan->pushbuf_bo = nouveau_channel_user_pushbuf_alloc(dev); +- if (!chan->pushbuf_bo) { +- ret = -ENOMEM; +- NV_ERROR(dev, "pushbuf %d\n", ret); ++ /* setup channel's memory and vm */ ++ ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle); ++ if (ret) { ++ NV_ERROR(dev, "gpuobj %d\n", ret); + nouveau_channel_put(&chan); + return ret; + } + +- nouveau_dma_pre_init(chan); +- chan->user_put = 0x40; +- chan->user_get = 0x44; +- + /* Allocate space for per-channel fixed notifier memory */ + ret = nouveau_notifier_init_channel(chan); + if (ret) { +@@ -181,21 +175,17 @@ + return ret; + } + +- /* Setup channel's default objects */ +- ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle); ++ /* Allocate DMA push buffer */ ++ ret = nouveau_channel_pushbuf_init(chan); + if (ret) { +- NV_ERROR(dev, "gpuobj %d\n", ret); ++ NV_ERROR(dev, "pushbuf %d\n", ret); + nouveau_channel_put(&chan); + return ret; + } + +- /* Create a dma object for the push buffer */ +- ret = nouveau_channel_pushbuf_ctxdma_init(chan); +- if (ret) { +- NV_ERROR(dev, "pbctxdma %d\n", ret); +- nouveau_channel_put(&chan); +- return ret; +- } ++ nouveau_dma_pre_init(chan); ++ chan->user_put = 0x40; ++ chan->user_get = 0x44; + + /* disable the fifo caches */ + pfifo->reassign(dev, false); +@@ -220,6 +210,11 @@ + nouveau_debugfs_channel_init(chan); + + NV_DEBUG(dev, "channel %d initialised\n", chan->id); ++ if (fpriv) { ++ spin_lock(&fpriv->lock); ++ list_add(&chan->list, &fpriv->channels); ++ spin_unlock(&fpriv->lock); ++ } + *chan_ret = chan; + return 0; + } +@@ -236,29 +231,23 @@ + } + + struct nouveau_channel * +-nouveau_channel_get(struct drm_device *dev, struct drm_file *file_priv, int id) ++nouveau_channel_get(struct drm_file *file_priv, int id) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); + struct nouveau_channel *chan; +- unsigned long flags; +- +- if (unlikely(id < 0 || id >= NOUVEAU_MAX_CHANNEL_NR)) +- return ERR_PTR(-EINVAL); +- +- spin_lock_irqsave(&dev_priv->channels.lock, flags); +- chan = nouveau_channel_get_unlocked(dev_priv->channels.ptr[id]); +- spin_unlock_irqrestore(&dev_priv->channels.lock, flags); +- +- if (unlikely(!chan)) +- return ERR_PTR(-EINVAL); + +- if (unlikely(file_priv && chan->file_priv != file_priv)) { +- nouveau_channel_put_unlocked(&chan); +- return ERR_PTR(-EINVAL); ++ spin_lock(&fpriv->lock); ++ list_for_each_entry(chan, &fpriv->channels, list) { ++ if (chan->id == id) { ++ chan = nouveau_channel_get_unlocked(chan); ++ spin_unlock(&fpriv->lock); ++ mutex_lock(&chan->mutex); ++ return chan; ++ } + } ++ spin_unlock(&fpriv->lock); + +- mutex_lock(&chan->mutex); +- return chan; ++ return ERR_PTR(-EINVAL); + } + + void +@@ -312,12 +301,14 @@ + /* destroy any resources the channel owned */ + nouveau_gpuobj_ref(NULL, &chan->pushbuf); + if (chan->pushbuf_bo) { ++ nouveau_bo_vma_del(chan->pushbuf_bo, &chan->pushbuf_vma); + nouveau_bo_unmap(chan->pushbuf_bo); + nouveau_bo_unpin(chan->pushbuf_bo); + nouveau_bo_ref(NULL, &chan->pushbuf_bo); + } +- nouveau_gpuobj_channel_takedown(chan); ++ nouveau_ramht_ref(NULL, &chan->ramht, chan); + nouveau_notifier_takedown_channel(chan); ++ nouveau_gpuobj_channel_takedown(chan); + + nouveau_channel_ref(NULL, pchan); + } +@@ -383,10 +374,11 @@ + + NV_DEBUG(dev, "clearing FIFO enables from file_priv\n"); + for (i = 0; i < engine->fifo.channels; i++) { +- chan = nouveau_channel_get(dev, file_priv, i); ++ chan = nouveau_channel_get(file_priv, i); + if (IS_ERR(chan)) + continue; + ++ list_del(&chan->list); + atomic_dec(&chan->users); + nouveau_channel_put(&chan); + } +@@ -459,10 +451,11 @@ + struct drm_nouveau_channel_free *req = data; + struct nouveau_channel *chan; + +- chan = nouveau_channel_get(dev, file_priv, req->channel); ++ chan = nouveau_channel_get(file_priv, req->channel); + if (IS_ERR(chan)) + return PTR_ERR(chan); + ++ list_del(&chan->list); + atomic_dec(&chan->users); + nouveau_channel_put(&chan); + return 0; +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_dma.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_dma.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.c 2011-06-26 07:59:23.000000000 +0200 +@@ -167,8 +167,13 @@ + int delta, int length) + { + struct nouveau_bo *pb = chan->pushbuf_bo; +- uint64_t offset = bo->bo.offset + delta; ++ struct nouveau_vma *vma; + int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base; ++ u64 offset; ++ ++ vma = nouveau_bo_vma_find(bo, chan->vm); ++ BUG_ON(!vma); ++ offset = vma->offset + delta; + + BUG_ON(chan->dma.ib_free < 1); + nouveau_bo_wr32(pb, ip++, lower_32_bits(offset)); +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_drv.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_drv.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.c 2011-06-26 07:59:23.000000000 +0200 +@@ -73,7 +73,7 @@ + module_param_named(ignorelid, nouveau_ignorelid, int, 0400); + + MODULE_PARM_DESC(noaccel, "Disable all acceleration"); +-int nouveau_noaccel = 0; ++int nouveau_noaccel = -1; + module_param_named(noaccel, nouveau_noaccel, int, 0400); + + MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration"); +@@ -119,6 +119,10 @@ + int nouveau_msi; + module_param_named(msi, nouveau_msi, int, 0400); + ++MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n"); ++int nouveau_ctxfw; ++module_param_named(ctxfw, nouveau_ctxfw, int, 0400); ++ + int nouveau_fbpercrtc; + #if 0 + module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400); +@@ -354,7 +358,7 @@ + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); +- u32 offset = nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT; ++ u32 offset = nv_crtc->cursor.nvbo->bo.offset; + + nv_crtc->cursor.set_offset(nv_crtc, offset); + nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x, +@@ -389,7 +393,9 @@ + .firstopen = nouveau_firstopen, + .lastclose = nouveau_lastclose, + .unload = nouveau_unload, ++ .open = nouveau_open, + .preclose = nouveau_preclose, ++ .postclose = nouveau_postclose, + #if defined(CONFIG_DRM_NOUVEAU_DEBUG) + .debugfs_init = nouveau_debugfs_init, + .debugfs_cleanup = nouveau_debugfs_takedown, +@@ -420,6 +426,8 @@ + + .gem_init_object = nouveau_gem_object_new, + .gem_free_object = nouveau_gem_object_del, ++ .gem_open_object = nouveau_gem_object_open, ++ .gem_close_object = nouveau_gem_object_close, + + .name = DRIVER_NAME, + .desc = DRIVER_DESC, +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_drv.h linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.h +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_drv.h 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.h 2011-06-26 07:59:23.000000000 +0200 +@@ -46,9 +46,17 @@ + #include "ttm/ttm_module.h" + + struct nouveau_fpriv { +- struct ttm_object_file *tfile; ++ spinlock_t lock; ++ struct list_head channels; ++ struct nouveau_vm *vm; + }; + ++static inline struct nouveau_fpriv * ++nouveau_fpriv(struct drm_file *file_priv) ++{ ++ return file_priv ? file_priv->driver_priv : NULL; ++} ++ + #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) + + #include "nouveau_drm.h" +@@ -69,7 +77,7 @@ + struct drm_device *dev; + + struct nouveau_vma bar_vma; +- struct nouveau_vma tmp_vma; ++ struct nouveau_vma vma[2]; + u8 page_shift; + + struct drm_mm_node *tag; +@@ -107,7 +115,8 @@ + + struct nouveau_channel *channel; + +- struct nouveau_vma vma; ++ struct list_head vma_list; ++ unsigned page_shift; + + uint32_t tile_mode; + uint32_t tile_flags; +@@ -176,9 +185,10 @@ + uint32_t flags; + + u32 size; +- u32 pinst; +- u32 cinst; +- u64 vinst; ++ u32 pinst; /* PRAMIN BAR offset */ ++ u32 cinst; /* Channel offset */ ++ u64 vinst; /* VRAM address */ ++ u64 linst; /* VM address */ + + uint32_t engine; + uint32_t class; +@@ -201,6 +211,7 @@ + + struct nouveau_channel { + struct drm_device *dev; ++ struct list_head list; + int id; + + /* references to the channel data structure */ +@@ -228,15 +239,18 @@ + uint32_t sequence; + uint32_t sequence_ack; + atomic_t last_sequence_irq; ++ struct nouveau_vma vma; + } fence; + + /* DMA push buffer */ + struct nouveau_gpuobj *pushbuf; + struct nouveau_bo *pushbuf_bo; ++ struct nouveau_vma pushbuf_vma; + uint32_t pushbuf_base; + + /* Notifier memory */ + struct nouveau_bo *notifier_bo; ++ struct nouveau_vma notifier_vma; + struct drm_mm notifier_heap; + + /* PFIFO context */ +@@ -278,6 +292,7 @@ + + uint32_t sw_subchannel[8]; + ++ struct nouveau_vma dispc_vma[2]; + struct { + struct nouveau_gpuobj *vblsem; + uint32_t vblsem_head; +@@ -314,7 +329,8 @@ + int (*suspend)(struct drm_device *dev); + void (*resume)(struct drm_device *dev); + +- int (*get)(struct nouveau_gpuobj *, u32 size, u32 align); ++ int (*get)(struct nouveau_gpuobj *, struct nouveau_channel *, ++ u32 size, u32 align); + void (*put)(struct nouveau_gpuobj *); + int (*map)(struct nouveau_gpuobj *); + void (*unmap)(struct nouveau_gpuobj *); +@@ -398,12 +414,13 @@ + }; + + struct nouveau_pm_voltage_level { +- u8 voltage; +- u8 vid; ++ u32 voltage; /* microvolts */ ++ u8 vid; + }; + + struct nouveau_pm_voltage { + bool supported; ++ u8 version; + u8 vid_mask; + + struct nouveau_pm_voltage_level *level; +@@ -432,11 +449,19 @@ + u32 core; + u32 memory; + u32 shader; +- u32 unk05; +- u32 unk0a; +- +- u8 voltage; +- u8 fanspeed; ++ u32 rop; ++ u32 copy; ++ u32 daemon; ++ u32 vdec; ++ u32 unk05; /* nv50:nva3, roughly.. */ ++ u32 unka0; /* nva3:nvc0 */ ++ u32 hub01; /* nvc0- */ ++ u32 hub06; /* nvc0- */ ++ u32 hub07; /* nvc0- */ ++ ++ u32 volt_min; /* microvolts */ ++ u32 volt_max; ++ u8 fanspeed; + + u16 memscript; + struct nouveau_pm_memtiming *timing; +@@ -445,9 +470,9 @@ + struct nouveau_pm_temp_sensor_constants { + u16 offset_constant; + s16 offset_mult; +- u16 offset_div; +- u16 slope_mult; +- u16 slope_div; ++ s16 offset_div; ++ s16 slope_mult; ++ s16 slope_div; + }; + + struct nouveau_pm_threshold_temp { +@@ -480,6 +505,11 @@ + void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *, + u32 id, int khz); + void (*clock_set)(struct drm_device *, void *); ++ ++ int (*clocks_get)(struct drm_device *, struct nouveau_pm_level *); ++ void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *); ++ void (*clocks_set)(struct drm_device *, void *); ++ + int (*voltage_get)(struct drm_device *); + int (*voltage_set)(struct drm_device *, int voltage); + int (*fanspeed_get)(struct drm_device *); +@@ -488,7 +518,10 @@ + }; + + struct nouveau_vram_engine { ++ struct nouveau_mm *mm; ++ + int (*init)(struct drm_device *); ++ void (*takedown)(struct drm_device *dev); + int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, + u32 type, struct nouveau_mem **); + void (*put)(struct drm_device *, struct nouveau_mem **); +@@ -608,6 +641,7 @@ + + struct drm_nouveau_private { + struct drm_device *dev; ++ bool noaccel; + + /* the card type, takes NV_* as values */ + enum nouveau_card_type card_type; +@@ -700,7 +734,6 @@ + /* VRAM/fb configuration */ + uint64_t vram_size; + uint64_t vram_sys_base; +- u32 vram_rblock_size; + + uint64_t fb_phys; + uint64_t fb_available_size; +@@ -784,12 +817,15 @@ + extern char *nouveau_perflvl; + extern int nouveau_perflvl_wr; + extern int nouveau_msi; ++extern int nouveau_ctxfw; + + extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state); + extern int nouveau_pci_resume(struct pci_dev *pdev); + + /* nouveau_state.c */ ++extern int nouveau_open(struct drm_device *, struct drm_file *); + extern void nouveau_preclose(struct drm_device *dev, struct drm_file *); ++extern void nouveau_postclose(struct drm_device *, struct drm_file *); + extern int nouveau_load(struct drm_device *, unsigned long flags); + extern int nouveau_firstopen(struct drm_device *); + extern void nouveau_lastclose(struct drm_device *); +@@ -802,6 +838,8 @@ + uint32_t reg, uint32_t mask, uint32_t val); + extern bool nouveau_wait_ne(struct drm_device *, uint64_t timeout, + uint32_t reg, uint32_t mask, uint32_t val); ++extern bool nouveau_wait_cb(struct drm_device *, u64 timeout, ++ bool (*cond)(void *), void *); + extern bool nouveau_wait_for_idle(struct drm_device *); + extern int nouveau_card_init(struct drm_device *); + +@@ -847,7 +885,7 @@ + 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); ++nouveau_channel_get(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, +@@ -1158,8 +1196,8 @@ + /* nvc0_copy.c */ + extern int nvc0_copy_create(struct drm_device *dev, int engine); + +-/* nv40_mpeg.c */ +-extern int nv40_mpeg_create(struct drm_device *dev); ++/* nv31_mpeg.c */ ++extern int nv31_mpeg_create(struct drm_device *dev); + + /* nv50_mpeg.c */ + extern int nv50_mpeg_create(struct drm_device *dev); +@@ -1169,7 +1207,8 @@ + 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_get(struct nouveau_gpuobj *, u32 size, u32 align); ++extern int nv04_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *, ++ u32 size, u32 align); + extern void nv04_instmem_put(struct nouveau_gpuobj *); + extern int nv04_instmem_map(struct nouveau_gpuobj *); + extern void nv04_instmem_unmap(struct nouveau_gpuobj *); +@@ -1180,7 +1219,8 @@ + extern void nv50_instmem_takedown(struct drm_device *); + extern int nv50_instmem_suspend(struct drm_device *); + extern void nv50_instmem_resume(struct drm_device *); +-extern int nv50_instmem_get(struct nouveau_gpuobj *, u32 size, u32 align); ++extern int nv50_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *, ++ u32 size, u32 align); + extern void nv50_instmem_put(struct nouveau_gpuobj *); + extern int nv50_instmem_map(struct nouveau_gpuobj *); + extern void nv50_instmem_unmap(struct nouveau_gpuobj *); +@@ -1247,10 +1287,9 @@ + + /* nouveau_bo.c */ + extern struct ttm_bo_driver nouveau_bo_driver; +-extern int nouveau_bo_new(struct drm_device *, struct nouveau_channel *, +- int size, int align, uint32_t flags, +- uint32_t tile_mode, uint32_t tile_flags, +- struct nouveau_bo **); ++extern int nouveau_bo_new(struct drm_device *, int size, int align, ++ uint32_t flags, uint32_t tile_mode, ++ uint32_t tile_flags, struct nouveau_bo **); + extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags); + extern int nouveau_bo_unpin(struct nouveau_bo *); + extern int nouveau_bo_map(struct nouveau_bo *); +@@ -1265,6 +1304,12 @@ + extern int nouveau_bo_validate(struct nouveau_bo *, bool interruptible, + bool no_wait_reserve, bool no_wait_gpu); + ++extern struct nouveau_vma * ++nouveau_bo_vma_find(struct nouveau_bo *, struct nouveau_vm *); ++extern int nouveau_bo_vma_add(struct nouveau_bo *, struct nouveau_vm *, ++ struct nouveau_vma *); ++extern void nouveau_bo_vma_del(struct nouveau_bo *, struct nouveau_vma *); ++ + /* nouveau_fence.c */ + struct nouveau_fence; + extern int nouveau_fence_init(struct drm_device *); +@@ -1310,12 +1355,14 @@ + } + + /* nouveau_gem.c */ +-extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, +- int size, int align, uint32_t domain, +- uint32_t tile_mode, uint32_t tile_flags, +- struct nouveau_bo **); ++extern int nouveau_gem_new(struct drm_device *, int size, int align, ++ uint32_t domain, uint32_t tile_mode, ++ uint32_t tile_flags, struct nouveau_bo **); + extern int nouveau_gem_object_new(struct drm_gem_object *); + extern void nouveau_gem_object_del(struct drm_gem_object *); ++extern int nouveau_gem_object_open(struct drm_gem_object *, struct drm_file *); ++extern void nouveau_gem_object_close(struct drm_gem_object *, ++ struct drm_file *); + extern int nouveau_gem_ioctl_new(struct drm_device *, void *, + struct drm_file *); + extern int nouveau_gem_ioctl_pushbuf(struct drm_device *, void *, +@@ -1418,6 +1465,8 @@ + nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val)) + #define nv_wait_ne(dev, reg, mask, val) \ + nouveau_wait_ne(dev, 2000000000ULL, (reg), (mask), (val)) ++#define nv_wait_cb(dev, func, data) \ ++ nouveau_wait_cb(dev, 2000000000ULL, (func), (data)) + + /* PRAMIN access */ + static inline u32 nv_ri32(struct drm_device *dev, unsigned offset) +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2011-06-26 07:59:23.000000000 +0200 +@@ -279,6 +279,7 @@ + struct fb_info *info; + struct drm_framebuffer *fb; + struct nouveau_framebuffer *nouveau_fb; ++ struct nouveau_channel *chan; + struct nouveau_bo *nvbo; + struct drm_mode_fb_cmd mode_cmd; + struct pci_dev *pdev = dev->pdev; +@@ -296,8 +297,8 @@ + size = mode_cmd.pitch * mode_cmd.height; + size = roundup(size, PAGE_SIZE); + +- ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, +- NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo); ++ ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM, ++ 0, 0x0000, &nvbo); + if (ret) { + NV_ERROR(dev, "failed to allocate framebuffer\n"); + goto out; +@@ -318,6 +319,15 @@ + goto out; + } + ++ chan = nouveau_nofbaccel ? NULL : dev_priv->channel; ++ if (chan && dev_priv->card_type >= NV_50) { ++ ret = nouveau_bo_vma_add(nvbo, chan->vm, &nfbdev->nouveau_fb.vma); ++ if (ret) { ++ NV_ERROR(dev, "failed to map fb into chan: %d\n", ret); ++ chan = NULL; ++ } ++ } ++ + mutex_lock(&dev->struct_mutex); + + info = framebuffer_alloc(0, device); +@@ -448,6 +458,7 @@ + + if (nouveau_fb->nvbo) { + nouveau_bo_unmap(nouveau_fb->nvbo); ++ nouveau_bo_vma_del(nouveau_fb->nvbo, &nouveau_fb->vma); + drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem); + nouveau_fb->nvbo = NULL; + } +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_fb.h linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_fb.h +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_fb.h 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_fb.h 2011-06-26 07:59:23.000000000 +0200 +@@ -30,6 +30,7 @@ + struct nouveau_framebuffer { + struct drm_framebuffer base; + struct nouveau_bo *nvbo; ++ struct nouveau_vma vma; + u32 r_dma; + u32 r_format; + u32 r_pitch; +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_fence.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_fence.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_fence.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_fence.c 2011-06-26 07:59:23.000000000 +0200 +@@ -336,6 +336,7 @@ + { + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct nouveau_fence *fence = NULL; ++ u64 offset = chan->fence.vma.offset + sema->mem->start; + int ret; + + if (dev_priv->chipset < 0x84) { +@@ -345,13 +346,10 @@ + + BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 3); + OUT_RING (chan, NvSema); +- OUT_RING (chan, sema->mem->start); ++ OUT_RING (chan, offset); + OUT_RING (chan, 1); + } else + if (dev_priv->chipset < 0xc0) { +- struct nouveau_vma *vma = &dev_priv->fence.bo->vma; +- u64 offset = vma->offset + sema->mem->start; +- + ret = RING_SPACE(chan, 7); + if (ret) + return ret; +@@ -364,9 +362,6 @@ + OUT_RING (chan, 1); + OUT_RING (chan, 1); /* ACQUIRE_EQ */ + } else { +- struct nouveau_vma *vma = &dev_priv->fence.bo->vma; +- u64 offset = vma->offset + sema->mem->start; +- + ret = RING_SPACE(chan, 5); + if (ret) + return ret; +@@ -394,6 +389,7 @@ + { + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct nouveau_fence *fence = NULL; ++ u64 offset = chan->fence.vma.offset + sema->mem->start; + int ret; + + if (dev_priv->chipset < 0x84) { +@@ -403,14 +399,11 @@ + + BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 2); + OUT_RING (chan, NvSema); +- OUT_RING (chan, sema->mem->start); ++ OUT_RING (chan, offset); + BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1); + OUT_RING (chan, 1); + } else + if (dev_priv->chipset < 0xc0) { +- struct nouveau_vma *vma = &dev_priv->fence.bo->vma; +- u64 offset = vma->offset + sema->mem->start; +- + ret = RING_SPACE(chan, 7); + if (ret) + return ret; +@@ -423,9 +416,6 @@ + OUT_RING (chan, 1); + OUT_RING (chan, 2); /* RELEASE */ + } else { +- struct nouveau_vma *vma = &dev_priv->fence.bo->vma; +- u64 offset = vma->offset + sema->mem->start; +- + ret = RING_SPACE(chan, 5); + if (ret) + return ret; +@@ -540,6 +530,12 @@ + nouveau_gpuobj_ref(NULL, &obj); + if (ret) + return ret; ++ } else { ++ /* map fence bo into channel's vm */ ++ ret = nouveau_bo_vma_add(dev_priv->fence.bo, chan->vm, ++ &chan->fence.vma); ++ if (ret) ++ return ret; + } + + INIT_LIST_HEAD(&chan->fence.pending); +@@ -551,10 +547,10 @@ + void + nouveau_fence_channel_fini(struct nouveau_channel *chan) + { ++ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct nouveau_fence *tmp, *fence; + + spin_lock(&chan->fence.lock); +- + list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { + fence->signalled = true; + list_del(&fence->entry); +@@ -564,8 +560,9 @@ + + kref_put(&fence->refcount, nouveau_fence_del); + } +- + spin_unlock(&chan->fence.lock); ++ ++ nouveau_bo_vma_del(dev_priv->fence.bo, &chan->fence.vma); + } + + int +@@ -577,7 +574,7 @@ + + /* Create a shared VRAM heap for cross-channel sync. */ + if (USE_SEMA(dev)) { +- ret = nouveau_bo_new(dev, NULL, size, 0, TTM_PL_FLAG_VRAM, ++ ret = nouveau_bo_new(dev, size, 0, TTM_PL_FLAG_VRAM, + 0, 0, &dev_priv->fence.bo); + if (ret) + return ret; +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_gem.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_gem.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_gem.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_gem.c 2011-06-26 07:59:23.000000000 +0200 +@@ -60,9 +60,71 @@ + } + + int +-nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan, +- int size, int align, uint32_t domain, uint32_t tile_mode, +- uint32_t tile_flags, struct nouveau_bo **pnvbo) ++nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) ++{ ++ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); ++ struct nouveau_bo *nvbo = nouveau_gem_object(gem); ++ struct nouveau_vma *vma; ++ int ret; ++ ++ if (!fpriv->vm) ++ return 0; ++ ++ ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0); ++ if (ret) ++ return ret; ++ ++ vma = nouveau_bo_vma_find(nvbo, fpriv->vm); ++ if (!vma) { ++ vma = kzalloc(sizeof(*vma), GFP_KERNEL); ++ if (!vma) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ret = nouveau_bo_vma_add(nvbo, fpriv->vm, vma); ++ if (ret) { ++ kfree(vma); ++ goto out; ++ } ++ } else { ++ vma->refcount++; ++ } ++ ++out: ++ ttm_bo_unreserve(&nvbo->bo); ++ return ret; ++} ++ ++void ++nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) ++{ ++ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); ++ struct nouveau_bo *nvbo = nouveau_gem_object(gem); ++ struct nouveau_vma *vma; ++ int ret; ++ ++ if (!fpriv->vm) ++ return; ++ ++ ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0); ++ if (ret) ++ return; ++ ++ vma = nouveau_bo_vma_find(nvbo, fpriv->vm); ++ if (vma) { ++ if (--vma->refcount == 0) { ++ nouveau_bo_vma_del(nvbo, vma); ++ kfree(vma); ++ } ++ } ++ ttm_bo_unreserve(&nvbo->bo); ++} ++ ++int ++nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain, ++ uint32_t tile_mode, uint32_t tile_flags, ++ struct nouveau_bo **pnvbo) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_bo *nvbo; +@@ -76,7 +138,7 @@ + if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU) + flags |= TTM_PL_FLAG_SYSTEM; + +- ret = nouveau_bo_new(dev, chan, size, align, flags, tile_mode, ++ ret = nouveau_bo_new(dev, size, align, flags, tile_mode, + tile_flags, pnvbo); + if (ret) + return ret; +@@ -103,17 +165,28 @@ + } + + static int +-nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep) ++nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, ++ struct drm_nouveau_gem_info *rep) + { ++ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); + struct nouveau_bo *nvbo = nouveau_gem_object(gem); ++ struct nouveau_vma *vma; + + if (nvbo->bo.mem.mem_type == TTM_PL_TT) + rep->domain = NOUVEAU_GEM_DOMAIN_GART; + else + rep->domain = NOUVEAU_GEM_DOMAIN_VRAM; + +- rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; + rep->offset = nvbo->bo.offset; ++ if (fpriv->vm) { ++ vma = nouveau_bo_vma_find(nvbo, fpriv->vm); ++ if (!vma) ++ return -EINVAL; ++ ++ rep->offset = vma->offset; ++ } ++ ++ rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; + rep->map_handle = nvbo->bo.addr_space_offset; + rep->tile_mode = nvbo->tile_mode; + rep->tile_flags = nvbo->tile_flags; +@@ -127,7 +200,6 @@ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_gem_new *req = data; + struct nouveau_bo *nvbo = NULL; +- struct nouveau_channel *chan = NULL; + int ret = 0; + + if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) +@@ -138,28 +210,21 @@ + return -EINVAL; + } + +- if (req->channel_hint) { +- chan = nouveau_channel_get(dev, file_priv, req->channel_hint); +- if (IS_ERR(chan)) +- return PTR_ERR(chan); +- } +- +- ret = nouveau_gem_new(dev, chan, req->info.size, req->align, ++ ret = nouveau_gem_new(dev, req->info.size, req->align, + req->info.domain, req->info.tile_mode, + req->info.tile_flags, &nvbo); +- if (chan) +- nouveau_channel_put(&chan); + if (ret) + return ret; + +- ret = nouveau_gem_info(nvbo->gem, &req->info); +- if (ret) +- goto out; +- + ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle); ++ if (ret == 0) { ++ ret = nouveau_gem_info(file_priv, nvbo->gem, &req->info); ++ if (ret) ++ drm_gem_handle_delete(file_priv, req->info.handle); ++ } ++ + /* drop reference from allocate - handle holds it now */ + drm_gem_object_unreference_unlocked(nvbo->gem); +-out: + return ret; + } + +@@ -318,6 +383,7 @@ + validate_list(struct nouveau_channel *chan, struct list_head *list, + struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr) + { ++ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct drm_nouveau_gem_pushbuf_bo __user *upbbo = + (void __force __user *)(uintptr_t)user_pbbo_ptr; + struct drm_device *dev = chan->dev; +@@ -356,24 +422,26 @@ + return ret; + } + +- if (nvbo->bo.offset == b->presumed.offset && +- ((nvbo->bo.mem.mem_type == TTM_PL_VRAM && +- b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) || +- (nvbo->bo.mem.mem_type == TTM_PL_TT && +- b->presumed.domain & NOUVEAU_GEM_DOMAIN_GART))) +- continue; ++ if (dev_priv->card_type < NV_50) { ++ if (nvbo->bo.offset == b->presumed.offset && ++ ((nvbo->bo.mem.mem_type == TTM_PL_VRAM && ++ b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) || ++ (nvbo->bo.mem.mem_type == TTM_PL_TT && ++ b->presumed.domain & NOUVEAU_GEM_DOMAIN_GART))) ++ continue; + +- if (nvbo->bo.mem.mem_type == TTM_PL_TT) +- b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART; +- else +- b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM; +- b->presumed.offset = nvbo->bo.offset; +- b->presumed.valid = 0; +- relocs++; +- +- if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed, +- &b->presumed, sizeof(b->presumed))) +- return -EFAULT; ++ if (nvbo->bo.mem.mem_type == TTM_PL_TT) ++ b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART; ++ else ++ b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM; ++ b->presumed.offset = nvbo->bo.offset; ++ b->presumed.valid = 0; ++ relocs++; ++ ++ if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed, ++ &b->presumed, sizeof(b->presumed))) ++ return -EFAULT; ++ } + } + + return relocs; +@@ -548,7 +616,7 @@ + struct nouveau_fence *fence = NULL; + int i, j, ret = 0, do_reloc = 0; + +- chan = nouveau_channel_get(dev, file_priv, req->channel); ++ chan = nouveau_channel_get(file_priv, req->channel); + if (IS_ERR(chan)) + return PTR_ERR(chan); + +@@ -782,7 +850,7 @@ + if (!gem) + return -ENOENT; + +- ret = nouveau_gem_info(gem, req); ++ ret = nouveau_gem_info(file_priv, gem, req); + drm_gem_object_unreference_unlocked(gem); + return ret; + } +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_mem.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_mem.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_mem.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_mem.c 2011-06-26 07:59:23.000000000 +0200 +@@ -423,38 +423,6 @@ + return ret; + } + +- /* reserve space at end of VRAM for PRAMIN */ +- if (dev_priv->card_type >= NV_50) { +- dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024; +- } else +- if (dev_priv->card_type >= NV_40) { +- u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8); +- u32 rsvd; +- +- /* estimate grctx size, the magics come from nv40_grctx.c */ +- if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs; +- else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs; +- else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs; +- else rsvd = 0x4a40 * vs; +- rsvd += 16 * 1024; +- rsvd *= dev_priv->engine.fifo.channels; +- +- /* pciegart table */ +- if (drm_pci_device_is_pcie(dev)) +- rsvd += 512 * 1024; +- +- /* object storage */ +- rsvd += 512 * 1024; +- +- dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096); +- } else { +- dev_priv->ramin_rsvd_vram = 512 * 1024; +- } +- +- ret = dev_priv->engine.vram.init(dev); +- if (ret) +- return ret; +- + NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); + if (dev_priv->vram_sys_base) { + NV_INFO(dev, "Stolen system memory at: 0x%010llx\n", +@@ -479,7 +447,7 @@ + } + + if (dev_priv->card_type < NV_50) { +- ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM, ++ ret = nouveau_bo_new(dev, 256*1024, 0, TTM_PL_FLAG_VRAM, + 0, 0, &dev_priv->vga_ram); + if (ret == 0) + ret = nouveau_bo_pin(dev_priv->vga_ram, +@@ -729,37 +697,31 @@ + } + + static int +-nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size) ++nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) + { +- struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); +- struct nouveau_mm *mm; +- u64 size, block, rsvd; +- int ret; +- +- rsvd = (256 * 1024); /* vga memory */ +- size = (p_size << PAGE_SHIFT) - rsvd; +- block = dev_priv->vram_rblock_size; +- +- ret = nouveau_mm_init(&mm, rsvd >> 12, size >> 12, block >> 12); +- if (ret) +- return ret; +- +- man->priv = mm; ++ /* nothing to do */ + return 0; + } + + static int + nouveau_vram_manager_fini(struct ttm_mem_type_manager *man) + { +- struct nouveau_mm *mm = man->priv; +- int ret; ++ /* nothing to do */ ++ return 0; ++} + +- ret = nouveau_mm_fini(&mm); +- if (ret) +- return ret; ++static inline void ++nouveau_mem_node_cleanup(struct nouveau_mem *node) ++{ ++ if (node->vma[0].node) { ++ nouveau_vm_unmap(&node->vma[0]); ++ nouveau_vm_put(&node->vma[0]); ++ } + +- man->priv = NULL; +- return 0; ++ if (node->vma[1].node) { ++ nouveau_vm_unmap(&node->vma[1]); ++ nouveau_vm_put(&node->vma[1]); ++ } + } + + static void +@@ -768,14 +730,9 @@ + { + struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; +- struct nouveau_mem *node = mem->mm_node; + struct drm_device *dev = dev_priv->dev; + +- if (node->tmp_vma.node) { +- nouveau_vm_unmap(&node->tmp_vma); +- nouveau_vm_put(&node->tmp_vma); +- } +- ++ nouveau_mem_node_cleanup(mem->mm_node); + vram->put(dev, (struct nouveau_mem **)&mem->mm_node); + } + +@@ -794,7 +751,7 @@ + int ret; + + if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) +- size_nc = 1 << nvbo->vma.node->type; ++ size_nc = 1 << nvbo->page_shift; + + ret = vram->get(dev, mem->num_pages << PAGE_SHIFT, + mem->page_alignment << PAGE_SHIFT, size_nc, +@@ -804,9 +761,7 @@ + return (ret == -ENOSPC) ? 0 : ret; + } + +- node->page_shift = 12; +- if (nvbo->vma.node) +- node->page_shift = nvbo->vma.node->type; ++ node->page_shift = nvbo->page_shift; + + mem->mm_node = node; + mem->start = node->offset >> PAGE_SHIFT; +@@ -862,15 +817,9 @@ + nouveau_gart_manager_del(struct ttm_mem_type_manager *man, + struct ttm_mem_reg *mem) + { +- struct nouveau_mem *node = mem->mm_node; +- +- if (node->tmp_vma.node) { +- nouveau_vm_unmap(&node->tmp_vma); +- nouveau_vm_put(&node->tmp_vma); +- } +- ++ nouveau_mem_node_cleanup(mem->mm_node); ++ kfree(mem->mm_node); + mem->mm_node = NULL; +- kfree(node); + } + + static int +@@ -880,11 +829,7 @@ + struct ttm_mem_reg *mem) + { + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); +- struct nouveau_bo *nvbo = nouveau_bo(bo); +- struct nouveau_vma *vma = &nvbo->vma; +- struct nouveau_vm *vm = vma->vm; + struct nouveau_mem *node; +- int ret; + + if (unlikely((mem->num_pages << PAGE_SHIFT) >= + dev_priv->gart_info.aper_size)) +@@ -893,24 +838,8 @@ + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return -ENOMEM; ++ node->page_shift = 12; + +- /* This node must be for evicting large-paged VRAM +- * to system memory. Due to a nv50 limitation of +- * not being able to mix large/small pages within +- * the same PDE, we need to create a temporary +- * small-paged VMA for the eviction. +- */ +- if (vma->node->type != vm->spg_shift) { +- ret = nouveau_vm_get(vm, (u64)vma->node->length << 12, +- vm->spg_shift, NV_MEM_ACCESS_RW, +- &node->tmp_vma); +- if (ret) { +- kfree(node); +- return ret; +- } +- } +- +- node->page_shift = nvbo->vma.node->type; + mem->mm_node = node; + mem->start = 0; + return 0; +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_mm.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_mm.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_mm.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_mm.c 2011-06-26 07:59:23.000000000 +0200 +@@ -158,11 +158,18 @@ + nouveau_mm_fini(struct nouveau_mm **prmm) + { + struct nouveau_mm *rmm = *prmm; +- struct nouveau_mm_node *heap = ++ struct nouveau_mm_node *node, *heap = + list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry); + +- if (!list_is_singular(&rmm->nodes)) ++ if (!list_is_singular(&rmm->nodes)) { ++ printk(KERN_ERR "nouveau_mm not empty at destroy time!\n"); ++ list_for_each_entry(node, &rmm->nodes, nl_entry) { ++ printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n", ++ node->type, node->offset, node->length); ++ } ++ WARN_ON(1); + return -EBUSY; ++ } + + kfree(heap); + kfree(rmm); +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_mm.h linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_mm.h +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_mm.h 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_mm.h 2011-06-26 07:59:23.000000000 +0200 +@@ -52,6 +52,7 @@ + void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *); + + int nv50_vram_init(struct drm_device *); ++void nv50_vram_fini(struct drm_device *); + int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc, + u32 memtype, struct nouveau_mem **); + void nv50_vram_del(struct drm_device *, struct nouveau_mem **); +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_notifier.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_notifier.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_notifier.c 2011-06-26 07:59:23.000000000 +0200 +@@ -34,6 +34,7 @@ + nouveau_notifier_init_channel(struct nouveau_channel *chan) + { + struct drm_device *dev = chan->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_bo *ntfy = NULL; + uint32_t flags, ttmpl; + int ret; +@@ -46,7 +47,7 @@ + ttmpl = TTM_PL_FLAG_TT; + } + +- ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, 0, 0, &ntfy); ++ ret = nouveau_gem_new(dev, PAGE_SIZE, 0, flags, 0, 0, &ntfy); + if (ret) + return ret; + +@@ -58,14 +59,22 @@ + if (ret) + goto out_err; + ++ if (dev_priv->card_type >= NV_50) { ++ ret = nouveau_bo_vma_add(ntfy, chan->vm, &chan->notifier_vma); ++ if (ret) ++ goto out_err; ++ } ++ + ret = drm_mm_init(&chan->notifier_heap, 0, ntfy->bo.mem.size); + if (ret) + goto out_err; + + chan->notifier_bo = ntfy; + out_err: +- if (ret) ++ if (ret) { ++ nouveau_bo_vma_del(ntfy, &chan->notifier_vma); + drm_gem_object_unreference_unlocked(ntfy->gem); ++ } + + return ret; + } +@@ -78,6 +87,7 @@ + if (!chan->notifier_bo) + return; + ++ nouveau_bo_vma_del(chan->notifier_bo, &chan->notifier_vma); + nouveau_bo_unmap(chan->notifier_bo); + mutex_lock(&dev->struct_mutex); + nouveau_bo_unpin(chan->notifier_bo); +@@ -122,10 +132,10 @@ + target = NV_MEM_TARGET_VRAM; + else + target = NV_MEM_TARGET_GART; +- offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; ++ offset = chan->notifier_bo->bo.offset; + } else { + target = NV_MEM_TARGET_VM; +- offset = chan->notifier_bo->vma.offset; ++ offset = chan->notifier_vma.offset; + } + offset += mem->start; + +@@ -183,7 +193,7 @@ + if (unlikely(dev_priv->card_type >= NV_C0)) + return -EINVAL; + +- chan = nouveau_channel_get(dev, file_priv, na->channel); ++ chan = nouveau_channel_get(file_priv, na->channel); + if (IS_ERR(chan)) + return PTR_ERR(chan); + +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_object.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_object.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_object.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_object.c 2011-06-26 07:59:23.000000000 +0200 +@@ -125,7 +125,7 @@ + int ret = -EINVAL; + + spin_lock_irqsave(&dev_priv->channels.lock, flags); +- if (chid > 0 && chid < dev_priv->engine.fifo.channels) ++ if (chid >= 0 && chid < dev_priv->engine.fifo.channels) + chan = dev_priv->channels.ptr[chid]; + if (chan) + ret = nouveau_gpuobj_mthd_call(chan, class, mthd, data); +@@ -191,7 +191,7 @@ + list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); + spin_unlock(&dev_priv->ramin_lock); + +- if (chan) { ++ if (!(flags & NVOBJ_FLAG_VM) && chan) { + ramin = drm_mm_search_free(&chan->ramin_heap, size, align, 0); + if (ramin) + ramin = drm_mm_get_block(ramin, size, align); +@@ -208,7 +208,7 @@ + gpuobj->vinst = ramin->start + chan->ramin->vinst; + gpuobj->node = ramin; + } else { +- ret = instmem->get(gpuobj, size, align); ++ ret = instmem->get(gpuobj, chan, size, align); + if (ret) { + nouveau_gpuobj_ref(NULL, &gpuobj); + return ret; +@@ -690,36 +690,65 @@ + return 0; + } + +-int +-nouveau_gpuobj_channel_init(struct nouveau_channel *chan, +- uint32_t vram_h, uint32_t tt_h) ++static int ++nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm) + { + struct drm_device *dev = chan->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpuobj *vram = NULL, *tt = NULL; ++ struct nouveau_gpuobj *pgd = NULL; ++ struct nouveau_vm_pgd *vpgd; + int ret, i; + +- NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); +- +- if (dev_priv->card_type == NV_C0) { +- struct nouveau_vm *vm = dev_priv->chan_vm; +- struct nouveau_vm_pgd *vpgd; ++ ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0, &chan->ramin); ++ if (ret) ++ return ret; + +- ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0, +- &chan->ramin); ++ /* create page directory for this vm if none currently exists, ++ * will be destroyed automagically when last reference to the ++ * vm is removed ++ */ ++ if (list_empty(&vm->pgd_list)) { ++ ret = nouveau_gpuobj_new(dev, NULL, 65536, 0x1000, 0, &pgd); + if (ret) + return ret; ++ } ++ nouveau_vm_ref(vm, &chan->vm, pgd); ++ nouveau_gpuobj_ref(NULL, &pgd); + +- nouveau_vm_ref(vm, &chan->vm, NULL); ++ /* point channel at vm's page directory */ ++ vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head); ++ nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst)); ++ nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst)); ++ nv_wo32(chan->ramin, 0x0208, 0xffffffff); ++ nv_wo32(chan->ramin, 0x020c, 0x000000ff); ++ ++ /* map display semaphore buffers into channel's vm */ ++ for (i = 0; i < 2; i++) { ++ struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i]; + +- vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head); +- nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst)); +- nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst)); +- nv_wo32(chan->ramin, 0x0208, 0xffffffff); +- nv_wo32(chan->ramin, 0x020c, 0x000000ff); +- return 0; ++ ret = nouveau_bo_vma_add(dispc->sem.bo, chan->vm, ++ &chan->dispc_vma[i]); ++ if (ret) ++ return ret; + } + ++ return 0; ++} ++ ++int ++nouveau_gpuobj_channel_init(struct nouveau_channel *chan, ++ uint32_t vram_h, uint32_t tt_h) ++{ ++ struct drm_device *dev = chan->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_fpriv *fpriv = nouveau_fpriv(chan->file_priv); ++ struct nouveau_vm *vm = fpriv ? fpriv->vm : dev_priv->chan_vm; ++ struct nouveau_gpuobj *vram = NULL, *tt = NULL; ++ int ret, i; ++ ++ NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); ++ if (dev_priv->card_type == NV_C0) ++ return nvc0_gpuobj_channel_init(chan, vm); ++ + /* Allocate a chunk of memory for per-channel object storage */ + ret = nouveau_gpuobj_channel_init_pramin(chan); + if (ret) { +@@ -731,7 +760,7 @@ + * - Allocate per-channel page-directory + * - Link with shared channel VM + */ +- if (dev_priv->chan_vm) { ++ if (vm) { + u32 pgd_offs = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; + u64 vm_vinst = chan->ramin->vinst + pgd_offs; + u32 vm_pinst = chan->ramin->pinst; +@@ -744,7 +773,7 @@ + if (ret) + return ret; + +- nouveau_vm_ref(dev_priv->chan_vm, &chan->vm, chan->vm_pd); ++ nouveau_vm_ref(vm, &chan->vm, chan->vm_pd); + } + + /* RAMHT */ +@@ -768,7 +797,7 @@ + struct nouveau_gpuobj *sem = NULL; + struct nv50_display_crtc *dispc = + &nv50_display(dev)->crtc[i]; +- u64 offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT; ++ u64 offset = dispc->sem.bo->bo.offset; + + ret = nouveau_gpuobj_dma_new(chan, 0x3d, offset, 0xfff, + NV_MEM_ACCESS_RW, +@@ -841,13 +870,22 @@ + nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) + { + struct drm_device *dev = chan->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ int i; + + NV_DEBUG(dev, "ch%d\n", chan->id); + +- nouveau_ramht_ref(NULL, &chan->ramht, chan); ++ if (dev_priv->card_type >= NV_50) { ++ struct nv50_display *disp = nv50_display(dev); ++ ++ for (i = 0; i < 2; i++) { ++ struct nv50_display_crtc *dispc = &disp->crtc[i]; ++ nouveau_bo_vma_del(dispc->sem.bo, &chan->dispc_vma[i]); ++ } + +- nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); +- nouveau_gpuobj_ref(NULL, &chan->vm_pd); ++ nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); ++ nouveau_gpuobj_ref(NULL, &chan->vm_pd); ++ } + + if (drm_mm_initialized(&chan->ramin_heap)) + drm_mm_takedown(&chan->ramin_heap); +@@ -909,7 +947,7 @@ + if (init->handle == ~0) + return -EINVAL; + +- chan = nouveau_channel_get(dev, file_priv, init->channel); ++ chan = nouveau_channel_get(file_priv, init->channel); + if (IS_ERR(chan)) + return PTR_ERR(chan); + +@@ -936,7 +974,7 @@ + struct nouveau_channel *chan; + int ret; + +- chan = nouveau_channel_get(dev, file_priv, objfree->channel); ++ chan = nouveau_channel_get(file_priv, objfree->channel); + if (IS_ERR(chan)) + return PTR_ERR(chan); + +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_perf.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_perf.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_perf.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_perf.c 2011-06-26 07:59:23.000000000 +0200 +@@ -134,6 +134,49 @@ + return &pm->memtimings.timing[entry[1]]; + } + ++static void ++nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P, ++ struct nouveau_pm_level *perflvl) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvbios *bios = &dev_priv->vbios; ++ u8 *vmap; ++ int id; ++ ++ id = perflvl->volt_min; ++ perflvl->volt_min = 0; ++ ++ /* boards using voltage table version <0x40 store the voltage ++ * level directly in the perflvl entry as a multiple of 10mV ++ */ ++ if (dev_priv->engine.pm.voltage.version < 0x40) { ++ perflvl->volt_min = id * 10000; ++ perflvl->volt_max = perflvl->volt_min; ++ return; ++ } ++ ++ /* on newer ones, the perflvl stores an index into yet another ++ * vbios table containing a min/max voltage value for the perflvl ++ */ ++ if (P->version != 2 || P->length < 34) { ++ NV_DEBUG(dev, "where's our volt map table ptr? %d %d\n", ++ P->version, P->length); ++ return; ++ } ++ ++ vmap = ROMPTR(bios, P->data[32]); ++ if (!vmap) { ++ NV_DEBUG(dev, "volt map table pointer invalid\n"); ++ return; ++ } ++ ++ if (id < vmap[3]) { ++ vmap += vmap[1] + (vmap[2] * id); ++ perflvl->volt_min = ROM32(vmap[0]); ++ perflvl->volt_max = ROM32(vmap[4]); ++ } ++} ++ + void + nouveau_perf_init(struct drm_device *dev) + { +@@ -203,7 +246,8 @@ + case 0x13: + case 0x15: + perflvl->fanspeed = entry[55]; +- perflvl->voltage = (recordlen > 56) ? entry[56] : 0; ++ if (recordlen > 56) ++ perflvl->volt_min = entry[56]; + perflvl->core = ROM32(entry[1]) * 10; + perflvl->memory = ROM32(entry[5]) * 20; + break; +@@ -211,7 +255,7 @@ + case 0x23: + case 0x24: + perflvl->fanspeed = entry[4]; +- perflvl->voltage = entry[5]; ++ perflvl->volt_min = entry[5]; + perflvl->core = ROM16(entry[6]) * 1000; + + if (dev_priv->chipset == 0x49 || +@@ -223,7 +267,7 @@ + break; + case 0x25: + perflvl->fanspeed = entry[4]; +- perflvl->voltage = entry[5]; ++ perflvl->volt_min = entry[5]; + perflvl->core = ROM16(entry[6]) * 1000; + perflvl->shader = ROM16(entry[10]) * 1000; + perflvl->memory = ROM16(entry[12]) * 1000; +@@ -232,7 +276,7 @@ + perflvl->memscript = ROM16(entry[2]); + case 0x35: + perflvl->fanspeed = entry[6]; +- perflvl->voltage = entry[7]; ++ perflvl->volt_min = entry[7]; + perflvl->core = ROM16(entry[8]) * 1000; + perflvl->shader = ROM16(entry[10]) * 1000; + perflvl->memory = ROM16(entry[12]) * 1000; +@@ -240,30 +284,34 @@ + perflvl->unk05 = ROM16(entry[16]) * 1000; + break; + case 0x40: +-#define subent(n) entry[perf[2] + ((n) * perf[3])] ++#define subent(n) (ROM16(entry[perf[2] + ((n) * perf[3])]) & 0xfff) * 1000 + perflvl->fanspeed = 0; /*XXX*/ +- perflvl->voltage = entry[2]; ++ perflvl->volt_min = entry[2]; + if (dev_priv->card_type == NV_50) { +- perflvl->core = ROM16(subent(0)) & 0xfff; +- perflvl->shader = ROM16(subent(1)) & 0xfff; +- perflvl->memory = ROM16(subent(2)) & 0xfff; ++ perflvl->core = subent(0); ++ perflvl->shader = subent(1); ++ perflvl->memory = subent(2); ++ perflvl->vdec = subent(3); ++ perflvl->unka0 = subent(4); + } else { +- perflvl->shader = ROM16(subent(3)) & 0xfff; ++ perflvl->hub06 = subent(0); ++ perflvl->hub01 = subent(1); ++ perflvl->copy = subent(2); ++ perflvl->shader = subent(3); ++ perflvl->rop = subent(4); ++ perflvl->memory = subent(5); ++ perflvl->vdec = subent(6); ++ perflvl->daemon = subent(10); ++ perflvl->hub07 = subent(11); + perflvl->core = perflvl->shader / 2; +- perflvl->unk0a = ROM16(subent(4)) & 0xfff; +- perflvl->memory = ROM16(subent(5)) & 0xfff; + } +- +- perflvl->core *= 1000; +- perflvl->shader *= 1000; +- perflvl->memory *= 1000; +- perflvl->unk0a *= 1000; + break; + } + + /* make sure vid is valid */ +- if (pm->voltage.supported && perflvl->voltage) { +- vid = nouveau_volt_vid_lookup(dev, perflvl->voltage); ++ nouveau_perf_voltage(dev, &P, perflvl); ++ if (pm->voltage.supported && perflvl->volt_min) { ++ vid = nouveau_volt_vid_lookup(dev, perflvl->volt_min); + if (vid < 0) { + NV_DEBUG(dev, "drop perflvl %d, bad vid\n", i); + entry += recordlen; +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_pm.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_pm.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.c 2011-06-26 07:59:23.000000000 +0200 +@@ -64,18 +64,26 @@ + if (perflvl == pm->cur) + return 0; + +- if (pm->voltage.supported && pm->voltage_set && perflvl->voltage) { +- ret = pm->voltage_set(dev, perflvl->voltage); ++ if (pm->voltage.supported && pm->voltage_set && perflvl->volt_min) { ++ ret = pm->voltage_set(dev, perflvl->volt_min); + if (ret) { + NV_ERROR(dev, "voltage_set %d failed: %d\n", +- perflvl->voltage, ret); ++ perflvl->volt_min, ret); + } + } + +- nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core); +- nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader); +- nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory); +- nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05); ++ if (pm->clocks_pre) { ++ void *state = pm->clocks_pre(dev, perflvl); ++ if (IS_ERR(state)) ++ return PTR_ERR(state); ++ pm->clocks_set(dev, state); ++ } else ++ if (pm->clock_set) { ++ nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core); ++ nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader); ++ nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory); ++ nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05); ++ } + + pm->cur = perflvl; + return 0; +@@ -92,9 +100,6 @@ + if (nouveau_perflvl_wr != 7777) + return -EPERM; + +- if (!pm->clock_set) +- return -EINVAL; +- + if (!strncmp(profile, "boot", 4)) + perflvl = &pm->boot; + else { +@@ -123,31 +128,37 @@ + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + int ret; + +- if (!pm->clock_get) +- return -EINVAL; +- + memset(perflvl, 0, sizeof(*perflvl)); + +- ret = pm->clock_get(dev, PLL_CORE); +- if (ret > 0) +- perflvl->core = ret; +- +- ret = pm->clock_get(dev, PLL_MEMORY); +- if (ret > 0) +- perflvl->memory = ret; +- +- ret = pm->clock_get(dev, PLL_SHADER); +- if (ret > 0) +- perflvl->shader = ret; +- +- ret = pm->clock_get(dev, PLL_UNK05); +- if (ret > 0) +- perflvl->unk05 = ret; ++ if (pm->clocks_get) { ++ ret = pm->clocks_get(dev, perflvl); ++ if (ret) ++ return ret; ++ } else ++ if (pm->clock_get) { ++ ret = pm->clock_get(dev, PLL_CORE); ++ if (ret > 0) ++ perflvl->core = ret; ++ ++ ret = pm->clock_get(dev, PLL_MEMORY); ++ if (ret > 0) ++ perflvl->memory = ret; ++ ++ ret = pm->clock_get(dev, PLL_SHADER); ++ if (ret > 0) ++ perflvl->shader = ret; ++ ++ ret = pm->clock_get(dev, PLL_UNK05); ++ if (ret > 0) ++ perflvl->unk05 = ret; ++ } + + if (pm->voltage.supported && pm->voltage_get) { + ret = pm->voltage_get(dev); +- if (ret > 0) +- perflvl->voltage = ret; ++ if (ret > 0) { ++ perflvl->volt_min = ret; ++ perflvl->volt_max = ret; ++ } + } + + return 0; +@@ -156,7 +167,7 @@ + static void + nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) + { +- char c[16], s[16], v[16], f[16], t[16]; ++ char c[16], s[16], v[32], f[16], t[16], m[16]; + + c[0] = '\0'; + if (perflvl->core) +@@ -166,9 +177,19 @@ + if (perflvl->shader) + snprintf(s, sizeof(s), " shader %dMHz", perflvl->shader / 1000); + ++ m[0] = '\0'; ++ if (perflvl->memory) ++ snprintf(m, sizeof(m), " memory %dMHz", perflvl->memory / 1000); ++ + v[0] = '\0'; +- if (perflvl->voltage) +- snprintf(v, sizeof(v), " voltage %dmV", perflvl->voltage * 10); ++ if (perflvl->volt_min && perflvl->volt_min != perflvl->volt_max) { ++ snprintf(v, sizeof(v), " voltage %dmV-%dmV", ++ perflvl->volt_min / 1000, perflvl->volt_max / 1000); ++ } else ++ if (perflvl->volt_min) { ++ snprintf(v, sizeof(v), " voltage %dmV", ++ perflvl->volt_min / 1000); ++ } + + f[0] = '\0'; + if (perflvl->fanspeed) +@@ -178,8 +199,7 @@ + if (perflvl->timing) + snprintf(t, sizeof(t), " timing %d", perflvl->timing->id); + +- snprintf(ptr, len, "memory %dMHz%s%s%s%s%s\n", perflvl->memory / 1000, +- c, s, v, f, t); ++ snprintf(ptr, len, "%s%s%s%s%s%s\n", c, s, m, t, v, f); + } + + static ssize_t +@@ -190,7 +210,7 @@ + char *ptr = buf; + int len = PAGE_SIZE; + +- snprintf(ptr, len, "%d: ", perflvl->id); ++ snprintf(ptr, len, "%d:", perflvl->id); + ptr += strlen(buf); + len -= strlen(buf); + +@@ -211,9 +231,9 @@ + if (!pm->cur) + snprintf(ptr, len, "setting: boot\n"); + else if (pm->cur == &pm->boot) +- snprintf(ptr, len, "setting: boot\nc: "); ++ snprintf(ptr, len, "setting: boot\nc:"); + else +- snprintf(ptr, len, "setting: static %d\nc: ", pm->cur->id); ++ snprintf(ptr, len, "setting: static %d\nc:", pm->cur->id); + ptr += strlen(buf); + len -= strlen(buf); + +@@ -488,7 +508,7 @@ + NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl); + for (i = 0; i < pm->nr_perflvl; i++) { + nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info)); +- NV_INFO(dev, "%d: %s", pm->perflvl[i].id, info); ++ NV_INFO(dev, "%d:%s", pm->perflvl[i].id, info); + } + + /* determine current ("boot") performance level */ +@@ -498,7 +518,7 @@ + pm->cur = &pm->boot; + + nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); +- NV_INFO(dev, "c: %s", info); ++ NV_INFO(dev, "c:%s", info); + } + + /* switch performance levels now if requested */ +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_pm.h linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.h +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_pm.h 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.h 2011-06-26 07:59:23.000000000 +0200 +@@ -59,10 +59,12 @@ + void nv50_pm_clock_set(struct drm_device *, void *); + + /* nva3_pm.c */ +-int nva3_pm_clock_get(struct drm_device *, u32 id); +-void *nva3_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, +- u32 id, int khz); +-void nva3_pm_clock_set(struct drm_device *, void *); ++int nva3_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); ++void *nva3_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); ++void nva3_pm_clocks_set(struct drm_device *, void *); ++ ++/* nvc0_pm.c */ ++int nvc0_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); + + /* nouveau_temp.c */ + void nouveau_temp_init(struct drm_device *dev); +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_state.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_state.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_state.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_state.c 2011-06-26 07:59:23.000000000 +0200 +@@ -91,6 +91,7 @@ + engine->pm.clock_pre = nv04_pm_clock_pre; + engine->pm.clock_set = nv04_pm_clock_set; + engine->vram.init = nouveau_mem_detect; ++ engine->vram.takedown = nouveau_stub_takedown; + engine->vram.flags_valid = nouveau_mem_flags_valid; + break; + case 0x10: +@@ -139,6 +140,7 @@ + engine->pm.clock_pre = nv04_pm_clock_pre; + engine->pm.clock_set = nv04_pm_clock_set; + engine->vram.init = nouveau_mem_detect; ++ engine->vram.takedown = nouveau_stub_takedown; + engine->vram.flags_valid = nouveau_mem_flags_valid; + break; + case 0x20: +@@ -187,6 +189,7 @@ + engine->pm.clock_pre = nv04_pm_clock_pre; + engine->pm.clock_set = nv04_pm_clock_set; + engine->vram.init = nouveau_mem_detect; ++ engine->vram.takedown = nouveau_stub_takedown; + engine->vram.flags_valid = nouveau_mem_flags_valid; + break; + case 0x30: +@@ -237,6 +240,7 @@ + engine->pm.voltage_get = nouveau_voltage_gpio_get; + engine->pm.voltage_set = nouveau_voltage_gpio_set; + engine->vram.init = nouveau_mem_detect; ++ engine->vram.takedown = nouveau_stub_takedown; + engine->vram.flags_valid = nouveau_mem_flags_valid; + break; + case 0x40: +@@ -289,6 +293,7 @@ + engine->pm.voltage_set = nouveau_voltage_gpio_set; + engine->pm.temp_get = nv40_temp_get; + engine->vram.init = nouveau_mem_detect; ++ engine->vram.takedown = nouveau_stub_takedown; + engine->vram.flags_valid = nouveau_mem_flags_valid; + break; + case 0x50: +@@ -354,9 +359,9 @@ + 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; ++ engine->pm.clocks_get = nva3_pm_clocks_get; ++ engine->pm.clocks_pre = nva3_pm_clocks_pre; ++ engine->pm.clocks_set = nva3_pm_clocks_set; + break; + } + engine->pm.voltage_get = nouveau_voltage_gpio_get; +@@ -366,6 +371,7 @@ + else + engine->pm.temp_get = nv40_temp_get; + engine->vram.init = nv50_vram_init; ++ engine->vram.takedown = nv50_vram_fini; + engine->vram.get = nv50_vram_new; + engine->vram.put = nv50_vram_del; + engine->vram.flags_valid = nv50_vram_flags_valid; +@@ -412,9 +418,14 @@ + engine->gpio.irq_unregister = nv50_gpio_irq_unregister; + engine->gpio.irq_enable = nv50_gpio_irq_enable; + engine->vram.init = nvc0_vram_init; ++ engine->vram.takedown = nv50_vram_fini; + engine->vram.get = nvc0_vram_new; + engine->vram.put = nv50_vram_del; + engine->vram.flags_valid = nvc0_vram_flags_valid; ++ engine->pm.temp_get = nv84_temp_get; ++ engine->pm.clocks_get = nvc0_pm_clocks_get; ++ engine->pm.voltage_get = nouveau_voltage_gpio_get; ++ engine->pm.voltage_set = nouveau_voltage_gpio_set; + break; + default: + NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); +@@ -448,8 +459,8 @@ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + +- ret = nouveau_channel_alloc(dev, &dev_priv->channel, +- (struct drm_file *)-2, NvDmaFB, NvDmaTT); ++ ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL, ++ NvDmaFB, NvDmaTT); + if (ret) + return ret; + +@@ -528,7 +539,7 @@ + + nouveau_pm_init(dev); + +- ret = nouveau_mem_vram_init(dev); ++ ret = engine->vram.init(dev); + if (ret) + goto out_bios; + +@@ -540,10 +551,14 @@ + if (ret) + goto out_gpuobj; + +- ret = nouveau_mem_gart_init(dev); ++ ret = nouveau_mem_vram_init(dev); + if (ret) + goto out_instmem; + ++ ret = nouveau_mem_gart_init(dev); ++ if (ret) ++ goto out_ttmvram; ++ + /* PMC */ + ret = engine->mc.init(dev); + if (ret) +@@ -564,7 +579,7 @@ + if (ret) + goto out_timer; + +- if (!nouveau_noaccel) { ++ if (!dev_priv->noaccel) { + switch (dev_priv->card_type) { + case NV_04: + nv04_graph_create(dev); +@@ -619,8 +634,11 @@ + break; + } + +- if (dev_priv->card_type == NV_40) +- nv40_mpeg_create(dev); ++ if (dev_priv->card_type == NV_40 || ++ dev_priv->chipset == 0x31 || ++ dev_priv->chipset == 0x34 || ++ dev_priv->chipset == 0x36) ++ nv31_mpeg_create(dev); + else + if (dev_priv->card_type == NV_50 && + (dev_priv->chipset < 0x98 || dev_priv->chipset == 0xa0)) +@@ -676,10 +694,10 @@ + drm_vblank_cleanup(dev); + engine->display.destroy(dev); + out_fifo: +- if (!nouveau_noaccel) ++ if (!dev_priv->noaccel) + engine->fifo.takedown(dev); + out_engine: +- if (!nouveau_noaccel) { ++ if (!dev_priv->noaccel) { + for (e = e - 1; e >= 0; e--) { + if (!dev_priv->eng[e]) + continue; +@@ -697,12 +715,14 @@ + engine->mc.takedown(dev); + out_gart: + nouveau_mem_gart_fini(dev); ++out_ttmvram: ++ nouveau_mem_vram_fini(dev); + out_instmem: + engine->instmem.takedown(dev); + out_gpuobj: + nouveau_gpuobj_takedown(dev); + out_vram: +- nouveau_mem_vram_fini(dev); ++ engine->vram.takedown(dev); + out_bios: + nouveau_pm_fini(dev); + nouveau_bios_takedown(dev); +@@ -719,12 +739,17 @@ + struct nouveau_engine *engine = &dev_priv->engine; + int e; + ++ drm_kms_helper_poll_fini(dev); ++ nouveau_fbcon_fini(dev); ++ + if (dev_priv->channel) { +- nouveau_fence_fini(dev); + nouveau_channel_put_unlocked(&dev_priv->channel); ++ nouveau_fence_fini(dev); + } + +- if (!nouveau_noaccel) { ++ engine->display.destroy(dev); ++ ++ if (!dev_priv->noaccel) { + engine->fifo.takedown(dev); + for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { + if (dev_priv->eng[e]) { +@@ -749,10 +774,11 @@ + ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); + mutex_unlock(&dev->struct_mutex); + nouveau_mem_gart_fini(dev); ++ nouveau_mem_vram_fini(dev); + + engine->instmem.takedown(dev); + nouveau_gpuobj_takedown(dev); +- nouveau_mem_vram_fini(dev); ++ engine->vram.takedown(dev); + + nouveau_irq_fini(dev); + drm_vblank_cleanup(dev); +@@ -763,6 +789,41 @@ + vga_client_register(dev->pdev, NULL, NULL, NULL); + } + ++int ++nouveau_open(struct drm_device *dev, struct drm_file *file_priv) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_fpriv *fpriv; ++ int ret; ++ ++ fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL); ++ if (unlikely(!fpriv)) ++ return -ENOMEM; ++ ++ spin_lock_init(&fpriv->lock); ++ INIT_LIST_HEAD(&fpriv->channels); ++ ++ if (dev_priv->card_type == NV_50) { ++ ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL, ++ &fpriv->vm); ++ if (ret) { ++ kfree(fpriv); ++ return ret; ++ } ++ } else ++ if (dev_priv->card_type >= NV_C0) { ++ ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, ++ &fpriv->vm); ++ if (ret) { ++ kfree(fpriv); ++ return ret; ++ } ++ } ++ ++ file_priv->driver_priv = fpriv; ++ return 0; ++} ++ + /* here a client dies, release the stuff that was allocated for its + * file_priv */ + void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv) +@@ -770,6 +831,14 @@ + nouveau_channel_cleanup(dev, file_priv); + } + ++void ++nouveau_postclose(struct drm_device *dev, struct drm_file *file_priv) ++{ ++ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); ++ nouveau_vm_ref(NULL, &fpriv->vm, NULL); ++ kfree(fpriv); ++} ++ + /* first module load, setup the mmio/fb mapping */ + /* KMS: we need mmio at load time, not when the first drm client opens. */ + int nouveau_firstopen(struct drm_device *dev) +@@ -935,6 +1004,25 @@ + NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", + dev_priv->card_type, reg0); + ++ /* Determine whether we'll attempt acceleration or not, some ++ * cards are disabled by default here due to them being known ++ * non-functional, or never been tested due to lack of hw. ++ */ ++ dev_priv->noaccel = !!nouveau_noaccel; ++ if (nouveau_noaccel == -1) { ++ switch (dev_priv->chipset) { ++ case 0xc1: /* known broken */ ++ case 0xc8: /* never tested */ ++ NV_INFO(dev, "acceleration disabled by default, pass " ++ "noaccel=0 to force enable\n"); ++ dev_priv->noaccel = true; ++ break; ++ default: ++ dev_priv->noaccel = false; ++ break; ++ } ++ } ++ + ret = nouveau_remove_conflicting_drivers(dev); + if (ret) + goto err_mmio; +@@ -999,11 +1087,7 @@ + int nouveau_unload(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_engine *engine = &dev_priv->engine; + +- drm_kms_helper_poll_fini(dev); +- nouveau_fbcon_fini(dev); +- engine->display.destroy(dev); + nouveau_card_takedown(dev); + + iounmap(dev_priv->mmio); +@@ -1122,6 +1206,23 @@ + return false; + } + ++/* Wait until cond(data) == true, up until timeout has hit */ ++bool ++nouveau_wait_cb(struct drm_device *dev, u64 timeout, ++ bool (*cond)(void *), void *data) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; ++ u64 start = ptimer->read(dev); ++ ++ do { ++ if (cond(data) == true) ++ return true; ++ } while (ptimer->read(dev) - start < timeout); ++ ++ return false; ++} ++ + /* Waits for PGRAPH to go completely idle */ + bool nouveau_wait_for_idle(struct drm_device *dev) + { +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_temp.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_temp.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_temp.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_temp.c 2011-06-26 07:59:23.000000000 +0200 +@@ -43,7 +43,7 @@ + + /* Set the default sensor's contants */ + sensor->offset_constant = 0; +- sensor->offset_mult = 1; ++ sensor->offset_mult = 0; + sensor->offset_div = 1; + sensor->slope_mult = 1; + sensor->slope_div = 1; +@@ -99,6 +99,13 @@ + sensor->slope_mult = 431; + sensor->slope_div = 10000; + break; ++ ++ case 0x67: ++ sensor->offset_mult = -26149; ++ sensor->offset_div = 100; ++ sensor->slope_mult = 484; ++ sensor->slope_div = 10000; ++ break; + } + } + +@@ -109,7 +116,7 @@ + + /* Read the entries from the table */ + for (i = 0; i < entries; i++) { +- u16 value = ROM16(temp[1]); ++ s16 value = ROM16(temp[1]); + + switch (temp[0]) { + case 0x01: +@@ -160,8 +167,8 @@ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; +- u32 offset = sensor->offset_mult / sensor->offset_div; +- u32 sensor_calibration; ++ s32 offset = sensor->offset_mult / sensor->offset_div; ++ s32 sensor_calibration; + + /* set up the sensors */ + sensor_calibration = 120 - offset - sensor->offset_constant; +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_vm.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_vm.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_vm.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_vm.c 2011-06-26 07:59:23.000000000 +0200 +@@ -369,23 +369,26 @@ + } + + static void +-nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd) ++nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd) + { + struct nouveau_vm_pgd *vpgd, *tmp; ++ struct nouveau_gpuobj *pgd = NULL; + +- if (!pgd) ++ if (!mpgd) + return; + + mutex_lock(&vm->mm->mutex); + list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { +- if (vpgd->obj != pgd) +- continue; +- +- list_del(&vpgd->head); +- nouveau_gpuobj_ref(NULL, &vpgd->obj); +- kfree(vpgd); ++ if (vpgd->obj == mpgd) { ++ pgd = vpgd->obj; ++ list_del(&vpgd->head); ++ kfree(vpgd); ++ break; ++ } + } + mutex_unlock(&vm->mm->mutex); ++ ++ nouveau_gpuobj_ref(NULL, &pgd); + } + + static void +@@ -396,8 +399,8 @@ + list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { + nouveau_vm_unlink(vm, vpgd->obj); + } +- WARN_ON(nouveau_mm_fini(&vm->mm) != 0); + ++ nouveau_mm_fini(&vm->mm); + kfree(vm->pgt); + kfree(vm); + } +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_vm.h linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_vm.h +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_vm.h 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_vm.h 2011-06-26 07:59:23.000000000 +0200 +@@ -41,6 +41,8 @@ + }; + + struct nouveau_vma { ++ struct list_head head; ++ int refcount; + struct nouveau_vm *vm; + struct nouveau_mm_node *node; + u64 offset; +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_volt.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_volt.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nouveau_volt.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nouveau_volt.c 2011-06-26 07:59:23.000000000 +0200 +@@ -27,7 +27,7 @@ + #include "nouveau_drv.h" + #include "nouveau_pm.h" + +-static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a }; ++static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 }; + static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); + + int +@@ -170,6 +170,13 @@ + */ + vidshift = 2; + break; ++ case 0x40: ++ headerlen = volt[1]; ++ recordlen = volt[2]; ++ entries = volt[3]; /* not a clue what the entries are for.. */ ++ vidmask = volt[11]; /* guess.. */ ++ vidshift = 0; ++ break; + default: + NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]); + return; +@@ -197,16 +204,37 @@ + } + + /* parse vbios entries into common format */ +- voltage->level = kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL); +- if (!voltage->level) +- return; ++ voltage->version = volt[0]; ++ if (voltage->version < 0x40) { ++ voltage->nr_level = entries; ++ voltage->level = ++ kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL); ++ if (!voltage->level) ++ return; + +- entry = volt + headerlen; +- for (i = 0; i < entries; i++, entry += recordlen) { +- voltage->level[i].voltage = entry[0]; +- voltage->level[i].vid = entry[1] >> vidshift; ++ entry = volt + headerlen; ++ for (i = 0; i < entries; i++, entry += recordlen) { ++ voltage->level[i].voltage = entry[0] * 10000; ++ voltage->level[i].vid = entry[1] >> vidshift; ++ } ++ } else { ++ u32 volt_uv = ROM32(volt[4]); ++ s16 step_uv = ROM16(volt[8]); ++ u8 vid; ++ ++ voltage->nr_level = voltage->vid_mask + 1; ++ voltage->level = kcalloc(voltage->nr_level, ++ sizeof(*voltage->level), GFP_KERNEL); ++ if (!voltage->level) ++ return; ++ ++ for (vid = 0; vid <= voltage->vid_mask; vid++) { ++ voltage->level[vid].voltage = volt_uv; ++ voltage->level[vid].vid = vid; ++ volt_uv += step_uv; ++ } + } +- voltage->nr_level = entries; ++ + voltage->supported = true; + } + +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nv04_crtc.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv04_crtc.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nv04_crtc.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv04_crtc.c 2011-06-26 07:59:23.000000000 +0200 +@@ -1035,7 +1035,7 @@ + drm_crtc_helper_add(&nv_crtc->base, &nv04_crtc_helper_funcs); + drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); + +- ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, ++ ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, + 0, 0x0000, &nv_crtc->cursor.nvbo); + if (!ret) { + ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nv04_instmem.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv04_instmem.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nv04_instmem.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv04_instmem.c 2011-06-26 07:59:23.000000000 +0200 +@@ -28,6 +28,31 @@ + /* RAMIN always available */ + dev_priv->ramin_available = true; + ++ /* Reserve space at end of VRAM for PRAMIN */ ++ if (dev_priv->card_type >= NV_40) { ++ u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8); ++ u32 rsvd; ++ ++ /* estimate grctx size, the magics come from nv40_grctx.c */ ++ if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs; ++ else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs; ++ else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs; ++ else rsvd = 0x4a40 * vs; ++ rsvd += 16 * 1024; ++ rsvd *= dev_priv->engine.fifo.channels; ++ ++ /* pciegart table */ ++ if (drm_pci_device_is_pcie(dev)) ++ rsvd += 512 * 1024; ++ ++ /* object storage */ ++ rsvd += 512 * 1024; ++ ++ dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096); ++ } else { ++ dev_priv->ramin_rsvd_vram = 512 * 1024; ++ } ++ + /* Setup shared RAMHT */ + ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096, + NVOBJ_FLAG_ZERO_ALLOC, &ramht); +@@ -112,7 +137,8 @@ + } + + int +-nv04_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align) ++nv04_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, ++ u32 size, u32 align) + { + struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; + struct drm_mm_node *ramin = NULL; +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nv31_mpeg.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv31_mpeg.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nv31_mpeg.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv31_mpeg.c 2011-06-26 07:59:23.000000000 +0200 +@@ -0,0 +1,344 @@ ++/* ++ * Copyright 2011 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_ramht.h" ++ ++struct nv31_mpeg_engine { ++ struct nouveau_exec_engine base; ++ atomic_t refcount; ++}; ++ ++ ++static int ++nv31_mpeg_context_new(struct nouveau_channel *chan, int engine) ++{ ++ struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); ++ ++ if (!atomic_add_unless(&pmpeg->refcount, 1, 1)) ++ return -EBUSY; ++ ++ chan->engctx[engine] = (void *)0xdeadcafe; ++ return 0; ++} ++ ++static void ++nv31_mpeg_context_del(struct nouveau_channel *chan, int engine) ++{ ++ struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); ++ atomic_dec(&pmpeg->refcount); ++ chan->engctx[engine] = NULL; ++} ++ ++static int ++nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) ++{ ++ struct drm_device *dev = chan->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpuobj *ctx = NULL; ++ unsigned long flags; ++ int ret; ++ ++ NV_DEBUG(dev, "ch%d\n", chan->id); ++ ++ ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC | ++ NVOBJ_FLAG_ZERO_FREE, &ctx); ++ if (ret) ++ return ret; ++ ++ nv_wo32(ctx, 0x78, 0x02001ec1); ++ ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ nv_mask(dev, 0x002500, 0x00000001, 0x00000000); ++ if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id) ++ nv_wr32(dev, 0x00330c, ctx->pinst >> 4); ++ nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4); ++ nv_mask(dev, 0x002500, 0x00000001, 0x00000001); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); ++ ++ chan->engctx[engine] = ctx; ++ return 0; ++} ++ ++static void ++nv40_mpeg_context_del(struct nouveau_channel *chan, int engine) ++{ ++ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; ++ struct nouveau_gpuobj *ctx = chan->engctx[engine]; ++ struct drm_device *dev = chan->dev; ++ unsigned long flags; ++ u32 inst = 0x80000000 | (ctx->pinst >> 4); ++ ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); ++ if (nv_rd32(dev, 0x00b318) == inst) ++ nv_mask(dev, 0x00b318, 0x80000000, 0x00000000); ++ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); ++ ++ nouveau_gpuobj_ref(NULL, &ctx); ++ chan->engctx[engine] = NULL; ++} ++ ++static int ++nv31_mpeg_object_new(struct nouveau_channel *chan, int engine, ++ u32 handle, u16 class) ++{ ++ struct drm_device *dev = chan->dev; ++ struct nouveau_gpuobj *obj = NULL; ++ int ret; ++ ++ ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC | ++ NVOBJ_FLAG_ZERO_FREE, &obj); ++ if (ret) ++ return ret; ++ obj->engine = 2; ++ obj->class = class; ++ ++ nv_wo32(obj, 0x00, class); ++ ++ ret = nouveau_ramht_insert(chan, handle, obj); ++ nouveau_gpuobj_ref(NULL, &obj); ++ return ret; ++} ++ ++static int ++nv31_mpeg_init(struct drm_device *dev, int engine) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); ++ int i; ++ ++ /* VPE init */ ++ nv_mask(dev, 0x000200, 0x00000002, 0x00000000); ++ nv_mask(dev, 0x000200, 0x00000002, 0x00000002); ++ nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ ++ nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ ++ ++ for (i = 0; i < dev_priv->engine.fb.num_tiles; i++) ++ pmpeg->base.set_tile_region(dev, i); ++ ++ /* PMPEG init */ ++ nv_wr32(dev, 0x00b32c, 0x00000000); ++ nv_wr32(dev, 0x00b314, 0x00000100); ++ nv_wr32(dev, 0x00b220, nv44_graph_class(dev) ? 0x00000044 : 0x00000031); ++ nv_wr32(dev, 0x00b300, 0x02001ec1); ++ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); ++ ++ nv_wr32(dev, 0x00b100, 0xffffffff); ++ nv_wr32(dev, 0x00b140, 0xffffffff); ++ ++ if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { ++ NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); ++ return -EBUSY; ++ } ++ ++ return 0; ++} ++ ++static int ++nv31_mpeg_fini(struct drm_device *dev, int engine) ++{ ++ /*XXX: context save? */ ++ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); ++ nv_wr32(dev, 0x00b140, 0x00000000); ++ return 0; ++} ++ ++static int ++nv31_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) ++{ ++ struct drm_device *dev = chan->dev; ++ u32 inst = data << 4; ++ u32 dma0 = nv_ri32(dev, inst + 0); ++ u32 dma1 = nv_ri32(dev, inst + 4); ++ u32 dma2 = nv_ri32(dev, inst + 8); ++ u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); ++ u32 size = dma1 + 1; ++ ++ /* only allow linear DMA objects */ ++ if (!(dma0 & 0x00002000)) ++ return -EINVAL; ++ ++ if (mthd == 0x0190) { ++ /* DMA_CMD */ ++ nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000)); ++ nv_wr32(dev, 0x00b334, base); ++ nv_wr32(dev, 0x00b324, size); ++ } else ++ if (mthd == 0x01a0) { ++ /* DMA_DATA */ ++ nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); ++ nv_wr32(dev, 0x00b360, base); ++ nv_wr32(dev, 0x00b364, size); ++ } else { ++ /* DMA_IMAGE, VRAM only */ ++ if (dma0 & 0x000c0000) ++ return -EINVAL; ++ ++ nv_wr32(dev, 0x00b370, base); ++ nv_wr32(dev, 0x00b374, size); ++ } ++ ++ return 0; ++} ++ ++static int ++nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpuobj *ctx; ++ unsigned long flags; ++ int i; ++ ++ /* hardcode drm channel id on nv3x, so swmthd lookup works */ ++ if (dev_priv->card_type < NV_40) ++ return 0; ++ ++ spin_lock_irqsave(&dev_priv->channels.lock, flags); ++ for (i = 0; i < dev_priv->engine.fifo.channels; i++) { ++ if (!dev_priv->channels.ptr[i]) ++ continue; ++ ++ ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG]; ++ if (ctx && ctx->pinst == inst) ++ break; ++ } ++ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); ++ return i; ++} ++ ++static void ++nv31_vpe_set_tile_region(struct drm_device *dev, int i) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; ++ ++ nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); ++ nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); ++ nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); ++} ++ ++static void ++nv31_mpeg_isr(struct drm_device *dev) ++{ ++ u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4; ++ u32 chid = nv31_mpeg_isr_chid(dev, inst); ++ u32 stat = nv_rd32(dev, 0x00b100); ++ u32 type = nv_rd32(dev, 0x00b230); ++ u32 mthd = nv_rd32(dev, 0x00b234); ++ u32 data = nv_rd32(dev, 0x00b238); ++ u32 show = stat; ++ ++ if (stat & 0x01000000) { ++ /* happens on initial binding of the object */ ++ if (type == 0x00000020 && mthd == 0x0000) { ++ nv_mask(dev, 0x00b308, 0x00000000, 0x00000000); ++ show &= ~0x01000000; ++ } ++ ++ if (type == 0x00000010) { ++ if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data)) ++ show &= ~0x01000000; ++ } ++ } ++ ++ nv_wr32(dev, 0x00b100, stat); ++ nv_wr32(dev, 0x00b230, 0x00000001); ++ ++ if (show && nouveau_ratelimit()) { ++ NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", ++ chid, inst, stat, type, mthd, data); ++ } ++} ++ ++static void ++nv31_vpe_isr(struct drm_device *dev) ++{ ++ if (nv_rd32(dev, 0x00b100)) ++ nv31_mpeg_isr(dev); ++ ++ if (nv_rd32(dev, 0x00b800)) { ++ u32 stat = nv_rd32(dev, 0x00b800); ++ NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); ++ nv_wr32(dev, 0xb800, stat); ++ } ++} ++ ++static void ++nv31_mpeg_destroy(struct drm_device *dev, int engine) ++{ ++ struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); ++ ++ nouveau_irq_unregister(dev, 0); ++ ++ NVOBJ_ENGINE_DEL(dev, MPEG); ++ kfree(pmpeg); ++} ++ ++int ++nv31_mpeg_create(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv31_mpeg_engine *pmpeg; ++ ++ pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); ++ if (!pmpeg) ++ return -ENOMEM; ++ atomic_set(&pmpeg->refcount, 0); ++ ++ pmpeg->base.destroy = nv31_mpeg_destroy; ++ pmpeg->base.init = nv31_mpeg_init; ++ pmpeg->base.fini = nv31_mpeg_fini; ++ if (dev_priv->card_type < NV_40) { ++ pmpeg->base.context_new = nv31_mpeg_context_new; ++ pmpeg->base.context_del = nv31_mpeg_context_del; ++ } else { ++ pmpeg->base.context_new = nv40_mpeg_context_new; ++ pmpeg->base.context_del = nv40_mpeg_context_del; ++ } ++ pmpeg->base.object_new = nv31_mpeg_object_new; ++ ++ /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between ++ * all VPE engines, for this driver's purposes the PMPEG engine ++ * will be treated as the "master" and handle the global VPE ++ * bits too ++ */ ++ pmpeg->base.set_tile_region = nv31_vpe_set_tile_region; ++ nouveau_irq_register(dev, 0, nv31_vpe_isr); ++ ++ NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); ++ NVOBJ_CLASS(dev, 0x3174, MPEG); ++ NVOBJ_MTHD (dev, 0x3174, 0x0190, nv31_mpeg_mthd_dma); ++ NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv31_mpeg_mthd_dma); ++ NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv31_mpeg_mthd_dma); ++ ++#if 0 ++ NVOBJ_ENGINE_ADD(dev, ME, &pme->base); ++ NVOBJ_CLASS(dev, 0x4075, ME); ++#endif ++ return 0; ++ ++} +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nv40_mpeg.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv40_mpeg.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nv40_mpeg.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv40_mpeg.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,311 +0,0 @@ +-/* +- * Copyright 2011 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_ramht.h" +- +-struct nv40_mpeg_engine { +- struct nouveau_exec_engine base; +-}; +- +-static int +-nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) +-{ +- struct drm_device *dev = chan->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpuobj *ctx = NULL; +- unsigned long flags; +- int ret; +- +- NV_DEBUG(dev, "ch%d\n", chan->id); +- +- ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC | +- NVOBJ_FLAG_ZERO_FREE, &ctx); +- if (ret) +- return ret; +- +- nv_wo32(ctx, 0x78, 0x02001ec1); +- +- spin_lock_irqsave(&dev_priv->context_switch_lock, flags); +- nv_mask(dev, 0x002500, 0x00000001, 0x00000000); +- if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id) +- nv_wr32(dev, 0x00330c, ctx->pinst >> 4); +- nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4); +- nv_mask(dev, 0x002500, 0x00000001, 0x00000001); +- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +- +- chan->engctx[engine] = ctx; +- return 0; +-} +- +-static void +-nv40_mpeg_context_del(struct nouveau_channel *chan, int engine) +-{ +- struct drm_nouveau_private *dev_priv = chan->dev->dev_private; +- struct nouveau_gpuobj *ctx = chan->engctx[engine]; +- struct drm_device *dev = chan->dev; +- unsigned long flags; +- u32 inst = 0x80000000 | (ctx->pinst >> 4); +- +- spin_lock_irqsave(&dev_priv->context_switch_lock, flags); +- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); +- if (nv_rd32(dev, 0x00b318) == inst) +- nv_mask(dev, 0x00b318, 0x80000000, 0x00000000); +- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); +- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +- +- nouveau_gpuobj_ref(NULL, &ctx); +- chan->engctx[engine] = NULL; +-} +- +-static int +-nv40_mpeg_object_new(struct nouveau_channel *chan, int engine, +- u32 handle, u16 class) +-{ +- struct drm_device *dev = chan->dev; +- struct nouveau_gpuobj *obj = NULL; +- int ret; +- +- ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC | +- NVOBJ_FLAG_ZERO_FREE, &obj); +- if (ret) +- return ret; +- obj->engine = 2; +- obj->class = class; +- +- nv_wo32(obj, 0x00, class); +- +- ret = nouveau_ramht_insert(chan, handle, obj); +- nouveau_gpuobj_ref(NULL, &obj); +- return ret; +-} +- +-static int +-nv40_mpeg_init(struct drm_device *dev, int engine) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine); +- int i; +- +- /* VPE init */ +- nv_mask(dev, 0x000200, 0x00000002, 0x00000000); +- nv_mask(dev, 0x000200, 0x00000002, 0x00000002); +- nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ +- nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ +- +- for (i = 0; i < dev_priv->engine.fb.num_tiles; i++) +- pmpeg->base.set_tile_region(dev, i); +- +- /* PMPEG init */ +- nv_wr32(dev, 0x00b32c, 0x00000000); +- nv_wr32(dev, 0x00b314, 0x00000100); +- nv_wr32(dev, 0x00b220, 0x00000044); +- nv_wr32(dev, 0x00b300, 0x02001ec1); +- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); +- +- nv_wr32(dev, 0x00b100, 0xffffffff); +- nv_wr32(dev, 0x00b140, 0xffffffff); +- +- if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { +- NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); +- return -EBUSY; +- } +- +- return 0; +-} +- +-static int +-nv40_mpeg_fini(struct drm_device *dev, int engine) +-{ +- /*XXX: context save? */ +- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); +- nv_wr32(dev, 0x00b140, 0x00000000); +- return 0; +-} +- +-static int +-nv40_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) +-{ +- struct drm_device *dev = chan->dev; +- u32 inst = data << 4; +- u32 dma0 = nv_ri32(dev, inst + 0); +- u32 dma1 = nv_ri32(dev, inst + 4); +- u32 dma2 = nv_ri32(dev, inst + 8); +- u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); +- u32 size = dma1 + 1; +- +- /* only allow linear DMA objects */ +- if (!(dma0 & 0x00002000)) +- return -EINVAL; +- +- if (mthd == 0x0190) { +- /* DMA_CMD */ +- nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000)); +- nv_wr32(dev, 0x00b334, base); +- nv_wr32(dev, 0x00b324, size); +- } else +- if (mthd == 0x01a0) { +- /* DMA_DATA */ +- nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); +- nv_wr32(dev, 0x00b360, base); +- nv_wr32(dev, 0x00b364, size); +- } else { +- /* DMA_IMAGE, VRAM only */ +- if (dma0 & 0x000c0000) +- return -EINVAL; +- +- nv_wr32(dev, 0x00b370, base); +- nv_wr32(dev, 0x00b374, size); +- } +- +- return 0; +-} +- +-static int +-nv40_mpeg_isr_chid(struct drm_device *dev, u32 inst) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpuobj *ctx; +- unsigned long flags; +- int i; +- +- spin_lock_irqsave(&dev_priv->channels.lock, flags); +- for (i = 0; i < dev_priv->engine.fifo.channels; i++) { +- if (!dev_priv->channels.ptr[i]) +- continue; +- +- ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG]; +- if (ctx && ctx->pinst == inst) +- break; +- } +- spin_unlock_irqrestore(&dev_priv->channels.lock, flags); +- return i; +-} +- +-static void +-nv40_vpe_set_tile_region(struct drm_device *dev, int i) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; +- +- nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); +- nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); +- nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); +-} +- +-static void +-nv40_mpeg_isr(struct drm_device *dev) +-{ +- u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4; +- u32 chid = nv40_mpeg_isr_chid(dev, inst); +- u32 stat = nv_rd32(dev, 0x00b100); +- u32 type = nv_rd32(dev, 0x00b230); +- u32 mthd = nv_rd32(dev, 0x00b234); +- u32 data = nv_rd32(dev, 0x00b238); +- u32 show = stat; +- +- if (stat & 0x01000000) { +- /* happens on initial binding of the object */ +- if (type == 0x00000020 && mthd == 0x0000) { +- nv_mask(dev, 0x00b308, 0x00000000, 0x00000000); +- show &= ~0x01000000; +- } +- +- if (type == 0x00000010) { +- if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data)) +- show &= ~0x01000000; +- } +- } +- +- nv_wr32(dev, 0x00b100, stat); +- nv_wr32(dev, 0x00b230, 0x00000001); +- +- if (show && nouveau_ratelimit()) { +- NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", +- chid, inst, stat, type, mthd, data); +- } +-} +- +-static void +-nv40_vpe_isr(struct drm_device *dev) +-{ +- if (nv_rd32(dev, 0x00b100)) +- nv40_mpeg_isr(dev); +- +- if (nv_rd32(dev, 0x00b800)) { +- u32 stat = nv_rd32(dev, 0x00b800); +- NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); +- nv_wr32(dev, 0xb800, stat); +- } +-} +- +-static void +-nv40_mpeg_destroy(struct drm_device *dev, int engine) +-{ +- struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine); +- +- nouveau_irq_unregister(dev, 0); +- +- NVOBJ_ENGINE_DEL(dev, MPEG); +- kfree(pmpeg); +-} +- +-int +-nv40_mpeg_create(struct drm_device *dev) +-{ +- struct nv40_mpeg_engine *pmpeg; +- +- pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); +- if (!pmpeg) +- return -ENOMEM; +- +- pmpeg->base.destroy = nv40_mpeg_destroy; +- pmpeg->base.init = nv40_mpeg_init; +- pmpeg->base.fini = nv40_mpeg_fini; +- pmpeg->base.context_new = nv40_mpeg_context_new; +- pmpeg->base.context_del = nv40_mpeg_context_del; +- pmpeg->base.object_new = nv40_mpeg_object_new; +- +- /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between +- * all VPE engines, for this driver's purposes the PMPEG engine +- * will be treated as the "master" and handle the global VPE +- * bits too +- */ +- pmpeg->base.set_tile_region = nv40_vpe_set_tile_region; +- nouveau_irq_register(dev, 0, nv40_vpe_isr); +- +- NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); +- NVOBJ_CLASS(dev, 0x3174, MPEG); +- NVOBJ_MTHD (dev, 0x3174, 0x0190, nv40_mpeg_mthd_dma); +- NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv40_mpeg_mthd_dma); +- NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv40_mpeg_mthd_dma); +- +-#if 0 +- NVOBJ_ENGINE_ADD(dev, ME, &pme->base); +- NVOBJ_CLASS(dev, 0x4075, ME); +-#endif +- return 0; +- +-} +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_crtc.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_crtc.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_crtc.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_crtc.c 2011-06-26 07:59:23.000000000 +0200 +@@ -104,7 +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.start << PAGE_SHIFT) >> 8); ++ OUT_RING(evo, nv_crtc->lut.nvbo->bo.offset >> 8); + if (dev_priv->chipset != 0x50) { + BEGIN_RING(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); + OUT_RING(evo, NvEvoVRAM); +@@ -372,7 +372,7 @@ + + nouveau_bo_unmap(cursor); + +- nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT); ++ nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset); + nv_crtc->cursor.show(nv_crtc, true); + + out: +@@ -546,7 +546,7 @@ + } + } + +- nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT; ++ nv_crtc->fb.offset = fb->nvbo->bo.offset; + nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo); + nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; + if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) { +@@ -747,7 +747,7 @@ + } + nv_crtc->lut.depth = 0; + +- ret = nouveau_bo_new(dev, NULL, 4096, 0x100, TTM_PL_FLAG_VRAM, ++ ret = nouveau_bo_new(dev, 4096, 0x100, TTM_PL_FLAG_VRAM, + 0, 0x0000, &nv_crtc->lut.nvbo); + if (!ret) { + ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); +@@ -773,7 +773,7 @@ + drm_crtc_helper_add(&nv_crtc->base, &nv50_crtc_helper_funcs); + drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); + +- ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, ++ ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, + 0, 0x0000, &nv_crtc->cursor.nvbo); + if (!ret) { + ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_display.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_display.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_display.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_display.c 2011-06-26 07:59:23.000000000 +0200 +@@ -415,8 +415,6 @@ + + /* synchronise with the rendering channel, if necessary */ + if (likely(chan)) { +- u64 offset = dispc->sem.bo->vma.offset + dispc->sem.offset; +- + ret = RING_SPACE(chan, 10); + if (ret) { + WIND_RING(evo); +@@ -438,6 +436,8 @@ + else + OUT_RING (chan, chan->vram_handle); + } else { ++ u64 offset = chan->dispc_vma[nv_crtc->index].offset; ++ offset += dispc->sem.offset; + BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); + OUT_RING (chan, upper_32_bits(offset)); + OUT_RING (chan, lower_32_bits(offset)); +@@ -484,7 +484,7 @@ + OUT_RING (evo, 0x00000000); + OUT_RING (evo, 0x00000000); + BEGIN_RING(evo, 0, 0x0800, 5); +- OUT_RING (evo, (nv_fb->nvbo->bo.mem.start << PAGE_SHIFT) >> 8); ++ OUT_RING (evo, nv_fb->nvbo->bo.offset >> 8); + OUT_RING (evo, 0); + OUT_RING (evo, (fb->height << 16) | fb->width); + OUT_RING (evo, nv_fb->r_pitch); +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_evo.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_evo.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_evo.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_evo.c 2011-06-26 07:59:23.000000000 +0200 +@@ -38,6 +38,7 @@ + return; + *pevo = NULL; + ++ nouveau_ramht_ref(NULL, &evo->ramht, evo); + nouveau_gpuobj_channel_takedown(evo); + nouveau_bo_unmap(evo->pushbuf_bo); + nouveau_bo_ref(NULL, &evo->pushbuf_bo); +@@ -116,7 +117,7 @@ + evo->user_get = 4; + evo->user_put = 0; + +- ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, ++ ret = nouveau_bo_new(dev, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, + &evo->pushbuf_bo); + if (ret == 0) + ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM); +@@ -153,7 +154,7 @@ + { + struct drm_device *dev = evo->dev; + int id = evo->id, ret, i; +- u64 pushbuf = evo->pushbuf_bo->bo.mem.start << PAGE_SHIFT; ++ u64 pushbuf = evo->pushbuf_bo->bo.offset; + u32 tmp; + + tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)); +@@ -331,16 +332,15 @@ + if (ret) + goto err; + +- ret = nouveau_bo_new(dev, NULL, 4096, 0x1000, TTM_PL_FLAG_VRAM, ++ ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, + 0, 0x0000, &dispc->sem.bo); + if (!ret) { +- offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT; +- + ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM); + if (!ret) + ret = nouveau_bo_map(dispc->sem.bo); + if (ret) + nouveau_bo_ref(NULL, &dispc->sem.bo); ++ offset = dispc->sem.bo->bo.offset; + } + + if (ret) +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_fbcon.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_fbcon.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_fbcon.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_fbcon.c 2011-06-26 07:59:23.000000000 +0200 +@@ -159,7 +159,7 @@ + struct drm_device *dev = nfbdev->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->channel; +- struct nouveau_bo *nvbo = nfbdev->nouveau_fb.nvbo; ++ struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb; + int ret, format; + + switch (info->var.bits_per_pixel) { +@@ -247,8 +247,8 @@ + OUT_RING(chan, info->fix.line_length); + OUT_RING(chan, info->var.xres_virtual); + OUT_RING(chan, info->var.yres_virtual); +- OUT_RING(chan, upper_32_bits(nvbo->vma.offset)); +- OUT_RING(chan, lower_32_bits(nvbo->vma.offset)); ++ OUT_RING(chan, upper_32_bits(fb->vma.offset)); ++ OUT_RING(chan, lower_32_bits(fb->vma.offset)); + BEGIN_RING(chan, NvSub2D, 0x0230, 2); + OUT_RING(chan, format); + OUT_RING(chan, 1); +@@ -256,8 +256,8 @@ + OUT_RING(chan, info->fix.line_length); + OUT_RING(chan, info->var.xres_virtual); + OUT_RING(chan, info->var.yres_virtual); +- OUT_RING(chan, upper_32_bits(nvbo->vma.offset)); +- OUT_RING(chan, lower_32_bits(nvbo->vma.offset)); ++ OUT_RING(chan, upper_32_bits(fb->vma.offset)); ++ OUT_RING(chan, lower_32_bits(fb->vma.offset)); + + return 0; + } +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_grctx.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_grctx.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_grctx.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_grctx.c 2011-06-26 07:59:23.000000000 +0200 +@@ -40,6 +40,9 @@ + #define CP_FLAG_UNK0B ((0 * 32) + 0xb) + #define CP_FLAG_UNK0B_CLEAR 0 + #define CP_FLAG_UNK0B_SET 1 ++#define CP_FLAG_STATE ((0 * 32) + 0x1c) ++#define CP_FLAG_STATE_STOPPED 0 ++#define CP_FLAG_STATE_RUNNING 1 + #define CP_FLAG_UNK1D ((0 * 32) + 0x1d) + #define CP_FLAG_UNK1D_CLEAR 0 + #define CP_FLAG_UNK1D_SET 1 +@@ -194,6 +197,8 @@ + "the devs.\n"); + return -ENOSYS; + } ++ ++ cp_set (ctx, STATE, RUNNING); + /* decide whether we're loading/unloading the context */ + cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save); + cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save); +@@ -260,6 +265,7 @@ + cp_name(ctx, cp_exit); + cp_set (ctx, USER_SAVE, NOT_PENDING); + cp_set (ctx, USER_LOAD, NOT_PENDING); ++ cp_set (ctx, STATE, STOPPED); + cp_out (ctx, CP_END); + ctx->ctxvals_pos += 0x400; /* padding... no idea why you need it */ + +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_instmem.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_instmem.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_instmem.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_instmem.c 2011-06-26 07:59:23.000000000 +0200 +@@ -305,9 +305,9 @@ + u32 align; + }; + +- + int +-nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align) ++nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, ++ u32 size, u32 align) + { + struct drm_device *dev = gpuobj->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +@@ -336,7 +336,7 @@ + if (!(gpuobj->flags & NVOBJ_FLAG_VM_USER)) + flags |= NV_MEM_ACCESS_SYS; + +- ret = nouveau_vm_get(dev_priv->chan_vm, size, 12, flags, ++ ret = nouveau_vm_get(chan->vm, size, 12, flags, + &node->chan_vma); + if (ret) { + vram->put(dev, &node->vram); +@@ -345,7 +345,7 @@ + } + + nouveau_vm_map(&node->chan_vma, node->vram); +- gpuobj->vinst = node->chan_vma.offset; ++ gpuobj->linst = node->chan_vma.offset; + } + + gpuobj->size = size; +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_vm.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_vm.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_vm.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_vm.c 2011-06-26 07:59:23.000000000 +0200 +@@ -156,7 +156,7 @@ + pinstmem->flush(vm->dev); + + /* BAR */ +- if (vm != dev_priv->chan_vm) { ++ if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) { + nv50_vm_flush_engine(vm->dev, 6); + return; + } +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_vram.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_vram.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nv50_vram.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nv50_vram.c 2011-06-26 07:59:23.000000000 +0200 +@@ -51,9 +51,7 @@ + nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; +- struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; +- struct nouveau_mm *mm = man->priv; ++ struct nouveau_mm *mm = dev_priv->engine.vram.mm; + struct nouveau_mm_node *this; + struct nouveau_mem *mem; + +@@ -84,9 +82,7 @@ + u32 memtype, struct nouveau_mem **pmem) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; +- struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; +- struct nouveau_mm *mm = man->priv; ++ struct nouveau_mm *mm = dev_priv->engine.vram.mm; + struct nouveau_mm_node *r; + struct nouveau_mem *mem; + int comp = (memtype & 0x300) >> 8; +@@ -190,22 +186,35 @@ + nv50_vram_init(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_vram_engine *vram = &dev_priv->engine.vram; ++ const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ ++ const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ ++ u32 rblock, length; + + dev_priv->vram_size = nv_rd32(dev, 0x10020c); + dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; + dev_priv->vram_size &= 0xffffffff00ULL; + +- switch (dev_priv->chipset) { +- case 0xaa: +- case 0xac: +- case 0xaf: ++ /* IGPs, no funky reordering happens here, they don't have VRAM */ ++ if (dev_priv->chipset == 0xaa || ++ dev_priv->chipset == 0xac || ++ dev_priv->chipset == 0xaf) { + dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12; +- dev_priv->vram_rblock_size = 4096; +- break; +- default: +- dev_priv->vram_rblock_size = nv50_vram_rblock(dev); +- break; ++ rblock = 4096 >> 12; ++ } else { ++ rblock = nv50_vram_rblock(dev) >> 12; + } + +- return 0; ++ length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; ++ ++ return nouveau_mm_init(&vram->mm, rsvd_head, length, rblock); ++} ++ ++void ++nv50_vram_fini(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_vram_engine *vram = &dev_priv->engine.vram; ++ ++ nouveau_mm_fini(&vram->mm); + } +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nva3_pm.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nva3_pm.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nva3_pm.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nva3_pm.c 2011-06-26 07:59:23.000000000 +0200 +@@ -27,178 +27,305 @@ + #include "nouveau_bios.h" + #include "nouveau_pm.h" + +-/* This is actually a lot more complex than it appears here, but hopefully +- * this should be able to deal with what the VBIOS leaves for us.. +- * +- * If not, well, I'll jump off that bridge when I come to it. +- */ ++static u32 read_clk(struct drm_device *, int, bool); ++static u32 read_pll(struct drm_device *, int, u32); + +-struct nva3_pm_state { +- enum pll_types type; +- u32 src0; +- u32 src1; +- u32 ctrl; +- u32 coef; +- u32 old_pnm; +- u32 new_pnm; +- u32 new_div; +-}; ++static u32 ++read_vco(struct drm_device *dev, int clk) ++{ ++ u32 sctl = nv_rd32(dev, 0x4120 + (clk * 4)); ++ if ((sctl & 0x00000030) != 0x00000030) ++ return read_pll(dev, 0x41, 0x00e820); ++ return read_pll(dev, 0x42, 0x00e8a0); ++} + +-static int +-nva3_pm_pll_offset(u32 id) ++static u32 ++read_clk(struct drm_device *dev, int clk, bool ignore_en) + { +- static const u32 pll_map[] = { +- 0x00, PLL_CORE, +- 0x01, PLL_SHADER, +- 0x02, PLL_MEMORY, +- 0x00, 0x00 +- }; +- const u32 *map = pll_map; +- +- while (map[1]) { +- if (id == map[1]) +- return map[0]; +- map += 2; ++ u32 sctl, sdiv, sclk; ++ ++ /* refclk for the 0xe8xx plls always 27KHz */ ++ if (clk >= 0x40) ++ return 27000; ++ ++ sctl = nv_rd32(dev, 0x4120 + (clk * 4)); ++ if (!ignore_en && !(sctl & 0x00000100)) ++ return 0; ++ ++ switch (sctl & 0x00003000) { ++ case 0x00000000: ++ return 27000; ++ case 0x00002000: ++ if (sctl & 0x00000040) ++ return 108000; ++ return 100000; ++ case 0x00003000: ++ sclk = read_vco(dev, clk); ++ sdiv = ((sctl & 0x003f0000) >> 16) + 2; ++ return (sclk * 2) / sdiv; ++ default: ++ return 0; + } ++} + +- return -ENOENT; ++static u32 ++read_pll(struct drm_device *dev, int clk, u32 pll) ++{ ++ u32 ctrl = nv_rd32(dev, pll + 0); ++ u32 sclk, P = 1, N = 1, M = 1; ++ ++ if (!(ctrl & 0x00000008)) { ++ u32 coef = nv_rd32(dev, pll + 4); ++ M = (coef & 0x000000ff) >> 0; ++ N = (coef & 0x0000ff00) >> 8; ++ P = (coef & 0x003f0000) >> 16; ++ ++ /* not post-divider on these.. */ ++ if ((pll & 0x00ff00) == 0x00e800) ++ P = 1; ++ ++ sclk = read_clk(dev, 0x00 + clk, false); ++ } else { ++ sclk = read_clk(dev, 0x10 + clk, false); ++ } ++ ++ return sclk * N / (M * P); + } + +-int +-nva3_pm_clock_get(struct drm_device *dev, u32 id) ++struct creg { ++ u32 clk; ++ u32 pll; ++}; ++ ++static int ++calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) + { +- u32 src0, src1, ctrl, coef; +- struct pll_lims pll; +- int ret, off; +- int P, N, M; ++ struct pll_lims limits; ++ u32 oclk, sclk, sdiv; ++ int P, N, M, diff; ++ int ret; ++ ++ reg->pll = 0; ++ reg->clk = 0; ++ if (!khz) { ++ NV_DEBUG(dev, "no clock for 0x%04x/0x%02x\n", pll, clk); ++ return 0; ++ } + +- ret = get_pll_limits(dev, id, &pll); ++ switch (khz) { ++ case 27000: ++ reg->clk = 0x00000100; ++ return khz; ++ case 100000: ++ reg->clk = 0x00002100; ++ return khz; ++ case 108000: ++ reg->clk = 0x00002140; ++ return khz; ++ default: ++ sclk = read_vco(dev, clk); ++ sdiv = min((sclk * 2) / (khz - 2999), (u32)65); ++ /* if the clock has a PLL attached, and we can get a within ++ * [-2, 3) MHz of a divider, we'll disable the PLL and use ++ * the divider instead. ++ * ++ * divider can go as low as 2, limited here because NVIDIA ++ * and the VBIOS on my NVA8 seem to prefer using the PLL ++ * for 810MHz - is there a good reason? ++ */ ++ if (sdiv > 4) { ++ oclk = (sclk * 2) / sdiv; ++ diff = khz - oclk; ++ if (!pll || (diff >= -2000 && diff < 3000)) { ++ reg->clk = (((sdiv - 2) << 16) | 0x00003100); ++ return oclk; ++ } ++ } ++ ++ if (!pll) { ++ NV_ERROR(dev, "bad freq %02x: %d %d\n", clk, khz, sclk); ++ return -ERANGE; ++ } ++ ++ break; ++ } ++ ++ ret = get_pll_limits(dev, pll, &limits); + if (ret) + return ret; + +- off = nva3_pm_pll_offset(id); +- if (off < 0) +- return off; +- +- src0 = nv_rd32(dev, 0x4120 + (off * 4)); +- src1 = nv_rd32(dev, 0x4160 + (off * 4)); +- ctrl = nv_rd32(dev, pll.reg + 0); +- coef = nv_rd32(dev, pll.reg + 4); +- NV_DEBUG(dev, "PLL %02x: 0x%08x 0x%08x 0x%08x 0x%08x\n", +- id, src0, src1, ctrl, coef); +- +- if (ctrl & 0x00000008) { +- u32 div = ((src1 & 0x003c0000) >> 18) + 1; +- return (pll.refclk * 2) / div; +- } +- +- P = (coef & 0x003f0000) >> 16; +- N = (coef & 0x0000ff00) >> 8; +- M = (coef & 0x000000ff); +- return pll.refclk * N / M / P; ++ limits.refclk = read_clk(dev, clk - 0x10, true); ++ if (!limits.refclk) ++ return -EINVAL; ++ ++ ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); ++ if (ret >= 0) { ++ reg->clk = nv_rd32(dev, 0x4120 + (clk * 4)); ++ reg->pll = (P << 16) | (N << 8) | M; ++ } ++ return ret; ++} ++ ++static void ++prog_pll(struct drm_device *dev, int clk, u32 pll, struct creg *reg) ++{ ++ const u32 src0 = 0x004120 + (clk * 4); ++ const u32 src1 = 0x004160 + (clk * 4); ++ const u32 ctrl = pll + 0; ++ const u32 coef = pll + 4; ++ u32 cntl; ++ ++ if (!reg->clk && !reg->pll) { ++ NV_DEBUG(dev, "no clock for %02x\n", clk); ++ return; ++ } ++ ++ cntl = nv_rd32(dev, ctrl) & 0xfffffff2; ++ if (reg->pll) { ++ nv_mask(dev, src0, 0x00000101, 0x00000101); ++ nv_wr32(dev, coef, reg->pll); ++ nv_wr32(dev, ctrl, cntl | 0x00000015); ++ nv_mask(dev, src1, 0x00000100, 0x00000000); ++ nv_mask(dev, src1, 0x00000001, 0x00000000); ++ } else { ++ nv_mask(dev, src1, 0x003f3141, 0x00000101 | reg->clk); ++ nv_wr32(dev, ctrl, cntl | 0x0000001d); ++ nv_mask(dev, ctrl, 0x00000001, 0x00000000); ++ nv_mask(dev, src0, 0x00000100, 0x00000000); ++ nv_mask(dev, src0, 0x00000001, 0x00000000); ++ } + } + ++static void ++prog_clk(struct drm_device *dev, int clk, struct creg *reg) ++{ ++ if (!reg->clk) { ++ NV_DEBUG(dev, "no clock for %02x\n", clk); ++ return; ++ } ++ ++ nv_mask(dev, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | reg->clk); ++} ++ ++int ++nva3_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) ++{ ++ perflvl->core = read_pll(dev, 0x00, 0x4200); ++ perflvl->shader = read_pll(dev, 0x01, 0x4220); ++ perflvl->memory = read_pll(dev, 0x02, 0x4000); ++ perflvl->unka0 = read_clk(dev, 0x20, false); ++ perflvl->vdec = read_clk(dev, 0x21, false); ++ perflvl->daemon = read_clk(dev, 0x25, false); ++ perflvl->copy = perflvl->core; ++ return 0; ++} ++ ++struct nva3_pm_state { ++ struct creg nclk; ++ struct creg sclk; ++ struct creg mclk; ++ struct creg vdec; ++ struct creg unka0; ++}; ++ + void * +-nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, +- u32 id, int khz) ++nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) + { +- struct nva3_pm_state *pll; +- struct pll_lims limits; +- int N, M, P, diff; +- int ret, off; ++ struct nva3_pm_state *info; ++ int ret; ++ ++ info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return ERR_PTR(-ENOMEM); + +- ret = get_pll_limits(dev, id, &limits); ++ ret = calc_clk(dev, 0x10, 0x4200, perflvl->core, &info->nclk); + if (ret < 0) +- return (ret == -ENOENT) ? NULL : ERR_PTR(ret); ++ goto out; + +- off = nva3_pm_pll_offset(id); +- if (id < 0) +- return ERR_PTR(-EINVAL); ++ ret = calc_clk(dev, 0x11, 0x4220, perflvl->shader, &info->sclk); ++ if (ret < 0) ++ goto out; + ++ ret = calc_clk(dev, 0x12, 0x4000, perflvl->memory, &info->mclk); ++ if (ret < 0) ++ goto out; + +- pll = kzalloc(sizeof(*pll), GFP_KERNEL); +- if (!pll) +- return ERR_PTR(-ENOMEM); +- pll->type = id; +- pll->src0 = 0x004120 + (off * 4); +- pll->src1 = 0x004160 + (off * 4); +- pll->ctrl = limits.reg + 0; +- pll->coef = limits.reg + 4; +- +- /* If target clock is within [-2, 3) MHz of a divisor, we'll +- * use that instead of calculating MNP values +- */ +- pll->new_div = min((limits.refclk * 2) / (khz - 2999), 16); +- if (pll->new_div) { +- diff = khz - ((limits.refclk * 2) / pll->new_div); +- if (diff < -2000 || diff >= 3000) +- pll->new_div = 0; +- } +- +- if (!pll->new_div) { +- ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); +- if (ret < 0) +- return ERR_PTR(ret); ++ ret = calc_clk(dev, 0x20, 0x0000, perflvl->unka0, &info->unka0); ++ if (ret < 0) ++ goto out; + +- pll->new_pnm = (P << 16) | (N << 8) | M; +- pll->new_div = 2 - 1; +- } else { +- pll->new_pnm = 0; +- pll->new_div--; ++ ret = calc_clk(dev, 0x21, 0x0000, perflvl->vdec, &info->vdec); ++ if (ret < 0) ++ goto out; ++ ++out: ++ if (ret < 0) { ++ kfree(info); ++ info = ERR_PTR(ret); + } ++ return info; ++} ++ ++static bool ++nva3_pm_grcp_idle(void *data) ++{ ++ struct drm_device *dev = data; + +- if ((nv_rd32(dev, pll->src1) & 0x00000101) != 0x00000101) +- pll->old_pnm = nv_rd32(dev, pll->coef); +- return pll; ++ if (!(nv_rd32(dev, 0x400304) & 0x00000001)) ++ return true; ++ if (nv_rd32(dev, 0x400308) == 0x0050001c) ++ return true; ++ return false; + } + + void +-nva3_pm_clock_set(struct drm_device *dev, void *pre_state) ++nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) + { +- struct nva3_pm_state *pll = pre_state; +- u32 ctrl = 0; +- +- /* For the memory clock, NVIDIA will build a "script" describing +- * the reclocking process and ask PDAEMON to execute it. +- */ +- if (pll->type == PLL_MEMORY) { +- nv_wr32(dev, 0x100210, 0); +- nv_wr32(dev, 0x1002dc, 1); +- nv_wr32(dev, 0x004018, 0x00001000); +- ctrl = 0x18000100; +- } +- +- if (pll->old_pnm || !pll->new_pnm) { +- nv_mask(dev, pll->src1, 0x003c0101, 0x00000101 | +- (pll->new_div << 18)); +- nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl); +- nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000); +- } +- +- if (pll->new_pnm) { +- nv_mask(dev, pll->src0, 0x00000101, 0x00000101); +- nv_wr32(dev, pll->coef, pll->new_pnm); +- nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl); +- nv_mask(dev, pll->ctrl, 0x00000010, 0x00000000); +- nv_mask(dev, pll->ctrl, 0x00020010, 0x00020010); +- nv_wr32(dev, pll->ctrl, 0x00010015 | ctrl); +- nv_mask(dev, pll->src1, 0x00000100, 0x00000000); +- nv_mask(dev, pll->src1, 0x00000001, 0x00000000); +- if (pll->type == PLL_MEMORY) +- nv_wr32(dev, 0x4018, 0x10005000); +- } else { +- nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000); +- nv_mask(dev, pll->src0, 0x00000100, 0x00000000); +- nv_mask(dev, pll->src0, 0x00000001, 0x00000000); +- if (pll->type == PLL_MEMORY) +- nv_wr32(dev, 0x4018, 0x1000d000); ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nva3_pm_state *info = pre_state; ++ unsigned long flags; ++ ++ /* prevent any new grctx switches from starting */ ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ nv_wr32(dev, 0x400324, 0x00000000); ++ nv_wr32(dev, 0x400328, 0x0050001c); /* wait flag 0x1c */ ++ /* wait for any pending grctx switches to complete */ ++ if (!nv_wait_cb(dev, nva3_pm_grcp_idle, dev)) { ++ NV_ERROR(dev, "pm: ctxprog didn't go idle\n"); ++ goto cleanup; + } +- +- if (pll->type == PLL_MEMORY) { +- nv_wr32(dev, 0x1002dc, 0); +- nv_wr32(dev, 0x100210, 0x80000000); ++ /* freeze PFIFO */ ++ nv_mask(dev, 0x002504, 0x00000001, 0x00000001); ++ if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) { ++ NV_ERROR(dev, "pm: fifo didn't go idle\n"); ++ goto cleanup; + } + +- kfree(pll); ++ prog_pll(dev, 0x00, 0x004200, &info->nclk); ++ prog_pll(dev, 0x01, 0x004220, &info->sclk); ++ prog_clk(dev, 0x20, &info->unka0); ++ prog_clk(dev, 0x21, &info->vdec); ++ ++ nv_wr32(dev, 0x100210, 0); ++ nv_wr32(dev, 0x1002dc, 1); ++ nv_wr32(dev, 0x004018, 0x00001000); ++ prog_pll(dev, 0x02, 0x004000, &info->mclk); ++ if (nv_rd32(dev, 0x4000) & 0x00000008) ++ nv_wr32(dev, 0x004018, 0x1000d000); ++ else ++ nv_wr32(dev, 0x004018, 0x10005000); ++ nv_wr32(dev, 0x1002dc, 0); ++ nv_wr32(dev, 0x100210, 0x80000000); ++ ++cleanup: ++ /* unfreeze PFIFO */ ++ nv_mask(dev, 0x002504, 0x00000001, 0x00000000); ++ /* restore ctxprog to normal */ ++ nv_wr32(dev, 0x400324, 0x00000000); ++ nv_wr32(dev, 0x400328, 0x0070009c); /* set flag 0x1c */ ++ /* unblock it if necessary */ ++ if (nv_rd32(dev, 0x400308) == 0x0050001c) ++ nv_mask(dev, 0x400824, 0x10000000, 0x10000000); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); ++ kfree(info); + } +- +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_copy.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_copy.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_copy.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_copy.c 2011-06-26 07:59:23.000000000 +0200 +@@ -48,14 +48,14 @@ + struct nouveau_gpuobj *ctx = NULL; + int ret; + +- ret = nouveau_gpuobj_new(dev, NULL, 256, 256, ++ ret = nouveau_gpuobj_new(dev, chan, 256, 256, + NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER | + NVOBJ_FLAG_ZERO_ALLOC, &ctx); + if (ret) + return ret; + +- nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(ctx->vinst)); +- nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(ctx->vinst)); ++ nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(ctx->linst)); ++ nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(ctx->linst)); + dev_priv->engine.instmem.flush(dev); + + chan->engctx[engine] = ctx; +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_fb.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_fb.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_fb.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_fb.c 2011-06-26 07:59:23.000000000 +0200 +@@ -1,5 +1,5 @@ + /* +- * Copyright 2010 Red Hat Inc. ++ * Copyright 2011 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"), +@@ -23,16 +23,80 @@ + */ + + #include "drmP.h" +- ++#include "drm.h" + #include "nouveau_drv.h" ++#include "nouveau_drm.h" ++ ++struct nvc0_fb_priv { ++ struct page *r100c10_page; ++ dma_addr_t r100c10; ++}; ++ ++static void ++nvc0_fb_destroy(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; ++ struct nvc0_fb_priv *priv = pfb->priv; ++ ++ if (priv->r100c10_page) { ++ pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE, ++ PCI_DMA_BIDIRECTIONAL); ++ __free_page(priv->r100c10_page); ++ } ++ ++ kfree(priv); ++ pfb->priv = NULL; ++} ++ ++static int ++nvc0_fb_create(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; ++ struct nvc0_fb_priv *priv; ++ ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ pfb->priv = priv; ++ ++ priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); ++ if (!priv->r100c10_page) { ++ nvc0_fb_destroy(dev); ++ return -ENOMEM; ++ } ++ ++ priv->r100c10 = pci_map_page(dev->pdev, priv->r100c10_page, 0, ++ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); ++ if (pci_dma_mapping_error(dev->pdev, priv->r100c10)) { ++ nvc0_fb_destroy(dev); ++ return -EFAULT; ++ } ++ ++ return 0; ++} + + int + nvc0_fb_init(struct drm_device *dev) + { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvc0_fb_priv *priv; ++ int ret; ++ ++ if (!dev_priv->engine.fb.priv) { ++ ret = nvc0_fb_create(dev); ++ if (ret) ++ return ret; ++ } ++ priv = dev_priv->engine.fb.priv; ++ ++ nv_wr32(dev, 0x100c10, priv->r100c10 >> 8); + return 0; + } + + void + nvc0_fb_takedown(struct drm_device *dev) + { ++ nvc0_fb_destroy(dev); + } +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_fbcon.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_fbcon.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_fbcon.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_fbcon.c 2011-06-26 07:59:23.000000000 +0200 +@@ -159,7 +159,7 @@ + struct drm_device *dev = nfbdev->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->channel; +- struct nouveau_bo *nvbo = nfbdev->nouveau_fb.nvbo; ++ struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb; + int ret, format; + + ret = nouveau_gpuobj_gr_new(chan, 0x902d, 0x902d); +@@ -203,8 +203,8 @@ + BEGIN_NVC0(chan, 2, NvSub2D, 0x0000, 1); + OUT_RING (chan, 0x0000902d); + BEGIN_NVC0(chan, 2, NvSub2D, 0x0104, 2); +- OUT_RING (chan, upper_32_bits(chan->notifier_bo->bo.offset)); +- OUT_RING (chan, lower_32_bits(chan->notifier_bo->bo.offset)); ++ OUT_RING (chan, upper_32_bits(chan->notifier_vma.offset)); ++ OUT_RING (chan, lower_32_bits(chan->notifier_vma.offset)); + BEGIN_NVC0(chan, 2, NvSub2D, 0x0290, 1); + OUT_RING (chan, 0); + BEGIN_NVC0(chan, 2, NvSub2D, 0x0888, 1); +@@ -249,8 +249,8 @@ + OUT_RING (chan, info->fix.line_length); + OUT_RING (chan, info->var.xres_virtual); + OUT_RING (chan, info->var.yres_virtual); +- OUT_RING (chan, upper_32_bits(nvbo->vma.offset)); +- OUT_RING (chan, lower_32_bits(nvbo->vma.offset)); ++ OUT_RING (chan, upper_32_bits(fb->vma.offset)); ++ OUT_RING (chan, lower_32_bits(fb->vma.offset)); + BEGIN_NVC0(chan, 2, NvSub2D, 0x0230, 10); + OUT_RING (chan, format); + OUT_RING (chan, 1); +@@ -260,8 +260,8 @@ + OUT_RING (chan, info->fix.line_length); + OUT_RING (chan, info->var.xres_virtual); + OUT_RING (chan, info->var.yres_virtual); +- OUT_RING (chan, upper_32_bits(nvbo->vma.offset)); +- OUT_RING (chan, lower_32_bits(nvbo->vma.offset)); ++ OUT_RING (chan, upper_32_bits(fb->vma.offset)); ++ OUT_RING (chan, lower_32_bits(fb->vma.offset)); + FIRE_RING (chan); + + return 0; +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_fifo.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_fifo.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_fifo.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_fifo.c 2011-06-26 07:59:23.000000000 +0200 +@@ -210,10 +210,10 @@ + int i; + + for (i = 0; i < 128; i++) { +- if (!(nv_rd32(dev, 0x003004 + (i * 4)) & 1)) ++ if (!(nv_rd32(dev, 0x003004 + (i * 8)) & 1)) + continue; + +- nv_mask(dev, 0x003004 + (i * 4), 0x00000001, 0x00000000); ++ nv_mask(dev, 0x003004 + (i * 8), 0x00000001, 0x00000000); + nv_wr32(dev, 0x002634, i); + if (!nv_wait(dev, 0x002634, 0xffffffff, i)) { + NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n", +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_graph.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_graph.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_graph.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_graph.c 2011-06-26 07:59:23.000000000 +0200 +@@ -28,7 +28,34 @@ + + #include "nouveau_drv.h" + #include "nouveau_mm.h" ++ + #include "nvc0_graph.h" ++#include "nvc0_grhub.fuc.h" ++#include "nvc0_grgpc.fuc.h" ++ ++static void ++nvc0_graph_ctxctl_debug_unit(struct drm_device *dev, u32 base) ++{ ++ NV_INFO(dev, "PGRAPH: %06x - done 0x%08x\n", base, ++ nv_rd32(dev, base + 0x400)); ++ NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, ++ nv_rd32(dev, base + 0x800), nv_rd32(dev, base + 0x804), ++ nv_rd32(dev, base + 0x808), nv_rd32(dev, base + 0x80c)); ++ NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, ++ nv_rd32(dev, base + 0x810), nv_rd32(dev, base + 0x814), ++ nv_rd32(dev, base + 0x818), nv_rd32(dev, base + 0x81c)); ++} ++ ++static void ++nvc0_graph_ctxctl_debug(struct drm_device *dev) ++{ ++ u32 gpcnr = nv_rd32(dev, 0x409604) & 0xffff; ++ u32 gpc; ++ ++ nvc0_graph_ctxctl_debug_unit(dev, 0x409000); ++ for (gpc = 0; gpc < gpcnr; gpc++) ++ nvc0_graph_ctxctl_debug_unit(dev, 0x502000 + (gpc * 0x8000)); ++} + + static int + nvc0_graph_load_context(struct nouveau_channel *chan) +@@ -72,24 +99,44 @@ + if (!ctx) + return -ENOMEM; + +- nvc0_graph_load_context(chan); ++ if (!nouveau_ctxfw) { ++ nv_wr32(dev, 0x409840, 0x80000000); ++ nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); ++ nv_wr32(dev, 0x409504, 0x00000001); ++ if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { ++ NV_ERROR(dev, "PGRAPH: HUB_SET_CHAN timeout\n"); ++ nvc0_graph_ctxctl_debug(dev); ++ ret = -EBUSY; ++ goto err; ++ } ++ } else { ++ nvc0_graph_load_context(chan); + +- nv_wo32(grch->grctx, 0x1c, 1); +- nv_wo32(grch->grctx, 0x20, 0); +- nv_wo32(grch->grctx, 0x28, 0); +- nv_wo32(grch->grctx, 0x2c, 0); +- dev_priv->engine.instmem.flush(dev); ++ nv_wo32(grch->grctx, 0x1c, 1); ++ nv_wo32(grch->grctx, 0x20, 0); ++ nv_wo32(grch->grctx, 0x28, 0); ++ nv_wo32(grch->grctx, 0x2c, 0); ++ dev_priv->engine.instmem.flush(dev); ++ } + + ret = nvc0_grctx_generate(chan); +- if (ret) { +- kfree(ctx); +- return ret; +- } ++ if (ret) ++ goto err; + +- ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst); +- if (ret) { +- kfree(ctx); +- return ret; ++ if (!nouveau_ctxfw) { ++ nv_wr32(dev, 0x409840, 0x80000000); ++ nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); ++ nv_wr32(dev, 0x409504, 0x00000002); ++ if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { ++ NV_ERROR(dev, "PGRAPH: HUB_CTX_SAVE timeout\n"); ++ nvc0_graph_ctxctl_debug(dev); ++ ret = -EBUSY; ++ goto err; ++ } ++ } else { ++ ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst); ++ if (ret) ++ goto err; + } + + for (i = 0; i < priv->grctx_size; i += 4) +@@ -97,6 +144,10 @@ + + priv->grctx_vals = ctx; + return 0; ++ ++err: ++ kfree(ctx); ++ return ret; + } + + static int +@@ -108,50 +159,50 @@ + int i = 0, gpc, tp, ret; + u32 magic; + +- ret = nouveau_gpuobj_new(dev, NULL, 0x2000, 256, NVOBJ_FLAG_VM, ++ ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM, + &grch->unk408004); + if (ret) + return ret; + +- ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 256, NVOBJ_FLAG_VM, ++ ret = nouveau_gpuobj_new(dev, chan, 0x8000, 256, NVOBJ_FLAG_VM, + &grch->unk40800c); + if (ret) + return ret; + +- ret = nouveau_gpuobj_new(dev, NULL, 384 * 1024, 4096, ++ ret = nouveau_gpuobj_new(dev, chan, 384 * 1024, 4096, + NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER, + &grch->unk418810); + if (ret) + return ret; + +- ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0, NVOBJ_FLAG_VM, ++ ret = nouveau_gpuobj_new(dev, chan, 0x1000, 0, NVOBJ_FLAG_VM, + &grch->mmio); + if (ret) + return ret; + + + nv_wo32(grch->mmio, i++ * 4, 0x00408004); +- nv_wo32(grch->mmio, i++ * 4, grch->unk408004->vinst >> 8); ++ nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8); + nv_wo32(grch->mmio, i++ * 4, 0x00408008); + nv_wo32(grch->mmio, i++ * 4, 0x80000018); + + nv_wo32(grch->mmio, i++ * 4, 0x0040800c); +- nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->vinst >> 8); ++ nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8); + nv_wo32(grch->mmio, i++ * 4, 0x00408010); + nv_wo32(grch->mmio, i++ * 4, 0x80000000); + + nv_wo32(grch->mmio, i++ * 4, 0x00418810); +- nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810->vinst >> 12); ++ nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810->linst >> 12); + nv_wo32(grch->mmio, i++ * 4, 0x00419848); +- nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810->vinst >> 12); ++ nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810->linst >> 12); + + nv_wo32(grch->mmio, i++ * 4, 0x00419004); +- nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->vinst >> 8); ++ nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8); + nv_wo32(grch->mmio, i++ * 4, 0x00419008); + nv_wo32(grch->mmio, i++ * 4, 0x00000000); + + nv_wo32(grch->mmio, i++ * 4, 0x00418808); +- nv_wo32(grch->mmio, i++ * 4, grch->unk408004->vinst >> 8); ++ nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8); + nv_wo32(grch->mmio, i++ * 4, 0x0041880c); + nv_wo32(grch->mmio, i++ * 4, 0x80000018); + +@@ -159,7 +210,7 @@ + nv_wo32(grch->mmio, i++ * 4, 0x00405830); + nv_wo32(grch->mmio, i++ * 4, magic); + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { +- for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x02fc) { ++ for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x0324) { + u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800); + nv_wo32(grch->mmio, i++ * 4, reg); + nv_wo32(grch->mmio, i++ * 4, magic); +@@ -186,7 +237,7 @@ + return -ENOMEM; + chan->engctx[NVOBJ_ENGINE_GR] = grch; + +- ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256, ++ ret = nouveau_gpuobj_new(dev, chan, priv->grctx_size, 256, + NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC, + &grch->grctx); + if (ret) +@@ -197,8 +248,8 @@ + if (ret) + goto error; + +- nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->vinst) | 4); +- nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->vinst)); ++ nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->linst) | 4); ++ nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->linst)); + pinstmem->flush(dev); + + if (!priv->grctx_vals) { +@@ -210,15 +261,20 @@ + for (i = 0; i < priv->grctx_size; i += 4) + nv_wo32(grctx, i, priv->grctx_vals[i / 4]); + +- nv_wo32(grctx, 0xf4, 0); +- nv_wo32(grctx, 0xf8, 0); +- nv_wo32(grctx, 0x10, grch->mmio_nr); +- nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->vinst)); +- nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->vinst)); +- nv_wo32(grctx, 0x1c, 1); +- nv_wo32(grctx, 0x20, 0); +- nv_wo32(grctx, 0x28, 0); +- nv_wo32(grctx, 0x2c, 0); ++ if (!nouveau_ctxfw) { ++ nv_wo32(grctx, 0x00, grch->mmio_nr); ++ nv_wo32(grctx, 0x04, grch->mmio->linst >> 8); ++ } else { ++ nv_wo32(grctx, 0xf4, 0); ++ nv_wo32(grctx, 0xf8, 0); ++ nv_wo32(grctx, 0x10, grch->mmio_nr); ++ nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->linst)); ++ nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->linst)); ++ nv_wo32(grctx, 0x1c, 1); ++ nv_wo32(grctx, 0x20, 0); ++ nv_wo32(grctx, 0x28, 0); ++ nv_wo32(grctx, 0x2c, 0); ++ } + pinstmem->flush(dev); + return 0; + +@@ -296,6 +352,7 @@ + nvc0_graph_init_gpc_0(struct drm_device *dev) + { + struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); ++ const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tp_total); + u32 data[TP_MAX / 8]; + u8 tpnr[GPC_MAX]; + int i, gpc, tpc; +@@ -307,13 +364,6 @@ + * 465: 3/4/4/0 4 7 + * 470: 3/3/4/4 5 5 + * 480: 3/4/4/4 6 6 +- * +- * magicgpc918 +- * 450: 00200000 00000000001000000000000000000000 +- * 460: 00124925 00000000000100100100100100100101 +- * 465: 000ba2e9 00000000000010111010001011101001 +- * 470: 00092493 00000000000010010010010010010011 +- * 480: 00088889 00000000000010001000100010001001 + */ + + memset(data, 0x00, sizeof(data)); +@@ -336,10 +386,10 @@ + nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 | + priv->tp_nr[gpc]); + nv_wr32(dev, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tp_total); +- nv_wr32(dev, GPC_UNIT(gpc, 0x0918), priv->magicgpc918); ++ nv_wr32(dev, GPC_UNIT(gpc, 0x0918), magicgpc918); + } + +- nv_wr32(dev, GPC_BCAST(0x1bd4), priv->magicgpc918); ++ nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918); + nv_wr32(dev, GPC_BCAST(0x08ac), priv->rop_nr); + } + +@@ -419,8 +469,51 @@ + static int + nvc0_graph_init_ctxctl(struct drm_device *dev) + { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); + u32 r000260; ++ int i; ++ ++ if (!nouveau_ctxfw) { ++ /* load HUB microcode */ ++ r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); ++ nv_wr32(dev, 0x4091c0, 0x01000000); ++ for (i = 0; i < sizeof(nvc0_grhub_data) / 4; i++) ++ nv_wr32(dev, 0x4091c4, nvc0_grhub_data[i]); ++ ++ nv_wr32(dev, 0x409180, 0x01000000); ++ for (i = 0; i < sizeof(nvc0_grhub_code) / 4; i++) { ++ if ((i & 0x3f) == 0) ++ nv_wr32(dev, 0x409188, i >> 6); ++ nv_wr32(dev, 0x409184, nvc0_grhub_code[i]); ++ } ++ ++ /* load GPC microcode */ ++ nv_wr32(dev, 0x41a1c0, 0x01000000); ++ for (i = 0; i < sizeof(nvc0_grgpc_data) / 4; i++) ++ nv_wr32(dev, 0x41a1c4, nvc0_grgpc_data[i]); ++ ++ nv_wr32(dev, 0x41a180, 0x01000000); ++ for (i = 0; i < sizeof(nvc0_grgpc_code) / 4; i++) { ++ if ((i & 0x3f) == 0) ++ nv_wr32(dev, 0x41a188, i >> 6); ++ nv_wr32(dev, 0x41a184, nvc0_grgpc_code[i]); ++ } ++ nv_wr32(dev, 0x000260, r000260); ++ ++ /* start HUB ucode running, it'll init the GPCs */ ++ nv_wr32(dev, 0x409800, dev_priv->chipset); ++ nv_wr32(dev, 0x40910c, 0x00000000); ++ nv_wr32(dev, 0x409100, 0x00000002); ++ if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { ++ NV_ERROR(dev, "PGRAPH: HUB_INIT timed out\n"); ++ nvc0_graph_ctxctl_debug(dev); ++ return -EBUSY; ++ } ++ ++ priv->grctx_size = nv_rd32(dev, 0x409804); ++ return 0; ++ } + + /* load fuc microcode */ + r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); +@@ -528,6 +621,22 @@ + } + + static void ++nvc0_graph_ctxctl_isr(struct drm_device *dev) ++{ ++ u32 ustat = nv_rd32(dev, 0x409c18); ++ ++ if (ustat & 0x00000001) ++ NV_INFO(dev, "PGRAPH: CTXCTRL ucode error\n"); ++ if (ustat & 0x00080000) ++ NV_INFO(dev, "PGRAPH: CTXCTRL watchdog timeout\n"); ++ if (ustat & ~0x00080001) ++ NV_INFO(dev, "PGRAPH: CTXCTRL 0x%08x\n", ustat); ++ ++ nvc0_graph_ctxctl_debug(dev); ++ nv_wr32(dev, 0x409c20, ustat); ++} ++ ++static void + nvc0_graph_isr(struct drm_device *dev) + { + u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12; +@@ -578,11 +687,7 @@ + } + + if (stat & 0x00080000) { +- u32 ustat = nv_rd32(dev, 0x409c18); +- +- NV_INFO(dev, "PGRAPH: CTXCTRL ustat 0x%08x\n", ustat); +- +- nv_wr32(dev, 0x409c20, ustat); ++ nvc0_graph_ctxctl_isr(dev); + nv_wr32(dev, 0x400100, 0x00080000); + stat &= ~0x00080000; + } +@@ -606,7 +711,7 @@ + u32 st0 = nv_mask(dev, reg + 0x1020, 0, 0); + u32 st1 = nv_mask(dev, reg + 0x1420, 0, 0); + +- NV_INFO(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1); ++ NV_DEBUG(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1); + units &= ~(1 << unit); + } + } +@@ -651,10 +756,12 @@ + { + struct nvc0_graph_priv *priv = nv_engine(dev, engine); + +- nvc0_graph_destroy_fw(&priv->fuc409c); +- nvc0_graph_destroy_fw(&priv->fuc409d); +- nvc0_graph_destroy_fw(&priv->fuc41ac); +- nvc0_graph_destroy_fw(&priv->fuc41ad); ++ if (nouveau_ctxfw) { ++ nvc0_graph_destroy_fw(&priv->fuc409c); ++ nvc0_graph_destroy_fw(&priv->fuc409d); ++ nvc0_graph_destroy_fw(&priv->fuc41ac); ++ nvc0_graph_destroy_fw(&priv->fuc41ad); ++ } + + nouveau_irq_unregister(dev, 12); + nouveau_irq_unregister(dev, 25); +@@ -675,13 +782,10 @@ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvc0_graph_priv *priv; + int ret, gpc, i; ++ u32 fermi; + +- switch (dev_priv->chipset) { +- case 0xc0: +- case 0xc3: +- case 0xc4: +- break; +- default: ++ fermi = nvc0_graph_class(dev); ++ if (!fermi) { + NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n"); + return 0; + } +@@ -701,15 +805,17 @@ + nouveau_irq_register(dev, 12, nvc0_graph_isr); + nouveau_irq_register(dev, 25, nvc0_runk140_isr); + +- if (nvc0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) || +- nvc0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) || +- nvc0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) || +- nvc0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) { +- ret = 0; +- goto error; ++ if (nouveau_ctxfw) { ++ NV_INFO(dev, "PGRAPH: using external firmware\n"); ++ if (nvc0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) || ++ nvc0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) || ++ nvc0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) || ++ nvc0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) { ++ ret = 0; ++ goto error; ++ } + } + +- + ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); + if (ret) + goto error; +@@ -735,25 +841,28 @@ + case 0xc0: + if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */ + priv->magic_not_rop_nr = 0x07; +- /* filled values up to tp_total, the rest 0 */ +- priv->magicgpc918 = 0x000ba2e9; + } else + if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */ + priv->magic_not_rop_nr = 0x05; +- priv->magicgpc918 = 0x00092493; + } else + if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */ + priv->magic_not_rop_nr = 0x06; +- priv->magicgpc918 = 0x00088889; + } + break; + case 0xc3: /* 450, 4/0/0/0, 2 */ + priv->magic_not_rop_nr = 0x03; +- priv->magicgpc918 = 0x00200000; + break; + case 0xc4: /* 460, 3/4/0/0, 4 */ + priv->magic_not_rop_nr = 0x01; +- priv->magicgpc918 = 0x00124925; ++ break; ++ case 0xc1: /* 2/0/0/0, 1 */ ++ priv->magic_not_rop_nr = 0x01; ++ break; ++ case 0xc8: /* 4/4/3/4, 5 */ ++ priv->magic_not_rop_nr = 0x06; ++ break; ++ case 0xce: /* 4/4/0/0, 4 */ ++ priv->magic_not_rop_nr = 0x03; + break; + } + +@@ -763,13 +872,16 @@ + priv->tp_nr[3], priv->rop_nr); + /* use 0xc3's values... */ + priv->magic_not_rop_nr = 0x03; +- priv->magicgpc918 = 0x00200000; + } + + NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ + NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ + NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip); + NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ ++ if (fermi >= 0x9197) ++ NVOBJ_CLASS(dev, 0x9197, GR); /* 3D (NVC1-) */ ++ if (fermi >= 0x9297) ++ NVOBJ_CLASS(dev, 0x9297, GR); /* 3D (NVC8-) */ + NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ + return 0; + +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_graph.fuc linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_graph.fuc +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_graph.fuc 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_graph.fuc 2011-06-26 07:59:23.000000000 +0200 +@@ -0,0 +1,400 @@ ++/* fuc microcode util functions for nvc0 PGRAPH ++ * ++ * Copyright 2011 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 ++ */ ++ ++define(`mmctx_data', `.b32 eval((($2 - 1) << 26) | $1)') ++define(`queue_init', `.skip eval((2 * 4) + ((8 * 4) * 2))') ++ ++ifdef(`include_code', ` ++// Error codes ++define(`E_BAD_COMMAND', 0x01) ++define(`E_CMD_OVERFLOW', 0x02) ++ ++// Util macros to help with debugging ucode hangs etc ++define(`T_WAIT', 0) ++define(`T_MMCTX', 1) ++define(`T_STRWAIT', 2) ++define(`T_STRINIT', 3) ++define(`T_AUTO', 4) ++define(`T_CHAN', 5) ++define(`T_LOAD', 6) ++define(`T_SAVE', 7) ++define(`T_LCHAN', 8) ++define(`T_LCTXH', 9) ++ ++define(`trace_set', ` ++ mov $r8 0x83c ++ shl b32 $r8 6 ++ clear b32 $r9 ++ bset $r9 $1 ++ iowr I[$r8 + 0x000] $r9 // CC_SCRATCH[7] ++') ++ ++define(`trace_clr', ` ++ mov $r8 0x85c ++ shl b32 $r8 6 ++ clear b32 $r9 ++ bset $r9 $1 ++ iowr I[$r8 + 0x000] $r9 // CC_SCRATCH[7] ++') ++ ++// queue_put - add request to queue ++// ++// In : $r13 queue pointer ++// $r14 command ++// $r15 data ++// ++queue_put: ++ // make sure we have space.. ++ ld b32 $r8 D[$r13 + 0x0] // GET ++ ld b32 $r9 D[$r13 + 0x4] // PUT ++ xor $r8 8 ++ cmpu b32 $r8 $r9 ++ bra ne queue_put_next ++ mov $r15 E_CMD_OVERFLOW ++ call error ++ ret ++ ++ // store cmd/data on queue ++ queue_put_next: ++ and $r8 $r9 7 ++ shl b32 $r8 3 ++ add b32 $r8 $r13 ++ add b32 $r8 8 ++ st b32 D[$r8 + 0x0] $r14 ++ st b32 D[$r8 + 0x4] $r15 ++ ++ // update PUT ++ add b32 $r9 1 ++ and $r9 0xf ++ st b32 D[$r13 + 0x4] $r9 ++ ret ++ ++// queue_get - fetch request from queue ++// ++// In : $r13 queue pointer ++// ++// Out: $p1 clear on success (data available) ++// $r14 command ++// $r15 data ++// ++queue_get: ++ bset $flags $p1 ++ ld b32 $r8 D[$r13 + 0x0] // GET ++ ld b32 $r9 D[$r13 + 0x4] // PUT ++ cmpu b32 $r8 $r9 ++ bra e queue_get_done ++ // fetch first cmd/data pair ++ and $r9 $r8 7 ++ shl b32 $r9 3 ++ add b32 $r9 $r13 ++ add b32 $r9 8 ++ ld b32 $r14 D[$r9 + 0x0] ++ ld b32 $r15 D[$r9 + 0x4] ++ ++ // update GET ++ add b32 $r8 1 ++ and $r8 0xf ++ st b32 D[$r13 + 0x0] $r8 ++ bclr $flags $p1 ++queue_get_done: ++ ret ++ ++// nv_rd32 - read 32-bit value from nv register ++// ++// In : $r14 register ++// Out: $r15 value ++// ++nv_rd32: ++ mov $r11 0x728 ++ shl b32 $r11 6 ++ mov b32 $r12 $r14 ++ bset $r12 31 // MMIO_CTRL_PENDING ++ iowr I[$r11 + 0x000] $r12 // MMIO_CTRL ++ nv_rd32_wait: ++ iord $r12 I[$r11 + 0x000] ++ xbit $r12 $r12 31 ++ bra ne nv_rd32_wait ++ mov $r10 6 // DONE_MMIO_RD ++ call wait_doneo ++ iord $r15 I[$r11 + 0x100] // MMIO_RDVAL ++ ret ++ ++// nv_wr32 - write 32-bit value to nv register ++// ++// In : $r14 register ++// $r15 value ++// ++nv_wr32: ++ mov $r11 0x728 ++ shl b32 $r11 6 ++ iowr I[$r11 + 0x200] $r15 // MMIO_WRVAL ++ mov b32 $r12 $r14 ++ bset $r12 31 // MMIO_CTRL_PENDING ++ bset $r12 30 // MMIO_CTRL_WRITE ++ iowr I[$r11 + 0x000] $r12 // MMIO_CTRL ++ nv_wr32_wait: ++ iord $r12 I[$r11 + 0x000] ++ xbit $r12 $r12 31 ++ bra ne nv_wr32_wait ++ ret ++ ++// (re)set watchdog timer ++// ++// In : $r15 timeout ++// ++watchdog_reset: ++ mov $r8 0x430 ++ shl b32 $r8 6 ++ bset $r15 31 ++ iowr I[$r8 + 0x000] $r15 ++ ret ++ ++// clear watchdog timer ++watchdog_clear: ++ mov $r8 0x430 ++ shl b32 $r8 6 ++ iowr I[$r8 + 0x000] $r0 ++ ret ++ ++// wait_done{z,o} - wait on FUC_DONE bit to become clear/set ++// ++// In : $r10 bit to wait on ++// ++define(`wait_done', ` ++$1: ++ trace_set(T_WAIT); ++ mov $r8 0x818 ++ shl b32 $r8 6 ++ iowr I[$r8 + 0x000] $r10 // CC_SCRATCH[6] = wait bit ++ wait_done_$1: ++ mov $r8 0x400 ++ shl b32 $r8 6 ++ iord $r8 I[$r8 + 0x000] // DONE ++ xbit $r8 $r8 $r10 ++ bra $2 wait_done_$1 ++ trace_clr(T_WAIT) ++ ret ++') ++wait_done(wait_donez, ne) ++wait_done(wait_doneo, e) ++ ++// mmctx_size - determine size of a mmio list transfer ++// ++// In : $r14 mmio list head ++// $r15 mmio list tail ++// Out: $r15 transfer size (in bytes) ++// ++mmctx_size: ++ clear b32 $r9 ++ nv_mmctx_size_loop: ++ ld b32 $r8 D[$r14] ++ shr b32 $r8 26 ++ add b32 $r8 1 ++ shl b32 $r8 2 ++ add b32 $r9 $r8 ++ add b32 $r14 4 ++ cmpu b32 $r14 $r15 ++ bra ne nv_mmctx_size_loop ++ mov b32 $r15 $r9 ++ ret ++ ++// mmctx_xfer - execute a list of mmio transfers ++// ++// In : $r10 flags ++// bit 0: direction (0 = save, 1 = load) ++// bit 1: set if first transfer ++// bit 2: set if last transfer ++// $r11 base ++// $r12 mmio list head ++// $r13 mmio list tail ++// $r14 multi_stride ++// $r15 multi_mask ++// ++mmctx_xfer: ++ trace_set(T_MMCTX) ++ mov $r8 0x710 ++ shl b32 $r8 6 ++ clear b32 $r9 ++ or $r11 $r11 ++ bra e mmctx_base_disabled ++ iowr I[$r8 + 0x000] $r11 // MMCTX_BASE ++ bset $r9 0 // BASE_EN ++ mmctx_base_disabled: ++ or $r14 $r14 ++ bra e mmctx_multi_disabled ++ iowr I[$r8 + 0x200] $r14 // MMCTX_MULTI_STRIDE ++ iowr I[$r8 + 0x300] $r15 // MMCTX_MULTI_MASK ++ bset $r9 1 // MULTI_EN ++ mmctx_multi_disabled: ++ add b32 $r8 0x100 ++ ++ xbit $r11 $r10 0 ++ shl b32 $r11 16 // DIR ++ bset $r11 12 // QLIMIT = 0x10 ++ xbit $r14 $r10 1 ++ shl b32 $r14 17 ++ or $r11 $r14 // START_TRIGGER ++ iowr I[$r8 + 0x000] $r11 // MMCTX_CTRL ++ ++ // loop over the mmio list, and send requests to the hw ++ mmctx_exec_loop: ++ // wait for space in mmctx queue ++ mmctx_wait_free: ++ iord $r14 I[$r8 + 0x000] // MMCTX_CTRL ++ and $r14 0x1f ++ bra e mmctx_wait_free ++ ++ // queue up an entry ++ ld b32 $r14 D[$r12] ++ or $r14 $r9 ++ iowr I[$r8 + 0x300] $r14 ++ add b32 $r12 4 ++ cmpu b32 $r12 $r13 ++ bra ne mmctx_exec_loop ++ ++ xbit $r11 $r10 2 ++ bra ne mmctx_stop ++ // wait for queue to empty ++ mmctx_fini_wait: ++ iord $r11 I[$r8 + 0x000] // MMCTX_CTRL ++ and $r11 0x1f ++ cmpu b32 $r11 0x10 ++ bra ne mmctx_fini_wait ++ mov $r10 2 // DONE_MMCTX ++ call wait_donez ++ bra mmctx_done ++ mmctx_stop: ++ xbit $r11 $r10 0 ++ shl b32 $r11 16 // DIR ++ bset $r11 12 // QLIMIT = 0x10 ++ bset $r11 18 // STOP_TRIGGER ++ iowr I[$r8 + 0x000] $r11 // MMCTX_CTRL ++ mmctx_stop_wait: ++ // wait for STOP_TRIGGER to clear ++ iord $r11 I[$r8 + 0x000] // MMCTX_CTRL ++ xbit $r11 $r11 18 ++ bra ne mmctx_stop_wait ++ mmctx_done: ++ trace_clr(T_MMCTX) ++ ret ++ ++// Wait for DONE_STRAND ++// ++strand_wait: ++ push $r10 ++ mov $r10 2 ++ call wait_donez ++ pop $r10 ++ ret ++ ++// unknown - call before issuing strand commands ++// ++strand_pre: ++ mov $r8 0x4afc ++ sethi $r8 0x20000 ++ mov $r9 0xc ++ iowr I[$r8] $r9 ++ call strand_wait ++ ret ++ ++// unknown - call after issuing strand commands ++// ++strand_post: ++ mov $r8 0x4afc ++ sethi $r8 0x20000 ++ mov $r9 0xd ++ iowr I[$r8] $r9 ++ call strand_wait ++ ret ++ ++// Selects strand set?! ++// ++// In: $r14 id ++// ++strand_set: ++ mov $r10 0x4ffc ++ sethi $r10 0x20000 ++ sub b32 $r11 $r10 0x500 ++ mov $r12 0xf ++ iowr I[$r10 + 0x000] $r12 // 0x93c = 0xf ++ mov $r12 0xb ++ iowr I[$r11 + 0x000] $r12 // 0x928 = 0xb ++ call strand_wait ++ iowr I[$r10 + 0x000] $r14 // 0x93c = ++ mov $r12 0xa ++ iowr I[$r11 + 0x000] $r12 // 0x928 = 0xa ++ call strand_wait ++ ret ++ ++// Initialise strand context data ++// ++// In : $r15 context base ++// Out: $r15 context size (in bytes) ++// ++// Strandset(?) 3 hardcoded currently ++// ++strand_ctx_init: ++ trace_set(T_STRINIT) ++ call strand_pre ++ mov $r14 3 ++ call strand_set ++ mov $r10 0x46fc ++ sethi $r10 0x20000 ++ add b32 $r11 $r10 0x400 ++ iowr I[$r10 + 0x100] $r0 // STRAND_FIRST_GENE = 0 ++ mov $r12 1 ++ iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_FIRST_GENE ++ call strand_wait ++ sub b32 $r12 $r0 1 ++ iowr I[$r10 + 0x000] $r12 // STRAND_GENE_CNT = 0xffffffff ++ mov $r12 2 ++ iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_GENE_CNT ++ call strand_wait ++ call strand_post ++ ++ // read the size of each strand, poke the context offset of ++ // each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry ++ // about it later then. ++ mov $r8 0x880 ++ shl b32 $r8 6 ++ iord $r9 I[$r8 + 0x000] // STRANDS ++ add b32 $r8 0x2200 ++ shr b32 $r14 $r15 8 ++ ctx_init_strand_loop: ++ iowr I[$r8 + 0x000] $r14 // STRAND_SAVE_SWBASE ++ iowr I[$r8 + 0x100] $r14 // STRAND_LOAD_SWBASE ++ iord $r10 I[$r8 + 0x200] // STRAND_SIZE ++ shr b32 $r10 6 ++ add b32 $r10 1 ++ add b32 $r14 $r10 ++ add b32 $r8 4 ++ sub b32 $r9 1 ++ bra ne ctx_init_strand_loop ++ ++ shl b32 $r14 8 ++ sub b32 $r15 $r14 $r15 ++ trace_clr(T_STRINIT) ++ ret ++') +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_graph.h linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_graph.h +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_graph.h 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_graph.h 2011-06-26 07:59:23.000000000 +0200 +@@ -57,8 +57,7 @@ + struct nouveau_gpuobj *unk4188b4; + struct nouveau_gpuobj *unk4188b8; + +- u8 magic_not_rop_nr; +- u32 magicgpc918; ++ u8 magic_not_rop_nr; + }; + + struct nvc0_graph_chan { +@@ -72,4 +71,25 @@ + + int nvc0_grctx_generate(struct nouveau_channel *); + ++/* nvc0_graph.c uses this also to determine supported chipsets */ ++static inline u32 ++nvc0_graph_class(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ switch (dev_priv->chipset) { ++ case 0xc0: ++ case 0xc3: ++ case 0xc4: ++ case 0xce: /* guess, mmio trace shows only 0x9097 state */ ++ return 0x9097; ++ case 0xc1: ++ return 0x9197; ++ case 0xc8: ++ return 0x9297; ++ default: ++ return 0; ++ } ++} ++ + #endif +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_grctx.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_grctx.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_grctx.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_grctx.c 2011-06-26 07:59:23.000000000 +0200 +@@ -45,6 +45,9 @@ + static void + nvc0_grctx_generate_9097(struct drm_device *dev) + { ++ u32 fermi = nvc0_graph_class(dev); ++ u32 mthd; ++ + nv_mthd(dev, 0x9097, 0x0800, 0x00000000); + nv_mthd(dev, 0x9097, 0x0840, 0x00000000); + nv_mthd(dev, 0x9097, 0x0880, 0x00000000); +@@ -824,134 +827,10 @@ + nv_mthd(dev, 0x9097, 0x1eb8, 0x00000001); + nv_mthd(dev, 0x9097, 0x1ed8, 0x00000001); + nv_mthd(dev, 0x9097, 0x1ef8, 0x00000001); +- nv_mthd(dev, 0x9097, 0x3400, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3404, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3408, 0x00000000); +- nv_mthd(dev, 0x9097, 0x340c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3410, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3414, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3418, 0x00000000); +- nv_mthd(dev, 0x9097, 0x341c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3420, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3424, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3428, 0x00000000); +- nv_mthd(dev, 0x9097, 0x342c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3430, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3434, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3438, 0x00000000); +- nv_mthd(dev, 0x9097, 0x343c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3440, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3444, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3448, 0x00000000); +- nv_mthd(dev, 0x9097, 0x344c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3450, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3454, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3458, 0x00000000); +- nv_mthd(dev, 0x9097, 0x345c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3460, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3464, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3468, 0x00000000); +- nv_mthd(dev, 0x9097, 0x346c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3470, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3474, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3478, 0x00000000); +- nv_mthd(dev, 0x9097, 0x347c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3480, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3484, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3488, 0x00000000); +- nv_mthd(dev, 0x9097, 0x348c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3490, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3494, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3498, 0x00000000); +- nv_mthd(dev, 0x9097, 0x349c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34a0, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34a4, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34a8, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34ac, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34b0, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34b4, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34b8, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34bc, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34c0, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34c4, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34c8, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34cc, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34d0, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34d4, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34d8, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34dc, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34e0, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34e4, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34e8, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34ec, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34f0, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34f4, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34f8, 0x00000000); +- nv_mthd(dev, 0x9097, 0x34fc, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3500, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3504, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3508, 0x00000000); +- nv_mthd(dev, 0x9097, 0x350c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3510, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3514, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3518, 0x00000000); +- nv_mthd(dev, 0x9097, 0x351c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3520, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3524, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3528, 0x00000000); +- nv_mthd(dev, 0x9097, 0x352c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3530, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3534, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3538, 0x00000000); +- nv_mthd(dev, 0x9097, 0x353c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3540, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3544, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3548, 0x00000000); +- nv_mthd(dev, 0x9097, 0x354c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3550, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3554, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3558, 0x00000000); +- nv_mthd(dev, 0x9097, 0x355c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3560, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3564, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3568, 0x00000000); +- nv_mthd(dev, 0x9097, 0x356c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3570, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3574, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3578, 0x00000000); +- nv_mthd(dev, 0x9097, 0x357c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3580, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3584, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3588, 0x00000000); +- nv_mthd(dev, 0x9097, 0x358c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3590, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3594, 0x00000000); +- nv_mthd(dev, 0x9097, 0x3598, 0x00000000); +- nv_mthd(dev, 0x9097, 0x359c, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35a0, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35a4, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35a8, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35ac, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35b0, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35b4, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35b8, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35bc, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35c0, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35c4, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35c8, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35cc, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35d0, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35d4, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35d8, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35dc, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35e0, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35e4, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35e8, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35ec, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35f0, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35f4, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35f8, 0x00000000); +- nv_mthd(dev, 0x9097, 0x35fc, 0x00000000); ++ if (fermi == 0x9097) { ++ for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4) ++ nv_mthd(dev, 0x9097, mthd, 0x00000000); ++ } + nv_mthd(dev, 0x9097, 0x030c, 0x00000001); + nv_mthd(dev, 0x9097, 0x1944, 0x00000000); + nv_mthd(dev, 0x9097, 0x1514, 0x00000000); +@@ -1321,6 +1200,37 @@ + } + + static void ++nvc0_grctx_generate_9197(struct drm_device *dev) ++{ ++ u32 fermi = nvc0_graph_class(dev); ++ u32 mthd; ++ ++ if (fermi == 0x9197) { ++ for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4) ++ nv_mthd(dev, 0x9197, mthd, 0x00000000); ++ } ++ nv_mthd(dev, 0x9197, 0x02e4, 0x0000b001); ++} ++ ++static void ++nvc0_grctx_generate_9297(struct drm_device *dev) ++{ ++ u32 fermi = nvc0_graph_class(dev); ++ u32 mthd; ++ ++ if (fermi == 0x9297) { ++ for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4) ++ nv_mthd(dev, 0x9297, mthd, 0x00000000); ++ } ++ nv_mthd(dev, 0x9297, 0x036c, 0x00000000); ++ nv_mthd(dev, 0x9297, 0x0370, 0x00000000); ++ nv_mthd(dev, 0x9297, 0x07a4, 0x00000000); ++ nv_mthd(dev, 0x9297, 0x07a8, 0x00000000); ++ nv_mthd(dev, 0x9297, 0x0374, 0x00000000); ++ nv_mthd(dev, 0x9297, 0x0378, 0x00000020); ++} ++ ++static void + nvc0_grctx_generate_902d(struct drm_device *dev) + { + nv_mthd(dev, 0x902d, 0x0200, 0x000000cf); +@@ -1559,8 +1469,15 @@ + static void + nvc0_grctx_generate_shaders(struct drm_device *dev) + { +- nv_wr32(dev, 0x405800, 0x078000bf); +- nv_wr32(dev, 0x405830, 0x02180000); ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ if (dev_priv->chipset != 0xc1) { ++ nv_wr32(dev, 0x405800, 0x078000bf); ++ nv_wr32(dev, 0x405830, 0x02180000); ++ } else { ++ nv_wr32(dev, 0x405800, 0x0f8000bf); ++ nv_wr32(dev, 0x405830, 0x02180218); ++ } + nv_wr32(dev, 0x405834, 0x00000000); + nv_wr32(dev, 0x405838, 0x00000000); + nv_wr32(dev, 0x405854, 0x00000000); +@@ -1586,10 +1503,16 @@ + static void + nvc0_grctx_generate_unk64xx(struct drm_device *dev) + { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ + nv_wr32(dev, 0x4064a8, 0x00000000); + nv_wr32(dev, 0x4064ac, 0x00003fff); + nv_wr32(dev, 0x4064b4, 0x00000000); + nv_wr32(dev, 0x4064b8, 0x00000000); ++ if (dev_priv->chipset == 0xc1) { ++ nv_wr32(dev, 0x4064c0, 0x80140078); ++ nv_wr32(dev, 0x4064c4, 0x0086ffff); ++ } + } + + static void +@@ -1622,21 +1545,14 @@ + nvc0_grctx_generate_rop(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ int chipset = dev_priv->chipset; + + /* ROPC_BROADCAST */ + nv_wr32(dev, 0x408800, 0x02802a3c); + nv_wr32(dev, 0x408804, 0x00000040); +- nv_wr32(dev, 0x408808, 0x0003e00d); +- switch (dev_priv->chipset) { +- case 0xc0: +- nv_wr32(dev, 0x408900, 0x0080b801); +- break; +- case 0xc3: +- case 0xc4: +- nv_wr32(dev, 0x408900, 0x3080b801); +- break; +- } +- nv_wr32(dev, 0x408904, 0x02000001); ++ nv_wr32(dev, 0x408808, chipset != 0xc1 ? 0x0003e00d : 0x1003e005); ++ nv_wr32(dev, 0x408900, 0x3080b801); ++ nv_wr32(dev, 0x408904, chipset != 0xc1 ? 0x02000001 : 0x62000001); + nv_wr32(dev, 0x408908, 0x00c80929); + nv_wr32(dev, 0x40890c, 0x00000000); + nv_wr32(dev, 0x408980, 0x0000011d); +@@ -1645,6 +1561,8 @@ + static void + nvc0_grctx_generate_gpc(struct drm_device *dev) + { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ int chipset = dev_priv->chipset; + int i; + + /* GPC_BROADCAST */ +@@ -1676,7 +1594,7 @@ + nv_wr32(dev, 0x41880c, 0x00000000); + nv_wr32(dev, 0x418810, 0x00000000); + nv_wr32(dev, 0x418828, 0x00008442); +- nv_wr32(dev, 0x418830, 0x00000001); ++ nv_wr32(dev, 0x418830, chipset != 0xc1 ? 0x00000001 : 0x10000001); + nv_wr32(dev, 0x4188d8, 0x00000008); + nv_wr32(dev, 0x4188e0, 0x01000000); + nv_wr32(dev, 0x4188e8, 0x00000000); +@@ -1684,7 +1602,7 @@ + nv_wr32(dev, 0x4188f0, 0x00000000); + nv_wr32(dev, 0x4188f4, 0x00000000); + nv_wr32(dev, 0x4188f8, 0x00000000); +- nv_wr32(dev, 0x4188fc, 0x00100000); ++ nv_wr32(dev, 0x4188fc, chipset != 0xc1 ? 0x00100000 : 0x00100018); + nv_wr32(dev, 0x41891c, 0x00ff00ff); + nv_wr32(dev, 0x418924, 0x00000000); + nv_wr32(dev, 0x418928, 0x00ffff00); +@@ -1715,6 +1633,8 @@ + nv_wr32(dev, 0x418c24, 0x00000000); + nv_wr32(dev, 0x418c28, 0x00000000); + nv_wr32(dev, 0x418c2c, 0x00000000); ++ if (chipset == 0xc1) ++ nv_wr32(dev, 0x418c6c, 0x00000001); + nv_wr32(dev, 0x418c80, 0x20200004); + nv_wr32(dev, 0x418c8c, 0x00000001); + nv_wr32(dev, 0x419000, 0x00000780); +@@ -1727,10 +1647,13 @@ + nvc0_grctx_generate_tp(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ int chipset = dev_priv->chipset; + + /* GPC_BROADCAST.TP_BROADCAST */ ++ nv_wr32(dev, 0x419818, 0x00000000); ++ nv_wr32(dev, 0x41983c, 0x00038bc7); + nv_wr32(dev, 0x419848, 0x00000000); +- nv_wr32(dev, 0x419864, 0x0000012a); ++ nv_wr32(dev, 0x419864, chipset != 0xc1 ? 0x0000012a : 0x00000129); + nv_wr32(dev, 0x419888, 0x00000000); + nv_wr32(dev, 0x419a00, 0x000001f0); + nv_wr32(dev, 0x419a04, 0x00000001); +@@ -1740,8 +1663,8 @@ + nv_wr32(dev, 0x419a14, 0x00000200); + nv_wr32(dev, 0x419a1c, 0x00000000); + nv_wr32(dev, 0x419a20, 0x00000800); +- if (dev_priv->chipset != 0xc0) +- nv_wr32(dev, 0x00419ac4, 0x0007f440); /* 0xc3 */ ++ if (chipset != 0xc0 && chipset != 0xc8) ++ nv_wr32(dev, 0x00419ac4, 0x0007f440); + nv_wr32(dev, 0x419b00, 0x0a418820); + nv_wr32(dev, 0x419b04, 0x062080e6); + nv_wr32(dev, 0x419b08, 0x020398a4); +@@ -1749,17 +1672,19 @@ + nv_wr32(dev, 0x419b10, 0x0a418820); + nv_wr32(dev, 0x419b14, 0x000000e6); + nv_wr32(dev, 0x419bd0, 0x00900103); +- nv_wr32(dev, 0x419be0, 0x00000001); ++ nv_wr32(dev, 0x419be0, chipset != 0xc1 ? 0x00000001 : 0x00400001); + nv_wr32(dev, 0x419be4, 0x00000000); + nv_wr32(dev, 0x419c00, 0x00000002); + nv_wr32(dev, 0x419c04, 0x00000006); + nv_wr32(dev, 0x419c08, 0x00000002); + nv_wr32(dev, 0x419c20, 0x00000000); +- nv_wr32(dev, 0x419cbc, 0x28137606); ++ nv_wr32(dev, 0x419cb0, 0x00060048); //XXX: 0xce 0x00020048 + nv_wr32(dev, 0x419ce8, 0x00000000); + nv_wr32(dev, 0x419cf4, 0x00000183); +- nv_wr32(dev, 0x419d20, 0x02180000); ++ nv_wr32(dev, 0x419d20, chipset != 0xc1 ? 0x02180000 : 0x12180000); + nv_wr32(dev, 0x419d24, 0x00001fff); ++ if (chipset == 0xc1) ++ nv_wr32(dev, 0x419d44, 0x02180218); + nv_wr32(dev, 0x419e04, 0x00000000); + nv_wr32(dev, 0x419e08, 0x00000000); + nv_wr32(dev, 0x419e0c, 0x00000000); +@@ -1785,11 +1710,11 @@ + nv_wr32(dev, 0x419e8c, 0x00000000); + nv_wr32(dev, 0x419e90, 0x00000000); + nv_wr32(dev, 0x419e98, 0x00000000); +- if (dev_priv->chipset != 0xc0) ++ if (chipset != 0xc0 && chipset != 0xc8) + nv_wr32(dev, 0x419ee0, 0x00011110); + nv_wr32(dev, 0x419f50, 0x00000000); + nv_wr32(dev, 0x419f54, 0x00000000); +- if (dev_priv->chipset != 0xc0) ++ if (chipset != 0xc0 && chipset != 0xc8) + nv_wr32(dev, 0x419f58, 0x00000000); + } + +@@ -1801,6 +1726,7 @@ + struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; + struct drm_device *dev = chan->dev; + int i, gpc, tp, id; ++ u32 fermi = nvc0_graph_class(dev); + u32 r000260, tmp; + + r000260 = nv_rd32(dev, 0x000260); +@@ -1857,10 +1783,11 @@ + nv_wr32(dev, 0x40587c, 0x00000000); + + if (1) { +- const u8 chipset_tp_max[] = { 16, 0, 0, 4, 8 }; ++ const u8 chipset_tp_max[] = { 16, 4, 0, 4, 8, 0, 0, 0, ++ 16, 0, 0, 0, 0, 0, 8, 0 }; + u8 max = chipset_tp_max[dev_priv->chipset & 0x0f]; + u8 tpnr[GPC_MAX]; +- u8 data[32]; ++ u8 data[TP_MAX]; + + memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); + memset(data, 0x1f, sizeof(data)); +@@ -2633,6 +2560,8 @@ + nv_icmd(dev, 0x0000053f, 0xffff0000); + nv_icmd(dev, 0x00000585, 0x0000003f); + nv_icmd(dev, 0x00000576, 0x00000003); ++ if (dev_priv->chipset == 0xc1) ++ nv_icmd(dev, 0x0000057b, 0x00000059); + nv_icmd(dev, 0x00000586, 0x00000040); + nv_icmd(dev, 0x00000582, 0x00000080); + nv_icmd(dev, 0x00000583, 0x00000080); +@@ -2865,6 +2794,10 @@ + nv_wr32(dev, 0x404154, 0x00000400); + + nvc0_grctx_generate_9097(dev); ++ if (fermi >= 0x9197) ++ nvc0_grctx_generate_9197(dev); ++ if (fermi >= 0x9297) ++ nvc0_grctx_generate_9297(dev); + nvc0_grctx_generate_902d(dev); + nvc0_grctx_generate_9039(dev); + nvc0_grctx_generate_90c0(dev); +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc 2011-06-26 07:59:23.000000000 +0200 +@@ -0,0 +1,474 @@ ++/* fuc microcode for nvc0 PGRAPH/GPC ++ * ++ * Copyright 2011 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 ++ */ ++ ++/* To build: ++ * m4 nvc0_grgpc.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grgpc.fuc.h ++ */ ++ ++/* TODO ++ * - bracket certain functions with scratch writes, useful for debugging ++ * - watchdog timer around ctx operations ++ */ ++ ++.section nvc0_grgpc_data ++include(`nvc0_graph.fuc') ++gpc_id: .b32 0 ++gpc_mmio_list_head: .b32 0 ++gpc_mmio_list_tail: .b32 0 ++ ++tpc_count: .b32 0 ++tpc_mask: .b32 0 ++tpc_mmio_list_head: .b32 0 ++tpc_mmio_list_tail: .b32 0 ++ ++cmd_queue: queue_init ++ ++// chipset descriptions ++chipsets: ++.b8 0xc0 0 0 0 ++.b16 nvc0_gpc_mmio_head ++.b16 nvc0_gpc_mmio_tail ++.b16 nvc0_tpc_mmio_head ++.b16 nvc0_tpc_mmio_tail ++.b8 0xc1 0 0 0 ++.b16 nvc0_gpc_mmio_head ++.b16 nvc1_gpc_mmio_tail ++.b16 nvc0_tpc_mmio_head ++.b16 nvc1_tpc_mmio_tail ++.b8 0xc3 0 0 0 ++.b16 nvc0_gpc_mmio_head ++.b16 nvc0_gpc_mmio_tail ++.b16 nvc0_tpc_mmio_head ++.b16 nvc3_tpc_mmio_tail ++.b8 0xc4 0 0 0 ++.b16 nvc0_gpc_mmio_head ++.b16 nvc0_gpc_mmio_tail ++.b16 nvc0_tpc_mmio_head ++.b16 nvc3_tpc_mmio_tail ++.b8 0xc8 0 0 0 ++.b16 nvc0_gpc_mmio_head ++.b16 nvc0_gpc_mmio_tail ++.b16 nvc0_tpc_mmio_head ++.b16 nvc0_tpc_mmio_tail ++.b8 0xce 0 0 0 ++.b16 nvc0_gpc_mmio_head ++.b16 nvc0_gpc_mmio_tail ++.b16 nvc0_tpc_mmio_head ++.b16 nvc3_tpc_mmio_tail ++.b8 0 0 0 0 ++ ++// GPC mmio lists ++nvc0_gpc_mmio_head: ++mmctx_data(0x000380, 1) ++mmctx_data(0x000400, 6) ++mmctx_data(0x000450, 9) ++mmctx_data(0x000600, 1) ++mmctx_data(0x000684, 1) ++mmctx_data(0x000700, 5) ++mmctx_data(0x000800, 1) ++mmctx_data(0x000808, 3) ++mmctx_data(0x000828, 1) ++mmctx_data(0x000830, 1) ++mmctx_data(0x0008d8, 1) ++mmctx_data(0x0008e0, 1) ++mmctx_data(0x0008e8, 6) ++mmctx_data(0x00091c, 1) ++mmctx_data(0x000924, 3) ++mmctx_data(0x000b00, 1) ++mmctx_data(0x000b08, 6) ++mmctx_data(0x000bb8, 1) ++mmctx_data(0x000c08, 1) ++mmctx_data(0x000c10, 8) ++mmctx_data(0x000c80, 1) ++mmctx_data(0x000c8c, 1) ++mmctx_data(0x001000, 3) ++mmctx_data(0x001014, 1) ++nvc0_gpc_mmio_tail: ++mmctx_data(0x000c6c, 1); ++nvc1_gpc_mmio_tail: ++ ++// TPC mmio lists ++nvc0_tpc_mmio_head: ++mmctx_data(0x000018, 1) ++mmctx_data(0x00003c, 1) ++mmctx_data(0x000048, 1) ++mmctx_data(0x000064, 1) ++mmctx_data(0x000088, 1) ++mmctx_data(0x000200, 6) ++mmctx_data(0x00021c, 2) ++mmctx_data(0x000300, 6) ++mmctx_data(0x0003d0, 1) ++mmctx_data(0x0003e0, 2) ++mmctx_data(0x000400, 3) ++mmctx_data(0x000420, 1) ++mmctx_data(0x0004b0, 1) ++mmctx_data(0x0004e8, 1) ++mmctx_data(0x0004f4, 1) ++mmctx_data(0x000520, 2) ++mmctx_data(0x000604, 4) ++mmctx_data(0x000644, 20) ++mmctx_data(0x000698, 1) ++mmctx_data(0x000750, 2) ++nvc0_tpc_mmio_tail: ++mmctx_data(0x000758, 1) ++mmctx_data(0x0002c4, 1) ++mmctx_data(0x0004bc, 1) ++mmctx_data(0x0006e0, 1) ++nvc3_tpc_mmio_tail: ++mmctx_data(0x000544, 1) ++nvc1_tpc_mmio_tail: ++ ++ ++.section nvc0_grgpc_code ++bra init ++define(`include_code') ++include(`nvc0_graph.fuc') ++ ++// reports an exception to the host ++// ++// In: $r15 error code (see nvc0_graph.fuc) ++// ++error: ++ push $r14 ++ mov $r14 -0x67ec // 0x9814 ++ sethi $r14 0x400000 ++ call nv_wr32 // HUB_CTXCTL_CC_SCRATCH[5] = error code ++ add b32 $r14 0x41c ++ mov $r15 1 ++ call nv_wr32 // HUB_CTXCTL_INTR_UP_SET ++ pop $r14 ++ ret ++ ++// GPC fuc initialisation, executed by triggering ucode start, will ++// fall through to main loop after completion. ++// ++// Input: ++// CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh) ++// CC_SCRATCH[1]: context base ++// ++// Output: ++// CC_SCRATCH[0]: ++// 31:31: set to signal completion ++// CC_SCRATCH[1]: ++// 31:0: GPC context size ++// ++init: ++ clear b32 $r0 ++ mov $sp $r0 ++ ++ // enable fifo access ++ mov $r1 0x1200 ++ mov $r2 2 ++ iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE ++ ++ // setup i0 handler, and route all interrupts to it ++ mov $r1 ih ++ mov $iv0 $r1 ++ mov $r1 0x400 ++ iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH ++ ++ // enable fifo interrupt ++ mov $r2 4 ++ iowr I[$r1 + 0x000] $r2 // INTR_EN_SET ++ ++ // enable interrupts ++ bset $flags ie0 ++ ++ // figure out which GPC we are, and how many TPCs we have ++ mov $r1 0x608 ++ shl b32 $r1 6 ++ iord $r2 I[$r1 + 0x000] // UNITS ++ mov $r3 1 ++ and $r2 0x1f ++ shl b32 $r3 $r2 ++ sub b32 $r3 1 ++ st b32 D[$r0 + tpc_count] $r2 ++ st b32 D[$r0 + tpc_mask] $r3 ++ add b32 $r1 0x400 ++ iord $r2 I[$r1 + 0x000] // MYINDEX ++ st b32 D[$r0 + gpc_id] $r2 ++ ++ // find context data for this chipset ++ mov $r2 0x800 ++ shl b32 $r2 6 ++ iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0] ++ mov $r1 chipsets - 12 ++ init_find_chipset: ++ add b32 $r1 12 ++ ld b32 $r3 D[$r1 + 0x00] ++ cmpu b32 $r3 $r2 ++ bra e init_context ++ cmpu b32 $r3 0 ++ bra ne init_find_chipset ++ // unknown chipset ++ ret ++ ++ // initialise context base, and size tracking ++ init_context: ++ mov $r2 0x800 ++ shl b32 $r2 6 ++ iord $r2 I[$r2 + 0x100] // CC_SCRATCH[1], initial base ++ clear b32 $r3 // track GPC context size here ++ ++ // set mmctx base addresses now so we don't have to do it later, ++ // they don't currently ever change ++ mov $r4 0x700 ++ shl b32 $r4 6 ++ shr b32 $r5 $r2 8 ++ iowr I[$r4 + 0x000] $r5 // MMCTX_SAVE_SWBASE ++ iowr I[$r4 + 0x100] $r5 // MMCTX_LOAD_SWBASE ++ ++ // calculate GPC mmio context size, store the chipset-specific ++ // mmio list pointers somewhere we can get at them later without ++ // re-parsing the chipset list ++ clear b32 $r14 ++ clear b32 $r15 ++ ld b16 $r14 D[$r1 + 4] ++ ld b16 $r15 D[$r1 + 6] ++ st b16 D[$r0 + gpc_mmio_list_head] $r14 ++ st b16 D[$r0 + gpc_mmio_list_tail] $r15 ++ call mmctx_size ++ add b32 $r2 $r15 ++ add b32 $r3 $r15 ++ ++ // calculate per-TPC mmio context size, store the list pointers ++ ld b16 $r14 D[$r1 + 8] ++ ld b16 $r15 D[$r1 + 10] ++ st b16 D[$r0 + tpc_mmio_list_head] $r14 ++ st b16 D[$r0 + tpc_mmio_list_tail] $r15 ++ call mmctx_size ++ ld b32 $r14 D[$r0 + tpc_count] ++ mulu $r14 $r15 ++ add b32 $r2 $r14 ++ add b32 $r3 $r14 ++ ++ // round up base/size to 256 byte boundary (for strand SWBASE) ++ add b32 $r4 0x1300 ++ shr b32 $r3 2 ++ iowr I[$r4 + 0x000] $r3 // MMCTX_LOAD_COUNT, wtf for?!? ++ shr b32 $r2 8 ++ shr b32 $r3 6 ++ add b32 $r2 1 ++ add b32 $r3 1 ++ shl b32 $r2 8 ++ shl b32 $r3 8 ++ ++ // calculate size of strand context data ++ mov b32 $r15 $r2 ++ call strand_ctx_init ++ add b32 $r3 $r15 ++ ++ // save context size, and tell HUB we're done ++ mov $r1 0x800 ++ shl b32 $r1 6 ++ iowr I[$r1 + 0x100] $r3 // CC_SCRATCH[1] = context size ++ add b32 $r1 0x800 ++ clear b32 $r2 ++ bset $r2 31 ++ iowr I[$r1 + 0x000] $r2 // CC_SCRATCH[0] |= 0x80000000 ++ ++// Main program loop, very simple, sleeps until woken up by the interrupt ++// handler, pulls a command from the queue and executes its handler ++// ++main: ++ bset $flags $p0 ++ sleep $p0 ++ mov $r13 cmd_queue ++ call queue_get ++ bra $p1 main ++ ++ // 0x0000-0x0003 are all context transfers ++ cmpu b32 $r14 0x04 ++ bra nc main_not_ctx_xfer ++ // fetch $flags and mask off $p1/$p2 ++ mov $r1 $flags ++ mov $r2 0x0006 ++ not b32 $r2 ++ and $r1 $r2 ++ // set $p1/$p2 according to transfer type ++ shl b32 $r14 1 ++ or $r1 $r14 ++ mov $flags $r1 ++ // transfer context data ++ call ctx_xfer ++ bra main ++ ++ main_not_ctx_xfer: ++ shl b32 $r15 $r14 16 ++ or $r15 E_BAD_COMMAND ++ call error ++ bra main ++ ++// interrupt handler ++ih: ++ push $r8 ++ mov $r8 $flags ++ push $r8 ++ push $r9 ++ push $r10 ++ push $r11 ++ push $r13 ++ push $r14 ++ push $r15 ++ ++ // incoming fifo command? ++ iord $r10 I[$r0 + 0x200] // INTR ++ and $r11 $r10 0x00000004 ++ bra e ih_no_fifo ++ // queue incoming fifo command for later processing ++ mov $r11 0x1900 ++ mov $r13 cmd_queue ++ iord $r14 I[$r11 + 0x100] // FIFO_CMD ++ iord $r15 I[$r11 + 0x000] // FIFO_DATA ++ call queue_put ++ add b32 $r11 0x400 ++ mov $r14 1 ++ iowr I[$r11 + 0x000] $r14 // FIFO_ACK ++ ++ // ack, and wake up main() ++ ih_no_fifo: ++ iowr I[$r0 + 0x100] $r10 // INTR_ACK ++ ++ pop $r15 ++ pop $r14 ++ pop $r13 ++ pop $r11 ++ pop $r10 ++ pop $r9 ++ pop $r8 ++ mov $flags $r8 ++ pop $r8 ++ bclr $flags $p0 ++ iret ++ ++// Set this GPC's bit in HUB_BAR, used to signal completion of various ++// activities to the HUB fuc ++// ++hub_barrier_done: ++ mov $r15 1 ++ ld b32 $r14 D[$r0 + gpc_id] ++ shl b32 $r15 $r14 ++ mov $r14 -0x6be8 // 0x409418 - HUB_BAR_SET ++ sethi $r14 0x400000 ++ call nv_wr32 ++ ret ++ ++// Disables various things, waits a bit, and re-enables them.. ++// ++// Not sure how exactly this helps, perhaps "ENABLE" is not such a ++// good description for the bits we turn off? Anyways, without this, ++// funny things happen. ++// ++ctx_redswitch: ++ mov $r14 0x614 ++ shl b32 $r14 6 ++ mov $r15 0x020 ++ iowr I[$r14] $r15 // GPC_RED_SWITCH = POWER ++ mov $r15 8 ++ ctx_redswitch_delay: ++ sub b32 $r15 1 ++ bra ne ctx_redswitch_delay ++ mov $r15 0xa20 ++ iowr I[$r14] $r15 // GPC_RED_SWITCH = UNK11, ENABLE, POWER ++ ret ++ ++// Transfer GPC context data between GPU and storage area ++// ++// In: $r15 context base address ++// $p1 clear on save, set on load ++// $p2 set if opposite direction done/will be done, so: ++// on save it means: "a load will follow this save" ++// on load it means: "a save preceeded this load" ++// ++ctx_xfer: ++ // set context base address ++ mov $r1 0xa04 ++ shl b32 $r1 6 ++ iowr I[$r1 + 0x000] $r15// MEM_BASE ++ bra not $p1 ctx_xfer_not_load ++ call ctx_redswitch ++ ctx_xfer_not_load: ++ ++ // strands ++ mov $r1 0x4afc ++ sethi $r1 0x20000 ++ mov $r2 0xc ++ iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c ++ call strand_wait ++ mov $r2 0x47fc ++ sethi $r2 0x20000 ++ iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00 ++ xbit $r2 $flags $p1 ++ add b32 $r2 3 ++ iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD) ++ ++ // mmio context ++ xbit $r10 $flags $p1 // direction ++ or $r10 2 // first ++ mov $r11 0x0000 ++ sethi $r11 0x500000 ++ ld b32 $r12 D[$r0 + gpc_id] ++ shl b32 $r12 15 ++ add b32 $r11 $r12 // base = NV_PGRAPH_GPCn ++ ld b32 $r12 D[$r0 + gpc_mmio_list_head] ++ ld b32 $r13 D[$r0 + gpc_mmio_list_tail] ++ mov $r14 0 // not multi ++ call mmctx_xfer ++ ++ // per-TPC mmio context ++ xbit $r10 $flags $p1 // direction ++ or $r10 4 // last ++ mov $r11 0x4000 ++ sethi $r11 0x500000 // base = NV_PGRAPH_GPC0_TPC0 ++ ld b32 $r12 D[$r0 + gpc_id] ++ shl b32 $r12 15 ++ add b32 $r11 $r12 // base = NV_PGRAPH_GPCn_TPC0 ++ ld b32 $r12 D[$r0 + tpc_mmio_list_head] ++ ld b32 $r13 D[$r0 + tpc_mmio_list_tail] ++ ld b32 $r15 D[$r0 + tpc_mask] ++ mov $r14 0x800 // stride = 0x800 ++ call mmctx_xfer ++ ++ // wait for strands to finish ++ call strand_wait ++ ++ // if load, or a save without a load following, do some ++ // unknown stuff that's done after finishing a block of ++ // strand commands ++ bra $p1 ctx_xfer_post ++ bra not $p2 ctx_xfer_done ++ ctx_xfer_post: ++ mov $r1 0x4afc ++ sethi $r1 0x20000 ++ mov $r2 0xd ++ iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0d ++ call strand_wait ++ ++ // mark completion in HUB's barrier ++ ctx_xfer_done: ++ call hub_barrier_done ++ ret ++ ++.align 256 +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h 2011-06-26 07:59:23.000000000 +0200 +@@ -0,0 +1,483 @@ ++uint32_t nvc0_grgpc_data[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x000000c0, ++ 0x011000b0, ++ 0x01640114, ++ 0x000000c1, ++ 0x011400b0, ++ 0x01780114, ++ 0x000000c3, ++ 0x011000b0, ++ 0x01740114, ++ 0x000000c4, ++ 0x011000b0, ++ 0x01740114, ++ 0x000000c8, ++ 0x011000b0, ++ 0x01640114, ++ 0x000000ce, ++ 0x011000b0, ++ 0x01740114, ++ 0x00000000, ++ 0x00000380, ++ 0x14000400, ++ 0x20000450, ++ 0x00000600, ++ 0x00000684, ++ 0x10000700, ++ 0x00000800, ++ 0x08000808, ++ 0x00000828, ++ 0x00000830, ++ 0x000008d8, ++ 0x000008e0, ++ 0x140008e8, ++ 0x0000091c, ++ 0x08000924, ++ 0x00000b00, ++ 0x14000b08, ++ 0x00000bb8, ++ 0x00000c08, ++ 0x1c000c10, ++ 0x00000c80, ++ 0x00000c8c, ++ 0x08001000, ++ 0x00001014, ++ 0x00000c6c, ++ 0x00000018, ++ 0x0000003c, ++ 0x00000048, ++ 0x00000064, ++ 0x00000088, ++ 0x14000200, ++ 0x0400021c, ++ 0x14000300, ++ 0x000003d0, ++ 0x040003e0, ++ 0x08000400, ++ 0x00000420, ++ 0x000004b0, ++ 0x000004e8, ++ 0x000004f4, ++ 0x04000520, ++ 0x0c000604, ++ 0x4c000644, ++ 0x00000698, ++ 0x04000750, ++ 0x00000758, ++ 0x000002c4, ++ 0x000004bc, ++ 0x000006e0, ++ 0x00000544, ++}; ++ ++uint32_t nvc0_grgpc_code[] = { ++ 0x03060ef5, ++ 0x9800d898, ++ 0x86f001d9, ++ 0x0489b808, ++ 0xf00c1bf4, ++ 0x21f502f7, ++ 0x00f802ec, ++ 0xb60798c4, ++ 0x8dbb0384, ++ 0x0880b600, ++ 0x80008e80, ++ 0x90b6018f, ++ 0x0f94f001, ++ 0xf801d980, ++ 0x0131f400, ++ 0x9800d898, ++ 0x89b801d9, ++ 0x210bf404, ++ 0xb60789c4, ++ 0x9dbb0394, ++ 0x0890b600, ++ 0x98009e98, ++ 0x80b6019f, ++ 0x0f84f001, ++ 0xf400d880, ++ 0x00f80132, ++ 0x0728b7f1, ++ 0xb906b4b6, ++ 0xc9f002ec, ++ 0x00bcd01f, ++ 0xc800bccf, ++ 0x1bf41fcc, ++ 0x06a7f0fa, ++ 0x010321f5, ++ 0xf840bfcf, ++ 0x28b7f100, ++ 0x06b4b607, ++ 0xb980bfd0, ++ 0xc9f002ec, ++ 0x1ec9f01f, ++ 0xcf00bcd0, ++ 0xccc800bc, ++ 0xfa1bf41f, ++ 0x87f100f8, ++ 0x84b60430, ++ 0x1ff9f006, ++ 0xf8008fd0, ++ 0x3087f100, ++ 0x0684b604, ++ 0xf80080d0, ++ 0x3c87f100, ++ 0x0684b608, ++ 0x99f094bd, ++ 0x0089d000, ++ 0x081887f1, ++ 0xd00684b6, ++ 0x87f1008a, ++ 0x84b60400, ++ 0x0088cf06, ++ 0xf4888aff, ++ 0x87f1f31b, ++ 0x84b6085c, ++ 0xf094bd06, ++ 0x89d00099, ++ 0xf100f800, ++ 0xb6083c87, ++ 0x94bd0684, ++ 0xd00099f0, ++ 0x87f10089, ++ 0x84b60818, ++ 0x008ad006, ++ 0x040087f1, ++ 0xcf0684b6, ++ 0x8aff0088, ++ 0xf30bf488, ++ 0x085c87f1, ++ 0xbd0684b6, ++ 0x0099f094, ++ 0xf80089d0, ++ 0x9894bd00, ++ 0x85b600e8, ++ 0x0180b61a, ++ 0xbb0284b6, ++ 0xe0b60098, ++ 0x04efb804, ++ 0xb9eb1bf4, ++ 0x00f8029f, ++ 0x083c87f1, ++ 0xbd0684b6, ++ 0x0199f094, ++ 0xf10089d0, ++ 0xb6071087, ++ 0x94bd0684, ++ 0xf405bbfd, ++ 0x8bd0090b, ++ 0x0099f000, ++ 0xf405eefd, ++ 0x8ed00c0b, ++ 0xc08fd080, ++ 0xb70199f0, ++ 0xc8010080, ++ 0xb4b600ab, ++ 0x0cb9f010, ++ 0xb601aec8, ++ 0xbefd11e4, ++ 0x008bd005, ++ 0xf0008ecf, ++ 0x0bf41fe4, ++ 0x00ce98fa, ++ 0xd005e9fd, ++ 0xc0b6c08e, ++ 0x04cdb804, ++ 0xc8e81bf4, ++ 0x1bf402ab, ++ 0x008bcf18, ++ 0xb01fb4f0, ++ 0x1bf410b4, ++ 0x02a7f0f7, ++ 0xf4c921f4, ++ 0xabc81b0e, ++ 0x10b4b600, ++ 0xf00cb9f0, ++ 0x8bd012b9, ++ 0x008bcf00, ++ 0xf412bbc8, ++ 0x87f1fa1b, ++ 0x84b6085c, ++ 0xf094bd06, ++ 0x89d00199, ++ 0xf900f800, ++ 0x02a7f0a0, ++ 0xfcc921f4, ++ 0xf100f8a0, ++ 0xf04afc87, ++ 0x97f00283, ++ 0x0089d00c, ++ 0x020721f5, ++ 0x87f100f8, ++ 0x83f04afc, ++ 0x0d97f002, ++ 0xf50089d0, ++ 0xf8020721, ++ 0xfca7f100, ++ 0x02a3f04f, ++ 0x0500aba2, ++ 0xd00fc7f0, ++ 0xc7f000ac, ++ 0x00bcd00b, ++ 0x020721f5, ++ 0xf000aed0, ++ 0xbcd00ac7, ++ 0x0721f500, ++ 0xf100f802, ++ 0xb6083c87, ++ 0x94bd0684, ++ 0xd00399f0, ++ 0x21f50089, ++ 0xe7f00213, ++ 0x3921f503, ++ 0xfca7f102, ++ 0x02a3f046, ++ 0x0400aba0, ++ 0xf040a0d0, ++ 0xbcd001c7, ++ 0x0721f500, ++ 0x010c9202, ++ 0xf000acd0, ++ 0xbcd002c7, ++ 0x0721f500, ++ 0x2621f502, ++ 0x8087f102, ++ 0x0684b608, ++ 0xb70089cf, ++ 0x95220080, ++ 0x8ed008fe, ++ 0x408ed000, ++ 0xb6808acf, ++ 0xa0b606a5, ++ 0x00eabb01, ++ 0xb60480b6, ++ 0x1bf40192, ++ 0x08e4b6e8, ++ 0xf1f2efbc, ++ 0xb6085c87, ++ 0x94bd0684, ++ 0xd00399f0, ++ 0x00f80089, ++ 0xe7f1e0f9, ++ 0xe3f09814, ++ 0x8d21f440, ++ 0x041ce0b7, ++ 0xf401f7f0, ++ 0xe0fc8d21, ++ 0x04bd00f8, ++ 0xf10004fe, ++ 0xf0120017, ++ 0x12d00227, ++ 0x3e17f100, ++ 0x0010fe04, ++ 0x040017f1, ++ 0xf0c010d0, ++ 0x12d00427, ++ 0x1031f400, ++ 0x060817f1, ++ 0xcf0614b6, ++ 0x37f00012, ++ 0x1f24f001, ++ 0xb60432bb, ++ 0x02800132, ++ 0x04038003, ++ 0x040010b7, ++ 0x800012cf, ++ 0x27f10002, ++ 0x24b60800, ++ 0x0022cf06, ++ 0xb65817f0, ++ 0x13980c10, ++ 0x0432b800, ++ 0xb00b0bf4, ++ 0x1bf40034, ++ 0xf100f8f1, ++ 0xb6080027, ++ 0x22cf0624, ++ 0xf134bd40, ++ 0xb6070047, ++ 0x25950644, ++ 0x0045d008, ++ 0xbd4045d0, ++ 0x58f4bde4, ++ 0x1f58021e, ++ 0x020e4003, ++ 0xf5040f40, ++ 0xbb013d21, ++ 0x3fbb002f, ++ 0x041e5800, ++ 0x40051f58, ++ 0x0f400a0e, ++ 0x3d21f50c, ++ 0x030e9801, ++ 0xbb00effd, ++ 0x3ebb002e, ++ 0x0040b700, ++ 0x0235b613, ++ 0xb60043d0, ++ 0x35b60825, ++ 0x0120b606, ++ 0xb60130b6, ++ 0x34b60824, ++ 0x022fb908, ++ 0x026321f5, ++ 0xf1003fbb, ++ 0xb6080017, ++ 0x13d00614, ++ 0x0010b740, ++ 0xf024bd08, ++ 0x12d01f29, ++ 0x0031f400, ++ 0xf00028f4, ++ 0x21f41cd7, ++ 0xf401f439, ++ 0xf404e4b0, ++ 0x81fe1e18, ++ 0x0627f001, ++ 0x12fd20bd, ++ 0x01e4b604, ++ 0xfe051efd, ++ 0x21f50018, ++ 0x0ef404c3, ++ 0x10ef94d3, ++ 0xf501f5f0, ++ 0xf402ec21, ++ 0x80f9c60e, ++ 0xf90188fe, ++ 0xf990f980, ++ 0xf9b0f9a0, ++ 0xf9e0f9d0, ++ 0x800acff0, ++ 0xf404abc4, ++ 0xb7f11d0b, ++ 0xd7f01900, ++ 0x40becf1c, ++ 0xf400bfcf, ++ 0xb0b70421, ++ 0xe7f00400, ++ 0x00bed001, ++ 0xfc400ad0, ++ 0xfce0fcf0, ++ 0xfcb0fcd0, ++ 0xfc90fca0, ++ 0x0088fe80, ++ 0x32f480fc, ++ 0xf001f800, ++ 0x0e9801f7, ++ 0x04febb00, ++ 0x9418e7f1, ++ 0xf440e3f0, ++ 0x00f88d21, ++ 0x0614e7f1, ++ 0xf006e4b6, ++ 0xefd020f7, ++ 0x08f7f000, ++ 0xf401f2b6, ++ 0xf7f1fd1b, ++ 0xefd00a20, ++ 0xf100f800, ++ 0xb60a0417, ++ 0x1fd00614, ++ 0x0711f400, ++ 0x04a421f5, ++ 0x4afc17f1, ++ 0xf00213f0, ++ 0x12d00c27, ++ 0x0721f500, ++ 0xfc27f102, ++ 0x0223f047, ++ 0xf00020d0, ++ 0x20b6012c, ++ 0x0012d003, ++ 0xf001acf0, ++ 0xb7f002a5, ++ 0x50b3f000, ++ 0xb6000c98, ++ 0xbcbb0fc4, ++ 0x010c9800, ++ 0xf0020d98, ++ 0x21f500e7, ++ 0xacf0015c, ++ 0x04a5f001, ++ 0x4000b7f1, ++ 0x9850b3f0, ++ 0xc4b6000c, ++ 0x00bcbb0f, ++ 0x98050c98, ++ 0x0f98060d, ++ 0x00e7f104, ++ 0x5c21f508, ++ 0x0721f501, ++ 0x0601f402, ++ 0xf11412f4, ++ 0xf04afc17, ++ 0x27f00213, ++ 0x0012d00d, ++ 0x020721f5, ++ 0x048f21f5, ++ 0x000000f8, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_grhub.fuc linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_grhub.fuc +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_grhub.fuc 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_grhub.fuc 2011-06-26 07:59:23.000000000 +0200 +@@ -0,0 +1,808 @@ ++/* fuc microcode for nvc0 PGRAPH/HUB ++ * ++ * Copyright 2011 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 ++ */ ++ ++/* To build: ++ * m4 nvc0_grhub.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grhub.fuc.h ++ */ ++ ++.section nvc0_grhub_data ++include(`nvc0_graph.fuc') ++gpc_count: .b32 0 ++rop_count: .b32 0 ++cmd_queue: queue_init ++hub_mmio_list_head: .b32 0 ++hub_mmio_list_tail: .b32 0 ++ ++ctx_current: .b32 0 ++ ++chipsets: ++.b8 0xc0 0 0 0 ++.b16 nvc0_hub_mmio_head ++.b16 nvc0_hub_mmio_tail ++.b8 0xc1 0 0 0 ++.b16 nvc0_hub_mmio_head ++.b16 nvc1_hub_mmio_tail ++.b8 0xc3 0 0 0 ++.b16 nvc0_hub_mmio_head ++.b16 nvc0_hub_mmio_tail ++.b8 0xc4 0 0 0 ++.b16 nvc0_hub_mmio_head ++.b16 nvc0_hub_mmio_tail ++.b8 0xc8 0 0 0 ++.b16 nvc0_hub_mmio_head ++.b16 nvc0_hub_mmio_tail ++.b8 0xce 0 0 0 ++.b16 nvc0_hub_mmio_head ++.b16 nvc0_hub_mmio_tail ++.b8 0 0 0 0 ++ ++nvc0_hub_mmio_head: ++mmctx_data(0x17e91c, 2) ++mmctx_data(0x400204, 2) ++mmctx_data(0x404004, 11) ++mmctx_data(0x404044, 1) ++mmctx_data(0x404094, 14) ++mmctx_data(0x4040d0, 7) ++mmctx_data(0x4040f8, 1) ++mmctx_data(0x404130, 3) ++mmctx_data(0x404150, 3) ++mmctx_data(0x404164, 2) ++mmctx_data(0x404174, 3) ++mmctx_data(0x404200, 8) ++mmctx_data(0x404404, 14) ++mmctx_data(0x404460, 4) ++mmctx_data(0x404480, 1) ++mmctx_data(0x404498, 1) ++mmctx_data(0x404604, 4) ++mmctx_data(0x404618, 32) ++mmctx_data(0x404698, 21) ++mmctx_data(0x4046f0, 2) ++mmctx_data(0x404700, 22) ++mmctx_data(0x405800, 1) ++mmctx_data(0x405830, 3) ++mmctx_data(0x405854, 1) ++mmctx_data(0x405870, 4) ++mmctx_data(0x405a00, 2) ++mmctx_data(0x405a18, 1) ++mmctx_data(0x406020, 1) ++mmctx_data(0x406028, 4) ++mmctx_data(0x4064a8, 2) ++mmctx_data(0x4064b4, 2) ++mmctx_data(0x407804, 1) ++mmctx_data(0x40780c, 6) ++mmctx_data(0x4078bc, 1) ++mmctx_data(0x408000, 7) ++mmctx_data(0x408064, 1) ++mmctx_data(0x408800, 3) ++mmctx_data(0x408900, 4) ++mmctx_data(0x408980, 1) ++nvc0_hub_mmio_tail: ++mmctx_data(0x4064c0, 2) ++nvc1_hub_mmio_tail: ++ ++.align 256 ++chan_data: ++chan_mmio_count: .b32 0 ++chan_mmio_address: .b32 0 ++ ++.align 256 ++xfer_data: .b32 0 ++ ++.section nvc0_grhub_code ++bra init ++define(`include_code') ++include(`nvc0_graph.fuc') ++ ++// reports an exception to the host ++// ++// In: $r15 error code (see nvc0_graph.fuc) ++// ++error: ++ push $r14 ++ mov $r14 0x814 ++ shl b32 $r14 6 ++ iowr I[$r14 + 0x000] $r15 // CC_SCRATCH[5] = error code ++ mov $r14 0xc1c ++ shl b32 $r14 6 ++ mov $r15 1 ++ iowr I[$r14 + 0x000] $r15 // INTR_UP_SET ++ pop $r14 ++ ret ++ ++// HUB fuc initialisation, executed by triggering ucode start, will ++// fall through to main loop after completion. ++// ++// Input: ++// CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh) ++// ++// Output: ++// CC_SCRATCH[0]: ++// 31:31: set to signal completion ++// CC_SCRATCH[1]: ++// 31:0: total PGRAPH context size ++// ++init: ++ clear b32 $r0 ++ mov $sp $r0 ++ mov $xdbase $r0 ++ ++ // enable fifo access ++ mov $r1 0x1200 ++ mov $r2 2 ++ iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE ++ ++ // setup i0 handler, and route all interrupts to it ++ mov $r1 ih ++ mov $iv0 $r1 ++ mov $r1 0x400 ++ iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH ++ ++ // route HUB_CHANNEL_SWITCH to fuc interrupt 8 ++ mov $r3 0x404 ++ shl b32 $r3 6 ++ mov $r2 0x2003 // { HUB_CHANNEL_SWITCH, ZERO } -> intr 8 ++ iowr I[$r3 + 0x000] $r2 ++ ++ // not sure what these are, route them because NVIDIA does, and ++ // the IRQ handler will signal the host if we ever get one.. we ++ // may find out if/why we need to handle these if so.. ++ // ++ mov $r2 0x2004 ++ iowr I[$r3 + 0x004] $r2 // { 0x04, ZERO } -> intr 9 ++ mov $r2 0x200b ++ iowr I[$r3 + 0x008] $r2 // { 0x0b, ZERO } -> intr 10 ++ mov $r2 0x200c ++ iowr I[$r3 + 0x01c] $r2 // { 0x0c, ZERO } -> intr 15 ++ ++ // enable all INTR_UP interrupts ++ mov $r2 0xc24 ++ shl b32 $r2 6 ++ not b32 $r3 $r0 ++ iowr I[$r2] $r3 ++ ++ // enable fifo, ctxsw, 9, 10, 15 interrupts ++ mov $r2 -0x78fc // 0x8704 ++ sethi $r2 0 ++ iowr I[$r1 + 0x000] $r2 // INTR_EN_SET ++ ++ // fifo level triggered, rest edge ++ sub b32 $r1 0x100 ++ mov $r2 4 ++ iowr I[$r1] $r2 ++ ++ // enable interrupts ++ bset $flags ie0 ++ ++ // fetch enabled GPC/ROP counts ++ mov $r14 -0x69fc // 0x409604 ++ sethi $r14 0x400000 ++ call nv_rd32 ++ extr $r1 $r15 16:20 ++ st b32 D[$r0 + rop_count] $r1 ++ and $r15 0x1f ++ st b32 D[$r0 + gpc_count] $r15 ++ ++ // set BAR_REQMASK to GPC mask ++ mov $r1 1 ++ shl b32 $r1 $r15 ++ sub b32 $r1 1 ++ mov $r2 0x40c ++ shl b32 $r2 6 ++ iowr I[$r2 + 0x000] $r1 ++ iowr I[$r2 + 0x100] $r1 ++ ++ // find context data for this chipset ++ mov $r2 0x800 ++ shl b32 $r2 6 ++ iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0] ++ mov $r15 chipsets - 8 ++ init_find_chipset: ++ add b32 $r15 8 ++ ld b32 $r3 D[$r15 + 0x00] ++ cmpu b32 $r3 $r2 ++ bra e init_context ++ cmpu b32 $r3 0 ++ bra ne init_find_chipset ++ // unknown chipset ++ ret ++ ++ // context size calculation, reserve first 256 bytes for use by fuc ++ init_context: ++ mov $r1 256 ++ ++ // calculate size of mmio context data ++ ld b16 $r14 D[$r15 + 4] ++ ld b16 $r15 D[$r15 + 6] ++ sethi $r14 0 ++ st b32 D[$r0 + hub_mmio_list_head] $r14 ++ st b32 D[$r0 + hub_mmio_list_tail] $r15 ++ call mmctx_size ++ ++ // set mmctx base addresses now so we don't have to do it later, ++ // they don't (currently) ever change ++ mov $r3 0x700 ++ shl b32 $r3 6 ++ shr b32 $r4 $r1 8 ++ iowr I[$r3 + 0x000] $r4 // MMCTX_SAVE_SWBASE ++ iowr I[$r3 + 0x100] $r4 // MMCTX_LOAD_SWBASE ++ add b32 $r3 0x1300 ++ add b32 $r1 $r15 ++ shr b32 $r15 2 ++ iowr I[$r3 + 0x000] $r15 // MMCTX_LOAD_COUNT, wtf for?!? ++ ++ // strands, base offset needs to be aligned to 256 bytes ++ shr b32 $r1 8 ++ add b32 $r1 1 ++ shl b32 $r1 8 ++ mov b32 $r15 $r1 ++ call strand_ctx_init ++ add b32 $r1 $r15 ++ ++ // initialise each GPC in sequence by passing in the offset of its ++ // context data in GPCn_CC_SCRATCH[1], and starting its FUC (which ++ // has previously been uploaded by the host) running. ++ // ++ // the GPC fuc init sequence will set GPCn_CC_SCRATCH[0] bit 31 ++ // when it has completed, and return the size of its context data ++ // in GPCn_CC_SCRATCH[1] ++ // ++ ld b32 $r3 D[$r0 + gpc_count] ++ mov $r4 0x2000 ++ sethi $r4 0x500000 ++ init_gpc: ++ // setup, and start GPC ucode running ++ add b32 $r14 $r4 0x804 ++ mov b32 $r15 $r1 ++ call nv_wr32 // CC_SCRATCH[1] = ctx offset ++ add b32 $r14 $r4 0x800 ++ mov b32 $r15 $r2 ++ call nv_wr32 // CC_SCRATCH[0] = chipset ++ add b32 $r14 $r4 0x10c ++ clear b32 $r15 ++ call nv_wr32 ++ add b32 $r14 $r4 0x104 ++ call nv_wr32 // ENTRY ++ add b32 $r14 $r4 0x100 ++ mov $r15 2 // CTRL_START_TRIGGER ++ call nv_wr32 // CTRL ++ ++ // wait for it to complete, and adjust context size ++ add b32 $r14 $r4 0x800 ++ init_gpc_wait: ++ call nv_rd32 ++ xbit $r15 $r15 31 ++ bra e init_gpc_wait ++ add b32 $r14 $r4 0x804 ++ call nv_rd32 ++ add b32 $r1 $r15 ++ ++ // next! ++ add b32 $r4 0x8000 ++ sub b32 $r3 1 ++ bra ne init_gpc ++ ++ // save context size, and tell host we're ready ++ mov $r2 0x800 ++ shl b32 $r2 6 ++ iowr I[$r2 + 0x100] $r1 // CC_SCRATCH[1] = context size ++ add b32 $r2 0x800 ++ clear b32 $r1 ++ bset $r1 31 ++ iowr I[$r2 + 0x000] $r1 // CC_SCRATCH[0] |= 0x80000000 ++ ++// Main program loop, very simple, sleeps until woken up by the interrupt ++// handler, pulls a command from the queue and executes its handler ++// ++main: ++ // sleep until we have something to do ++ bset $flags $p0 ++ sleep $p0 ++ mov $r13 cmd_queue ++ call queue_get ++ bra $p1 main ++ ++ // context switch, requested by GPU? ++ cmpu b32 $r14 0x4001 ++ bra ne main_not_ctx_switch ++ trace_set(T_AUTO) ++ mov $r1 0xb00 ++ shl b32 $r1 6 ++ iord $r2 I[$r1 + 0x100] // CHAN_NEXT ++ iord $r1 I[$r1 + 0x000] // CHAN_CUR ++ ++ xbit $r3 $r1 31 ++ bra e chsw_no_prev ++ xbit $r3 $r2 31 ++ bra e chsw_prev_no_next ++ push $r2 ++ mov b32 $r2 $r1 ++ trace_set(T_SAVE) ++ bclr $flags $p1 ++ bset $flags $p2 ++ call ctx_xfer ++ trace_clr(T_SAVE); ++ pop $r2 ++ trace_set(T_LOAD); ++ bset $flags $p1 ++ call ctx_xfer ++ trace_clr(T_LOAD); ++ bra chsw_done ++ chsw_prev_no_next: ++ push $r2 ++ mov b32 $r2 $r1 ++ bclr $flags $p1 ++ bclr $flags $p2 ++ call ctx_xfer ++ pop $r2 ++ mov $r1 0xb00 ++ shl b32 $r1 6 ++ iowr I[$r1] $r2 ++ bra chsw_done ++ chsw_no_prev: ++ xbit $r3 $r2 31 ++ bra e chsw_done ++ bset $flags $p1 ++ bclr $flags $p2 ++ call ctx_xfer ++ ++ // ack the context switch request ++ chsw_done: ++ mov $r1 0xb0c ++ shl b32 $r1 6 ++ mov $r2 1 ++ iowr I[$r1 + 0x000] $r2 // 0x409b0c ++ trace_clr(T_AUTO) ++ bra main ++ ++ // request to set current channel? (*not* a context switch) ++ main_not_ctx_switch: ++ cmpu b32 $r14 0x0001 ++ bra ne main_not_ctx_chan ++ mov b32 $r2 $r15 ++ call ctx_chan ++ bra main_done ++ ++ // request to store current channel context? ++ main_not_ctx_chan: ++ cmpu b32 $r14 0x0002 ++ bra ne main_not_ctx_save ++ trace_set(T_SAVE) ++ bclr $flags $p1 ++ bclr $flags $p2 ++ call ctx_xfer ++ trace_clr(T_SAVE) ++ bra main_done ++ ++ main_not_ctx_save: ++ shl b32 $r15 $r14 16 ++ or $r15 E_BAD_COMMAND ++ call error ++ bra main ++ ++ main_done: ++ mov $r1 0x820 ++ shl b32 $r1 6 ++ clear b32 $r2 ++ bset $r2 31 ++ iowr I[$r1 + 0x000] $r2 // CC_SCRATCH[0] |= 0x80000000 ++ bra main ++ ++// interrupt handler ++ih: ++ push $r8 ++ mov $r8 $flags ++ push $r8 ++ push $r9 ++ push $r10 ++ push $r11 ++ push $r13 ++ push $r14 ++ push $r15 ++ ++ // incoming fifo command? ++ iord $r10 I[$r0 + 0x200] // INTR ++ and $r11 $r10 0x00000004 ++ bra e ih_no_fifo ++ // queue incoming fifo command for later processing ++ mov $r11 0x1900 ++ mov $r13 cmd_queue ++ iord $r14 I[$r11 + 0x100] // FIFO_CMD ++ iord $r15 I[$r11 + 0x000] // FIFO_DATA ++ call queue_put ++ add b32 $r11 0x400 ++ mov $r14 1 ++ iowr I[$r11 + 0x000] $r14 // FIFO_ACK ++ ++ // context switch request? ++ ih_no_fifo: ++ and $r11 $r10 0x00000100 ++ bra e ih_no_ctxsw ++ // enqueue a context switch for later processing ++ mov $r13 cmd_queue ++ mov $r14 0x4001 ++ call queue_put ++ ++ // anything we didn't handle, bring it to the host's attention ++ ih_no_ctxsw: ++ mov $r11 0x104 ++ not b32 $r11 ++ and $r11 $r10 $r11 ++ bra e ih_no_other ++ mov $r10 0xc1c ++ shl b32 $r10 6 ++ iowr I[$r10] $r11 // INTR_UP_SET ++ ++ // ack, and wake up main() ++ ih_no_other: ++ iowr I[$r0 + 0x100] $r10 // INTR_ACK ++ ++ pop $r15 ++ pop $r14 ++ pop $r13 ++ pop $r11 ++ pop $r10 ++ pop $r9 ++ pop $r8 ++ mov $flags $r8 ++ pop $r8 ++ bclr $flags $p0 ++ iret ++ ++// Not real sure, but, MEM_CMD 7 will hang forever if this isn't done ++ctx_4160s: ++ mov $r14 0x4160 ++ sethi $r14 0x400000 ++ mov $r15 1 ++ call nv_wr32 ++ ctx_4160s_wait: ++ call nv_rd32 ++ xbit $r15 $r15 4 ++ bra e ctx_4160s_wait ++ ret ++ ++// Without clearing again at end of xfer, some things cause PGRAPH ++// to hang with STATUS=0x00000007 until it's cleared.. fbcon can ++// still function with it set however... ++ctx_4160c: ++ mov $r14 0x4160 ++ sethi $r14 0x400000 ++ clear b32 $r15 ++ call nv_wr32 ++ ret ++ ++// Again, not real sure ++// ++// In: $r15 value to set 0x404170 to ++// ++ctx_4170s: ++ mov $r14 0x4170 ++ sethi $r14 0x400000 ++ or $r15 0x10 ++ call nv_wr32 ++ ret ++ ++// Waits for a ctx_4170s() call to complete ++// ++ctx_4170w: ++ mov $r14 0x4170 ++ sethi $r14 0x400000 ++ call nv_rd32 ++ and $r15 0x10 ++ bra ne ctx_4170w ++ ret ++ ++// Disables various things, waits a bit, and re-enables them.. ++// ++// Not sure how exactly this helps, perhaps "ENABLE" is not such a ++// good description for the bits we turn off? Anyways, without this, ++// funny things happen. ++// ++ctx_redswitch: ++ mov $r14 0x614 ++ shl b32 $r14 6 ++ mov $r15 0x270 ++ iowr I[$r14] $r15 // HUB_RED_SWITCH = ENABLE_GPC, POWER_ALL ++ mov $r15 8 ++ ctx_redswitch_delay: ++ sub b32 $r15 1 ++ bra ne ctx_redswitch_delay ++ mov $r15 0x770 ++ iowr I[$r14] $r15 // HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL ++ ret ++ ++// Not a clue what this is for, except that unless the value is 0x10, the ++// strand context is saved (and presumably restored) incorrectly.. ++// ++// In: $r15 value to set to (0x00/0x10 are used) ++// ++ctx_86c: ++ mov $r14 0x86c ++ shl b32 $r14 6 ++ iowr I[$r14] $r15 // HUB(0x86c) = val ++ mov $r14 -0x75ec ++ sethi $r14 0x400000 ++ call nv_wr32 // ROP(0xa14) = val ++ mov $r14 -0x5794 ++ sethi $r14 0x410000 ++ call nv_wr32 // GPC(0x86c) = val ++ ret ++ ++// ctx_load - load's a channel's ctxctl data, and selects its vm ++// ++// In: $r2 channel address ++// ++ctx_load: ++ trace_set(T_CHAN) ++ ++ // switch to channel, somewhat magic in parts.. ++ mov $r10 12 // DONE_UNK12 ++ call wait_donez ++ mov $r1 0xa24 ++ shl b32 $r1 6 ++ iowr I[$r1 + 0x000] $r0 // 0x409a24 ++ mov $r3 0xb00 ++ shl b32 $r3 6 ++ iowr I[$r3 + 0x100] $r2 // CHAN_NEXT ++ mov $r1 0xa0c ++ shl b32 $r1 6 ++ mov $r4 7 ++ iowr I[$r1 + 0x000] $r2 // MEM_CHAN ++ iowr I[$r1 + 0x100] $r4 // MEM_CMD ++ ctx_chan_wait_0: ++ iord $r4 I[$r1 + 0x100] ++ and $r4 0x1f ++ bra ne ctx_chan_wait_0 ++ iowr I[$r3 + 0x000] $r2 // CHAN_CUR ++ ++ // load channel header, fetch PGRAPH context pointer ++ mov $xtargets $r0 ++ bclr $r2 31 ++ shl b32 $r2 4 ++ add b32 $r2 2 ++ ++ trace_set(T_LCHAN) ++ mov $r1 0xa04 ++ shl b32 $r1 6 ++ iowr I[$r1 + 0x000] $r2 // MEM_BASE ++ mov $r1 0xa20 ++ shl b32 $r1 6 ++ mov $r2 0x0002 ++ sethi $r2 0x80000000 ++ iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vram ++ mov $r1 0x10 // chan + 0x0210 ++ mov $r2 xfer_data ++ sethi $r2 0x00020000 // 16 bytes ++ xdld $r1 $r2 ++ xdwait ++ trace_clr(T_LCHAN) ++ ++ // update current context ++ ld b32 $r1 D[$r0 + xfer_data + 4] ++ shl b32 $r1 24 ++ ld b32 $r2 D[$r0 + xfer_data + 0] ++ shr b32 $r2 8 ++ or $r1 $r2 ++ st b32 D[$r0 + ctx_current] $r1 ++ ++ // set transfer base to start of context, and fetch context header ++ trace_set(T_LCTXH) ++ mov $r2 0xa04 ++ shl b32 $r2 6 ++ iowr I[$r2 + 0x000] $r1 // MEM_BASE ++ mov $r2 1 ++ mov $r1 0xa20 ++ shl b32 $r1 6 ++ iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vm ++ mov $r1 chan_data ++ sethi $r1 0x00060000 // 256 bytes ++ xdld $r0 $r1 ++ xdwait ++ trace_clr(T_LCTXH) ++ ++ trace_clr(T_CHAN) ++ ret ++ ++// ctx_chan - handler for HUB_SET_CHAN command, will set a channel as ++// the active channel for ctxctl, but not actually transfer ++// any context data. intended for use only during initial ++// context construction. ++// ++// In: $r2 channel address ++// ++ctx_chan: ++ call ctx_4160s ++ call ctx_load ++ mov $r10 12 // DONE_UNK12 ++ call wait_donez ++ mov $r1 0xa10 ++ shl b32 $r1 6 ++ mov $r2 5 ++ iowr I[$r1 + 0x000] $r2 // MEM_CMD = 5 (???) ++ ctx_chan_wait: ++ iord $r2 I[$r1 + 0x000] ++ or $r2 $r2 ++ bra ne ctx_chan_wait ++ call ctx_4160c ++ ret ++ ++// Execute per-context state overrides list ++// ++// Only executed on the first load of a channel. Might want to look into ++// removing this and having the host directly modify the channel's context ++// to change this state... The nouveau DRM already builds this list as ++// it's definitely needed for NVIDIA's, so we may as well use it for now ++// ++// Input: $r1 mmio list length ++// ++ctx_mmio_exec: ++ // set transfer base to be the mmio list ++ ld b32 $r3 D[$r0 + chan_mmio_address] ++ mov $r2 0xa04 ++ shl b32 $r2 6 ++ iowr I[$r2 + 0x000] $r3 // MEM_BASE ++ ++ clear b32 $r3 ++ ctx_mmio_loop: ++ // fetch next 256 bytes of mmio list if necessary ++ and $r4 $r3 0xff ++ bra ne ctx_mmio_pull ++ mov $r5 xfer_data ++ sethi $r5 0x00060000 // 256 bytes ++ xdld $r3 $r5 ++ xdwait ++ ++ // execute a single list entry ++ ctx_mmio_pull: ++ ld b32 $r14 D[$r4 + xfer_data + 0x00] ++ ld b32 $r15 D[$r4 + xfer_data + 0x04] ++ call nv_wr32 ++ ++ // next! ++ add b32 $r3 8 ++ sub b32 $r1 1 ++ bra ne ctx_mmio_loop ++ ++ // set transfer base back to the current context ++ ctx_mmio_done: ++ ld b32 $r3 D[$r0 + ctx_current] ++ iowr I[$r2 + 0x000] $r3 // MEM_BASE ++ ++ // disable the mmio list now, we don't need/want to execute it again ++ st b32 D[$r0 + chan_mmio_count] $r0 ++ mov $r1 chan_data ++ sethi $r1 0x00060000 // 256 bytes ++ xdst $r0 $r1 ++ xdwait ++ ret ++ ++// Transfer HUB context data between GPU and storage area ++// ++// In: $r2 channel address ++// $p1 clear on save, set on load ++// $p2 set if opposite direction done/will be done, so: ++// on save it means: "a load will follow this save" ++// on load it means: "a save preceeded this load" ++// ++ctx_xfer: ++ bra not $p1 ctx_xfer_pre ++ bra $p2 ctx_xfer_pre_load ++ ctx_xfer_pre: ++ mov $r15 0x10 ++ call ctx_86c ++ call ctx_4160s ++ bra not $p1 ctx_xfer_exec ++ ++ ctx_xfer_pre_load: ++ mov $r15 2 ++ call ctx_4170s ++ call ctx_4170w ++ call ctx_redswitch ++ clear b32 $r15 ++ call ctx_4170s ++ call ctx_load ++ ++ // fetch context pointer, and initiate xfer on all GPCs ++ ctx_xfer_exec: ++ ld b32 $r1 D[$r0 + ctx_current] ++ mov $r2 0x414 ++ shl b32 $r2 6 ++ iowr I[$r2 + 0x000] $r0 // BAR_STATUS = reset ++ mov $r14 -0x5b00 ++ sethi $r14 0x410000 ++ mov b32 $r15 $r1 ++ call nv_wr32 // GPC_BCAST_WRCMD_DATA = ctx pointer ++ add b32 $r14 4 ++ xbit $r15 $flags $p1 ++ xbit $r2 $flags $p2 ++ shl b32 $r2 1 ++ or $r15 $r2 ++ call nv_wr32 // GPC_BCAST_WRCMD_CMD = GPC_XFER(type) ++ ++ // strands ++ mov $r1 0x4afc ++ sethi $r1 0x20000 ++ mov $r2 0xc ++ iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c ++ call strand_wait ++ mov $r2 0x47fc ++ sethi $r2 0x20000 ++ iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00 ++ xbit $r2 $flags $p1 ++ add b32 $r2 3 ++ iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD) ++ ++ // mmio context ++ xbit $r10 $flags $p1 // direction ++ or $r10 6 // first, last ++ mov $r11 0 // base = 0 ++ ld b32 $r12 D[$r0 + hub_mmio_list_head] ++ ld b32 $r13 D[$r0 + hub_mmio_list_tail] ++ mov $r14 0 // not multi ++ call mmctx_xfer ++ ++ // wait for GPCs to all complete ++ mov $r10 8 // DONE_BAR ++ call wait_doneo ++ ++ // wait for strand xfer to complete ++ call strand_wait ++ ++ // post-op ++ bra $p1 ctx_xfer_post ++ mov $r10 12 // DONE_UNK12 ++ call wait_donez ++ mov $r1 0xa10 ++ shl b32 $r1 6 ++ mov $r2 5 ++ iowr I[$r1] $r2 // MEM_CMD ++ ctx_xfer_post_save_wait: ++ iord $r2 I[$r1] ++ or $r2 $r2 ++ bra ne ctx_xfer_post_save_wait ++ ++ bra $p2 ctx_xfer_done ++ ctx_xfer_post: ++ mov $r15 2 ++ call ctx_4170s ++ clear b32 $r15 ++ call ctx_86c ++ call strand_post ++ call ctx_4170w ++ clear b32 $r15 ++ call ctx_4170s ++ ++ bra not $p1 ctx_xfer_no_post_mmio ++ ld b32 $r1 D[$r0 + chan_mmio_count] ++ or $r1 $r1 ++ bra e ctx_xfer_no_post_mmio ++ call ctx_mmio_exec ++ ++ ctx_xfer_no_post_mmio: ++ call ctx_4160c ++ ++ ctx_xfer_done: ++ ret ++ ++.align 256 +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h 2011-06-26 07:59:23.000000000 +0200 +@@ -0,0 +1,838 @@ ++uint32_t nvc0_grhub_data[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x000000c0, ++ 0x012c0090, ++ 0x000000c1, ++ 0x01300090, ++ 0x000000c3, ++ 0x012c0090, ++ 0x000000c4, ++ 0x012c0090, ++ 0x000000c8, ++ 0x012c0090, ++ 0x000000ce, ++ 0x012c0090, ++ 0x00000000, ++ 0x0417e91c, ++ 0x04400204, ++ 0x28404004, ++ 0x00404044, ++ 0x34404094, ++ 0x184040d0, ++ 0x004040f8, ++ 0x08404130, ++ 0x08404150, ++ 0x04404164, ++ 0x08404174, ++ 0x1c404200, ++ 0x34404404, ++ 0x0c404460, ++ 0x00404480, ++ 0x00404498, ++ 0x0c404604, ++ 0x7c404618, ++ 0x50404698, ++ 0x044046f0, ++ 0x54404700, ++ 0x00405800, ++ 0x08405830, ++ 0x00405854, ++ 0x0c405870, ++ 0x04405a00, ++ 0x00405a18, ++ 0x00406020, ++ 0x0c406028, ++ 0x044064a8, ++ 0x044064b4, ++ 0x00407804, ++ 0x1440780c, ++ 0x004078bc, ++ 0x18408000, ++ 0x00408064, ++ 0x08408800, ++ 0x0c408900, ++ 0x00408980, ++ 0x044064c0, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++uint32_t nvc0_grhub_code[] = { ++ 0x03090ef5, ++ 0x9800d898, ++ 0x86f001d9, ++ 0x0489b808, ++ 0xf00c1bf4, ++ 0x21f502f7, ++ 0x00f802ec, ++ 0xb60798c4, ++ 0x8dbb0384, ++ 0x0880b600, ++ 0x80008e80, ++ 0x90b6018f, ++ 0x0f94f001, ++ 0xf801d980, ++ 0x0131f400, ++ 0x9800d898, ++ 0x89b801d9, ++ 0x210bf404, ++ 0xb60789c4, ++ 0x9dbb0394, ++ 0x0890b600, ++ 0x98009e98, ++ 0x80b6019f, ++ 0x0f84f001, ++ 0xf400d880, ++ 0x00f80132, ++ 0x0728b7f1, ++ 0xb906b4b6, ++ 0xc9f002ec, ++ 0x00bcd01f, ++ 0xc800bccf, ++ 0x1bf41fcc, ++ 0x06a7f0fa, ++ 0x010321f5, ++ 0xf840bfcf, ++ 0x28b7f100, ++ 0x06b4b607, ++ 0xb980bfd0, ++ 0xc9f002ec, ++ 0x1ec9f01f, ++ 0xcf00bcd0, ++ 0xccc800bc, ++ 0xfa1bf41f, ++ 0x87f100f8, ++ 0x84b60430, ++ 0x1ff9f006, ++ 0xf8008fd0, ++ 0x3087f100, ++ 0x0684b604, ++ 0xf80080d0, ++ 0x3c87f100, ++ 0x0684b608, ++ 0x99f094bd, ++ 0x0089d000, ++ 0x081887f1, ++ 0xd00684b6, ++ 0x87f1008a, ++ 0x84b60400, ++ 0x0088cf06, ++ 0xf4888aff, ++ 0x87f1f31b, ++ 0x84b6085c, ++ 0xf094bd06, ++ 0x89d00099, ++ 0xf100f800, ++ 0xb6083c87, ++ 0x94bd0684, ++ 0xd00099f0, ++ 0x87f10089, ++ 0x84b60818, ++ 0x008ad006, ++ 0x040087f1, ++ 0xcf0684b6, ++ 0x8aff0088, ++ 0xf30bf488, ++ 0x085c87f1, ++ 0xbd0684b6, ++ 0x0099f094, ++ 0xf80089d0, ++ 0x9894bd00, ++ 0x85b600e8, ++ 0x0180b61a, ++ 0xbb0284b6, ++ 0xe0b60098, ++ 0x04efb804, ++ 0xb9eb1bf4, ++ 0x00f8029f, ++ 0x083c87f1, ++ 0xbd0684b6, ++ 0x0199f094, ++ 0xf10089d0, ++ 0xb6071087, ++ 0x94bd0684, ++ 0xf405bbfd, ++ 0x8bd0090b, ++ 0x0099f000, ++ 0xf405eefd, ++ 0x8ed00c0b, ++ 0xc08fd080, ++ 0xb70199f0, ++ 0xc8010080, ++ 0xb4b600ab, ++ 0x0cb9f010, ++ 0xb601aec8, ++ 0xbefd11e4, ++ 0x008bd005, ++ 0xf0008ecf, ++ 0x0bf41fe4, ++ 0x00ce98fa, ++ 0xd005e9fd, ++ 0xc0b6c08e, ++ 0x04cdb804, ++ 0xc8e81bf4, ++ 0x1bf402ab, ++ 0x008bcf18, ++ 0xb01fb4f0, ++ 0x1bf410b4, ++ 0x02a7f0f7, ++ 0xf4c921f4, ++ 0xabc81b0e, ++ 0x10b4b600, ++ 0xf00cb9f0, ++ 0x8bd012b9, ++ 0x008bcf00, ++ 0xf412bbc8, ++ 0x87f1fa1b, ++ 0x84b6085c, ++ 0xf094bd06, ++ 0x89d00199, ++ 0xf900f800, ++ 0x02a7f0a0, ++ 0xfcc921f4, ++ 0xf100f8a0, ++ 0xf04afc87, ++ 0x97f00283, ++ 0x0089d00c, ++ 0x020721f5, ++ 0x87f100f8, ++ 0x83f04afc, ++ 0x0d97f002, ++ 0xf50089d0, ++ 0xf8020721, ++ 0xfca7f100, ++ 0x02a3f04f, ++ 0x0500aba2, ++ 0xd00fc7f0, ++ 0xc7f000ac, ++ 0x00bcd00b, ++ 0x020721f5, ++ 0xf000aed0, ++ 0xbcd00ac7, ++ 0x0721f500, ++ 0xf100f802, ++ 0xb6083c87, ++ 0x94bd0684, ++ 0xd00399f0, ++ 0x21f50089, ++ 0xe7f00213, ++ 0x3921f503, ++ 0xfca7f102, ++ 0x02a3f046, ++ 0x0400aba0, ++ 0xf040a0d0, ++ 0xbcd001c7, ++ 0x0721f500, ++ 0x010c9202, ++ 0xf000acd0, ++ 0xbcd002c7, ++ 0x0721f500, ++ 0x2621f502, ++ 0x8087f102, ++ 0x0684b608, ++ 0xb70089cf, ++ 0x95220080, ++ 0x8ed008fe, ++ 0x408ed000, ++ 0xb6808acf, ++ 0xa0b606a5, ++ 0x00eabb01, ++ 0xb60480b6, ++ 0x1bf40192, ++ 0x08e4b6e8, ++ 0xf1f2efbc, ++ 0xb6085c87, ++ 0x94bd0684, ++ 0xd00399f0, ++ 0x00f80089, ++ 0xe7f1e0f9, ++ 0xe4b60814, ++ 0x00efd006, ++ 0x0c1ce7f1, ++ 0xf006e4b6, ++ 0xefd001f7, ++ 0xf8e0fc00, ++ 0xfe04bd00, ++ 0x07fe0004, ++ 0x0017f100, ++ 0x0227f012, ++ 0xf10012d0, ++ 0xfe05b917, ++ 0x17f10010, ++ 0x10d00400, ++ 0x0437f1c0, ++ 0x0634b604, ++ 0x200327f1, ++ 0xf10032d0, ++ 0xd0200427, ++ 0x27f10132, ++ 0x32d0200b, ++ 0x0c27f102, ++ 0x0732d020, ++ 0x0c2427f1, ++ 0xb90624b6, ++ 0x23d00003, ++ 0x0427f100, ++ 0x0023f087, ++ 0xb70012d0, ++ 0xf0010012, ++ 0x12d00427, ++ 0x1031f400, ++ 0x9604e7f1, ++ 0xf440e3f0, ++ 0xf1c76821, ++ 0x01018090, ++ 0x801ff4f0, ++ 0x17f0000f, ++ 0x041fbb01, ++ 0xf10112b6, ++ 0xb6040c27, ++ 0x21d00624, ++ 0x4021d000, ++ 0x080027f1, ++ 0xcf0624b6, ++ 0xf7f00022, ++ 0x08f0b654, ++ 0xb800f398, ++ 0x0bf40432, ++ 0x0034b00b, ++ 0xf8f11bf4, ++ 0x0017f100, ++ 0x02fe5801, ++ 0xf003ff58, ++ 0x0e8000e3, ++ 0x150f8014, ++ 0x013d21f5, ++ 0x070037f1, ++ 0x950634b6, ++ 0x34d00814, ++ 0x4034d000, ++ 0x130030b7, ++ 0xb6001fbb, ++ 0x3fd002f5, ++ 0x0815b600, ++ 0xb60110b6, ++ 0x1fb90814, ++ 0x6321f502, ++ 0x001fbb02, ++ 0xf1000398, ++ 0xf0200047, ++ 0x4ea05043, ++ 0x1fb90804, ++ 0x8d21f402, ++ 0x08004ea0, ++ 0xf4022fb9, ++ 0x4ea08d21, ++ 0xf4bd010c, ++ 0xa08d21f4, ++ 0xf401044e, ++ 0x4ea08d21, ++ 0xf7f00100, ++ 0x8d21f402, ++ 0x08004ea0, ++ 0xc86821f4, ++ 0x0bf41fff, ++ 0x044ea0fa, ++ 0x6821f408, ++ 0xb7001fbb, ++ 0xb6800040, ++ 0x1bf40132, ++ 0x0027f1b4, ++ 0x0624b608, ++ 0xb74021d0, ++ 0xbd080020, ++ 0x1f19f014, ++ 0xf40021d0, ++ 0x28f40031, ++ 0x08d7f000, ++ 0xf43921f4, ++ 0xe4b1f401, ++ 0x1bf54001, ++ 0x87f100d1, ++ 0x84b6083c, ++ 0xf094bd06, ++ 0x89d00499, ++ 0x0017f100, ++ 0x0614b60b, ++ 0xcf4012cf, ++ 0x13c80011, ++ 0x7e0bf41f, ++ 0xf41f23c8, ++ 0x20f95a0b, ++ 0xf10212b9, ++ 0xb6083c87, ++ 0x94bd0684, ++ 0xd00799f0, ++ 0x32f40089, ++ 0x0231f401, ++ 0x082921f5, ++ 0x085c87f1, ++ 0xbd0684b6, ++ 0x0799f094, ++ 0xfc0089d0, ++ 0x3c87f120, ++ 0x0684b608, ++ 0x99f094bd, ++ 0x0089d006, ++ 0xf50131f4, ++ 0xf1082921, ++ 0xb6085c87, ++ 0x94bd0684, ++ 0xd00699f0, ++ 0x0ef40089, ++ 0xb920f931, ++ 0x32f40212, ++ 0x0232f401, ++ 0x082921f5, ++ 0x17f120fc, ++ 0x14b60b00, ++ 0x0012d006, ++ 0xc8130ef4, ++ 0x0bf41f23, ++ 0x0131f40d, ++ 0xf50232f4, ++ 0xf1082921, ++ 0xb60b0c17, ++ 0x27f00614, ++ 0x0012d001, ++ 0x085c87f1, ++ 0xbd0684b6, ++ 0x0499f094, ++ 0xf50089d0, ++ 0xb0ff200e, ++ 0x1bf401e4, ++ 0x02f2b90d, ++ 0x07b521f5, ++ 0xb0420ef4, ++ 0x1bf402e4, ++ 0x3c87f12e, ++ 0x0684b608, ++ 0x99f094bd, ++ 0x0089d007, ++ 0xf40132f4, ++ 0x21f50232, ++ 0x87f10829, ++ 0x84b6085c, ++ 0xf094bd06, ++ 0x89d00799, ++ 0x110ef400, ++ 0xf010ef94, ++ 0x21f501f5, ++ 0x0ef502ec, ++ 0x17f1fed1, ++ 0x14b60820, ++ 0xf024bd06, ++ 0x12d01f29, ++ 0xbe0ef500, ++ 0xfe80f9fe, ++ 0x80f90188, ++ 0xa0f990f9, ++ 0xd0f9b0f9, ++ 0xf0f9e0f9, ++ 0xc4800acf, ++ 0x0bf404ab, ++ 0x00b7f11d, ++ 0x08d7f019, ++ 0xcf40becf, ++ 0x21f400bf, ++ 0x00b0b704, ++ 0x01e7f004, ++ 0xe400bed0, ++ 0xf40100ab, ++ 0xd7f00d0b, ++ 0x01e7f108, ++ 0x0421f440, ++ 0x0104b7f1, ++ 0xabffb0bd, ++ 0x0d0bf4b4, ++ 0x0c1ca7f1, ++ 0xd006a4b6, ++ 0x0ad000ab, ++ 0xfcf0fc40, ++ 0xfcd0fce0, ++ 0xfca0fcb0, ++ 0xfe80fc90, ++ 0x80fc0088, ++ 0xf80032f4, ++ 0x60e7f101, ++ 0x40e3f041, ++ 0xf401f7f0, ++ 0x21f48d21, ++ 0x04ffc868, ++ 0xf8fa0bf4, ++ 0x60e7f100, ++ 0x40e3f041, ++ 0x21f4f4bd, ++ 0xf100f88d, ++ 0xf04170e7, ++ 0xf5f040e3, ++ 0x8d21f410, ++ 0xe7f100f8, ++ 0xe3f04170, ++ 0x6821f440, ++ 0xf410f4f0, ++ 0x00f8f31b, ++ 0x0614e7f1, ++ 0xf106e4b6, ++ 0xd00270f7, ++ 0xf7f000ef, ++ 0x01f2b608, ++ 0xf1fd1bf4, ++ 0xd00770f7, ++ 0x00f800ef, ++ 0x086ce7f1, ++ 0xd006e4b6, ++ 0xe7f100ef, ++ 0xe3f08a14, ++ 0x8d21f440, ++ 0xa86ce7f1, ++ 0xf441e3f0, ++ 0x00f88d21, ++ 0x083c87f1, ++ 0xbd0684b6, ++ 0x0599f094, ++ 0xf00089d0, ++ 0x21f40ca7, ++ 0x2417f1c9, ++ 0x0614b60a, ++ 0xf10010d0, ++ 0xb60b0037, ++ 0x32d00634, ++ 0x0c17f140, ++ 0x0614b60a, ++ 0xd00747f0, ++ 0x14d00012, ++ 0x4014cf40, ++ 0xf41f44f0, ++ 0x32d0fa1b, ++ 0x000bfe00, ++ 0xb61f2af0, ++ 0x20b60424, ++ 0x3c87f102, ++ 0x0684b608, ++ 0x99f094bd, ++ 0x0089d008, ++ 0x0a0417f1, ++ 0xd00614b6, ++ 0x17f10012, ++ 0x14b60a20, ++ 0x0227f006, ++ 0x800023f1, ++ 0xf00012d0, ++ 0x27f11017, ++ 0x23f00300, ++ 0x0512fa02, ++ 0x87f103f8, ++ 0x84b6085c, ++ 0xf094bd06, ++ 0x89d00899, ++ 0xc1019800, ++ 0x981814b6, ++ 0x25b6c002, ++ 0x0512fd08, ++ 0xf1160180, ++ 0xb6083c87, ++ 0x94bd0684, ++ 0xd00999f0, ++ 0x27f10089, ++ 0x24b60a04, ++ 0x0021d006, ++ 0xf10127f0, ++ 0xb60a2017, ++ 0x12d00614, ++ 0x0017f100, ++ 0x0613f002, ++ 0xf80501fa, ++ 0x5c87f103, ++ 0x0684b608, ++ 0x99f094bd, ++ 0x0089d009, ++ 0x085c87f1, ++ 0xbd0684b6, ++ 0x0599f094, ++ 0xf80089d0, ++ 0x3121f500, ++ 0xb821f506, ++ 0x0ca7f006, ++ 0xf1c921f4, ++ 0xb60a1017, ++ 0x27f00614, ++ 0x0012d005, ++ 0xfd0012cf, ++ 0x1bf40522, ++ 0x4921f5fa, ++ 0x9800f806, ++ 0x27f18103, ++ 0x24b60a04, ++ 0x0023d006, ++ 0x34c434bd, ++ 0x0f1bf4ff, ++ 0x030057f1, ++ 0xfa0653f0, ++ 0x03f80535, ++ 0x98c04e98, ++ 0x21f4c14f, ++ 0x0830b68d, ++ 0xf40112b6, ++ 0x0398df1b, ++ 0x0023d016, ++ 0xf1800080, ++ 0xf0020017, ++ 0x01fa0613, ++ 0xf803f806, ++ 0x0611f400, ++ 0xf01102f4, ++ 0x21f510f7, ++ 0x21f50698, ++ 0x11f40631, ++ 0x02f7f01c, ++ 0x065721f5, ++ 0x066621f5, ++ 0x067821f5, ++ 0x21f5f4bd, ++ 0x21f50657, ++ 0x019806b8, ++ 0x1427f116, ++ 0x0624b604, ++ 0xf10020d0, ++ 0xf0a500e7, ++ 0x1fb941e3, ++ 0x8d21f402, ++ 0xf004e0b6, ++ 0x2cf001fc, ++ 0x0124b602, ++ 0xf405f2fd, ++ 0x17f18d21, ++ 0x13f04afc, ++ 0x0c27f002, ++ 0xf50012d0, ++ 0xf1020721, ++ 0xf047fc27, ++ 0x20d00223, ++ 0x012cf000, ++ 0xd00320b6, ++ 0xacf00012, ++ 0x06a5f001, ++ 0x9800b7f0, ++ 0x0d98140c, ++ 0x00e7f015, ++ 0x015c21f5, ++ 0xf508a7f0, ++ 0xf5010321, ++ 0xf4020721, ++ 0xa7f02201, ++ 0xc921f40c, ++ 0x0a1017f1, ++ 0xf00614b6, ++ 0x12d00527, ++ 0x0012cf00, ++ 0xf40522fd, ++ 0x02f4fa1b, ++ 0x02f7f032, ++ 0x065721f5, ++ 0x21f5f4bd, ++ 0x21f50698, ++ 0x21f50226, ++ 0xf4bd0666, ++ 0x065721f5, ++ 0x981011f4, ++ 0x11fd8001, ++ 0x070bf405, ++ 0x07df21f5, ++ 0x064921f5, ++ 0x000000f8, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_instmem.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_instmem.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_instmem.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_instmem.c 2011-06-26 07:59:23.000000000 +0200 +@@ -32,7 +32,6 @@ + struct nouveau_channel *bar1; + struct nouveau_gpuobj *bar3_pgd; + struct nouveau_channel *bar3; +- struct nouveau_gpuobj *chan_pgd; + }; + + int +@@ -181,17 +180,11 @@ + goto error; + + /* channel vm */ +- ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, &vm); ++ ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, ++ &dev_priv->chan_vm); + if (ret) + goto error; + +- ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, 0, &priv->chan_pgd); +- if (ret) +- goto error; +- +- nouveau_vm_ref(vm, &dev_priv->chan_vm, priv->chan_pgd); +- nouveau_vm_ref(NULL, &vm, NULL); +- + nvc0_instmem_resume(dev); + return 0; + error: +@@ -211,8 +204,7 @@ + nv_wr32(dev, 0x1704, 0x00000000); + nv_wr32(dev, 0x1714, 0x00000000); + +- nouveau_vm_ref(NULL, &dev_priv->chan_vm, priv->chan_pgd); +- nouveau_gpuobj_ref(NULL, &priv->chan_pgd); ++ nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL); + + nvc0_channel_del(&priv->bar1); + nouveau_vm_ref(NULL, &dev_priv->bar1_vm, priv->bar1_pgd); +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_pm.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_pm.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_pm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_pm.c 2011-06-26 07:59:23.000000000 +0200 +@@ -0,0 +1,151 @@ ++/* ++ * Copyright 2011 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_bios.h" ++#include "nouveau_pm.h" ++ ++static u32 read_div(struct drm_device *, int, u32, u32); ++static u32 read_pll(struct drm_device *, u32); ++ ++static u32 ++read_vco(struct drm_device *dev, u32 dsrc) ++{ ++ u32 ssrc = nv_rd32(dev, dsrc); ++ if (!(ssrc & 0x00000100)) ++ return read_pll(dev, 0x00e800); ++ return read_pll(dev, 0x00e820); ++} ++ ++static u32 ++read_pll(struct drm_device *dev, u32 pll) ++{ ++ u32 coef = nv_rd32(dev, pll + 4); ++ u32 P = (coef & 0x003f0000) >> 16; ++ u32 N = (coef & 0x0000ff00) >> 8; ++ u32 M = (coef & 0x000000ff) >> 0; ++ u32 sclk, doff; ++ ++ switch (pll & 0xfff000) { ++ case 0x00e000: ++ sclk = 27000; ++ P = 1; ++ break; ++ case 0x137000: ++ doff = (pll - 0x137000) / 0x20; ++ sclk = read_div(dev, doff, 0x137120, 0x137140); ++ break; ++ case 0x132000: ++ switch (pll) { ++ case 0x132000: ++ sclk = read_pll(dev, 0x132020); ++ break; ++ case 0x132020: ++ sclk = read_div(dev, 0, 0x137320, 0x137330); ++ break; ++ default: ++ return 0; ++ } ++ break; ++ default: ++ return 0; ++ } ++ ++ return sclk * N / M / P; ++} ++ ++static u32 ++read_div(struct drm_device *dev, int doff, u32 dsrc, u32 dctl) ++{ ++ u32 ssrc = nv_rd32(dev, dsrc + (doff * 4)); ++ u32 sctl = nv_rd32(dev, dctl + (doff * 4)); ++ ++ switch (ssrc & 0x00000003) { ++ case 0: ++ if ((ssrc & 0x00030000) != 0x00030000) ++ return 27000; ++ return 108000; ++ case 2: ++ return 100000; ++ case 3: ++ if (sctl & 0x80000000) { ++ u32 sclk = read_vco(dev, dsrc); ++ u32 sdiv = (sctl & 0x0000003f) + 2; ++ return (sclk * 2) / sdiv; ++ } ++ ++ return read_vco(dev, dsrc); ++ default: ++ return 0; ++ } ++} ++ ++static u32 ++read_mem(struct drm_device *dev) ++{ ++ u32 ssel = nv_rd32(dev, 0x1373f0); ++ if (ssel & 0x00000001) ++ return read_div(dev, 0, 0x137300, 0x137310); ++ return read_pll(dev, 0x132000); ++} ++ ++static u32 ++read_clk(struct drm_device *dev, int clk) ++{ ++ u32 sctl = nv_rd32(dev, 0x137250 + (clk * 4)); ++ u32 ssel = nv_rd32(dev, 0x137100); ++ u32 sclk, sdiv; ++ ++ if (ssel & (1 << clk)) { ++ if (clk < 7) ++ sclk = read_pll(dev, 0x137000 + (clk * 0x20)); ++ else ++ sclk = read_pll(dev, 0x1370e0); ++ sdiv = ((sctl & 0x00003f00) >> 8) + 2; ++ } else { ++ sclk = read_div(dev, clk, 0x137160, 0x1371d0); ++ sdiv = ((sctl & 0x0000003f) >> 0) + 2; ++ } ++ ++ if (sctl & 0x80000000) ++ return (sclk * 2) / sdiv; ++ return sclk; ++} ++ ++int ++nvc0_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) ++{ ++ perflvl->shader = read_clk(dev, 0x00); ++ perflvl->core = perflvl->shader / 2; ++ perflvl->memory = read_mem(dev); ++ perflvl->rop = read_clk(dev, 0x01); ++ perflvl->hub07 = read_clk(dev, 0x02); ++ perflvl->hub06 = read_clk(dev, 0x07); ++ perflvl->hub01 = read_clk(dev, 0x08); ++ perflvl->copy = read_clk(dev, 0x09); ++ perflvl->daemon = read_clk(dev, 0x0c); ++ perflvl->vdec = read_clk(dev, 0x0e); ++ return 0; ++} +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_vm.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_vm.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_vm.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_vm.c 2011-06-26 07:59:23.000000000 +0200 +@@ -105,7 +105,11 @@ + struct drm_device *dev = vm->dev; + struct nouveau_vm_pgd *vpgd; + unsigned long flags; +- u32 engine = (dev_priv->chan_vm == vm) ? 1 : 5; ++ u32 engine; ++ ++ engine = 1; ++ if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) ++ engine |= 4; + + pinstmem->flush(vm->dev); + +diff -Naur linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_vram.c linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_vram.c +--- linux-3.0-rc4/drivers/gpu/drm/nouveau/nvc0_vram.c 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/drivers/gpu/drm/nouveau/nvc0_vram.c 2011-06-26 07:59:23.000000000 +0200 +@@ -61,9 +61,7 @@ + u32 type, struct nouveau_mem **pmem) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; +- struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; +- struct nouveau_mm *mm = man->priv; ++ struct nouveau_mm *mm = dev_priv->engine.vram.mm; + struct nouveau_mm_node *r; + struct nouveau_mem *mem; + int ret; +@@ -105,9 +103,15 @@ + nvc0_vram_init(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_vram_engine *vram = &dev_priv->engine.vram; ++ const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ ++ const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ ++ u32 length; + + dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; + dev_priv->vram_size *= nv_rd32(dev, 0x121c74); +- dev_priv->vram_rblock_size = 4096; +- return 0; ++ ++ length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; ++ ++ return nouveau_mm_init(&vram->mm, rsvd_head, length, 1); + } +diff -Naur linux-3.0-rc4/.gitignore linux-3.0-rc4.nouveau/.gitignore +diff -Naur linux-3.0-rc4/include/drm/drmP.h linux-3.0-rc4.nouveau/include/drm/drmP.h +--- linux-3.0-rc4/include/drm/drmP.h 2011-06-21 05:25:46.000000000 +0200 ++++ linux-3.0-rc4.nouveau/include/drm/drmP.h 2011-06-26 07:59:43.000000000 +0200 +@@ -886,6 +886,8 @@ + */ + int (*gem_init_object) (struct drm_gem_object *obj); + void (*gem_free_object) (struct drm_gem_object *obj); ++ int (*gem_open_object) (struct drm_gem_object *, struct drm_file *); ++ void (*gem_close_object) (struct drm_gem_object *, struct drm_file *); + + /* vga arb irq handler */ + void (*vgaarb_irq)(struct drm_device *dev, bool state); From 17d209e8ac0c07516134e8192a94aa6ce24dda01 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Mon, 27 Jun 2011 13:05:22 +0200 Subject: [PATCH 7/9] udisks: dont install unneeded udev rule which also produces segfaults in dmesg Signed-off-by: Stephan Raue --- packages/sysutils/udisks/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sysutils/udisks/install b/packages/sysutils/udisks/install index 22c151e4a2..8c28c8ac98 100755 --- a/packages/sysutils/udisks/install +++ b/packages/sysutils/udisks/install @@ -32,7 +32,7 @@ mkdir -p $INSTALL/lib/udev cp -P $PKG_BUILD/src/probers/udisks-probe-sas-expander $INSTALL/lib/udev mkdir -p $INSTALL/lib/udev/rules.d - cp $PKG_BUILD/data/80-udisks.rules $INSTALL/lib/udev/rules.d +# cp $PKG_BUILD/data/80-udisks.rules $INSTALL/lib/udev/rules.d mkdir -p $INSTALL/sbin cp -P $PKG_BUILD/tools/umount.udisks $INSTALL/sbin From 74d4582b055c9e536a6638c081d5d9774293bda9 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Mon, 27 Jun 2011 13:06:21 +0200 Subject: [PATCH 8/9] udisks: automount internally partitions via udev Signed-off-by: Stephan Raue --- .../97-automount.rules} | 37 +++++-------------- 1 file changed, 10 insertions(+), 27 deletions(-) rename packages/sysutils/udisks/{init.d/31_mount-disks => udev.d/97-automount.rules} (57%) diff --git a/packages/sysutils/udisks/init.d/31_mount-disks b/packages/sysutils/udisks/udev.d/97-automount.rules similarity index 57% rename from packages/sysutils/udisks/init.d/31_mount-disks rename to packages/sysutils/udisks/udev.d/97-automount.rules index a02d14aebd..f78b00f905 100644 --- a/packages/sysutils/udisks/init.d/31_mount-disks +++ b/packages/sysutils/udisks/udev.d/97-automount.rules @@ -1,6 +1,6 @@ ################################################################################ -# Copyright (C) 2009-2010 OpenELEC.tv -# http://www.openelec.tv +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2011 Stephan Raue (stephan@openelec.tv) # # This Program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,30 +18,13 @@ # http://www.gnu.org/copyleft/gpl.html ################################################################################ -# -# automount internal disks -# -# runlevels: openelec, textmode +ACTION!="add|change", GOTO="end" +SUBSYSTEM!="block", GOTO="end" -( - progress "automount internal disks" +# mount the partition on add/change, if its a filesystem and on a ata drive + KERNEL=="sd[a-z][0-9]*", \ + ENV{ID_BUS}=="ata", \ + ENV{ID_FS_USAGE}=="filesystem", \ + RUN+="/usr/bin/udisks --mount /dev/%k" - drive_dump () { - udisks --dump | tr -d ' ' | grep 'device-file:' | cut -d ':' -f2 - } - - show_info () { - udisks --show-info $2 | grep "$1:" | tr -d ' ' | cut -d ":" -f2 - } - - for DEVICE in `drive_dump`; do - REMOVABLE="`show_info "removable" $DEVICE`" - MOUNTED="`show_info "is mounted" $DEVICE`" - USAGE="`show_info "usage" $DEVICE`" - - if [ "$REMOVABLE" = "0" -a "$MOUNTED" = "0" -a "$USAGE" = "filesystem" ]; then - udisks --mount "$DEVICE" >/dev/null - fi - - done -)& +LABEL="end" From 634601f7f86249f2ab47df460d6e32a8eb9149b3 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Mon, 27 Jun 2011 13:11:01 +0200 Subject: [PATCH 9/9] xorg-server: add support for driver based configfiles in /stoareg/.config, thanks to chewitt Signed-off-by: Stephan Raue --- packages/x11/xserver/xorg-server/scripts/xorg_start | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/x11/xserver/xorg-server/scripts/xorg_start b/packages/x11/xserver/xorg-server/scripts/xorg_start index 8d38758750..c971eec77c 100755 --- a/packages/x11/xserver/xorg-server/scripts/xorg_start +++ b/packages/x11/xserver/xorg-server/scripts/xorg_start @@ -33,8 +33,9 @@ if [ "$RUNLEVEL" = openelec ]; then logger -t Xorg "### setup xorg.conf paths ###" XORG_CONF_USER="/storage/.config/xorg.conf" + XORG_CONF_USER_DRV="/storage/.config/xorg-${xorg_driver}.conf" XORG_CONF_DEFAULT="/etc/X11/xorg.conf" - XORG_CONF_DRIVER="/etc/X11/xorg-${xorg_driver}.conf" + XORG_CONF_DEFAULT_DRV="/etc/X11/xorg-${xorg_driver}.conf" ############################################################################## # creating start options @@ -51,10 +52,12 @@ if [ "$RUNLEVEL" = openelec ]; then # load user defined xorg.conf, if exist if [ -f "$XORG_CONF_USER" ]; then XORG_ARGS="$XORG_ARGS -config $XORG_CONF_USER" + elif [ -f "$XORG_CONF_USER_DRV" ]; then + XORG_ARGS="$XORG_ARGS -config $XORG_CONF_USER_DRV" elif [ -f "$XORG_CONF_DEFAULT" ]; then XORG_ARGS="$XORG_ARGS -config $XORG_CONF_DEFAULT" - elif [ -f "$XORG_CONF_DRIVER" ]; then - XORG_ARGS="$XORG_ARGS -config $XORG_CONF_DRIVER" + elif [ -f "$XORG_CONF_DEFAULT_DRV" ]; then + XORG_ARGS="$XORG_ARGS -config $XORG_CONF_DEFAULT_DRV" fi ##############################################################################