From 187c5dce9d340adc7c474e42b2c90cea69a47fda Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 00:34:06 +0100 Subject: [PATCH 01/16] linux: update to linux-2.6.38-rc5 (initially) Signed-off-by: Stephan Raue --- packages/linux/meta | 4 +- .../linux-2.6.37.1-071-fstrim-0.1.patch | 23 - ...linux-2.6.37.1-700_701-730_BFS_patches.txt | 20 - .../linux-2.6.37.1-701_sched-bfs-363.patch | 8243 ----------------- ...x-2.6.37.1-702_bfs363-nonhotplug_fix.patch | 60 - .../linux-2.6.37.1-702_ck2-version.patch | 19 - ...inux-2.6.37.1-703_cpufreq-bfs_tweaks.patch | 37 - .../linux-2.6.37.1-704_hz-default_1000.patch | 17 - ...linux-2.6.37.1-705_hz-no_default_250.patch | 47 - .../linux-2.6.37.1-706_hz-raise_max.patch | 174 - ....1-707_kconfig-expose_vmsplit_option.patch | 40 - ...-708_mm-kswapd_inherit_prio-1.patch.ignore | 69 - ...-709_mm-decrease_default_dirty_ratio.patch | 34 - ...-710_mm-drop_swap_cache_aggressively.patch | 87 - ...enable_swaptoken_only_when_swap_full.patch | 20 - ...inux-2.6.37.1-712_mm-background_scan.patch | 137 - ...6.37.1-713_mm-idleprio_prio-1.patch.ignore | 33 - ...6.37.1-714_mm-lru_cache_add_lru_tail.patch | 250 - ...ake_swappiness_really_mean_it.patch.ignore | 29 - ...inux-2.6.37.1-716_mm-zero_swappiness.patch | 17 - ...ux-2.6.37.1-717_preempt-desktop-tune.patch | 36 - ...d-add-above-background-load-function.patch | 61 - ...> linux-2.6.38-rc5-000_crosscompile.patch} | 0 ...ux-2.6.38-rc5-002_bash_only_feature.patch} | 0 ...linux-2.6.38-rc5-003-no_dev_console.patch} | 0 ...c5-004_lower_undefined_mode_timeout.patch} | 0 ...2.6.38-rc5-005_kconfig_no_timestamp.patch} | 0 ...=> linux-2.6.38-rc5-006_enable_utf8.patch} | 0 ...linux-2.6.38-rc5-007_die_floppy_die.patch} | 0 ...08-hda_intel_prealloc_4mb_dmabuffer.patch} | 0 ...09_disable_i8042_check_on_apple_mac.patch} | 0 ...6.38-rc5-050_add_appleir_usb_driver.patch} | 0 ....38-rc5-052-aureal_remote_quirk-0.1.patch} | 0 ...i-remote_all_keys_and_keychange-0.1.patch} | 0 ...DVR-212D_failed_xfermode-0.1.patch.ignore} | 0 ...DVR-216D_failed_xfermode-0.1.patch.ignore} | 0 ...rm_nouveau_upstream-20110111.patch.ignore} | 0 projects/ATV/linux/linux.i386.conf | 96 +- projects/Generic/linux/linux.i386.conf | 112 +- projects/ION/linux/linux.i386.conf | 105 +- projects/ION/linux/linux.x86_64.conf | 102 +- projects/Intel/linux/linux.i386.conf | 130 +- projects/Intel/linux/linux.x86_64.conf | 126 +- 43 files changed, 474 insertions(+), 9654 deletions(-) delete mode 100644 packages/linux/patches/linux-2.6.37.1-071-fstrim-0.1.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-700_701-730_BFS_patches.txt delete mode 100644 packages/linux/patches/linux-2.6.37.1-701_sched-bfs-363.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-702_bfs363-nonhotplug_fix.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-702_ck2-version.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-703_cpufreq-bfs_tweaks.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-704_hz-default_1000.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-705_hz-no_default_250.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-706_hz-raise_max.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-707_kconfig-expose_vmsplit_option.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-708_mm-kswapd_inherit_prio-1.patch.ignore delete mode 100644 packages/linux/patches/linux-2.6.37.1-709_mm-decrease_default_dirty_ratio.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-710_mm-drop_swap_cache_aggressively.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-711_mm-enable_swaptoken_only_when_swap_full.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-712_mm-background_scan.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-713_mm-idleprio_prio-1.patch.ignore delete mode 100644 packages/linux/patches/linux-2.6.37.1-714_mm-lru_cache_add_lru_tail.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-715_mm-make_swappiness_really_mean_it.patch.ignore delete mode 100644 packages/linux/patches/linux-2.6.37.1-716_mm-zero_swappiness.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-717_preempt-desktop-tune.patch delete mode 100644 packages/linux/patches/linux-2.6.37.1-718_sched-add-above-background-load-function.patch rename packages/linux/patches/{linux-2.6.37.1-000_crosscompile.patch => linux-2.6.38-rc5-000_crosscompile.patch} (100%) rename packages/linux/patches/{linux-2.6.37.1-002_bash_only_feature.patch => linux-2.6.38-rc5-002_bash_only_feature.patch} (100%) rename packages/linux/patches/{linux-2.6.37.1-003-no_dev_console.patch => linux-2.6.38-rc5-003-no_dev_console.patch} (100%) rename packages/linux/patches/{linux-2.6.37.1-004_lower_undefined_mode_timeout.patch => linux-2.6.38-rc5-004_lower_undefined_mode_timeout.patch} (100%) rename packages/linux/patches/{linux-2.6.37.1-005_kconfig_no_timestamp.patch => linux-2.6.38-rc5-005_kconfig_no_timestamp.patch} (100%) rename packages/linux/patches/{linux-2.6.37.1-006_enable_utf8.patch => linux-2.6.38-rc5-006_enable_utf8.patch} (100%) rename packages/linux/patches/{linux-2.6.37.1-007_die_floppy_die.patch => linux-2.6.38-rc5-007_die_floppy_die.patch} (100%) rename packages/linux/patches/{linux-2.6.37.1-008-hda_intel_prealloc_4mb_dmabuffer.patch => linux-2.6.38-rc5-008-hda_intel_prealloc_4mb_dmabuffer.patch} (100%) rename packages/linux/patches/{linux-2.6.37.1-009_disable_i8042_check_on_apple_mac.patch => linux-2.6.38-rc5-009_disable_i8042_check_on_apple_mac.patch} (100%) rename packages/linux/patches/{linux-2.6.37.1-050_add_appleir_usb_driver.patch => linux-2.6.38-rc5-050_add_appleir_usb_driver.patch} (100%) rename packages/linux/patches/{linux-2.6.37.1-052-aureal_remote_quirk-0.1.patch => linux-2.6.38-rc5-052-aureal_remote_quirk-0.1.patch} (100%) rename packages/linux/patches/{linux-2.6.37.1-053_ati-remote_all_keys_and_keychange-0.1.patch => linux-2.6.38-rc5-053_ati-remote_all_keys_and_keychange-0.1.patch} (100%) rename packages/linux/patches/{linux-2.6.37.1-061-Pioneer_DVR-212D_failed_xfermode-0.1.patch => linux-2.6.38-rc5-061-Pioneer_DVR-212D_failed_xfermode-0.1.patch.ignore} (100%) rename packages/linux/patches/{linux-2.6.37.1-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch => linux-2.6.38-rc5-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch.ignore} (100%) rename packages/linux/patches/{linux-2.6.37.1-110-drm_nouveau_upstream-20110111.patch => linux-2.6.38-rc5-110-drm_nouveau_upstream-20110111.patch.ignore} (100%) diff --git a/packages/linux/meta b/packages/linux/meta index 435c1f1921..9fad95a8ab 100644 --- a/packages/linux/meta +++ b/packages/linux/meta @@ -19,13 +19,13 @@ ################################################################################ PKG_NAME="linux" -PKG_VERSION="2.6.37.1" +PKG_VERSION="2.6.38-rc5" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" PKG_SITE="http://www.kernel.org" PKG_URL="http://www.kernel.org/pub/linux/kernel/v2.6/$PKG_NAME-$PKG_VERSION.tar.bz2" -#PKG_URL="http://www.kernel.org/pub/linux/kernel/v2.6/testing/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_URL="http://www.kernel.org/pub/linux/kernel/v2.6/testing/$PKG_NAME-$PKG_VERSION.tar.bz2" PKG_DEPENDS="busybox linux-drivers linux-firmware" PKG_BUILD_DEPENDS="toolchain busybox-hosttools" PKG_PRIORITY="optional" diff --git a/packages/linux/patches/linux-2.6.37.1-071-fstrim-0.1.patch b/packages/linux/patches/linux-2.6.37.1-071-fstrim-0.1.patch deleted file mode 100644 index f0f2259e80..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-071-fstrim-0.1.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff -Naur linux-2.6.37/fs/ext4/mballoc.c linux-2.6.37.patch/fs/ext4/mballoc.c ---- linux-2.6.37/fs/ext4/mballoc.c 2011-01-05 01:50:19.000000000 +0100 -+++ linux-2.6.37.patch/fs/ext4/mballoc.c 2011-01-11 16:40:40.592434028 +0100 -@@ -4819,6 +4819,8 @@ - ext4_group_t group, ngroups = ext4_get_groups_count(sb); - ext4_grpblk_t cnt = 0, first_block, last_block; - uint64_t start, len, minlen, trimmed; -+ ext4_fsblk_t first_data_blk = -+ le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); - int ret = 0; - - start = range->start >> sb->s_blocksize_bits; -@@ -4828,6 +4830,10 @@ - - if (unlikely(minlen > EXT4_BLOCKS_PER_GROUP(sb))) - return -EINVAL; -+ if (start < first_data_blk) { -+ len -= first_data_blk - start; -+ start = first_data_blk; -+ } - - /* Determine first and last group to examine based on start and len */ - ext4_get_group_no_and_offset(sb, (ext4_fsblk_t) start, diff --git a/packages/linux/patches/linux-2.6.37.1-700_701-730_BFS_patches.txt b/packages/linux/patches/linux-2.6.37.1-700_701-730_BFS_patches.txt deleted file mode 100644 index 1e9f6475cc..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-700_701-730_BFS_patches.txt +++ /dev/null @@ -1,20 +0,0 @@ -http://www.kernel.org/pub/linux/kernel/people/ck/patches/2.6/2.6.37/2.6.37-ck1/patches/ - -2.6.37-sched-bfs-363.patch -2637-bfs363-nonhotplug_fix.patch -sched-add-above-background-load-function.patch -mm-zero_swappiness.patch -mm-enable_swaptoken_only_when_swap_full.patch -mm-drop_swap_cache_aggressively.patch -mm-kswapd_inherit_prio-1.patch -mm-background_scan.patch -mm-idleprio_prio-1.patch -mm-lru_cache_add_lru_tail.patch -mm-decrease_default_dirty_ratio.patch -kconfig-expose_vmsplit_option.patch -hz-default_1000.patch -hz-no_default_250.patch -hz-raise_max.patch -preempt-desktop-tune.patch -cpufreq-bfs_tweaks.patch -ck2-version.patch diff --git a/packages/linux/patches/linux-2.6.37.1-701_sched-bfs-363.patch b/packages/linux/patches/linux-2.6.37.1-701_sched-bfs-363.patch deleted file mode 100644 index 77a4076fdc..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-701_sched-bfs-363.patch +++ /dev/null @@ -1,8243 +0,0 @@ -The Brain Fuck Scheduler v0.363 by Con Kolivas. - -A single shared runqueue O(n) strict fairness earliest deadline first design. - -Ultra low latency and excellent desktop performance for 1 to many CPUs. -Not recommended for 4096 cpus. - -Scalability is optimal when your workload is equal to the number of CPUs on -bfs. ie you should ONLY do make -j4 on quad core, -j2 on dual core and so on. - -Features SCHED_IDLEPRIO and SCHED_ISO scheduling policies as well. -You do NOT need to use these policies for good performance, they are purely -optional for even better performance in extreme conditions. - -To run something idleprio, use schedtool like so: - -schedtool -D -e make -j4 - -To run something isoprio, use schedtool like so: - -schedtool -I -e amarok - -Includes accurate sub-tick accounting of tasks so userspace reported -cpu usage may be very different if you have very short lived tasks. - --ck - ---- - Documentation/scheduler/sched-BFS.txt | 351 + - Documentation/sysctl/kernel.txt | 26 - arch/powerpc/platforms/cell/spufs/sched.c | 5 - fs/proc/base.c | 2 - include/linux/init_task.h | 63 - include/linux/ioprio.h | 2 - include/linux/jiffies.h | 2 - include/linux/sched.h | 91 - init/Kconfig | 16 - init/main.c | 1 - kernel/delayacct.c | 2 - kernel/exit.c | 2 - kernel/kthread.c | 2 - kernel/posix-cpu-timers.c | 14 - kernel/sched.c | 4 - kernel/sched_bfs.c | 7223 ++++++++++++++++++++++++++++++ - kernel/sysctl.c | 31 - lib/Kconfig.debug | 2 - 18 files changed, 7812 insertions(+), 27 deletions(-) - -Index: linux-2.6.37-ck2/arch/powerpc/platforms/cell/spufs/sched.c -=================================================================== ---- linux-2.6.37-ck2.orig/arch/powerpc/platforms/cell/spufs/sched.c 2010-05-17 18:51:19.000000000 +1000 -+++ linux-2.6.37-ck2/arch/powerpc/platforms/cell/spufs/sched.c 2011-02-14 09:47:50.982252001 +1100 -@@ -64,11 +64,6 @@ - static struct timer_list spuloadavg_timer; - - /* -- * Priority of a normal, non-rt, non-niced'd process (aka nice level 0). -- */ --#define NORMAL_PRIO 120 -- --/* - * Frequency of the spu scheduler tick. By default we do one SPU scheduler - * tick for every 10 CPU scheduler ticks. - */ -Index: linux-2.6.37-ck2/Documentation/scheduler/sched-BFS.txt -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.37-ck2/Documentation/scheduler/sched-BFS.txt 2011-02-14 09:47:50.984252001 +1100 -@@ -0,0 +1,351 @@ -+BFS - The Brain Fuck Scheduler by Con Kolivas. -+ -+Goals. -+ -+The goal of the Brain Fuck Scheduler, referred to as BFS from here on, is to -+completely do away with the complex designs of the past for the cpu process -+scheduler and instead implement one that is very simple in basic design. -+The main focus of BFS is to achieve excellent desktop interactivity and -+responsiveness without heuristics and tuning knobs that are difficult to -+understand, impossible to model and predict the effect of, and when tuned to -+one workload cause massive detriment to another. -+ -+ -+Design summary. -+ -+BFS is best described as a single runqueue, O(n) lookup, earliest effective -+virtual deadline first design, loosely based on EEVDF (earliest eligible virtual -+deadline first) and my previous Staircase Deadline scheduler. Each component -+shall be described in order to understand the significance of, and reasoning for -+it. The codebase when the first stable version was released was approximately -+9000 lines less code than the existing mainline linux kernel scheduler (in -+2.6.31). This does not even take into account the removal of documentation and -+the cgroups code that is not used. -+ -+Design reasoning. -+ -+The single runqueue refers to the queued but not running processes for the -+entire system, regardless of the number of CPUs. The reason for going back to -+a single runqueue design is that once multiple runqueues are introduced, -+per-CPU or otherwise, there will be complex interactions as each runqueue will -+be responsible for the scheduling latency and fairness of the tasks only on its -+own runqueue, and to achieve fairness and low latency across multiple CPUs, any -+advantage in throughput of having CPU local tasks causes other disadvantages. -+This is due to requiring a very complex balancing system to at best achieve some -+semblance of fairness across CPUs and can only maintain relatively low latency -+for tasks bound to the same CPUs, not across them. To increase said fairness -+and latency across CPUs, the advantage of local runqueue locking, which makes -+for better scalability, is lost due to having to grab multiple locks. -+ -+A significant feature of BFS is that all accounting is done purely based on CPU -+used and nowhere is sleep time used in any way to determine entitlement or -+interactivity. Interactivity "estimators" that use some kind of sleep/run -+algorithm are doomed to fail to detect all interactive tasks, and to falsely tag -+tasks that aren't interactive as being so. The reason for this is that it is -+close to impossible to determine that when a task is sleeping, whether it is -+doing it voluntarily, as in a userspace application waiting for input in the -+form of a mouse click or otherwise, or involuntarily, because it is waiting for -+another thread, process, I/O, kernel activity or whatever. Thus, such an -+estimator will introduce corner cases, and more heuristics will be required to -+cope with those corner cases, introducing more corner cases and failed -+interactivity detection and so on. Interactivity in BFS is built into the design -+by virtue of the fact that tasks that are waking up have not used up their quota -+of CPU time, and have earlier effective deadlines, thereby making it very likely -+they will preempt any CPU bound task of equivalent nice level. See below for -+more information on the virtual deadline mechanism. Even if they do not preempt -+a running task, because the rr interval is guaranteed to have a bound upper -+limit on how long a task will wait for, it will be scheduled within a timeframe -+that will not cause visible interface jitter. -+ -+ -+Design details. -+ -+Task insertion. -+ -+BFS inserts tasks into each relevant queue as an O(1) insertion into a double -+linked list. On insertion, *every* running queue is checked to see if the newly -+queued task can run on any idle queue, or preempt the lowest running task on the -+system. This is how the cross-CPU scheduling of BFS achieves significantly lower -+latency per extra CPU the system has. In this case the lookup is, in the worst -+case scenario, O(n) where n is the number of CPUs on the system. -+ -+Data protection. -+ -+BFS has one single lock protecting the process local data of every task in the -+global queue. Thus every insertion, removal and modification of task data in the -+global runqueue needs to grab the global lock. However, once a task is taken by -+a CPU, the CPU has its own local data copy of the running process' accounting -+information which only that CPU accesses and modifies (such as during a -+timer tick) thus allowing the accounting data to be updated lockless. Once a -+CPU has taken a task to run, it removes it from the global queue. Thus the -+global queue only ever has, at most, -+ -+ (number of tasks requesting cpu time) - (number of logical CPUs) + 1 -+ -+tasks in the global queue. This value is relevant for the time taken to look up -+tasks during scheduling. This will increase if many tasks with CPU affinity set -+in their policy to limit which CPUs they're allowed to run on if they outnumber -+the number of CPUs. The +1 is because when rescheduling a task, the CPU's -+currently running task is put back on the queue. Lookup will be described after -+the virtual deadline mechanism is explained. -+ -+Virtual deadline. -+ -+The key to achieving low latency, scheduling fairness, and "nice level" -+distribution in BFS is entirely in the virtual deadline mechanism. The one -+tunable in BFS is the rr_interval, or "round robin interval". This is the -+maximum time two SCHED_OTHER (or SCHED_NORMAL, the common scheduling policy) -+tasks of the same nice level will be running for, or looking at it the other -+way around, the longest duration two tasks of the same nice level will be -+delayed for. When a task requests cpu time, it is given a quota (time_slice) -+equal to the rr_interval and a virtual deadline. The virtual deadline is -+offset from the current time in jiffies by this equation: -+ -+ jiffies + (prio_ratio * rr_interval) -+ -+The prio_ratio is determined as a ratio compared to the baseline of nice -20 -+and increases by 10% per nice level. The deadline is a virtual one only in that -+no guarantee is placed that a task will actually be scheduled by this time, but -+it is used to compare which task should go next. There are three components to -+how a task is next chosen. First is time_slice expiration. If a task runs out -+of its time_slice, it is descheduled, the time_slice is refilled, and the -+deadline reset to that formula above. Second is sleep, where a task no longer -+is requesting CPU for whatever reason. The time_slice and deadline are _not_ -+adjusted in this case and are just carried over for when the task is next -+scheduled. Third is preemption, and that is when a newly waking task is deemed -+higher priority than a currently running task on any cpu by virtue of the fact -+that it has an earlier virtual deadline than the currently running task. The -+earlier deadline is the key to which task is next chosen for the first and -+second cases. Once a task is descheduled, it is put back on the queue, and an -+O(n) lookup of all queued-but-not-running tasks is done to determine which has -+the earliest deadline and that task is chosen to receive CPU next. -+ -+The CPU proportion of different nice tasks works out to be approximately the -+ -+ (prio_ratio difference)^2 -+ -+The reason it is squared is that a task's deadline does not change while it is -+running unless it runs out of time_slice. Thus, even if the time actually -+passes the deadline of another task that is queued, it will not get CPU time -+unless the current running task deschedules, and the time "base" (jiffies) is -+constantly moving. -+ -+Task lookup. -+ -+BFS has 103 priority queues. 100 of these are dedicated to the static priority -+of realtime tasks, and the remaining 3 are, in order of best to worst priority, -+SCHED_ISO (isochronous), SCHED_NORMAL, and SCHED_IDLEPRIO (idle priority -+scheduling). When a task of these priorities is queued, a bitmap of running -+priorities is set showing which of these priorities has tasks waiting for CPU -+time. When a CPU is made to reschedule, the lookup for the next task to get -+CPU time is performed in the following way: -+ -+First the bitmap is checked to see what static priority tasks are queued. If -+any realtime priorities are found, the corresponding queue is checked and the -+first task listed there is taken (provided CPU affinity is suitable) and lookup -+is complete. If the priority corresponds to a SCHED_ISO task, they are also -+taken in FIFO order (as they behave like SCHED_RR). If the priority corresponds -+to either SCHED_NORMAL or SCHED_IDLEPRIO, then the lookup becomes O(n). At this -+stage, every task in the runlist that corresponds to that priority is checked -+to see which has the earliest set deadline, and (provided it has suitable CPU -+affinity) it is taken off the runqueue and given the CPU. If a task has an -+expired deadline, it is taken and the rest of the lookup aborted (as they are -+chosen in FIFO order). -+ -+Thus, the lookup is O(n) in the worst case only, where n is as described -+earlier, as tasks may be chosen before the whole task list is looked over. -+ -+ -+Scalability. -+ -+The major limitations of BFS will be that of scalability, as the separate -+runqueue designs will have less lock contention as the number of CPUs rises. -+However they do not scale linearly even with separate runqueues as multiple -+runqueues will need to be locked concurrently on such designs to be able to -+achieve fair CPU balancing, to try and achieve some sort of nice-level fairness -+across CPUs, and to achieve low enough latency for tasks on a busy CPU when -+other CPUs would be more suited. BFS has the advantage that it requires no -+balancing algorithm whatsoever, as balancing occurs by proxy simply because -+all CPUs draw off the global runqueue, in priority and deadline order. Despite -+the fact that scalability is _not_ the prime concern of BFS, it both shows very -+good scalability to smaller numbers of CPUs and is likely a more scalable design -+at these numbers of CPUs. -+ -+It also has some very low overhead scalability features built into the design -+when it has been deemed their overhead is so marginal that they're worth adding. -+The first is the local copy of the running process' data to the CPU it's running -+on to allow that data to be updated lockless where possible. Then there is -+deference paid to the last CPU a task was running on, by trying that CPU first -+when looking for an idle CPU to use the next time it's scheduled. Finally there -+is the notion of cache locality beyond the last running CPU. The sched_domains -+information is used to determine the relative virtual "cache distance" that -+other CPUs have from the last CPU a task was running on. CPUs with shared -+caches, such as SMT siblings, or multicore CPUs with shared caches, are treated -+as cache local. CPUs without shared caches are treated as not cache local, and -+CPUs on different NUMA nodes are treated as very distant. This "relative cache -+distance" is used by modifying the virtual deadline value when doing lookups. -+Effectively, the deadline is unaltered between "cache local" CPUs, doubled for -+"cache distant" CPUs, and quadrupled for "very distant" CPUs. The reasoning -+behind the doubling of deadlines is as follows. The real cost of migrating a -+task from one CPU to another is entirely dependant on the cache footprint of -+the task, how cache intensive the task is, how long it's been running on that -+CPU to take up the bulk of its cache, how big the CPU cache is, how fast and -+how layered the CPU cache is, how fast a context switch is... and so on. In -+other words, it's close to random in the real world where we do more than just -+one sole workload. The only thing we can be sure of is that it's not free. So -+BFS uses the principle that an idle CPU is a wasted CPU and utilising idle CPUs -+is more important than cache locality, and cache locality only plays a part -+after that. Doubling the effective deadline is based on the premise that the -+"cache local" CPUs will tend to work on the same tasks up to double the number -+of cache local CPUs, and once the workload is beyond that amount, it is likely -+that none of the tasks are cache warm anywhere anyway. The quadrupling for NUMA -+is a value I pulled out of my arse. -+ -+When choosing an idle CPU for a waking task, the cache locality is determined -+according to where the task last ran and then idle CPUs are ranked from best -+to worst to choose the most suitable idle CPU based on cache locality, NUMA -+node locality and hyperthread sibling business. They are chosen in the -+following preference (if idle): -+ -+* Same core, idle or busy cache, idle threads -+* Other core, same cache, idle or busy cache, idle threads. -+* Same node, other CPU, idle cache, idle threads. -+* Same node, other CPU, busy cache, idle threads. -+* Same core, busy threads. -+* Other core, same cache, busy threads. -+* Same node, other CPU, busy threads. -+* Other node, other CPU, idle cache, idle threads. -+* Other node, other CPU, busy cache, idle threads. -+* Other node, other CPU, busy threads. -+ -+This shows the SMT or "hyperthread" awareness in the design as well which will -+choose a real idle core first before a logical SMT sibling which already has -+tasks on the physical CPU. -+ -+Early benchmarking of BFS suggested scalability dropped off at the 16 CPU mark. -+However this benchmarking was performed on an earlier design that was far less -+scalable than the current one so it's hard to know how scalable it is in terms -+of both CPUs (due to the global runqueue) and heavily loaded machines (due to -+O(n) lookup) at this stage. Note that in terms of scalability, the number of -+_logical_ CPUs matters, not the number of _physical_ CPUs. Thus, a dual (2x) -+quad core (4X) hyperthreaded (2X) machine is effectively a 16X. Newer benchmark -+results are very promising indeed, without needing to tweak any knobs, features -+or options. Benchmark contributions are most welcome. -+ -+ -+Features -+ -+As the initial prime target audience for BFS was the average desktop user, it -+was designed to not need tweaking, tuning or have features set to obtain benefit -+from it. Thus the number of knobs and features has been kept to an absolute -+minimum and should not require extra user input for the vast majority of cases. -+There are precisely 2 tunables, and 2 extra scheduling policies. The rr_interval -+and iso_cpu tunables, and the SCHED_ISO and SCHED_IDLEPRIO policies. In addition -+to this, BFS also uses sub-tick accounting. What BFS does _not_ now feature is -+support for CGROUPS. The average user should neither need to know what these -+are, nor should they need to be using them to have good desktop behaviour. -+ -+rr_interval -+ -+There is only one "scheduler" tunable, the round robin interval. This can be -+accessed in -+ -+ /proc/sys/kernel/rr_interval -+ -+The value is in milliseconds, and the default value is set to 6 on a -+uniprocessor machine, and automatically set to a progressively higher value on -+multiprocessor machines. The reasoning behind increasing the value on more CPUs -+is that the effective latency is decreased by virtue of there being more CPUs on -+BFS (for reasons explained above), and increasing the value allows for less -+cache contention and more throughput. Valid values are from 1 to 1000 -+Decreasing the value will decrease latencies at the cost of decreasing -+throughput, while increasing it will improve throughput, but at the cost of -+worsening latencies. The accuracy of the rr interval is limited by HZ resolution -+of the kernel configuration. Thus, the worst case latencies are usually slightly -+higher than this actual value. The default value of 6 is not an arbitrary one. -+It is based on the fact that humans can detect jitter at approximately 7ms, so -+aiming for much lower latencies is pointless under most circumstances. It is -+worth noting this fact when comparing the latency performance of BFS to other -+schedulers. Worst case latencies being higher than 7ms are far worse than -+average latencies not being in the microsecond range. -+ -+Isochronous scheduling. -+ -+Isochronous scheduling is a unique scheduling policy designed to provide -+near-real-time performance to unprivileged (ie non-root) users without the -+ability to starve the machine indefinitely. Isochronous tasks (which means -+"same time") are set using, for example, the schedtool application like so: -+ -+ schedtool -I -e amarok -+ -+This will start the audio application "amarok" as SCHED_ISO. How SCHED_ISO works -+is that it has a priority level between true realtime tasks and SCHED_NORMAL -+which would allow them to preempt all normal tasks, in a SCHED_RR fashion (ie, -+if multiple SCHED_ISO tasks are running, they purely round robin at rr_interval -+rate). However if ISO tasks run for more than a tunable finite amount of time, -+they are then demoted back to SCHED_NORMAL scheduling. This finite amount of -+time is the percentage of _total CPU_ available across the machine, configurable -+as a percentage in the following "resource handling" tunable (as opposed to a -+scheduler tunable): -+ -+ /proc/sys/kernel/iso_cpu -+ -+and is set to 70% by default. It is calculated over a rolling 5 second average -+Because it is the total CPU available, it means that on a multi CPU machine, it -+is possible to have an ISO task running as realtime scheduling indefinitely on -+just one CPU, as the other CPUs will be available. Setting this to 100 is the -+equivalent of giving all users SCHED_RR access and setting it to 0 removes the -+ability to run any pseudo-realtime tasks. -+ -+A feature of BFS is that it detects when an application tries to obtain a -+realtime policy (SCHED_RR or SCHED_FIFO) and the caller does not have the -+appropriate privileges to use those policies. When it detects this, it will -+give the task SCHED_ISO policy instead. Thus it is transparent to the user. -+Because some applications constantly set their policy as well as their nice -+level, there is potential for them to undo the override specified by the user -+on the command line of setting the policy to SCHED_ISO. To counter this, once -+a task has been set to SCHED_ISO policy, it needs superuser privileges to set -+it back to SCHED_NORMAL. This will ensure the task remains ISO and all child -+processes and threads will also inherit the ISO policy. -+ -+Idleprio scheduling. -+ -+Idleprio scheduling is a scheduling policy designed to give out CPU to a task -+_only_ when the CPU would be otherwise idle. The idea behind this is to allow -+ultra low priority tasks to be run in the background that have virtually no -+effect on the foreground tasks. This is ideally suited to distributed computing -+clients (like setiathome, folding, mprime etc) but can also be used to start -+a video encode or so on without any slowdown of other tasks. To avoid this -+policy from grabbing shared resources and holding them indefinitely, if it -+detects a state where the task is waiting on I/O, the machine is about to -+suspend to ram and so on, it will transiently schedule them as SCHED_NORMAL. As -+per the Isochronous task management, once a task has been scheduled as IDLEPRIO, -+it cannot be put back to SCHED_NORMAL without superuser privileges. Tasks can -+be set to start as SCHED_IDLEPRIO with the schedtool command like so: -+ -+ schedtool -D -e ./mprime -+ -+Subtick accounting. -+ -+It is surprisingly difficult to get accurate CPU accounting, and in many cases, -+the accounting is done by simply determining what is happening at the precise -+moment a timer tick fires off. This becomes increasingly inaccurate as the -+timer tick frequency (HZ) is lowered. It is possible to create an application -+which uses almost 100% CPU, yet by being descheduled at the right time, records -+zero CPU usage. While the main problem with this is that there are possible -+security implications, it is also difficult to determine how much CPU a task -+really does use. BFS tries to use the sub-tick accounting from the TSC clock, -+where possible, to determine real CPU usage. This is not entirely reliable, but -+is far more likely to produce accurate CPU usage data than the existing designs -+and will not show tasks as consuming no CPU usage when they actually are. Thus, -+the amount of CPU reported as being used by BFS will more accurately represent -+how much CPU the task itself is using (as is shown for example by the 'time' -+application), so the reported values may be quite different to other schedulers. -+Values reported as the 'load' are more prone to problems with this design, but -+per process values are closer to real usage. When comparing throughput of BFS -+to other designs, it is important to compare the actual completed work in terms -+of total wall clock time taken and total work done, rather than the reported -+"cpu usage". -+ -+ -+Con Kolivas Fri Aug 27 2010 -Index: linux-2.6.37-ck2/Documentation/sysctl/kernel.txt -=================================================================== ---- linux-2.6.37-ck2.orig/Documentation/sysctl/kernel.txt 2011-01-06 14:04:07.000000000 +1100 -+++ linux-2.6.37-ck2/Documentation/sysctl/kernel.txt 2011-02-14 09:47:50.984252001 +1100 -@@ -32,6 +32,7 @@ - - domainname - - hostname - - hotplug -+- iso_cpu - - java-appletviewer [ binfmt_java, obsolete ] - - java-interpreter [ binfmt_java, obsolete ] - - kstack_depth_to_print [ X86 only ] -@@ -54,6 +55,7 @@ - - randomize_va_space - - real-root-dev ==> Documentation/initrd.txt - - reboot-cmd [ SPARC only ] -+- rr_interval - - rtsig-max - - rtsig-nr - - sem -@@ -254,6 +256,16 @@ - - ============================================================== - -+iso_cpu: (BFS CPU scheduler only). -+ -+This sets the percentage cpu that the unprivileged SCHED_ISO tasks can -+run effectively at realtime priority, averaged over a rolling five -+seconds over the -whole- system, meaning all cpus. -+ -+Set to 70 (percent) by default. -+ -+============================================================== -+ - l2cr: (PPC only) - - This flag controls the L2 cache of G3 processor boards. If -@@ -428,6 +440,20 @@ - - ============================================================== - -+rr_interval: (BFS CPU scheduler only) -+ -+This is the smallest duration that any cpu process scheduling unit -+will run for. Increasing this value can increase throughput of cpu -+bound tasks substantially but at the expense of increased latencies -+overall. Conversely decreasing it will decrease average and maximum -+latencies but at the expense of throughput. This value is in -+milliseconds and the default value chosen depends on the number of -+cpus available at scheduler initialisation with a minimum of 6. -+ -+Valid values are from 1-1000. -+ -+============================================================== -+ - rtsig-max & rtsig-nr: - - The file rtsig-max can be used to tune the maximum number -Index: linux-2.6.37-ck2/fs/proc/base.c -=================================================================== ---- linux-2.6.37-ck2.orig/fs/proc/base.c 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/fs/proc/base.c 2011-02-14 09:47:50.986252000 +1100 -@@ -356,7 +356,7 @@ - static int proc_pid_schedstat(struct task_struct *task, char *buffer) - { - return sprintf(buffer, "%llu %llu %lu\n", -- (unsigned long long)task->se.sum_exec_runtime, -+ (unsigned long long)tsk_seruntime(task), - (unsigned long long)task->sched_info.run_delay, - task->sched_info.pcount); - } -Index: linux-2.6.37-ck2/include/linux/init_task.h -=================================================================== ---- linux-2.6.37-ck2.orig/include/linux/init_task.h 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/include/linux/init_task.h 2011-02-14 09:47:50.986252001 +1100 -@@ -114,6 +114,67 @@ - * INIT_TASK is used to set up the first task table, touch at - * your own risk!. Base=0, limit=0x1fffff (=2MB) - */ -+#ifdef CONFIG_SCHED_BFS -+#define INIT_TASK(tsk) \ -+{ \ -+ .state = 0, \ -+ .stack = &init_thread_info, \ -+ .usage = ATOMIC_INIT(2), \ -+ .flags = PF_KTHREAD, \ -+ .lock_depth = -1, \ -+ .prio = NORMAL_PRIO, \ -+ .static_prio = MAX_PRIO-20, \ -+ .normal_prio = NORMAL_PRIO, \ -+ .deadline = 0, \ -+ .policy = SCHED_NORMAL, \ -+ .cpus_allowed = CPU_MASK_ALL, \ -+ .mm = NULL, \ -+ .active_mm = &init_mm, \ -+ .run_list = LIST_HEAD_INIT(tsk.run_list), \ -+ .time_slice = HZ, \ -+ .tasks = LIST_HEAD_INIT(tsk.tasks), \ -+ .pushable_tasks = PLIST_NODE_INIT(tsk.pushable_tasks, MAX_PRIO), \ -+ .ptraced = LIST_HEAD_INIT(tsk.ptraced), \ -+ .ptrace_entry = LIST_HEAD_INIT(tsk.ptrace_entry), \ -+ .real_parent = &tsk, \ -+ .parent = &tsk, \ -+ .children = LIST_HEAD_INIT(tsk.children), \ -+ .sibling = LIST_HEAD_INIT(tsk.sibling), \ -+ .group_leader = &tsk, \ -+ RCU_INIT_POINTER(.real_cred, &init_cred), \ -+ RCU_INIT_POINTER(.cred, &init_cred), \ -+ .comm = "swapper", \ -+ .thread = INIT_THREAD, \ -+ .fs = &init_fs, \ -+ .files = &init_files, \ -+ .signal = &init_signals, \ -+ .sighand = &init_sighand, \ -+ .nsproxy = &init_nsproxy, \ -+ .pending = { \ -+ .list = LIST_HEAD_INIT(tsk.pending.list), \ -+ .signal = {{0}}}, \ -+ .blocked = {{0}}, \ -+ .alloc_lock = __SPIN_LOCK_UNLOCKED(tsk.alloc_lock), \ -+ .journal_info = NULL, \ -+ .cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \ -+ .fs_excl = ATOMIC_INIT(0), \ -+ .pi_lock = __RAW_SPIN_LOCK_UNLOCKED(tsk.pi_lock), \ -+ .timer_slack_ns = 50000, /* 50 usec default slack */ \ -+ .pids = { \ -+ [PIDTYPE_PID] = INIT_PID_LINK(PIDTYPE_PID), \ -+ [PIDTYPE_PGID] = INIT_PID_LINK(PIDTYPE_PGID), \ -+ [PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \ -+ }, \ -+ .dirties = INIT_PROP_LOCAL_SINGLE(dirties), \ -+ INIT_IDS \ -+ INIT_PERF_EVENTS(tsk) \ -+ INIT_TRACE_IRQFLAGS \ -+ INIT_LOCKDEP \ -+ INIT_FTRACE_GRAPH \ -+ INIT_TRACE_RECURSION \ -+ INIT_TASK_RCU_PREEMPT(tsk) \ -+} -+#else /* CONFIG_SCHED_BFS */ - #define INIT_TASK(tsk) \ - { \ - .state = 0, \ -@@ -179,7 +240,7 @@ - INIT_TRACE_RECURSION \ - INIT_TASK_RCU_PREEMPT(tsk) \ - } -- -+#endif /* CONFIG_SCHED_BFS */ - - #define INIT_CPU_TIMERS(cpu_timers) \ - { \ -Index: linux-2.6.37-ck2/include/linux/ioprio.h -=================================================================== ---- linux-2.6.37-ck2.orig/include/linux/ioprio.h 2009-06-10 13:05:27.000000000 +1000 -+++ linux-2.6.37-ck2/include/linux/ioprio.h 2011-02-14 09:47:50.986252001 +1100 -@@ -64,6 +64,8 @@ - - static inline int task_nice_ioprio(struct task_struct *task) - { -+ if (iso_task(task)) -+ return 0; - return (task_nice(task) + 20) / 5; - } - -Index: linux-2.6.37-ck2/include/linux/sched.h -=================================================================== ---- linux-2.6.37-ck2.orig/include/linux/sched.h 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/include/linux/sched.h 2011-02-14 09:47:50.988252000 +1100 -@@ -36,8 +36,15 @@ - #define SCHED_FIFO 1 - #define SCHED_RR 2 - #define SCHED_BATCH 3 --/* SCHED_ISO: reserved but not implemented yet */ -+/* SCHED_ISO: Implemented on BFS only */ - #define SCHED_IDLE 5 -+#ifdef CONFIG_SCHED_BFS -+#define SCHED_ISO 4 -+#define SCHED_IDLEPRIO SCHED_IDLE -+#define SCHED_MAX (SCHED_IDLEPRIO) -+#define SCHED_RANGE(policy) ((policy) <= SCHED_MAX) -+#endif -+ - /* Can be ORed in to make sure the process is reverted back to SCHED_NORMAL on fork */ - #define SCHED_RESET_ON_FORK 0x40000000 - -@@ -268,8 +275,6 @@ - extern void init_idle(struct task_struct *idle, int cpu); - extern void init_idle_bootup_task(struct task_struct *idle); - --extern int runqueue_is_locked(int cpu); -- - extern cpumask_var_t nohz_cpu_mask; - #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ) - extern void select_nohz_load_balancer(int stop_tick); -@@ -1188,17 +1193,31 @@ - - int lock_depth; /* BKL lock depth */ - -+#ifndef CONFIG_SCHED_BFS - #ifdef CONFIG_SMP - #ifdef __ARCH_WANT_UNLOCKED_CTXSW - int oncpu; - #endif - #endif -+#else /* CONFIG_SCHED_BFS */ -+ int oncpu; -+#endif - - int prio, static_prio, normal_prio; - unsigned int rt_priority; -+#ifdef CONFIG_SCHED_BFS -+ int time_slice; -+ u64 deadline; -+ struct list_head run_list; -+ u64 last_ran; -+ u64 sched_time; /* sched_clock time spent running */ -+ -+ unsigned long rt_timeout; -+#else /* CONFIG_SCHED_BFS */ - const struct sched_class *sched_class; - struct sched_entity se; - struct sched_rt_entity rt; -+#endif - - #ifdef CONFIG_PREEMPT_NOTIFIERS - /* list of struct preempt_notifier: */ -@@ -1295,6 +1314,9 @@ - int __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */ - - cputime_t utime, stime, utimescaled, stimescaled; -+#ifdef CONFIG_SCHED_BFS -+ unsigned long utime_pc, stime_pc; -+#endif - cputime_t gtime; - #ifndef CONFIG_VIRT_CPU_ACCOUNTING - cputime_t prev_utime, prev_stime; -@@ -1514,6 +1536,53 @@ - #endif - }; - -+#ifdef CONFIG_SCHED_BFS -+extern int grunqueue_is_locked(void); -+extern void grq_unlock_wait(void); -+#define tsk_seruntime(t) ((t)->sched_time) -+#define tsk_rttimeout(t) ((t)->rt_timeout) -+ -+static inline void tsk_cpus_current(struct task_struct *p) -+{ -+} -+ -+#define runqueue_is_locked(cpu) grunqueue_is_locked() -+ -+static inline void print_scheduler_version(void) -+{ -+ printk(KERN_INFO"BFS CPU scheduler v0.363 by Con Kolivas.\n"); -+} -+ -+static inline int iso_task(struct task_struct *p) -+{ -+ return (p->policy == SCHED_ISO); -+} -+extern void remove_cpu(unsigned long cpu); -+#else /* CFS */ -+extern int runqueue_is_locked(int cpu); -+#define tsk_seruntime(t) ((t)->se.sum_exec_runtime) -+#define tsk_rttimeout(t) ((t)->rt.timeout) -+ -+static inline void tsk_cpus_current(struct task_struct *p) -+{ -+ p->rt.nr_cpus_allowed = current->rt.nr_cpus_allowed; -+} -+ -+static inline void print_scheduler_version(void) -+{ -+ printk(KERN_INFO"CFS CPU scheduler.\n"); -+} -+ -+static inline int iso_task(struct task_struct *p) -+{ -+ return 0; -+} -+ -+static inline void remove_cpu(unsigned long cpu) -+{ -+} -+#endif /* CONFIG_SCHED_BFS */ -+ - /* Future-safe accessor for struct task_struct's cpus_allowed. */ - #define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed) - -@@ -1531,10 +1600,20 @@ - */ - - #define MAX_USER_RT_PRIO 100 --#define MAX_RT_PRIO MAX_USER_RT_PRIO -+#define MAX_RT_PRIO (MAX_USER_RT_PRIO + 1) -+#define DEFAULT_PRIO (MAX_RT_PRIO + 20) - -+#ifdef CONFIG_SCHED_BFS -+#define PRIO_RANGE (40) -+#define MAX_PRIO (MAX_RT_PRIO + PRIO_RANGE) -+#define ISO_PRIO (MAX_RT_PRIO) -+#define NORMAL_PRIO (MAX_RT_PRIO + 1) -+#define IDLE_PRIO (MAX_RT_PRIO + 2) -+#define PRIO_LIMIT ((IDLE_PRIO) + 1) -+#else /* CONFIG_SCHED_BFS */ - #define MAX_PRIO (MAX_RT_PRIO + 40) --#define DEFAULT_PRIO (MAX_RT_PRIO + 20) -+#define NORMAL_PRIO DEFAULT_PRIO -+#endif /* CONFIG_SCHED_BFS */ - - static inline int rt_prio(int prio) - { -@@ -1862,7 +1941,7 @@ - extern unsigned long long thread_group_sched_runtime(struct task_struct *task); - - /* sched_exec is called by processes performing an exec */ --#ifdef CONFIG_SMP -+#if defined(CONFIG_SMP) && !defined(CONFIG_SCHED_BFS) - extern void sched_exec(void); - #else - #define sched_exec() {} -Index: linux-2.6.37-ck2/init/Kconfig -=================================================================== ---- linux-2.6.37-ck2.orig/init/Kconfig 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/init/Kconfig 2011-02-14 09:47:50.988252001 +1100 -@@ -30,6 +30,19 @@ - - menu "General setup" - -+config SCHED_BFS -+ bool "BFS cpu scheduler" -+ ---help--- -+ The Brain Fuck CPU Scheduler for excellent interactivity and -+ responsiveness on the desktop and solid scalability on normal -+ hardware. Not recommended for 4096 CPUs. -+ -+ Currently incompatible with the Group CPU scheduler, and RCU TORTURE -+ TEST so these options are disabled. -+ -+ Say Y here. -+ default y -+ - config EXPERIMENTAL - bool "Prompt for development and/or incomplete code/drivers" - ---help--- -@@ -563,6 +576,7 @@ - - config CGROUP_CPUACCT - bool "Simple CPU accounting cgroup subsystem" -+ depends on !SCHED_BFS - help - Provides a simple Resource Controller for monitoring the - total CPU consumed by the tasks in a cgroup. -@@ -629,7 +643,7 @@ - - menuconfig CGROUP_SCHED - bool "Group CPU scheduler" -- depends on EXPERIMENTAL -+ depends on EXPERIMENTAL && !SCHED_BFS - default n - help - This feature lets CPU scheduler recognize task groups and control CPU -Index: linux-2.6.37-ck2/init/main.c -=================================================================== ---- linux-2.6.37-ck2.orig/init/main.c 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/init/main.c 2011-02-14 09:47:50.989252001 +1100 -@@ -824,6 +824,7 @@ - system_state = SYSTEM_RUNNING; - numa_default_policy(); - -+ print_scheduler_version(); - - current->signal->flags |= SIGNAL_UNKILLABLE; - -Index: linux-2.6.37-ck2/kernel/delayacct.c -=================================================================== ---- linux-2.6.37-ck2.orig/kernel/delayacct.c 2009-12-03 21:40:09.000000000 +1100 -+++ linux-2.6.37-ck2/kernel/delayacct.c 2011-02-14 09:47:50.989252001 +1100 -@@ -128,7 +128,7 @@ - */ - t1 = tsk->sched_info.pcount; - t2 = tsk->sched_info.run_delay; -- t3 = tsk->se.sum_exec_runtime; -+ t3 = tsk_seruntime(tsk); - - d->cpu_count += t1; - -Index: linux-2.6.37-ck2/kernel/exit.c -=================================================================== ---- linux-2.6.37-ck2.orig/kernel/exit.c 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/kernel/exit.c 2011-02-14 09:47:50.989252001 +1100 -@@ -132,7 +132,7 @@ - sig->inblock += task_io_get_inblock(tsk); - sig->oublock += task_io_get_oublock(tsk); - task_io_accounting_add(&sig->ioac, &tsk->ioac); -- sig->sum_sched_runtime += tsk->se.sum_exec_runtime; -+ sig->sum_sched_runtime += tsk_seruntime(tsk); - } - - sig->nr_threads--; -Index: linux-2.6.37-ck2/kernel/kthread.c -=================================================================== ---- linux-2.6.37-ck2.orig/kernel/kthread.c 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/kernel/kthread.c 2011-02-14 09:47:50.989252001 +1100 -@@ -184,7 +184,9 @@ - } - - p->cpus_allowed = cpumask_of_cpu(cpu); -+#ifndef CONFIG_SCHED_BFS - p->rt.nr_cpus_allowed = 1; -+#endif - p->flags |= PF_THREAD_BOUND; - } - EXPORT_SYMBOL(kthread_bind); -Index: linux-2.6.37-ck2/kernel/posix-cpu-timers.c -=================================================================== ---- linux-2.6.37-ck2.orig/kernel/posix-cpu-timers.c 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/kernel/posix-cpu-timers.c 2011-02-14 09:47:50.990252001 +1100 -@@ -248,7 +248,7 @@ - do { - times->utime = cputime_add(times->utime, t->utime); - times->stime = cputime_add(times->stime, t->stime); -- times->sum_exec_runtime += t->se.sum_exec_runtime; -+ times->sum_exec_runtime += tsk_seruntime(t); - } while_each_thread(tsk, t); - out: - rcu_read_unlock(); -@@ -508,7 +508,7 @@ - void posix_cpu_timers_exit(struct task_struct *tsk) - { - cleanup_timers(tsk->cpu_timers, -- tsk->utime, tsk->stime, tsk->se.sum_exec_runtime); -+ tsk->utime, tsk->stime, tsk_seruntime(tsk)); - - } - void posix_cpu_timers_exit_group(struct task_struct *tsk) -@@ -518,7 +518,7 @@ - cleanup_timers(tsk->signal->cpu_timers, - cputime_add(tsk->utime, sig->utime), - cputime_add(tsk->stime, sig->stime), -- tsk->se.sum_exec_runtime + sig->sum_sched_runtime); -+ tsk_seruntime(tsk) + sig->sum_sched_runtime); - } - - static void clear_dead_task(struct k_itimer *timer, union cpu_time_count now) -@@ -949,7 +949,7 @@ - struct cpu_timer_list *t = list_first_entry(timers, - struct cpu_timer_list, - entry); -- if (!--maxfire || tsk->se.sum_exec_runtime < t->expires.sched) { -+ if (!--maxfire || tsk_seruntime(tsk) < t->expires.sched) { - tsk->cputime_expires.sched_exp = t->expires.sched; - break; - } -@@ -966,7 +966,7 @@ - ACCESS_ONCE(sig->rlim[RLIMIT_RTTIME].rlim_max); - - if (hard != RLIM_INFINITY && -- tsk->rt.timeout > DIV_ROUND_UP(hard, USEC_PER_SEC/HZ)) { -+ tsk_rttimeout(tsk) > DIV_ROUND_UP(hard, USEC_PER_SEC/HZ)) { - /* - * At the hard limit, we just die. - * No need to calculate anything else now. -@@ -974,7 +974,7 @@ - __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk); - return; - } -- if (tsk->rt.timeout > DIV_ROUND_UP(soft, USEC_PER_SEC/HZ)) { -+ if (tsk_rttimeout(tsk) > DIV_ROUND_UP(soft, USEC_PER_SEC/HZ)) { - /* - * At the soft limit, send a SIGXCPU every second. - */ -@@ -1276,7 +1276,7 @@ - struct task_cputime task_sample = { - .utime = tsk->utime, - .stime = tsk->stime, -- .sum_exec_runtime = tsk->se.sum_exec_runtime -+ .sum_exec_runtime = tsk_seruntime(tsk) - }; - - if (task_cputime_expired(&task_sample, &tsk->cputime_expires)) -Index: linux-2.6.37-ck2/kernel/sched_bfs.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.37-ck2/kernel/sched_bfs.c 2011-02-14 09:47:50.993252001 +1100 -@@ -0,0 +1,7223 @@ -+/* -+ * kernel/sched_bfs.c, was sched.c -+ * -+ * Kernel scheduler and related syscalls -+ * -+ * Copyright (C) 1991-2002 Linus Torvalds -+ * -+ * 1996-12-23 Modified by Dave Grothe to fix bugs in semaphores and -+ * make semaphores SMP safe -+ * 1998-11-19 Implemented schedule_timeout() and related stuff -+ * by Andrea Arcangeli -+ * 2002-01-04 New ultra-scalable O(1) scheduler by Ingo Molnar: -+ * hybrid priority-list and round-robin design with -+ * an array-switch method of distributing timeslices -+ * and per-CPU runqueues. Cleanups and useful suggestions -+ * by Davide Libenzi, preemptible kernel bits by Robert Love. -+ * 2003-09-03 Interactivity tuning by Con Kolivas. -+ * 2004-04-02 Scheduler domains code by Nick Piggin -+ * 2007-04-15 Work begun on replacing all interactivity tuning with a -+ * fair scheduling design by Con Kolivas. -+ * 2007-05-05 Load balancing (smp-nice) and other improvements -+ * by Peter Williams -+ * 2007-05-06 Interactivity improvements to CFS by Mike Galbraith -+ * 2007-07-01 Group scheduling enhancements by Srivatsa Vaddagiri -+ * 2007-11-29 RT balancing improvements by Steven Rostedt, Gregory Haskins, -+ * Thomas Gleixner, Mike Kravetz -+ * now Brainfuck deadline scheduling policy by Con Kolivas deletes -+ * a whole lot of those previous things. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "sched_cpupri.h" -+#include "workqueue_sched.h" -+ -+#define CREATE_TRACE_POINTS -+#include -+ -+#define rt_prio(prio) unlikely((prio) < MAX_RT_PRIO) -+#define rt_task(p) rt_prio((p)->prio) -+#define rt_queue(rq) rt_prio((rq)->rq_prio) -+#define batch_task(p) (unlikely((p)->policy == SCHED_BATCH)) -+#define is_rt_policy(policy) ((policy) == SCHED_FIFO || \ -+ (policy) == SCHED_RR) -+#define has_rt_policy(p) unlikely(is_rt_policy((p)->policy)) -+#define idleprio_task(p) unlikely((p)->policy == SCHED_IDLEPRIO) -+#define iso_task(p) unlikely((p)->policy == SCHED_ISO) -+#define iso_queue(rq) unlikely((rq)->rq_policy == SCHED_ISO) -+#define ISO_PERIOD ((5 * HZ * num_online_cpus()) + 1) -+ -+/* -+ * Convert user-nice values [ -20 ... 0 ... 19 ] -+ * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ], -+ * and back. -+ */ -+#define NICE_TO_PRIO(nice) (MAX_RT_PRIO + (nice) + 20) -+#define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20) -+#define TASK_NICE(p) PRIO_TO_NICE((p)->static_prio) -+ -+/* -+ * 'User priority' is the nice value converted to something we -+ * can work with better when scaling various scheduler parameters, -+ * it's a [ 0 ... 39 ] range. -+ */ -+#define USER_PRIO(p) ((p) - MAX_RT_PRIO) -+#define TASK_USER_PRIO(p) USER_PRIO((p)->static_prio) -+#define MAX_USER_PRIO (USER_PRIO(MAX_PRIO)) -+#define SCHED_PRIO(p) ((p) + MAX_RT_PRIO) -+#define STOP_PRIO (MAX_RT_PRIO - 1) -+ -+/* -+ * Some helpers for converting to/from various scales. Use shifts to get -+ * approximate multiples of ten for less overhead. -+ */ -+#define JIFFIES_TO_NS(TIME) ((TIME) * (1000000000 / HZ)) -+#define JIFFY_NS (1000000000 / HZ) -+#define HALF_JIFFY_NS (1000000000 / HZ / 2) -+#define HALF_JIFFY_US (1000000 / HZ / 2) -+#define MS_TO_NS(TIME) ((TIME) << 20) -+#define MS_TO_US(TIME) ((TIME) << 10) -+#define NS_TO_MS(TIME) ((TIME) >> 20) -+#define NS_TO_US(TIME) ((TIME) >> 10) -+ -+#define RESCHED_US (100) /* Reschedule if less than this many μs left */ -+ -+/* -+ * This is the time all tasks within the same priority round robin. -+ * Value is in ms and set to a minimum of 6ms. Scales with number of cpus. -+ * Tunable via /proc interface. -+ */ -+int rr_interval __read_mostly = 6; -+ -+/* -+ * sched_iso_cpu - sysctl which determines the cpu percentage SCHED_ISO tasks -+ * are allowed to run five seconds as real time tasks. This is the total over -+ * all online cpus. -+ */ -+int sched_iso_cpu __read_mostly = 70; -+ -+/* -+ * The relative length of deadline for each priority(nice) level. -+ */ -+static int prio_ratios[PRIO_RANGE] __read_mostly; -+ -+/* -+ * The quota handed out to tasks of all priority levels when refilling their -+ * time_slice. -+ */ -+static inline unsigned long timeslice(void) -+{ -+ return MS_TO_US(rr_interval); -+} -+ -+/* -+ * The global runqueue data that all CPUs work off. Data is protected either -+ * by the global grq lock, or the discrete lock that precedes the data in this -+ * struct. -+ */ -+struct global_rq { -+ raw_spinlock_t lock; -+ unsigned long nr_running; -+ unsigned long nr_uninterruptible; -+ unsigned long long nr_switches; -+ struct list_head queue[PRIO_LIMIT]; -+ DECLARE_BITMAP(prio_bitmap, PRIO_LIMIT + 1); -+#ifdef CONFIG_SMP -+ unsigned long qnr; /* queued not running */ -+ cpumask_t cpu_idle_map; -+ int idle_cpus; -+#endif -+ u64 niffies; /* Nanosecond jiffies */ -+ unsigned long last_jiffy; /* Last jiffy we updated niffies */ -+ -+ raw_spinlock_t iso_lock; -+ int iso_ticks; -+ int iso_refractory; -+}; -+ -+/* There can be only one */ -+static struct global_rq grq; -+ -+/* -+ * This is the main, per-CPU runqueue data structure. -+ * This data should only be modified by the local cpu. -+ */ -+struct rq { -+#ifdef CONFIG_SMP -+#ifdef CONFIG_NO_HZ -+ u64 nohz_stamp; -+ unsigned char in_nohz_recently; -+#endif -+#endif -+ -+ struct task_struct *curr, *idle, *stop; -+ struct mm_struct *prev_mm; -+ -+ /* Stored data about rq->curr to work outside grq lock */ -+ u64 rq_deadline; -+ unsigned int rq_policy; -+ int rq_time_slice; -+ u64 rq_last_ran; -+ int rq_prio; -+ int rq_running; /* There is a task running */ -+ -+ /* Accurate timekeeping data */ -+ u64 timekeep_clock; -+ unsigned long user_pc, nice_pc, irq_pc, softirq_pc, system_pc, -+ iowait_pc, idle_pc; -+ atomic_t nr_iowait; -+ -+#ifdef CONFIG_SMP -+ int cpu; /* cpu of this runqueue */ -+ int online; -+ -+ struct root_domain *rd; -+ struct sched_domain *sd; -+ unsigned long *cpu_locality; /* CPU relative cache distance */ -+#ifdef CONFIG_SCHED_SMT -+ int (*siblings_idle)(unsigned long cpu); -+ /* See if all smt siblings are idle */ -+ cpumask_t smt_siblings; -+#endif -+#ifdef CONFIG_SCHED_MC -+ int (*cache_idle)(unsigned long cpu); -+ /* See if all cache siblings are idle */ -+ cpumask_t cache_siblings; -+#endif -+ u64 last_niffy; /* Last time this RQ updated grq.niffies */ -+#endif -+#ifdef CONFIG_IRQ_TIME_ACCOUNTING -+ u64 prev_irq_time; -+#endif -+ u64 clock, old_clock, last_tick; -+ u64 clock_task; -+ int dither; -+ -+#ifdef CONFIG_SCHEDSTATS -+ -+ /* latency stats */ -+ struct sched_info rq_sched_info; -+ unsigned long long rq_cpu_time; -+ /* could above be rq->cfs_rq.exec_clock + rq->rt_rq.rt_runtime ? */ -+ -+ /* sys_sched_yield() stats */ -+ unsigned int yld_count; -+ -+ /* schedule() stats */ -+ unsigned int sched_switch; -+ unsigned int sched_count; -+ unsigned int sched_goidle; -+ -+ /* try_to_wake_up() stats */ -+ unsigned int ttwu_count; -+ unsigned int ttwu_local; -+ -+ /* BKL stats */ -+ unsigned int bkl_count; -+#endif -+}; -+ -+static DEFINE_PER_CPU(struct rq, runqueues) ____cacheline_aligned_in_smp; -+static DEFINE_MUTEX(sched_hotcpu_mutex); -+ -+#ifdef CONFIG_SMP -+/* -+ * sched_domains_mutex serializes calls to arch_init_sched_domains, -+ * detach_destroy_domains and partition_sched_domains. -+ */ -+static DEFINE_MUTEX(sched_domains_mutex); -+ -+/* -+ * By default the system creates a single root-domain with all cpus as -+ * members (mimicking the global state we have today). -+ */ -+static struct root_domain def_root_domain; -+ -+int __weak arch_sd_sibling_asym_packing(void) -+{ -+ return 0*SD_ASYM_PACKING; -+} -+#endif -+ -+/* -+ * We add the notion of a root-domain which will be used to define per-domain -+ * variables. Each exclusive cpuset essentially defines an island domain by -+ * fully partitioning the member cpus from any other cpuset. Whenever a new -+ * exclusive cpuset is created, we also create and attach a new root-domain -+ * object. -+ * -+ */ -+struct root_domain { -+ atomic_t refcount; -+ cpumask_var_t span; -+ cpumask_var_t online; -+ -+ /* -+ * The "RT overload" flag: it gets set if a CPU has more than -+ * one runnable RT task. -+ */ -+ cpumask_var_t rto_mask; -+ atomic_t rto_count; -+#ifdef CONFIG_SMP -+ struct cpupri cpupri; -+#endif -+}; -+ -+#define rcu_dereference_check_sched_domain(p) \ -+ rcu_dereference_check((p), \ -+ rcu_read_lock_sched_held() || \ -+ lockdep_is_held(&sched_domains_mutex)) -+ -+/* -+ * The domain tree (rq->sd) is protected by RCU's quiescent state transition. -+ * See detach_destroy_domains: synchronize_sched for details. -+ * -+ * The domain tree of any CPU may only be accessed from within -+ * preempt-disabled sections. -+ */ -+#define for_each_domain(cpu, __sd) \ -+ for (__sd = rcu_dereference_check_sched_domain(cpu_rq(cpu)->sd); __sd; __sd = __sd->parent) -+ -+static inline void update_rq_clock(struct rq *rq); -+ -+/* -+ * Sanity check should sched_clock return bogus values. We make sure it does -+ * not appear to go backwards, and use jiffies to determine the maximum and -+ * minimum it could possibly have increased, and round down to the nearest -+ * jiffy when it falls outside this. -+ */ -+static inline void niffy_diff(s64 *niff_diff, int jiff_diff) -+{ -+ unsigned long min_diff, max_diff; -+ -+ if (jiff_diff > 1) -+ min_diff = JIFFIES_TO_NS(jiff_diff - 1); -+ else -+ min_diff = 1; -+ /* Round up to the nearest tick for maximum */ -+ max_diff = JIFFIES_TO_NS(jiff_diff + 1); -+ -+ if (unlikely(*niff_diff < min_diff || *niff_diff > max_diff)) -+ *niff_diff = min_diff; -+} -+ -+#ifdef CONFIG_SMP -+#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu))) -+#define this_rq() (&__get_cpu_var(runqueues)) -+#define task_rq(p) cpu_rq(task_cpu(p)) -+#define cpu_curr(cpu) (cpu_rq(cpu)->curr) -+static inline int cpu_of(struct rq *rq) -+{ -+ return rq->cpu; -+} -+ -+/* -+ * Niffies are a globally increasing nanosecond counter. Whenever a runqueue -+ * clock is updated with the grq.lock held, it is an opportunity to update the -+ * niffies value. Any CPU can update it by adding how much its clock has -+ * increased since it last updated niffies, minus any added niffies by other -+ * CPUs. -+ */ -+static inline void update_clocks(struct rq *rq) -+{ -+ s64 ndiff; -+ long jdiff; -+ -+ update_rq_clock(rq); -+ ndiff = rq->clock - rq->old_clock; -+ /* old_clock is only updated when we are updating niffies */ -+ rq->old_clock = rq->clock; -+ ndiff -= grq.niffies - rq->last_niffy; -+ jdiff = jiffies - grq.last_jiffy; -+ niffy_diff(&ndiff, jdiff); -+ grq.last_jiffy += jdiff; -+ grq.niffies += ndiff; -+ rq->last_niffy = grq.niffies; -+} -+#else /* CONFIG_SMP */ -+static struct rq *uprq; -+#define cpu_rq(cpu) (uprq) -+#define this_rq() (uprq) -+#define task_rq(p) (uprq) -+#define cpu_curr(cpu) ((uprq)->curr) -+static inline int cpu_of(struct rq *rq) -+{ -+ return 0; -+} -+ -+static inline void update_clocks(struct rq *rq) -+{ -+ s64 ndiff; -+ long jdiff; -+ -+ update_rq_clock(rq); -+ ndiff = rq->clock - rq->old_clock; -+ rq->old_clock = rq->clock; -+ jdiff = jiffies - grq.last_jiffy; -+ niffy_diff(&ndiff, jdiff); -+ grq.last_jiffy += jdiff; -+ grq.niffies += ndiff; -+} -+#endif -+#define raw_rq() (&__raw_get_cpu_var(runqueues)) -+ -+#include "sched_stats.h" -+ -+#ifndef prepare_arch_switch -+# define prepare_arch_switch(next) do { } while (0) -+#endif -+#ifndef finish_arch_switch -+# define finish_arch_switch(prev) do { } while (0) -+#endif -+ -+/* -+ * All common locking functions performed on grq.lock. rq->clock is local to -+ * the CPU accessing it so it can be modified just with interrupts disabled -+ * when we're not updating niffies. -+ * Looking up task_rq must be done under grq.lock to be safe. -+ */ -+static void update_rq_clock_task(struct rq *rq, s64 delta); -+ -+static inline void update_rq_clock(struct rq *rq) -+{ -+ s64 delta = sched_clock_cpu(cpu_of(rq)) - rq->clock; -+ -+ rq->clock += delta; -+ update_rq_clock_task(rq, delta); -+} -+ -+static inline int task_running(struct task_struct *p) -+{ -+ return p->oncpu; -+} -+ -+static inline void grq_lock(void) -+ __acquires(grq.lock) -+{ -+ raw_spin_lock(&grq.lock); -+} -+ -+static inline void grq_unlock(void) -+ __releases(grq.lock) -+{ -+ raw_spin_unlock(&grq.lock); -+} -+ -+static inline void grq_lock_irq(void) -+ __acquires(grq.lock) -+{ -+ raw_spin_lock_irq(&grq.lock); -+} -+ -+static inline void time_lock_grq(struct rq *rq) -+ __acquires(grq.lock) -+{ -+ grq_lock(); -+ update_clocks(rq); -+} -+ -+static inline void grq_unlock_irq(void) -+ __releases(grq.lock) -+{ -+ raw_spin_unlock_irq(&grq.lock); -+} -+ -+static inline void grq_lock_irqsave(unsigned long *flags) -+ __acquires(grq.lock) -+{ -+ raw_spin_lock_irqsave(&grq.lock, *flags); -+} -+ -+static inline void grq_unlock_irqrestore(unsigned long *flags) -+ __releases(grq.lock) -+{ -+ raw_spin_unlock_irqrestore(&grq.lock, *flags); -+} -+ -+static inline struct rq -+*task_grq_lock(struct task_struct *p, unsigned long *flags) -+ __acquires(grq.lock) -+{ -+ grq_lock_irqsave(flags); -+ return task_rq(p); -+} -+ -+static inline struct rq -+*time_task_grq_lock(struct task_struct *p, unsigned long *flags) -+ __acquires(grq.lock) -+{ -+ struct rq *rq = task_grq_lock(p, flags); -+ update_clocks(rq); -+ return rq; -+} -+ -+static inline struct rq *task_grq_lock_irq(struct task_struct *p) -+ __acquires(grq.lock) -+{ -+ grq_lock_irq(); -+ return task_rq(p); -+} -+ -+static inline void time_task_grq_lock_irq(struct task_struct *p) -+ __acquires(grq.lock) -+{ -+ struct rq *rq = task_grq_lock_irq(p); -+ update_clocks(rq); -+} -+ -+static inline void task_grq_unlock_irq(void) -+ __releases(grq.lock) -+{ -+ grq_unlock_irq(); -+} -+ -+static inline void task_grq_unlock(unsigned long *flags) -+ __releases(grq.lock) -+{ -+ grq_unlock_irqrestore(flags); -+} -+ -+/** -+ * grunqueue_is_locked -+ * -+ * Returns true if the global runqueue is locked. -+ * This interface allows printk to be called with the runqueue lock -+ * held and know whether or not it is OK to wake up the klogd. -+ */ -+inline int grunqueue_is_locked(void) -+{ -+ return raw_spin_is_locked(&grq.lock); -+} -+ -+inline void grq_unlock_wait(void) -+ __releases(grq.lock) -+{ -+ smp_mb(); /* spin-unlock-wait is not a full memory barrier */ -+ raw_spin_unlock_wait(&grq.lock); -+} -+ -+static inline void time_grq_lock(struct rq *rq, unsigned long *flags) -+ __acquires(grq.lock) -+{ -+ local_irq_save(*flags); -+ time_lock_grq(rq); -+} -+ -+static inline struct rq *__task_grq_lock(struct task_struct *p) -+ __acquires(grq.lock) -+{ -+ grq_lock(); -+ return task_rq(p); -+} -+ -+static inline void __task_grq_unlock(void) -+ __releases(grq.lock) -+{ -+ grq_unlock(); -+} -+ -+#ifndef __ARCH_WANT_UNLOCKED_CTXSW -+static inline void prepare_lock_switch(struct rq *rq, struct task_struct *next) -+{ -+} -+ -+static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev) -+{ -+#ifdef CONFIG_DEBUG_SPINLOCK -+ /* this is a valid case when another task releases the spinlock */ -+ grq.lock.owner = current; -+#endif -+ /* -+ * If we are tracking spinlock dependencies then we have to -+ * fix up the runqueue lock - which gets 'carried over' from -+ * prev into current: -+ */ -+ spin_acquire(&grq.lock.dep_map, 0, 0, _THIS_IP_); -+ -+ grq_unlock_irq(); -+} -+ -+#else /* __ARCH_WANT_UNLOCKED_CTXSW */ -+ -+static inline void prepare_lock_switch(struct rq *rq, struct task_struct *next) -+{ -+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW -+ grq_unlock_irq(); -+#else -+ grq_unlock(); -+#endif -+} -+ -+static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev) -+{ -+ smp_wmb(); -+#ifndef __ARCH_WANT_INTERRUPTS_ON_CTXSW -+ local_irq_enable(); -+#endif -+} -+#endif /* __ARCH_WANT_UNLOCKED_CTXSW */ -+ -+static inline int deadline_before(u64 deadline, u64 time) -+{ -+ return (deadline < time); -+} -+ -+static inline int deadline_after(u64 deadline, u64 time) -+{ -+ return (deadline > time); -+} -+ -+/* -+ * A task that is queued but not running will be on the grq run list. -+ * A task that is not running or queued will not be on the grq run list. -+ * A task that is currently running will have ->oncpu set but not on the -+ * grq run list. -+ */ -+static inline int task_queued(struct task_struct *p) -+{ -+ return (!list_empty(&p->run_list)); -+} -+ -+/* -+ * Removing from the global runqueue. Enter with grq locked. -+ */ -+static void dequeue_task(struct task_struct *p) -+{ -+ list_del_init(&p->run_list); -+ if (list_empty(grq.queue + p->prio)) -+ __clear_bit(p->prio, grq.prio_bitmap); -+} -+ -+/* -+ * To determine if it's safe for a task of SCHED_IDLEPRIO to actually run as -+ * an idle task, we ensure none of the following conditions are met. -+ */ -+static int idleprio_suitable(struct task_struct *p) -+{ -+ return (!freezing(p) && !signal_pending(p) && -+ !(task_contributes_to_load(p)) && !(p->flags & (PF_EXITING))); -+} -+ -+/* -+ * To determine if a task of SCHED_ISO can run in pseudo-realtime, we check -+ * that the iso_refractory flag is not set. -+ */ -+static int isoprio_suitable(void) -+{ -+ return !grq.iso_refractory; -+} -+ -+/* -+ * Adding to the global runqueue. Enter with grq locked. -+ */ -+static void enqueue_task(struct task_struct *p) -+{ -+ if (!rt_task(p)) { -+ /* Check it hasn't gotten rt from PI */ -+ if ((idleprio_task(p) && idleprio_suitable(p)) || -+ (iso_task(p) && isoprio_suitable())) -+ p->prio = p->normal_prio; -+ else -+ p->prio = NORMAL_PRIO; -+ } -+ __set_bit(p->prio, grq.prio_bitmap); -+ list_add_tail(&p->run_list, grq.queue + p->prio); -+ sched_info_queued(p); -+} -+ -+/* Only idle task does this as a real time task*/ -+static inline void enqueue_task_head(struct task_struct *p) -+{ -+ __set_bit(p->prio, grq.prio_bitmap); -+ list_add(&p->run_list, grq.queue + p->prio); -+ sched_info_queued(p); -+} -+ -+static inline void requeue_task(struct task_struct *p) -+{ -+ sched_info_queued(p); -+} -+ -+/* -+ * Returns the relative length of deadline all compared to the shortest -+ * deadline which is that of nice -20. -+ */ -+static inline int task_prio_ratio(struct task_struct *p) -+{ -+ return prio_ratios[TASK_USER_PRIO(p)]; -+} -+ -+/* -+ * task_timeslice - all tasks of all priorities get the exact same timeslice -+ * length. CPU distribution is handled by giving different deadlines to -+ * tasks of different priorities. Use 128 as the base value for fast shifts. -+ */ -+static inline int task_timeslice(struct task_struct *p) -+{ -+ return (rr_interval * task_prio_ratio(p) / 128); -+} -+ -+#ifdef CONFIG_SMP -+/* -+ * qnr is the "queued but not running" count which is the total number of -+ * tasks on the global runqueue list waiting for cpu time but not actually -+ * currently running on a cpu. -+ */ -+static inline void inc_qnr(void) -+{ -+ grq.qnr++; -+} -+ -+static inline void dec_qnr(void) -+{ -+ grq.qnr--; -+} -+ -+static inline int queued_notrunning(void) -+{ -+ return grq.qnr; -+} -+ -+/* -+ * The cpu_idle_map stores a bitmap of all the CPUs currently idle to -+ * allow easy lookup of whether any suitable idle CPUs are available. -+ * It's cheaper to maintain a binary yes/no if there are any idle CPUs on the -+ * idle_cpus variable than to do a full bitmask check when we are busy. -+ */ -+static inline void set_cpuidle_map(unsigned long cpu) -+{ -+ if (likely(cpu_online(cpu))) { -+ cpu_set(cpu, grq.cpu_idle_map); -+ grq.idle_cpus = 1; -+ } -+} -+ -+static inline void clear_cpuidle_map(unsigned long cpu) -+{ -+ cpu_clear(cpu, grq.cpu_idle_map); -+ if (cpus_empty(grq.cpu_idle_map)) -+ grq.idle_cpus = 0; -+} -+ -+static int suitable_idle_cpus(struct task_struct *p) -+{ -+ if (!grq.idle_cpus) -+ return 0; -+ return (cpus_intersects(p->cpus_allowed, grq.cpu_idle_map)); -+} -+ -+static void resched_task(struct task_struct *p); -+ -+#define CPUIDLE_DIFF_THREAD (1) -+#define CPUIDLE_DIFF_CORE (2) -+#define CPUIDLE_CACHE_BUSY (4) -+#define CPUIDLE_DIFF_CPU (8) -+#define CPUIDLE_THREAD_BUSY (16) -+#define CPUIDLE_DIFF_NODE (32) -+ -+/* -+ * The best idle CPU is chosen according to the CPUIDLE ranking above where the -+ * lowest value would give the most suitable CPU to schedule p onto next. We -+ * iterate from the last CPU upwards instead of using for_each_cpu_mask so as -+ * to be able to break out immediately if the last CPU is idle. The order works -+ * out to be the following: -+ * -+ * Same core, idle or busy cache, idle threads -+ * Other core, same cache, idle or busy cache, idle threads. -+ * Same node, other CPU, idle cache, idle threads. -+ * Same node, other CPU, busy cache, idle threads. -+ * Same core, busy threads. -+ * Other core, same cache, busy threads. -+ * Same node, other CPU, busy threads. -+ * Other node, other CPU, idle cache, idle threads. -+ * Other node, other CPU, busy cache, idle threads. -+ * Other node, other CPU, busy threads. -+ * -+ * If p was the last task running on this rq, then regardless of where -+ * it has been running since then, it is cache warm on this rq. -+ */ -+static void resched_best_idle(struct task_struct *p) -+{ -+ unsigned long cpu_tmp, best_cpu, best_ranking; -+ cpumask_t tmpmask; -+ struct rq *rq; -+ int iterate; -+ -+ cpus_and(tmpmask, p->cpus_allowed, grq.cpu_idle_map); -+ iterate = cpus_weight(tmpmask); -+ best_cpu = task_cpu(p); -+ /* -+ * Start below the last CPU and work up with next_cpu as the last -+ * CPU might not be idle or affinity might not allow it. -+ */ -+ cpu_tmp = best_cpu - 1; -+ rq = cpu_rq(best_cpu); -+ best_ranking = ~0UL; -+ -+ do { -+ unsigned long ranking; -+ struct rq *tmp_rq; -+ -+ ranking = 0; -+ cpu_tmp = next_cpu(cpu_tmp, tmpmask); -+ if (cpu_tmp >= nr_cpu_ids) { -+ cpu_tmp = -1; -+ cpu_tmp = next_cpu(cpu_tmp, tmpmask); -+ } -+ tmp_rq = cpu_rq(cpu_tmp); -+ -+#ifdef CONFIG_NUMA -+ if (rq->cpu_locality[cpu_tmp] > 3) -+ ranking |= CPUIDLE_DIFF_NODE; -+ else -+#endif -+ if (rq->cpu_locality[cpu_tmp] > 2) -+ ranking |= CPUIDLE_DIFF_CPU; -+#ifdef CONFIG_SCHED_MC -+ if (rq->cpu_locality[cpu_tmp] == 2) -+ ranking |= CPUIDLE_DIFF_CORE; -+ if (!(tmp_rq->cache_idle(cpu_tmp))) -+ ranking |= CPUIDLE_CACHE_BUSY; -+#endif -+#ifdef CONFIG_SCHED_SMT -+ if (rq->cpu_locality[cpu_tmp] == 1) -+ ranking |= CPUIDLE_DIFF_THREAD; -+ if (!(tmp_rq->siblings_idle(cpu_tmp))) -+ ranking |= CPUIDLE_THREAD_BUSY; -+#endif -+ if (ranking < best_ranking) { -+ best_cpu = cpu_tmp; -+ if (ranking == 0) -+ break; -+ best_ranking = ranking; -+ } -+ } while (--iterate > 0); -+ -+ resched_task(cpu_rq(best_cpu)->curr); -+} -+ -+static inline void resched_suitable_idle(struct task_struct *p) -+{ -+ if (suitable_idle_cpus(p)) -+ resched_best_idle(p); -+} -+ -+/* -+ * The cpu cache locality difference between CPUs is used to determine how far -+ * to offset the virtual deadline. <2 difference in locality means that one -+ * timeslice difference is allowed longer for the cpu local tasks. This is -+ * enough in the common case when tasks are up to 2* number of CPUs to keep -+ * tasks within their shared cache CPUs only. CPUs on different nodes or not -+ * even in this domain (NUMA) have "4" difference, allowing 4 times longer -+ * deadlines before being taken onto another cpu, allowing for 2* the double -+ * seen by separate CPUs above. -+ * Simple summary: Virtual deadlines are equal on shared cache CPUs, double -+ * on separate CPUs and quadruple in separate NUMA nodes. -+ */ -+static inline int -+cache_distance(struct rq *task_rq, struct rq *rq, struct task_struct *p) -+{ -+ int locality = rq->cpu_locality[cpu_of(task_rq)] - 2; -+ -+ if (locality > 0) -+ return task_timeslice(p) << locality; -+ return 0; -+} -+#else /* CONFIG_SMP */ -+static inline void inc_qnr(void) -+{ -+} -+ -+static inline void dec_qnr(void) -+{ -+} -+ -+static inline int queued_notrunning(void) -+{ -+ return grq.nr_running; -+} -+ -+static inline void set_cpuidle_map(unsigned long cpu) -+{ -+} -+ -+static inline void clear_cpuidle_map(unsigned long cpu) -+{ -+} -+ -+static inline int suitable_idle_cpus(struct task_struct *p) -+{ -+ return uprq->curr == uprq->idle; -+} -+ -+static inline void resched_suitable_idle(struct task_struct *p) -+{ -+} -+ -+static inline int -+cache_distance(struct rq *task_rq, struct rq *rq, struct task_struct *p) -+{ -+ return 0; -+} -+#endif /* CONFIG_SMP */ -+ -+/* -+ * activate_idle_task - move idle task to the _front_ of runqueue. -+ */ -+static inline void activate_idle_task(struct task_struct *p) -+{ -+ enqueue_task_head(p); -+ grq.nr_running++; -+ inc_qnr(); -+} -+ -+static inline int normal_prio(struct task_struct *p) -+{ -+ if (has_rt_policy(p)) -+ return MAX_RT_PRIO - 1 - p->rt_priority; -+ if (idleprio_task(p)) -+ return IDLE_PRIO; -+ if (iso_task(p)) -+ return ISO_PRIO; -+ return NORMAL_PRIO; -+} -+ -+/* -+ * Calculate the current priority, i.e. the priority -+ * taken into account by the scheduler. This value might -+ * be boosted by RT tasks as it will be RT if the task got -+ * RT-boosted. If not then it returns p->normal_prio. -+ */ -+static int effective_prio(struct task_struct *p) -+{ -+ p->normal_prio = normal_prio(p); -+ /* -+ * If we are RT tasks or we were boosted to RT priority, -+ * keep the priority unchanged. Otherwise, update priority -+ * to the normal priority: -+ */ -+ if (!rt_prio(p->prio)) -+ return p->normal_prio; -+ return p->prio; -+} -+ -+/* -+ * activate_task - move a task to the runqueue. Enter with grq locked. -+ */ -+static void activate_task(struct task_struct *p, struct rq *rq) -+{ -+ update_clocks(rq); -+ -+ /* -+ * Sleep time is in units of nanosecs, so shift by 20 to get a -+ * milliseconds-range estimation of the amount of time that the task -+ * spent sleeping: -+ */ -+ if (unlikely(prof_on == SLEEP_PROFILING)) { -+ if (p->state == TASK_UNINTERRUPTIBLE) -+ profile_hits(SLEEP_PROFILING, (void *)get_wchan(p), -+ (rq->clock - p->last_ran) >> 20); -+ } -+ -+ p->prio = effective_prio(p); -+ if (task_contributes_to_load(p)) -+ grq.nr_uninterruptible--; -+ enqueue_task(p); -+ grq.nr_running++; -+ inc_qnr(); -+} -+ -+/* -+ * deactivate_task - If it's running, it's not on the grq and we can just -+ * decrement the nr_running. Enter with grq locked. -+ */ -+static inline void deactivate_task(struct task_struct *p) -+{ -+ if (task_contributes_to_load(p)) -+ grq.nr_uninterruptible++; -+ grq.nr_running--; -+} -+ -+#ifdef CONFIG_SMP -+void set_task_cpu(struct task_struct *p, unsigned int cpu) -+{ -+ trace_sched_migrate_task(p, cpu); -+ if (task_cpu(p) != cpu) -+ perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS, 1, 1, NULL, 0); -+ -+ /* -+ * After ->cpu is set up to a new value, task_grq_lock(p, ...) can be -+ * successfuly executed on another CPU. We must ensure that updates of -+ * per-task data have been completed by this moment. -+ */ -+ smp_wmb(); -+ task_thread_info(p)->cpu = cpu; -+} -+#endif -+ -+/* -+ * Move a task off the global queue and take it to a cpu for it will -+ * become the running task. -+ */ -+static inline void take_task(struct rq *rq, struct task_struct *p) -+{ -+ set_task_cpu(p, cpu_of(rq)); -+ dequeue_task(p); -+ dec_qnr(); -+} -+ -+/* -+ * Returns a descheduling task to the grq runqueue unless it is being -+ * deactivated. -+ */ -+static inline void return_task(struct task_struct *p, int deactivate) -+{ -+ if (deactivate) -+ deactivate_task(p); -+ else { -+ inc_qnr(); -+ enqueue_task(p); -+ } -+} -+ -+/* -+ * resched_task - mark a task 'to be rescheduled now'. -+ * -+ * On UP this means the setting of the need_resched flag, on SMP it -+ * might also involve a cross-CPU call to trigger the scheduler on -+ * the target CPU. -+ */ -+#ifdef CONFIG_SMP -+ -+#ifndef tsk_is_polling -+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG) -+#endif -+ -+static void resched_task(struct task_struct *p) -+{ -+ int cpu; -+ -+ assert_raw_spin_locked(&grq.lock); -+ -+ if (unlikely(test_tsk_thread_flag(p, TIF_NEED_RESCHED))) -+ return; -+ -+ set_tsk_thread_flag(p, TIF_NEED_RESCHED); -+ -+ cpu = task_cpu(p); -+ if (cpu == smp_processor_id()) -+ return; -+ -+ /* NEED_RESCHED must be visible before we test polling */ -+ smp_mb(); -+ if (!tsk_is_polling(p)) -+ smp_send_reschedule(cpu); -+} -+ -+#else -+static inline void resched_task(struct task_struct *p) -+{ -+ assert_raw_spin_locked(&grq.lock); -+ set_tsk_need_resched(p); -+} -+#endif -+ -+/** -+ * task_curr - is this task currently executing on a CPU? -+ * @p: the task in question. -+ */ -+inline int task_curr(const struct task_struct *p) -+{ -+ return cpu_curr(task_cpu(p)) == p; -+} -+ -+#ifdef CONFIG_SMP -+struct migration_req { -+ struct task_struct *task; -+ int dest_cpu; -+}; -+ -+/* -+ * wait_task_inactive - wait for a thread to unschedule. -+ * -+ * If @match_state is nonzero, it's the @p->state value just checked and -+ * not expected to change. If it changes, i.e. @p might have woken up, -+ * then return zero. When we succeed in waiting for @p to be off its CPU, -+ * we return a positive number (its total switch count). If a second call -+ * a short while later returns the same number, the caller can be sure that -+ * @p has remained unscheduled the whole time. -+ * -+ * The caller must ensure that the task *will* unschedule sometime soon, -+ * else this function might spin for a *long* time. This function can't -+ * be called with interrupts off, or it may introduce deadlock with -+ * smp_call_function() if an IPI is sent by the same process we are -+ * waiting to become inactive. -+ */ -+unsigned long wait_task_inactive(struct task_struct *p, long match_state) -+{ -+ unsigned long flags; -+ int running, on_rq; -+ unsigned long ncsw; -+ struct rq *rq; -+ -+ for (;;) { -+ /* -+ * We do the initial early heuristics without holding -+ * any task-queue locks at all. We'll only try to get -+ * the runqueue lock when things look like they will -+ * work out! In the unlikely event rq is dereferenced -+ * since we're lockless, grab it again. -+ */ -+#ifdef CONFIG_SMP -+retry_rq: -+ rq = task_rq(p); -+ if (unlikely(!rq)) -+ goto retry_rq; -+#else /* CONFIG_SMP */ -+ rq = task_rq(p); -+#endif -+ /* -+ * If the task is actively running on another CPU -+ * still, just relax and busy-wait without holding -+ * any locks. -+ * -+ * NOTE! Since we don't hold any locks, it's not -+ * even sure that "rq" stays as the right runqueue! -+ * But we don't care, since this will return false -+ * if the runqueue has changed and p is actually now -+ * running somewhere else! -+ */ -+ while (task_running(p) && p == rq->curr) { -+ if (match_state && unlikely(p->state != match_state)) -+ return 0; -+ cpu_relax(); -+ } -+ -+ /* -+ * Ok, time to look more closely! We need the grq -+ * lock now, to be *sure*. If we're wrong, we'll -+ * just go back and repeat. -+ */ -+ rq = task_grq_lock(p, &flags); -+ trace_sched_wait_task(p); -+ running = task_running(p); -+ on_rq = task_queued(p); -+ ncsw = 0; -+ if (!match_state || p->state == match_state) -+ ncsw = p->nvcsw | LONG_MIN; /* sets MSB */ -+ task_grq_unlock(&flags); -+ -+ /* -+ * If it changed from the expected state, bail out now. -+ */ -+ if (unlikely(!ncsw)) -+ break; -+ -+ /* -+ * Was it really running after all now that we -+ * checked with the proper locks actually held? -+ * -+ * Oops. Go back and try again.. -+ */ -+ if (unlikely(running)) { -+ cpu_relax(); -+ continue; -+ } -+ -+ /* -+ * It's not enough that it's not actively running, -+ * it must be off the runqueue _entirely_, and not -+ * preempted! -+ * -+ * So if it was still runnable (but just not actively -+ * running right now), it's preempted, and we should -+ * yield - it could be a while. -+ */ -+ if (unlikely(on_rq)) { -+ schedule_timeout_uninterruptible(1); -+ continue; -+ } -+ -+ /* -+ * Ahh, all good. It wasn't running, and it wasn't -+ * runnable, which means that it will never become -+ * running in the future either. We're all done! -+ */ -+ break; -+ } -+ -+ return ncsw; -+} -+ -+/*** -+ * kick_process - kick a running thread to enter/exit the kernel -+ * @p: the to-be-kicked thread -+ * -+ * Cause a process which is running on another CPU to enter -+ * kernel-mode, without any delay. (to get signals handled.) -+ * -+ * NOTE: this function doesnt have to take the runqueue lock, -+ * because all it wants to ensure is that the remote task enters -+ * the kernel. If the IPI races and the task has been migrated -+ * to another CPU then no harm is done and the purpose has been -+ * achieved as well. -+ */ -+void kick_process(struct task_struct *p) -+{ -+ int cpu; -+ -+ preempt_disable(); -+ cpu = task_cpu(p); -+ if ((cpu != smp_processor_id()) && task_curr(p)) -+ smp_send_reschedule(cpu); -+ preempt_enable(); -+} -+EXPORT_SYMBOL_GPL(kick_process); -+#endif -+ -+#define rq_idle(rq) ((rq)->rq_prio == PRIO_LIMIT) -+ -+/* -+ * RT tasks preempt purely on priority. SCHED_NORMAL tasks preempt on the -+ * basis of earlier deadlines. SCHED_IDLEPRIO don't preempt anything else or -+ * between themselves, they cooperatively multitask. An idle rq scores as -+ * prio PRIO_LIMIT so it is always preempted. -+ */ -+static inline int -+can_preempt(struct task_struct *p, int prio, u64 deadline, -+ unsigned int policy) -+{ -+ /* Better static priority RT task or better policy preemption */ -+ if (p->prio < prio) -+ return 1; -+ if (p->prio > prio) -+ return 0; -+ /* SCHED_NORMAL, BATCH and ISO will preempt based on deadline */ -+ if (!deadline_before(p->deadline, deadline)) -+ return 0; -+ return 1; -+} -+#ifdef CONFIG_SMP -+#ifdef CONFIG_HOTPLUG_CPU -+/* -+ * Check to see if there is a task that is affined only to offline CPUs but -+ * still wants runtime. This happens to kernel threads during suspend/halt and -+ * disabling of CPUs. -+ */ -+static inline int online_cpus(struct task_struct *p) -+{ -+ return (likely(cpus_intersects(cpu_online_map, p->cpus_allowed))); -+} -+#else /* CONFIG_HOTPLUG_CPU */ -+/* All available CPUs are always online without hotplug. */ -+static inline int online_cpus(struct task_struct *p) -+{ -+ return 1; -+} -+#endif -+ -+/* -+ * Check to see if p can run on cpu, and if not, whether there are any online -+ * CPUs it can run on instead. -+ */ -+static inline int needs_other_cpu(struct task_struct *p, int cpu) -+{ -+ if (unlikely(!cpu_isset(cpu, p->cpus_allowed))) -+ return 1; -+ return 0; -+} -+ -+/* -+ * latest_deadline and highest_prio_rq are initialised only to silence the -+ * compiler. When all else is equal, still prefer this_rq. -+ */ -+static void try_preempt(struct task_struct *p, struct rq *this_rq) -+{ -+ struct rq *highest_prio_rq = this_rq; -+ u64 latest_deadline; -+ unsigned long cpu; -+ int highest_prio; -+ cpumask_t tmp; -+ -+ if (suitable_idle_cpus(p)) { -+ resched_best_idle(p); -+ return; -+ } -+ -+ /* IDLEPRIO tasks never preempt anything */ -+ if (p->policy == SCHED_IDLEPRIO) -+ return; -+ -+ if (likely(online_cpus(p))) -+ cpus_and(tmp, cpu_online_map, p->cpus_allowed); -+ else -+ return; -+ -+ latest_deadline = 0; -+ highest_prio = -1; -+ -+ for_each_cpu_mask(cpu, tmp) { -+ u64 offset_deadline; -+ struct rq *rq; -+ int rq_prio; -+ -+ rq = cpu_rq(cpu); -+ rq_prio = rq->rq_prio; -+ if (rq_prio < highest_prio) -+ continue; -+ -+ offset_deadline = rq->rq_deadline - -+ cache_distance(this_rq, rq, p); -+ -+ if (rq_prio > highest_prio || (rq_prio == highest_prio && -+ deadline_after(offset_deadline, latest_deadline))) { -+ latest_deadline = offset_deadline; -+ highest_prio = rq_prio; -+ highest_prio_rq = rq; -+ } -+ } -+ -+ if (!can_preempt(p, highest_prio, highest_prio_rq->rq_deadline, -+ highest_prio_rq->rq_policy)) -+ return; -+ -+ resched_task(highest_prio_rq->curr); -+} -+#else /* CONFIG_SMP */ -+static inline int needs_other_cpu(struct task_struct *p, int cpu) -+{ -+ return 0; -+} -+ -+static void try_preempt(struct task_struct *p, struct rq *this_rq) -+{ -+ if (p->policy == SCHED_IDLEPRIO) -+ return; -+ if (can_preempt(p, uprq->rq_prio, uprq->rq_deadline, -+ uprq->rq_policy)) -+ resched_task(uprq->curr); -+} -+#endif /* CONFIG_SMP */ -+ -+/** -+ * task_oncpu_function_call - call a function on the cpu on which a task runs -+ * @p: the task to evaluate -+ * @func: the function to be called -+ * @info: the function call argument -+ * -+ * Calls the function @func when the task is currently running. This might -+ * be on the current CPU, which just calls the function directly -+ */ -+void task_oncpu_function_call(struct task_struct *p, -+ void (*func) (void *info), void *info) -+{ -+ int cpu; -+ -+ preempt_disable(); -+ cpu = task_cpu(p); -+ if (task_curr(p)) -+ smp_call_function_single(cpu, func, info, 1); -+ preempt_enable(); -+} -+ -+static inline void ttwu_activate(struct task_struct *p, struct rq *rq, -+ bool is_sync) -+{ -+ activate_task(p, rq); -+ -+ /* -+ * Sync wakeups (i.e. those types of wakeups where the waker -+ * has indicated that it will leave the CPU in short order) -+ * don't trigger a preemption if there are no idle cpus, -+ * instead waiting for current to deschedule. -+ */ -+ if (!is_sync || suitable_idle_cpus(p)) -+ try_preempt(p, rq); -+} -+ -+static inline void ttwu_post_activation(struct task_struct *p, struct rq *rq, -+ bool success) -+{ -+ trace_sched_wakeup(p, success); -+ p->state = TASK_RUNNING; -+ -+ /* -+ * if a worker is waking up, notify workqueue. Note that on BFS, we -+ * don't really know what cpu it will be, so we fake it for -+ * wq_worker_waking_up :/ -+ */ -+ if ((p->flags & PF_WQ_WORKER) && success) -+ wq_worker_waking_up(p, cpu_of(rq)); -+} -+ -+/*** -+ * try_to_wake_up - wake up a thread -+ * @p: the thread to be awakened -+ * @state: the mask of task states that can be woken -+ * @wake_flags: wake modifier flags (WF_*) -+ * -+ * Put it on the run-queue if it's not already there. The "current" -+ * thread is always on the run-queue (except when the actual -+ * re-schedule is in progress), and as such you're allowed to do -+ * the simpler "current->state = TASK_RUNNING" to mark yourself -+ * runnable without the overhead of this. -+ * -+ * Returns %true if @p was woken up, %false if it was already running -+ * or @state didn't match @p's state. -+ */ -+static int try_to_wake_up(struct task_struct *p, unsigned int state, -+ int wake_flags) -+{ -+ unsigned long flags; -+ int success = 0; -+ struct rq *rq; -+ -+ get_cpu(); -+ -+ /* This barrier is undocumented, probably for p->state? くそ */ -+ smp_wmb(); -+ -+ /* -+ * No need to do time_lock_grq as we only need to update the rq clock -+ * if we activate the task -+ */ -+ rq = task_grq_lock(p, &flags); -+ -+ /* state is a volatile long, どうして、分からない */ -+ if (!((unsigned int)p->state & state)) -+ goto out_unlock; -+ -+ if (task_queued(p) || task_running(p)) -+ goto out_running; -+ -+ ttwu_activate(p, rq, wake_flags & WF_SYNC); -+ success = true; -+ -+out_running: -+ ttwu_post_activation(p, rq, success); -+out_unlock: -+ task_grq_unlock(&flags); -+ put_cpu(); -+ -+ return success; -+} -+ -+/** -+ * try_to_wake_up_local - try to wake up a local task with grq lock held -+ * @p: the thread to be awakened -+ * -+ * Put @p on the run-queue if it's not already there. The caller must -+ * ensure that grq is locked and, @p is not the current task. -+ * grq stays locked over invocation. -+ */ -+static void try_to_wake_up_local(struct task_struct *p) -+{ -+ struct rq *rq = task_rq(p); -+ bool success = false; -+ -+ WARN_ON(rq != this_rq()); -+ BUG_ON(p == current); -+ lockdep_assert_held(&grq.lock); -+ -+ if (!(p->state & TASK_NORMAL)) -+ return; -+ -+ if (!task_queued(p)) { -+ if (likely(!task_running(p))) { -+ schedstat_inc(rq, ttwu_count); -+ schedstat_inc(rq, ttwu_local); -+ } -+ ttwu_activate(p, rq, false); -+ success = true; -+ } -+ ttwu_post_activation(p, rq, success); -+} -+ -+/** -+ * wake_up_process - Wake up a specific process -+ * @p: The process to be woken up. -+ * -+ * Attempt to wake up the nominated process and move it to the set of runnable -+ * processes. Returns 1 if the process was woken up, 0 if it was already -+ * running. -+ * -+ * It may be assumed that this function implies a write memory barrier before -+ * changing the task state if and only if any tasks are woken up. -+ */ -+int wake_up_process(struct task_struct *p) -+{ -+ return try_to_wake_up(p, TASK_ALL, 0); -+} -+EXPORT_SYMBOL(wake_up_process); -+ -+int wake_up_state(struct task_struct *p, unsigned int state) -+{ -+ return try_to_wake_up(p, state, 0); -+} -+ -+static void time_slice_expired(struct task_struct *p); -+ -+/* -+ * Perform scheduler related setup for a newly forked process p. -+ * p is forked by current. -+ */ -+void sched_fork(struct task_struct *p, int clone_flags) -+{ -+ struct task_struct *curr; -+ int cpu = get_cpu(); -+ struct rq *rq; -+ -+#ifdef CONFIG_PREEMPT_NOTIFIERS -+ INIT_HLIST_HEAD(&p->preempt_notifiers); -+#endif -+ /* -+ * We mark the process as running here. This guarantees that -+ * nobody will actually run it, and a signal or other external -+ * event cannot wake it up and insert it on the runqueue either. -+ */ -+ p->state = TASK_RUNNING; -+ set_task_cpu(p, cpu); -+ -+ /* Should be reset in fork.c but done here for ease of bfs patching */ -+ p->sched_time = p->stime_pc = p->utime_pc = 0; -+ -+ /* -+ * Revert to default priority/policy on fork if requested. -+ */ -+ if (unlikely(p->sched_reset_on_fork)) { -+ if (p->policy == SCHED_FIFO || p->policy == SCHED_RR) { -+ p->policy = SCHED_NORMAL; -+ p->normal_prio = normal_prio(p); -+ } -+ -+ if (PRIO_TO_NICE(p->static_prio) < 0) { -+ p->static_prio = NICE_TO_PRIO(0); -+ p->normal_prio = p->static_prio; -+ } -+ -+ /* -+ * We don't need the reset flag anymore after the fork. It has -+ * fulfilled its duty: -+ */ -+ p->sched_reset_on_fork = 0; -+ } -+ -+ curr = current; -+ /* -+ * Make sure we do not leak PI boosting priority to the child. -+ */ -+ p->prio = curr->normal_prio; -+ -+ INIT_LIST_HEAD(&p->run_list); -+#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) -+ if (unlikely(sched_info_on())) -+ memset(&p->sched_info, 0, sizeof(p->sched_info)); -+#endif -+ -+ p->oncpu = 0; -+ -+#ifdef CONFIG_PREEMPT -+ /* Want to start with kernel preemption disabled. */ -+ task_thread_info(p)->preempt_count = 1; -+#endif -+ if (unlikely(p->policy == SCHED_FIFO)) -+ goto out; -+ /* -+ * Share the timeslice between parent and child, thus the -+ * total amount of pending timeslices in the system doesn't change, -+ * resulting in more scheduling fairness. If it's negative, it won't -+ * matter since that's the same as being 0. current's time_slice is -+ * actually in rq_time_slice when it's running, as is its last_ran -+ * value. rq->rq_deadline is only modified within schedule() so it -+ * is always equal to current->deadline. -+ */ -+ rq = task_grq_lock_irq(curr); -+ if (likely(rq->rq_time_slice >= RESCHED_US * 2)) { -+ rq->rq_time_slice /= 2; -+ p->time_slice = rq->rq_time_slice; -+ } else { -+ /* -+ * Forking task has run out of timeslice. Reschedule it and -+ * start its child with a new time slice and deadline. The -+ * child will end up running first because its deadline will -+ * be slightly earlier. -+ */ -+ rq->rq_time_slice = 0; -+ set_tsk_need_resched(curr); -+ time_slice_expired(p); -+ } -+ p->last_ran = rq->rq_last_ran; -+ task_grq_unlock_irq(); -+out: -+ put_cpu(); -+} -+ -+/* -+ * wake_up_new_task - wake up a newly created task for the first time. -+ * -+ * This function will do some initial scheduler statistics housekeeping -+ * that must be done for every newly created context, then puts the task -+ * on the runqueue and wakes it. -+ */ -+void wake_up_new_task(struct task_struct *p, unsigned long clone_flags) -+{ -+ struct task_struct *parent; -+ unsigned long flags; -+ struct rq *rq; -+ -+ rq = task_grq_lock(p, &flags); -+ p->state = TASK_RUNNING; -+ parent = p->parent; -+ /* Unnecessary but small chance that the parent changed CPU */ -+ set_task_cpu(p, task_cpu(parent)); -+ activate_task(p, rq); -+ trace_sched_wakeup_new(p, 1); -+ if (!(clone_flags & CLONE_VM) && rq->curr == parent && -+ !suitable_idle_cpus(p)) { -+ /* -+ * The VM isn't cloned, so we're in a good position to -+ * do child-runs-first in anticipation of an exec. This -+ * usually avoids a lot of COW overhead. -+ */ -+ resched_task(parent); -+ } else -+ try_preempt(p, rq); -+ task_grq_unlock(&flags); -+} -+ -+#ifdef CONFIG_PREEMPT_NOTIFIERS -+ -+/** -+ * preempt_notifier_register - tell me when current is being preempted & rescheduled -+ * @notifier: notifier struct to register -+ */ -+void preempt_notifier_register(struct preempt_notifier *notifier) -+{ -+ hlist_add_head(¬ifier->link, ¤t->preempt_notifiers); -+} -+EXPORT_SYMBOL_GPL(preempt_notifier_register); -+ -+/** -+ * preempt_notifier_unregister - no longer interested in preemption notifications -+ * @notifier: notifier struct to unregister -+ * -+ * This is safe to call from within a preemption notifier. -+ */ -+void preempt_notifier_unregister(struct preempt_notifier *notifier) -+{ -+ hlist_del(¬ifier->link); -+} -+EXPORT_SYMBOL_GPL(preempt_notifier_unregister); -+ -+static void fire_sched_in_preempt_notifiers(struct task_struct *curr) -+{ -+ struct preempt_notifier *notifier; -+ struct hlist_node *node; -+ -+ hlist_for_each_entry(notifier, node, &curr->preempt_notifiers, link) -+ notifier->ops->sched_in(notifier, raw_smp_processor_id()); -+} -+ -+static void -+fire_sched_out_preempt_notifiers(struct task_struct *curr, -+ struct task_struct *next) -+{ -+ struct preempt_notifier *notifier; -+ struct hlist_node *node; -+ -+ hlist_for_each_entry(notifier, node, &curr->preempt_notifiers, link) -+ notifier->ops->sched_out(notifier, next); -+} -+ -+#else /* !CONFIG_PREEMPT_NOTIFIERS */ -+ -+static void fire_sched_in_preempt_notifiers(struct task_struct *curr) -+{ -+} -+ -+static void -+fire_sched_out_preempt_notifiers(struct task_struct *curr, -+ struct task_struct *next) -+{ -+} -+ -+#endif /* CONFIG_PREEMPT_NOTIFIERS */ -+ -+/** -+ * prepare_task_switch - prepare to switch tasks -+ * @rq: the runqueue preparing to switch -+ * @next: the task we are going to switch to. -+ * -+ * This is called with the rq lock held and interrupts off. It must -+ * be paired with a subsequent finish_task_switch after the context -+ * switch. -+ * -+ * prepare_task_switch sets up locking and calls architecture specific -+ * hooks. -+ */ -+static inline void -+prepare_task_switch(struct rq *rq, struct task_struct *prev, -+ struct task_struct *next) -+{ -+ fire_sched_out_preempt_notifiers(prev, next); -+ prepare_lock_switch(rq, next); -+ prepare_arch_switch(next); -+} -+ -+/** -+ * finish_task_switch - clean up after a task-switch -+ * @rq: runqueue associated with task-switch -+ * @prev: the thread we just switched away from. -+ * -+ * finish_task_switch must be called after the context switch, paired -+ * with a prepare_task_switch call before the context switch. -+ * finish_task_switch will reconcile locking set up by prepare_task_switch, -+ * and do any other architecture-specific cleanup actions. -+ * -+ * Note that we may have delayed dropping an mm in context_switch(). If -+ * so, we finish that here outside of the runqueue lock. (Doing it -+ * with the lock held can cause deadlocks; see schedule() for -+ * details.) -+ */ -+static inline void finish_task_switch(struct rq *rq, struct task_struct *prev) -+ __releases(grq.lock) -+{ -+ struct mm_struct *mm = rq->prev_mm; -+ long prev_state; -+ -+ rq->prev_mm = NULL; -+ -+ /* -+ * A task struct has one reference for the use as "current". -+ * If a task dies, then it sets TASK_DEAD in tsk->state and calls -+ * schedule one last time. The schedule call will never return, and -+ * the scheduled task must drop that reference. -+ * The test for TASK_DEAD must occur while the runqueue locks are -+ * still held, otherwise prev could be scheduled on another cpu, die -+ * there before we look at prev->state, and then the reference would -+ * be dropped twice. -+ * Manfred Spraul -+ */ -+ prev_state = prev->state; -+ finish_arch_switch(prev); -+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW -+ local_irq_disable(); -+#endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */ -+ perf_event_task_sched_in(current); -+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW -+ local_irq_enable(); -+#endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */ -+ finish_lock_switch(rq, prev); -+ -+ fire_sched_in_preempt_notifiers(current); -+ if (mm) -+ mmdrop(mm); -+ if (unlikely(prev_state == TASK_DEAD)) { -+ /* -+ * Remove function-return probe instances associated with this -+ * task and put them back on the free list. -+ */ -+ kprobe_flush_task(prev); -+ put_task_struct(prev); -+ } -+} -+ -+/** -+ * schedule_tail - first thing a freshly forked thread must call. -+ * @prev: the thread we just switched away from. -+ */ -+asmlinkage void schedule_tail(struct task_struct *prev) -+ __releases(grq.lock) -+{ -+ struct rq *rq = this_rq(); -+ -+ finish_task_switch(rq, prev); -+#ifdef __ARCH_WANT_UNLOCKED_CTXSW -+ /* In this case, finish_task_switch does not reenable preemption */ -+ preempt_enable(); -+#endif -+ if (current->set_child_tid) -+ put_user(current->pid, current->set_child_tid); -+} -+ -+/* -+ * context_switch - switch to the new MM and the new -+ * thread's register state. -+ */ -+static inline void -+context_switch(struct rq *rq, struct task_struct *prev, -+ struct task_struct *next) -+{ -+ struct mm_struct *mm, *oldmm; -+ -+ prepare_task_switch(rq, prev, next); -+ trace_sched_switch(prev, next); -+ mm = next->mm; -+ oldmm = prev->active_mm; -+ /* -+ * For paravirt, this is coupled with an exit in switch_to to -+ * combine the page table reload and the switch backend into -+ * one hypercall. -+ */ -+ arch_start_context_switch(prev); -+ -+ if (!mm) { -+ next->active_mm = oldmm; -+ atomic_inc(&oldmm->mm_count); -+ enter_lazy_tlb(oldmm, next); -+ } else -+ switch_mm(oldmm, mm, next); -+ -+ if (!prev->mm) { -+ prev->active_mm = NULL; -+ rq->prev_mm = oldmm; -+ } -+ /* -+ * Since the runqueue lock will be released by the next -+ * task (which is an invalid locking op but in the case -+ * of the scheduler it's an obvious special-case), so we -+ * do an early lockdep release here: -+ */ -+#ifndef __ARCH_WANT_UNLOCKED_CTXSW -+ spin_release(&grq.lock.dep_map, 1, _THIS_IP_); -+#endif -+ -+ /* Here we just switch the register state and the stack. */ -+ switch_to(prev, next, prev); -+ -+ barrier(); -+ /* -+ * this_rq must be evaluated again because prev may have moved -+ * CPUs since it called schedule(), thus the 'rq' on its stack -+ * frame will be invalid. -+ */ -+ finish_task_switch(this_rq(), prev); -+} -+ -+/* -+ * nr_running, nr_uninterruptible and nr_context_switches: -+ * -+ * externally visible scheduler statistics: current number of runnable -+ * threads, current number of uninterruptible-sleeping threads, total -+ * number of context switches performed since bootup. All are measured -+ * without grabbing the grq lock but the occasional inaccurate result -+ * doesn't matter so long as it's positive. -+ */ -+unsigned long nr_running(void) -+{ -+ long nr = grq.nr_running; -+ -+ if (unlikely(nr < 0)) -+ nr = 0; -+ return (unsigned long)nr; -+} -+ -+unsigned long nr_uninterruptible(void) -+{ -+ long nu = grq.nr_uninterruptible; -+ -+ if (unlikely(nu < 0)) -+ nu = 0; -+ return nu; -+} -+ -+unsigned long long nr_context_switches(void) -+{ -+ long long ns = grq.nr_switches; -+ -+ /* This is of course impossible */ -+ if (unlikely(ns < 0)) -+ ns = 1; -+ return (long long)ns; -+} -+ -+unsigned long nr_iowait(void) -+{ -+ unsigned long i, sum = 0; -+ -+ for_each_possible_cpu(i) -+ sum += atomic_read(&cpu_rq(i)->nr_iowait); -+ -+ return sum; -+} -+ -+unsigned long nr_iowait_cpu(int cpu) -+{ -+ struct rq *this = cpu_rq(cpu); -+ return atomic_read(&this->nr_iowait); -+} -+ -+unsigned long nr_active(void) -+{ -+ return nr_running() + nr_uninterruptible(); -+} -+ -+/* Beyond a task running on this CPU, load is equal everywhere on BFS */ -+unsigned long this_cpu_load(void) -+{ -+ return this_rq()->rq_running + -+ (queued_notrunning() + nr_uninterruptible()) / -+ (1 + num_online_cpus()); -+} -+ -+/* Variables and functions for calc_load */ -+static unsigned long calc_load_update; -+unsigned long avenrun[3]; -+EXPORT_SYMBOL(avenrun); -+ -+/** -+ * get_avenrun - get the load average array -+ * @loads: pointer to dest load array -+ * @offset: offset to add -+ * @shift: shift count to shift the result left -+ * -+ * These values are estimates at best, so no need for locking. -+ */ -+void get_avenrun(unsigned long *loads, unsigned long offset, int shift) -+{ -+ loads[0] = (avenrun[0] + offset) << shift; -+ loads[1] = (avenrun[1] + offset) << shift; -+ loads[2] = (avenrun[2] + offset) << shift; -+} -+ -+static unsigned long -+calc_load(unsigned long load, unsigned long exp, unsigned long active) -+{ -+ load *= exp; -+ load += active * (FIXED_1 - exp); -+ return load >> FSHIFT; -+} -+ -+/* -+ * calc_load - update the avenrun load estimates every LOAD_FREQ seconds. -+ */ -+void calc_global_load(unsigned long ticks) -+{ -+ long active; -+ -+ if (time_before(jiffies, calc_load_update)) -+ return; -+ active = nr_active() * FIXED_1; -+ -+ avenrun[0] = calc_load(avenrun[0], EXP_1, active); -+ avenrun[1] = calc_load(avenrun[1], EXP_5, active); -+ avenrun[2] = calc_load(avenrun[2], EXP_15, active); -+ -+ calc_load_update = jiffies + LOAD_FREQ; -+} -+ -+DEFINE_PER_CPU(struct kernel_stat, kstat); -+ -+EXPORT_PER_CPU_SYMBOL(kstat); -+ -+#ifdef CONFIG_IRQ_TIME_ACCOUNTING -+ -+/* -+ * There are no locks covering percpu hardirq/softirq time. -+ * They are only modified in account_system_vtime, on corresponding CPU -+ * with interrupts disabled. So, writes are safe. -+ * They are read and saved off onto struct rq in update_rq_clock(). -+ * This may result in other CPU reading this CPU's irq time and can -+ * race with irq/account_system_vtime on this CPU. We would either get old -+ * or new value with a side effect of accounting a slice of irq time to wrong -+ * task when irq is in progress while we read rq->clock. That is a worthy -+ * compromise in place of having locks on each irq in account_system_time. -+ */ -+static DEFINE_PER_CPU(u64, cpu_hardirq_time); -+static DEFINE_PER_CPU(u64, cpu_softirq_time); -+ -+static DEFINE_PER_CPU(u64, irq_start_time); -+static int sched_clock_irqtime; -+ -+void enable_sched_clock_irqtime(void) -+{ -+ sched_clock_irqtime = 1; -+} -+ -+void disable_sched_clock_irqtime(void) -+{ -+ sched_clock_irqtime = 0; -+} -+ -+#ifndef CONFIG_64BIT -+static DEFINE_PER_CPU(seqcount_t, irq_time_seq); -+ -+static inline void irq_time_write_begin(void) -+{ -+ __this_cpu_inc(irq_time_seq.sequence); -+ smp_wmb(); -+} -+ -+static inline void irq_time_write_end(void) -+{ -+ smp_wmb(); -+ __this_cpu_inc(irq_time_seq.sequence); -+} -+ -+static inline u64 irq_time_read(int cpu) -+{ -+ u64 irq_time; -+ unsigned seq; -+ -+ do { -+ seq = read_seqcount_begin(&per_cpu(irq_time_seq, cpu)); -+ irq_time = per_cpu(cpu_softirq_time, cpu) + -+ per_cpu(cpu_hardirq_time, cpu); -+ } while (read_seqcount_retry(&per_cpu(irq_time_seq, cpu), seq)); -+ -+ return irq_time; -+} -+#else /* CONFIG_64BIT */ -+static inline void irq_time_write_begin(void) -+{ -+} -+ -+static inline void irq_time_write_end(void) -+{ -+} -+ -+static inline u64 irq_time_read(int cpu) -+{ -+ return per_cpu(cpu_softirq_time, cpu) + per_cpu(cpu_hardirq_time, cpu); -+} -+#endif /* CONFIG_64BIT */ -+ -+/* -+ * Called before incrementing preempt_count on {soft,}irq_enter -+ * and before decrementing preempt_count on {soft,}irq_exit. -+ */ -+void account_system_vtime(struct task_struct *curr) -+{ -+ unsigned long flags; -+ s64 delta; -+ int cpu; -+ -+ if (!sched_clock_irqtime) -+ return; -+ -+ local_irq_save(flags); -+ -+ cpu = smp_processor_id(); -+ delta = sched_clock_cpu(cpu) - __this_cpu_read(irq_start_time); -+ __this_cpu_add(irq_start_time, delta); -+ -+ irq_time_write_begin(); -+ /* -+ * We do not account for softirq time from ksoftirqd here. -+ * We want to continue accounting softirq time to ksoftirqd thread -+ * in that case, so as not to confuse scheduler with a special task -+ * that do not consume any time, but still wants to run. -+ */ -+ if (hardirq_count()) -+ __this_cpu_add(cpu_hardirq_time, delta); -+ else if (in_serving_softirq() && !(curr->flags & PF_KSOFTIRQD)) -+ __this_cpu_add(cpu_softirq_time, delta); -+ -+ irq_time_write_end(); -+ local_irq_restore(flags); -+} -+EXPORT_SYMBOL_GPL(account_system_vtime); -+ -+static void update_rq_clock_task(struct rq *rq, s64 delta) -+{ -+ s64 irq_delta; -+ -+ irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time; -+ -+ /* -+ * Since irq_time is only updated on {soft,}irq_exit, we might run into -+ * this case when a previous update_rq_clock() happened inside a -+ * {soft,}irq region. -+ * -+ * When this happens, we stop ->clock_task and only update the -+ * prev_irq_time stamp to account for the part that fit, so that a next -+ * update will consume the rest. This ensures ->clock_task is -+ * monotonic. -+ * -+ * It does however cause some slight miss-attribution of {soft,}irq -+ * time, a more accurate solution would be to update the irq_time using -+ * the current rq->clock timestamp, except that would require using -+ * atomic ops. -+ */ -+ if (irq_delta > delta) -+ irq_delta = delta; -+ -+ rq->prev_irq_time += irq_delta; -+ delta -= irq_delta; -+ rq->clock_task += delta; -+} -+ -+#else /* CONFIG_IRQ_TIME_ACCOUNTING */ -+ -+static void update_rq_clock_task(struct rq *rq, s64 delta) -+{ -+ rq->clock_task += delta; -+} -+ -+#endif /* CONFIG_IRQ_TIME_ACCOUNTING */ -+ -+/* -+ * On each tick, see what percentage of that tick was attributed to each -+ * component and add the percentage to the _pc values. Once a _pc value has -+ * accumulated one tick's worth, account for that. This means the total -+ * percentage of load components will always be 100 per tick. -+ */ -+static void pc_idle_time(struct rq *rq, unsigned long pc) -+{ -+ struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; -+ cputime64_t tmp = cputime_to_cputime64(cputime_one_jiffy); -+ -+ if (atomic_read(&rq->nr_iowait) > 0) { -+ rq->iowait_pc += pc; -+ if (rq->iowait_pc >= 100) { -+ rq->iowait_pc %= 100; -+ cpustat->iowait = cputime64_add(cpustat->iowait, tmp); -+ } -+ } else { -+ rq->idle_pc += pc; -+ if (rq->idle_pc >= 100) { -+ rq->idle_pc %= 100; -+ cpustat->idle = cputime64_add(cpustat->idle, tmp); -+ } -+ } -+} -+ -+static void -+pc_system_time(struct rq *rq, struct task_struct *p, int hardirq_offset, -+ unsigned long pc, unsigned long ns) -+{ -+ struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; -+ cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy); -+ cputime64_t tmp = cputime_to_cputime64(cputime_one_jiffy); -+ -+ p->stime_pc += pc; -+ if (p->stime_pc >= 100) { -+ p->stime_pc -= 100; -+ p->stime = cputime_add(p->stime, cputime_one_jiffy); -+ p->stimescaled = cputime_add(p->stimescaled, one_jiffy_scaled); -+ account_group_system_time(p, cputime_one_jiffy); -+ acct_update_integrals(p); -+ } -+ p->sched_time += ns; -+ -+ if (hardirq_count() - hardirq_offset) { -+ rq->irq_pc += pc; -+ if (rq->irq_pc >= 100) { -+ rq->irq_pc %= 100; -+ cpustat->irq = cputime64_add(cpustat->irq, tmp); -+ } -+ } else if (in_serving_softirq()) { -+ rq->softirq_pc += pc; -+ if (rq->softirq_pc >= 100) { -+ rq->softirq_pc %= 100; -+ cpustat->softirq = cputime64_add(cpustat->softirq, tmp); -+ } -+ } else { -+ rq->system_pc += pc; -+ if (rq->system_pc >= 100) { -+ rq->system_pc %= 100; -+ cpustat->system = cputime64_add(cpustat->system, tmp); -+ } -+ } -+} -+ -+static void pc_user_time(struct rq *rq, struct task_struct *p, -+ unsigned long pc, unsigned long ns) -+{ -+ struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; -+ cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy); -+ cputime64_t tmp = cputime_to_cputime64(cputime_one_jiffy); -+ -+ p->utime_pc += pc; -+ if (p->utime_pc >= 100) { -+ p->utime_pc -= 100; -+ p->utime = cputime_add(p->utime, cputime_one_jiffy); -+ p->utimescaled = cputime_add(p->utimescaled, one_jiffy_scaled); -+ account_group_user_time(p, cputime_one_jiffy); -+ acct_update_integrals(p); -+ } -+ p->sched_time += ns; -+ -+ if (TASK_NICE(p) > 0 || idleprio_task(p)) { -+ rq->nice_pc += pc; -+ if (rq->nice_pc >= 100) { -+ rq->nice_pc %= 100; -+ cpustat->nice = cputime64_add(cpustat->nice, tmp); -+ } -+ } else { -+ rq->user_pc += pc; -+ if (rq->user_pc >= 100) { -+ rq->user_pc %= 100; -+ cpustat->user = cputime64_add(cpustat->user, tmp); -+ } -+ } -+} -+ -+/* Convert nanoseconds to percentage of one tick. */ -+#define NS_TO_PC(NS) (NS * 100 / JIFFY_NS) -+ -+/* -+ * This is called on clock ticks and on context switches. -+ * Bank in p->sched_time the ns elapsed since the last tick or switch. -+ * CPU scheduler quota accounting is also performed here in microseconds. -+ */ -+static void -+update_cpu_clock(struct rq *rq, struct task_struct *p, int tick) -+{ -+ long account_ns = rq->clock - rq->timekeep_clock; -+ struct task_struct *idle = rq->idle; -+ unsigned long account_pc; -+ -+ if (unlikely(account_ns < 0)) -+ account_ns = 0; -+ -+ account_pc = NS_TO_PC(account_ns); -+ -+ if (tick) { -+ int user_tick = user_mode(get_irq_regs()); -+ -+ /* Accurate tick timekeeping */ -+ if (user_tick) -+ pc_user_time(rq, p, account_pc, account_ns); -+ else if (p != idle || (irq_count() != HARDIRQ_OFFSET)) -+ pc_system_time(rq, p, HARDIRQ_OFFSET, -+ account_pc, account_ns); -+ else -+ pc_idle_time(rq, account_pc); -+ } else { -+ /* Accurate subtick timekeeping */ -+ if (p == idle) -+ pc_idle_time(rq, account_pc); -+ else -+ pc_user_time(rq, p, account_pc, account_ns); -+ } -+ -+ /* time_slice accounting is done in usecs to avoid overflow on 32bit */ -+ if (rq->rq_policy != SCHED_FIFO && p != idle) { -+ s64 time_diff = rq->clock - rq->rq_last_ran; -+ -+ niffy_diff(&time_diff, 1); -+ rq->rq_time_slice -= NS_TO_US(time_diff); -+ } -+ rq->rq_last_ran = rq->timekeep_clock = rq->clock; -+} -+ -+/* -+ * Return any ns on the sched_clock that have not yet been accounted in -+ * @p in case that task is currently running. -+ * -+ * Called with task_grq_lock() held. -+ */ -+static u64 do_task_delta_exec(struct task_struct *p, struct rq *rq) -+{ -+ u64 ns = 0; -+ -+ if (p == rq->curr) { -+ update_clocks(rq); -+ ns = rq->clock_task - rq->rq_last_ran; -+ if (unlikely((s64)ns < 0)) -+ ns = 0; -+ } -+ -+ return ns; -+} -+ -+unsigned long long task_delta_exec(struct task_struct *p) -+{ -+ unsigned long flags; -+ struct rq *rq; -+ u64 ns; -+ -+ rq = task_grq_lock(p, &flags); -+ ns = do_task_delta_exec(p, rq); -+ task_grq_unlock(&flags); -+ -+ return ns; -+} -+ -+/* -+ * Return accounted runtime for the task. -+ * In case the task is currently running, return the runtime plus current's -+ * pending runtime that have not been accounted yet. -+ */ -+unsigned long long task_sched_runtime(struct task_struct *p) -+{ -+ unsigned long flags; -+ struct rq *rq; -+ u64 ns; -+ -+ rq = task_grq_lock(p, &flags); -+ ns = p->sched_time + do_task_delta_exec(p, rq); -+ task_grq_unlock(&flags); -+ -+ return ns; -+} -+ -+/* -+ * Return sum_exec_runtime for the thread group. -+ * In case the task is currently running, return the sum plus current's -+ * pending runtime that have not been accounted yet. -+ * -+ * Note that the thread group might have other running tasks as well, -+ * so the return value not includes other pending runtime that other -+ * running tasks might have. -+ */ -+unsigned long long thread_group_sched_runtime(struct task_struct *p) -+{ -+ struct task_cputime totals; -+ unsigned long flags; -+ struct rq *rq; -+ u64 ns; -+ -+ rq = task_grq_lock(p, &flags); -+ thread_group_cputime(p, &totals); -+ ns = totals.sum_exec_runtime + do_task_delta_exec(p, rq); -+ task_grq_unlock(&flags); -+ -+ return ns; -+} -+ -+/* Compatibility crap for removal */ -+void account_user_time(struct task_struct *p, cputime_t cputime, -+ cputime_t cputime_scaled) -+{ -+} -+ -+void account_idle_time(cputime_t cputime) -+{ -+} -+ -+/* -+ * Account guest cpu time to a process. -+ * @p: the process that the cpu time gets accounted to -+ * @cputime: the cpu time spent in virtual machine since the last update -+ * @cputime_scaled: cputime scaled by cpu frequency -+ */ -+static void account_guest_time(struct task_struct *p, cputime_t cputime, -+ cputime_t cputime_scaled) -+{ -+ cputime64_t tmp; -+ struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; -+ -+ tmp = cputime_to_cputime64(cputime); -+ -+ /* Add guest time to process. */ -+ p->utime = cputime_add(p->utime, cputime); -+ p->utimescaled = cputime_add(p->utimescaled, cputime_scaled); -+ account_group_user_time(p, cputime); -+ p->gtime = cputime_add(p->gtime, cputime); -+ -+ /* Add guest time to cpustat. */ -+ if (TASK_NICE(p) > 0) { -+ cpustat->nice = cputime64_add(cpustat->nice, tmp); -+ cpustat->guest_nice = cputime64_add(cpustat->guest_nice, tmp); -+ } else { -+ cpustat->user = cputime64_add(cpustat->user, tmp); -+ cpustat->guest = cputime64_add(cpustat->guest, tmp); -+ } -+} -+ -+/* -+ * Account system cpu time to a process. -+ * @p: the process that the cpu time gets accounted to -+ * @hardirq_offset: the offset to subtract from hardirq_count() -+ * @cputime: the cpu time spent in kernel space since the last update -+ * @cputime_scaled: cputime scaled by cpu frequency -+ * This is for guest only now. -+ */ -+void account_system_time(struct task_struct *p, int hardirq_offset, -+ cputime_t cputime, cputime_t cputime_scaled) -+{ -+ -+ if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) -+ account_guest_time(p, cputime, cputime_scaled); -+} -+ -+/* -+ * Account for involuntary wait time. -+ * @steal: the cpu time spent in involuntary wait -+ */ -+void account_steal_time(cputime_t cputime) -+{ -+ struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; -+ cputime64_t cputime64 = cputime_to_cputime64(cputime); -+ -+ cpustat->steal = cputime64_add(cpustat->steal, cputime64); -+} -+ -+/* -+ * Account for idle time. -+ * @cputime: the cpu time spent in idle wait -+ */ -+static void account_idle_times(cputime_t cputime) -+{ -+ struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; -+ cputime64_t cputime64 = cputime_to_cputime64(cputime); -+ struct rq *rq = this_rq(); -+ -+ if (atomic_read(&rq->nr_iowait) > 0) -+ cpustat->iowait = cputime64_add(cpustat->iowait, cputime64); -+ else -+ cpustat->idle = cputime64_add(cpustat->idle, cputime64); -+} -+ -+#ifndef CONFIG_VIRT_CPU_ACCOUNTING -+ -+void account_process_tick(struct task_struct *p, int user_tick) -+{ -+} -+ -+/* -+ * Account multiple ticks of steal time. -+ * @p: the process from which the cpu time has been stolen -+ * @ticks: number of stolen ticks -+ */ -+void account_steal_ticks(unsigned long ticks) -+{ -+ account_steal_time(jiffies_to_cputime(ticks)); -+} -+ -+/* -+ * Account multiple ticks of idle time. -+ * @ticks: number of stolen ticks -+ */ -+void account_idle_ticks(unsigned long ticks) -+{ -+ account_idle_times(jiffies_to_cputime(ticks)); -+} -+#endif -+ -+static inline void grq_iso_lock(void) -+ __acquires(grq.iso_lock) -+{ -+ raw_spin_lock(&grq.iso_lock); -+} -+ -+static inline void grq_iso_unlock(void) -+ __releases(grq.iso_lock) -+{ -+ raw_spin_unlock(&grq.iso_lock); -+} -+ -+/* -+ * Functions to test for when SCHED_ISO tasks have used their allocated -+ * quota as real time scheduling and convert them back to SCHED_NORMAL. -+ * Where possible, the data is tested lockless, to avoid grabbing iso_lock -+ * because the occasional inaccurate result won't matter. However the -+ * tick data is only ever modified under lock. iso_refractory is only simply -+ * set to 0 or 1 so it's not worth grabbing the lock yet again for that. -+ */ -+static void set_iso_refractory(void) -+{ -+ grq.iso_refractory = 1; -+} -+ -+static void clear_iso_refractory(void) -+{ -+ grq.iso_refractory = 0; -+} -+ -+/* -+ * Test if SCHED_ISO tasks have run longer than their alloted period as RT -+ * tasks and set the refractory flag if necessary. There is 10% hysteresis -+ * for unsetting the flag. 115/128 is ~90/100 as a fast shift instead of a -+ * slow division. -+ */ -+static unsigned int test_ret_isorefractory(struct rq *rq) -+{ -+ if (likely(!grq.iso_refractory)) { -+ if (grq.iso_ticks > ISO_PERIOD * sched_iso_cpu) -+ set_iso_refractory(); -+ } else { -+ if (grq.iso_ticks < ISO_PERIOD * (sched_iso_cpu * 115 / 128)) -+ clear_iso_refractory(); -+ } -+ return grq.iso_refractory; -+} -+ -+static void iso_tick(void) -+{ -+ grq_iso_lock(); -+ grq.iso_ticks += 100; -+ grq_iso_unlock(); -+} -+ -+/* No SCHED_ISO task was running so decrease rq->iso_ticks */ -+static inline void no_iso_tick(void) -+{ -+ if (grq.iso_ticks) { -+ grq_iso_lock(); -+ grq.iso_ticks -= grq.iso_ticks / ISO_PERIOD + 1; -+ if (unlikely(grq.iso_refractory && grq.iso_ticks < -+ ISO_PERIOD * (sched_iso_cpu * 115 / 128))) -+ clear_iso_refractory(); -+ grq_iso_unlock(); -+ } -+} -+ -+static int rq_running_iso(struct rq *rq) -+{ -+ return rq->rq_prio == ISO_PRIO; -+} -+ -+/* This manages tasks that have run out of timeslice during a scheduler_tick */ -+static void task_running_tick(struct rq *rq) -+{ -+ struct task_struct *p; -+ -+ /* -+ * If a SCHED_ISO task is running we increment the iso_ticks. In -+ * order to prevent SCHED_ISO tasks from causing starvation in the -+ * presence of true RT tasks we account those as iso_ticks as well. -+ */ -+ if ((rt_queue(rq) || (iso_queue(rq) && !grq.iso_refractory))) { -+ if (grq.iso_ticks <= (ISO_PERIOD * 100) - 100) -+ iso_tick(); -+ } else -+ no_iso_tick(); -+ -+ if (iso_queue(rq)) { -+ if (unlikely(test_ret_isorefractory(rq))) { -+ if (rq_running_iso(rq)) { -+ /* -+ * SCHED_ISO task is running as RT and limit -+ * has been hit. Force it to reschedule as -+ * SCHED_NORMAL by zeroing its time_slice -+ */ -+ rq->rq_time_slice = 0; -+ } -+ } -+ } -+ -+ /* SCHED_FIFO tasks never run out of timeslice. */ -+ if (rq->rq_policy == SCHED_FIFO) -+ return; -+ /* -+ * Tasks that were scheduled in the first half of a tick are not -+ * allowed to run into the 2nd half of the next tick if they will -+ * run out of time slice in the interim. Otherwise, if they have -+ * less than RESCHED_US μs of time slice left they will be rescheduled. -+ */ -+ if (rq->dither) { -+ if (rq->rq_time_slice > HALF_JIFFY_US) -+ return; -+ else -+ rq->rq_time_slice = 0; -+ } else if (rq->rq_time_slice >= RESCHED_US) -+ return; -+ -+ /* p->time_slice < RESCHED_US. We only modify task_struct under grq lock */ -+ p = rq->curr; -+ requeue_task(p); -+ grq_lock(); -+ set_tsk_need_resched(p); -+ grq_unlock(); -+} -+ -+void wake_up_idle_cpu(int cpu); -+ -+/* -+ * This function gets called by the timer code, with HZ frequency. -+ * We call it with interrupts disabled. The data modified is all -+ * local to struct rq so we don't need to grab grq lock. -+ */ -+void scheduler_tick(void) -+{ -+ int cpu __maybe_unused = smp_processor_id(); -+ struct rq *rq = cpu_rq(cpu); -+ -+ sched_clock_tick(); -+ /* grq lock not grabbed, so only update rq clock */ -+ update_rq_clock(rq); -+ update_cpu_clock(rq, rq->curr, 1); -+ if (!rq_idle(rq)) -+ task_running_tick(rq); -+ else -+ no_iso_tick(); -+ rq->last_tick = rq->clock; -+ perf_event_task_tick(); -+} -+ -+notrace unsigned long get_parent_ip(unsigned long addr) -+{ -+ if (in_lock_functions(addr)) { -+ addr = CALLER_ADDR2; -+ if (in_lock_functions(addr)) -+ addr = CALLER_ADDR3; -+ } -+ return addr; -+} -+ -+#if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \ -+ defined(CONFIG_PREEMPT_TRACER)) -+void __kprobes add_preempt_count(int val) -+{ -+#ifdef CONFIG_DEBUG_PREEMPT -+ /* -+ * Underflow? -+ */ -+ if (DEBUG_LOCKS_WARN_ON((preempt_count() < 0))) -+ return; -+#endif -+ preempt_count() += val; -+#ifdef CONFIG_DEBUG_PREEMPT -+ /* -+ * Spinlock count overflowing soon? -+ */ -+ DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >= -+ PREEMPT_MASK - 10); -+#endif -+ if (preempt_count() == val) -+ trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); -+} -+EXPORT_SYMBOL(add_preempt_count); -+ -+void __kprobes sub_preempt_count(int val) -+{ -+#ifdef CONFIG_DEBUG_PREEMPT -+ /* -+ * Underflow? -+ */ -+ if (DEBUG_LOCKS_WARN_ON(val > preempt_count())) -+ return; -+ /* -+ * Is the spinlock portion underflowing? -+ */ -+ if (DEBUG_LOCKS_WARN_ON((val < PREEMPT_MASK) && -+ !(preempt_count() & PREEMPT_MASK))) -+ return; -+#endif -+ -+ if (preempt_count() == val) -+ trace_preempt_on(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); -+ preempt_count() -= val; -+} -+EXPORT_SYMBOL(sub_preempt_count); -+#endif -+ -+/* -+ * Deadline is "now" in niffies + (offset by priority). Setting the deadline -+ * is the key to everything. It distributes cpu fairly amongst tasks of the -+ * same nice value, it proportions cpu according to nice level, it means the -+ * task that last woke up the longest ago has the earliest deadline, thus -+ * ensuring that interactive tasks get low latency on wake up. The CPU -+ * proportion works out to the square of the virtual deadline difference, so -+ * this equation will give nice 19 3% CPU compared to nice 0. -+ */ -+static inline u64 prio_deadline_diff(int user_prio) -+{ -+ return (prio_ratios[user_prio] * rr_interval * (MS_TO_NS(1) / 128)); -+} -+ -+static inline u64 task_deadline_diff(struct task_struct *p) -+{ -+ return prio_deadline_diff(TASK_USER_PRIO(p)); -+} -+ -+static inline u64 static_deadline_diff(int static_prio) -+{ -+ return prio_deadline_diff(USER_PRIO(static_prio)); -+} -+ -+static inline int ms_longest_deadline_diff(void) -+{ -+ return NS_TO_MS(prio_deadline_diff(39)); -+} -+ -+/* -+ * The time_slice is only refilled when it is empty and that is when we set a -+ * new deadline. -+ */ -+static void time_slice_expired(struct task_struct *p) -+{ -+ p->time_slice = timeslice(); -+ p->deadline = grq.niffies + task_deadline_diff(p); -+} -+ -+/* -+ * Timeslices below RESCHED_US are considered as good as expired as there's no -+ * point rescheduling when there's so little time left. SCHED_BATCH tasks -+ * have been flagged be not latency sensitive and likely to be fully CPU -+ * bound so every time they're rescheduled they have their time_slice -+ * refilled, but get a new later deadline to have little effect on -+ * SCHED_NORMAL tasks. -+ -+ */ -+static inline void check_deadline(struct task_struct *p) -+{ -+ if (p->time_slice < RESCHED_US || batch_task(p)) -+ time_slice_expired(p); -+} -+ -+/* -+ * O(n) lookup of all tasks in the global runqueue. The real brainfuck -+ * of lock contention and O(n). It's not really O(n) as only the queued, -+ * but not running tasks are scanned, and is O(n) queued in the worst case -+ * scenario only because the right task can be found before scanning all of -+ * them. -+ * Tasks are selected in this order: -+ * Real time tasks are selected purely by their static priority and in the -+ * order they were queued, so the lowest value idx, and the first queued task -+ * of that priority value is chosen. -+ * If no real time tasks are found, the SCHED_ISO priority is checked, and -+ * all SCHED_ISO tasks have the same priority value, so they're selected by -+ * the earliest deadline value. -+ * If no SCHED_ISO tasks are found, SCHED_NORMAL tasks are selected by the -+ * earliest deadline. -+ * Finally if no SCHED_NORMAL tasks are found, SCHED_IDLEPRIO tasks are -+ * selected by the earliest deadline. -+ */ -+static inline struct -+task_struct *earliest_deadline_task(struct rq *rq, struct task_struct *idle) -+{ -+ u64 dl, earliest_deadline = 0; /* Initialise to silence compiler */ -+ struct task_struct *p, *edt = idle; -+ unsigned int cpu = cpu_of(rq); -+ struct list_head *queue; -+ int idx = 0; -+ -+retry: -+ idx = find_next_bit(grq.prio_bitmap, PRIO_LIMIT, idx); -+ if (idx >= PRIO_LIMIT) -+ goto out; -+ queue = grq.queue + idx; -+ list_for_each_entry(p, queue, run_list) { -+ /* Make sure cpu affinity is ok */ -+ if (needs_other_cpu(p, cpu)) -+ continue; -+ if (idx < MAX_RT_PRIO) { -+ /* We found an rt task */ -+ edt = p; -+ goto out_take; -+ } -+ -+ dl = p->deadline + cache_distance(task_rq(p), rq, p); -+ -+ /* -+ * No rt tasks. Find the earliest deadline task. Now we're in -+ * O(n) territory. This is what we silenced the compiler for: -+ * edt will always start as idle. -+ */ -+ if (edt == idle || -+ deadline_before(dl, earliest_deadline)) { -+ earliest_deadline = dl; -+ edt = p; -+ } -+ } -+ if (edt == idle) { -+ if (++idx < PRIO_LIMIT) -+ goto retry; -+ goto out; -+ } -+out_take: -+ take_task(rq, edt); -+out: -+ return edt; -+} -+ -+/* -+ * Print scheduling while atomic bug: -+ */ -+static noinline void __schedule_bug(struct task_struct *prev) -+{ -+ struct pt_regs *regs = get_irq_regs(); -+ -+ printk(KERN_ERR "BUG: scheduling while atomic: %s/%d/0x%08x\n", -+ prev->comm, prev->pid, preempt_count()); -+ -+ debug_show_held_locks(prev); -+ print_modules(); -+ if (irqs_disabled()) -+ print_irqtrace_events(prev); -+ -+ if (regs) -+ show_regs(regs); -+ else -+ dump_stack(); -+} -+ -+/* -+ * Various schedule()-time debugging checks and statistics: -+ */ -+static inline void schedule_debug(struct task_struct *prev) -+{ -+ /* -+ * Test if we are atomic. Since do_exit() needs to call into -+ * schedule() atomically, we ignore that path for now. -+ * Otherwise, whine if we are scheduling when we should not be. -+ */ -+ if (unlikely(in_atomic_preempt_off() && !prev->exit_state)) -+ __schedule_bug(prev); -+ -+ profile_hit(SCHED_PROFILING, __builtin_return_address(0)); -+ -+ schedstat_inc(this_rq(), sched_count); -+#ifdef CONFIG_SCHEDSTATS -+ if (unlikely(prev->lock_depth >= 0)) { -+ schedstat_inc(this_rq(), bkl_count); -+ schedstat_inc(prev, sched_info.bkl_count); -+ } -+#endif -+} -+ -+/* -+ * The currently running task's information is all stored in rq local data -+ * which is only modified by the local CPU, thereby allowing the data to be -+ * changed without grabbing the grq lock. -+ */ -+static inline void set_rq_task(struct rq *rq, struct task_struct *p) -+{ -+ rq->rq_time_slice = p->time_slice; -+ rq->rq_deadline = p->deadline; -+ rq->rq_last_ran = p->last_ran; -+ rq->rq_policy = p->policy; -+ rq->rq_prio = p->prio; -+ if (p != rq->idle) -+ rq->rq_running = 1; -+ else -+ rq->rq_running = 0; -+} -+ -+static void reset_rq_task(struct rq *rq, struct task_struct *p) -+{ -+ rq->rq_policy = p->policy; -+ rq->rq_prio = p->prio; -+} -+ -+/* -+ * schedule() is the main scheduler function. -+ */ -+asmlinkage void __sched schedule(void) -+{ -+ struct task_struct *prev, *next, *idle; -+ unsigned long *switch_count; -+ int deactivate, cpu; -+ struct rq *rq; -+ -+need_resched: -+ preempt_disable(); -+ -+ cpu = smp_processor_id(); -+ rq = cpu_rq(cpu); -+ idle = rq->idle; -+ rcu_note_context_switch(cpu); -+ prev = rq->curr; -+ -+ release_kernel_lock(prev); -+need_resched_nonpreemptible: -+ -+ deactivate = 0; -+ schedule_debug(prev); -+ -+ grq_lock_irq(); -+ update_clocks(rq); -+ update_cpu_clock(rq, prev, 0); -+ if (rq->clock - rq->last_tick > HALF_JIFFY_NS) -+ rq->dither = 0; -+ else -+ rq->dither = 1; -+ -+ clear_tsk_need_resched(prev); -+ -+ switch_count = &prev->nivcsw; -+ if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { -+ if (unlikely(signal_pending_state(prev->state, prev))) { -+ prev->state = TASK_RUNNING; -+ } else { -+ deactivate = 1; -+ /* -+ * If a worker is going to sleep, notify and -+ * ask workqueue whether it wants to wake up a -+ * task to maintain concurrency. If so, wake -+ * up the task. -+ */ -+ if (prev->flags & PF_WQ_WORKER) { -+ struct task_struct *to_wakeup; -+ -+ to_wakeup = wq_worker_sleeping(prev, cpu); -+ if (to_wakeup) { -+ /* This shouldn't happen, but does */ -+ if (unlikely(to_wakeup == prev)) -+ deactivate = 0; -+ else -+ try_to_wake_up_local(to_wakeup); -+ } -+ } -+ } -+ switch_count = &prev->nvcsw; -+ } -+ -+ if (prev != idle) { -+ /* Update all the information stored on struct rq */ -+ prev->time_slice = rq->rq_time_slice; -+ prev->deadline = rq->rq_deadline; -+ check_deadline(prev); -+ prev->last_ran = rq->clock; -+ -+ /* Task changed affinity off this CPU */ -+ if (needs_other_cpu(prev, cpu)) -+ resched_suitable_idle(prev); -+ else if (!deactivate) { -+ if (!queued_notrunning()) { -+ /* -+ * We now know prev is the only thing that is -+ * awaiting CPU so we can bypass rechecking for -+ * the earliest deadline task and just run it -+ * again. -+ */ -+ grq_unlock_irq(); -+ goto rerun_prev_unlocked; -+ } else { -+ /* -+ * If prev got kicked off by a task that has to -+ * run on this CPU for affinity reasons then -+ * there may be an idle CPU it can go to. -+ */ -+ resched_suitable_idle(prev); -+ } -+ } -+ return_task(prev, deactivate); -+ } -+ -+ if (unlikely(!queued_notrunning())) { -+ /* -+ * This CPU is now truly idle as opposed to when idle is -+ * scheduled as a high priority task in its own right. -+ */ -+ next = idle; -+ schedstat_inc(rq, sched_goidle); -+ set_cpuidle_map(cpu); -+ } else { -+ next = earliest_deadline_task(rq, idle); -+ prefetch(next); -+ prefetch_stack(next); -+ clear_cpuidle_map(cpu); -+ } -+ -+ if (likely(prev != next)) { -+ sched_info_switch(prev, next); -+ perf_event_task_sched_out(prev, next); -+ -+ set_rq_task(rq, next); -+ grq.nr_switches++; -+ prev->oncpu = 0; -+ next->oncpu = 1; -+ rq->curr = next; -+ ++*switch_count; -+ -+ context_switch(rq, prev, next); /* unlocks the grq */ -+ /* -+ * The context switch have flipped the stack from under us -+ * and restored the local variables which were saved when -+ * this task called schedule() in the past. prev == current -+ * is still correct, but it can be moved to another cpu/rq. -+ */ -+ cpu = smp_processor_id(); -+ rq = cpu_rq(cpu); -+ idle = rq->idle; -+ } else -+ grq_unlock_irq(); -+ -+rerun_prev_unlocked: -+ if (unlikely(reacquire_kernel_lock(prev))) -+ goto need_resched_nonpreemptible; -+ -+ preempt_enable_no_resched(); -+ if (need_resched()) -+ goto need_resched; -+} -+EXPORT_SYMBOL(schedule); -+ -+#ifdef CONFIG_SMP -+int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner) -+{ -+ unsigned int cpu; -+ struct rq *rq; -+ -+#ifdef CONFIG_DEBUG_PAGEALLOC -+ /* -+ * Need to access the cpu field knowing that -+ * DEBUG_PAGEALLOC could have unmapped it if -+ * the mutex owner just released it and exited. -+ */ -+ if (probe_kernel_address(&owner->cpu, cpu)) -+ return 0; -+#else -+ cpu = owner->cpu; -+#endif -+ -+ /* -+ * Even if the access succeeded (likely case), -+ * the cpu field may no longer be valid. -+ */ -+ if (cpu >= nr_cpumask_bits) -+ return 0; -+ -+ /* -+ * We need to validate that we can do a -+ * get_cpu() and that we have the percpu area. -+ */ -+ if (!cpu_online(cpu)) -+ return 0; -+ -+ rq = cpu_rq(cpu); -+ -+ for (;;) { -+ /* -+ * Owner changed, break to re-assess state. -+ */ -+ if (lock->owner != owner) -+ break; -+ -+ /* -+ * Is that owner really running on that cpu? -+ */ -+ if (task_thread_info(rq->curr) != owner || need_resched()) -+ return 0; -+ -+ cpu_relax(); -+ } -+ -+ return 1; -+} -+#endif -+ -+#ifdef CONFIG_PREEMPT -+/* -+ * this is the entry point to schedule() from in-kernel preemption -+ * off of preempt_enable. Kernel preemptions off return from interrupt -+ * occur there and call schedule directly. -+ */ -+asmlinkage void __sched notrace preempt_schedule(void) -+{ -+ struct thread_info *ti = current_thread_info(); -+ -+ /* -+ * If there is a non-zero preempt_count or interrupts are disabled, -+ * we do not want to preempt the current task. Just return.. -+ */ -+ if (likely(ti->preempt_count || irqs_disabled())) -+ return; -+ -+ do { -+ add_preempt_count_notrace(PREEMPT_ACTIVE); -+ schedule(); -+ sub_preempt_count_notrace(PREEMPT_ACTIVE); -+ -+ /* -+ * Check again in case we missed a preemption opportunity -+ * between schedule and now. -+ */ -+ barrier(); -+ } while (need_resched()); -+} -+EXPORT_SYMBOL(preempt_schedule); -+ -+/* -+ * this is the entry point to schedule() from kernel preemption -+ * off of irq context. -+ * Note, that this is called and return with irqs disabled. This will -+ * protect us against recursive calling from irq. -+ */ -+asmlinkage void __sched preempt_schedule_irq(void) -+{ -+ struct thread_info *ti = current_thread_info(); -+ -+ /* Catch callers which need to be fixed */ -+ BUG_ON(ti->preempt_count || !irqs_disabled()); -+ -+ do { -+ add_preempt_count(PREEMPT_ACTIVE); -+ local_irq_enable(); -+ schedule(); -+ local_irq_disable(); -+ sub_preempt_count(PREEMPT_ACTIVE); -+ -+ /* -+ * Check again in case we missed a preemption opportunity -+ * between schedule and now. -+ */ -+ barrier(); -+ } while (need_resched()); -+} -+ -+#endif /* CONFIG_PREEMPT */ -+ -+int default_wake_function(wait_queue_t *curr, unsigned mode, int wake_flags, -+ void *key) -+{ -+ return try_to_wake_up(curr->private, mode, wake_flags); -+} -+EXPORT_SYMBOL(default_wake_function); -+ -+/* -+ * The core wakeup function. Non-exclusive wakeups (nr_exclusive == 0) just -+ * wake everything up. If it's an exclusive wakeup (nr_exclusive == small +ve -+ * number) then we wake all the non-exclusive tasks and one exclusive task. -+ * -+ * There are circumstances in which we can try to wake a task which has already -+ * started to run but is not in state TASK_RUNNING. try_to_wake_up() returns -+ * zero in this (rare) case, and we handle it by continuing to scan the queue. -+ */ -+static void __wake_up_common(wait_queue_head_t *q, unsigned int mode, -+ int nr_exclusive, int wake_flags, void *key) -+{ -+ struct list_head *tmp, *next; -+ -+ list_for_each_safe(tmp, next, &q->task_list) { -+ wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list); -+ unsigned int flags = curr->flags; -+ -+ if (curr->func(curr, mode, wake_flags, key) && -+ (flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive) -+ break; -+ } -+} -+ -+/** -+ * __wake_up - wake up threads blocked on a waitqueue. -+ * @q: the waitqueue -+ * @mode: which threads -+ * @nr_exclusive: how many wake-one or wake-many threads to wake up -+ * @key: is directly passed to the wakeup function -+ * -+ * It may be assumed that this function implies a write memory barrier before -+ * changing the task state if and only if any tasks are woken up. -+ */ -+void __wake_up(wait_queue_head_t *q, unsigned int mode, -+ int nr_exclusive, void *key) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&q->lock, flags); -+ __wake_up_common(q, mode, nr_exclusive, 0, key); -+ spin_unlock_irqrestore(&q->lock, flags); -+} -+EXPORT_SYMBOL(__wake_up); -+ -+/* -+ * Same as __wake_up but called with the spinlock in wait_queue_head_t held. -+ */ -+void __wake_up_locked(wait_queue_head_t *q, unsigned int mode) -+{ -+ __wake_up_common(q, mode, 1, 0, NULL); -+} -+EXPORT_SYMBOL_GPL(__wake_up_locked); -+ -+void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key) -+{ -+ __wake_up_common(q, mode, 1, 0, key); -+} -+ -+/** -+ * __wake_up_sync_key - wake up threads blocked on a waitqueue. -+ * @q: the waitqueue -+ * @mode: which threads -+ * @nr_exclusive: how many wake-one or wake-many threads to wake up -+ * @key: opaque value to be passed to wakeup targets -+ * -+ * The sync wakeup differs that the waker knows that it will schedule -+ * away soon, so while the target thread will be woken up, it will not -+ * be migrated to another CPU - ie. the two threads are 'synchronised' -+ * with each other. This can prevent needless bouncing between CPUs. -+ * -+ * On UP it can prevent extra preemption. -+ * -+ * It may be assumed that this function implies a write memory barrier before -+ * changing the task state if and only if any tasks are woken up. -+ */ -+void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, -+ int nr_exclusive, void *key) -+{ -+ unsigned long flags; -+ int wake_flags = WF_SYNC; -+ -+ if (unlikely(!q)) -+ return; -+ -+ if (unlikely(!nr_exclusive)) -+ wake_flags = 0; -+ -+ spin_lock_irqsave(&q->lock, flags); -+ __wake_up_common(q, mode, nr_exclusive, wake_flags, key); -+ spin_unlock_irqrestore(&q->lock, flags); -+} -+EXPORT_SYMBOL_GPL(__wake_up_sync_key); -+ -+/** -+ * __wake_up_sync - wake up threads blocked on a waitqueue. -+ * @q: the waitqueue -+ * @mode: which threads -+ * @nr_exclusive: how many wake-one or wake-many threads to wake up -+ * -+ * The sync wakeup differs that the waker knows that it will schedule -+ * away soon, so while the target thread will be woken up, it will not -+ * be migrated to another CPU - ie. the two threads are 'synchronised' -+ * with each other. This can prevent needless bouncing between CPUs. -+ * -+ * On UP it can prevent extra preemption. -+ */ -+void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive) -+{ -+ unsigned long flags; -+ int sync = 1; -+ -+ if (unlikely(!q)) -+ return; -+ -+ if (unlikely(!nr_exclusive)) -+ sync = 0; -+ -+ spin_lock_irqsave(&q->lock, flags); -+ __wake_up_common(q, mode, nr_exclusive, sync, NULL); -+ spin_unlock_irqrestore(&q->lock, flags); -+} -+EXPORT_SYMBOL_GPL(__wake_up_sync); /* For internal use only */ -+ -+/** -+ * complete: - signals a single thread waiting on this completion -+ * @x: holds the state of this particular completion -+ * -+ * This will wake up a single thread waiting on this completion. Threads will be -+ * awakened in the same order in which they were queued. -+ * -+ * See also complete_all(), wait_for_completion() and related routines. -+ * -+ * It may be assumed that this function implies a write memory barrier before -+ * changing the task state if and only if any tasks are woken up. -+ */ -+void complete(struct completion *x) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&x->wait.lock, flags); -+ x->done++; -+ __wake_up_common(&x->wait, TASK_NORMAL, 1, 0, NULL); -+ spin_unlock_irqrestore(&x->wait.lock, flags); -+} -+EXPORT_SYMBOL(complete); -+ -+/** -+ * complete_all: - signals all threads waiting on this completion -+ * @x: holds the state of this particular completion -+ * -+ * This will wake up all threads waiting on this particular completion event. -+ * -+ * It may be assumed that this function implies a write memory barrier before -+ * changing the task state if and only if any tasks are woken up. -+ */ -+void complete_all(struct completion *x) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&x->wait.lock, flags); -+ x->done += UINT_MAX/2; -+ __wake_up_common(&x->wait, TASK_NORMAL, 0, 0, NULL); -+ spin_unlock_irqrestore(&x->wait.lock, flags); -+} -+EXPORT_SYMBOL(complete_all); -+ -+static inline long __sched -+do_wait_for_common(struct completion *x, long timeout, int state) -+{ -+ if (!x->done) { -+ DECLARE_WAITQUEUE(wait, current); -+ -+ __add_wait_queue_tail_exclusive(&x->wait, &wait); -+ do { -+ if (signal_pending_state(state, current)) { -+ timeout = -ERESTARTSYS; -+ break; -+ } -+ __set_current_state(state); -+ spin_unlock_irq(&x->wait.lock); -+ timeout = schedule_timeout(timeout); -+ spin_lock_irq(&x->wait.lock); -+ } while (!x->done && timeout); -+ __remove_wait_queue(&x->wait, &wait); -+ if (!x->done) -+ return timeout; -+ } -+ x->done--; -+ return timeout ?: 1; -+} -+ -+static long __sched -+wait_for_common(struct completion *x, long timeout, int state) -+{ -+ might_sleep(); -+ -+ spin_lock_irq(&x->wait.lock); -+ timeout = do_wait_for_common(x, timeout, state); -+ spin_unlock_irq(&x->wait.lock); -+ return timeout; -+} -+ -+/** -+ * wait_for_completion: - waits for completion of a task -+ * @x: holds the state of this particular completion -+ * -+ * This waits to be signaled for completion of a specific task. It is NOT -+ * interruptible and there is no timeout. -+ * -+ * See also similar routines (i.e. wait_for_completion_timeout()) with timeout -+ * and interrupt capability. Also see complete(). -+ */ -+void __sched wait_for_completion(struct completion *x) -+{ -+ wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE); -+} -+EXPORT_SYMBOL(wait_for_completion); -+ -+/** -+ * wait_for_completion_timeout: - waits for completion of a task (w/timeout) -+ * @x: holds the state of this particular completion -+ * @timeout: timeout value in jiffies -+ * -+ * This waits for either a completion of a specific task to be signaled or for a -+ * specified timeout to expire. The timeout is in jiffies. It is not -+ * interruptible. -+ */ -+unsigned long __sched -+wait_for_completion_timeout(struct completion *x, unsigned long timeout) -+{ -+ return wait_for_common(x, timeout, TASK_UNINTERRUPTIBLE); -+} -+EXPORT_SYMBOL(wait_for_completion_timeout); -+ -+/** -+ * wait_for_completion_interruptible: - waits for completion of a task (w/intr) -+ * @x: holds the state of this particular completion -+ * -+ * This waits for completion of a specific task to be signaled. It is -+ * interruptible. -+ */ -+int __sched wait_for_completion_interruptible(struct completion *x) -+{ -+ long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE); -+ if (t == -ERESTARTSYS) -+ return t; -+ return 0; -+} -+EXPORT_SYMBOL(wait_for_completion_interruptible); -+ -+/** -+ * wait_for_completion_interruptible_timeout: - waits for completion (w/(to,intr)) -+ * @x: holds the state of this particular completion -+ * @timeout: timeout value in jiffies -+ * -+ * This waits for either a completion of a specific task to be signaled or for a -+ * specified timeout to expire. It is interruptible. The timeout is in jiffies. -+ */ -+unsigned long __sched -+wait_for_completion_interruptible_timeout(struct completion *x, -+ unsigned long timeout) -+{ -+ return wait_for_common(x, timeout, TASK_INTERRUPTIBLE); -+} -+EXPORT_SYMBOL(wait_for_completion_interruptible_timeout); -+ -+/** -+ * wait_for_completion_killable: - waits for completion of a task (killable) -+ * @x: holds the state of this particular completion -+ * -+ * This waits to be signaled for completion of a specific task. It can be -+ * interrupted by a kill signal. -+ */ -+int __sched wait_for_completion_killable(struct completion *x) -+{ -+ long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_KILLABLE); -+ if (t == -ERESTARTSYS) -+ return t; -+ return 0; -+} -+EXPORT_SYMBOL(wait_for_completion_killable); -+ -+/** -+ * wait_for_completion_killable_timeout: - waits for completion of a task (w/(to,killable)) -+ * @x: holds the state of this particular completion -+ * @timeout: timeout value in jiffies -+ * -+ * This waits for either a completion of a specific task to be -+ * signaled or for a specified timeout to expire. It can be -+ * interrupted by a kill signal. The timeout is in jiffies. -+ */ -+unsigned long __sched -+wait_for_completion_killable_timeout(struct completion *x, -+ unsigned long timeout) -+{ -+ return wait_for_common(x, timeout, TASK_KILLABLE); -+} -+EXPORT_SYMBOL(wait_for_completion_killable_timeout); -+ -+/** -+ * try_wait_for_completion - try to decrement a completion without blocking -+ * @x: completion structure -+ * -+ * Returns: 0 if a decrement cannot be done without blocking -+ * 1 if a decrement succeeded. -+ * -+ * If a completion is being used as a counting completion, -+ * attempt to decrement the counter without blocking. This -+ * enables us to avoid waiting if the resource the completion -+ * is protecting is not available. -+ */ -+bool try_wait_for_completion(struct completion *x) -+{ -+ unsigned long flags; -+ int ret = 1; -+ -+ spin_lock_irqsave(&x->wait.lock, flags); -+ if (!x->done) -+ ret = 0; -+ else -+ x->done--; -+ spin_unlock_irqrestore(&x->wait.lock, flags); -+ return ret; -+} -+EXPORT_SYMBOL(try_wait_for_completion); -+ -+/** -+ * completion_done - Test to see if a completion has any waiters -+ * @x: completion structure -+ * -+ * Returns: 0 if there are waiters (wait_for_completion() in progress) -+ * 1 if there are no waiters. -+ * -+ */ -+bool completion_done(struct completion *x) -+{ -+ unsigned long flags; -+ int ret = 1; -+ -+ spin_lock_irqsave(&x->wait.lock, flags); -+ if (!x->done) -+ ret = 0; -+ spin_unlock_irqrestore(&x->wait.lock, flags); -+ return ret; -+} -+EXPORT_SYMBOL(completion_done); -+ -+static long __sched -+sleep_on_common(wait_queue_head_t *q, int state, long timeout) -+{ -+ unsigned long flags; -+ wait_queue_t wait; -+ -+ init_waitqueue_entry(&wait, current); -+ -+ __set_current_state(state); -+ -+ spin_lock_irqsave(&q->lock, flags); -+ __add_wait_queue(q, &wait); -+ spin_unlock(&q->lock); -+ timeout = schedule_timeout(timeout); -+ spin_lock_irq(&q->lock); -+ __remove_wait_queue(q, &wait); -+ spin_unlock_irqrestore(&q->lock, flags); -+ -+ return timeout; -+} -+ -+void __sched interruptible_sleep_on(wait_queue_head_t *q) -+{ -+ sleep_on_common(q, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); -+} -+EXPORT_SYMBOL(interruptible_sleep_on); -+ -+long __sched -+interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout) -+{ -+ return sleep_on_common(q, TASK_INTERRUPTIBLE, timeout); -+} -+EXPORT_SYMBOL(interruptible_sleep_on_timeout); -+ -+void __sched sleep_on(wait_queue_head_t *q) -+{ -+ sleep_on_common(q, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); -+} -+EXPORT_SYMBOL(sleep_on); -+ -+long __sched sleep_on_timeout(wait_queue_head_t *q, long timeout) -+{ -+ return sleep_on_common(q, TASK_UNINTERRUPTIBLE, timeout); -+} -+EXPORT_SYMBOL(sleep_on_timeout); -+ -+#ifdef CONFIG_RT_MUTEXES -+ -+/* -+ * rt_mutex_setprio - set the current priority of a task -+ * @p: task -+ * @prio: prio value (kernel-internal form) -+ * -+ * This function changes the 'effective' priority of a task. It does -+ * not touch ->normal_prio like __setscheduler(). -+ * -+ * Used by the rt_mutex code to implement priority inheritance logic. -+ */ -+void rt_mutex_setprio(struct task_struct *p, int prio) -+{ -+ unsigned long flags; -+ int queued, oldprio; -+ struct rq *rq; -+ -+ BUG_ON(prio < 0 || prio > MAX_PRIO); -+ -+ rq = task_grq_lock(p, &flags); -+ -+ trace_sched_pi_setprio(p, prio); -+ oldprio = p->prio; -+ queued = task_queued(p); -+ if (queued) -+ dequeue_task(p); -+ p->prio = prio; -+ if (task_running(p) && prio > oldprio) -+ resched_task(p); -+ if (queued) { -+ enqueue_task(p); -+ try_preempt(p, rq); -+ } -+ -+ task_grq_unlock(&flags); -+} -+ -+#endif -+ -+/* -+ * Adjust the deadline for when the priority is to change, before it's -+ * changed. -+ */ -+static inline void adjust_deadline(struct task_struct *p, int new_prio) -+{ -+ p->deadline += static_deadline_diff(new_prio) - task_deadline_diff(p); -+} -+ -+void set_user_nice(struct task_struct *p, long nice) -+{ -+ int queued, new_static, old_static; -+ unsigned long flags; -+ struct rq *rq; -+ -+ if (TASK_NICE(p) == nice || nice < -20 || nice > 19) -+ return; -+ new_static = NICE_TO_PRIO(nice); -+ /* -+ * We have to be careful, if called from sys_setpriority(), -+ * the task might be in the middle of scheduling on another CPU. -+ */ -+ rq = time_task_grq_lock(p, &flags); -+ /* -+ * The RT priorities are set via sched_setscheduler(), but we still -+ * allow the 'normal' nice value to be set - but as expected -+ * it wont have any effect on scheduling until the task is -+ * not SCHED_NORMAL/SCHED_BATCH: -+ */ -+ if (has_rt_policy(p)) { -+ p->static_prio = new_static; -+ goto out_unlock; -+ } -+ queued = task_queued(p); -+ if (queued) -+ dequeue_task(p); -+ -+ adjust_deadline(p, new_static); -+ old_static = p->static_prio; -+ p->static_prio = new_static; -+ p->prio = effective_prio(p); -+ -+ if (queued) { -+ enqueue_task(p); -+ if (new_static < old_static) -+ try_preempt(p, rq); -+ } else if (task_running(p)) { -+ reset_rq_task(rq, p); -+ if (old_static < new_static) -+ resched_task(p); -+ } -+out_unlock: -+ task_grq_unlock(&flags); -+} -+EXPORT_SYMBOL(set_user_nice); -+ -+/* -+ * can_nice - check if a task can reduce its nice value -+ * @p: task -+ * @nice: nice value -+ */ -+int can_nice(const struct task_struct *p, const int nice) -+{ -+ /* convert nice value [19,-20] to rlimit style value [1,40] */ -+ int nice_rlim = 20 - nice; -+ -+ return (nice_rlim <= task_rlimit(p, RLIMIT_NICE) || -+ capable(CAP_SYS_NICE)); -+} -+ -+#ifdef __ARCH_WANT_SYS_NICE -+ -+/* -+ * sys_nice - change the priority of the current process. -+ * @increment: priority increment -+ * -+ * sys_setpriority is a more generic, but much slower function that -+ * does similar things. -+ */ -+SYSCALL_DEFINE1(nice, int, increment) -+{ -+ long nice, retval; -+ -+ /* -+ * Setpriority might change our priority at the same moment. -+ * We don't have to worry. Conceptually one call occurs first -+ * and we have a single winner. -+ */ -+ if (increment < -40) -+ increment = -40; -+ if (increment > 40) -+ increment = 40; -+ -+ nice = TASK_NICE(current) + increment; -+ if (nice < -20) -+ nice = -20; -+ if (nice > 19) -+ nice = 19; -+ -+ if (increment < 0 && !can_nice(current, nice)) -+ return -EPERM; -+ -+ retval = security_task_setnice(current, nice); -+ if (retval) -+ return retval; -+ -+ set_user_nice(current, nice); -+ return 0; -+} -+ -+#endif -+ -+/** -+ * task_prio - return the priority value of a given task. -+ * @p: the task in question. -+ * -+ * This is the priority value as seen by users in /proc. -+ * RT tasks are offset by -100. Normal tasks are centered around 1, value goes -+ * from 0 (SCHED_ISO) up to 82 (nice +19 SCHED_IDLEPRIO). -+ */ -+int task_prio(const struct task_struct *p) -+{ -+ int delta, prio = p->prio - MAX_RT_PRIO; -+ -+ /* rt tasks and iso tasks */ -+ if (prio <= 0) -+ goto out; -+ -+ /* Convert to ms to avoid overflows */ -+ delta = NS_TO_MS(p->deadline - grq.niffies); -+ delta = delta * 40 / ms_longest_deadline_diff(); -+ if (delta > 0 && delta <= 80) -+ prio += delta; -+ if (idleprio_task(p)) -+ prio += 40; -+out: -+ return prio; -+} -+ -+/** -+ * task_nice - return the nice value of a given task. -+ * @p: the task in question. -+ */ -+int task_nice(const struct task_struct *p) -+{ -+ return TASK_NICE(p); -+} -+EXPORT_SYMBOL_GPL(task_nice); -+ -+/** -+ * idle_cpu - is a given cpu idle currently? -+ * @cpu: the processor in question. -+ */ -+int idle_cpu(int cpu) -+{ -+ return cpu_curr(cpu) == cpu_rq(cpu)->idle; -+} -+ -+/** -+ * idle_task - return the idle task for a given cpu. -+ * @cpu: the processor in question. -+ */ -+struct task_struct *idle_task(int cpu) -+{ -+ return cpu_rq(cpu)->idle; -+} -+ -+/** -+ * find_process_by_pid - find a process with a matching PID value. -+ * @pid: the pid in question. -+ */ -+static inline struct task_struct *find_process_by_pid(pid_t pid) -+{ -+ return pid ? find_task_by_vpid(pid) : current; -+} -+ -+/* Actually do priority change: must hold grq lock. */ -+static void -+__setscheduler(struct task_struct *p, struct rq *rq, int policy, int prio) -+{ -+ int oldrtprio, oldprio; -+ -+ BUG_ON(task_queued(p)); -+ -+ p->policy = policy; -+ oldrtprio = p->rt_priority; -+ p->rt_priority = prio; -+ p->normal_prio = normal_prio(p); -+ oldprio = p->prio; -+ /* we are holding p->pi_lock already */ -+ p->prio = rt_mutex_getprio(p); -+ if (task_running(p)) { -+ reset_rq_task(rq, p); -+ /* Resched only if we might now be preempted */ -+ if (p->prio > oldprio || p->rt_priority > oldrtprio) -+ resched_task(p); -+ } -+} -+ -+/* -+ * check the target process has a UID that matches the current process's -+ */ -+static bool check_same_owner(struct task_struct *p) -+{ -+ const struct cred *cred = current_cred(), *pcred; -+ bool match; -+ -+ rcu_read_lock(); -+ pcred = __task_cred(p); -+ match = (cred->euid == pcred->euid || -+ cred->euid == pcred->uid); -+ rcu_read_unlock(); -+ return match; -+} -+ -+static int __sched_setscheduler(struct task_struct *p, int policy, -+ struct sched_param *param, bool user) -+{ -+ struct sched_param zero_param = { .sched_priority = 0 }; -+ int queued, retval, oldpolicy = -1; -+ unsigned long flags, rlim_rtprio = 0; -+ int reset_on_fork; -+ struct rq *rq; -+ -+ /* may grab non-irq protected spin_locks */ -+ BUG_ON(in_interrupt()); -+ -+ if (is_rt_policy(policy) && !capable(CAP_SYS_NICE)) { -+ unsigned long lflags; -+ -+ if (!lock_task_sighand(p, &lflags)) -+ return -ESRCH; -+ rlim_rtprio = task_rlimit(p, RLIMIT_RTPRIO); -+ unlock_task_sighand(p, &lflags); -+ if (rlim_rtprio) -+ goto recheck; -+ /* -+ * If the caller requested an RT policy without having the -+ * necessary rights, we downgrade the policy to SCHED_ISO. -+ * We also set the parameter to zero to pass the checks. -+ */ -+ policy = SCHED_ISO; -+ param = &zero_param; -+ } -+recheck: -+ /* double check policy once rq lock held */ -+ if (policy < 0) { -+ reset_on_fork = p->sched_reset_on_fork; -+ policy = oldpolicy = p->policy; -+ } else { -+ reset_on_fork = !!(policy & SCHED_RESET_ON_FORK); -+ policy &= ~SCHED_RESET_ON_FORK; -+ -+ if (!SCHED_RANGE(policy)) -+ return -EINVAL; -+ } -+ -+ /* -+ * Valid priorities for SCHED_FIFO and SCHED_RR are -+ * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL and -+ * SCHED_BATCH is 0. -+ */ -+ if (param->sched_priority < 0 || -+ (p->mm && param->sched_priority > MAX_USER_RT_PRIO - 1) || -+ (!p->mm && param->sched_priority > MAX_RT_PRIO - 1)) -+ return -EINVAL; -+ if (is_rt_policy(policy) != (param->sched_priority != 0)) -+ return -EINVAL; -+ -+ /* -+ * Allow unprivileged RT tasks to decrease priority: -+ */ -+ if (user && !capable(CAP_SYS_NICE)) { -+ if (is_rt_policy(policy)) { -+ unsigned long rlim_rtprio = -+ task_rlimit(p, RLIMIT_RTPRIO); -+ -+ /* can't set/change the rt policy */ -+ if (policy != p->policy && !rlim_rtprio) -+ return -EPERM; -+ -+ /* can't increase priority */ -+ if (param->sched_priority > p->rt_priority && -+ param->sched_priority > rlim_rtprio) -+ return -EPERM; -+ } else { -+ switch (p->policy) { -+ /* -+ * Can only downgrade policies but not back to -+ * SCHED_NORMAL -+ */ -+ case SCHED_ISO: -+ if (policy == SCHED_ISO) -+ goto out; -+ if (policy == SCHED_NORMAL) -+ return -EPERM; -+ break; -+ case SCHED_BATCH: -+ if (policy == SCHED_BATCH) -+ goto out; -+ if (policy != SCHED_IDLEPRIO) -+ return -EPERM; -+ break; -+ case SCHED_IDLEPRIO: -+ if (policy == SCHED_IDLEPRIO) -+ goto out; -+ return -EPERM; -+ default: -+ break; -+ } -+ } -+ -+ /* can't change other user's priorities */ -+ if (!check_same_owner(p)) -+ return -EPERM; -+ -+ /* Normal users shall not reset the sched_reset_on_fork flag */ -+ if (p->sched_reset_on_fork && !reset_on_fork) -+ return -EPERM; -+ } -+ -+ if (user) { -+ retval = security_task_setscheduler(p); -+ if (retval) -+ return retval; -+ } -+ -+ /* -+ * make sure no PI-waiters arrive (or leave) while we are -+ * changing the priority of the task: -+ */ -+ raw_spin_lock_irqsave(&p->pi_lock, flags); -+ /* -+ * To be able to change p->policy safely, the apropriate -+ * runqueue lock must be held. -+ */ -+ rq = __task_grq_lock(p); -+ -+ /* -+ * Changing the policy of the stop threads its a very bad idea -+ */ -+ if (p == rq->stop) { -+ __task_grq_unlock(); -+ raw_spin_unlock_irqrestore(&p->pi_lock, flags); -+ return -EINVAL; -+ } -+ -+ /* recheck policy now with rq lock held */ -+ if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) { -+ policy = oldpolicy = -1; -+ __task_grq_unlock(); -+ raw_spin_unlock_irqrestore(&p->pi_lock, flags); -+ goto recheck; -+ } -+ update_clocks(rq); -+ p->sched_reset_on_fork = reset_on_fork; -+ -+ queued = task_queued(p); -+ if (queued) -+ dequeue_task(p); -+ __setscheduler(p, rq, policy, param->sched_priority); -+ if (queued) { -+ enqueue_task(p); -+ try_preempt(p, rq); -+ } -+ __task_grq_unlock(); -+ raw_spin_unlock_irqrestore(&p->pi_lock, flags); -+ -+ rt_mutex_adjust_pi(p); -+out: -+ return 0; -+} -+ -+/** -+ * sched_setscheduler - change the scheduling policy and/or RT priority of a thread. -+ * @p: the task in question. -+ * @policy: new policy. -+ * @param: structure containing the new RT priority. -+ * -+ * NOTE that the task may be already dead. -+ */ -+int sched_setscheduler(struct task_struct *p, int policy, -+ struct sched_param *param) -+{ -+ return __sched_setscheduler(p, policy, param, true); -+} -+ -+EXPORT_SYMBOL_GPL(sched_setscheduler); -+ -+/** -+ * sched_setscheduler_nocheck - change the scheduling policy and/or RT priority of a thread from kernelspace. -+ * @p: the task in question. -+ * @policy: new policy. -+ * @param: structure containing the new RT priority. -+ * -+ * Just like sched_setscheduler, only don't bother checking if the -+ * current context has permission. For example, this is needed in -+ * stop_machine(): we create temporary high priority worker threads, -+ * but our caller might not have that capability. -+ */ -+int sched_setscheduler_nocheck(struct task_struct *p, int policy, -+ struct sched_param *param) -+{ -+ return __sched_setscheduler(p, policy, param, false); -+} -+ -+static int -+do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) -+{ -+ struct sched_param lparam; -+ struct task_struct *p; -+ int retval; -+ -+ if (!param || pid < 0) -+ return -EINVAL; -+ if (copy_from_user(&lparam, param, sizeof(struct sched_param))) -+ return -EFAULT; -+ -+ rcu_read_lock(); -+ retval = -ESRCH; -+ p = find_process_by_pid(pid); -+ if (p != NULL) -+ retval = sched_setscheduler(p, policy, &lparam); -+ rcu_read_unlock(); -+ -+ return retval; -+} -+ -+/** -+ * sys_sched_setscheduler - set/change the scheduler policy and RT priority -+ * @pid: the pid in question. -+ * @policy: new policy. -+ * @param: structure containing the new RT priority. -+ */ -+asmlinkage long sys_sched_setscheduler(pid_t pid, int policy, -+ struct sched_param __user *param) -+{ -+ /* negative values for policy are not valid */ -+ if (policy < 0) -+ return -EINVAL; -+ -+ return do_sched_setscheduler(pid, policy, param); -+} -+ -+/** -+ * sys_sched_setparam - set/change the RT priority of a thread -+ * @pid: the pid in question. -+ * @param: structure containing the new RT priority. -+ */ -+SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param) -+{ -+ return do_sched_setscheduler(pid, -1, param); -+} -+ -+/** -+ * sys_sched_getscheduler - get the policy (scheduling class) of a thread -+ * @pid: the pid in question. -+ */ -+SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid) -+{ -+ struct task_struct *p; -+ int retval = -EINVAL; -+ -+ if (pid < 0) -+ goto out_nounlock; -+ -+ retval = -ESRCH; -+ rcu_read_lock(); -+ p = find_process_by_pid(pid); -+ if (p) { -+ retval = security_task_getscheduler(p); -+ if (!retval) -+ retval = p->policy; -+ } -+ rcu_read_unlock(); -+ -+out_nounlock: -+ return retval; -+} -+ -+/** -+ * sys_sched_getscheduler - get the RT priority of a thread -+ * @pid: the pid in question. -+ * @param: structure containing the RT priority. -+ */ -+SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param) -+{ -+ struct sched_param lp; -+ struct task_struct *p; -+ int retval = -EINVAL; -+ -+ if (!param || pid < 0) -+ goto out_nounlock; -+ -+ rcu_read_lock(); -+ p = find_process_by_pid(pid); -+ retval = -ESRCH; -+ if (!p) -+ goto out_unlock; -+ -+ retval = security_task_getscheduler(p); -+ if (retval) -+ goto out_unlock; -+ -+ lp.sched_priority = p->rt_priority; -+ rcu_read_unlock(); -+ -+ /* -+ * This one might sleep, we cannot do it with a spinlock held ... -+ */ -+ retval = copy_to_user(param, &lp, sizeof(*param)) ? -EFAULT : 0; -+ -+out_nounlock: -+ return retval; -+ -+out_unlock: -+ rcu_read_unlock(); -+ return retval; -+} -+ -+long sched_setaffinity(pid_t pid, const struct cpumask *in_mask) -+{ -+ cpumask_var_t cpus_allowed, new_mask; -+ struct task_struct *p; -+ int retval; -+ -+ get_online_cpus(); -+ rcu_read_lock(); -+ -+ p = find_process_by_pid(pid); -+ if (!p) { -+ rcu_read_unlock(); -+ put_online_cpus(); -+ return -ESRCH; -+ } -+ -+ /* Prevent p going away */ -+ get_task_struct(p); -+ rcu_read_unlock(); -+ -+ if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL)) { -+ retval = -ENOMEM; -+ goto out_put_task; -+ } -+ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) { -+ retval = -ENOMEM; -+ goto out_free_cpus_allowed; -+ } -+ retval = -EPERM; -+ if (!check_same_owner(p) && !capable(CAP_SYS_NICE)) -+ goto out_unlock; -+ -+ retval = security_task_setscheduler(p); -+ if (retval) -+ goto out_unlock; -+ -+ cpuset_cpus_allowed(p, cpus_allowed); -+ cpumask_and(new_mask, in_mask, cpus_allowed); -+again: -+ retval = set_cpus_allowed_ptr(p, new_mask); -+ -+ if (!retval) { -+ cpuset_cpus_allowed(p, cpus_allowed); -+ if (!cpumask_subset(new_mask, cpus_allowed)) { -+ /* -+ * We must have raced with a concurrent cpuset -+ * update. Just reset the cpus_allowed to the -+ * cpuset's cpus_allowed -+ */ -+ cpumask_copy(new_mask, cpus_allowed); -+ goto again; -+ } -+ } -+out_unlock: -+ free_cpumask_var(new_mask); -+out_free_cpus_allowed: -+ free_cpumask_var(cpus_allowed); -+out_put_task: -+ put_task_struct(p); -+ put_online_cpus(); -+ return retval; -+} -+ -+static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len, -+ cpumask_t *new_mask) -+{ -+ if (len < sizeof(cpumask_t)) { -+ memset(new_mask, 0, sizeof(cpumask_t)); -+ } else if (len > sizeof(cpumask_t)) { -+ len = sizeof(cpumask_t); -+ } -+ return copy_from_user(new_mask, user_mask_ptr, len) ? -EFAULT : 0; -+} -+ -+ -+/** -+ * sys_sched_setaffinity - set the cpu affinity of a process -+ * @pid: pid of the process -+ * @len: length in bytes of the bitmask pointed to by user_mask_ptr -+ * @user_mask_ptr: user-space pointer to the new cpu mask -+ */ -+SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len, -+ unsigned long __user *, user_mask_ptr) -+{ -+ cpumask_var_t new_mask; -+ int retval; -+ -+ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) -+ return -ENOMEM; -+ -+ retval = get_user_cpu_mask(user_mask_ptr, len, new_mask); -+ if (retval == 0) -+ retval = sched_setaffinity(pid, new_mask); -+ free_cpumask_var(new_mask); -+ return retval; -+} -+ -+long sched_getaffinity(pid_t pid, cpumask_t *mask) -+{ -+ struct task_struct *p; -+ unsigned long flags; -+ struct rq *rq; -+ int retval; -+ -+ get_online_cpus(); -+ rcu_read_lock(); -+ -+ retval = -ESRCH; -+ p = find_process_by_pid(pid); -+ if (!p) -+ goto out_unlock; -+ -+ retval = security_task_getscheduler(p); -+ if (retval) -+ goto out_unlock; -+ -+ rq = task_grq_lock(p, &flags); -+ cpumask_and(mask, &p->cpus_allowed, cpu_online_mask); -+ task_grq_unlock(&flags); -+ -+out_unlock: -+ rcu_read_unlock(); -+ put_online_cpus(); -+ -+ return retval; -+} -+ -+/** -+ * sys_sched_getaffinity - get the cpu affinity of a process -+ * @pid: pid of the process -+ * @len: length in bytes of the bitmask pointed to by user_mask_ptr -+ * @user_mask_ptr: user-space pointer to hold the current cpu mask -+ */ -+SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len, -+ unsigned long __user *, user_mask_ptr) -+{ -+ int ret; -+ cpumask_var_t mask; -+ -+ if ((len * BITS_PER_BYTE) < nr_cpu_ids) -+ return -EINVAL; -+ if (len & (sizeof(unsigned long)-1)) -+ return -EINVAL; -+ -+ if (!alloc_cpumask_var(&mask, GFP_KERNEL)) -+ return -ENOMEM; -+ -+ ret = sched_getaffinity(pid, mask); -+ if (ret == 0) { -+ size_t retlen = min_t(size_t, len, cpumask_size()); -+ -+ if (copy_to_user(user_mask_ptr, mask, retlen)) -+ ret = -EFAULT; -+ else -+ ret = retlen; -+ } -+ free_cpumask_var(mask); -+ -+ return ret; -+} -+ -+/** -+ * sys_sched_yield - yield the current processor to other threads. -+ * -+ * This function yields the current CPU to other tasks. It does this by -+ * scheduling away the current task. If it still has the earliest deadline -+ * it will be scheduled again as the next task. -+ */ -+SYSCALL_DEFINE0(sched_yield) -+{ -+ struct task_struct *p; -+ struct rq *rq; -+ -+ p = current; -+ rq = task_grq_lock_irq(p); -+ schedstat_inc(rq, yld_count); -+ requeue_task(p); -+ -+ /* -+ * Since we are going to call schedule() anyway, there's -+ * no need to preempt or enable interrupts: -+ */ -+ __release(grq.lock); -+ spin_release(&grq.lock.dep_map, 1, _THIS_IP_); -+ do_raw_spin_unlock(&grq.lock); -+ preempt_enable_no_resched(); -+ -+ schedule(); -+ -+ return 0; -+} -+ -+static inline int should_resched(void) -+{ -+ return need_resched() && !(preempt_count() & PREEMPT_ACTIVE); -+} -+ -+static void __cond_resched(void) -+{ -+ /* NOT a real fix but will make voluntary preempt work. 馬鹿な事 */ -+ if (unlikely(system_state != SYSTEM_RUNNING)) -+ return; -+ -+ add_preempt_count(PREEMPT_ACTIVE); -+ schedule(); -+ sub_preempt_count(PREEMPT_ACTIVE); -+} -+ -+int __sched _cond_resched(void) -+{ -+ if (should_resched()) { -+ __cond_resched(); -+ return 1; -+ } -+ return 0; -+} -+EXPORT_SYMBOL(_cond_resched); -+ -+/* -+ * __cond_resched_lock() - if a reschedule is pending, drop the given lock, -+ * call schedule, and on return reacquire the lock. -+ * -+ * This works OK both with and without CONFIG_PREEMPT. We do strange low-level -+ * operations here to prevent schedule() from being called twice (once via -+ * spin_unlock(), once by hand). -+ */ -+int __cond_resched_lock(spinlock_t *lock) -+{ -+ int resched = should_resched(); -+ int ret = 0; -+ -+ lockdep_assert_held(lock); -+ -+ if (spin_needbreak(lock) || resched) { -+ spin_unlock(lock); -+ if (resched) -+ __cond_resched(); -+ else -+ cpu_relax(); -+ ret = 1; -+ spin_lock(lock); -+ } -+ return ret; -+} -+EXPORT_SYMBOL(__cond_resched_lock); -+ -+int __sched __cond_resched_softirq(void) -+{ -+ BUG_ON(!in_softirq()); -+ -+ if (should_resched()) { -+ local_bh_enable(); -+ __cond_resched(); -+ local_bh_disable(); -+ return 1; -+ } -+ return 0; -+} -+EXPORT_SYMBOL(__cond_resched_softirq); -+ -+/** -+ * yield - yield the current processor to other threads. -+ * -+ * This is a shortcut for kernel-space yielding - it marks the -+ * thread runnable and calls sys_sched_yield(). -+ */ -+void __sched yield(void) -+{ -+ set_current_state(TASK_RUNNING); -+ sys_sched_yield(); -+} -+EXPORT_SYMBOL(yield); -+ -+/* -+ * This task is about to go to sleep on IO. Increment rq->nr_iowait so -+ * that process accounting knows that this is a task in IO wait state. -+ * -+ * But don't do that if it is a deliberate, throttling IO wait (this task -+ * has set its backing_dev_info: the queue against which it should throttle) -+ */ -+void __sched io_schedule(void) -+{ -+ struct rq *rq = raw_rq(); -+ -+ delayacct_blkio_start(); -+ atomic_inc(&rq->nr_iowait); -+ current->in_iowait = 1; -+ schedule(); -+ current->in_iowait = 0; -+ atomic_dec(&rq->nr_iowait); -+ delayacct_blkio_end(); -+} -+EXPORT_SYMBOL(io_schedule); -+ -+long __sched io_schedule_timeout(long timeout) -+{ -+ struct rq *rq = raw_rq(); -+ long ret; -+ -+ delayacct_blkio_start(); -+ atomic_inc(&rq->nr_iowait); -+ current->in_iowait = 1; -+ ret = schedule_timeout(timeout); -+ current->in_iowait = 0; -+ atomic_dec(&rq->nr_iowait); -+ delayacct_blkio_end(); -+ return ret; -+} -+ -+/** -+ * sys_sched_get_priority_max - return maximum RT priority. -+ * @policy: scheduling class. -+ * -+ * this syscall returns the maximum rt_priority that can be used -+ * by a given scheduling class. -+ */ -+SYSCALL_DEFINE1(sched_get_priority_max, int, policy) -+{ -+ int ret = -EINVAL; -+ -+ switch (policy) { -+ case SCHED_FIFO: -+ case SCHED_RR: -+ ret = MAX_USER_RT_PRIO-1; -+ break; -+ case SCHED_NORMAL: -+ case SCHED_BATCH: -+ case SCHED_ISO: -+ case SCHED_IDLEPRIO: -+ ret = 0; -+ break; -+ } -+ return ret; -+} -+ -+/** -+ * sys_sched_get_priority_min - return minimum RT priority. -+ * @policy: scheduling class. -+ * -+ * this syscall returns the minimum rt_priority that can be used -+ * by a given scheduling class. -+ */ -+SYSCALL_DEFINE1(sched_get_priority_min, int, policy) -+{ -+ int ret = -EINVAL; -+ -+ switch (policy) { -+ case SCHED_FIFO: -+ case SCHED_RR: -+ ret = 1; -+ break; -+ case SCHED_NORMAL: -+ case SCHED_BATCH: -+ case SCHED_ISO: -+ case SCHED_IDLEPRIO: -+ ret = 0; -+ break; -+ } -+ return ret; -+} -+ -+/** -+ * sys_sched_rr_get_interval - return the default timeslice of a process. -+ * @pid: pid of the process. -+ * @interval: userspace pointer to the timeslice value. -+ * -+ * this syscall writes the default timeslice value of a given process -+ * into the user-space timespec buffer. A value of '0' means infinity. -+ */ -+SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, -+ struct timespec __user *, interval) -+{ -+ struct task_struct *p; -+ unsigned int time_slice; -+ unsigned long flags; -+ struct rq *rq; -+ int retval; -+ struct timespec t; -+ -+ if (pid < 0) -+ return -EINVAL; -+ -+ retval = -ESRCH; -+ rcu_read_lock(); -+ p = find_process_by_pid(pid); -+ if (!p) -+ goto out_unlock; -+ -+ retval = security_task_getscheduler(p); -+ if (retval) -+ goto out_unlock; -+ -+ rq = task_grq_lock(p, &flags); -+ time_slice = p->policy == SCHED_FIFO ? 0 : MS_TO_NS(task_timeslice(p)); -+ task_grq_unlock(&flags); -+ -+ rcu_read_unlock(); -+ t = ns_to_timespec(time_slice); -+ retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0; -+ return retval; -+ -+out_unlock: -+ rcu_read_unlock(); -+ return retval; -+} -+ -+static const char stat_nam[] = TASK_STATE_TO_CHAR_STR; -+ -+void sched_show_task(struct task_struct *p) -+{ -+ unsigned long free = 0; -+ unsigned state; -+ -+ state = p->state ? __ffs(p->state) + 1 : 0; -+ printk(KERN_INFO "%-13.13s %c", p->comm, -+ state < sizeof(stat_nam) - 1 ? stat_nam[state] : '?'); -+#if BITS_PER_LONG == 32 -+ if (state == TASK_RUNNING) -+ printk(KERN_CONT " running "); -+ else -+ printk(KERN_CONT " %08lx ", thread_saved_pc(p)); -+#else -+ if (state == TASK_RUNNING) -+ printk(KERN_CONT " running task "); -+ else -+ printk(KERN_CONT " %016lx ", thread_saved_pc(p)); -+#endif -+#ifdef CONFIG_DEBUG_STACK_USAGE -+ free = stack_not_used(p); -+#endif -+ printk(KERN_CONT "%5lu %5d %6d 0x%08lx\n", free, -+ task_pid_nr(p), task_pid_nr(p->real_parent), -+ (unsigned long)task_thread_info(p)->flags); -+ -+ show_stack(p, NULL); -+} -+ -+void show_state_filter(unsigned long state_filter) -+{ -+ struct task_struct *g, *p; -+ -+#if BITS_PER_LONG == 32 -+ printk(KERN_INFO -+ " task PC stack pid father\n"); -+#else -+ printk(KERN_INFO -+ " task PC stack pid father\n"); -+#endif -+ read_lock(&tasklist_lock); -+ do_each_thread(g, p) { -+ /* -+ * reset the NMI-timeout, listing all files on a slow -+ * console might take alot of time: -+ */ -+ touch_nmi_watchdog(); -+ if (!state_filter || (p->state & state_filter)) -+ sched_show_task(p); -+ } while_each_thread(g, p); -+ -+ touch_all_softlockup_watchdogs(); -+ -+ read_unlock(&tasklist_lock); -+ /* -+ * Only show locks if all tasks are dumped: -+ */ -+ if (!state_filter) -+ debug_show_all_locks(); -+} -+ -+/** -+ * init_idle - set up an idle thread for a given CPU -+ * @idle: task in question -+ * @cpu: cpu the idle task belongs to -+ * -+ * NOTE: this function does not set the idle thread's NEED_RESCHED -+ * flag, to make booting more robust. -+ */ -+void init_idle(struct task_struct *idle, int cpu) -+{ -+ struct rq *rq = cpu_rq(cpu); -+ unsigned long flags; -+ -+ time_grq_lock(rq, &flags); -+ idle->last_ran = rq->clock; -+ idle->state = TASK_RUNNING; -+ /* Setting prio to illegal value shouldn't matter when never queued */ -+ idle->prio = PRIO_LIMIT; -+ set_rq_task(rq, idle); -+ idle->cpus_allowed = cpumask_of_cpu(cpu); -+ /* Silence PROVE_RCU */ -+ rcu_read_lock(); -+ set_task_cpu(idle, cpu); -+ rcu_read_unlock(); -+ rq->curr = rq->idle = idle; -+ idle->oncpu = 1; -+ set_cpuidle_map(cpu); -+ grq_unlock_irqrestore(&flags); -+ -+ /* Set the preempt count _outside_ the spinlocks! */ -+#if defined(CONFIG_PREEMPT) && !defined(CONFIG_PREEMPT_BKL) -+ task_thread_info(idle)->preempt_count = (idle->lock_depth >= 0); -+#else -+ task_thread_info(idle)->preempt_count = 0; -+#endif -+ ftrace_graph_init_task(idle); -+} -+ -+/* -+ * In a system that switches off the HZ timer nohz_cpu_mask -+ * indicates which cpus entered this state. This is used -+ * in the rcu update to wait only for active cpus. For system -+ * which do not switch off the HZ timer nohz_cpu_mask should -+ * always be CPU_BITS_NONE. -+ */ -+cpumask_var_t nohz_cpu_mask; -+ -+#ifdef CONFIG_SMP -+#ifdef CONFIG_NO_HZ -+void select_nohz_load_balancer(int stop_tick) -+{ -+} -+#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) -+/** -+ * lowest_flag_domain - Return lowest sched_domain containing flag. -+ * @cpu: The cpu whose lowest level of sched domain is to -+ * be returned. -+ * @flag: The flag to check for the lowest sched_domain -+ * for the given cpu. -+ * -+ * Returns the lowest sched_domain of a cpu which contains the given flag. -+ */ -+static inline struct sched_domain *lowest_flag_domain(int cpu, int flag) -+{ -+ struct sched_domain *sd; -+ -+ for_each_domain(cpu, sd) -+ if (sd && (sd->flags & flag)) -+ break; -+ -+ return sd; -+} -+ -+/** -+ * for_each_flag_domain - Iterates over sched_domains containing the flag. -+ * @cpu: The cpu whose domains we're iterating over. -+ * @sd: variable holding the value of the power_savings_sd -+ * for cpu. -+ * @flag: The flag to filter the sched_domains to be iterated. -+ * -+ * Iterates over all the scheduler domains for a given cpu that has the 'flag' -+ * set, starting from the lowest sched_domain to the highest. -+ */ -+#define for_each_flag_domain(cpu, sd, flag) \ -+ for (sd = lowest_flag_domain(cpu, flag); \ -+ (sd && (sd->flags & flag)); sd = sd->parent) -+ -+#endif /* (CONFIG_SCHED_MC || CONFIG_SCHED_SMT) */ -+ -+static inline void resched_cpu(int cpu) -+{ -+ unsigned long flags; -+ -+ grq_lock_irqsave(&flags); -+ resched_task(cpu_curr(cpu)); -+ grq_unlock_irqrestore(&flags); -+} -+ -+/* -+ * In the semi idle case, use the nearest busy cpu for migrating timers -+ * from an idle cpu. This is good for power-savings. -+ * -+ * We don't do similar optimization for completely idle system, as -+ * selecting an idle cpu will add more delays to the timers than intended -+ * (as that cpu's timer base may not be uptodate wrt jiffies etc). -+ */ -+int get_nohz_timer_target(void) -+{ -+ int cpu = smp_processor_id(); -+ int i; -+ struct sched_domain *sd; -+ -+ for_each_domain(cpu, sd) { -+ for_each_cpu(i, sched_domain_span(sd)) -+ if (!idle_cpu(i)) -+ return i; -+ } -+ return cpu; -+} -+ -+/* -+ * When add_timer_on() enqueues a timer into the timer wheel of an -+ * idle CPU then this timer might expire before the next timer event -+ * which is scheduled to wake up that CPU. In case of a completely -+ * idle system the next event might even be infinite time into the -+ * future. wake_up_idle_cpu() ensures that the CPU is woken up and -+ * leaves the inner idle loop so the newly added timer is taken into -+ * account when the CPU goes back to idle and evaluates the timer -+ * wheel for the next timer event. -+ */ -+void wake_up_idle_cpu(int cpu) -+{ -+ struct task_struct *idle; -+ struct rq *rq; -+ -+ if (cpu == smp_processor_id()) -+ return; -+ -+ rq = cpu_rq(cpu); -+ idle = rq->idle; -+ -+ /* -+ * This is safe, as this function is called with the timer -+ * wheel base lock of (cpu) held. When the CPU is on the way -+ * to idle and has not yet set rq->curr to idle then it will -+ * be serialised on the timer wheel base lock and take the new -+ * timer into account automatically. -+ */ -+ if (unlikely(rq->curr != idle)) -+ return; -+ -+ /* -+ * We can set TIF_RESCHED on the idle task of the other CPU -+ * lockless. The worst case is that the other CPU runs the -+ * idle task through an additional NOOP schedule() -+ */ -+ set_tsk_need_resched(idle); -+ -+ /* NEED_RESCHED must be visible before we test polling */ -+ smp_mb(); -+ if (!tsk_is_polling(idle)) -+ smp_send_reschedule(cpu); -+} -+ -+#endif /* CONFIG_NO_HZ */ -+ -+/* -+ * Change a given task's CPU affinity. Migrate the thread to a -+ * proper CPU and schedule it away if the CPU it's executing on -+ * is removed from the allowed bitmask. -+ * -+ * NOTE: the caller must have a valid reference to the task, the -+ * task must not exit() & deallocate itself prematurely. The -+ * call is not atomic; no spinlocks may be held. -+ */ -+int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask) -+{ -+ unsigned long flags; -+ int running_wrong = 0; -+ int queued = 0; -+ struct rq *rq; -+ int ret = 0; -+ -+ rq = task_grq_lock(p, &flags); -+ -+ if (!cpumask_intersects(new_mask, cpu_active_mask)) { -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ if (unlikely((p->flags & PF_THREAD_BOUND) && p != current && -+ !cpumask_equal(&p->cpus_allowed, new_mask))) { -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ queued = task_queued(p); -+ -+ cpumask_copy(&p->cpus_allowed, new_mask); -+ -+ /* Can the task run on the task's current CPU? If so, we're done */ -+ if (cpumask_test_cpu(task_cpu(p), new_mask)) -+ goto out; -+ -+ if (task_running(p)) { -+ /* Task is running on the wrong cpu now, reschedule it. */ -+ if (rq == this_rq()) { -+ set_tsk_need_resched(p); -+ running_wrong = 1; -+ } else -+ resched_task(p); -+ } else -+ set_task_cpu(p, cpumask_any_and(cpu_active_mask, new_mask)); -+ -+out: -+ if (queued) -+ try_preempt(p, rq); -+ task_grq_unlock(&flags); -+ -+ if (running_wrong) -+ _cond_resched(); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(set_cpus_allowed_ptr); -+ -+#ifdef CONFIG_HOTPLUG_CPU -+/* -+ * Reschedule a task if it's on a dead CPU. -+ */ -+void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p) -+{ -+ unsigned long flags; -+ struct rq *rq, *dead_rq; -+ -+ dead_rq = cpu_rq(dead_cpu); -+ rq = task_grq_lock(p, &flags); -+ if (rq == dead_rq && task_running(p)) -+ resched_task(p); -+ task_grq_unlock(&flags); -+ -+} -+ -+/* Run through task list and find tasks affined to just the dead cpu, then -+ * allocate a new affinity */ -+static void break_sole_affinity(int src_cpu) -+{ -+ struct task_struct *p, *t; -+ -+ do_each_thread(t, p) { -+ if (!online_cpus(p)) { -+ cpumask_copy(&p->cpus_allowed, cpu_possible_mask); -+ /* -+ * Don't tell them about moving exiting tasks or -+ * kernel threads (both mm NULL), since they never -+ * leave kernel. -+ */ -+ if (p->mm && printk_ratelimit()) { -+ printk(KERN_INFO "process %d (%s) no " -+ "longer affine to cpu %d\n", -+ task_pid_nr(p), p->comm, src_cpu); -+ } -+ } -+ } while_each_thread(t, p); -+} -+ -+/* -+ * Schedules idle task to be the next runnable task on current CPU. -+ * It does so by boosting its priority to highest possible. -+ * Used by CPU offline code. -+ */ -+void sched_idle_next(void) -+{ -+ int this_cpu = smp_processor_id(); -+ struct rq *rq = cpu_rq(this_cpu); -+ struct task_struct *idle = rq->idle; -+ unsigned long flags; -+ -+ /* cpu has to be offline */ -+ BUG_ON(cpu_online(this_cpu)); -+ -+ /* -+ * Strictly not necessary since rest of the CPUs are stopped by now -+ * and interrupts disabled on the current cpu. -+ */ -+ grq_lock_irqsave(&flags); -+ break_sole_affinity(this_cpu); -+ -+ __setscheduler(idle, rq, SCHED_FIFO, STOP_PRIO); -+ -+ activate_idle_task(idle); -+ set_tsk_need_resched(rq->curr); -+ -+ grq_unlock_irqrestore(&flags); -+} -+ -+void sched_set_stop_task(int cpu, struct task_struct *stop) -+{ -+ struct sched_param stop_param = { .sched_priority = STOP_PRIO }; -+ struct sched_param start_param = { .sched_priority = MAX_USER_RT_PRIO - 1 }; -+ struct task_struct *old_stop = cpu_rq(cpu)->stop; -+ -+ if (stop) { -+ /* -+ * Make it appear like a SCHED_FIFO task, its something -+ * userspace knows about and won't get confused about. -+ * -+ * Also, it will make PI more or less work without too -+ * much confusion -- but then, stop work should not -+ * rely on PI working anyway. -+ */ -+ sched_setscheduler_nocheck(stop, SCHED_FIFO, &stop_param); -+ } -+ -+ cpu_rq(cpu)->stop = stop; -+ -+ if (old_stop) { -+ /* -+ * Reset it back to a normal rt scheduling prio so that -+ * it can die in pieces. -+ */ -+ sched_setscheduler_nocheck(old_stop, SCHED_FIFO, &start_param); -+ } -+} -+ -+/* -+ * Ensures that the idle task is using init_mm right before its cpu goes -+ * offline. -+ */ -+void idle_task_exit(void) -+{ -+ struct mm_struct *mm = current->active_mm; -+ -+ BUG_ON(cpu_online(smp_processor_id())); -+ -+ if (mm != &init_mm) -+ switch_mm(mm, &init_mm, current); -+ mmdrop(mm); -+} -+ -+#endif /* CONFIG_HOTPLUG_CPU */ -+ -+#if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL) -+ -+static struct ctl_table sd_ctl_dir[] = { -+ { -+ .procname = "sched_domain", -+ .mode = 0555, -+ }, -+ {} -+}; -+ -+static struct ctl_table sd_ctl_root[] = { -+ { -+ .procname = "kernel", -+ .mode = 0555, -+ .child = sd_ctl_dir, -+ }, -+ {} -+}; -+ -+static struct ctl_table *sd_alloc_ctl_entry(int n) -+{ -+ struct ctl_table *entry = -+ kcalloc(n, sizeof(struct ctl_table), GFP_KERNEL); -+ -+ return entry; -+} -+ -+static void sd_free_ctl_entry(struct ctl_table **tablep) -+{ -+ struct ctl_table *entry; -+ -+ /* -+ * In the intermediate directories, both the child directory and -+ * procname are dynamically allocated and could fail but the mode -+ * will always be set. In the lowest directory the names are -+ * static strings and all have proc handlers. -+ */ -+ for (entry = *tablep; entry->mode; entry++) { -+ if (entry->child) -+ sd_free_ctl_entry(&entry->child); -+ if (entry->proc_handler == NULL) -+ kfree(entry->procname); -+ } -+ -+ kfree(*tablep); -+ *tablep = NULL; -+} -+ -+static void -+set_table_entry(struct ctl_table *entry, -+ const char *procname, void *data, int maxlen, -+ mode_t mode, proc_handler *proc_handler) -+{ -+ entry->procname = procname; -+ entry->data = data; -+ entry->maxlen = maxlen; -+ entry->mode = mode; -+ entry->proc_handler = proc_handler; -+} -+ -+static struct ctl_table * -+sd_alloc_ctl_domain_table(struct sched_domain *sd) -+{ -+ struct ctl_table *table = sd_alloc_ctl_entry(13); -+ -+ if (table == NULL) -+ return NULL; -+ -+ set_table_entry(&table[0], "min_interval", &sd->min_interval, -+ sizeof(long), 0644, proc_doulongvec_minmax); -+ set_table_entry(&table[1], "max_interval", &sd->max_interval, -+ sizeof(long), 0644, proc_doulongvec_minmax); -+ set_table_entry(&table[2], "busy_idx", &sd->busy_idx, -+ sizeof(int), 0644, proc_dointvec_minmax); -+ set_table_entry(&table[3], "idle_idx", &sd->idle_idx, -+ sizeof(int), 0644, proc_dointvec_minmax); -+ set_table_entry(&table[4], "newidle_idx", &sd->newidle_idx, -+ sizeof(int), 0644, proc_dointvec_minmax); -+ set_table_entry(&table[5], "wake_idx", &sd->wake_idx, -+ sizeof(int), 0644, proc_dointvec_minmax); -+ set_table_entry(&table[6], "forkexec_idx", &sd->forkexec_idx, -+ sizeof(int), 0644, proc_dointvec_minmax); -+ set_table_entry(&table[7], "busy_factor", &sd->busy_factor, -+ sizeof(int), 0644, proc_dointvec_minmax); -+ set_table_entry(&table[8], "imbalance_pct", &sd->imbalance_pct, -+ sizeof(int), 0644, proc_dointvec_minmax); -+ set_table_entry(&table[9], "cache_nice_tries", -+ &sd->cache_nice_tries, -+ sizeof(int), 0644, proc_dointvec_minmax); -+ set_table_entry(&table[10], "flags", &sd->flags, -+ sizeof(int), 0644, proc_dointvec_minmax); -+ set_table_entry(&table[11], "name", sd->name, -+ CORENAME_MAX_SIZE, 0444, proc_dostring); -+ /* &table[12] is terminator */ -+ -+ return table; -+} -+ -+static ctl_table *sd_alloc_ctl_cpu_table(int cpu) -+{ -+ struct ctl_table *entry, *table; -+ struct sched_domain *sd; -+ int domain_num = 0, i; -+ char buf[32]; -+ -+ for_each_domain(cpu, sd) -+ domain_num++; -+ entry = table = sd_alloc_ctl_entry(domain_num + 1); -+ if (table == NULL) -+ return NULL; -+ -+ i = 0; -+ for_each_domain(cpu, sd) { -+ snprintf(buf, 32, "domain%d", i); -+ entry->procname = kstrdup(buf, GFP_KERNEL); -+ entry->mode = 0555; -+ entry->child = sd_alloc_ctl_domain_table(sd); -+ entry++; -+ i++; -+ } -+ return table; -+} -+ -+static struct ctl_table_header *sd_sysctl_header; -+static void register_sched_domain_sysctl(void) -+{ -+ int i, cpu_num = num_possible_cpus(); -+ struct ctl_table *entry = sd_alloc_ctl_entry(cpu_num + 1); -+ char buf[32]; -+ -+ WARN_ON(sd_ctl_dir[0].child); -+ sd_ctl_dir[0].child = entry; -+ -+ if (entry == NULL) -+ return; -+ -+ for_each_possible_cpu(i) { -+ snprintf(buf, 32, "cpu%d", i); -+ entry->procname = kstrdup(buf, GFP_KERNEL); -+ entry->mode = 0555; -+ entry->child = sd_alloc_ctl_cpu_table(i); -+ entry++; -+ } -+ -+ WARN_ON(sd_sysctl_header); -+ sd_sysctl_header = register_sysctl_table(sd_ctl_root); -+} -+ -+/* may be called multiple times per register */ -+static void unregister_sched_domain_sysctl(void) -+{ -+ if (sd_sysctl_header) -+ unregister_sysctl_table(sd_sysctl_header); -+ sd_sysctl_header = NULL; -+ if (sd_ctl_dir[0].child) -+ sd_free_ctl_entry(&sd_ctl_dir[0].child); -+} -+#else -+static void register_sched_domain_sysctl(void) -+{ -+} -+static void unregister_sched_domain_sysctl(void) -+{ -+} -+#endif -+ -+static void set_rq_online(struct rq *rq) -+{ -+ if (!rq->online) { -+ cpumask_set_cpu(cpu_of(rq), rq->rd->online); -+ rq->online = 1; -+ } -+} -+ -+static void set_rq_offline(struct rq *rq) -+{ -+ if (rq->online) { -+ cpumask_clear_cpu(cpu_of(rq), rq->rd->online); -+ rq->online = 0; -+ } -+} -+ -+/* -+ * migration_call - callback that gets triggered when a CPU is added. -+ */ -+static int __cpuinit -+migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) -+{ -+#ifdef CONFIG_HOTPLUG_CPU -+ struct task_struct *idle; -+#endif -+ int cpu = (long)hcpu; -+ unsigned long flags; -+ struct rq *rq = cpu_rq(cpu); -+ -+ switch (action) { -+ -+ case CPU_UP_PREPARE: -+ case CPU_UP_PREPARE_FROZEN: -+ break; -+ -+ case CPU_ONLINE: -+ case CPU_ONLINE_FROZEN: -+ /* Update our root-domain */ -+ grq_lock_irqsave(&flags); -+ if (rq->rd) { -+ BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); -+ -+ set_rq_online(rq); -+ } -+ grq_unlock_irqrestore(&flags); -+ break; -+ -+#ifdef CONFIG_HOTPLUG_CPU -+ case CPU_DEAD: -+ case CPU_DEAD_FROZEN: -+ idle = rq->idle; -+ /* Idle task back to normal (off runqueue, low prio) */ -+ grq_lock_irq(); -+ return_task(idle, 1); -+ idle->static_prio = MAX_PRIO; -+ __setscheduler(idle, rq, SCHED_NORMAL, 0); -+ idle->prio = PRIO_LIMIT; -+ set_rq_task(rq, idle); -+ update_clocks(rq); -+ grq_unlock_irq(); -+ break; -+ -+ case CPU_DYING: -+ case CPU_DYING_FROZEN: -+ /* Update our root-domain */ -+ grq_lock_irqsave(&flags); -+ if (rq->rd) { -+ BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); -+ set_rq_offline(rq); -+ } -+ grq_unlock_irqrestore(&flags); -+ break; -+#endif -+ } -+ return NOTIFY_OK; -+} -+ -+/* -+ * Register at high priority so that task migration (migrate_all_tasks) -+ * happens before everything else. This has to be lower priority than -+ * the notifier in the perf_counter subsystem, though. -+ */ -+static struct notifier_block __cpuinitdata migration_notifier = { -+ .notifier_call = migration_call, -+ .priority = CPU_PRI_MIGRATION, -+}; -+ -+static int __cpuinit sched_cpu_active(struct notifier_block *nfb, -+ unsigned long action, void *hcpu) -+{ -+ switch (action & ~CPU_TASKS_FROZEN) { -+ case CPU_ONLINE: -+ case CPU_DOWN_FAILED: -+ set_cpu_active((long)hcpu, true); -+ return NOTIFY_OK; -+ default: -+ return NOTIFY_DONE; -+ } -+} -+ -+static int __cpuinit sched_cpu_inactive(struct notifier_block *nfb, -+ unsigned long action, void *hcpu) -+{ -+ switch (action & ~CPU_TASKS_FROZEN) { -+ case CPU_DOWN_PREPARE: -+ set_cpu_active((long)hcpu, false); -+ return NOTIFY_OK; -+ default: -+ return NOTIFY_DONE; -+ } -+} -+ -+int __init migration_init(void) -+{ -+ void *cpu = (void *)(long)smp_processor_id(); -+ int err; -+ -+ /* Initialise migration for the boot CPU */ -+ err = migration_call(&migration_notifier, CPU_UP_PREPARE, cpu); -+ BUG_ON(err == NOTIFY_BAD); -+ migration_call(&migration_notifier, CPU_ONLINE, cpu); -+ register_cpu_notifier(&migration_notifier); -+ -+ /* Register cpu active notifiers */ -+ cpu_notifier(sched_cpu_active, CPU_PRI_SCHED_ACTIVE); -+ cpu_notifier(sched_cpu_inactive, CPU_PRI_SCHED_INACTIVE); -+ -+ return 0; -+} -+early_initcall(migration_init); -+#endif -+ -+#ifdef CONFIG_SMP -+ -+#ifdef CONFIG_SCHED_DEBUG -+ -+static __read_mostly int sched_domain_debug_enabled; -+ -+static int __init sched_domain_debug_setup(char *str) -+{ -+ sched_domain_debug_enabled = 1; -+ -+ return 0; -+} -+early_param("sched_debug", sched_domain_debug_setup); -+ -+static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level, -+ struct cpumask *groupmask) -+{ -+ struct sched_group *group = sd->groups; -+ char str[256]; -+ -+ cpulist_scnprintf(str, sizeof(str), sched_domain_span(sd)); -+ cpumask_clear(groupmask); -+ -+ printk(KERN_DEBUG "%*s domain %d: ", level, "", level); -+ -+ if (!(sd->flags & SD_LOAD_BALANCE)) { -+ printk("does not load-balance\n"); -+ if (sd->parent) -+ printk(KERN_ERR "ERROR: !SD_LOAD_BALANCE domain" -+ " has parent"); -+ return -1; -+ } -+ -+ printk(KERN_CONT "span %s level %s\n", str, sd->name); -+ -+ if (!cpumask_test_cpu(cpu, sched_domain_span(sd))) { -+ printk(KERN_ERR "ERROR: domain->span does not contain " -+ "CPU%d\n", cpu); -+ } -+ if (!cpumask_test_cpu(cpu, sched_group_cpus(group))) { -+ printk(KERN_ERR "ERROR: domain->groups does not contain" -+ " CPU%d\n", cpu); -+ } -+ -+ printk(KERN_DEBUG "%*s groups:", level + 1, ""); -+ do { -+ if (!group) { -+ printk("\n"); -+ printk(KERN_ERR "ERROR: group is NULL\n"); -+ break; -+ } -+ -+ if (!group->cpu_power) { -+ printk(KERN_CONT "\n"); -+ printk(KERN_ERR "ERROR: domain->cpu_power not " -+ "set\n"); -+ break; -+ } -+ -+ if (!cpumask_weight(sched_group_cpus(group))) { -+ printk(KERN_CONT "\n"); -+ printk(KERN_ERR "ERROR: empty group\n"); -+ break; -+ } -+ -+ if (cpumask_intersects(groupmask, sched_group_cpus(group))) { -+ printk(KERN_CONT "\n"); -+ printk(KERN_ERR "ERROR: repeated CPUs\n"); -+ break; -+ } -+ -+ cpumask_or(groupmask, groupmask, sched_group_cpus(group)); -+ -+ cpulist_scnprintf(str, sizeof(str), sched_group_cpus(group)); -+ -+ printk(KERN_CONT " %s", str); -+ if (group->cpu_power != SCHED_LOAD_SCALE) { -+ printk(KERN_CONT " (cpu_power = %d)", -+ group->cpu_power); -+ } -+ -+ group = group->next; -+ } while (group != sd->groups); -+ printk(KERN_CONT "\n"); -+ -+ if (!cpumask_equal(sched_domain_span(sd), groupmask)) -+ printk(KERN_ERR "ERROR: groups don't span domain->span\n"); -+ -+ if (sd->parent && -+ !cpumask_subset(groupmask, sched_domain_span(sd->parent))) -+ printk(KERN_ERR "ERROR: parent span is not a superset " -+ "of domain->span\n"); -+ return 0; -+} -+ -+static void sched_domain_debug(struct sched_domain *sd, int cpu) -+{ -+ cpumask_var_t groupmask; -+ int level = 0; -+ -+ if (!sched_domain_debug_enabled) -+ return; -+ -+ if (!sd) { -+ printk(KERN_DEBUG "CPU%d attaching NULL sched-domain.\n", cpu); -+ return; -+ } -+ -+ printk(KERN_DEBUG "CPU%d attaching sched-domain:\n", cpu); -+ -+ if (!alloc_cpumask_var(&groupmask, GFP_KERNEL)) { -+ printk(KERN_DEBUG "Cannot load-balance (out of memory)\n"); -+ return; -+ } -+ -+ for (;;) { -+ if (sched_domain_debug_one(sd, cpu, level, groupmask)) -+ break; -+ level++; -+ sd = sd->parent; -+ if (!sd) -+ break; -+ } -+ free_cpumask_var(groupmask); -+} -+#else /* !CONFIG_SCHED_DEBUG */ -+# define sched_domain_debug(sd, cpu) do { } while (0) -+#endif /* CONFIG_SCHED_DEBUG */ -+ -+static int sd_degenerate(struct sched_domain *sd) -+{ -+ if (cpumask_weight(sched_domain_span(sd)) == 1) -+ return 1; -+ -+ /* Following flags need at least 2 groups */ -+ if (sd->flags & (SD_LOAD_BALANCE | -+ SD_BALANCE_NEWIDLE | -+ SD_BALANCE_FORK | -+ SD_BALANCE_EXEC | -+ SD_SHARE_CPUPOWER | -+ SD_SHARE_PKG_RESOURCES)) { -+ if (sd->groups != sd->groups->next) -+ return 0; -+ } -+ -+ /* Following flags don't use groups */ -+ if (sd->flags & (SD_WAKE_AFFINE)) -+ return 0; -+ -+ return 1; -+} -+ -+static int -+sd_parent_degenerate(struct sched_domain *sd, struct sched_domain *parent) -+{ -+ unsigned long cflags = sd->flags, pflags = parent->flags; -+ -+ if (sd_degenerate(parent)) -+ return 1; -+ -+ if (!cpumask_equal(sched_domain_span(sd), sched_domain_span(parent))) -+ return 0; -+ -+ /* Flags needing groups don't count if only 1 group in parent */ -+ if (parent->groups == parent->groups->next) { -+ pflags &= ~(SD_LOAD_BALANCE | -+ SD_BALANCE_NEWIDLE | -+ SD_BALANCE_FORK | -+ SD_BALANCE_EXEC | -+ SD_SHARE_CPUPOWER | -+ SD_SHARE_PKG_RESOURCES); -+ if (nr_node_ids == 1) -+ pflags &= ~SD_SERIALIZE; -+ } -+ if (~cflags & pflags) -+ return 0; -+ -+ return 1; -+} -+ -+static void free_rootdomain(struct root_domain *rd) -+{ -+ synchronize_sched(); -+ -+ free_cpumask_var(rd->rto_mask); -+ free_cpumask_var(rd->online); -+ free_cpumask_var(rd->span); -+ kfree(rd); -+} -+ -+static void rq_attach_root(struct rq *rq, struct root_domain *rd) -+{ -+ struct root_domain *old_rd = NULL; -+ unsigned long flags; -+ -+ grq_lock_irqsave(&flags); -+ -+ if (rq->rd) { -+ old_rd = rq->rd; -+ -+ if (cpumask_test_cpu(cpu_of(rq), old_rd->online)) -+ set_rq_offline(rq); -+ -+ cpumask_clear_cpu(cpu_of(rq), old_rd->span); -+ -+ /* -+ * If we dont want to free the old_rt yet then -+ * set old_rd to NULL to skip the freeing later -+ * in this function: -+ */ -+ if (!atomic_dec_and_test(&old_rd->refcount)) -+ old_rd = NULL; -+ } -+ -+ atomic_inc(&rd->refcount); -+ rq->rd = rd; -+ -+ cpumask_set_cpu(cpu_of(rq), rd->span); -+ if (cpumask_test_cpu(rq->cpu, cpu_active_mask)) -+ set_rq_online(rq); -+ -+ grq_unlock_irqrestore(&flags); -+ -+ if (old_rd) -+ free_rootdomain(old_rd); -+} -+ -+static int init_rootdomain(struct root_domain *rd) -+{ -+ memset(rd, 0, sizeof(*rd)); -+ -+ if (!alloc_cpumask_var(&rd->span, GFP_KERNEL)) -+ goto out; -+ if (!alloc_cpumask_var(&rd->online, GFP_KERNEL)) -+ goto free_span; -+ if (!alloc_cpumask_var(&rd->rto_mask, GFP_KERNEL)) -+ goto free_online; -+ -+ if (cpupri_init(&rd->cpupri) != 0) -+ goto free_rto_mask; -+ return 0; -+ -+free_rto_mask: -+ free_cpumask_var(rd->rto_mask); -+free_online: -+ free_cpumask_var(rd->online); -+free_span: -+ free_cpumask_var(rd->span); -+out: -+ return -ENOMEM; -+} -+ -+static void init_defrootdomain(void) -+{ -+ init_rootdomain(&def_root_domain); -+ -+ atomic_set(&def_root_domain.refcount, 1); -+} -+ -+static struct root_domain *alloc_rootdomain(void) -+{ -+ struct root_domain *rd; -+ -+ rd = kmalloc(sizeof(*rd), GFP_KERNEL); -+ if (!rd) -+ return NULL; -+ -+ if (init_rootdomain(rd) != 0) { -+ kfree(rd); -+ return NULL; -+ } -+ -+ return rd; -+} -+ -+/* -+ * Attach the domain 'sd' to 'cpu' as its base domain. Callers must -+ * hold the hotplug lock. -+ */ -+static void -+cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu) -+{ -+ struct rq *rq = cpu_rq(cpu); -+ struct sched_domain *tmp; -+ -+ for (tmp = sd; tmp; tmp = tmp->parent) -+ tmp->span_weight = cpumask_weight(sched_domain_span(tmp)); -+ -+ /* Remove the sched domains which do not contribute to scheduling. */ -+ for (tmp = sd; tmp; ) { -+ struct sched_domain *parent = tmp->parent; -+ if (!parent) -+ break; -+ -+ if (sd_parent_degenerate(tmp, parent)) { -+ tmp->parent = parent->parent; -+ if (parent->parent) -+ parent->parent->child = tmp; -+ } else -+ tmp = tmp->parent; -+ } -+ -+ if (sd && sd_degenerate(sd)) { -+ sd = sd->parent; -+ if (sd) -+ sd->child = NULL; -+ } -+ -+ sched_domain_debug(sd, cpu); -+ -+ rq_attach_root(rq, rd); -+ rcu_assign_pointer(rq->sd, sd); -+} -+ -+/* cpus with isolated domains */ -+static cpumask_var_t cpu_isolated_map; -+ -+/* Setup the mask of cpus configured for isolated domains */ -+static int __init isolated_cpu_setup(char *str) -+{ -+ alloc_bootmem_cpumask_var(&cpu_isolated_map); -+ cpulist_parse(str, cpu_isolated_map); -+ return 1; -+} -+ -+__setup("isolcpus=", isolated_cpu_setup); -+ -+/* -+ * init_sched_build_groups takes the cpumask we wish to span, and a pointer -+ * to a function which identifies what group(along with sched group) a CPU -+ * belongs to. The return value of group_fn must be a >= 0 and < nr_cpu_ids -+ * (due to the fact that we keep track of groups covered with a struct cpumask). -+ * -+ * init_sched_build_groups will build a circular linked list of the groups -+ * covered by the given span, and will set each group's ->cpumask correctly, -+ * and ->cpu_power to 0. -+ */ -+static void -+init_sched_build_groups(const struct cpumask *span, -+ const struct cpumask *cpu_map, -+ int (*group_fn)(int cpu, const struct cpumask *cpu_map, -+ struct sched_group **sg, -+ struct cpumask *tmpmask), -+ struct cpumask *covered, struct cpumask *tmpmask) -+{ -+ struct sched_group *first = NULL, *last = NULL; -+ int i; -+ -+ cpumask_clear(covered); -+ -+ for_each_cpu(i, span) { -+ struct sched_group *sg; -+ int group = group_fn(i, cpu_map, &sg, tmpmask); -+ int j; -+ -+ if (cpumask_test_cpu(i, covered)) -+ continue; -+ -+ cpumask_clear(sched_group_cpus(sg)); -+ sg->cpu_power = 0; -+ -+ for_each_cpu(j, span) { -+ if (group_fn(j, cpu_map, NULL, tmpmask) != group) -+ continue; -+ -+ cpumask_set_cpu(j, covered); -+ cpumask_set_cpu(j, sched_group_cpus(sg)); -+ } -+ if (!first) -+ first = sg; -+ if (last) -+ last->next = sg; -+ last = sg; -+ } -+ last->next = first; -+} -+ -+#define SD_NODES_PER_DOMAIN 16 -+ -+#ifdef CONFIG_NUMA -+ -+/** -+ * find_next_best_node - find the next node to include in a sched_domain -+ * @node: node whose sched_domain we're building -+ * @used_nodes: nodes already in the sched_domain -+ * -+ * Find the next node to include in a given scheduling domain. Simply -+ * finds the closest node not already in the @used_nodes map. -+ * -+ * Should use nodemask_t. -+ */ -+static int find_next_best_node(int node, nodemask_t *used_nodes) -+{ -+ int i, n, val, min_val, best_node = 0; -+ -+ min_val = INT_MAX; -+ -+ for (i = 0; i < nr_node_ids; i++) { -+ /* Start at @node */ -+ n = (node + i) % nr_node_ids; -+ -+ if (!nr_cpus_node(n)) -+ continue; -+ -+ /* Skip already used nodes */ -+ if (node_isset(n, *used_nodes)) -+ continue; -+ -+ /* Simple min distance search */ -+ val = node_distance(node, n); -+ -+ if (val < min_val) { -+ min_val = val; -+ best_node = n; -+ } -+ } -+ -+ node_set(best_node, *used_nodes); -+ return best_node; -+} -+ -+/** -+ * sched_domain_node_span - get a cpumask for a node's sched_domain -+ * @node: node whose cpumask we're constructing -+ * @span: resulting cpumask -+ * -+ * Given a node, construct a good cpumask for its sched_domain to span. It -+ * should be one that prevents unnecessary balancing, but also spreads tasks -+ * out optimally. -+ */ -+static void sched_domain_node_span(int node, struct cpumask *span) -+{ -+ nodemask_t used_nodes; -+ int i; -+ -+ cpumask_clear(span); -+ nodes_clear(used_nodes); -+ -+ cpumask_or(span, span, cpumask_of_node(node)); -+ node_set(node, used_nodes); -+ -+ for (i = 1; i < SD_NODES_PER_DOMAIN; i++) { -+ int next_node = find_next_best_node(node, &used_nodes); -+ -+ cpumask_or(span, span, cpumask_of_node(next_node)); -+ } -+} -+#endif /* CONFIG_NUMA */ -+ -+int sched_smt_power_savings = 0, sched_mc_power_savings = 0; -+ -+/* -+ * The cpus mask in sched_group and sched_domain hangs off the end. -+ * -+ * ( See the the comments in include/linux/sched.h:struct sched_group -+ * and struct sched_domain. ) -+ */ -+struct static_sched_group { -+ struct sched_group sg; -+ DECLARE_BITMAP(cpus, CONFIG_NR_CPUS); -+}; -+ -+struct static_sched_domain { -+ struct sched_domain sd; -+ DECLARE_BITMAP(span, CONFIG_NR_CPUS); -+}; -+ -+struct s_data { -+#ifdef CONFIG_NUMA -+ int sd_allnodes; -+ cpumask_var_t domainspan; -+ cpumask_var_t covered; -+ cpumask_var_t notcovered; -+#endif -+ cpumask_var_t nodemask; -+ cpumask_var_t this_sibling_map; -+ cpumask_var_t this_core_map; -+ cpumask_var_t this_book_map; -+ cpumask_var_t send_covered; -+ cpumask_var_t tmpmask; -+ struct sched_group **sched_group_nodes; -+ struct root_domain *rd; -+}; -+ -+enum s_alloc { -+ sa_sched_groups = 0, -+ sa_rootdomain, -+ sa_tmpmask, -+ sa_send_covered, -+ sa_this_book_map, -+ sa_this_core_map, -+ sa_this_sibling_map, -+ sa_nodemask, -+ sa_sched_group_nodes, -+#ifdef CONFIG_NUMA -+ sa_notcovered, -+ sa_covered, -+ sa_domainspan, -+#endif -+ sa_none, -+}; -+ -+/* -+ * SMT sched-domains: -+ */ -+#ifdef CONFIG_SCHED_SMT -+static DEFINE_PER_CPU(struct static_sched_domain, cpu_domains); -+static DEFINE_PER_CPU(struct static_sched_group, sched_groups); -+ -+static int -+cpu_to_cpu_group(int cpu, const struct cpumask *cpu_map, -+ struct sched_group **sg, struct cpumask *unused) -+{ -+ if (sg) -+ *sg = &per_cpu(sched_groups, cpu).sg; -+ return cpu; -+} -+#endif /* CONFIG_SCHED_SMT */ -+ -+/* -+ * multi-core sched-domains: -+ */ -+#ifdef CONFIG_SCHED_MC -+static DEFINE_PER_CPU(struct static_sched_domain, core_domains); -+static DEFINE_PER_CPU(struct static_sched_group, sched_group_core); -+ -+static int -+cpu_to_core_group(int cpu, const struct cpumask *cpu_map, -+ struct sched_group **sg, struct cpumask *mask) -+{ -+ int group; -+#ifdef CONFIG_SCHED_SMT -+ cpumask_and(mask, topology_thread_cpumask(cpu), cpu_map); -+ group = cpumask_first(mask); -+#else -+ group = cpu; -+#endif -+ if (sg) -+ *sg = &per_cpu(sched_group_core, group).sg; -+ return group; -+} -+#endif /* CONFIG_SCHED_MC */ -+ -+/* -+ * book sched-domains: -+ */ -+#ifdef CONFIG_SCHED_BOOK -+static DEFINE_PER_CPU(struct static_sched_domain, book_domains); -+static DEFINE_PER_CPU(struct static_sched_group, sched_group_book); -+ -+static int -+cpu_to_book_group(int cpu, const struct cpumask *cpu_map, -+ struct sched_group **sg, struct cpumask *mask) -+{ -+ int group = cpu; -+#ifdef CONFIG_SCHED_MC -+ cpumask_and(mask, cpu_coregroup_mask(cpu), cpu_map); -+ group = cpumask_first(mask); -+#elif defined(CONFIG_SCHED_SMT) -+ cpumask_and(mask, topology_thread_cpumask(cpu), cpu_map); -+ group = cpumask_first(mask); -+#endif -+ if (sg) -+ *sg = &per_cpu(sched_group_book, group).sg; -+ return group; -+} -+#endif /* CONFIG_SCHED_BOOK */ -+ -+static DEFINE_PER_CPU(struct static_sched_domain, phys_domains); -+static DEFINE_PER_CPU(struct static_sched_group, sched_group_phys); -+ -+static int -+cpu_to_phys_group(int cpu, const struct cpumask *cpu_map, -+ struct sched_group **sg, struct cpumask *mask) -+{ -+ int group; -+#ifdef CONFIG_SCHED_BOOK -+ cpumask_and(mask, cpu_book_mask(cpu), cpu_map); -+ group = cpumask_first(mask); -+#elif defined(CONFIG_SCHED_MC) -+ cpumask_and(mask, cpu_coregroup_mask(cpu), cpu_map); -+ group = cpumask_first(mask); -+#elif defined(CONFIG_SCHED_SMT) -+ cpumask_and(mask, topology_thread_cpumask(cpu), cpu_map); -+ group = cpumask_first(mask); -+#else -+ group = cpu; -+#endif -+ if (sg) -+ *sg = &per_cpu(sched_group_phys, group).sg; -+ return group; -+} -+ -+/** -+ * group_first_cpu - Returns the first cpu in the cpumask of a sched_group. -+ * @group: The group whose first cpu is to be returned. -+ */ -+static inline unsigned int group_first_cpu(struct sched_group *group) -+{ -+ return cpumask_first(sched_group_cpus(group)); -+} -+ -+#ifdef CONFIG_NUMA -+/* -+ * The init_sched_build_groups can't handle what we want to do with node -+ * groups, so roll our own. Now each node has its own list of groups which -+ * gets dynamically allocated. -+ */ -+static DEFINE_PER_CPU(struct static_sched_domain, node_domains); -+static struct sched_group ***sched_group_nodes_bycpu; -+ -+static DEFINE_PER_CPU(struct static_sched_domain, allnodes_domains); -+static DEFINE_PER_CPU(struct static_sched_group, sched_group_allnodes); -+ -+static int cpu_to_allnodes_group(int cpu, const struct cpumask *cpu_map, -+ struct sched_group **sg, -+ struct cpumask *nodemask) -+{ -+ int group; -+ -+ cpumask_and(nodemask, cpumask_of_node(cpu_to_node(cpu)), cpu_map); -+ group = cpumask_first(nodemask); -+ -+ if (sg) -+ *sg = &per_cpu(sched_group_allnodes, group).sg; -+ return group; -+} -+ -+static void init_numa_sched_groups_power(struct sched_group *group_head) -+{ -+ struct sched_group *sg = group_head; -+ int j; -+ -+ if (!sg) -+ return; -+ do { -+ for_each_cpu(j, sched_group_cpus(sg)) { -+ struct sched_domain *sd; -+ -+ sd = &per_cpu(phys_domains, j).sd; -+ if (j != group_first_cpu(sd->groups)) { -+ /* -+ * Only add "power" once for each -+ * physical package. -+ */ -+ continue; -+ } -+ -+ sg->cpu_power += sd->groups->cpu_power; -+ } -+ sg = sg->next; -+ } while (sg != group_head); -+} -+ -+static int build_numa_sched_groups(struct s_data *d, -+ const struct cpumask *cpu_map, int num) -+{ -+ struct sched_domain *sd; -+ struct sched_group *sg, *prev; -+ int n, j; -+ -+ cpumask_clear(d->covered); -+ cpumask_and(d->nodemask, cpumask_of_node(num), cpu_map); -+ if (cpumask_empty(d->nodemask)) { -+ d->sched_group_nodes[num] = NULL; -+ goto out; -+ } -+ -+ sched_domain_node_span(num, d->domainspan); -+ cpumask_and(d->domainspan, d->domainspan, cpu_map); -+ -+ sg = kmalloc_node(sizeof(struct sched_group) + cpumask_size(), -+ GFP_KERNEL, num); -+ if (!sg) { -+ printk(KERN_WARNING "Can not alloc domain group for node %d\n", -+ num); -+ return -ENOMEM; -+ } -+ d->sched_group_nodes[num] = sg; -+ -+ for_each_cpu(j, d->nodemask) { -+ sd = &per_cpu(node_domains, j).sd; -+ sd->groups = sg; -+ } -+ -+ sg->cpu_power = 0; -+ cpumask_copy(sched_group_cpus(sg), d->nodemask); -+ sg->next = sg; -+ cpumask_or(d->covered, d->covered, d->nodemask); -+ -+ prev = sg; -+ for (j = 0; j < nr_node_ids; j++) { -+ n = (num + j) % nr_node_ids; -+ cpumask_complement(d->notcovered, d->covered); -+ cpumask_and(d->tmpmask, d->notcovered, cpu_map); -+ cpumask_and(d->tmpmask, d->tmpmask, d->domainspan); -+ if (cpumask_empty(d->tmpmask)) -+ break; -+ cpumask_and(d->tmpmask, d->tmpmask, cpumask_of_node(n)); -+ if (cpumask_empty(d->tmpmask)) -+ continue; -+ sg = kmalloc_node(sizeof(struct sched_group) + cpumask_size(), -+ GFP_KERNEL, num); -+ if (!sg) { -+ printk(KERN_WARNING -+ "Can not alloc domain group for node %d\n", j); -+ return -ENOMEM; -+ } -+ sg->cpu_power = 0; -+ cpumask_copy(sched_group_cpus(sg), d->tmpmask); -+ sg->next = prev->next; -+ cpumask_or(d->covered, d->covered, d->tmpmask); -+ prev->next = sg; -+ prev = sg; -+ } -+out: -+ return 0; -+} -+#endif /* CONFIG_NUMA */ -+ -+#ifdef CONFIG_NUMA -+/* Free memory allocated for various sched_group structures */ -+static void free_sched_groups(const struct cpumask *cpu_map, -+ struct cpumask *nodemask) -+{ -+ int cpu, i; -+ -+ for_each_cpu(cpu, cpu_map) { -+ struct sched_group **sched_group_nodes -+ = sched_group_nodes_bycpu[cpu]; -+ -+ if (!sched_group_nodes) -+ continue; -+ -+ for (i = 0; i < nr_node_ids; i++) { -+ struct sched_group *oldsg, *sg = sched_group_nodes[i]; -+ -+ cpumask_and(nodemask, cpumask_of_node(i), cpu_map); -+ if (cpumask_empty(nodemask)) -+ continue; -+ -+ if (sg == NULL) -+ continue; -+ sg = sg->next; -+next_sg: -+ oldsg = sg; -+ sg = sg->next; -+ kfree(oldsg); -+ if (oldsg != sched_group_nodes[i]) -+ goto next_sg; -+ } -+ kfree(sched_group_nodes); -+ sched_group_nodes_bycpu[cpu] = NULL; -+ } -+} -+#else /* !CONFIG_NUMA */ -+static void free_sched_groups(const struct cpumask *cpu_map, -+ struct cpumask *nodemask) -+{ -+} -+#endif /* CONFIG_NUMA */ -+ -+/* -+ * Initialise sched groups cpu_power. -+ * -+ * cpu_power indicates the capacity of sched group, which is used while -+ * distributing the load between different sched groups in a sched domain. -+ * Typically cpu_power for all the groups in a sched domain will be same unless -+ * there are asymmetries in the topology. If there are asymmetries, group -+ * having more cpu_power will pickup more load compared to the group having -+ * less cpu_power. -+ * -+ * cpu_power will be a multiple of SCHED_LOAD_SCALE. This multiple represents -+ * the maximum number of tasks a group can handle in the presence of other idle -+ * or lightly loaded groups in the same sched domain. -+ */ -+static void init_sched_groups_power(int cpu, struct sched_domain *sd) -+{ -+ struct sched_domain *child; -+ struct sched_group *group; -+ long power; -+ int weight; -+ -+ WARN_ON(!sd || !sd->groups); -+ -+ if (cpu != group_first_cpu(sd->groups)) -+ return; -+ -+ sd->groups->group_weight = cpumask_weight(sched_group_cpus(sd->groups)); -+ -+ child = sd->child; -+ -+ sd->groups->cpu_power = 0; -+ -+ if (!child) { -+ power = SCHED_LOAD_SCALE; -+ weight = cpumask_weight(sched_domain_span(sd)); -+ /* -+ * SMT siblings share the power of a single core. -+ * Usually multiple threads get a better yield out of -+ * that one core than a single thread would have, -+ * reflect that in sd->smt_gain. -+ */ -+ if ((sd->flags & SD_SHARE_CPUPOWER) && weight > 1) { -+ power *= sd->smt_gain; -+ power /= weight; -+ power >>= SCHED_LOAD_SHIFT; -+ } -+ sd->groups->cpu_power += power; -+ return; -+ } -+ -+ /* -+ * Add cpu_power of each child group to this groups cpu_power -+ */ -+ group = child->groups; -+ do { -+ sd->groups->cpu_power += group->cpu_power; -+ group = group->next; -+ } while (group != child->groups); -+} -+ -+/* -+ * Initialisers for schedule domains -+ * Non-inlined to reduce accumulated stack pressure in build_sched_domains() -+ */ -+ -+#ifdef CONFIG_SCHED_DEBUG -+# define SD_INIT_NAME(sd, type) sd->name = #type -+#else -+# define SD_INIT_NAME(sd, type) do { } while (0) -+#endif -+ -+#define SD_INIT(sd, type) sd_init_##type(sd) -+ -+#define SD_INIT_FUNC(type) \ -+static noinline void sd_init_##type(struct sched_domain *sd) \ -+{ \ -+ memset(sd, 0, sizeof(*sd)); \ -+ *sd = SD_##type##_INIT; \ -+ sd->level = SD_LV_##type; \ -+ SD_INIT_NAME(sd, type); \ -+} -+ -+SD_INIT_FUNC(CPU) -+#ifdef CONFIG_NUMA -+ SD_INIT_FUNC(ALLNODES) -+ SD_INIT_FUNC(NODE) -+#endif -+#ifdef CONFIG_SCHED_SMT -+ SD_INIT_FUNC(SIBLING) -+#endif -+#ifdef CONFIG_SCHED_MC -+ SD_INIT_FUNC(MC) -+#endif -+#ifdef CONFIG_SCHED_BOOK -+ SD_INIT_FUNC(BOOK) -+#endif -+ -+static int default_relax_domain_level = -1; -+ -+static int __init setup_relax_domain_level(char *str) -+{ -+ unsigned long val; -+ -+ val = simple_strtoul(str, NULL, 0); -+ if (val < SD_LV_MAX) -+ default_relax_domain_level = val; -+ -+ return 1; -+} -+__setup("relax_domain_level=", setup_relax_domain_level); -+ -+static void set_domain_attribute(struct sched_domain *sd, -+ struct sched_domain_attr *attr) -+{ -+ int request; -+ -+ if (!attr || attr->relax_domain_level < 0) { -+ if (default_relax_domain_level < 0) -+ return; -+ else -+ request = default_relax_domain_level; -+ } else -+ request = attr->relax_domain_level; -+ if (request < sd->level) { -+ /* turn off idle balance on this domain */ -+ sd->flags &= ~(SD_BALANCE_WAKE|SD_BALANCE_NEWIDLE); -+ } else { -+ /* turn on idle balance on this domain */ -+ sd->flags |= (SD_BALANCE_WAKE|SD_BALANCE_NEWIDLE); -+ } -+} -+ -+static void __free_domain_allocs(struct s_data *d, enum s_alloc what, -+ const struct cpumask *cpu_map) -+{ -+ switch (what) { -+ case sa_sched_groups: -+ free_sched_groups(cpu_map, d->tmpmask); /* fall through */ -+ d->sched_group_nodes = NULL; -+ case sa_rootdomain: -+ free_rootdomain(d->rd); /* fall through */ -+ case sa_tmpmask: -+ free_cpumask_var(d->tmpmask); /* fall through */ -+ case sa_send_covered: -+ free_cpumask_var(d->send_covered); /* fall through */ -+ case sa_this_book_map: -+ free_cpumask_var(d->this_book_map); /* fall through */ -+ case sa_this_core_map: -+ free_cpumask_var(d->this_core_map); /* fall through */ -+ case sa_this_sibling_map: -+ free_cpumask_var(d->this_sibling_map); /* fall through */ -+ case sa_nodemask: -+ free_cpumask_var(d->nodemask); /* fall through */ -+ case sa_sched_group_nodes: -+#ifdef CONFIG_NUMA -+ kfree(d->sched_group_nodes); /* fall through */ -+ case sa_notcovered: -+ free_cpumask_var(d->notcovered); /* fall through */ -+ case sa_covered: -+ free_cpumask_var(d->covered); /* fall through */ -+ case sa_domainspan: -+ free_cpumask_var(d->domainspan); /* fall through */ -+#endif -+ case sa_none: -+ break; -+ } -+} -+ -+static enum s_alloc __visit_domain_allocation_hell(struct s_data *d, -+ const struct cpumask *cpu_map) -+{ -+#ifdef CONFIG_NUMA -+ if (!alloc_cpumask_var(&d->domainspan, GFP_KERNEL)) -+ return sa_none; -+ if (!alloc_cpumask_var(&d->covered, GFP_KERNEL)) -+ return sa_domainspan; -+ if (!alloc_cpumask_var(&d->notcovered, GFP_KERNEL)) -+ return sa_covered; -+ /* Allocate the per-node list of sched groups */ -+ d->sched_group_nodes = kcalloc(nr_node_ids, -+ sizeof(struct sched_group *), GFP_KERNEL); -+ if (!d->sched_group_nodes) { -+ printk(KERN_WARNING "Can not alloc sched group node list\n"); -+ return sa_notcovered; -+ } -+ sched_group_nodes_bycpu[cpumask_first(cpu_map)] = d->sched_group_nodes; -+#endif -+ if (!alloc_cpumask_var(&d->nodemask, GFP_KERNEL)) -+ return sa_sched_group_nodes; -+ if (!alloc_cpumask_var(&d->this_sibling_map, GFP_KERNEL)) -+ return sa_nodemask; -+ if (!alloc_cpumask_var(&d->this_core_map, GFP_KERNEL)) -+ return sa_this_sibling_map; -+ if (!alloc_cpumask_var(&d->this_book_map, GFP_KERNEL)) -+ return sa_this_core_map; -+ if (!alloc_cpumask_var(&d->send_covered, GFP_KERNEL)) -+ return sa_this_book_map; -+ if (!alloc_cpumask_var(&d->tmpmask, GFP_KERNEL)) -+ return sa_send_covered; -+ d->rd = alloc_rootdomain(); -+ if (!d->rd) { -+ printk(KERN_WARNING "Cannot alloc root domain\n"); -+ return sa_tmpmask; -+ } -+ return sa_rootdomain; -+} -+ -+static struct sched_domain *__build_numa_sched_domains(struct s_data *d, -+ const struct cpumask *cpu_map, struct sched_domain_attr *attr, int i) -+{ -+ struct sched_domain *sd = NULL; -+#ifdef CONFIG_NUMA -+ struct sched_domain *parent; -+ -+ d->sd_allnodes = 0; -+ if (cpumask_weight(cpu_map) > -+ SD_NODES_PER_DOMAIN * cpumask_weight(d->nodemask)) { -+ sd = &per_cpu(allnodes_domains, i).sd; -+ SD_INIT(sd, ALLNODES); -+ set_domain_attribute(sd, attr); -+ cpumask_copy(sched_domain_span(sd), cpu_map); -+ cpu_to_allnodes_group(i, cpu_map, &sd->groups, d->tmpmask); -+ d->sd_allnodes = 1; -+ } -+ parent = sd; -+ -+ sd = &per_cpu(node_domains, i).sd; -+ SD_INIT(sd, NODE); -+ set_domain_attribute(sd, attr); -+ sched_domain_node_span(cpu_to_node(i), sched_domain_span(sd)); -+ sd->parent = parent; -+ if (parent) -+ parent->child = sd; -+ cpumask_and(sched_domain_span(sd), sched_domain_span(sd), cpu_map); -+#endif -+ return sd; -+} -+ -+static struct sched_domain *__build_cpu_sched_domain(struct s_data *d, -+ const struct cpumask *cpu_map, struct sched_domain_attr *attr, -+ struct sched_domain *parent, int i) -+{ -+ struct sched_domain *sd; -+ sd = &per_cpu(phys_domains, i).sd; -+ SD_INIT(sd, CPU); -+ set_domain_attribute(sd, attr); -+ cpumask_copy(sched_domain_span(sd), d->nodemask); -+ sd->parent = parent; -+ if (parent) -+ parent->child = sd; -+ cpu_to_phys_group(i, cpu_map, &sd->groups, d->tmpmask); -+ return sd; -+} -+ -+static struct sched_domain *__build_book_sched_domain(struct s_data *d, -+ const struct cpumask *cpu_map, struct sched_domain_attr *attr, -+ struct sched_domain *parent, int i) -+{ -+ struct sched_domain *sd = parent; -+#ifdef CONFIG_SCHED_BOOK -+ sd = &per_cpu(book_domains, i).sd; -+ SD_INIT(sd, BOOK); -+ set_domain_attribute(sd, attr); -+ cpumask_and(sched_domain_span(sd), cpu_map, cpu_book_mask(i)); -+ sd->parent = parent; -+ parent->child = sd; -+ cpu_to_book_group(i, cpu_map, &sd->groups, d->tmpmask); -+#endif -+ return sd; -+} -+ -+static struct sched_domain *__build_mc_sched_domain(struct s_data *d, -+ const struct cpumask *cpu_map, struct sched_domain_attr *attr, -+ struct sched_domain *parent, int i) -+{ -+ struct sched_domain *sd = parent; -+#ifdef CONFIG_SCHED_MC -+ sd = &per_cpu(core_domains, i).sd; -+ SD_INIT(sd, MC); -+ set_domain_attribute(sd, attr); -+ cpumask_and(sched_domain_span(sd), cpu_map, cpu_coregroup_mask(i)); -+ sd->parent = parent; -+ parent->child = sd; -+ cpu_to_core_group(i, cpu_map, &sd->groups, d->tmpmask); -+#endif -+ return sd; -+} -+ -+static struct sched_domain *__build_smt_sched_domain(struct s_data *d, -+ const struct cpumask *cpu_map, struct sched_domain_attr *attr, -+ struct sched_domain *parent, int i) -+{ -+ struct sched_domain *sd = parent; -+#ifdef CONFIG_SCHED_SMT -+ sd = &per_cpu(cpu_domains, i).sd; -+ SD_INIT(sd, SIBLING); -+ set_domain_attribute(sd, attr); -+ cpumask_and(sched_domain_span(sd), cpu_map, topology_thread_cpumask(i)); -+ sd->parent = parent; -+ parent->child = sd; -+ cpu_to_cpu_group(i, cpu_map, &sd->groups, d->tmpmask); -+#endif -+ return sd; -+} -+ -+static void build_sched_groups(struct s_data *d, enum sched_domain_level l, -+ const struct cpumask *cpu_map, int cpu) -+{ -+ switch (l) { -+#ifdef CONFIG_SCHED_SMT -+ case SD_LV_SIBLING: /* set up CPU (sibling) groups */ -+ cpumask_and(d->this_sibling_map, cpu_map, -+ topology_thread_cpumask(cpu)); -+ if (cpu == cpumask_first(d->this_sibling_map)) -+ init_sched_build_groups(d->this_sibling_map, cpu_map, -+ &cpu_to_cpu_group, -+ d->send_covered, d->tmpmask); -+ break; -+#endif -+#ifdef CONFIG_SCHED_MC -+ case SD_LV_MC: /* set up multi-core groups */ -+ cpumask_and(d->this_core_map, cpu_map, cpu_coregroup_mask(cpu)); -+ if (cpu == cpumask_first(d->this_core_map)) -+ init_sched_build_groups(d->this_core_map, cpu_map, -+ &cpu_to_core_group, -+ d->send_covered, d->tmpmask); -+ break; -+#endif -+#ifdef CONFIG_SCHED_BOOK -+ case SD_LV_BOOK: /* set up book groups */ -+ cpumask_and(d->this_book_map, cpu_map, cpu_book_mask(cpu)); -+ if (cpu == cpumask_first(d->this_book_map)) -+ init_sched_build_groups(d->this_book_map, cpu_map, -+ &cpu_to_book_group, -+ d->send_covered, d->tmpmask); -+ break; -+#endif -+ case SD_LV_CPU: /* set up physical groups */ -+ cpumask_and(d->nodemask, cpumask_of_node(cpu), cpu_map); -+ if (!cpumask_empty(d->nodemask)) -+ init_sched_build_groups(d->nodemask, cpu_map, -+ &cpu_to_phys_group, -+ d->send_covered, d->tmpmask); -+ break; -+#ifdef CONFIG_NUMA -+ case SD_LV_ALLNODES: -+ init_sched_build_groups(cpu_map, cpu_map, &cpu_to_allnodes_group, -+ d->send_covered, d->tmpmask); -+ break; -+#endif -+ default: -+ break; -+ } -+} -+ -+/* -+ * Build sched domains for a given set of cpus and attach the sched domains -+ * to the individual cpus -+ */ -+static int __build_sched_domains(const struct cpumask *cpu_map, -+ struct sched_domain_attr *attr) -+{ -+ enum s_alloc alloc_state = sa_none; -+ struct s_data d; -+ struct sched_domain *sd; -+ int i; -+#ifdef CONFIG_NUMA -+ d.sd_allnodes = 0; -+#endif -+ -+ alloc_state = __visit_domain_allocation_hell(&d, cpu_map); -+ if (alloc_state != sa_rootdomain) -+ goto error; -+ alloc_state = sa_sched_groups; -+ -+ /* -+ * Set up domains for cpus specified by the cpu_map. -+ */ -+ for_each_cpu(i, cpu_map) { -+ cpumask_and(d.nodemask, cpumask_of_node(cpu_to_node(i)), -+ cpu_map); -+ -+ sd = __build_numa_sched_domains(&d, cpu_map, attr, i); -+ sd = __build_cpu_sched_domain(&d, cpu_map, attr, sd, i); -+ sd = __build_book_sched_domain(&d, cpu_map, attr, sd, i); -+ sd = __build_mc_sched_domain(&d, cpu_map, attr, sd, i); -+ sd = __build_smt_sched_domain(&d, cpu_map, attr, sd, i); -+ } -+ -+ for_each_cpu(i, cpu_map) { -+ build_sched_groups(&d, SD_LV_SIBLING, cpu_map, i); -+ build_sched_groups(&d, SD_LV_BOOK, cpu_map, i); -+ build_sched_groups(&d, SD_LV_MC, cpu_map, i); -+ } -+ -+ /* Set up physical groups */ -+ for (i = 0; i < nr_node_ids; i++) -+ build_sched_groups(&d, SD_LV_CPU, cpu_map, i); -+ -+#ifdef CONFIG_NUMA -+ /* Set up node groups */ -+ if (d.sd_allnodes) -+ build_sched_groups(&d, SD_LV_ALLNODES, cpu_map, 0); -+ -+ for (i = 0; i < nr_node_ids; i++) -+ if (build_numa_sched_groups(&d, cpu_map, i)) -+ goto error; -+#endif -+ -+ /* Calculate CPU power for physical packages and nodes */ -+#ifdef CONFIG_SCHED_SMT -+ for_each_cpu(i, cpu_map) { -+ sd = &per_cpu(cpu_domains, i).sd; -+ init_sched_groups_power(i, sd); -+ } -+#endif -+#ifdef CONFIG_SCHED_MC -+ for_each_cpu(i, cpu_map) { -+ sd = &per_cpu(core_domains, i).sd; -+ init_sched_groups_power(i, sd); -+ } -+#endif -+#ifdef CONFIG_SCHED_BOOK -+ for_each_cpu(i, cpu_map) { -+ sd = &per_cpu(book_domains, i).sd; -+ init_sched_groups_power(i, sd); -+ } -+#endif -+ -+ for_each_cpu(i, cpu_map) { -+ sd = &per_cpu(phys_domains, i).sd; -+ init_sched_groups_power(i, sd); -+ } -+ -+#ifdef CONFIG_NUMA -+ for (i = 0; i < nr_node_ids; i++) -+ init_numa_sched_groups_power(d.sched_group_nodes[i]); -+ -+ if (d.sd_allnodes) { -+ struct sched_group *sg; -+ -+ cpu_to_allnodes_group(cpumask_first(cpu_map), cpu_map, &sg, -+ d.tmpmask); -+ init_numa_sched_groups_power(sg); -+ } -+#endif -+ -+ /* Attach the domains */ -+ for_each_cpu(i, cpu_map) { -+#ifdef CONFIG_SCHED_SMT -+ sd = &per_cpu(cpu_domains, i).sd; -+#elif defined(CONFIG_SCHED_MC) -+ sd = &per_cpu(core_domains, i).sd; -+#elif defined(CONFIG_SCHED_BOOK) -+ sd = &per_cpu(book_domains, i).sd; -+#else -+ sd = &per_cpu(phys_domains, i).sd; -+#endif -+ cpu_attach_domain(sd, d.rd, i); -+ } -+ -+ d.sched_group_nodes = NULL; /* don't free this we still need it */ -+ __free_domain_allocs(&d, sa_tmpmask, cpu_map); -+ return 0; -+ -+error: -+ __free_domain_allocs(&d, alloc_state, cpu_map); -+ return -ENOMEM; -+} -+ -+static int build_sched_domains(const struct cpumask *cpu_map) -+{ -+ return __build_sched_domains(cpu_map, NULL); -+} -+ -+static cpumask_var_t *doms_cur; /* current sched domains */ -+static int ndoms_cur; /* number of sched domains in 'doms_cur' */ -+static struct sched_domain_attr *dattr_cur; -+ /* attribues of custom domains in 'doms_cur' */ -+ -+/* -+ * Special case: If a kmalloc of a doms_cur partition (array of -+ * cpumask) fails, then fallback to a single sched domain, -+ * as determined by the single cpumask fallback_doms. -+ */ -+static cpumask_var_t fallback_doms; -+ -+/* -+ * arch_update_cpu_topology lets virtualised architectures update the -+ * cpu core maps. It is supposed to return 1 if the topology changed -+ * or 0 if it stayed the same. -+ */ -+int __attribute__((weak)) arch_update_cpu_topology(void) -+{ -+ return 0; -+} -+ -+cpumask_var_t *alloc_sched_domains(unsigned int ndoms) -+{ -+ int i; -+ cpumask_var_t *doms; -+ -+ doms = kmalloc(sizeof(*doms) * ndoms, GFP_KERNEL); -+ if (!doms) -+ return NULL; -+ for (i = 0; i < ndoms; i++) { -+ if (!alloc_cpumask_var(&doms[i], GFP_KERNEL)) { -+ free_sched_domains(doms, i); -+ return NULL; -+ } -+ } -+ return doms; -+} -+ -+void free_sched_domains(cpumask_var_t doms[], unsigned int ndoms) -+{ -+ unsigned int i; -+ for (i = 0; i < ndoms; i++) -+ free_cpumask_var(doms[i]); -+ kfree(doms); -+} -+ -+/* -+ * Set up scheduler domains and groups. Callers must hold the hotplug lock. -+ * For now this just excludes isolated cpus, but could be used to -+ * exclude other special cases in the future. -+ */ -+static int arch_init_sched_domains(const struct cpumask *cpu_map) -+{ -+ int err; -+ -+ arch_update_cpu_topology(); -+ ndoms_cur = 1; -+ doms_cur = alloc_sched_domains(ndoms_cur); -+ if (!doms_cur) -+ doms_cur = &fallback_doms; -+ cpumask_andnot(doms_cur[0], cpu_map, cpu_isolated_map); -+ dattr_cur = NULL; -+ err = build_sched_domains(doms_cur[0]); -+ register_sched_domain_sysctl(); -+ -+ return err; -+} -+ -+static void arch_destroy_sched_domains(const struct cpumask *cpu_map, -+ struct cpumask *tmpmask) -+{ -+ free_sched_groups(cpu_map, tmpmask); -+} -+ -+/* -+ * Detach sched domains from a group of cpus specified in cpu_map -+ * These cpus will now be attached to the NULL domain -+ */ -+static void detach_destroy_domains(const struct cpumask *cpu_map) -+{ -+ /* Save because hotplug lock held. */ -+ static DECLARE_BITMAP(tmpmask, CONFIG_NR_CPUS); -+ int i; -+ -+ for_each_cpu(i, cpu_map) -+ cpu_attach_domain(NULL, &def_root_domain, i); -+ synchronize_sched(); -+ arch_destroy_sched_domains(cpu_map, to_cpumask(tmpmask)); -+} -+ -+/* handle null as "default" */ -+static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur, -+ struct sched_domain_attr *new, int idx_new) -+{ -+ struct sched_domain_attr tmp; -+ -+ /* fast path */ -+ if (!new && !cur) -+ return 1; -+ -+ tmp = SD_ATTR_INIT; -+ return !memcmp(cur ? (cur + idx_cur) : &tmp, -+ new ? (new + idx_new) : &tmp, -+ sizeof(struct sched_domain_attr)); -+} -+ -+/* -+ * Partition sched domains as specified by the 'ndoms_new' -+ * cpumasks in the array doms_new[] of cpumasks. This compares -+ * doms_new[] to the current sched domain partitioning, doms_cur[]. -+ * It destroys each deleted domain and builds each new domain. -+ * -+ * 'doms_new' is an array of cpumask_var_t's of length 'ndoms_new'. -+ * The masks don't intersect (don't overlap.) We should setup one -+ * sched domain for each mask. CPUs not in any of the cpumasks will -+ * not be load balanced. If the same cpumask appears both in the -+ * current 'doms_cur' domains and in the new 'doms_new', we can leave -+ * it as it is. -+ * -+ * The passed in 'doms_new' should be allocated using -+ * alloc_sched_domains. This routine takes ownership of it and will -+ * free_sched_domains it when done with it. If the caller failed the -+ * alloc call, then it can pass in doms_new == NULL && ndoms_new == 1, -+ * and partition_sched_domains() will fallback to the single partition -+ * 'fallback_doms', it also forces the domains to be rebuilt. -+ * -+ * If doms_new == NULL it will be replaced with cpu_online_mask. -+ * ndoms_new == 0 is a special case for destroying existing domains, -+ * and it will not create the default domain. -+ * -+ * Call with hotplug lock held -+ */ -+void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[], -+ struct sched_domain_attr *dattr_new) -+{ -+ int i, j, n; -+ int new_topology; -+ -+ mutex_lock(&sched_domains_mutex); -+ -+ /* always unregister in case we don't destroy any domains */ -+ unregister_sched_domain_sysctl(); -+ -+ /* Let architecture update cpu core mappings. */ -+ new_topology = arch_update_cpu_topology(); -+ -+ n = doms_new ? ndoms_new : 0; -+ -+ /* Destroy deleted domains */ -+ for (i = 0; i < ndoms_cur; i++) { -+ for (j = 0; j < n && !new_topology; j++) { -+ if (cpumask_equal(doms_cur[i], doms_new[j]) -+ && dattrs_equal(dattr_cur, i, dattr_new, j)) -+ goto match1; -+ } -+ /* no match - a current sched domain not in new doms_new[] */ -+ detach_destroy_domains(doms_cur[i]); -+match1: -+ ; -+ } -+ -+ if (doms_new == NULL) { -+ ndoms_cur = 0; -+ doms_new = &fallback_doms; -+ cpumask_andnot(doms_new[0], cpu_active_mask, cpu_isolated_map); -+ WARN_ON_ONCE(dattr_new); -+ } -+ -+ /* Build new domains */ -+ for (i = 0; i < ndoms_new; i++) { -+ for (j = 0; j < ndoms_cur && !new_topology; j++) { -+ if (cpumask_equal(doms_new[i], doms_cur[j]) -+ && dattrs_equal(dattr_new, i, dattr_cur, j)) -+ goto match2; -+ } -+ /* no match - add a new doms_new */ -+ __build_sched_domains(doms_new[i], -+ dattr_new ? dattr_new + i : NULL); -+match2: -+ ; -+ } -+ -+ /* Remember the new sched domains */ -+ if (doms_cur != &fallback_doms) -+ free_sched_domains(doms_cur, ndoms_cur); -+ kfree(dattr_cur); /* kfree(NULL) is safe */ -+ doms_cur = doms_new; -+ dattr_cur = dattr_new; -+ ndoms_cur = ndoms_new; -+ -+ register_sched_domain_sysctl(); -+ -+ mutex_unlock(&sched_domains_mutex); -+} -+ -+#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) -+static void arch_reinit_sched_domains(void) -+{ -+ get_online_cpus(); -+ -+ /* Destroy domains first to force the rebuild */ -+ partition_sched_domains(0, NULL, NULL); -+ -+ rebuild_sched_domains(); -+ put_online_cpus(); -+} -+ -+static ssize_t sched_power_savings_store(const char *buf, size_t count, int smt) -+{ -+ unsigned int level = 0; -+ -+ if (sscanf(buf, "%u", &level) != 1) -+ return -EINVAL; -+ -+ /* -+ * level is always be positive so don't check for -+ * level < POWERSAVINGS_BALANCE_NONE which is 0 -+ * What happens on 0 or 1 byte write, -+ * need to check for count as well? -+ */ -+ -+ if (level >= MAX_POWERSAVINGS_BALANCE_LEVELS) -+ return -EINVAL; -+ -+ if (smt) -+ sched_smt_power_savings = level; -+ else -+ sched_mc_power_savings = level; -+ -+ arch_reinit_sched_domains(); -+ -+ return count; -+} -+ -+#ifdef CONFIG_SCHED_MC -+static ssize_t sched_mc_power_savings_show(struct sysdev_class *class, -+ struct sysdev_class_attribute *attr, -+ char *page) -+{ -+ return sprintf(page, "%u\n", sched_mc_power_savings); -+} -+static ssize_t sched_mc_power_savings_store(struct sysdev_class *class, -+ struct sysdev_class_attribute *attr, -+ const char *buf, size_t count) -+{ -+ return sched_power_savings_store(buf, count, 0); -+} -+static SYSDEV_CLASS_ATTR(sched_mc_power_savings, 0644, -+ sched_mc_power_savings_show, -+ sched_mc_power_savings_store); -+#endif -+ -+#ifdef CONFIG_SCHED_SMT -+static ssize_t sched_smt_power_savings_show(struct sysdev_class *dev, -+ struct sysdev_class_attribute *attr, -+ char *page) -+{ -+ return sprintf(page, "%u\n", sched_smt_power_savings); -+} -+static ssize_t sched_smt_power_savings_store(struct sysdev_class *dev, -+ struct sysdev_class_attribute *attr, -+ const char *buf, size_t count) -+{ -+ return sched_power_savings_store(buf, count, 1); -+} -+static SYSDEV_CLASS_ATTR(sched_smt_power_savings, 0644, -+ sched_smt_power_savings_show, -+ sched_smt_power_savings_store); -+#endif -+ -+int __init sched_create_sysfs_power_savings_entries(struct sysdev_class *cls) -+{ -+ int err = 0; -+ -+#ifdef CONFIG_SCHED_SMT -+ if (smt_capable()) -+ err = sysfs_create_file(&cls->kset.kobj, -+ &attr_sched_smt_power_savings.attr); -+#endif -+#ifdef CONFIG_SCHED_MC -+ if (!err && mc_capable()) -+ err = sysfs_create_file(&cls->kset.kobj, -+ &attr_sched_mc_power_savings.attr); -+#endif -+ return err; -+} -+#endif /* CONFIG_SCHED_MC || CONFIG_SCHED_SMT */ -+ -+/* -+ * Update cpusets according to cpu_active mask. If cpusets are -+ * disabled, cpuset_update_active_cpus() becomes a simple wrapper -+ * around partition_sched_domains(). -+ */ -+static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action, -+ void *hcpu) -+{ -+ switch (action & ~CPU_TASKS_FROZEN) { -+ case CPU_ONLINE: -+ case CPU_DOWN_FAILED: -+ cpuset_update_active_cpus(); -+ return NOTIFY_OK; -+ default: -+ return NOTIFY_DONE; -+ } -+} -+ -+static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action, -+ void *hcpu) -+{ -+ switch (action & ~CPU_TASKS_FROZEN) { -+ case CPU_DOWN_PREPARE: -+ cpuset_update_active_cpus(); -+ return NOTIFY_OK; -+ default: -+ return NOTIFY_DONE; -+ } -+} -+ -+static int update_runtime(struct notifier_block *nfb, -+ unsigned long action, void *hcpu) -+{ -+ switch (action) { -+ case CPU_DOWN_PREPARE: -+ case CPU_DOWN_PREPARE_FROZEN: -+ return NOTIFY_OK; -+ -+ case CPU_DOWN_FAILED: -+ case CPU_DOWN_FAILED_FROZEN: -+ case CPU_ONLINE: -+ case CPU_ONLINE_FROZEN: -+ return NOTIFY_OK; -+ -+ default: -+ return NOTIFY_DONE; -+ } -+} -+ -+#if defined(CONFIG_SCHED_SMT) || defined(CONFIG_SCHED_MC) -+/* -+ * Cheaper version of the below functions in case support for SMT and MC is -+ * compiled in but CPUs have no siblings. -+ */ -+static int sole_cpu_idle(unsigned long cpu) -+{ -+ return rq_idle(cpu_rq(cpu)); -+} -+#endif -+#ifdef CONFIG_SCHED_SMT -+/* All this CPU's SMT siblings are idle */ -+static int siblings_cpu_idle(unsigned long cpu) -+{ -+ return cpumask_subset(&(cpu_rq(cpu)->smt_siblings), -+ &grq.cpu_idle_map); -+} -+#endif -+#ifdef CONFIG_SCHED_MC -+/* All this CPU's shared cache siblings are idle */ -+static int cache_cpu_idle(unsigned long cpu) -+{ -+ return cpumask_subset(&(cpu_rq(cpu)->cache_siblings), -+ &grq.cpu_idle_map); -+} -+#endif -+ -+void __init sched_init_smp(void) -+{ -+ struct sched_domain *sd; -+ int cpu, cpus; -+ -+ cpumask_var_t non_isolated_cpus; -+ -+ alloc_cpumask_var(&non_isolated_cpus, GFP_KERNEL); -+ alloc_cpumask_var(&fallback_doms, GFP_KERNEL); -+ -+#if defined(CONFIG_NUMA) -+ sched_group_nodes_bycpu = kzalloc(nr_cpu_ids * sizeof(void **), -+ GFP_KERNEL); -+ BUG_ON(sched_group_nodes_bycpu == NULL); -+#endif -+ get_online_cpus(); -+ mutex_lock(&sched_domains_mutex); -+ arch_init_sched_domains(cpu_active_mask); -+ cpumask_andnot(non_isolated_cpus, cpu_possible_mask, cpu_isolated_map); -+ if (cpumask_empty(non_isolated_cpus)) -+ cpumask_set_cpu(smp_processor_id(), non_isolated_cpus); -+ mutex_unlock(&sched_domains_mutex); -+ put_online_cpus(); -+ -+ hotcpu_notifier(cpuset_cpu_active, CPU_PRI_CPUSET_ACTIVE); -+ hotcpu_notifier(cpuset_cpu_inactive, CPU_PRI_CPUSET_INACTIVE); -+ -+ /* RT runtime code needs to handle some hotplug events */ -+ hotcpu_notifier(update_runtime, 0); -+ -+ /* Move init over to a non-isolated CPU */ -+ if (set_cpus_allowed_ptr(current, non_isolated_cpus) < 0) -+ BUG(); -+ free_cpumask_var(non_isolated_cpus); -+ -+ /* -+ * Assume that every added cpu gives us slightly less overall latency -+ * allowing us to increase the base rr_interval, non-linearly and with -+ * an upper bound. -+ */ -+ cpus = num_online_cpus(); -+ rr_interval = rr_interval * (4 * cpus + 4) / (cpus + 6); -+ -+ grq_lock_irq(); -+ /* -+ * Set up the relative cache distance of each online cpu from each -+ * other in a simple array for quick lookup. Locality is determined -+ * by the closest sched_domain that CPUs are separated by. CPUs with -+ * shared cache in SMT and MC are treated as local. Separate CPUs -+ * (within the same package or physically) within the same node are -+ * treated as not local. CPUs not even in the same domain (different -+ * nodes) are treated as very distant. -+ */ -+ for_each_online_cpu(cpu) { -+ struct rq *rq = cpu_rq(cpu); -+ for_each_domain(cpu, sd) { -+ unsigned long locality; -+ int other_cpu; -+ -+#ifdef CONFIG_SCHED_SMT -+ if (sd->level == SD_LV_SIBLING) { -+ for_each_cpu_mask(other_cpu, *sched_domain_span(sd)) -+ cpumask_set_cpu(other_cpu, &rq->smt_siblings); -+ } -+#endif -+#ifdef CONFIG_SCHED_MC -+ if (sd->level == SD_LV_MC) { -+ for_each_cpu_mask(other_cpu, *sched_domain_span(sd)) -+ cpumask_set_cpu(other_cpu, &rq->cache_siblings); -+ } -+#endif -+ if (sd->level <= SD_LV_SIBLING) -+ locality = 1; -+ else if (sd->level <= SD_LV_MC) -+ locality = 2; -+ else if (sd->level <= SD_LV_NODE) -+ locality = 3; -+ else -+ continue; -+ -+ for_each_cpu_mask(other_cpu, *sched_domain_span(sd)) { -+ if (locality < rq->cpu_locality[other_cpu]) -+ rq->cpu_locality[other_cpu] = locality; -+ } -+ } -+ -+/* -+ * Each runqueue has its own function in case it doesn't have -+ * siblings of its own allowing mixed topologies. -+ */ -+#ifdef CONFIG_SCHED_SMT -+ if (cpus_weight(rq->smt_siblings) > 1) -+ rq->siblings_idle = siblings_cpu_idle; -+#endif -+#ifdef CONFIG_SCHED_MC -+ if (cpus_weight(rq->cache_siblings) > 1) -+ rq->cache_idle = cache_cpu_idle; -+#endif -+ } -+ grq_unlock_irq(); -+} -+#else -+void __init sched_init_smp(void) -+{ -+} -+#endif /* CONFIG_SMP */ -+ -+unsigned int sysctl_timer_migration = 1; -+ -+int in_sched_functions(unsigned long addr) -+{ -+ return in_lock_functions(addr) || -+ (addr >= (unsigned long)__sched_text_start -+ && addr < (unsigned long)__sched_text_end); -+} -+ -+void __init sched_init(void) -+{ -+ int i; -+ struct rq *rq; -+ -+ prio_ratios[0] = 128; -+ for (i = 1 ; i < PRIO_RANGE ; i++) -+ prio_ratios[i] = prio_ratios[i - 1] * 11 / 10; -+ -+ raw_spin_lock_init(&grq.lock); -+ grq.nr_running = grq.nr_uninterruptible = grq.nr_switches = 0; -+ grq.niffies = 0; -+ grq.last_jiffy = jiffies; -+ raw_spin_lock_init(&grq.iso_lock); -+ grq.iso_ticks = grq.iso_refractory = 0; -+#ifdef CONFIG_SMP -+ init_defrootdomain(); -+ grq.qnr = grq.idle_cpus = 0; -+ cpumask_clear(&grq.cpu_idle_map); -+#else -+ uprq = &per_cpu(runqueues, 0); -+#endif -+ for_each_possible_cpu(i) { -+ rq = cpu_rq(i); -+ rq->user_pc = rq->nice_pc = rq->softirq_pc = rq->system_pc = -+ rq->iowait_pc = rq->idle_pc = 0; -+ rq->dither = 0; -+#ifdef CONFIG_SMP -+ rq->last_niffy = 0; -+ rq->sd = NULL; -+ rq->rd = NULL; -+ rq->online = 0; -+ rq->cpu = i; -+ rq_attach_root(rq, &def_root_domain); -+#endif -+ atomic_set(&rq->nr_iowait, 0); -+ } -+ -+#ifdef CONFIG_SMP -+ nr_cpu_ids = i; -+ /* -+ * Set the base locality for cpu cache distance calculation to -+ * "distant" (3). Make sure the distance from a CPU to itself is 0. -+ */ -+ for_each_possible_cpu(i) { -+ int j; -+ -+ rq = cpu_rq(i); -+#ifdef CONFIG_SCHED_SMT -+ cpumask_clear(&rq->smt_siblings); -+ cpumask_set_cpu(i, &rq->smt_siblings); -+ rq->siblings_idle = sole_cpu_idle; -+ cpumask_set_cpu(i, &rq->smt_siblings); -+#endif -+#ifdef CONFIG_SCHED_MC -+ cpumask_clear(&rq->cache_siblings); -+ cpumask_set_cpu(i, &rq->cache_siblings); -+ rq->cache_idle = sole_cpu_idle; -+ cpumask_set_cpu(i, &rq->cache_siblings); -+#endif -+ rq->cpu_locality = kmalloc(nr_cpu_ids * sizeof(unsigned long), -+ GFP_NOWAIT); -+ for_each_possible_cpu(j) { -+ if (i == j) -+ rq->cpu_locality[j] = 0; -+ else -+ rq->cpu_locality[j] = 4; -+ } -+ } -+#endif -+ -+ for (i = 0; i < PRIO_LIMIT; i++) -+ INIT_LIST_HEAD(grq.queue + i); -+ /* delimiter for bitsearch */ -+ __set_bit(PRIO_LIMIT, grq.prio_bitmap); -+ -+#ifdef CONFIG_PREEMPT_NOTIFIERS -+ INIT_HLIST_HEAD(&init_task.preempt_notifiers); -+#endif -+ -+#ifdef CONFIG_RT_MUTEXES -+ plist_head_init_raw(&init_task.pi_waiters, &init_task.pi_lock); -+#endif -+ -+ /* -+ * The boot idle thread does lazy MMU switching as well: -+ */ -+ atomic_inc(&init_mm.mm_count); -+ enter_lazy_tlb(&init_mm, current); -+ -+ /* -+ * Make us the idle thread. Technically, schedule() should not be -+ * called from this thread, however somewhere below it might be, -+ * but because we are the idle thread, we just pick up running again -+ * when this runqueue becomes "idle". -+ */ -+ init_idle(current, smp_processor_id()); -+ -+ /* Allocate the nohz_cpu_mask if CONFIG_CPUMASK_OFFSTACK */ -+ zalloc_cpumask_var(&nohz_cpu_mask, GFP_NOWAIT); -+#ifdef CONFIG_SMP -+ /* May be allocated at isolcpus cmdline parse time */ -+ if (cpu_isolated_map == NULL) -+ zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT); -+#endif /* SMP */ -+ perf_event_init(); -+} -+ -+#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP -+static inline int preempt_count_equals(int preempt_offset) -+{ -+ int nested = (preempt_count() & ~PREEMPT_ACTIVE) + rcu_preempt_depth(); -+ -+ return (nested == PREEMPT_INATOMIC_BASE + preempt_offset); -+} -+ -+void __might_sleep(const char *file, int line, int preempt_offset) -+{ -+#ifdef in_atomic -+ static unsigned long prev_jiffy; /* ratelimiting */ -+ -+ if ((preempt_count_equals(preempt_offset) && !irqs_disabled()) || -+ system_state != SYSTEM_RUNNING || oops_in_progress) -+ return; -+ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy) -+ return; -+ prev_jiffy = jiffies; -+ -+ printk(KERN_ERR -+ "BUG: sleeping function called from invalid context at %s:%d\n", -+ file, line); -+ printk(KERN_ERR -+ "in_atomic(): %d, irqs_disabled(): %d, pid: %d, name: %s\n", -+ in_atomic(), irqs_disabled(), -+ current->pid, current->comm); -+ -+ debug_show_held_locks(current); -+ if (irqs_disabled()) -+ print_irqtrace_events(current); -+ dump_stack(); -+#endif -+} -+EXPORT_SYMBOL(__might_sleep); -+#endif -+ -+#ifdef CONFIG_MAGIC_SYSRQ -+void normalize_rt_tasks(void) -+{ -+ struct task_struct *g, *p; -+ unsigned long flags; -+ struct rq *rq; -+ int queued; -+ -+ read_lock_irq(&tasklist_lock); -+ -+ do_each_thread(g, p) { -+ if (!rt_task(p) && !iso_task(p)) -+ continue; -+ -+ raw_spin_lock_irqsave(&p->pi_lock, flags); -+ rq = __task_grq_lock(p); -+ -+ queued = task_queued(p); -+ if (queued) -+ dequeue_task(p); -+ __setscheduler(p, rq, SCHED_NORMAL, 0); -+ if (queued) { -+ enqueue_task(p); -+ try_preempt(p, rq); -+ } -+ -+ __task_grq_unlock(); -+ raw_spin_unlock_irqrestore(&p->pi_lock, flags); -+ } while_each_thread(g, p); -+ -+ read_unlock_irq(&tasklist_lock); -+} -+#endif /* CONFIG_MAGIC_SYSRQ */ -+ -+#if defined(CONFIG_IA64) || defined(CONFIG_KGDB_KDB) -+/* -+ * These functions are only useful for the IA64 MCA handling, or kdb. -+ * -+ * They can only be called when the whole system has been -+ * stopped - every CPU needs to be quiescent, and no scheduling -+ * activity can take place. Using them for anything else would -+ * be a serious bug, and as a result, they aren't even visible -+ * under any other configuration. -+ */ -+ -+/** -+ * curr_task - return the current task for a given cpu. -+ * @cpu: the processor in question. -+ * -+ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED! -+ */ -+struct task_struct *curr_task(int cpu) -+{ -+ return cpu_curr(cpu); -+} -+ -+#endif /* defined(CONFIG_IA64) || defined(CONFIG_KGDB_KDB) */ -+ -+#ifdef CONFIG_IA64 -+/** -+ * set_curr_task - set the current task for a given cpu. -+ * @cpu: the processor in question. -+ * @p: the task pointer to set. -+ * -+ * Description: This function must only be used when non-maskable interrupts -+ * are serviced on a separate stack. It allows the architecture to switch the -+ * notion of the current task on a cpu in a non-blocking manner. This function -+ * must be called with all CPU's synchronised, and interrupts disabled, the -+ * and caller must save the original value of the current task (see -+ * curr_task() above) and restore that value before reenabling interrupts and -+ * re-starting the system. -+ * -+ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED! -+ */ -+void set_curr_task(int cpu, struct task_struct *p) -+{ -+ cpu_curr(cpu) = p; -+} -+ -+#endif -+ -+/* -+ * Use precise platform statistics if available: -+ */ -+#ifdef CONFIG_VIRT_CPU_ACCOUNTING -+void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st) -+{ -+ *ut = p->utime; -+ *st = p->stime; -+} -+ -+void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) -+{ -+ struct task_cputime cputime; -+ -+ thread_group_cputime(p, &cputime); -+ -+ *ut = cputime.utime; -+ *st = cputime.stime; -+} -+#else -+ -+#ifndef nsecs_to_cputime -+# define nsecs_to_cputime(__nsecs) nsecs_to_jiffies(__nsecs) -+#endif -+ -+void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st) -+{ -+ cputime_t rtime, utime = p->utime, total = cputime_add(utime, p->stime); -+ -+ rtime = nsecs_to_cputime(p->sched_time); -+ -+ if (total) { -+ u64 temp; -+ -+ temp = (u64)(rtime * utime); -+ do_div(temp, total); -+ utime = (cputime_t)temp; -+ } else -+ utime = rtime; -+ -+ /* -+ * Compare with previous values, to keep monotonicity: -+ */ -+ p->prev_utime = max(p->prev_utime, utime); -+ p->prev_stime = max(p->prev_stime, cputime_sub(rtime, p->prev_utime)); -+ -+ *ut = p->prev_utime; -+ *st = p->prev_stime; -+} -+ -+/* -+ * Must be called with siglock held. -+ */ -+void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) -+{ -+ struct signal_struct *sig = p->signal; -+ struct task_cputime cputime; -+ cputime_t rtime, utime, total; -+ -+ thread_group_cputime(p, &cputime); -+ -+ total = cputime_add(cputime.utime, cputime.stime); -+ rtime = nsecs_to_cputime(cputime.sum_exec_runtime); -+ -+ if (total) { -+ u64 temp; -+ -+ temp = (u64)(rtime * cputime.utime); -+ do_div(temp, total); -+ utime = (cputime_t)temp; -+ } else -+ utime = rtime; -+ -+ sig->prev_utime = max(sig->prev_utime, utime); -+ sig->prev_stime = max(sig->prev_stime, -+ cputime_sub(rtime, sig->prev_utime)); -+ -+ *ut = sig->prev_utime; -+ *st = sig->prev_stime; -+} -+#endif -+ -+inline cputime_t task_gtime(struct task_struct *p) -+{ -+ return p->gtime; -+} -+ -+void __cpuinit init_idle_bootup_task(struct task_struct *idle) -+{} -+ -+#ifdef CONFIG_SCHED_DEBUG -+void proc_sched_show_task(struct task_struct *p, struct seq_file *m) -+{} -+ -+void proc_sched_set_task(struct task_struct *p) -+{} -+#endif -+ -+/* No RCU torture test support */ -+void synchronize_sched_expedited(void) -+{ -+ barrier(); -+} -+EXPORT_SYMBOL_GPL(synchronize_sched_expedited); -+ -+#ifdef CONFIG_SMP -+unsigned long default_scale_freq_power(struct sched_domain *sd, int cpu) -+{ -+ return SCHED_LOAD_SCALE; -+} -+ -+unsigned long default_scale_smt_power(struct sched_domain *sd, int cpu) -+{ -+ unsigned long weight = cpumask_weight(sched_domain_span(sd)); -+ unsigned long smt_gain = sd->smt_gain; -+ -+ smt_gain /= weight; -+ -+ return smt_gain; -+} -+#endif -Index: linux-2.6.37-ck2/kernel/sched.c -=================================================================== ---- linux-2.6.37-ck2.orig/kernel/sched.c 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/kernel/sched.c 2011-02-14 09:47:50.994252001 +1100 -@@ -1,3 +1,6 @@ -+#ifdef CONFIG_SCHED_BFS -+#include "sched_bfs.c" -+#else - /* - * kernel/sched.c - * -@@ -9603,3 +9606,4 @@ - EXPORT_SYMBOL_GPL(synchronize_sched_expedited); - - #endif /* #else #ifndef CONFIG_SMP */ -+#endif /* CONFIG_SCHED_BFS */ -Index: linux-2.6.37-ck2/kernel/sysctl.c -=================================================================== ---- linux-2.6.37-ck2.orig/kernel/sysctl.c 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/kernel/sysctl.c 2011-02-14 09:47:50.995252001 +1100 -@@ -117,7 +117,12 @@ - static int __maybe_unused one = 1; - static int __maybe_unused two = 2; - static unsigned long one_ul = 1; --static int one_hundred = 100; -+static int __maybe_unused one_hundred = 100; -+#ifdef CONFIG_SCHED_BFS -+extern int rr_interval; -+extern int sched_iso_cpu; -+static int __read_mostly one_thousand = 1000; -+#endif - #ifdef CONFIG_PRINTK - static int ten_thousand = 10000; - #endif -@@ -252,7 +257,7 @@ - { } - }; - --#ifdef CONFIG_SCHED_DEBUG -+#if defined(CONFIG_SCHED_DEBUG) && !defined(CONFIG_SCHED_BFS) - static int min_sched_granularity_ns = 100000; /* 100 usecs */ - static int max_sched_granularity_ns = NSEC_PER_SEC; /* 1 second */ - static int min_wakeup_granularity_ns; /* 0 usecs */ -@@ -269,6 +274,7 @@ - #endif - - static struct ctl_table kern_table[] = { -+#ifndef CONFIG_SCHED_BFS - { - .procname = "sched_child_runs_first", - .data = &sysctl_sched_child_runs_first, -@@ -382,6 +388,7 @@ - .mode = 0644, - .proc_handler = proc_dointvec, - }, -+#endif /* !CONFIG_SCHED_BFS */ - #ifdef CONFIG_PROVE_LOCKING - { - .procname = "prove_locking", -@@ -815,6 +822,26 @@ - .proc_handler = proc_dointvec, - }, - #endif -+#ifdef CONFIG_SCHED_BFS -+ { -+ .procname = "rr_interval", -+ .data = &rr_interval, -+ .maxlen = sizeof (int), -+ .mode = 0644, -+ .proc_handler = &proc_dointvec_minmax, -+ .extra1 = &one, -+ .extra2 = &one_thousand, -+ }, -+ { -+ .procname = "iso_cpu", -+ .data = &sched_iso_cpu, -+ .maxlen = sizeof (int), -+ .mode = 0644, -+ .proc_handler = &proc_dointvec_minmax, -+ .extra1 = &zero, -+ .extra2 = &one_hundred, -+ }, -+#endif - #if defined(CONFIG_S390) && defined(CONFIG_SMP) - { - .procname = "spin_retry", -Index: linux-2.6.37-ck2/lib/Kconfig.debug -=================================================================== ---- linux-2.6.37-ck2.orig/lib/Kconfig.debug 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/lib/Kconfig.debug 2011-02-14 09:47:50.995252001 +1100 -@@ -833,7 +833,7 @@ - - config RCU_TORTURE_TEST - tristate "torture tests for RCU" -- depends on DEBUG_KERNEL -+ depends on DEBUG_KERNEL && !SCHED_BFS - default n - help - This option provides a kernel module that runs torture tests -Index: linux-2.6.37-ck2/include/linux/jiffies.h -=================================================================== ---- linux-2.6.37-ck2.orig/include/linux/jiffies.h 2010-02-25 21:51:52.000000000 +1100 -+++ linux-2.6.37-ck2/include/linux/jiffies.h 2011-02-14 09:47:50.995252001 +1100 -@@ -164,7 +164,7 @@ - * Have the 32 bit jiffies value wrap 5 minutes after boot - * so jiffies wrap bugs show up earlier. - */ --#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ)) -+#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-10*HZ)) - - /* - * Change timeval to jiffies, trying to avoid the diff --git a/packages/linux/patches/linux-2.6.37.1-702_bfs363-nonhotplug_fix.patch b/packages/linux/patches/linux-2.6.37.1-702_bfs363-nonhotplug_fix.patch deleted file mode 100644 index 59b401dea6..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-702_bfs363-nonhotplug_fix.patch +++ /dev/null @@ -1,60 +0,0 @@ -Fix a failure to build if CPU hotplug is disabled with BFS. - --ck - ---- - kernel/sched_bfs.c | 34 +++++++++++++++++----------------- - 1 file changed, 17 insertions(+), 17 deletions(-) - -Index: linux-2.6.37-ck2/kernel/sched_bfs.c -=================================================================== ---- linux-2.6.37-ck2.orig/kernel/sched_bfs.c 2011-02-14 09:50:24.351252002 +1100 -+++ linux-2.6.37-ck2/kernel/sched_bfs.c 2011-02-14 09:53:53.820252000 +1100 -@@ -4812,6 +4812,23 @@ - grq_unlock_irqrestore(&flags); - } - -+/* -+ * Ensures that the idle task is using init_mm right before its cpu goes -+ * offline. -+ */ -+void idle_task_exit(void) -+{ -+ struct mm_struct *mm = current->active_mm; -+ -+ BUG_ON(cpu_online(smp_processor_id())); -+ -+ if (mm != &init_mm) -+ switch_mm(mm, &init_mm, current); -+ mmdrop(mm); -+} -+ -+#endif /* CONFIG_HOTPLUG_CPU */ -+ - void sched_set_stop_task(int cpu, struct task_struct *stop) - { - struct sched_param stop_param = { .sched_priority = STOP_PRIO }; -@@ -4841,23 +4858,6 @@ - } - } - --/* -- * Ensures that the idle task is using init_mm right before its cpu goes -- * offline. -- */ --void idle_task_exit(void) --{ -- struct mm_struct *mm = current->active_mm; -- -- BUG_ON(cpu_online(smp_processor_id())); -- -- if (mm != &init_mm) -- switch_mm(mm, &init_mm, current); -- mmdrop(mm); --} -- --#endif /* CONFIG_HOTPLUG_CPU */ -- - #if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL) - - static struct ctl_table sd_ctl_dir[] = { diff --git a/packages/linux/patches/linux-2.6.37.1-702_ck2-version.patch b/packages/linux/patches/linux-2.6.37.1-702_ck2-version.patch deleted file mode 100644 index 4f34a3ebed..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-702_ck2-version.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- - Makefile | 4 ++++ - 1 file changed, 4 insertions(+) - -Index: linux-2.6.37-ck2/Makefile -=================================================================== ---- linux-2.6.37-ck2.orig/Makefile 2011-01-06 14:04:07.000000000 +1100 -+++ linux-2.6.37-ck2/Makefile 2011-02-14 10:11:20.469252000 +1100 -@@ -10,6 +10,10 @@ - # Comments in this file are targeted only to the developer, do not - # expect to learn how to build the kernel reading this file. - -+CKVERSION = -ck2 -+CKNAME = BFS Powered -+EXTRAVERSION := $(EXTRAVERSION)$(CKVERSION) -+ - # Do not: - # o use make's built-in rules and variables - # (this increases performance and avoids hard-to-debug behaviour); diff --git a/packages/linux/patches/linux-2.6.37.1-703_cpufreq-bfs_tweaks.patch b/packages/linux/patches/linux-2.6.37.1-703_cpufreq-bfs_tweaks.patch deleted file mode 100644 index fc0122e323..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-703_cpufreq-bfs_tweaks.patch +++ /dev/null @@ -1,37 +0,0 @@ ---- - drivers/cpufreq/cpufreq_ondemand.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -Index: linux-2.6.37-ck2/drivers/cpufreq/cpufreq_ondemand.c -=================================================================== ---- linux-2.6.37-ck2.orig/drivers/cpufreq/cpufreq_ondemand.c 2011-01-06 14:04:08.000000000 +1100 -+++ linux-2.6.37-ck2/drivers/cpufreq/cpufreq_ondemand.c 2011-02-14 10:11:11.438252001 +1100 -@@ -28,12 +28,12 @@ - * It helps to keep variable names smaller, simpler - */ - --#define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10) --#define DEF_FREQUENCY_UP_THRESHOLD (80) -+#define DEF_FREQUENCY_DOWN_DIFFERENTIAL (17) -+#define DEF_FREQUENCY_UP_THRESHOLD (63) - #define DEF_SAMPLING_DOWN_FACTOR (1) - #define MAX_SAMPLING_DOWN_FACTOR (100000) - #define MICRO_FREQUENCY_DOWN_DIFFERENTIAL (3) --#define MICRO_FREQUENCY_UP_THRESHOLD (95) -+#define MICRO_FREQUENCY_UP_THRESHOLD (80) - #define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000) - #define MIN_FREQUENCY_UP_THRESHOLD (11) - #define MAX_FREQUENCY_UP_THRESHOLD (100) -@@ -513,10 +513,10 @@ - - /* - * Every sampling_rate, we check, if current idle time is less -- * than 20% (default), then we try to increase frequency -+ * than 37% (default), then we try to increase frequency - * Every sampling_rate, we look for a the lowest - * frequency which can sustain the load while keeping idle time over -- * 30%. If such a frequency exist, we try to decrease to this frequency. -+ * 50%. If such a frequency exist, we try to decrease to this frequency. - * - * Any frequency increase takes it to the maximum frequency. - * Frequency reduction happens at minimum steps of diff --git a/packages/linux/patches/linux-2.6.37.1-704_hz-default_1000.patch b/packages/linux/patches/linux-2.6.37.1-704_hz-default_1000.patch deleted file mode 100644 index 5af5138068..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-704_hz-default_1000.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- - kernel/Kconfig.hz | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Index: linux-2.6.37-ck2/kernel/Kconfig.hz -=================================================================== ---- linux-2.6.37-ck2.orig/kernel/Kconfig.hz 2009-06-10 13:05:27.000000000 +1000 -+++ linux-2.6.37-ck2/kernel/Kconfig.hz 2011-02-14 10:11:10.474252000 +1100 -@@ -4,7 +4,7 @@ - - choice - prompt "Timer frequency" -- default HZ_250 -+ default HZ_1000 - help - Allows the configuration of the timer frequency. It is customary - to have the timer interrupt run at 1000 Hz but 100 Hz may be more diff --git a/packages/linux/patches/linux-2.6.37.1-705_hz-no_default_250.patch b/packages/linux/patches/linux-2.6.37.1-705_hz-no_default_250.patch deleted file mode 100644 index 051075471a..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-705_hz-no_default_250.patch +++ /dev/null @@ -1,47 +0,0 @@ ---- - kernel/Kconfig.hz | 17 ++++++++++------- - 1 file changed, 10 insertions(+), 7 deletions(-) - -Index: linux-2.6.37-ck2/kernel/Kconfig.hz -=================================================================== ---- linux-2.6.37-ck2.orig/kernel/Kconfig.hz 2011-02-14 10:11:10.474252000 +1100 -+++ linux-2.6.37-ck2/kernel/Kconfig.hz 2011-02-14 10:11:10.702252000 +1100 -@@ -23,13 +23,14 @@ - with lots of processors that may show reduced performance if - too many timer interrupts are occurring. - -- config HZ_250 -+ config HZ_250_NODEFAULT - bool "250 HZ" - help -- 250 Hz is a good compromise choice allowing server performance -- while also showing good interactive responsiveness even -- on SMP and NUMA systems. If you are going to be using NTSC video -- or multimedia, selected 300Hz instead. -+ 250 HZ is a lousy compromise choice allowing server interactivity -+ while also showing desktop throughput and no extra power saving on -+ laptops. No good for anything. -+ -+ Recommend 100 or 1000 instead. - - config HZ_300 - bool "300 HZ" -@@ -43,14 +44,16 @@ - bool "1000 HZ" - help - 1000 Hz is the preferred choice for desktop systems and other -- systems requiring fast interactive responses to events. -+ systems requiring fast interactive responses to events. Laptops -+ can also benefit from this choice without sacrificing battery life -+ if dynticks is also enabled. - - endchoice - - config HZ - int - default 100 if HZ_100 -- default 250 if HZ_250 -+ default 250 if HZ_250_NODEFAULT - default 300 if HZ_300 - default 1000 if HZ_1000 - diff --git a/packages/linux/patches/linux-2.6.37.1-706_hz-raise_max.patch b/packages/linux/patches/linux-2.6.37.1-706_hz-raise_max.patch deleted file mode 100644 index bf70f54392..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-706_hz-raise_max.patch +++ /dev/null @@ -1,174 +0,0 @@ ---- - arch/x86/kernel/cpu/proc.c | 2 - - arch/x86/kernel/smpboot.c | 2 - - include/linux/nfsd/stats.h | 4 +- - include/net/inet_timewait_sock.h | 10 ++++-- - init/calibrate.c | 2 - - kernel/Kconfig.hz | 64 +++++++++++++++++++++++++++++++++++++++ - 6 files changed, 76 insertions(+), 8 deletions(-) - -Index: linux-2.6.37-ck2/arch/x86/kernel/cpu/proc.c -=================================================================== ---- linux-2.6.37-ck2.orig/arch/x86/kernel/cpu/proc.c 2009-12-03 21:39:58.000000000 +1100 -+++ linux-2.6.37-ck2/arch/x86/kernel/cpu/proc.c 2011-02-14 10:11:10.919252001 +1100 -@@ -109,7 +109,7 @@ - - seq_printf(m, "\nbogomips\t: %lu.%02lu\n", - c->loops_per_jiffy/(500000/HZ), -- (c->loops_per_jiffy/(5000/HZ)) % 100); -+ (c->loops_per_jiffy * 10 /(50000/HZ)) % 100); - - #ifdef CONFIG_X86_64 - if (c->x86_tlbsize > 0) -Index: linux-2.6.37-ck2/arch/x86/kernel/smpboot.c -=================================================================== ---- linux-2.6.37-ck2.orig/arch/x86/kernel/smpboot.c 2011-01-06 14:04:08.000000000 +1100 -+++ linux-2.6.37-ck2/arch/x86/kernel/smpboot.c 2011-02-14 10:11:10.920252001 +1100 -@@ -497,7 +497,7 @@ - "Total of %d processors activated (%lu.%02lu BogoMIPS).\n", - num_online_cpus(), - bogosum/(500000/HZ), -- (bogosum/(5000/HZ))%100); -+ (bogosum * 10/(50000/HZ))%100); - - pr_debug("Before bogocount - setting activated=1.\n"); - } -Index: linux-2.6.37-ck2/include/linux/nfsd/stats.h -=================================================================== ---- linux-2.6.37-ck2.orig/include/linux/nfsd/stats.h 2009-06-10 13:05:27.000000000 +1000 -+++ linux-2.6.37-ck2/include/linux/nfsd/stats.h 2011-02-14 10:11:10.920252001 +1100 -@@ -11,8 +11,8 @@ - - #include - --/* thread usage wraps very million seconds (approx one fortnight) */ --#define NFSD_USAGE_WRAP (HZ*1000000) -+/* thread usage wraps every one hundred thousand seconds (approx one day) */ -+#define NFSD_USAGE_WRAP (HZ*100000) - - #ifdef __KERNEL__ - -Index: linux-2.6.37-ck2/include/net/inet_timewait_sock.h -=================================================================== ---- linux-2.6.37-ck2.orig/include/net/inet_timewait_sock.h 2010-08-02 11:12:25.000000000 +1000 -+++ linux-2.6.37-ck2/include/net/inet_timewait_sock.h 2011-02-14 10:11:10.920252001 +1100 -@@ -39,8 +39,8 @@ - * If time > 4sec, it is "slow" path, no recycling is required, - * so that we select tick to get range about 4 seconds. - */ --#if HZ <= 16 || HZ > 4096 --# error Unsupported: HZ <= 16 or HZ > 4096 -+#if HZ <= 16 || HZ > 16384 -+# error Unsupported: HZ <= 16 or HZ > 16384 - #elif HZ <= 32 - # define INET_TWDR_RECYCLE_TICK (5 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG) - #elif HZ <= 64 -@@ -55,8 +55,12 @@ - # define INET_TWDR_RECYCLE_TICK (10 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG) - #elif HZ <= 2048 - # define INET_TWDR_RECYCLE_TICK (11 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG) --#else -+#elif HZ <= 4096 - # define INET_TWDR_RECYCLE_TICK (12 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG) -+#elif HZ <= 8192 -+# define INET_TWDR_RECYCLE_TICK (13 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG) -+#else -+# define INET_TWDR_RECYCLE_TICK (14 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG) - #endif - - /* TIME_WAIT reaping mechanism. */ -Index: linux-2.6.37-ck2/init/calibrate.c -=================================================================== ---- linux-2.6.37-ck2.orig/init/calibrate.c 2010-02-25 21:51:52.000000000 +1100 -+++ linux-2.6.37-ck2/init/calibrate.c 2011-02-14 10:11:10.921252001 +1100 -@@ -176,7 +176,7 @@ - if (!printed) - pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n", - loops_per_jiffy/(500000/HZ), -- (loops_per_jiffy/(5000/HZ)) % 100, loops_per_jiffy); -+ (loops_per_jiffy * 10 /(50000/HZ)) % 100, loops_per_jiffy); - - printed = true; - } -Index: linux-2.6.37-ck2/kernel/Kconfig.hz -=================================================================== ---- linux-2.6.37-ck2.orig/kernel/Kconfig.hz 2011-02-14 10:11:10.702252000 +1100 -+++ linux-2.6.37-ck2/kernel/Kconfig.hz 2011-02-14 10:11:10.921252001 +1100 -@@ -48,6 +48,63 @@ - can also benefit from this choice without sacrificing battery life - if dynticks is also enabled. - -+ config HZ_1500 -+ bool "1500 HZ" -+ help -+ 1500 Hz is an insane value to use to run broken software that is Hz -+ limited. -+ -+ Being over 1000, driver breakage is likely. -+ -+ config HZ_2000 -+ bool "2000 HZ" -+ help -+ 2000 Hz is an insane value to use to run broken software that is Hz -+ limited. -+ -+ Being over 1000, driver breakage is likely. -+ -+ config HZ_3000 -+ bool "3000 HZ" -+ help -+ 3000 Hz is an insane value to use to run broken software that is Hz -+ limited. -+ -+ Being over 1000, driver breakage is likely. -+ -+ config HZ_4000 -+ bool "4000 HZ" -+ help -+ 4000 Hz is an insane value to use to run broken software that is Hz -+ limited. -+ -+ Being over 1000, driver breakage is likely. -+ -+ config HZ_5000 -+ bool "5000 HZ" -+ help -+ 5000 Hz is an obscene value to use to run broken software that is Hz -+ limited. -+ -+ Being over 1000, driver breakage is likely. -+ -+ config HZ_7500 -+ bool "7500 HZ" -+ help -+ 7500 Hz is an obscene value to use to run broken software that is Hz -+ limited. -+ -+ Being over 1000, driver breakage is likely. -+ -+ config HZ_10000 -+ bool "10000 HZ" -+ help -+ 10000 Hz is an obscene value to use to run broken software that is Hz -+ limited. -+ -+ Being over 1000, driver breakage is likely. -+ -+ - endchoice - - config HZ -@@ -56,6 +113,13 @@ - default 250 if HZ_250_NODEFAULT - default 300 if HZ_300 - default 1000 if HZ_1000 -+ default 1500 if HZ_1500 -+ default 2000 if HZ_2000 -+ default 3000 if HZ_3000 -+ default 4000 if HZ_4000 -+ default 5000 if HZ_5000 -+ default 7500 if HZ_7500 -+ default 10000 if HZ_10000 - - config SCHED_HRTICK - def_bool HIGH_RES_TIMERS && (!SMP || USE_GENERIC_SMP_HELPERS) diff --git a/packages/linux/patches/linux-2.6.37.1-707_kconfig-expose_vmsplit_option.patch b/packages/linux/patches/linux-2.6.37.1-707_kconfig-expose_vmsplit_option.patch deleted file mode 100644 index 937cf72f31..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-707_kconfig-expose_vmsplit_option.patch +++ /dev/null @@ -1,40 +0,0 @@ ---- - arch/x86/Kconfig | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -Index: linux-2.6.37-ck2/arch/x86/Kconfig -=================================================================== ---- linux-2.6.37-ck2.orig/arch/x86/Kconfig 2011-01-06 14:04:08.000000000 +1100 -+++ linux-2.6.37-ck2/arch/x86/Kconfig 2011-02-14 10:11:10.260252001 +1100 -@@ -1046,7 +1046,7 @@ - - choice - depends on EXPERIMENTAL -- prompt "Memory split" if EMBEDDED -+ prompt "Memory split" - default VMSPLIT_3G - depends on X86_32 - ---help--- -@@ -1066,17 +1066,17 @@ - option alone! - - config VMSPLIT_3G -- bool "3G/1G user/kernel split" -+ bool "Default 896MB lowmem (3G/1G user/kernel split)" - config VMSPLIT_3G_OPT - depends on !X86_PAE -- bool "3G/1G user/kernel split (for full 1G low memory)" -+ bool "1GB lowmem (3G/1G user/kernel split)" - config VMSPLIT_2G -- bool "2G/2G user/kernel split" -+ bool "2GB lowmem (2G/2G user/kernel split)" - config VMSPLIT_2G_OPT - depends on !X86_PAE -- bool "2G/2G user/kernel split (for full 2G low memory)" -+ bool "2GB lowmem (2G/2G user/kernel split)" - config VMSPLIT_1G -- bool "1G/3G user/kernel split" -+ bool "3GB lowmem (1G/3G user/kernel split)" - endchoice - - config PAGE_OFFSET diff --git a/packages/linux/patches/linux-2.6.37.1-708_mm-kswapd_inherit_prio-1.patch.ignore b/packages/linux/patches/linux-2.6.37.1-708_mm-kswapd_inherit_prio-1.patch.ignore deleted file mode 100644 index 04d3712fe7..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-708_mm-kswapd_inherit_prio-1.patch.ignore +++ /dev/null @@ -1,69 +0,0 @@ ---- - mm/vmscan.c | 33 ++++++++++++++++++++++++++++++++- - 1 file changed, 32 insertions(+), 1 deletion(-) - -Index: linux-2.6.37-ck2/mm/vmscan.c -=================================================================== ---- linux-2.6.37-ck2.orig/mm/vmscan.c 2011-02-14 10:11:00.986252001 +1100 -+++ linux-2.6.37-ck2/mm/vmscan.c 2011-02-14 10:11:01.254252001 +1100 -@@ -1855,6 +1855,33 @@ - } - - /* -+ * Helper functions to adjust nice level of kswapd, based on the priority of -+ * the task (p) that called it. If it is already higher priority we do not -+ * demote its nice level since it is still working on behalf of a higher -+ * priority task. With kernel threads we leave it at nice 0. -+ * -+ * We don't ever run kswapd real time, so if a real time task calls kswapd we -+ * set it to highest SCHED_NORMAL priority. -+ */ -+static inline int effective_sc_prio(struct task_struct *p) -+{ -+ if (likely(p->mm)) { -+ if (rt_task(p)) -+ return -20; -+ return task_nice(p); -+ } -+ return 0; -+} -+ -+static void set_kswapd_nice(struct task_struct *kswapd, int active) -+{ -+ long nice = effective_sc_prio(current); -+ -+ if (task_nice(kswapd) > nice || !active) -+ set_user_nice(kswapd, nice); -+} -+ -+/* - * This is the direct reclaim path, for page-allocating processes. We only - * try to reclaim pages from zones which will satisfy the caller's allocation - * request. -@@ -2457,6 +2484,7 @@ - } - } - -+ set_user_nice(tsk, 0); - order = pgdat->kswapd_max_order; - } - finish_wait(&pgdat->kswapd_wait, &wait); -@@ -2483,6 +2511,7 @@ - void wakeup_kswapd(struct zone *zone, int order) - { - pg_data_t *pgdat; -+ int active; - - if (!populated_zone(zone)) - return; -@@ -2495,7 +2524,9 @@ - trace_mm_vmscan_wakeup_kswapd(pgdat->node_id, zone_idx(zone), order); - if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL)) - return; -- if (!waitqueue_active(&pgdat->kswapd_wait)) -+ active = waitqueue_active(&pgdat->kswapd_wait); -+ set_kswapd_nice(pgdat->kswapd, active); -+ if (!active) - return; - wake_up_interruptible(&pgdat->kswapd_wait); - } diff --git a/packages/linux/patches/linux-2.6.37.1-709_mm-decrease_default_dirty_ratio.patch b/packages/linux/patches/linux-2.6.37.1-709_mm-decrease_default_dirty_ratio.patch deleted file mode 100644 index 804bccfcd4..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-709_mm-decrease_default_dirty_ratio.patch +++ /dev/null @@ -1,34 +0,0 @@ -The default dirty ratio is chosen to be a compromise between throughput and -overall system latency. On a desktop, if an application writes to disk a lot, -that application should be the one to slow down rather than the desktop as a -whole. At higher dirty ratio settings, an application could write a lot to -disk and then happily use lots of CPU time after that while the rest of the -system is busy waiting on that naughty applications disk writes to complete -before anything else happening. - -Lower ratios mean that the application that do a lot of disk writes end up -being responsible for their own actions and they're the ones that slow down -rather than the system in general. - -This does decrease overall write throughput slightly, but to the benefit of -the latency of the system as a whole. - --ck - ---- - mm/page-writeback.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Index: linux-2.6.37-ck2/mm/page-writeback.c -=================================================================== ---- linux-2.6.37-ck2.orig/mm/page-writeback.c 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/mm/page-writeback.c 2011-02-14 10:11:10.037252000 +1100 -@@ -78,7 +78,7 @@ - /* - * The generator of dirty data starts writeback at this percentage - */ --int vm_dirty_ratio = 20; -+int vm_dirty_ratio = 5; - - /* - * vm_dirty_bytes starts at 0 (disabled) so that it is a function of diff --git a/packages/linux/patches/linux-2.6.37.1-710_mm-drop_swap_cache_aggressively.patch b/packages/linux/patches/linux-2.6.37.1-710_mm-drop_swap_cache_aggressively.patch deleted file mode 100644 index 2cd9f63b62..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-710_mm-drop_swap_cache_aggressively.patch +++ /dev/null @@ -1,87 +0,0 @@ ---- - include/linux/swap.h | 2 +- - mm/memory.c | 2 +- - mm/swapfile.c | 9 ++++----- - mm/vmscan.c | 2 +- - 4 files changed, 7 insertions(+), 8 deletions(-) - -Index: linux-2.6.37-ck2/include/linux/swap.h -=================================================================== ---- linux-2.6.37-ck2.orig/include/linux/swap.h 2011-02-14 10:11:00.763252001 +1100 -+++ linux-2.6.37-ck2/include/linux/swap.h 2011-02-14 10:11:00.982252001 +1100 -@@ -192,7 +192,7 @@ - int next; /* swapfile to be used next */ - }; - --/* Swap 50% full? Release swapcache more aggressively.. */ -+/* Swap 50% full? */ - #define vm_swap_full() (nr_swap_pages*2 < total_swap_pages) - - /* linux/mm/page_alloc.c */ -Index: linux-2.6.37-ck2/mm/memory.c -=================================================================== ---- linux-2.6.37-ck2.orig/mm/memory.c 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/mm/memory.c 2011-02-14 10:11:00.984252001 +1100 -@@ -2754,7 +2754,7 @@ - mem_cgroup_commit_charge_swapin(page, ptr); - - swap_free(entry); -- if (vm_swap_full() || (vma->vm_flags & VM_LOCKED) || PageMlocked(page)) -+ if ((vma->vm_flags & VM_LOCKED) || PageMlocked(page)) - try_to_free_swap(page); - unlock_page(page); - if (swapcache) { -Index: linux-2.6.37-ck2/mm/swapfile.c -=================================================================== ---- linux-2.6.37-ck2.orig/mm/swapfile.c 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/mm/swapfile.c 2011-02-14 10:11:00.985252001 +1100 -@@ -321,7 +321,7 @@ - scan_base = offset = si->lowest_bit; - - /* reuse swap entry of cache-only swap if not busy. */ -- if (vm_swap_full() && si->swap_map[offset] == SWAP_HAS_CACHE) { -+ if (si->swap_map[offset] == SWAP_HAS_CACHE) { - int swap_was_freed; - spin_unlock(&swap_lock); - swap_was_freed = __try_to_reclaim_swap(si, offset); -@@ -410,7 +410,7 @@ - spin_lock(&swap_lock); - goto checks; - } -- if (vm_swap_full() && si->swap_map[offset] == SWAP_HAS_CACHE) { -+ if (si->swap_map[offset] == SWAP_HAS_CACHE) { - spin_lock(&swap_lock); - goto checks; - } -@@ -425,7 +425,7 @@ - spin_lock(&swap_lock); - goto checks; - } -- if (vm_swap_full() && si->swap_map[offset] == SWAP_HAS_CACHE) { -+ if (si->swap_map[offset] == SWAP_HAS_CACHE) { - spin_lock(&swap_lock); - goto checks; - } -@@ -739,8 +739,7 @@ - * Not mapped elsewhere, or swap space full? Free it! - * Also recheck PageSwapCache now page is locked (above). - */ -- if (PageSwapCache(page) && !PageWriteback(page) && -- (!page_mapped(page) || vm_swap_full())) { -+ if (PageSwapCache(page) && !PageWriteback(page)) { - delete_from_swap_cache(page); - SetPageDirty(page); - } -Index: linux-2.6.37-ck2/mm/vmscan.c -=================================================================== ---- linux-2.6.37-ck2.orig/mm/vmscan.c 2011-02-14 10:11:00.536252000 +1100 -+++ linux-2.6.37-ck2/mm/vmscan.c 2011-02-14 10:11:00.986252001 +1100 -@@ -900,7 +900,7 @@ - - activate_locked: - /* Not a candidate for swapping, so reclaim swap space. */ -- if (PageSwapCache(page) && vm_swap_full()) -+ if (PageSwapCache(page)) - try_to_free_swap(page); - VM_BUG_ON(PageActive(page)); - SetPageActive(page); diff --git a/packages/linux/patches/linux-2.6.37.1-711_mm-enable_swaptoken_only_when_swap_full.patch b/packages/linux/patches/linux-2.6.37.1-711_mm-enable_swaptoken_only_when_swap_full.patch deleted file mode 100644 index f7f76ea318..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-711_mm-enable_swaptoken_only_when_swap_full.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- - include/linux/swap.h | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -Index: linux-2.6.37-ck2/include/linux/swap.h -=================================================================== ---- linux-2.6.37-ck2.orig/include/linux/swap.h 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/include/linux/swap.h 2011-02-14 10:11:00.763252001 +1100 -@@ -348,9 +348,10 @@ - extern void grab_swap_token(struct mm_struct *); - extern void __put_swap_token(struct mm_struct *); - -+/* Only allow swap token to have effect if swap is full */ - static inline int has_swap_token(struct mm_struct *mm) - { -- return (mm == swap_token_mm); -+ return (mm == swap_token_mm && vm_swap_full()); - } - - static inline void put_swap_token(struct mm_struct *mm) diff --git a/packages/linux/patches/linux-2.6.37.1-712_mm-background_scan.patch b/packages/linux/patches/linux-2.6.37.1-712_mm-background_scan.patch deleted file mode 100644 index c84d37d1af..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-712_mm-background_scan.patch +++ /dev/null @@ -1,137 +0,0 @@ ---- - include/linux/mmzone.h | 6 +++++- - mm/vmscan.c | 42 ++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 47 insertions(+), 1 deletion(-) - -Index: linux-2.6.37-ck2/include/linux/mmzone.h -=================================================================== ---- linux-2.6.37-ck2.orig/include/linux/mmzone.h 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/include/linux/mmzone.h 2011-02-14 10:11:01.470252001 +1100 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -161,12 +162,14 @@ - WMARK_MIN, - WMARK_LOW, - WMARK_HIGH, -+ WMARK_LOTS, - NR_WMARK - }; - - #define min_wmark_pages(z) (z->watermark[WMARK_MIN]) - #define low_wmark_pages(z) (z->watermark[WMARK_LOW]) - #define high_wmark_pages(z) (z->watermark[WMARK_HIGH]) -+#define lots_wmark_pages(z) (z->watermark[WMARK_LOTS]) - - struct per_cpu_pages { - int count; /* number of pages in the list */ -@@ -343,7 +346,7 @@ - ZONE_PADDING(_pad1_) - - /* Fields commonly accessed by the page reclaim scanner */ -- spinlock_t lru_lock; -+ spinlock_t lru_lock; - struct zone_lru { - struct list_head list; - } lru[NR_LRU_LISTS]; -@@ -645,6 +648,7 @@ - wait_queue_head_t kswapd_wait; - struct task_struct *kswapd; - int kswapd_max_order; -+ struct timer_list watermark_timer; - } pg_data_t; - - #define node_present_pages(nid) (NODE_DATA(nid)->node_present_pages) -Index: linux-2.6.37-ck2/mm/vmscan.c -=================================================================== ---- linux-2.6.37-ck2.orig/mm/vmscan.c 2011-02-14 10:11:01.254252001 +1100 -+++ linux-2.6.37-ck2/mm/vmscan.c 2011-02-14 10:11:01.471252001 +1100 -@@ -36,6 +36,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -2398,6 +2399,8 @@ - return sc.nr_reclaimed; - } - -+#define WT_EXPIRY (HZ * 5) /* Time to wakeup watermark_timer */ -+ - /* - * The background pageout daemon, started as a kernel thread - * from the init process. -@@ -2448,6 +2451,8 @@ - unsigned long new_order; - int ret; - -+ /* kswapd has been busy so delay watermark_timer */ -+ mod_timer(&pgdat->watermark_timer, jiffies + WT_EXPIRY); - prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE); - new_order = pgdat->kswapd_max_order; - pgdat->kswapd_max_order = 0; -@@ -2632,20 +2637,57 @@ - } - - /* -+ * We wake up kswapd every WT_EXPIRY till free ram is above pages_lots -+ */ -+static void watermark_wakeup(unsigned long data) -+{ -+ pg_data_t *pgdat = (pg_data_t *)data; -+ struct timer_list *wt = &pgdat->watermark_timer; -+ int i; -+ -+ if (!waitqueue_active(&pgdat->kswapd_wait) || above_background_load()) -+ goto out; -+ for (i = pgdat->nr_zones - 1; i >= 0; i--) { -+ struct zone *z = pgdat->node_zones + i; -+ -+ if (!populated_zone(z) || is_highmem(z)) { -+ /* We are better off leaving highmem full */ -+ continue; -+ } -+ if (!zone_watermark_ok(z, 0, lots_wmark_pages(z), 0, 0)) { -+ wake_up_interruptible(&pgdat->kswapd_wait); -+ goto out; -+ } -+ } -+out: -+ mod_timer(wt, jiffies + WT_EXPIRY); -+ return; -+} -+ -+/* - * This kswapd start function will be called by init and node-hot-add. - * On node-hot-add, kswapd will moved to proper cpus if cpus are hot-added. - */ - int kswapd_run(int nid) - { - pg_data_t *pgdat = NODE_DATA(nid); -+ struct timer_list *wt; - int ret = 0; - - if (pgdat->kswapd) - return 0; - -+ wt = &pgdat->watermark_timer; -+ init_timer(wt); -+ wt->data = (unsigned long)pgdat; -+ wt->function = watermark_wakeup; -+ wt->expires = jiffies + WT_EXPIRY; -+ add_timer(wt); -+ - pgdat->kswapd = kthread_run(kswapd, pgdat, "kswapd%d", nid); - if (IS_ERR(pgdat->kswapd)) { - /* failure at boot is fatal */ -+ del_timer(wt); - BUG_ON(system_state == SYSTEM_BOOTING); - printk("Failed to start kswapd on node %d\n",nid); - ret = -1; diff --git a/packages/linux/patches/linux-2.6.37.1-713_mm-idleprio_prio-1.patch.ignore b/packages/linux/patches/linux-2.6.37.1-713_mm-idleprio_prio-1.patch.ignore deleted file mode 100644 index f0ca19b956..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-713_mm-idleprio_prio-1.patch.ignore +++ /dev/null @@ -1,33 +0,0 @@ ---- - include/linux/sched.h | 2 +- - mm/vmscan.c | 2 ++ - 2 files changed, 3 insertions(+), 1 deletion(-) - -Index: linux-2.6.37-ck1/include/linux/sched.h -=================================================================== ---- linux-2.6.37-ck1.orig/include/linux/sched.h 2011-01-06 14:07:19.971048973 +1100 -+++ linux-2.6.37-ck1/include/linux/sched.h 2011-01-06 14:07:58.442334300 +1100 -@@ -38,9 +38,9 @@ - #define SCHED_BATCH 3 - /* SCHED_ISO: Implemented on BFS only */ - #define SCHED_IDLE 5 -+#define SCHED_IDLEPRIO SCHED_IDLE - #ifdef CONFIG_SCHED_BFS - #define SCHED_ISO 4 --#define SCHED_IDLEPRIO SCHED_IDLE - #define SCHED_MAX (SCHED_IDLEPRIO) - #define SCHED_RANGE(policy) ((policy) <= SCHED_MAX) - #endif -Index: linux-2.6.37-ck1/mm/vmscan.c -=================================================================== ---- linux-2.6.37-ck1.orig/mm/vmscan.c 2011-01-06 14:07:58.305326159 +1100 -+++ linux-2.6.37-ck1/mm/vmscan.c 2011-01-06 14:07:58.443334359 +1100 -@@ -1874,6 +1874,8 @@ static inline int effective_sc_prio(stru - if (likely(p->mm)) { - if (rt_task(p)) - return -20; -+ if (p->policy == SCHED_IDLEPRIO) -+ return 19; - return task_nice(p); - } - return 0; diff --git a/packages/linux/patches/linux-2.6.37.1-714_mm-lru_cache_add_lru_tail.patch b/packages/linux/patches/linux-2.6.37.1-714_mm-lru_cache_add_lru_tail.patch deleted file mode 100644 index 98cf2994f4..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-714_mm-lru_cache_add_lru_tail.patch +++ /dev/null @@ -1,250 +0,0 @@ ---- - include/linux/mm_inline.h | 14 +++++++++++- - include/linux/swap.h | 8 ++++++- - mm/filemap.c | 50 +++++++++++++++++++++++++++++++++++++++------- - mm/swap.c | 30 ++++++++++++++++++++++----- - 4 files changed, 86 insertions(+), 16 deletions(-) - -Index: linux-2.6.37-ck2/include/linux/mm_inline.h -=================================================================== ---- linux-2.6.37-ck2.orig/include/linux/mm_inline.h 2009-12-03 21:40:09.000000000 +1100 -+++ linux-2.6.37-ck2/include/linux/mm_inline.h 2011-02-14 10:11:09.770252000 +1100 -@@ -20,14 +20,24 @@ - } - - static inline void --add_page_to_lru_list(struct zone *zone, struct page *page, enum lru_list l) -+__add_page_to_lru_list(struct zone *zone, struct page *page, enum lru_list l, int tail) - { -- list_add(&page->lru, &zone->lru[l].list); -+ /* See if this should be added to the tail of this lru list */ -+ if (tail) -+ list_add_tail(&page->lru, &zone->lru[l].list); -+ else -+ list_add(&page->lru, &zone->lru[l].list); - __inc_zone_state(zone, NR_LRU_BASE + l); - mem_cgroup_add_lru_list(page, l); - } - - static inline void -+add_page_to_lru_list(struct zone *zone, struct page *page, enum lru_list l) -+{ -+ __add_page_to_lru_list(zone, page, l, 0); -+} -+ -+static inline void - del_page_from_lru_list(struct zone *zone, struct page *page, enum lru_list l) - { - list_del(&page->lru); -Index: linux-2.6.37-ck2/include/linux/swap.h -=================================================================== ---- linux-2.6.37-ck2.orig/include/linux/swap.h 2011-02-14 10:11:00.982252001 +1100 -+++ linux-2.6.37-ck2/include/linux/swap.h 2011-02-14 10:11:09.770252000 +1100 -@@ -206,6 +206,7 @@ - - - /* linux/mm/swap.c */ -+extern void ____lru_cache_add(struct page *, enum lru_list lru, int tail); - extern void __lru_cache_add(struct page *, enum lru_list lru); - extern void lru_cache_add_lru(struct page *, enum lru_list lru); - extern void activate_page(struct page *); -@@ -226,9 +227,14 @@ - __lru_cache_add(page, LRU_INACTIVE_ANON); - } - -+static inline void lru_cache_add_file_tail(struct page *page, int tail) -+{ -+ ____lru_cache_add(page, LRU_INACTIVE_FILE, tail); -+} -+ - static inline void lru_cache_add_file(struct page *page) - { -- __lru_cache_add(page, LRU_INACTIVE_FILE); -+ ____lru_cache_add(page, LRU_INACTIVE_FILE, 0); - } - - /* LRU Isolation modes. */ -Index: linux-2.6.37-ck2/mm/filemap.c -=================================================================== ---- linux-2.6.37-ck2.orig/mm/filemap.c 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/mm/filemap.c 2011-02-14 10:11:09.772252000 +1100 -@@ -439,8 +439,8 @@ - } - EXPORT_SYMBOL(add_to_page_cache_locked); - --int add_to_page_cache_lru(struct page *page, struct address_space *mapping, -- pgoff_t offset, gfp_t gfp_mask) -+int __add_to_page_cache_lru(struct page *page, struct address_space *mapping, -+ pgoff_t offset, gfp_t gfp_mask, int tail) - { - int ret; - -@@ -456,12 +456,18 @@ - ret = add_to_page_cache(page, mapping, offset, gfp_mask); - if (ret == 0) { - if (page_is_file_cache(page)) -- lru_cache_add_file(page); -+ lru_cache_add_file_tail(page, tail); - else - lru_cache_add_anon(page); - } - return ret; - } -+ -+int add_to_page_cache_lru(struct page *page, struct address_space *mapping, -+ pgoff_t offset, gfp_t gfp_mask) -+{ -+ return __add_to_page_cache_lru(page, mapping, offset, gfp_mask, 0); -+} - EXPORT_SYMBOL_GPL(add_to_page_cache_lru); - - #ifdef CONFIG_NUMA -@@ -968,6 +974,28 @@ - ra->ra_pages /= 4; - } - -+static inline int nr_mapped(void) -+{ -+ return global_page_state(NR_FILE_MAPPED) + -+ global_page_state(NR_ANON_PAGES); -+} -+ -+/* -+ * This examines how large in pages a file size is and returns 1 if it is -+ * more than half the unmapped ram. Avoid doing read_page_state which is -+ * expensive unless we already know it is likely to be large enough. -+ */ -+static int large_isize(unsigned long nr_pages) -+{ -+ if (nr_pages * 6 > vm_total_pages) { -+ unsigned long unmapped_ram = vm_total_pages - nr_mapped(); -+ -+ if (nr_pages * 2 > unmapped_ram) -+ return 1; -+ } -+ return 0; -+} -+ - /** - * do_generic_file_read - generic file read routine - * @filp: the file to read -@@ -992,7 +1020,7 @@ - pgoff_t prev_index; - unsigned long offset; /* offset into pagecache page */ - unsigned int prev_offset; -- int error; -+ int error, tail = 0; - - index = *ppos >> PAGE_CACHE_SHIFT; - prev_index = ra->prev_pos >> PAGE_CACHE_SHIFT; -@@ -1003,7 +1031,7 @@ - for (;;) { - struct page *page; - pgoff_t end_index; -- loff_t isize; -+ loff_t isize = 0; - unsigned long nr, ret; - - cond_resched(); -@@ -1177,8 +1205,16 @@ - desc->error = -ENOMEM; - goto out; - } -- error = add_to_page_cache_lru(page, mapping, -- index, GFP_KERNEL); -+ /* -+ * If we know the file is large we add the pages read to the -+ * end of the lru as we're unlikely to be able to cache the -+ * whole file in ram so make those pages the first to be -+ * dropped if not referenced soon. -+ */ -+ if (large_isize(end_index)) -+ tail = 1; -+ error = __add_to_page_cache_lru(page, mapping, -+ index, GFP_KERNEL, tail); - if (error) { - page_cache_release(page); - if (error == -EEXIST) -Index: linux-2.6.37-ck2/mm/swap.c -=================================================================== ---- linux-2.6.37-ck2.orig/mm/swap.c 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/mm/swap.c 2011-02-14 10:11:09.772252000 +1100 -@@ -215,15 +215,23 @@ - - EXPORT_SYMBOL(mark_page_accessed); - --void __lru_cache_add(struct page *page, enum lru_list lru) -+void ______pagevec_lru_add(struct pagevec *pvec, enum lru_list lru, int tail); -+ -+void ____lru_cache_add(struct page *page, enum lru_list lru, int tail) - { - struct pagevec *pvec = &get_cpu_var(lru_add_pvecs)[lru]; - - page_cache_get(page); - if (!pagevec_add(pvec, page)) -- ____pagevec_lru_add(pvec, lru); -+ ______pagevec_lru_add(pvec, lru, tail); - put_cpu_var(lru_add_pvecs); - } -+EXPORT_SYMBOL(____lru_cache_add); -+ -+void __lru_cache_add(struct page *page, enum lru_list lru) -+{ -+ ____lru_cache_add(page, lru, 0); -+} - EXPORT_SYMBOL(__lru_cache_add); - - /** -@@ -231,7 +239,7 @@ - * @page: the page to be added to the LRU. - * @lru: the LRU list to which the page is added. - */ --void lru_cache_add_lru(struct page *page, enum lru_list lru) -+void __lru_cache_add_lru(struct page *page, enum lru_list lru, int tail) - { - if (PageActive(page)) { - VM_BUG_ON(PageUnevictable(page)); -@@ -242,7 +250,12 @@ - } - - VM_BUG_ON(PageLRU(page) || PageActive(page) || PageUnevictable(page)); -- __lru_cache_add(page, lru); -+ ____lru_cache_add(page, lru, tail); -+} -+ -+void lru_cache_add_lru(struct page *page, enum lru_list lru) -+{ -+ __lru_cache_add_lru(page, lru, 0); - } - - /** -@@ -403,7 +416,7 @@ - * Add the passed pages to the LRU, then drop the caller's refcount - * on them. Reinitialises the caller's pagevec. - */ --void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru) -+void ______pagevec_lru_add(struct pagevec *pvec, enum lru_list lru, int tail) - { - int i; - struct zone *zone = NULL; -@@ -431,7 +444,7 @@ - if (active) - SetPageActive(page); - update_page_reclaim_stat(zone, page, file, active); -- add_page_to_lru_list(zone, page, lru); -+ __add_page_to_lru_list(zone, page, lru, tail); - } - if (zone) - spin_unlock_irq(&zone->lru_lock); -@@ -439,6 +452,11 @@ - pagevec_reinit(pvec); - } - -+void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru) -+{ -+ ______pagevec_lru_add(pvec, lru, 0); -+} -+ - EXPORT_SYMBOL(____pagevec_lru_add); - - /* diff --git a/packages/linux/patches/linux-2.6.37.1-715_mm-make_swappiness_really_mean_it.patch.ignore b/packages/linux/patches/linux-2.6.37.1-715_mm-make_swappiness_really_mean_it.patch.ignore deleted file mode 100644 index 0edb5daa86..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-715_mm-make_swappiness_really_mean_it.patch.ignore +++ /dev/null @@ -1,29 +0,0 @@ ---- - mm/vmscan.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -Index: linux-2.6.37-ck1/mm/vmscan.c -=================================================================== ---- linux-2.6.37-ck1.orig/mm/vmscan.c 2011-01-06 14:04:10.584810957 +1100 -+++ linux-2.6.37-ck1/mm/vmscan.c 2011-01-06 14:07:57.629285994 +1100 -@@ -1718,6 +1718,7 @@ static void get_scan_count(struct zone * - u64 fraction[2], denominator; - enum lru_list l; - int noswap = 0; -+ int tmp_priority; - - /* If we have no swap space, do not bother scanning anon pages. */ - if (!sc->may_swap || (nr_swap_pages <= 0)) { -@@ -1796,7 +1797,11 @@ out: - - scan = zone_nr_lru_pages(zone, sc, l); - if (priority || noswap) { -- scan >>= priority; -+ tmp_priority = priority; -+ -+ if (file && priority > 0) -+ tmp_priority = DEF_PRIORITY; -+ scan >>= tmp_priority; - scan = div64_u64(scan * fraction[file], denominator); - } - nr[l] = nr_scan_try_batch(scan, diff --git a/packages/linux/patches/linux-2.6.37.1-716_mm-zero_swappiness.patch b/packages/linux/patches/linux-2.6.37.1-716_mm-zero_swappiness.patch deleted file mode 100644 index fad5b48936..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-716_mm-zero_swappiness.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- - mm/vmscan.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Index: linux-2.6.37-ck2/mm/vmscan.c -=================================================================== ---- linux-2.6.37-ck2.orig/mm/vmscan.c 2011-01-06 14:04:10.000000000 +1100 -+++ linux-2.6.37-ck2/mm/vmscan.c 2011-02-14 10:11:00.536252000 +1100 -@@ -133,7 +133,7 @@ - /* - * From 0 .. 100. Higher means more swappy. - */ --int vm_swappiness = 60; -+int vm_swappiness; - long vm_total_pages; /* The total number of pages which the VM controls */ - - static LIST_HEAD(shrinker_list); diff --git a/packages/linux/patches/linux-2.6.37.1-717_preempt-desktop-tune.patch b/packages/linux/patches/linux-2.6.37.1-717_preempt-desktop-tune.patch deleted file mode 100644 index 89d3f3aead..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-717_preempt-desktop-tune.patch +++ /dev/null @@ -1,36 +0,0 @@ ---- - kernel/Kconfig.preempt | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -Index: linux-2.6.37-ck2/kernel/Kconfig.preempt -=================================================================== ---- linux-2.6.37-ck2.orig/kernel/Kconfig.preempt 2009-06-10 13:05:27.000000000 +1000 -+++ linux-2.6.37-ck2/kernel/Kconfig.preempt 2011-02-14 10:11:11.217252001 +1100 -@@ -1,7 +1,7 @@ - - choice - prompt "Preemption Model" -- default PREEMPT_NONE -+ default PREEMPT - - config PREEMPT_NONE - bool "No Forced Preemption (Server)" -@@ -17,7 +17,7 @@ - latencies. - - config PREEMPT_VOLUNTARY -- bool "Voluntary Kernel Preemption (Desktop)" -+ bool "Voluntary Kernel Preemption (Nothing)" - help - This option reduces the latency of the kernel by adding more - "explicit preemption points" to the kernel code. These new -@@ -31,7 +31,8 @@ - applications to run more 'smoothly' even when the system is - under load. - -- Select this if you are building a kernel for a desktop system. -+ Select this for no system in particular (choose Preemptible -+ instead on a desktop if you know what's good for you). - - config PREEMPT - bool "Preemptible Kernel (Low-Latency Desktop)" diff --git a/packages/linux/patches/linux-2.6.37.1-718_sched-add-above-background-load-function.patch b/packages/linux/patches/linux-2.6.37.1-718_sched-add-above-background-load-function.patch deleted file mode 100644 index ea1c1fa5b1..0000000000 --- a/packages/linux/patches/linux-2.6.37.1-718_sched-add-above-background-load-function.patch +++ /dev/null @@ -1,61 +0,0 @@ ---- - include/linux/sched.h | 7 +++++++ - kernel/sched_bfs.c | 20 ++++++++++++++++++++ - 2 files changed, 27 insertions(+) - -Index: linux-2.6.37-ck2/include/linux/sched.h -=================================================================== ---- linux-2.6.37-ck2.orig/include/linux/sched.h 2011-02-14 09:47:50.988252000 +1100 -+++ linux-2.6.37-ck2/include/linux/sched.h 2011-02-14 10:11:00.292251999 +1100 -@@ -1558,6 +1558,7 @@ - return (p->policy == SCHED_ISO); - } - extern void remove_cpu(unsigned long cpu); -+extern int above_background_load(void); - #else /* CFS */ - extern int runqueue_is_locked(int cpu); - #define tsk_seruntime(t) ((t)->se.sum_exec_runtime) -@@ -1581,6 +1582,12 @@ - static inline void remove_cpu(unsigned long cpu) - { - } -+ -+/* Anyone feel like implementing this? */ -+static inline int above_background_load(void) -+{ -+ return 1; -+} - #endif /* CONFIG_SCHED_BFS */ - - /* Future-safe accessor for struct task_struct's cpus_allowed. */ -Index: linux-2.6.37-ck2/kernel/sched_bfs.c -=================================================================== ---- linux-2.6.37-ck2.orig/kernel/sched_bfs.c 2011-02-14 09:53:53.820252000 +1100 -+++ linux-2.6.37-ck2/kernel/sched_bfs.c 2011-02-14 10:11:00.294252001 +1100 -@@ -559,6 +559,26 @@ - grq_unlock(); - } - -+/* -+ * Look for any tasks *anywhere* that are running nice 0 or better. We do -+ * this lockless for overhead reasons since the occasional wrong result -+ * is harmless. -+ */ -+int above_background_load(void) -+{ -+ struct task_struct *cpu_curr; -+ unsigned long cpu; -+ -+ for_each_online_cpu(cpu) { -+ cpu_curr = cpu_rq(cpu)->curr; -+ if (unlikely(!cpu_curr)) -+ continue; -+ if (PRIO_TO_NICE(cpu_curr->static_prio) < 1) -+ return 1; -+ } -+ return 0; -+} -+ - #ifndef __ARCH_WANT_UNLOCKED_CTXSW - static inline void prepare_lock_switch(struct rq *rq, struct task_struct *next) - { diff --git a/packages/linux/patches/linux-2.6.37.1-000_crosscompile.patch b/packages/linux/patches/linux-2.6.38-rc5-000_crosscompile.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37.1-000_crosscompile.patch rename to packages/linux/patches/linux-2.6.38-rc5-000_crosscompile.patch diff --git a/packages/linux/patches/linux-2.6.37.1-002_bash_only_feature.patch b/packages/linux/patches/linux-2.6.38-rc5-002_bash_only_feature.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37.1-002_bash_only_feature.patch rename to packages/linux/patches/linux-2.6.38-rc5-002_bash_only_feature.patch diff --git a/packages/linux/patches/linux-2.6.37.1-003-no_dev_console.patch b/packages/linux/patches/linux-2.6.38-rc5-003-no_dev_console.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37.1-003-no_dev_console.patch rename to packages/linux/patches/linux-2.6.38-rc5-003-no_dev_console.patch diff --git a/packages/linux/patches/linux-2.6.37.1-004_lower_undefined_mode_timeout.patch b/packages/linux/patches/linux-2.6.38-rc5-004_lower_undefined_mode_timeout.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37.1-004_lower_undefined_mode_timeout.patch rename to packages/linux/patches/linux-2.6.38-rc5-004_lower_undefined_mode_timeout.patch diff --git a/packages/linux/patches/linux-2.6.37.1-005_kconfig_no_timestamp.patch b/packages/linux/patches/linux-2.6.38-rc5-005_kconfig_no_timestamp.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37.1-005_kconfig_no_timestamp.patch rename to packages/linux/patches/linux-2.6.38-rc5-005_kconfig_no_timestamp.patch diff --git a/packages/linux/patches/linux-2.6.37.1-006_enable_utf8.patch b/packages/linux/patches/linux-2.6.38-rc5-006_enable_utf8.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37.1-006_enable_utf8.patch rename to packages/linux/patches/linux-2.6.38-rc5-006_enable_utf8.patch diff --git a/packages/linux/patches/linux-2.6.37.1-007_die_floppy_die.patch b/packages/linux/patches/linux-2.6.38-rc5-007_die_floppy_die.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37.1-007_die_floppy_die.patch rename to packages/linux/patches/linux-2.6.38-rc5-007_die_floppy_die.patch diff --git a/packages/linux/patches/linux-2.6.37.1-008-hda_intel_prealloc_4mb_dmabuffer.patch b/packages/linux/patches/linux-2.6.38-rc5-008-hda_intel_prealloc_4mb_dmabuffer.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37.1-008-hda_intel_prealloc_4mb_dmabuffer.patch rename to packages/linux/patches/linux-2.6.38-rc5-008-hda_intel_prealloc_4mb_dmabuffer.patch diff --git a/packages/linux/patches/linux-2.6.37.1-009_disable_i8042_check_on_apple_mac.patch b/packages/linux/patches/linux-2.6.38-rc5-009_disable_i8042_check_on_apple_mac.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37.1-009_disable_i8042_check_on_apple_mac.patch rename to packages/linux/patches/linux-2.6.38-rc5-009_disable_i8042_check_on_apple_mac.patch diff --git a/packages/linux/patches/linux-2.6.37.1-050_add_appleir_usb_driver.patch b/packages/linux/patches/linux-2.6.38-rc5-050_add_appleir_usb_driver.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37.1-050_add_appleir_usb_driver.patch rename to packages/linux/patches/linux-2.6.38-rc5-050_add_appleir_usb_driver.patch diff --git a/packages/linux/patches/linux-2.6.37.1-052-aureal_remote_quirk-0.1.patch b/packages/linux/patches/linux-2.6.38-rc5-052-aureal_remote_quirk-0.1.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37.1-052-aureal_remote_quirk-0.1.patch rename to packages/linux/patches/linux-2.6.38-rc5-052-aureal_remote_quirk-0.1.patch diff --git a/packages/linux/patches/linux-2.6.37.1-053_ati-remote_all_keys_and_keychange-0.1.patch b/packages/linux/patches/linux-2.6.38-rc5-053_ati-remote_all_keys_and_keychange-0.1.patch similarity index 100% rename from packages/linux/patches/linux-2.6.37.1-053_ati-remote_all_keys_and_keychange-0.1.patch rename to packages/linux/patches/linux-2.6.38-rc5-053_ati-remote_all_keys_and_keychange-0.1.patch diff --git a/packages/linux/patches/linux-2.6.37.1-061-Pioneer_DVR-212D_failed_xfermode-0.1.patch b/packages/linux/patches/linux-2.6.38-rc5-061-Pioneer_DVR-212D_failed_xfermode-0.1.patch.ignore similarity index 100% rename from packages/linux/patches/linux-2.6.37.1-061-Pioneer_DVR-212D_failed_xfermode-0.1.patch rename to packages/linux/patches/linux-2.6.38-rc5-061-Pioneer_DVR-212D_failed_xfermode-0.1.patch.ignore diff --git a/packages/linux/patches/linux-2.6.37.1-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch b/packages/linux/patches/linux-2.6.38-rc5-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch.ignore similarity index 100% rename from packages/linux/patches/linux-2.6.37.1-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch rename to packages/linux/patches/linux-2.6.38-rc5-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch.ignore diff --git a/packages/linux/patches/linux-2.6.37.1-110-drm_nouveau_upstream-20110111.patch b/packages/linux/patches/linux-2.6.38-rc5-110-drm_nouveau_upstream-20110111.patch.ignore similarity index 100% rename from packages/linux/patches/linux-2.6.37.1-110-drm_nouveau_upstream-20110111.patch rename to packages/linux/patches/linux-2.6.38-rc5-110-drm_nouveau_upstream-20110111.patch.ignore diff --git a/projects/ATV/linux/linux.i386.conf b/projects/ATV/linux/linux.i386.conf index ca22120675..784a27389d 100644 --- a/projects/ATV/linux/linux.i386.conf +++ b/projects/ATV/linux/linux.i386.conf @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux/i386 2.6.37-ck1 Kernel Configuration +# Linux/i386 2.6.38-rc5 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -43,7 +43,6 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y # CONFIG_AUDIT_ARCH is not set CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y -CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_X86_32_SMP=y CONFIG_X86_HT=y CONFIG_X86_TRAMPOLINE=y @@ -58,7 +57,6 @@ CONFIG_IRQ_WORK=y # # General setup # -# CONFIG_SCHED_BFS is not set CONFIG_EXPERIMENTAL=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" @@ -67,10 +65,12 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y CONFIG_HAVE_KERNEL_LZO=y # CONFIG_KERNEL_GZIP is not set # CONFIG_KERNEL_BZIP2 is not set -CONFIG_KERNEL_LZMA=y +# CONFIG_KERNEL_LZMA is not set +CONFIG_KERNEL_XZ=y # CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y @@ -87,7 +87,6 @@ CONFIG_HAVE_GENERIC_HARDIRQS=y # IRQ subsystem # CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y # CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set CONFIG_HAVE_SPARSE_IRQ=y CONFIG_GENERIC_IRQ_PROBE=y @@ -129,6 +128,7 @@ CONFIG_IPC_NS=y CONFIG_USER_NS=y CONFIG_PID_NS=y CONFIG_NET_NS=y +CONFIG_SCHED_AUTOGROUP=y # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set CONFIG_BLK_DEV_INITRD=y @@ -138,11 +138,13 @@ CONFIG_INITRAMFS_ROOT_GID=0 # CONFIG_RD_GZIP is not set # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set # CONFIG_RD_LZO is not set CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y +CONFIG_EXPERT=y CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -185,6 +187,7 @@ CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_OPTPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y +CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_DMA_API_DEBUG=y CONFIG_HAVE_HW_BREAKPOINT=y @@ -265,6 +268,7 @@ CONFIG_X86_MPPARSE=y # CONFIG_X86_BIGSMP is not set # CONFIG_X86_EXTENDED_PLATFORM is not set CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y +# CONFIG_X86_32_IRIS is not set CONFIG_SCHED_OMIT_FRAME_POINTER=y # CONFIG_PARAVIRT_GUEST is not set CONFIG_NO_BOOTMEM=y @@ -297,6 +301,7 @@ CONFIG_MPENTIUMM=y CONFIG_X86_CPU=y CONFIG_X86_INTERNODE_CACHE_SHIFT=6 CONFIG_X86_CMPXCHG=y +CONFIG_CMPXCHG_LOCAL=y CONFIG_X86_L1_CACHE_SHIFT=6 CONFIG_X86_XADD=y CONFIG_X86_WP_WORKS_OK=y @@ -371,6 +376,8 @@ CONFIG_SPARSEMEM_STATIC=y CONFIG_HAVE_MEMBLOCK=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y @@ -379,6 +386,9 @@ CONFIG_VIRT_TO_BUS=y CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y # CONFIG_MEMORY_FAILURE is not set +CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y +# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set # CONFIG_X86_CHECK_BIOS_CORRUPTION is not set CONFIG_X86_RESERVE_LOW=64 # CONFIG_MATH_EMULATION is not set @@ -392,17 +402,10 @@ CONFIG_EFI=y CONFIG_SECCOMP=y # CONFIG_CC_STACKPROTECTOR is not set # CONFIG_HZ_100 is not set -# CONFIG_HZ_250_NODEFAULT is not set -CONFIG_HZ_300=y -# CONFIG_HZ_1000 is not set -# CONFIG_HZ_1500 is not set -# CONFIG_HZ_2000 is not set -# CONFIG_HZ_3000 is not set -# CONFIG_HZ_4000 is not set -# CONFIG_HZ_5000 is not set -# CONFIG_HZ_7500 is not set -# CONFIG_HZ_10000 is not set -CONFIG_HZ=300 +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 CONFIG_SCHED_HRTICK=y # CONFIG_KEXEC is not set CONFIG_PHYSICAL_START=0x1000000 @@ -608,7 +611,9 @@ CONFIG_IPV6_NDISC_NODETYPE=y # CONFIG_NET_SCHED is not set # CONFIG_DCB is not set CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set CONFIG_RPS=y +CONFIG_XPS=y # # Network testing @@ -761,6 +766,7 @@ CONFIG_ATA_ACPI=y # CONFIG_SATA_AHCI is not set # CONFIG_SATA_AHCI_PLATFORM is not set # CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_ACARD_AHCI is not set # CONFIG_SATA_SIL24 is not set CONFIG_ATA_SFF=y @@ -845,6 +851,7 @@ CONFIG_PATA_ACPI=y # CONFIG_ATA_GENERIC is not set # CONFIG_PATA_LEGACY is not set # CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set # CONFIG_FUSION is not set # @@ -945,7 +952,6 @@ CONFIG_RT2X00=m # CONFIG_RT2400PCI is not set # CONFIG_RT2500PCI is not set # CONFIG_RT61PCI is not set -CONFIG_RT2800PCI_PCI=y # CONFIG_RT2800PCI is not set CONFIG_RT2500USB=m CONFIG_RT73USB=m @@ -956,8 +962,9 @@ CONFIG_RT2X00_LIB_FIRMWARE=y CONFIG_RT2X00_LIB_CRYPTO=y CONFIG_RT2X00_LIB_LEDS=y # CONFIG_RT2X00_DEBUG is not set +# CONFIG_RTL8192CE is not set # CONFIG_WL1251 is not set -# CONFIG_WL12XX is not set +# CONFIG_WL12XX_MENU is not set CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set @@ -1063,6 +1070,7 @@ CONFIG_INPUT_JOYSTICK=y # CONFIG_JOYSTICK_STINGER is not set # CONFIG_JOYSTICK_TWIDJOY is not set # CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set # CONFIG_JOYSTICK_JOYDUMP is not set CONFIG_JOYSTICK_XPAD=m CONFIG_JOYSTICK_XPAD_FF=y @@ -1082,9 +1090,9 @@ CONFIG_INPUT_APPLEIR=y # CONFIG_INPUT_YEALINK is not set # CONFIG_INPUT_CM109 is not set CONFIG_INPUT_UINPUT=y -# CONFIG_INPUT_WINBOND_CIR is not set # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_CMA3000 is not set # # Hardware I/O ports @@ -1147,7 +1155,6 @@ CONFIG_UNIX98_PTYS=y # CONFIG_MWAVE is not set # CONFIG_PC8736x_GPIO is not set # CONFIG_NSC_GPIO is not set -# CONFIG_CS5535_GPIO is not set # CONFIG_RAW_DRIVER is not set # CONFIG_HPET is not set # CONFIG_HANGCHECK_TIMER is not set @@ -1198,6 +1205,7 @@ CONFIG_I2C_I801=y # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_SIMTEC is not set # CONFIG_I2C_XILINX is not set +# CONFIG_I2C_EG20T is not set # # External I2C/SMBus adapter drivers @@ -1220,6 +1228,10 @@ CONFIG_I2C_I801=y # PPS support # # CONFIG_PPS is not set + +# +# PPS generators support +# CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIOLIB is not set # CONFIG_W1 is not set @@ -1231,6 +1243,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_BATTERY_BQ20Z75 is not set # CONFIG_BATTERY_BQ27x00 is not set # CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set # CONFIG_HWMON is not set CONFIG_THERMAL=y # CONFIG_WATCHDOG is not set @@ -1262,8 +1275,7 @@ CONFIG_VIDEO_MEDIA=y # # Multimedia drivers # -CONFIG_IR_CORE=y -CONFIG_VIDEO_IR=y +CONFIG_RC_CORE=y CONFIG_LIRC=y CONFIG_RC_MAP=y CONFIG_IR_NEC_DECODER=y @@ -1278,6 +1290,8 @@ CONFIG_IR_RC5_SZ_DECODER=y CONFIG_IR_MCEUSB=m # CONFIG_IR_NUVOTON is not set # CONFIG_IR_STREAMZAP is not set +# CONFIG_IR_WINBOND_CIR is not set +# CONFIG_RC_LOOPBACK is not set # CONFIG_MEDIA_ATTACH is not set CONFIG_MEDIA_TUNER=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set @@ -1453,7 +1467,6 @@ CONFIG_DVB_TUNER_DIB0090=m # Tools to develop new frontends # # CONFIG_DVB_DUMMY_FE is not set -# CONFIG_DAB is not set # # Graphics support @@ -1497,6 +1510,7 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set CONFIG_FB_BACKLIGHT=y @@ -1541,6 +1555,7 @@ CONFIG_FB_BACKLIGHT=y # CONFIG_FB_PM3 is not set # CONFIG_FB_CARMINE is not set # CONFIG_FB_GEODE is not set +# CONFIG_FB_UDL is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set @@ -1659,7 +1674,6 @@ CONFIG_SND_HDA_GENERIC=y # CONFIG_SND_HDA_POWER_SAVE is not set # CONFIG_SND_HDSP is not set # CONFIG_SND_HDSPM is not set -# CONFIG_SND_HIFIER is not set # CONFIG_SND_ICE1712 is not set # CONFIG_SND_ICE1724 is not set # CONFIG_SND_INTEL8X0 is not set @@ -1711,6 +1725,7 @@ CONFIG_HID_AUREAL=y # CONFIG_HID_PRODIKEYS is not set # CONFIG_HID_CYPRESS is not set # CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set # CONFIG_HID_EGALAX is not set # CONFIG_HID_EZKEY is not set # CONFIG_HID_KYE is not set @@ -1727,6 +1742,7 @@ CONFIG_LOGIWII_FF=y CONFIG_HID_MICROSOFT=y # CONFIG_HID_MOSART is not set # CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set # CONFIG_HID_NTRIG is not set # CONFIG_HID_ORTEK is not set # CONFIG_HID_PANTHERLORD is not set @@ -1735,6 +1751,7 @@ CONFIG_HID_MICROSOFT=y # CONFIG_HID_QUANTA is not set # CONFIG_HID_ROCCAT is not set # CONFIG_HID_ROCCAT_KONE is not set +# CONFIG_HID_ROCCAT_KONEPLUS is not set # CONFIG_HID_ROCCAT_PYRA is not set # CONFIG_HID_SAMSUNG is not set CONFIG_HID_SONY=y @@ -1938,6 +1955,7 @@ CONFIG_LEDS_TRIGGERS=y # # iptables trigger is under Netfilter config (LED target) # +# CONFIG_NFC_DEVICES is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -1953,7 +1971,6 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc0" CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y CONFIG_RTC_INTF_DEV=y -# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # CONFIG_RTC_DRV_TEST is not set # @@ -2006,6 +2023,7 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_UIO is not set CONFIG_STAGING=y # CONFIG_STAGING_EXCLUDE_BUILD is not set +# CONFIG_USB_DABUSB is not set # CONFIG_W35UND is not set # CONFIG_PRISM2_USB is not set # CONFIG_ECHO is not set @@ -2036,12 +2054,12 @@ CONFIG_DRM_I2C_SIL164=m # CONFIG_USB_SERIAL_QUATECH_USB2 is not set # CONFIG_VT6655 is not set # CONFIG_VT6656 is not set -# CONFIG_FB_UDL is not set # CONFIG_HYPERV is not set # CONFIG_VME_BUS is not set +# CONFIG_DX_SEP is not set # CONFIG_IIO is not set +# CONFIG_CS5535_GPIO is not set # CONFIG_ZRAM is not set -# CONFIG_BATMAN_ADV is not set # CONFIG_SAMSUNG_LAPTOP is not set # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set @@ -2061,6 +2079,7 @@ CONFIG_MACH_NO_WESTBRIDGE=y # Speakup console speech # # CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set # CONFIG_X86_PLATFORM_DEVICES is not set # @@ -2086,12 +2105,11 @@ CONFIG_EXT4_USE_FOR_EXT23=y CONFIG_JBD2=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set # CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set # CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y @@ -2114,6 +2132,8 @@ CONFIG_FUSE_FS=y CONFIG_ISO9660_FS=y CONFIG_JOLIET=y CONFIG_ZISOFS=y +CONFIG_UDF_FS=y +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -2151,6 +2171,7 @@ CONFIG_HFSPLUS_FS=y CONFIG_SQUASHFS=y CONFIG_SQUASHFS_XATTR=y CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y # CONFIG_SQUASHFS_EMBEDDED is not set CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_VXFS_FS is not set @@ -2251,7 +2272,6 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set CONFIG_NLS_UTF8=y -# CONFIG_DLM is not set # # Kernel hacking @@ -2297,6 +2317,7 @@ CONFIG_HAVE_ARCH_KMEMCHECK=y CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set # CONFIG_EARLY_PRINTK is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set CONFIG_DOUBLEFAULT=y # CONFIG_IOMMU_STRESS is not set CONFIG_HAVE_MMIOTRACE_SUPPORT=y @@ -2377,7 +2398,7 @@ CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_CRC32C is not set # CONFIG_CRYPTO_CRC32C_INTEL is not set # CONFIG_CRYPTO_GHASH is not set -# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=y # CONFIG_CRYPTO_RMD128 is not set @@ -2395,6 +2416,7 @@ CONFIG_CRYPTO_MICHAEL_MIC=y # CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_AES_586 is not set +# CONFIG_CRYPTO_AES_NI_INTEL is not set # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set @@ -2423,6 +2445,8 @@ CONFIG_CRYPTO_DES=y # Random Number Generation # # CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set # CONFIG_CRYPTO_HW is not set CONFIG_HAVE_KVM=y # CONFIG_VIRTUALIZATION is not set @@ -2444,7 +2468,17 @@ CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y CONFIG_LZO_DECOMPRESS=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_IA64 is not set +# CONFIG_XZ_DEC_ARM is not set +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_SPARC is not set +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y CONFIG_NLATTR=y +CONFIG_AVERAGE=y diff --git a/projects/Generic/linux/linux.i386.conf b/projects/Generic/linux/linux.i386.conf index 6f386e5085..79d1c9f5ce 100644 --- a/projects/Generic/linux/linux.i386.conf +++ b/projects/Generic/linux/linux.i386.conf @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux/i386 2.6.37.1-ck2 Kernel Configuration +# Linux/i386 2.6.38-rc5 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -44,7 +44,6 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y CONFIG_HAVE_INTEL_TXT=y -CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_X86_32_SMP=y CONFIG_X86_HT=y CONFIG_X86_TRAMPOLINE=y @@ -59,7 +58,6 @@ CONFIG_IRQ_WORK=y # # General setup # -# CONFIG_SCHED_BFS is not set CONFIG_EXPERIMENTAL=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" @@ -68,10 +66,12 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y CONFIG_HAVE_KERNEL_LZO=y # CONFIG_KERNEL_GZIP is not set # CONFIG_KERNEL_BZIP2 is not set -CONFIG_KERNEL_LZMA=y +# CONFIG_KERNEL_LZMA is not set +CONFIG_KERNEL_XZ=y # CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y @@ -88,7 +88,6 @@ CONFIG_HAVE_GENERIC_HARDIRQS=y # IRQ subsystem # CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y # CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set CONFIG_HAVE_SPARSE_IRQ=y CONFIG_GENERIC_IRQ_PROBE=y @@ -121,9 +120,12 @@ CONFIG_PROC_PID_CPUSET=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y # CONFIG_CGROUP_MEM_RES_CTLR is not set -# CONFIG_CGROUP_SCHED is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y # CONFIG_BLK_CGROUP is not set # CONFIG_NAMESPACES is not set +CONFIG_SCHED_AUTOGROUP=y # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set CONFIG_BLK_DEV_INITRD=y @@ -133,11 +135,13 @@ CONFIG_INITRAMFS_ROOT_GID=0 # CONFIG_RD_GZIP is not set # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set # CONFIG_RD_LZO is not set CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y +CONFIG_EXPERT=y CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -180,6 +184,7 @@ CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_OPTPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y +CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_DMA_API_DEBUG=y CONFIG_HAVE_HW_BREAKPOINT=y @@ -257,6 +262,7 @@ CONFIG_SMP=y CONFIG_X86_MPPARSE=y # CONFIG_X86_BIGSMP is not set # CONFIG_X86_EXTENDED_PLATFORM is not set +# CONFIG_X86_32_IRIS is not set CONFIG_SCHED_OMIT_FRAME_POINTER=y # CONFIG_PARAVIRT_GUEST is not set CONFIG_NO_BOOTMEM=y @@ -289,6 +295,7 @@ CONFIG_X86_GENERIC=y CONFIG_X86_CPU=y CONFIG_X86_INTERNODE_CACHE_SHIFT=6 CONFIG_X86_CMPXCHG=y +CONFIG_CMPXCHG_LOCAL=y CONFIG_X86_L1_CACHE_SHIFT=6 CONFIG_X86_XADD=y CONFIG_X86_WP_WORKS_OK=y @@ -357,12 +364,17 @@ CONFIG_SPARSEMEM_STATIC=y CONFIG_HAVE_MEMBLOCK=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y +# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set # CONFIG_HIGHPTE is not set # CONFIG_X86_CHECK_BIOS_CORRUPTION is not set CONFIG_X86_RESERVE_LOW=64 @@ -377,17 +389,10 @@ CONFIG_ARCH_USES_PG_UNCACHED=y CONFIG_SECCOMP=y CONFIG_CC_STACKPROTECTOR=y # CONFIG_HZ_100 is not set -# CONFIG_HZ_250_NODEFAULT is not set -CONFIG_HZ_300=y -# CONFIG_HZ_1000 is not set -# CONFIG_HZ_1500 is not set -# CONFIG_HZ_2000 is not set -# CONFIG_HZ_3000 is not set -# CONFIG_HZ_4000 is not set -# CONFIG_HZ_5000 is not set -# CONFIG_HZ_7500 is not set -# CONFIG_HZ_10000 is not set -CONFIG_HZ=300 +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 CONFIG_SCHED_HRTICK=y # CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set @@ -408,7 +413,6 @@ CONFIG_PM=y # CONFIG_PM_DEBUG is not set CONFIG_PM_SLEEP_SMP=y CONFIG_PM_SLEEP=y -CONFIG_SUSPEND_NVS=y CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y CONFIG_PM_RUNTIME=y @@ -610,7 +614,9 @@ CONFIG_IPV6_NDISC_NODETYPE=y # CONFIG_NET_SCHED is not set # CONFIG_DCB is not set CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set CONFIG_RPS=y +CONFIG_XPS=y # # Network testing @@ -784,6 +790,7 @@ CONFIG_ATA_ACPI=y CONFIG_SATA_AHCI=y CONFIG_SATA_AHCI_PLATFORM=y # CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_ACARD_AHCI is not set # CONFIG_SATA_SIL24 is not set CONFIG_ATA_SFF=y @@ -868,6 +875,7 @@ CONFIG_PATA_ACPI=y CONFIG_ATA_GENERIC=y # CONFIG_PATA_LEGACY is not set # CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set # CONFIG_FUSION is not set # @@ -1017,6 +1025,7 @@ CONFIG_ATH_COMMON=m # CONFIG_ATH_DEBUG is not set CONFIG_ATH5K=m # CONFIG_ATH5K_DEBUG is not set +CONFIG_ATH5K_PCI=y CONFIG_ATH9K_HW=m CONFIG_ATH9K_COMMON=m CONFIG_ATH9K=m @@ -1030,6 +1039,7 @@ CONFIG_B43_PCI_AUTOSELECT=y CONFIG_B43_PCICORE_AUTOSELECT=y # CONFIG_B43_SDIO is not set CONFIG_B43_PIO=y +CONFIG_B43_PHY_N=y CONFIG_B43_PHY_LP=y CONFIG_B43_LEDS=y # CONFIG_B43_DEBUG is not set @@ -1079,7 +1089,6 @@ CONFIG_RT2X00=m CONFIG_RT2400PCI=m CONFIG_RT2500PCI=m CONFIG_RT61PCI=m -CONFIG_RT2800PCI_PCI=y # CONFIG_RT2800PCI is not set CONFIG_RT2500USB=m CONFIG_RT73USB=m @@ -1091,8 +1100,10 @@ CONFIG_RT2X00_LIB_FIRMWARE=y CONFIG_RT2X00_LIB_CRYPTO=y CONFIG_RT2X00_LIB_LEDS=y # CONFIG_RT2X00_DEBUG is not set +CONFIG_RTL8192CE=m +CONFIG_RTLWIFI=m # CONFIG_WL1251 is not set -# CONFIG_WL12XX is not set +# CONFIG_WL12XX_MENU is not set CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set @@ -1198,6 +1209,7 @@ CONFIG_INPUT_JOYSTICK=y # CONFIG_JOYSTICK_STINGER is not set # CONFIG_JOYSTICK_TWIDJOY is not set # CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set # CONFIG_JOYSTICK_JOYDUMP is not set CONFIG_JOYSTICK_XPAD=m CONFIG_JOYSTICK_XPAD_FF=y @@ -1217,9 +1229,9 @@ CONFIG_INPUT_APPLEIR=m # CONFIG_INPUT_YEALINK is not set # CONFIG_INPUT_CM109 is not set CONFIG_INPUT_UINPUT=y -# CONFIG_INPUT_WINBOND_CIR is not set # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_CMA3000 is not set # # Hardware I/O ports @@ -1282,7 +1294,6 @@ CONFIG_UNIX98_PTYS=y # CONFIG_MWAVE is not set # CONFIG_PC8736x_GPIO is not set # CONFIG_NSC_GPIO is not set -# CONFIG_CS5535_GPIO is not set # CONFIG_RAW_DRIVER is not set # CONFIG_HPET is not set # CONFIG_HANGCHECK_TIMER is not set @@ -1334,6 +1345,7 @@ CONFIG_I2C_INTEL_MID=m # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_SIMTEC is not set # CONFIG_I2C_XILINX is not set +# CONFIG_I2C_EG20T is not set # # External I2C/SMBus adapter drivers @@ -1356,6 +1368,10 @@ CONFIG_I2C_INTEL_MID=m # PPS support # # CONFIG_PPS is not set + +# +# PPS generators support +# CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIOLIB is not set # CONFIG_W1 is not set @@ -1367,6 +1383,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_BATTERY_BQ20Z75 is not set # CONFIG_BATTERY_BQ27x00 is not set # CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set CONFIG_HWMON=y CONFIG_HWMON_VID=m # CONFIG_HWMON_DEBUG_CHIP is not set @@ -1393,6 +1410,7 @@ CONFIG_SENSORS_K8TEMP=m CONFIG_SENSORS_K10TEMP=m # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_I5K_AMB is not set # CONFIG_SENSORS_F71805F is not set @@ -1427,6 +1445,7 @@ CONFIG_SENSORS_IT87=m # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set # CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT21 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMM665 is not set # CONFIG_SENSORS_DME1737 is not set @@ -1499,8 +1518,7 @@ CONFIG_VIDEO_MEDIA=y # Multimedia drivers # CONFIG_VIDEO_SAA7146=m -CONFIG_IR_CORE=y -CONFIG_VIDEO_IR=y +CONFIG_RC_CORE=y CONFIG_LIRC=y CONFIG_RC_MAP=y CONFIG_IR_NEC_DECODER=y @@ -1515,6 +1533,8 @@ CONFIG_IR_IMON=m CONFIG_IR_MCEUSB=m CONFIG_IR_NUVOTON=m CONFIG_IR_STREAMZAP=m +CONFIG_IR_WINBOND_CIR=m +# CONFIG_RC_LOOPBACK is not set CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set @@ -1712,7 +1732,6 @@ CONFIG_DVB_TDA665x=y # Tools to develop new frontends # # CONFIG_DVB_DUMMY_FE is not set -# CONFIG_DAB is not set # # Graphics support @@ -1760,6 +1779,7 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_WMT_GE_ROPS is not set CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set @@ -1804,6 +1824,7 @@ CONFIG_FB_VESA=y # CONFIG_FB_CARMINE is not set # CONFIG_FB_GEODE is not set # CONFIG_FB_TMIO is not set +# CONFIG_FB_UDL is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set @@ -1918,7 +1939,6 @@ CONFIG_SND_HDA_GENERIC=y # CONFIG_SND_HDA_POWER_SAVE is not set # CONFIG_SND_HDSP is not set # CONFIG_SND_HDSPM is not set -# CONFIG_SND_HIFIER is not set # CONFIG_SND_ICE1712 is not set CONFIG_SND_ICE1724=m CONFIG_SND_INTEL8X0=m @@ -1976,6 +1996,7 @@ CONFIG_HID_AUREAL=y # CONFIG_HID_PRODIKEYS is not set # CONFIG_HID_CYPRESS is not set # CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set # CONFIG_HID_EGALAX is not set # CONFIG_HID_ELECOM is not set # CONFIG_HID_EZKEY is not set @@ -1994,6 +2015,7 @@ CONFIG_LOGIG940_FF=y CONFIG_HID_MICROSOFT=y # CONFIG_HID_MOSART is not set # CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set # CONFIG_HID_NTRIG is not set # CONFIG_HID_ORTEK is not set # CONFIG_HID_PANTHERLORD is not set @@ -2002,6 +2024,7 @@ CONFIG_HID_MICROSOFT=y # CONFIG_HID_QUANTA is not set # CONFIG_HID_ROCCAT is not set # CONFIG_HID_ROCCAT_KONE is not set +# CONFIG_HID_ROCCAT_KONEPLUS is not set # CONFIG_HID_ROCCAT_PYRA is not set # CONFIG_HID_SAMSUNG is not set CONFIG_HID_SONY=y @@ -2184,6 +2207,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=m CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set +# CONFIG_MMC_CLKGATE is not set # # MMC/SD/SDIO Card Drivers @@ -2248,6 +2272,7 @@ CONFIG_LEDS_TRIGGERS=y # # iptables trigger is under Netfilter config (LED target) # +# CONFIG_NFC_DEVICES is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -2263,7 +2288,6 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc0" CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y CONFIG_RTC_INTF_DEV=y -# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # CONFIG_RTC_DRV_TEST is not set # @@ -2325,6 +2349,7 @@ CONFIG_STAGING=y # CONFIG_STAGING_EXCLUDE_BUILD is not set # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set +# CONFIG_USB_DABUSB is not set # CONFIG_W35UND is not set # CONFIG_PRISM2_USB is not set # CONFIG_ECHO is not set @@ -2354,12 +2379,12 @@ CONFIG_DRM_VMWGFX=y # CONFIG_USB_SERIAL_QUATECH_USB2 is not set # CONFIG_VT6655 is not set CONFIG_VT6656=m -# CONFIG_FB_UDL is not set # CONFIG_HYPERV is not set # CONFIG_VME_BUS is not set +# CONFIG_DX_SEP is not set # CONFIG_IIO is not set +# CONFIG_CS5535_GPIO is not set # CONFIG_ZRAM is not set -# CONFIG_BATMAN_ADV is not set # CONFIG_SAMSUNG_LAPTOP is not set # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set @@ -2381,6 +2406,7 @@ CONFIG_MACH_NO_WESTBRIDGE=y # Speakup console speech # # CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set # CONFIG_X86_PLATFORM_DEVICES is not set # @@ -2405,12 +2431,11 @@ CONFIG_EXT4_USE_FOR_EXT23=y CONFIG_JBD2=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set # CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set # CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y @@ -2433,6 +2458,8 @@ CONFIG_FUSE_FS=m CONFIG_ISO9660_FS=y CONFIG_JOLIET=y CONFIG_ZISOFS=y +CONFIG_UDF_FS=y +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -2470,6 +2497,7 @@ CONFIG_HFSPLUS_FS=m CONFIG_SQUASHFS=y # CONFIG_SQUASHFS_XATTR is not set # CONFIG_SQUASHFS_LZO is not set +CONFIG_SQUASHFS_XZ=y # CONFIG_SQUASHFS_EMBEDDED is not set CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_VXFS_FS is not set @@ -2570,7 +2598,6 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set CONFIG_NLS_UTF8=y -# CONFIG_DLM is not set # # Kernel hacking @@ -2616,6 +2643,7 @@ CONFIG_HAVE_ARCH_KMEMCHECK=y CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set # CONFIG_EARLY_PRINTK is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set CONFIG_DOUBLEFAULT=y # CONFIG_IOMMU_STRESS is not set CONFIG_HAVE_MMIOTRACE_SUPPORT=y @@ -2662,7 +2690,7 @@ CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_PCRYPT is not set CONFIG_CRYPTO_WORKQUEUE=y -# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_CRYPTD=y # CONFIG_CRYPTO_AUTHENC is not set # CONFIG_CRYPTO_TEST is not set @@ -2683,6 +2711,7 @@ CONFIG_CRYPTO_ECB=y # CONFIG_CRYPTO_LRW is not set # CONFIG_CRYPTO_PCBC is not set # CONFIG_CRYPTO_XTS is not set +CONFIG_CRYPTO_FPU=y # # Hash modes @@ -2697,7 +2726,7 @@ CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_CRC32C is not set # CONFIG_CRYPTO_CRC32C_INTEL is not set # CONFIG_CRYPTO_GHASH is not set -# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=y # CONFIG_CRYPTO_RMD128 is not set @@ -2714,7 +2743,8 @@ CONFIG_CRYPTO_MICHAEL_MIC=y # Ciphers # CONFIG_CRYPTO_AES=y -# CONFIG_CRYPTO_AES_586 is not set +CONFIG_CRYPTO_AES_586=y +CONFIG_CRYPTO_AES_NI_INTEL=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set @@ -2743,6 +2773,8 @@ CONFIG_CRYPTO_DES=y # Random Number Generation # # CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set # CONFIG_CRYPTO_HW is not set CONFIG_HAVE_KVM=y # CONFIG_VIRTUALIZATION is not set @@ -2763,7 +2795,17 @@ CONFIG_CRC32=y # CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_IA64 is not set +# CONFIG_XZ_DEC_ARM is not set +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_SPARC is not set +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y CONFIG_NLATTR=y +CONFIG_AVERAGE=y diff --git a/projects/ION/linux/linux.i386.conf b/projects/ION/linux/linux.i386.conf index 8e87390ff4..1fb8668285 100644 --- a/projects/ION/linux/linux.i386.conf +++ b/projects/ION/linux/linux.i386.conf @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux/i386 2.6.37.1-ck2 Kernel Configuration +# Linux/i386 2.6.38-rc5 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -44,7 +44,6 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y CONFIG_HAVE_INTEL_TXT=y -CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_X86_32_SMP=y CONFIG_X86_HT=y CONFIG_X86_TRAMPOLINE=y @@ -59,7 +58,6 @@ CONFIG_IRQ_WORK=y # # General setup # -# CONFIG_SCHED_BFS is not set CONFIG_EXPERIMENTAL=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" @@ -68,10 +66,12 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y CONFIG_HAVE_KERNEL_LZO=y # CONFIG_KERNEL_GZIP is not set # CONFIG_KERNEL_BZIP2 is not set -CONFIG_KERNEL_LZMA=y +# CONFIG_KERNEL_LZMA is not set +CONFIG_KERNEL_XZ=y # CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y @@ -88,7 +88,6 @@ CONFIG_HAVE_GENERIC_HARDIRQS=y # IRQ subsystem # CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y # CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set CONFIG_HAVE_SPARSE_IRQ=y CONFIG_GENERIC_IRQ_PROBE=y @@ -121,9 +120,12 @@ CONFIG_PROC_PID_CPUSET=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y # CONFIG_CGROUP_MEM_RES_CTLR is not set -# CONFIG_CGROUP_SCHED is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y # CONFIG_BLK_CGROUP is not set # CONFIG_NAMESPACES is not set +CONFIG_SCHED_AUTOGROUP=y # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set CONFIG_BLK_DEV_INITRD=y @@ -133,11 +135,13 @@ CONFIG_INITRAMFS_ROOT_GID=0 # CONFIG_RD_GZIP is not set # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set # CONFIG_RD_LZO is not set CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y +CONFIG_EXPERT=y CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -180,6 +184,7 @@ CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_OPTPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y +CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_DMA_API_DEBUG=y CONFIG_HAVE_HW_BREAKPOINT=y @@ -257,6 +262,7 @@ CONFIG_SMP=y CONFIG_X86_MPPARSE=y # CONFIG_X86_BIGSMP is not set # CONFIG_X86_EXTENDED_PLATFORM is not set +# CONFIG_X86_32_IRIS is not set CONFIG_SCHED_OMIT_FRAME_POINTER=y # CONFIG_PARAVIRT_GUEST is not set CONFIG_NO_BOOTMEM=y @@ -289,6 +295,7 @@ CONFIG_MATOM=y CONFIG_X86_CPU=y CONFIG_X86_INTERNODE_CACHE_SHIFT=6 CONFIG_X86_CMPXCHG=y +CONFIG_CMPXCHG_LOCAL=y CONFIG_X86_L1_CACHE_SHIFT=6 CONFIG_X86_XADD=y CONFIG_X86_WP_WORKS_OK=y @@ -356,12 +363,17 @@ CONFIG_SPARSEMEM_STATIC=y CONFIG_HAVE_MEMBLOCK=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y +# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set # CONFIG_HIGHPTE is not set # CONFIG_X86_CHECK_BIOS_CORRUPTION is not set CONFIG_X86_RESERVE_LOW=64 @@ -376,17 +388,10 @@ CONFIG_ARCH_USES_PG_UNCACHED=y CONFIG_SECCOMP=y CONFIG_CC_STACKPROTECTOR=y # CONFIG_HZ_100 is not set -# CONFIG_HZ_250_NODEFAULT is not set -CONFIG_HZ_300=y -# CONFIG_HZ_1000 is not set -# CONFIG_HZ_1500 is not set -# CONFIG_HZ_2000 is not set -# CONFIG_HZ_3000 is not set -# CONFIG_HZ_4000 is not set -# CONFIG_HZ_5000 is not set -# CONFIG_HZ_7500 is not set -# CONFIG_HZ_10000 is not set -CONFIG_HZ=300 +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 CONFIG_SCHED_HRTICK=y # CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set @@ -407,7 +412,6 @@ CONFIG_PM=y # CONFIG_PM_DEBUG is not set CONFIG_PM_SLEEP_SMP=y CONFIG_PM_SLEEP=y -CONFIG_SUSPEND_NVS=y CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y CONFIG_PM_RUNTIME=y @@ -607,7 +611,9 @@ CONFIG_IPV6_NDISC_NODETYPE=y # CONFIG_NET_SCHED is not set # CONFIG_DCB is not set CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set CONFIG_RPS=y +CONFIG_XPS=y # # Network testing @@ -780,6 +786,7 @@ CONFIG_ATA_ACPI=y CONFIG_SATA_AHCI=y CONFIG_SATA_AHCI_PLATFORM=y # CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_ACARD_AHCI is not set # CONFIG_SATA_SIL24 is not set CONFIG_ATA_SFF=y @@ -864,6 +871,7 @@ CONFIG_PATA_ACPI=y CONFIG_ATA_GENERIC=y # CONFIG_PATA_LEGACY is not set # CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set # CONFIG_FUSION is not set # @@ -972,6 +980,7 @@ CONFIG_ATH_COMMON=m # CONFIG_ATH_DEBUG is not set CONFIG_ATH5K=m # CONFIG_ATH5K_DEBUG is not set +CONFIG_ATH5K_PCI=y CONFIG_ATH9K_HW=m CONFIG_ATH9K_COMMON=m CONFIG_ATH9K=m @@ -996,7 +1005,6 @@ CONFIG_RT2X00=m # CONFIG_RT2400PCI is not set # CONFIG_RT2500PCI is not set # CONFIG_RT61PCI is not set -CONFIG_RT2800PCI_PCI=y # CONFIG_RT2800PCI is not set CONFIG_RT2500USB=m CONFIG_RT73USB=m @@ -1007,8 +1015,9 @@ CONFIG_RT2X00_LIB_FIRMWARE=y CONFIG_RT2X00_LIB_CRYPTO=y CONFIG_RT2X00_LIB_LEDS=y # CONFIG_RT2X00_DEBUG is not set +# CONFIG_RTL8192CE is not set # CONFIG_WL1251 is not set -# CONFIG_WL12XX is not set +# CONFIG_WL12XX_MENU is not set CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set @@ -1114,6 +1123,7 @@ CONFIG_INPUT_JOYSTICK=y # CONFIG_JOYSTICK_STINGER is not set # CONFIG_JOYSTICK_TWIDJOY is not set # CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set # CONFIG_JOYSTICK_JOYDUMP is not set CONFIG_JOYSTICK_XPAD=m CONFIG_JOYSTICK_XPAD_FF=y @@ -1133,9 +1143,9 @@ CONFIG_INPUT_ATI_REMOTE2=m # CONFIG_INPUT_YEALINK is not set # CONFIG_INPUT_CM109 is not set CONFIG_INPUT_UINPUT=y -# CONFIG_INPUT_WINBOND_CIR is not set # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_CMA3000 is not set # # Hardware I/O ports @@ -1198,7 +1208,6 @@ CONFIG_UNIX98_PTYS=y # CONFIG_MWAVE is not set # CONFIG_PC8736x_GPIO is not set # CONFIG_NSC_GPIO is not set -# CONFIG_CS5535_GPIO is not set # CONFIG_RAW_DRIVER is not set # CONFIG_HPET is not set # CONFIG_HANGCHECK_TIMER is not set @@ -1249,6 +1258,7 @@ CONFIG_I2C_INTEL_MID=m # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_SIMTEC is not set # CONFIG_I2C_XILINX is not set +# CONFIG_I2C_EG20T is not set # # External I2C/SMBus adapter drivers @@ -1271,6 +1281,10 @@ CONFIG_I2C_INTEL_MID=m # PPS support # # CONFIG_PPS is not set + +# +# PPS generators support +# CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIOLIB is not set # CONFIG_W1 is not set @@ -1282,6 +1296,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_BATTERY_BQ20Z75 is not set # CONFIG_BATTERY_BQ27x00 is not set # CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_HWMON_DEBUG_CHIP is not set @@ -1308,6 +1323,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_K10TEMP is not set # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_I5K_AMB is not set # CONFIG_SENSORS_F71805F is not set @@ -1342,6 +1358,7 @@ CONFIG_SENSORS_PKGTEMP=m # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set # CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT21 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMM665 is not set # CONFIG_SENSORS_DME1737 is not set @@ -1403,8 +1420,7 @@ CONFIG_VIDEO_MEDIA=y # Multimedia drivers # CONFIG_VIDEO_SAA7146=m -CONFIG_IR_CORE=y -CONFIG_VIDEO_IR=y +CONFIG_RC_CORE=y CONFIG_LIRC=y CONFIG_RC_MAP=y CONFIG_IR_NEC_DECODER=y @@ -1419,6 +1435,8 @@ CONFIG_IR_IMON=m CONFIG_IR_MCEUSB=m CONFIG_IR_NUVOTON=m CONFIG_IR_STREAMZAP=m +CONFIG_IR_WINBOND_CIR=m +# CONFIG_RC_LOOPBACK is not set CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set @@ -1616,7 +1634,6 @@ CONFIG_DVB_TDA665x=y # Tools to develop new frontends # # CONFIG_DVB_DUMMY_FE is not set -# CONFIG_DAB is not set # # Graphics support @@ -1651,6 +1668,7 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -1695,6 +1713,7 @@ CONFIG_FB_VESA=y # CONFIG_FB_CARMINE is not set # CONFIG_FB_GEODE is not set # CONFIG_FB_TMIO is not set +# CONFIG_FB_UDL is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set @@ -1807,7 +1826,6 @@ CONFIG_SND_HDA_GENERIC=y # CONFIG_SND_HDA_POWER_SAVE is not set # CONFIG_SND_HDSP is not set # CONFIG_SND_HDSPM is not set -# CONFIG_SND_HIFIER is not set # CONFIG_SND_ICE1712 is not set # CONFIG_SND_ICE1724 is not set # CONFIG_SND_INTEL8X0 is not set @@ -1864,6 +1882,7 @@ CONFIG_HID_AUREAL=y # CONFIG_HID_PRODIKEYS is not set # CONFIG_HID_CYPRESS is not set # CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set # CONFIG_HID_EGALAX is not set # CONFIG_HID_ELECOM is not set # CONFIG_HID_EZKEY is not set @@ -1882,6 +1901,7 @@ CONFIG_LOGIG940_FF=y CONFIG_HID_MICROSOFT=y # CONFIG_HID_MOSART is not set # CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set # CONFIG_HID_NTRIG is not set # CONFIG_HID_ORTEK is not set # CONFIG_HID_PANTHERLORD is not set @@ -1890,6 +1910,7 @@ CONFIG_HID_MICROSOFT=y # CONFIG_HID_QUANTA is not set # CONFIG_HID_ROCCAT is not set # CONFIG_HID_ROCCAT_KONE is not set +# CONFIG_HID_ROCCAT_KONEPLUS is not set # CONFIG_HID_ROCCAT_PYRA is not set # CONFIG_HID_SAMSUNG is not set CONFIG_HID_SONY=y @@ -2072,6 +2093,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=m CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set +# CONFIG_MMC_CLKGATE is not set # # MMC/SD/SDIO Card Drivers @@ -2136,6 +2158,7 @@ CONFIG_LEDS_TRIGGERS=y # # iptables trigger is under Netfilter config (LED target) # +# CONFIG_NFC_DEVICES is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -2151,7 +2174,6 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc0" CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y CONFIG_RTC_INTF_DEV=y -# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # CONFIG_RTC_DRV_TEST is not set # @@ -2206,6 +2228,7 @@ CONFIG_STAGING=y # CONFIG_STAGING_EXCLUDE_BUILD is not set # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set +# CONFIG_USB_DABUSB is not set # CONFIG_W35UND is not set # CONFIG_PRISM2_USB is not set # CONFIG_ECHO is not set @@ -2227,12 +2250,12 @@ CONFIG_R8712_AP=y # CONFIG_USB_SERIAL_QUATECH_USB2 is not set # CONFIG_VT6655 is not set CONFIG_VT6656=m -# CONFIG_FB_UDL is not set # CONFIG_HYPERV is not set # CONFIG_VME_BUS is not set +# CONFIG_DX_SEP is not set # CONFIG_IIO is not set +# CONFIG_CS5535_GPIO is not set # CONFIG_ZRAM is not set -# CONFIG_BATMAN_ADV is not set # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set @@ -2253,6 +2276,7 @@ CONFIG_MACH_NO_WESTBRIDGE=y # Speakup console speech # # CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set # CONFIG_X86_PLATFORM_DEVICES is not set # @@ -2277,12 +2301,11 @@ CONFIG_EXT4_USE_FOR_EXT23=y CONFIG_JBD2=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set # CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set # CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y @@ -2305,6 +2328,8 @@ CONFIG_FUSE_FS=m CONFIG_ISO9660_FS=y CONFIG_JOLIET=y CONFIG_ZISOFS=y +CONFIG_UDF_FS=y +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -2342,6 +2367,7 @@ CONFIG_HFSPLUS_FS=m CONFIG_SQUASHFS=y # CONFIG_SQUASHFS_XATTR is not set # CONFIG_SQUASHFS_LZO is not set +CONFIG_SQUASHFS_XZ=y # CONFIG_SQUASHFS_EMBEDDED is not set CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_VXFS_FS is not set @@ -2442,7 +2468,6 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set CONFIG_NLS_UTF8=y -# CONFIG_DLM is not set # # Kernel hacking @@ -2488,6 +2513,7 @@ CONFIG_HAVE_ARCH_KMEMCHECK=y CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set # CONFIG_EARLY_PRINTK is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set CONFIG_DOUBLEFAULT=y # CONFIG_IOMMU_STRESS is not set CONFIG_HAVE_MMIOTRACE_SUPPORT=y @@ -2569,7 +2595,7 @@ CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_CRC32C is not set # CONFIG_CRYPTO_CRC32C_INTEL is not set # CONFIG_CRYPTO_GHASH is not set -# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_RMD128 is not set @@ -2587,6 +2613,7 @@ CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_AES_586 is not set +# CONFIG_CRYPTO_AES_NI_INTEL is not set # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set @@ -2615,6 +2642,8 @@ CONFIG_CRYPTO_DES=y # Random Number Generation # # CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set # CONFIG_CRYPTO_HW is not set CONFIG_HAVE_KVM=y # CONFIG_VIRTUALIZATION is not set @@ -2635,7 +2664,17 @@ CONFIG_CRC32=y # CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_IA64 is not set +# CONFIG_XZ_DEC_ARM is not set +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_SPARC is not set +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y CONFIG_NLATTR=y +CONFIG_AVERAGE=y diff --git a/projects/ION/linux/linux.x86_64.conf b/projects/ION/linux/linux.x86_64.conf index 4376d2d05b..afa27505e2 100644 --- a/projects/ION/linux/linux.x86_64.conf +++ b/projects/ION/linux/linux.x86_64.conf @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux/x86_64 2.6.37.1-ck2 Kernel Configuration +# Linux/x86_64 2.6.38-rc5 Kernel Configuration # CONFIG_64BIT=y # CONFIG_X86_32 is not set @@ -44,7 +44,6 @@ CONFIG_AUDIT_ARCH=y CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y CONFIG_HAVE_INTEL_TXT=y -CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_X86_64_SMP=y CONFIG_X86_HT=y CONFIG_X86_TRAMPOLINE=y @@ -59,7 +58,6 @@ CONFIG_IRQ_WORK=y # # General setup # -# CONFIG_SCHED_BFS is not set CONFIG_EXPERIMENTAL=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" @@ -68,10 +66,12 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y CONFIG_HAVE_KERNEL_LZO=y # CONFIG_KERNEL_GZIP is not set # CONFIG_KERNEL_BZIP2 is not set -CONFIG_KERNEL_LZMA=y +# CONFIG_KERNEL_LZMA is not set +CONFIG_KERNEL_XZ=y # CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y @@ -88,7 +88,6 @@ CONFIG_HAVE_GENERIC_HARDIRQS=y # IRQ subsystem # CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y # CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set CONFIG_HAVE_SPARSE_IRQ=y CONFIG_GENERIC_IRQ_PROBE=y @@ -121,9 +120,12 @@ CONFIG_PROC_PID_CPUSET=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y # CONFIG_CGROUP_MEM_RES_CTLR is not set -# CONFIG_CGROUP_SCHED is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y # CONFIG_BLK_CGROUP is not set # CONFIG_NAMESPACES is not set +CONFIG_SCHED_AUTOGROUP=y # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set CONFIG_BLK_DEV_INITRD=y @@ -133,11 +135,13 @@ CONFIG_INITRAMFS_ROOT_GID=0 # CONFIG_RD_GZIP is not set # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set # CONFIG_RD_LZO is not set CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y +CONFIG_EXPERT=y CONFIG_EMBEDDED=y CONFIG_SYSCTL_SYSCALL=y # CONFIG_KALLSYMS is not set @@ -179,6 +183,7 @@ CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_OPTPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y +CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_DMA_API_DEBUG=y CONFIG_HAVE_HW_BREAKPOINT=y @@ -266,6 +271,7 @@ CONFIG_MATOM=y CONFIG_X86_CPU=y CONFIG_X86_INTERNODE_CACHE_SHIFT=6 CONFIG_X86_CMPXCHG=y +CONFIG_CMPXCHG_LOCAL=y CONFIG_X86_L1_CACHE_SHIFT=6 CONFIG_X86_XADD=y CONFIG_X86_WP_WORKS_OK=y @@ -323,12 +329,17 @@ CONFIG_HAVE_MEMBLOCK=y # CONFIG_MEMORY_HOTPLUG is not set CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y CONFIG_PHYS_ADDR_T_64BIT=y CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y +# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set # CONFIG_X86_CHECK_BIOS_CORRUPTION is not set CONFIG_X86_RESERVE_LOW=64 CONFIG_MTRR=y @@ -341,17 +352,10 @@ CONFIG_ARCH_USES_PG_UNCACHED=y CONFIG_SECCOMP=y CONFIG_CC_STACKPROTECTOR=y # CONFIG_HZ_100 is not set -# CONFIG_HZ_250_NODEFAULT is not set -CONFIG_HZ_300=y -# CONFIG_HZ_1000 is not set -# CONFIG_HZ_1500 is not set -# CONFIG_HZ_2000 is not set -# CONFIG_HZ_3000 is not set -# CONFIG_HZ_4000 is not set -# CONFIG_HZ_5000 is not set -# CONFIG_HZ_7500 is not set -# CONFIG_HZ_10000 is not set -CONFIG_HZ=300 +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 CONFIG_SCHED_HRTICK=y # CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set @@ -371,7 +375,6 @@ CONFIG_PM=y # CONFIG_PM_DEBUG is not set CONFIG_PM_SLEEP_SMP=y CONFIG_PM_SLEEP=y -CONFIG_SUSPEND_NVS=y CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y CONFIG_PM_RUNTIME=y @@ -557,7 +560,9 @@ CONFIG_IPV6_NDISC_NODETYPE=y # CONFIG_NET_SCHED is not set # CONFIG_DCB is not set CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set CONFIG_RPS=y +CONFIG_XPS=y # # Network testing @@ -730,6 +735,7 @@ CONFIG_ATA_ACPI=y CONFIG_SATA_AHCI=y CONFIG_SATA_AHCI_PLATFORM=y # CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_ACARD_AHCI is not set # CONFIG_SATA_SIL24 is not set CONFIG_ATA_SFF=y @@ -813,6 +819,7 @@ CONFIG_PATA_ACPI=y CONFIG_ATA_GENERIC=y # CONFIG_PATA_LEGACY is not set # CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set # CONFIG_FUSION is not set # @@ -921,6 +928,7 @@ CONFIG_ATH_COMMON=m # CONFIG_ATH_DEBUG is not set CONFIG_ATH5K=m # CONFIG_ATH5K_DEBUG is not set +CONFIG_ATH5K_PCI=y CONFIG_ATH9K_HW=m CONFIG_ATH9K_COMMON=m CONFIG_ATH9K=m @@ -945,7 +953,6 @@ CONFIG_RT2X00=m # CONFIG_RT2400PCI is not set # CONFIG_RT2500PCI is not set # CONFIG_RT61PCI is not set -CONFIG_RT2800PCI_PCI=y # CONFIG_RT2800PCI is not set CONFIG_RT2500USB=m CONFIG_RT73USB=m @@ -956,8 +963,9 @@ CONFIG_RT2X00_LIB_FIRMWARE=y CONFIG_RT2X00_LIB_CRYPTO=y CONFIG_RT2X00_LIB_LEDS=y # CONFIG_RT2X00_DEBUG is not set +# CONFIG_RTL8192CE is not set # CONFIG_WL1251 is not set -# CONFIG_WL12XX is not set +# CONFIG_WL12XX_MENU is not set CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set @@ -1063,6 +1071,7 @@ CONFIG_INPUT_JOYSTICK=y # CONFIG_JOYSTICK_STINGER is not set # CONFIG_JOYSTICK_TWIDJOY is not set # CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set # CONFIG_JOYSTICK_JOYDUMP is not set CONFIG_JOYSTICK_XPAD=m CONFIG_JOYSTICK_XPAD_FF=y @@ -1081,9 +1090,9 @@ CONFIG_INPUT_ATI_REMOTE2=m # CONFIG_INPUT_YEALINK is not set # CONFIG_INPUT_CM109 is not set CONFIG_INPUT_UINPUT=y -# CONFIG_INPUT_WINBOND_CIR is not set # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_CMA3000 is not set # # Hardware I/O ports @@ -1192,6 +1201,7 @@ CONFIG_I2C_INTEL_MID=m # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_SIMTEC is not set # CONFIG_I2C_XILINX is not set +# CONFIG_I2C_EG20T is not set # # External I2C/SMBus adapter drivers @@ -1213,6 +1223,10 @@ CONFIG_I2C_INTEL_MID=m # PPS support # # CONFIG_PPS is not set + +# +# PPS generators support +# CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIOLIB is not set # CONFIG_W1 is not set @@ -1224,6 +1238,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_BATTERY_BQ20Z75 is not set # CONFIG_BATTERY_BQ27x00 is not set # CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_HWMON_DEBUG_CHIP is not set @@ -1250,6 +1265,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_K10TEMP is not set # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_I5K_AMB is not set # CONFIG_SENSORS_F71805F is not set @@ -1284,6 +1300,7 @@ CONFIG_SENSORS_PKGTEMP=m # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set # CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT21 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMM665 is not set # CONFIG_SENSORS_DME1737 is not set @@ -1345,8 +1362,7 @@ CONFIG_VIDEO_MEDIA=y # Multimedia drivers # CONFIG_VIDEO_SAA7146=m -CONFIG_IR_CORE=y -CONFIG_VIDEO_IR=y +CONFIG_RC_CORE=y CONFIG_LIRC=y CONFIG_RC_MAP=y CONFIG_IR_NEC_DECODER=y @@ -1361,6 +1377,8 @@ CONFIG_IR_IMON=m CONFIG_IR_MCEUSB=m CONFIG_IR_NUVOTON=m CONFIG_IR_STREAMZAP=m +CONFIG_IR_WINBOND_CIR=m +# CONFIG_RC_LOOPBACK is not set CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set @@ -1558,7 +1576,6 @@ CONFIG_DVB_TDA665x=y # Tools to develop new frontends # # CONFIG_DVB_DUMMY_FE is not set -# CONFIG_DAB is not set # # Graphics support @@ -1587,6 +1604,7 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -1630,6 +1648,7 @@ CONFIG_FB_VESA=y # CONFIG_FB_CARMINE is not set # CONFIG_FB_GEODE is not set # CONFIG_FB_TMIO is not set +# CONFIG_FB_UDL is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set @@ -1742,7 +1761,6 @@ CONFIG_SND_HDA_GENERIC=y # CONFIG_SND_HDA_POWER_SAVE is not set # CONFIG_SND_HDSP is not set # CONFIG_SND_HDSPM is not set -# CONFIG_SND_HIFIER is not set # CONFIG_SND_ICE1712 is not set # CONFIG_SND_ICE1724 is not set # CONFIG_SND_INTEL8X0 is not set @@ -1798,6 +1816,7 @@ CONFIG_HID_AUREAL=y # CONFIG_HID_PRODIKEYS is not set # CONFIG_HID_CYPRESS is not set # CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set # CONFIG_HID_EGALAX is not set # CONFIG_HID_ELECOM is not set # CONFIG_HID_EZKEY is not set @@ -1816,6 +1835,7 @@ CONFIG_LOGIG940_FF=y CONFIG_HID_MICROSOFT=y # CONFIG_HID_MOSART is not set # CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set # CONFIG_HID_NTRIG is not set # CONFIG_HID_ORTEK is not set # CONFIG_HID_PANTHERLORD is not set @@ -1824,6 +1844,7 @@ CONFIG_HID_MICROSOFT=y # CONFIG_HID_QUANTA is not set # CONFIG_HID_ROCCAT is not set # CONFIG_HID_ROCCAT_KONE is not set +# CONFIG_HID_ROCCAT_KONEPLUS is not set # CONFIG_HID_ROCCAT_PYRA is not set # CONFIG_HID_SAMSUNG is not set CONFIG_HID_SONY=y @@ -2006,6 +2027,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=m CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set +# CONFIG_MMC_CLKGATE is not set # # MMC/SD/SDIO Card Drivers @@ -2070,6 +2092,7 @@ CONFIG_LEDS_TRIGGERS=y # # iptables trigger is under Netfilter config (LED target) # +# CONFIG_NFC_DEVICES is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -2085,7 +2108,6 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc0" CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y CONFIG_RTC_INTF_DEV=y -# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # CONFIG_RTC_DRV_TEST is not set # @@ -2140,6 +2162,7 @@ CONFIG_STAGING=y # CONFIG_STAGING_EXCLUDE_BUILD is not set # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set +# CONFIG_USB_DABUSB is not set # CONFIG_W35UND is not set # CONFIG_PRISM2_USB is not set # CONFIG_ECHO is not set @@ -2161,12 +2184,11 @@ CONFIG_R8712_AP=y # CONFIG_USB_SERIAL_QUATECH_USB2 is not set # CONFIG_VT6655 is not set CONFIG_VT6656=m -# CONFIG_FB_UDL is not set # CONFIG_HYPERV is not set # CONFIG_VME_BUS is not set +# CONFIG_DX_SEP is not set # CONFIG_IIO is not set # CONFIG_ZRAM is not set -# CONFIG_BATMAN_ADV is not set # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set @@ -2177,7 +2199,6 @@ CONFIG_VT6656=m # CONFIG_FB_XGI is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set -# CONFIG_LIRC_I2C is not set CONFIG_LIRC_IGORPLUGUSB=m # CONFIG_LIRC_IMON is not set CONFIG_LIRC_IT87=m @@ -2199,6 +2220,7 @@ CONFIG_MACH_NO_WESTBRIDGE=y # Speakup console speech # # CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set # CONFIG_X86_PLATFORM_DEVICES is not set # @@ -2223,12 +2245,11 @@ CONFIG_EXT4_USE_FOR_EXT23=y CONFIG_JBD2=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set # CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set # CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y @@ -2251,6 +2272,8 @@ CONFIG_FUSE_FS=m CONFIG_ISO9660_FS=y CONFIG_JOLIET=y CONFIG_ZISOFS=y +CONFIG_UDF_FS=y +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -2288,6 +2311,7 @@ CONFIG_HFSPLUS_FS=m CONFIG_SQUASHFS=y # CONFIG_SQUASHFS_XATTR is not set # CONFIG_SQUASHFS_LZO is not set +CONFIG_SQUASHFS_XZ=y # CONFIG_SQUASHFS_EMBEDDED is not set CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_VXFS_FS is not set @@ -2388,7 +2412,6 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set CONFIG_NLS_UTF8=y -# CONFIG_DLM is not set # # Kernel hacking @@ -2434,6 +2457,7 @@ CONFIG_HAVE_ARCH_KMEMCHECK=y CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set # CONFIG_EARLY_PRINTK is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set # CONFIG_IOMMU_STRESS is not set CONFIG_HAVE_MMIOTRACE_SUPPORT=y CONFIG_IO_DELAY_TYPE_0X80=0 @@ -2514,7 +2538,7 @@ CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_CRC32C is not set # CONFIG_CRYPTO_CRC32C_INTEL is not set # CONFIG_CRYPTO_GHASH is not set -# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_RMD128 is not set @@ -2562,6 +2586,8 @@ CONFIG_CRYPTO_DES=y # Random Number Generation # # CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set # CONFIG_CRYPTO_HW is not set CONFIG_HAVE_KVM=y # CONFIG_VIRTUALIZATION is not set @@ -2582,7 +2608,17 @@ CONFIG_CRC32=y # CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_IA64=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y CONFIG_NLATTR=y +CONFIG_AVERAGE=y diff --git a/projects/Intel/linux/linux.i386.conf b/projects/Intel/linux/linux.i386.conf index aec8eda471..f87e57232b 100644 --- a/projects/Intel/linux/linux.i386.conf +++ b/projects/Intel/linux/linux.i386.conf @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux/i386 2.6.37.1-ck2 Kernel Configuration +# Linux/i386 2.6.38-rc5 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -44,7 +44,6 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y CONFIG_HAVE_INTEL_TXT=y -CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_X86_32_SMP=y CONFIG_X86_HT=y CONFIG_X86_TRAMPOLINE=y @@ -59,7 +58,6 @@ CONFIG_IRQ_WORK=y # # General setup # -# CONFIG_SCHED_BFS is not set CONFIG_EXPERIMENTAL=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" @@ -68,10 +66,12 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y CONFIG_HAVE_KERNEL_LZO=y # CONFIG_KERNEL_GZIP is not set # CONFIG_KERNEL_BZIP2 is not set -CONFIG_KERNEL_LZMA=y +# CONFIG_KERNEL_LZMA is not set +CONFIG_KERNEL_XZ=y # CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y @@ -88,7 +88,6 @@ CONFIG_HAVE_GENERIC_HARDIRQS=y # IRQ subsystem # CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y # CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set CONFIG_HAVE_SPARSE_IRQ=y CONFIG_GENERIC_IRQ_PROBE=y @@ -121,9 +120,12 @@ CONFIG_PROC_PID_CPUSET=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y # CONFIG_CGROUP_MEM_RES_CTLR is not set -# CONFIG_CGROUP_SCHED is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y # CONFIG_BLK_CGROUP is not set # CONFIG_NAMESPACES is not set +CONFIG_SCHED_AUTOGROUP=y # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set CONFIG_BLK_DEV_INITRD=y @@ -133,11 +135,13 @@ CONFIG_INITRAMFS_ROOT_GID=0 # CONFIG_RD_GZIP is not set # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set # CONFIG_RD_LZO is not set CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y +CONFIG_EXPERT=y CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y @@ -180,6 +184,7 @@ CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_OPTPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y +CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_DMA_API_DEBUG=y CONFIG_HAVE_HW_BREAKPOINT=y @@ -257,6 +262,7 @@ CONFIG_SMP=y CONFIG_X86_MPPARSE=y # CONFIG_X86_BIGSMP is not set # CONFIG_X86_EXTENDED_PLATFORM is not set +# CONFIG_X86_32_IRIS is not set CONFIG_SCHED_OMIT_FRAME_POINTER=y # CONFIG_PARAVIRT_GUEST is not set CONFIG_NO_BOOTMEM=y @@ -289,6 +295,7 @@ CONFIG_MCORE2=y CONFIG_X86_CPU=y CONFIG_X86_INTERNODE_CACHE_SHIFT=6 CONFIG_X86_CMPXCHG=y +CONFIG_CMPXCHG_LOCAL=y CONFIG_X86_L1_CACHE_SHIFT=6 CONFIG_X86_XADD=y CONFIG_X86_WP_WORKS_OK=y @@ -357,12 +364,17 @@ CONFIG_SPARSEMEM_STATIC=y CONFIG_HAVE_MEMBLOCK=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y +# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set # CONFIG_HIGHPTE is not set # CONFIG_X86_CHECK_BIOS_CORRUPTION is not set CONFIG_X86_RESERVE_LOW=64 @@ -377,17 +389,10 @@ CONFIG_ARCH_USES_PG_UNCACHED=y CONFIG_SECCOMP=y CONFIG_CC_STACKPROTECTOR=y # CONFIG_HZ_100 is not set -# CONFIG_HZ_250_NODEFAULT is not set -CONFIG_HZ_300=y -# CONFIG_HZ_1000 is not set -# CONFIG_HZ_1500 is not set -# CONFIG_HZ_2000 is not set -# CONFIG_HZ_3000 is not set -# CONFIG_HZ_4000 is not set -# CONFIG_HZ_5000 is not set -# CONFIG_HZ_7500 is not set -# CONFIG_HZ_10000 is not set -CONFIG_HZ=300 +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 CONFIG_SCHED_HRTICK=y # CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set @@ -408,7 +413,6 @@ CONFIG_PM=y # CONFIG_PM_DEBUG is not set CONFIG_PM_SLEEP_SMP=y CONFIG_PM_SLEEP=y -CONFIG_SUSPEND_NVS=y CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y CONFIG_PM_RUNTIME=y @@ -609,7 +613,9 @@ CONFIG_IPV6_NDISC_NODETYPE=y # CONFIG_NET_SCHED is not set # CONFIG_DCB is not set CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set CONFIG_RPS=y +CONFIG_XPS=y # # Network testing @@ -666,9 +672,11 @@ CONFIG_MAC80211_RC_MINSTREL_HT=y CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" # CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_LEDS is not set # CONFIG_MAC80211_DEBUG_MENU is not set # CONFIG_WIMAX is not set CONFIG_RFKILL=y +CONFIG_RFKILL_LEDS=y CONFIG_RFKILL_INPUT=y # CONFIG_NET_9P is not set # CONFIG_CAIF is not set @@ -780,6 +788,7 @@ CONFIG_ATA_ACPI=y CONFIG_SATA_AHCI=y CONFIG_SATA_AHCI_PLATFORM=y # CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_ACARD_AHCI is not set # CONFIG_SATA_SIL24 is not set CONFIG_ATA_SFF=y @@ -864,6 +873,7 @@ CONFIG_PATA_ACPI=y CONFIG_ATA_GENERIC=y # CONFIG_PATA_LEGACY is not set # CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set # CONFIG_FUSION is not set # @@ -957,7 +967,6 @@ CONFIG_RT2X00=m # CONFIG_RT2400PCI is not set # CONFIG_RT2500PCI is not set # CONFIG_RT61PCI is not set -CONFIG_RT2800PCI_PCI=y # CONFIG_RT2800PCI is not set CONFIG_RT2500USB=m CONFIG_RT73USB=m @@ -966,9 +975,11 @@ CONFIG_RT2X00_LIB_USB=m CONFIG_RT2X00_LIB=m CONFIG_RT2X00_LIB_FIRMWARE=y CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y # CONFIG_RT2X00_DEBUG is not set +# CONFIG_RTL8192CE is not set # CONFIG_WL1251 is not set -# CONFIG_WL12XX is not set +# CONFIG_WL12XX_MENU is not set CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set @@ -1031,6 +1042,7 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_QT2160 is not set # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_LM8323 is not set # CONFIG_KEYBOARD_MAX7359 is not set # CONFIG_KEYBOARD_MCS is not set # CONFIG_KEYBOARD_NEWTON is not set @@ -1073,13 +1085,16 @@ CONFIG_INPUT_JOYSTICK=y # CONFIG_JOYSTICK_STINGER is not set # CONFIG_JOYSTICK_TWIDJOY is not set # CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set # CONFIG_JOYSTICK_JOYDUMP is not set CONFIG_JOYSTICK_XPAD=m CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y # CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set CONFIG_INPUT_MISC=y # CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_APANEL is not set # CONFIG_INPUT_WISTRON_BTNS is not set # CONFIG_INPUT_ATLAS_BTNS is not set CONFIG_INPUT_ATI_REMOTE=m @@ -1090,9 +1105,9 @@ CONFIG_INPUT_ATI_REMOTE2=m # CONFIG_INPUT_YEALINK is not set # CONFIG_INPUT_CM109 is not set CONFIG_INPUT_UINPUT=y -# CONFIG_INPUT_WINBOND_CIR is not set # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_CMA3000 is not set # # Hardware I/O ports @@ -1155,7 +1170,6 @@ CONFIG_UNIX98_PTYS=y # CONFIG_MWAVE is not set # CONFIG_PC8736x_GPIO is not set # CONFIG_NSC_GPIO is not set -# CONFIG_CS5535_GPIO is not set # CONFIG_RAW_DRIVER is not set # CONFIG_HPET is not set # CONFIG_HANGCHECK_TIMER is not set @@ -1206,6 +1220,7 @@ CONFIG_I2C_INTEL_MID=m # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_SIMTEC is not set # CONFIG_I2C_XILINX is not set +# CONFIG_I2C_EG20T is not set # # External I2C/SMBus adapter drivers @@ -1228,6 +1243,10 @@ CONFIG_I2C_INTEL_MID=m # PPS support # # CONFIG_PPS is not set + +# +# PPS generators support +# CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIOLIB is not set # CONFIG_W1 is not set @@ -1239,6 +1258,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_BATTERY_BQ20Z75 is not set # CONFIG_BATTERY_BQ27x00 is not set # CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_HWMON_DEBUG_CHIP is not set @@ -1265,6 +1285,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_K10TEMP is not set # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_I5K_AMB is not set # CONFIG_SENSORS_F71805F is not set @@ -1299,6 +1320,7 @@ CONFIG_SENSORS_PKGTEMP=m # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set # CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT21 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMM665 is not set # CONFIG_SENSORS_DME1737 is not set @@ -1360,8 +1382,7 @@ CONFIG_VIDEO_MEDIA=y # Multimedia drivers # CONFIG_VIDEO_SAA7146=m -CONFIG_IR_CORE=y -CONFIG_VIDEO_IR=y +CONFIG_RC_CORE=y CONFIG_LIRC=y CONFIG_RC_MAP=y CONFIG_IR_NEC_DECODER=y @@ -1376,6 +1397,8 @@ CONFIG_IR_IMON=m CONFIG_IR_MCEUSB=m CONFIG_IR_NUVOTON=m CONFIG_IR_STREAMZAP=m +CONFIG_IR_WINBOND_CIR=m +# CONFIG_RC_LOOPBACK is not set CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set @@ -1570,7 +1593,6 @@ CONFIG_DVB_TDA665x=y # Tools to develop new frontends # # CONFIG_DVB_DUMMY_FE is not set -# CONFIG_DAB is not set # # Graphics support @@ -1615,6 +1637,7 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -1658,6 +1681,7 @@ CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_CARMINE is not set # CONFIG_FB_GEODE is not set # CONFIG_FB_TMIO is not set +# CONFIG_FB_UDL is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set @@ -1771,7 +1795,6 @@ CONFIG_SND_HDA_GENERIC=y # CONFIG_SND_HDA_POWER_SAVE is not set # CONFIG_SND_HDSP is not set # CONFIG_SND_HDSPM is not set -# CONFIG_SND_HIFIER is not set # CONFIG_SND_ICE1712 is not set # CONFIG_SND_ICE1724 is not set # CONFIG_SND_INTEL8X0 is not set @@ -1828,6 +1851,7 @@ CONFIG_HID_AUREAL=y # CONFIG_HID_PRODIKEYS is not set # CONFIG_HID_CYPRESS is not set # CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set # CONFIG_HID_EGALAX is not set # CONFIG_HID_ELECOM is not set # CONFIG_HID_EZKEY is not set @@ -1846,6 +1870,7 @@ CONFIG_LOGIG940_FF=y CONFIG_HID_MICROSOFT=y # CONFIG_HID_MOSART is not set # CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set # CONFIG_HID_NTRIG is not set # CONFIG_HID_ORTEK is not set # CONFIG_HID_PANTHERLORD is not set @@ -1854,6 +1879,7 @@ CONFIG_HID_MICROSOFT=y # CONFIG_HID_QUANTA is not set # CONFIG_HID_ROCCAT is not set # CONFIG_HID_ROCCAT_KONE is not set +# CONFIG_HID_ROCCAT_KONEPLUS is not set # CONFIG_HID_ROCCAT_PYRA is not set # CONFIG_HID_SAMSUNG is not set CONFIG_HID_SONY=y @@ -2033,6 +2059,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=m CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set +# CONFIG_MMC_CLKGATE is not set # # MMC/SD/SDIO Card Drivers @@ -2070,15 +2097,34 @@ CONFIG_MEMSTICK=m # CONFIG_MEMSTICK_TIFM_MS is not set CONFIG_MEMSTICK_JMICRON_38X=m CONFIG_NEW_LEDS=y -# CONFIG_LEDS_CLASS is not set +CONFIG_LEDS_CLASS=y # # LED drivers # +# CONFIG_LEDS_ALIX2 is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_CLEVO_MAIL is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_INTEL_SS4200 is not set +CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_NFC_DEVICES is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -2094,7 +2140,6 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc0" CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y CONFIG_RTC_INTF_DEV=y -# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # CONFIG_RTC_DRV_TEST is not set # @@ -2149,6 +2194,7 @@ CONFIG_STAGING=y # CONFIG_STAGING_EXCLUDE_BUILD is not set # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set +# CONFIG_USB_DABUSB is not set # CONFIG_W35UND is not set # CONFIG_PRISM2_USB is not set # CONFIG_ECHO is not set @@ -2178,12 +2224,12 @@ CONFIG_R8712_AP=y # CONFIG_USB_SERIAL_QUATECH_USB2 is not set # CONFIG_VT6655 is not set CONFIG_VT6656=m -# CONFIG_FB_UDL is not set # CONFIG_HYPERV is not set # CONFIG_VME_BUS is not set +# CONFIG_DX_SEP is not set # CONFIG_IIO is not set +# CONFIG_CS5535_GPIO is not set # CONFIG_ZRAM is not set -# CONFIG_BATMAN_ADV is not set # CONFIG_SAMSUNG_LAPTOP is not set # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set @@ -2205,6 +2251,7 @@ CONFIG_MACH_NO_WESTBRIDGE=y # Speakup console speech # # CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set # CONFIG_X86_PLATFORM_DEVICES is not set # @@ -2229,12 +2276,11 @@ CONFIG_EXT4_USE_FOR_EXT23=y CONFIG_JBD2=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set # CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set # CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y @@ -2257,6 +2303,8 @@ CONFIG_FUSE_FS=m CONFIG_ISO9660_FS=y CONFIG_JOLIET=y CONFIG_ZISOFS=y +CONFIG_UDF_FS=y +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -2294,6 +2342,7 @@ CONFIG_HFSPLUS_FS=m CONFIG_SQUASHFS=y # CONFIG_SQUASHFS_XATTR is not set # CONFIG_SQUASHFS_LZO is not set +CONFIG_SQUASHFS_XZ=y # CONFIG_SQUASHFS_EMBEDDED is not set CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_VXFS_FS is not set @@ -2394,7 +2443,6 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set CONFIG_NLS_UTF8=y -# CONFIG_DLM is not set # # Kernel hacking @@ -2440,6 +2488,7 @@ CONFIG_HAVE_ARCH_KMEMCHECK=y CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set # CONFIG_EARLY_PRINTK is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set CONFIG_DOUBLEFAULT=y # CONFIG_IOMMU_STRESS is not set CONFIG_HAVE_MMIOTRACE_SUPPORT=y @@ -2521,7 +2570,7 @@ CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_CRC32C is not set # CONFIG_CRYPTO_CRC32C_INTEL is not set # CONFIG_CRYPTO_GHASH is not set -# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_RMD128 is not set @@ -2539,6 +2588,7 @@ CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_AES_586 is not set +# CONFIG_CRYPTO_AES_NI_INTEL is not set # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set @@ -2567,6 +2617,8 @@ CONFIG_CRYPTO_DES=y # Random Number Generation # # CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set # CONFIG_CRYPTO_HW is not set CONFIG_HAVE_KVM=y # CONFIG_VIRTUALIZATION is not set @@ -2587,7 +2639,17 @@ CONFIG_CRC32=y # CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_IA64 is not set +# CONFIG_XZ_DEC_ARM is not set +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_SPARC is not set +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y CONFIG_NLATTR=y +CONFIG_AVERAGE=y diff --git a/projects/Intel/linux/linux.x86_64.conf b/projects/Intel/linux/linux.x86_64.conf index 0dd11b4834..8daaa61182 100644 --- a/projects/Intel/linux/linux.x86_64.conf +++ b/projects/Intel/linux/linux.x86_64.conf @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux/x86_64 2.6.37.1-ck2 Kernel Configuration +# Linux/x86_64 2.6.38-rc5 Kernel Configuration # CONFIG_64BIT=y # CONFIG_X86_32 is not set @@ -44,7 +44,6 @@ CONFIG_AUDIT_ARCH=y CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y CONFIG_HAVE_INTEL_TXT=y -CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_X86_64_SMP=y CONFIG_X86_HT=y CONFIG_X86_TRAMPOLINE=y @@ -59,7 +58,6 @@ CONFIG_IRQ_WORK=y # # General setup # -# CONFIG_SCHED_BFS is not set CONFIG_EXPERIMENTAL=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" @@ -68,10 +66,12 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y CONFIG_HAVE_KERNEL_LZO=y # CONFIG_KERNEL_GZIP is not set # CONFIG_KERNEL_BZIP2 is not set -CONFIG_KERNEL_LZMA=y +# CONFIG_KERNEL_LZMA is not set +CONFIG_KERNEL_XZ=y # CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y @@ -88,7 +88,6 @@ CONFIG_HAVE_GENERIC_HARDIRQS=y # IRQ subsystem # CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y # CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set CONFIG_HAVE_SPARSE_IRQ=y CONFIG_GENERIC_IRQ_PROBE=y @@ -121,9 +120,12 @@ CONFIG_PROC_PID_CPUSET=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y # CONFIG_CGROUP_MEM_RES_CTLR is not set -# CONFIG_CGROUP_SCHED is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y # CONFIG_BLK_CGROUP is not set # CONFIG_NAMESPACES is not set +CONFIG_SCHED_AUTOGROUP=y # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set CONFIG_BLK_DEV_INITRD=y @@ -133,11 +135,13 @@ CONFIG_INITRAMFS_ROOT_GID=0 # CONFIG_RD_GZIP is not set # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set # CONFIG_RD_LZO is not set CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y +CONFIG_EXPERT=y CONFIG_EMBEDDED=y CONFIG_SYSCTL_SYSCALL=y # CONFIG_KALLSYMS is not set @@ -179,6 +183,7 @@ CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_OPTPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y +CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_DMA_API_DEBUG=y CONFIG_HAVE_HW_BREAKPOINT=y @@ -266,6 +271,7 @@ CONFIG_MCORE2=y CONFIG_X86_CPU=y CONFIG_X86_INTERNODE_CACHE_SHIFT=6 CONFIG_X86_CMPXCHG=y +CONFIG_CMPXCHG_LOCAL=y CONFIG_X86_L1_CACHE_SHIFT=6 CONFIG_X86_XADD=y CONFIG_X86_WP_WORKS_OK=y @@ -325,12 +331,17 @@ CONFIG_HAVE_MEMBLOCK=y # CONFIG_MEMORY_HOTPLUG is not set CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y CONFIG_PHYS_ADDR_T_64BIT=y CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y +# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set # CONFIG_X86_CHECK_BIOS_CORRUPTION is not set CONFIG_X86_RESERVE_LOW=64 CONFIG_MTRR=y @@ -343,17 +354,10 @@ CONFIG_ARCH_USES_PG_UNCACHED=y CONFIG_SECCOMP=y CONFIG_CC_STACKPROTECTOR=y # CONFIG_HZ_100 is not set -# CONFIG_HZ_250_NODEFAULT is not set -CONFIG_HZ_300=y -# CONFIG_HZ_1000 is not set -# CONFIG_HZ_1500 is not set -# CONFIG_HZ_2000 is not set -# CONFIG_HZ_3000 is not set -# CONFIG_HZ_4000 is not set -# CONFIG_HZ_5000 is not set -# CONFIG_HZ_7500 is not set -# CONFIG_HZ_10000 is not set -CONFIG_HZ=300 +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 CONFIG_SCHED_HRTICK=y # CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set @@ -373,7 +377,6 @@ CONFIG_PM=y # CONFIG_PM_DEBUG is not set CONFIG_PM_SLEEP_SMP=y CONFIG_PM_SLEEP=y -CONFIG_SUSPEND_NVS=y CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y CONFIG_PM_RUNTIME=y @@ -560,7 +563,9 @@ CONFIG_IPV6_NDISC_NODETYPE=y # CONFIG_NET_SCHED is not set # CONFIG_DCB is not set CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set CONFIG_RPS=y +CONFIG_XPS=y # # Network testing @@ -617,9 +622,11 @@ CONFIG_MAC80211_RC_MINSTREL_HT=y CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" # CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_LEDS is not set # CONFIG_MAC80211_DEBUG_MENU is not set # CONFIG_WIMAX is not set CONFIG_RFKILL=y +CONFIG_RFKILL_LEDS=y CONFIG_RFKILL_INPUT=y # CONFIG_NET_9P is not set # CONFIG_CAIF is not set @@ -731,6 +738,7 @@ CONFIG_ATA_ACPI=y CONFIG_SATA_AHCI=y CONFIG_SATA_AHCI_PLATFORM=y # CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_ACARD_AHCI is not set # CONFIG_SATA_SIL24 is not set CONFIG_ATA_SFF=y @@ -814,6 +822,7 @@ CONFIG_PATA_ACPI=y CONFIG_ATA_GENERIC=y # CONFIG_PATA_LEGACY is not set # CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set # CONFIG_FUSION is not set # @@ -907,7 +916,6 @@ CONFIG_RT2X00=m # CONFIG_RT2400PCI is not set # CONFIG_RT2500PCI is not set # CONFIG_RT61PCI is not set -CONFIG_RT2800PCI_PCI=y # CONFIG_RT2800PCI is not set CONFIG_RT2500USB=m CONFIG_RT73USB=m @@ -916,9 +924,11 @@ CONFIG_RT2X00_LIB_USB=m CONFIG_RT2X00_LIB=m CONFIG_RT2X00_LIB_FIRMWARE=y CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y # CONFIG_RT2X00_DEBUG is not set +# CONFIG_RTL8192CE is not set # CONFIG_WL1251 is not set -# CONFIG_WL12XX is not set +# CONFIG_WL12XX_MENU is not set CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set @@ -981,6 +991,7 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_QT2160 is not set # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_LM8323 is not set # CONFIG_KEYBOARD_MAX7359 is not set # CONFIG_KEYBOARD_MCS is not set # CONFIG_KEYBOARD_NEWTON is not set @@ -1023,13 +1034,16 @@ CONFIG_INPUT_JOYSTICK=y # CONFIG_JOYSTICK_STINGER is not set # CONFIG_JOYSTICK_TWIDJOY is not set # CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set # CONFIG_JOYSTICK_JOYDUMP is not set CONFIG_JOYSTICK_XPAD=m CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y # CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set CONFIG_INPUT_MISC=y # CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_APANEL is not set # CONFIG_INPUT_ATLAS_BTNS is not set CONFIG_INPUT_ATI_REMOTE=m CONFIG_INPUT_ATI_REMOTE2=m @@ -1039,9 +1053,9 @@ CONFIG_INPUT_ATI_REMOTE2=m # CONFIG_INPUT_YEALINK is not set # CONFIG_INPUT_CM109 is not set CONFIG_INPUT_UINPUT=y -# CONFIG_INPUT_WINBOND_CIR is not set # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_CMA3000 is not set # # Hardware I/O ports @@ -1151,6 +1165,7 @@ CONFIG_I2C_INTEL_MID=m # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_SIMTEC is not set # CONFIG_I2C_XILINX is not set +# CONFIG_I2C_EG20T is not set # # External I2C/SMBus adapter drivers @@ -1172,6 +1187,10 @@ CONFIG_I2C_INTEL_MID=m # PPS support # # CONFIG_PPS is not set + +# +# PPS generators support +# CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_GPIOLIB is not set # CONFIG_W1 is not set @@ -1183,6 +1202,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_BATTERY_BQ20Z75 is not set # CONFIG_BATTERY_BQ27x00 is not set # CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_HWMON_DEBUG_CHIP is not set @@ -1209,6 +1229,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_K10TEMP is not set # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_I5K_AMB is not set # CONFIG_SENSORS_F71805F is not set @@ -1243,6 +1264,7 @@ CONFIG_SENSORS_PKGTEMP=m # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set # CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT21 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMM665 is not set # CONFIG_SENSORS_DME1737 is not set @@ -1304,8 +1326,7 @@ CONFIG_VIDEO_MEDIA=y # Multimedia drivers # CONFIG_VIDEO_SAA7146=m -CONFIG_IR_CORE=y -CONFIG_VIDEO_IR=y +CONFIG_RC_CORE=y CONFIG_LIRC=y CONFIG_RC_MAP=y CONFIG_IR_NEC_DECODER=y @@ -1320,6 +1341,8 @@ CONFIG_IR_IMON=m CONFIG_IR_MCEUSB=m CONFIG_IR_NUVOTON=m CONFIG_IR_STREAMZAP=m +CONFIG_IR_WINBOND_CIR=m +# CONFIG_RC_LOOPBACK is not set CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set @@ -1517,7 +1540,6 @@ CONFIG_DVB_TDA665x=y # Tools to develop new frontends # # CONFIG_DVB_DUMMY_FE is not set -# CONFIG_DAB is not set # # Graphics support @@ -1556,6 +1578,7 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -1598,6 +1621,7 @@ CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_CARMINE is not set # CONFIG_FB_GEODE is not set # CONFIG_FB_TMIO is not set +# CONFIG_FB_UDL is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set @@ -1711,7 +1735,6 @@ CONFIG_SND_HDA_GENERIC=y # CONFIG_SND_HDA_POWER_SAVE is not set # CONFIG_SND_HDSP is not set # CONFIG_SND_HDSPM is not set -# CONFIG_SND_HIFIER is not set # CONFIG_SND_ICE1712 is not set # CONFIG_SND_ICE1724 is not set # CONFIG_SND_INTEL8X0 is not set @@ -1767,6 +1790,7 @@ CONFIG_HID_AUREAL=y # CONFIG_HID_PRODIKEYS is not set # CONFIG_HID_CYPRESS is not set # CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set # CONFIG_HID_EGALAX is not set # CONFIG_HID_ELECOM is not set # CONFIG_HID_EZKEY is not set @@ -1785,6 +1809,7 @@ CONFIG_LOGIG940_FF=y CONFIG_HID_MICROSOFT=y # CONFIG_HID_MOSART is not set # CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set # CONFIG_HID_NTRIG is not set # CONFIG_HID_ORTEK is not set # CONFIG_HID_PANTHERLORD is not set @@ -1793,6 +1818,7 @@ CONFIG_HID_MICROSOFT=y # CONFIG_HID_QUANTA is not set # CONFIG_HID_ROCCAT is not set # CONFIG_HID_ROCCAT_KONE is not set +# CONFIG_HID_ROCCAT_KONEPLUS is not set # CONFIG_HID_ROCCAT_PYRA is not set # CONFIG_HID_SAMSUNG is not set CONFIG_HID_SONY=y @@ -1972,6 +1998,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=m CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set +# CONFIG_MMC_CLKGATE is not set # # MMC/SD/SDIO Card Drivers @@ -2009,15 +2036,34 @@ CONFIG_MEMSTICK=m # CONFIG_MEMSTICK_TIFM_MS is not set CONFIG_MEMSTICK_JMICRON_38X=m CONFIG_NEW_LEDS=y -# CONFIG_LEDS_CLASS is not set +CONFIG_LEDS_CLASS=y # # LED drivers # +# CONFIG_LEDS_ALIX2 is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_CLEVO_MAIL is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_INTEL_SS4200 is not set +CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_NFC_DEVICES is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -2033,7 +2079,6 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc0" CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y CONFIG_RTC_INTF_DEV=y -# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # CONFIG_RTC_DRV_TEST is not set # @@ -2088,6 +2133,7 @@ CONFIG_STAGING=y # CONFIG_STAGING_EXCLUDE_BUILD is not set # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set +# CONFIG_USB_DABUSB is not set # CONFIG_W35UND is not set # CONFIG_PRISM2_USB is not set # CONFIG_ECHO is not set @@ -2117,12 +2163,11 @@ CONFIG_R8712_AP=y # CONFIG_USB_SERIAL_QUATECH_USB2 is not set # CONFIG_VT6655 is not set CONFIG_VT6656=m -# CONFIG_FB_UDL is not set # CONFIG_HYPERV is not set # CONFIG_VME_BUS is not set +# CONFIG_DX_SEP is not set # CONFIG_IIO is not set # CONFIG_ZRAM is not set -# CONFIG_BATMAN_ADV is not set # CONFIG_SAMSUNG_LAPTOP is not set # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set @@ -2144,6 +2189,7 @@ CONFIG_MACH_NO_WESTBRIDGE=y # Speakup console speech # # CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set # CONFIG_X86_PLATFORM_DEVICES is not set # @@ -2168,12 +2214,11 @@ CONFIG_EXT4_USE_FOR_EXT23=y CONFIG_JBD2=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set # CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set # CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y @@ -2196,6 +2241,8 @@ CONFIG_FUSE_FS=m CONFIG_ISO9660_FS=y CONFIG_JOLIET=y CONFIG_ZISOFS=y +CONFIG_UDF_FS=y +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -2233,6 +2280,7 @@ CONFIG_HFSPLUS_FS=m CONFIG_SQUASHFS=y # CONFIG_SQUASHFS_XATTR is not set # CONFIG_SQUASHFS_LZO is not set +CONFIG_SQUASHFS_XZ=y # CONFIG_SQUASHFS_EMBEDDED is not set CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_VXFS_FS is not set @@ -2333,7 +2381,6 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set CONFIG_NLS_UTF8=y -# CONFIG_DLM is not set # # Kernel hacking @@ -2379,6 +2426,7 @@ CONFIG_HAVE_ARCH_KMEMCHECK=y CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set # CONFIG_EARLY_PRINTK is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set # CONFIG_IOMMU_STRESS is not set CONFIG_HAVE_MMIOTRACE_SUPPORT=y CONFIG_IO_DELAY_TYPE_0X80=0 @@ -2459,7 +2507,7 @@ CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_CRC32C is not set # CONFIG_CRYPTO_CRC32C_INTEL is not set # CONFIG_CRYPTO_GHASH is not set -# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_RMD128 is not set @@ -2507,6 +2555,8 @@ CONFIG_CRYPTO_DES=y # Random Number Generation # # CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set # CONFIG_CRYPTO_HW is not set CONFIG_HAVE_KVM=y # CONFIG_VIRTUALIZATION is not set @@ -2527,7 +2577,17 @@ CONFIG_CRC32=y # CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_IA64=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y CONFIG_NLATTR=y +CONFIG_AVERAGE=y From fc1280453782455842c5a536b0828bca20faaaf9 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 00:35:03 +0100 Subject: [PATCH 02/16] w_scan: add patch to fix build agains linux-2.6.38 Signed-off-by: Stephan Raue --- ...can-20110206-001-remove_videodev_include-0.1.patch | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 packages/debug/w_scan/patches/w_scan-20110206-001-remove_videodev_include-0.1.patch diff --git a/packages/debug/w_scan/patches/w_scan-20110206-001-remove_videodev_include-0.1.patch b/packages/debug/w_scan/patches/w_scan-20110206-001-remove_videodev_include-0.1.patch new file mode 100644 index 0000000000..9c3cbbe1f0 --- /dev/null +++ b/packages/debug/w_scan/patches/w_scan-20110206-001-remove_videodev_include-0.1.patch @@ -0,0 +1,11 @@ +diff -Naur w_scan-20110206/countries.c w_scan-20110206.patch/countries.c +--- w_scan-20110206/countries.c 2011-02-05 20:03:50.000000000 +0100 ++++ w_scan-20110206.patch/countries.c 2011-02-21 23:21:51.194553010 +0100 +@@ -31,7 +31,6 @@ + #include + #include + #include +-#include + #include + + #ifdef VDRVERSNUM From bc2833c2e4097c888ef6da9ff350decf55beda8f Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 00:35:27 +0100 Subject: [PATCH 03/16] udev: add patch to fix build against linux-2.6.38 Signed-off-by: Stephan Raue --- .../patches/udev-166-drop_obsolete_v4l1.patch | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 packages/sysutils/udev/patches/udev-166-drop_obsolete_v4l1.patch diff --git a/packages/sysutils/udev/patches/udev-166-drop_obsolete_v4l1.patch b/packages/sysutils/udev/patches/udev-166-drop_obsolete_v4l1.patch new file mode 100644 index 0000000000..e445ecadf5 --- /dev/null +++ b/packages/sysutils/udev/patches/udev-166-drop_obsolete_v4l1.patch @@ -0,0 +1,39 @@ +diff -Naur udev-166/extras/v4l_id/v4l_id.c udev-166a/extras/v4l_id/v4l_id.c +--- udev-166/extras/v4l_id/v4l_id.c 2009-12-03 13:45:03.000000000 +0100 ++++ udev-166a/extras/v4l_id/v4l_id.c 2011-02-12 12:02:38.183834848 +0100 +@@ -28,7 +28,6 @@ + #include + #include + #include +-#include + #include + + int main (int argc, char *argv[]) +@@ -39,7 +38,6 @@ + }; + int fd; + char *device; +- struct video_capability v1cap; + struct v4l2_capability v2cap; + + while (1) { +@@ -82,19 +80,6 @@ + if ((v2cap.capabilities & V4L2_CAP_RADIO) > 0) + printf("radio:"); + printf("\n"); +- } else if (ioctl (fd, VIDIOCGCAP, &v1cap) == 0) { +- printf("ID_V4L_VERSION=1\n"); +- printf("ID_V4L_PRODUCT=%s\n", v1cap.name); +- printf("ID_V4L_CAPABILITIES=:"); +- if ((v1cap.type & VID_TYPE_CAPTURE) > 0) +- printf("capture:"); +- if ((v1cap.type & VID_TYPE_OVERLAY) > 0) +- printf("video_overlay:"); +- if (v1cap.audios > 0) +- printf("audio:"); +- if ((v1cap.type & VID_TYPE_TUNER) > 0) +- printf("tuner:"); +- printf("\n"); + } + + close (fd); From 605b0591f1dd52e2cb25f33d487ef0455522684b Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 00:36:02 +0100 Subject: [PATCH 04/16] new package: add package 'xz' Signed-off-by: Stephan Raue --- packages/toolchain/archivers/xz/build | 37 +++++++++++++++++++++++++++ packages/toolchain/archivers/xz/meta | 36 ++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100755 packages/toolchain/archivers/xz/build create mode 100644 packages/toolchain/archivers/xz/meta diff --git a/packages/toolchain/archivers/xz/build b/packages/toolchain/archivers/xz/build new file mode 100755 index 0000000000..30d816d518 --- /dev/null +++ b/packages/toolchain/archivers/xz/build @@ -0,0 +1,37 @@ +#!/bin/sh + +################################################################################ +# 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 +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This Program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +. config/options $1 + +setup_toolchain host + +cd $PKG_BUILD +./configure --host=$HOST_NAME \ + --build=$HOST_NAME \ + --prefix=$ROOT/$TOOLCHAIN \ + --disable-lzmadec \ + --disable-lzmainfo \ + --disable-lzma-links \ + --disable-scripts \ + --disable-nls +make +make install diff --git a/packages/toolchain/archivers/xz/meta b/packages/toolchain/archivers/xz/meta new file mode 100644 index 0000000000..a9809e904f --- /dev/null +++ b/packages/toolchain/archivers/xz/meta @@ -0,0 +1,36 @@ +################################################################################ +# 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 +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This Program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ + +PKG_NAME="xz" +PKG_VERSION="5.0.1" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="http://tukaani.org/xz/" +PKG_URL="http://tukaani.org/xz/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_DEPENDS="" +PKG_BUILD_DEPENDS="ccache" +PKG_PRIORITY="optional" +PKG_SECTION="toolchain/archivers" +PKG_SHORTDESC="xz: a free general-purpose data compression software with high compression ratio." +PKG_LONGDESC="XZ Utils is free general-purpose data compression software with high compression ratio. XZ Utils were written for POSIX-like systems, but also work on some not-so-POSIX systems. XZ Utils are the successor to LZMA Utils." +PKG_IS_ADDON="no" + +PKG_AUTORECONF="no" From 7e7fc9ae5f92a9bd01c2dbcf2406005445c6796d Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 00:41:02 +0100 Subject: [PATCH 05/16] squashfs: change from lzma to xz support Signed-off-by: Stephan Raue --- packages/toolchain/sysutils/squashfs/build | 9 ++--- packages/toolchain/sysutils/squashfs/meta | 7 ++-- ...ch => squashfs-a56f344-defaults-0.1.patch} | 34 +++++++++---------- 3 files changed, 23 insertions(+), 27 deletions(-) rename packages/toolchain/sysutils/squashfs/patches/{squashfs-4.1-defaults-0.1.patch => squashfs-a56f344-defaults-0.1.patch} (57%) diff --git a/packages/toolchain/sysutils/squashfs/build b/packages/toolchain/sysutils/squashfs/build index 9706da1080..a810a07d98 100755 --- a/packages/toolchain/sysutils/squashfs/build +++ b/packages/toolchain/sysutils/squashfs/build @@ -22,17 +22,12 @@ . config/options $1 -$SCRIPTS/unpack lzma - -LZMA_DIR=`ls -d $ROOT/$BUILD/lzma*` - setup_toolchain host cd $BUILD/$1*/squashfs-tools - make mksquashfs \ - LZMA_SUPPORT=1 LZMA_DIR=$LZMA_DIR \ - INCLUDEDIR="-I. -I$ROOT/$TOOLCHAIN/include -I$LZMA_DIR/C" + XZ_SUPPORT=1 \ + INCLUDEDIR="-I. -I$ROOT/$TOOLCHAIN/include" mkdir -p $ROOT/$TOOLCHAIN/bin cp mksquashfs $ROOT/$TOOLCHAIN/bin diff --git a/packages/toolchain/sysutils/squashfs/meta b/packages/toolchain/sysutils/squashfs/meta index b7392944b0..f7cc61d63e 100644 --- a/packages/toolchain/sysutils/squashfs/meta +++ b/packages/toolchain/sysutils/squashfs/meta @@ -19,14 +19,15 @@ ################################################################################ PKG_NAME="squashfs" -PKG_VERSION="4.1" +PKG_VERSION="a56f344" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" PKG_SITE="http://squashfs.sourceforge.net/" -PKG_URL="$SOURCEFORGE_SRC/squashfs/squashfs/${PKG_NAME}${PKG_VERSION}/${PKG_NAME}${PKG_VERSION}.tar.gz" +#PKG_URL="$SOURCEFORGE_SRC/squashfs/squashfs/${PKG_NAME}${PKG_VERSION}/${PKG_NAME}${PKG_VERSION}.tar.gz" +PKG_URL="$OPENELEC_SRC/${PKG_NAME}-${PKG_VERSION}.tar.gz" PKG_DEPENDS="" -PKG_BUILD_DEPENDS="ccache" +PKG_BUILD_DEPENDS="ccache xz" PKG_PRIORITY="optional" PKG_SECTION="toolchain/sysutils" PKG_SHORTDESC="squashfs-tools: A compressed read-only filesystem for Linux" diff --git a/packages/toolchain/sysutils/squashfs/patches/squashfs-4.1-defaults-0.1.patch b/packages/toolchain/sysutils/squashfs/patches/squashfs-a56f344-defaults-0.1.patch similarity index 57% rename from packages/toolchain/sysutils/squashfs/patches/squashfs-4.1-defaults-0.1.patch rename to packages/toolchain/sysutils/squashfs/patches/squashfs-a56f344-defaults-0.1.patch index 57ac724d08..e53e3317c3 100644 --- a/packages/toolchain/sysutils/squashfs/patches/squashfs-4.1-defaults-0.1.patch +++ b/packages/toolchain/sysutils/squashfs/patches/squashfs-a56f344-defaults-0.1.patch @@ -1,7 +1,7 @@ -diff -Naur squashfs4.1/squashfs-tools/Makefile squashfs4.1.patch/squashfs-tools/Makefile ---- squashfs4.1/squashfs-tools/Makefile 2010-09-21 00:11:47.000000000 +0200 -+++ squashfs4.1.patch/squashfs-tools/Makefile 2010-10-12 19:13:52.504611650 +0200 -@@ -64,7 +64,7 @@ +diff -Naur squashfs-a56f344/squashfs-tools/Makefile squashfs-a56f344.patch/squashfs-tools/Makefile +--- squashfs-a56f344/squashfs-tools/Makefile 2011-02-21 23:58:19.000000000 +0100 ++++ squashfs-a56f344.patch/squashfs-tools/Makefile 2011-02-22 00:05:33.197451875 +0100 +@@ -77,7 +77,7 @@ # If your C library or build/target environment doesn't support XATTRs then # comment out the next line to build Mksquashfs and Unsquashfs without XATTR # support @@ -10,7 +10,7 @@ diff -Naur squashfs4.1/squashfs-tools/Makefile squashfs4.1.patch/squashfs-tools/ # Select whether you wish xattrs to be stored by Mksquashfs and extracted # by Unsquashfs by default. If selected users can disable xattr support by -@@ -72,7 +72,7 @@ +@@ -85,7 +85,7 @@ # # If unselected, Mksquashfs/Unsquashfs won't store and extract xattrs by # default. Users can enable xattrs by using the -xattrs option. @@ -19,7 +19,7 @@ diff -Naur squashfs4.1/squashfs-tools/Makefile squashfs4.1.patch/squashfs-tools/ ############################################### -@@ -87,7 +87,7 @@ +@@ -100,7 +100,7 @@ UNSQUASHFS_OBJS = unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o \ unsquash-4.o swap.o compressor.o @@ -27,22 +27,22 @@ diff -Naur squashfs4.1/squashfs-tools/Makefile squashfs4.1.patch/squashfs-tools/ +CFLAGS += $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ -D_GNU_SOURCE -DCOMP_DEFAULT=\"$(COMP_DEFAULT)\" -O2 -Wall - LIBS = -@@ -175,7 +175,7 @@ + LIBS = -lpthread -lm +@@ -196,7 +196,7 @@ all: mksquashfs unsquashfs mksquashfs: $(MKSQUASHFS_OBJS) -- $(CC) $(MKSQUASHFS_OBJS) -lpthread -lm $(LIBS) -o $@ -+ $(CC) $(CFLAGS) $(LDFLAGS) $(MKSQUASHFS_OBJS) -lpthread -lm $(LIBS) -o $@ +- $(CC) $(MKSQUASHFS_OBJS) $(LIBS) -o $@ ++ $(CC) $(CFLAGS) $(LDFLAGS) $(MKSQUASHFS_OBJS) $(LIBS) -o $@ - mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \ - squashfs_swap.h xattr.h -@@ -195,7 +195,7 @@ - read_xattrs.o: xattr.h + mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h sort.h squashfs_swap.h \ + xattr.h pseudo.h compressor.h +@@ -227,7 +227,7 @@ + xz_wrapper.o: xz_wrapper.c compressor.h squashfs_fs.h unsquashfs: $(UNSQUASHFS_OBJS) -- $(CC) $(UNSQUASHFS_OBJS) -lpthread -lm $(LIBS) -o $@ -+ $(CC) $(CFLAGS) $(LDFLAGS) $(UNSQUASHFS_OBJS) -lpthread -lm $(LIBS) -o $@ +- $(CC) $(UNSQUASHFS_OBJS) $(LIBS) -o $@ ++ $(CC) $(CFLAGS) $(LDFLAGS) $(UNSQUASHFS_OBJS) $(LIBS) -o $@ unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h \ - squashfs_compat.h global.h xattr.h + squashfs_compat.h xattr.h read_fs.h compressor.h From 4c82bfc1adccc95d1833599c0dd22488969c7796 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 00:41:31 +0100 Subject: [PATCH 06/16] lzma: remove package 'lzma' Signed-off-by: Stephan Raue --- packages/toolchain/archivers/lzma/meta | 36 -------------------------- 1 file changed, 36 deletions(-) delete mode 100644 packages/toolchain/archivers/lzma/meta diff --git a/packages/toolchain/archivers/lzma/meta b/packages/toolchain/archivers/lzma/meta deleted file mode 100644 index 0a6976ed17..0000000000 --- a/packages/toolchain/archivers/lzma/meta +++ /dev/null @@ -1,36 +0,0 @@ -################################################################################ -# 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 -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ - -PKG_NAME="lzma" -PKG_VERSION="907" -PKG_REV="1" -PKG_ARCH="any" -PKG_LICENSE="GPL" -PKG_SITE="http://www.7-zip.org/sdk.html" -PKG_URL="$OPENELEC_SRC/$PKG_NAME-$PKG_VERSION.tar.bz2" -PKG_DEPENDS="" -PKG_BUILD_DEPENDS="ccache" -PKG_PRIORITY="optional" -PKG_SECTION="toolchain/archivers" -PKG_SHORTDESC="lzma: A file compression utility using the LZMA algorithm" -PKG_LONGDESC="LZMA utils in a nutshell. Average compression ratio of LZMA is about 30% better than that of gzip, and 15% better than that of bzip2. Decompression speed is only little slower than that of gzip, being two to five times faster than bzip2. In fast mode, compresses faster than bzip2 with a comparable compression ratio. However achieving the best compression ratios takes four to even twelve times longer than with bzip2. However, this doesn't affect decompressing speed." -PKG_IS_ADDON="no" - -PKG_AUTORECONF="no" From 15117b4588763671aa283e150ab75fb1a289b80c Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 00:43:15 +0100 Subject: [PATCH 07/16] scripts/image_squashfs: change to xz support (disabled) Signed-off-by: Stephan Raue --- scripts/image_squashfs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/image_squashfs b/scripts/image_squashfs index 523144dd35..94ac5feb7e 100755 --- a/scripts/image_squashfs +++ b/scripts/image_squashfs @@ -37,7 +37,7 @@ mkdir -p $TARGET_IMG cp -PR $BUILD/linux-*/arch/x86/boot/bzImage $TARGET_IMG/$DISTRONAME-$TARGET_VERSION.kernel echo "rm -rf $TARGET_IMG/$DISTRONAME-$TARGET_VERSION.system" >> $FAKEROOT_SCRIPT -# echo "$ROOT/$TOOLCHAIN/bin/mksquashfs $BUILD/image/system $TARGET_IMG/$DISTRONAME-$TARGET_VERSION.system -noappend -comp lzma" >> $FAKEROOT_SCRIPT +# echo "$ROOT/$TOOLCHAIN/bin/mksquashfs $BUILD/image/system $TARGET_IMG/$DISTRONAME-$TARGET_VERSION.system -noappend -comp xz" >> $FAKEROOT_SCRIPT echo "$ROOT/$TOOLCHAIN/bin/mksquashfs $BUILD/image/system $TARGET_IMG/$DISTRONAME-$TARGET_VERSION.system -noappend" >> $FAKEROOT_SCRIPT $ROOT/$TOOLCHAIN/bin/fakeroot -- $FAKEROOT_SCRIPT chmod 0644 $TARGET_IMG/$DISTRONAME-$TARGET_VERSION.system From 84edbe314e08b8a9b34311e28ce72369ee1700d3 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 01:29:04 +0100 Subject: [PATCH 08/16] linux: remove now unneeded patch Signed-off-by: Stephan Raue --- ...-Pioneer_DVR-212D_failed_xfermode-0.1.patch.ignore | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 packages/linux/patches/linux-2.6.38-rc5-061-Pioneer_DVR-212D_failed_xfermode-0.1.patch.ignore diff --git a/packages/linux/patches/linux-2.6.38-rc5-061-Pioneer_DVR-212D_failed_xfermode-0.1.patch.ignore b/packages/linux/patches/linux-2.6.38-rc5-061-Pioneer_DVR-212D_failed_xfermode-0.1.patch.ignore deleted file mode 100644 index b1bc6cf05e..0000000000 --- a/packages/linux/patches/linux-2.6.38-rc5-061-Pioneer_DVR-212D_failed_xfermode-0.1.patch.ignore +++ /dev/null @@ -1,11 +0,0 @@ -diff -Naur linux-2.6.37/drivers/ata/libata-core.c linux-2.6.37.patch/drivers/ata/libata-core.c ---- linux-2.6.37/drivers/ata/libata-core.c 2011-01-05 01:50:19.000000000 +0100 -+++ linux-2.6.37.patch/drivers/ata/libata-core.c 2011-01-11 14:39:29.399037122 +0100 -@@ -4138,6 +4138,7 @@ - * device and controller are SATA. - */ - { "PIONEER DVD-RW DVRTD08", "1.00", ATA_HORKAGE_NOSETXFER }, -+ { "PIONEER DVD-RW DVR-212D", "1.28", ATA_HORKAGE_NOSETXFER }, - - /* End Marker */ - { } From d81c647f7af72b7e6c10c11e3486d8c375cbe478 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 01:29:43 +0100 Subject: [PATCH 09/16] linux: fix and reenable Pioneer DVR-216D fix Signed-off-by: Stephan Raue --- ...rc5-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch | 11 +++++++++++ ...-Pioneer_DVR-216D_failed_xfermode-0.1.patch.ignore | 11 ----------- 2 files changed, 11 insertions(+), 11 deletions(-) create mode 100644 packages/linux/patches/linux-2.6.38-rc5-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch delete mode 100644 packages/linux/patches/linux-2.6.38-rc5-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch.ignore diff --git a/packages/linux/patches/linux-2.6.38-rc5-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch b/packages/linux/patches/linux-2.6.38-rc5-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch new file mode 100644 index 0000000000..432a72d48d --- /dev/null +++ b/packages/linux/patches/linux-2.6.38-rc5-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch @@ -0,0 +1,11 @@ +diff -Naur linux-2.6.38-rc5/drivers/ata/libata-core.c linux-2.6.38-rc5.patch/drivers/ata/libata-core.c +--- linux-2.6.38-rc5/drivers/ata/libata-core.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.patch/drivers/ata/libata-core.c 2011-02-22 00:57:25.789636966 +0100 +@@ -4139,6 +4139,7 @@ + */ + { "PIONEER DVD-RW DVRTD08", "1.00", ATA_HORKAGE_NOSETXFER }, + { "PIONEER DVD-RW DVR-212D", "1.28", ATA_HORKAGE_NOSETXFER }, ++ { "PIONEER DVD-RW DVR-216D", "1.07", ATA_HORKAGE_NOSETXFER }, + + /* End Marker */ + { } diff --git a/packages/linux/patches/linux-2.6.38-rc5-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch.ignore b/packages/linux/patches/linux-2.6.38-rc5-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch.ignore deleted file mode 100644 index b7f8b03723..0000000000 --- a/packages/linux/patches/linux-2.6.38-rc5-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch.ignore +++ /dev/null @@ -1,11 +0,0 @@ -diff -Naur linux-2.6.37/drivers/ata/libata-core.c linux-2.6.37.patch/drivers/ata/libata-core.c ---- linux-2.6.37/drivers/ata/libata-core.c 2011-01-11 16:44:09.983014222 +0100 -+++ linux-2.6.37.patch/drivers/ata/libata-core.c 2011-01-11 16:43:58.733876132 +0100 -@@ -4139,6 +4139,7 @@ - */ - { "PIONEER DVD-RW DVRTD08", "1.00", ATA_HORKAGE_NOSETXFER }, - { "PIONEER DVD-RW DVR-212D", "1.28", ATA_HORKAGE_NOSETXFER }, -+ { "PIONEER DVD-RW DVR-216D", "1.07", ATA_HORKAGE_NOSETXFER }, - - /* End Marker */ - { } From a3aaf06e79578fd8874fbb47900cd58630f5cc87 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 02:31:15 +0100 Subject: [PATCH 10/16] linux: update nouveau patch Signed-off-by: Stephan Raue --- ...drm_nouveau_upstream-20110111.patch.ignore | 29027 ---------------- ...c5-110-drm_nouveau_upstream-20110222.patch | 4649 +++ 2 files changed, 4649 insertions(+), 29027 deletions(-) delete mode 100644 packages/linux/patches/linux-2.6.38-rc5-110-drm_nouveau_upstream-20110111.patch.ignore create mode 100644 packages/linux/patches/linux-2.6.38-rc5-110-drm_nouveau_upstream-20110222.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-110-drm_nouveau_upstream-20110111.patch.ignore b/packages/linux/patches/linux-2.6.38-rc5-110-drm_nouveau_upstream-20110111.patch.ignore deleted file mode 100644 index db7c4af7f5..0000000000 --- a/packages/linux/patches/linux-2.6.38-rc5-110-drm_nouveau_upstream-20110111.patch.ignore +++ /dev/null @@ -1,29027 +0,0 @@ -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/drm_crtc_helper.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/drm_crtc_helper.c ---- linux-2.6.37-rc3/drivers/gpu/drm/drm_crtc_helper.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/drm_crtc_helper.c 2011-01-07 14:22:17.000000000 +0100 -@@ -336,7 +336,7 @@ - struct drm_framebuffer *old_fb) - { - struct drm_device *dev = crtc->dev; -- struct drm_display_mode *adjusted_mode, saved_mode; -+ struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode; - struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - struct drm_encoder_helper_funcs *encoder_funcs; - int saved_x, saved_y; -@@ -350,6 +350,7 @@ - if (!crtc->enabled) - return true; - -+ saved_hwmode = crtc->hwmode; - saved_mode = crtc->mode; - saved_x = crtc->x; - saved_y = crtc->y; -@@ -427,11 +428,21 @@ - - } - -+ /* Store real post-adjustment hardware mode. */ -+ crtc->hwmode = *adjusted_mode; -+ -+ /* Calculate and store various constants which -+ * are later needed by vblank and swap-completion -+ * timestamping. They are derived from true hwmode. -+ */ -+ drm_calc_timestamping_constants(crtc); -+ - /* XXX free adjustedmode */ - drm_mode_destroy(dev, adjusted_mode); - /* FIXME: add subpixel order */ - done: - if (!ret) { -+ crtc->hwmode = saved_hwmode; - crtc->mode = saved_mode; - crtc->x = saved_x; - crtc->y = saved_y; -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/drm_irq.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/drm_irq.c ---- linux-2.6.37-rc3/drivers/gpu/drm/drm_irq.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/drm_irq.c 2011-01-07 14:22:17.000000000 +0100 -@@ -40,6 +40,22 @@ - #include - - #include -+ -+/* Access macro for slots in vblank timestamp ringbuffer. */ -+#define vblanktimestamp(dev, crtc, count) ( \ -+ (dev)->_vblank_time[(crtc) * DRM_VBLANKTIME_RBSIZE + \ -+ ((count) % DRM_VBLANKTIME_RBSIZE)]) -+ -+/* Retry timestamp calculation up to 3 times to satisfy -+ * drm_timestamp_precision before giving up. -+ */ -+#define DRM_TIMESTAMP_MAXRETRIES 3 -+ -+/* Threshold in nanoseconds for detection of redundant -+ * vblank irq in drm_handle_vblank(). 1 msec should be ok. -+ */ -+#define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000 -+ - /** - * Get interrupt from bus id. - * -@@ -77,6 +93,87 @@ - return 0; - } - -+/* -+ * Clear vblank timestamp buffer for a crtc. -+ */ -+static void clear_vblank_timestamps(struct drm_device *dev, int crtc) -+{ -+ memset(&dev->_vblank_time[crtc * DRM_VBLANKTIME_RBSIZE], 0, -+ DRM_VBLANKTIME_RBSIZE * sizeof(struct timeval)); -+} -+ -+/* -+ * Disable vblank irq's on crtc, make sure that last vblank count -+ * of hardware and corresponding consistent software vblank counter -+ * are preserved, even if there are any spurious vblank irq's after -+ * disable. -+ */ -+static void vblank_disable_and_save(struct drm_device *dev, int crtc) -+{ -+ unsigned long irqflags; -+ u32 vblcount; -+ s64 diff_ns; -+ int vblrc; -+ struct timeval tvblank; -+ -+ /* Prevent vblank irq processing while disabling vblank irqs, -+ * so no updates of timestamps or count can happen after we've -+ * disabled. Needed to prevent races in case of delayed irq's. -+ * Disable preemption, so vblank_time_lock is held as short as -+ * possible, even under a kernel with PREEMPT_RT patches. -+ */ -+ preempt_disable(); -+ spin_lock_irqsave(&dev->vblank_time_lock, irqflags); -+ -+ dev->driver->disable_vblank(dev, crtc); -+ dev->vblank_enabled[crtc] = 0; -+ -+ /* No further vblank irq's will be processed after -+ * this point. Get current hardware vblank count and -+ * vblank timestamp, repeat until they are consistent. -+ * -+ * FIXME: There is still a race condition here and in -+ * drm_update_vblank_count() which can cause off-by-one -+ * reinitialization of software vblank counter. If gpu -+ * vblank counter doesn't increment exactly at the leading -+ * edge of a vblank interval, then we can lose 1 count if -+ * we happen to execute between start of vblank and the -+ * delayed gpu counter increment. -+ */ -+ do { -+ dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); -+ vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0); -+ } while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc)); -+ -+ /* Compute time difference to stored timestamp of last vblank -+ * as updated by last invocation of drm_handle_vblank() in vblank irq. -+ */ -+ vblcount = atomic_read(&dev->_vblank_count[crtc]); -+ diff_ns = timeval_to_ns(&tvblank) - -+ timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); -+ -+ /* If there is at least 1 msec difference between the last stored -+ * timestamp and tvblank, then we are currently executing our -+ * disable inside a new vblank interval, the tvblank timestamp -+ * corresponds to this new vblank interval and the irq handler -+ * for this vblank didn't run yet and won't run due to our disable. -+ * Therefore we need to do the job of drm_handle_vblank() and -+ * increment the vblank counter by one to account for this vblank. -+ * -+ * Skip this step if there isn't any high precision timestamp -+ * available. In that case we can't account for this and just -+ * hope for the best. -+ */ -+ if ((vblrc > 0) && (abs(diff_ns) > 1000000)) -+ atomic_inc(&dev->_vblank_count[crtc]); -+ -+ /* Invalidate all timestamps while vblank irq's are off. */ -+ clear_vblank_timestamps(dev, crtc); -+ -+ spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); -+ preempt_enable(); -+} -+ - static void vblank_disable_fn(unsigned long arg) - { - struct drm_device *dev = (struct drm_device *)arg; -@@ -91,10 +188,7 @@ - if (atomic_read(&dev->vblank_refcount[i]) == 0 && - dev->vblank_enabled[i]) { - DRM_DEBUG("disabling vblank on crtc %d\n", i); -- dev->last_vblank[i] = -- dev->driver->get_vblank_counter(dev, i); -- dev->driver->disable_vblank(dev, i); -- dev->vblank_enabled[i] = 0; -+ vblank_disable_and_save(dev, i); - } - spin_unlock_irqrestore(&dev->vbl_lock, irqflags); - } -@@ -117,6 +211,7 @@ - kfree(dev->last_vblank); - kfree(dev->last_vblank_wait); - kfree(dev->vblank_inmodeset); -+ kfree(dev->_vblank_time); - - dev->num_crtcs = 0; - } -@@ -129,6 +224,8 @@ - setup_timer(&dev->vblank_disable_timer, vblank_disable_fn, - (unsigned long)dev); - spin_lock_init(&dev->vbl_lock); -+ spin_lock_init(&dev->vblank_time_lock); -+ - dev->num_crtcs = num_crtcs; - - dev->vbl_queue = kmalloc(sizeof(wait_queue_head_t) * num_crtcs, -@@ -161,6 +258,19 @@ - if (!dev->vblank_inmodeset) - goto err; - -+ dev->_vblank_time = kcalloc(num_crtcs * DRM_VBLANKTIME_RBSIZE, -+ sizeof(struct timeval), GFP_KERNEL); -+ if (!dev->_vblank_time) -+ goto err; -+ -+ DRM_INFO("Supports vblank timestamp caching Rev 1 (10.10.2010).\n"); -+ -+ /* Driver specific high-precision vblank timestamping supported? */ -+ if (dev->driver->get_vblank_timestamp) -+ DRM_INFO("Driver supports precise vblank timestamp query.\n"); -+ else -+ DRM_INFO("No driver support for vblank timestamp query.\n"); -+ - /* Zero per-crtc vblank stuff */ - for (i = 0; i < num_crtcs; i++) { - init_waitqueue_head(&dev->vbl_queue[i]); -@@ -279,7 +389,7 @@ - * - * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq. - */ --int drm_irq_uninstall(struct drm_device * dev) -+int drm_irq_uninstall(struct drm_device *dev) - { - unsigned long irqflags; - int irq_enabled, i; -@@ -335,7 +445,9 @@ - { - struct drm_control *ctl = data; - -- /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */ -+ /* if we haven't irq we fallback for compatibility reasons - -+ * this used to be a separate function in drm_dma.h -+ */ - - - switch (ctl->func) { -@@ -360,6 +472,287 @@ - } - - /** -+ * drm_calc_timestamping_constants - Calculate and -+ * store various constants which are later needed by -+ * vblank and swap-completion timestamping, e.g, by -+ * drm_calc_vbltimestamp_from_scanoutpos(). -+ * They are derived from crtc's true scanout timing, -+ * so they take things like panel scaling or other -+ * adjustments into account. -+ * -+ * @crtc drm_crtc whose timestamp constants should be updated. -+ * -+ */ -+void drm_calc_timestamping_constants(struct drm_crtc *crtc) -+{ -+ s64 linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; -+ u64 dotclock; -+ -+ /* Dot clock in Hz: */ -+ dotclock = (u64) crtc->hwmode.clock * 1000; -+ -+ /* Valid dotclock? */ -+ if (dotclock > 0) { -+ /* Convert scanline length in pixels and video dot clock to -+ * line duration, frame duration and pixel duration in -+ * nanoseconds: -+ */ -+ pixeldur_ns = (s64) div64_u64(1000000000, dotclock); -+ linedur_ns = (s64) div64_u64(((u64) crtc->hwmode.crtc_htotal * -+ 1000000000), dotclock); -+ framedur_ns = (s64) crtc->hwmode.crtc_vtotal * linedur_ns; -+ } else -+ DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n", -+ crtc->base.id); -+ -+ crtc->pixeldur_ns = pixeldur_ns; -+ crtc->linedur_ns = linedur_ns; -+ crtc->framedur_ns = framedur_ns; -+ -+ DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n", -+ crtc->base.id, crtc->hwmode.crtc_htotal, -+ crtc->hwmode.crtc_vtotal, crtc->hwmode.crtc_vdisplay); -+ DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n", -+ crtc->base.id, (int) dotclock/1000, (int) framedur_ns, -+ (int) linedur_ns, (int) pixeldur_ns); -+} -+EXPORT_SYMBOL(drm_calc_timestamping_constants); -+ -+/** -+ * drm_calc_vbltimestamp_from_scanoutpos - helper routine for kms -+ * drivers. Implements calculation of exact vblank timestamps from -+ * given drm_display_mode timings and current video scanout position -+ * of a crtc. This can be called from within get_vblank_timestamp() -+ * implementation of a kms driver to implement the actual timestamping. -+ * -+ * Should return timestamps conforming to the OML_sync_control OpenML -+ * extension specification. The timestamp corresponds to the end of -+ * the vblank interval, aka start of scanout of topmost-leftmost display -+ * pixel in the following video frame. -+ * -+ * Requires support for optional dev->driver->get_scanout_position() -+ * in kms driver, plus a bit of setup code to provide a drm_display_mode -+ * that corresponds to the true scanout timing. -+ * -+ * The current implementation only handles standard video modes. It -+ * returns as no operation if a doublescan or interlaced video mode is -+ * active. Higher level code is expected to handle this. -+ * -+ * @dev: DRM device. -+ * @crtc: Which crtc's vblank timestamp to retrieve. -+ * @max_error: Desired maximum allowable error in timestamps (nanosecs). -+ * On return contains true maximum error of timestamp. -+ * @vblank_time: Pointer to struct timeval which should receive the timestamp. -+ * @flags: Flags to pass to driver: -+ * 0 = Default. -+ * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler. -+ * @refcrtc: drm_crtc* of crtc which defines scanout timing. -+ * -+ * Returns negative value on error, failure or if not supported in current -+ * video mode: -+ * -+ * -EINVAL - Invalid crtc. -+ * -EAGAIN - Temporary unavailable, e.g., called before initial modeset. -+ * -ENOTSUPP - Function not supported in current display mode. -+ * -EIO - Failed, e.g., due to failed scanout position query. -+ * -+ * Returns or'ed positive status flags on success: -+ * -+ * DRM_VBLANKTIME_SCANOUTPOS_METHOD - Signal this method used for timestamping. -+ * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval. -+ * -+ */ -+int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, -+ int *max_error, -+ struct timeval *vblank_time, -+ unsigned flags, -+ struct drm_crtc *refcrtc) -+{ -+ struct timeval stime, raw_time; -+ struct drm_display_mode *mode; -+ int vbl_status, vtotal, vdisplay; -+ int vpos, hpos, i; -+ s64 framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; -+ bool invbl; -+ -+ if (crtc < 0 || crtc >= dev->num_crtcs) { -+ DRM_ERROR("Invalid crtc %d\n", crtc); -+ return -EINVAL; -+ } -+ -+ /* Scanout position query not supported? Should not happen. */ -+ if (!dev->driver->get_scanout_position) { -+ DRM_ERROR("Called from driver w/o get_scanout_position()!?\n"); -+ return -EIO; -+ } -+ -+ mode = &refcrtc->hwmode; -+ vtotal = mode->crtc_vtotal; -+ vdisplay = mode->crtc_vdisplay; -+ -+ /* Durations of frames, lines, pixels in nanoseconds. */ -+ framedur_ns = refcrtc->framedur_ns; -+ linedur_ns = refcrtc->linedur_ns; -+ pixeldur_ns = refcrtc->pixeldur_ns; -+ -+ /* If mode timing undefined, just return as no-op: -+ * Happens during initial modesetting of a crtc. -+ */ -+ if (vtotal <= 0 || vdisplay <= 0 || framedur_ns == 0) { -+ DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc); -+ return -EAGAIN; -+ } -+ -+ /* Don't know yet how to handle interlaced or -+ * double scan modes. Just no-op for now. -+ */ -+ if (mode->flags & (DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN)) { -+ DRM_DEBUG("crtc %d: Noop due to unsupported mode.\n", crtc); -+ return -ENOTSUPP; -+ } -+ -+ /* Get current scanout position with system timestamp. -+ * Repeat query up to DRM_TIMESTAMP_MAXRETRIES times -+ * if single query takes longer than max_error nanoseconds. -+ * -+ * This guarantees a tight bound on maximum error if -+ * code gets preempted or delayed for some reason. -+ */ -+ for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) { -+ /* Disable preemption to make it very likely to -+ * succeed in the first iteration even on PREEMPT_RT kernel. -+ */ -+ preempt_disable(); -+ -+ /* Get system timestamp before query. */ -+ do_gettimeofday(&stime); -+ -+ /* Get vertical and horizontal scanout pos. vpos, hpos. */ -+ vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos, &hpos); -+ -+ /* Get system timestamp after query. */ -+ do_gettimeofday(&raw_time); -+ -+ preempt_enable(); -+ -+ /* Return as no-op if scanout query unsupported or failed. */ -+ if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { -+ DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n", -+ crtc, vbl_status); -+ return -EIO; -+ } -+ -+ duration_ns = timeval_to_ns(&raw_time) - timeval_to_ns(&stime); -+ -+ /* Accept result with < max_error nsecs timing uncertainty. */ -+ if (duration_ns <= (s64) *max_error) -+ break; -+ } -+ -+ /* Noisy system timing? */ -+ if (i == DRM_TIMESTAMP_MAXRETRIES) { -+ DRM_DEBUG("crtc %d: Noisy timestamp %d us > %d us [%d reps].\n", -+ crtc, (int) duration_ns/1000, *max_error/1000, i); -+ } -+ -+ /* Return upper bound of timestamp precision error. */ -+ *max_error = (int) duration_ns; -+ -+ /* Check if in vblank area: -+ * vpos is >=0 in video scanout area, but negative -+ * within vblank area, counting down the number of lines until -+ * start of scanout. -+ */ -+ invbl = vbl_status & DRM_SCANOUTPOS_INVBL; -+ -+ /* Convert scanout position into elapsed time at raw_time query -+ * since start of scanout at first display scanline. delta_ns -+ * can be negative if start of scanout hasn't happened yet. -+ */ -+ delta_ns = (s64) vpos * linedur_ns + (s64) hpos * pixeldur_ns; -+ -+ /* Is vpos outside nominal vblank area, but less than -+ * 1/100 of a frame height away from start of vblank? -+ * If so, assume this isn't a massively delayed vblank -+ * interrupt, but a vblank interrupt that fired a few -+ * microseconds before true start of vblank. Compensate -+ * by adding a full frame duration to the final timestamp. -+ * Happens, e.g., on ATI R500, R600. -+ * -+ * We only do this if DRM_CALLED_FROM_VBLIRQ. -+ */ -+ if ((flags & DRM_CALLED_FROM_VBLIRQ) && !invbl && -+ ((vdisplay - vpos) < vtotal / 100)) { -+ delta_ns = delta_ns - framedur_ns; -+ -+ /* Signal this correction as "applied". */ -+ vbl_status |= 0x8; -+ } -+ -+ /* Subtract time delta from raw timestamp to get final -+ * vblank_time timestamp for end of vblank. -+ */ -+ *vblank_time = ns_to_timeval(timeval_to_ns(&raw_time) - delta_ns); -+ -+ DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %d.%d -> %d.%d [e %d us, %d rep]\n", -+ crtc, (int) vbl_status, hpos, vpos, raw_time.tv_sec, -+ raw_time.tv_usec, vblank_time->tv_sec, vblank_time->tv_usec, -+ (int) duration_ns/1000, i); -+ -+ vbl_status = DRM_VBLANKTIME_SCANOUTPOS_METHOD; -+ if (invbl) -+ vbl_status |= DRM_VBLANKTIME_INVBL; -+ -+ return vbl_status; -+} -+EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); -+ -+/** -+ * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent -+ * vblank interval. -+ * -+ * @dev: DRM device -+ * @crtc: which crtc's vblank timestamp to retrieve -+ * @tvblank: Pointer to target struct timeval which should receive the timestamp -+ * @flags: Flags to pass to driver: -+ * 0 = Default. -+ * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler. -+ * -+ * Fetches the system timestamp corresponding to the time of the most recent -+ * vblank interval on specified crtc. May call into kms-driver to -+ * compute the timestamp with a high-precision GPU specific method. -+ * -+ * Returns zero if timestamp originates from uncorrected do_gettimeofday() -+ * call, i.e., it isn't very precisely locked to the true vblank. -+ * -+ * Returns non-zero if timestamp is considered to be very precise. -+ */ -+u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, -+ struct timeval *tvblank, unsigned flags) -+{ -+ int ret = 0; -+ -+ /* Define requested maximum error on timestamps (nanoseconds). */ -+ int max_error = (int) drm_timestamp_precision * 1000; -+ -+ /* Query driver if possible and precision timestamping enabled. */ -+ if (dev->driver->get_vblank_timestamp && (max_error > 0)) { -+ ret = dev->driver->get_vblank_timestamp(dev, crtc, &max_error, -+ tvblank, flags); -+ if (ret > 0) -+ return (u32) ret; -+ } -+ -+ /* GPU high precision timestamp query unsupported or failed. -+ * Return gettimeofday timestamp as best estimate. -+ */ -+ do_gettimeofday(tvblank); -+ -+ return 0; -+} -+EXPORT_SYMBOL(drm_get_last_vbltimestamp); -+ -+/** - * drm_vblank_count - retrieve "cooked" vblank counter value - * @dev: DRM device - * @crtc: which counter to retrieve -@@ -375,6 +768,40 @@ - EXPORT_SYMBOL(drm_vblank_count); - - /** -+ * drm_vblank_count_and_time - retrieve "cooked" vblank counter value -+ * and the system timestamp corresponding to that vblank counter value. -+ * -+ * @dev: DRM device -+ * @crtc: which counter to retrieve -+ * @vblanktime: Pointer to struct timeval to receive the vblank timestamp. -+ * -+ * Fetches the "cooked" vblank count value that represents the number of -+ * vblank events since the system was booted, including lost events due to -+ * modesetting activity. Returns corresponding system timestamp of the time -+ * of the vblank interval that corresponds to the current value vblank counter -+ * value. -+ */ -+u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, -+ struct timeval *vblanktime) -+{ -+ u32 cur_vblank; -+ -+ /* Read timestamp from slot of _vblank_time ringbuffer -+ * that corresponds to current vblank count. Retry if -+ * count has incremented during readout. This works like -+ * a seqlock. -+ */ -+ do { -+ cur_vblank = atomic_read(&dev->_vblank_count[crtc]); -+ *vblanktime = vblanktimestamp(dev, crtc, cur_vblank); -+ smp_rmb(); -+ } while (cur_vblank != atomic_read(&dev->_vblank_count[crtc])); -+ -+ return cur_vblank; -+} -+EXPORT_SYMBOL(drm_vblank_count_and_time); -+ -+/** - * drm_update_vblank_count - update the master vblank counter - * @dev: DRM device - * @crtc: counter to update -@@ -392,7 +819,8 @@ - */ - static void drm_update_vblank_count(struct drm_device *dev, int crtc) - { -- u32 cur_vblank, diff; -+ u32 cur_vblank, diff, tslot, rc; -+ struct timeval t_vblank; - - /* - * Interrupts were disabled prior to this call, so deal with counter -@@ -400,8 +828,18 @@ - * NOTE! It's possible we lost a full dev->max_vblank_count events - * here if the register is small or we had vblank interrupts off for - * a long time. -+ * -+ * We repeat the hardware vblank counter & timestamp query until -+ * we get consistent results. This to prevent races between gpu -+ * updating its hardware counter while we are retrieving the -+ * corresponding vblank timestamp. - */ -- cur_vblank = dev->driver->get_vblank_counter(dev, crtc); -+ do { -+ cur_vblank = dev->driver->get_vblank_counter(dev, crtc); -+ rc = drm_get_last_vbltimestamp(dev, crtc, &t_vblank, 0); -+ } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc)); -+ -+ /* Deal with counter wrap */ - diff = cur_vblank - dev->last_vblank[crtc]; - if (cur_vblank < dev->last_vblank[crtc]) { - diff += dev->max_vblank_count; -@@ -413,6 +851,16 @@ - DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", - crtc, diff); - -+ /* Reinitialize corresponding vblank timestamp if high-precision query -+ * available. Skip this step if query unsupported or failed. Will -+ * reinitialize delayed at next vblank interrupt in that case. -+ */ -+ if (rc) { -+ tslot = atomic_read(&dev->_vblank_count[crtc]) + diff; -+ vblanktimestamp(dev, crtc, tslot) = t_vblank; -+ smp_wmb(); -+ } -+ - atomic_add(diff, &dev->_vblank_count[crtc]); - } - -@@ -429,15 +877,27 @@ - */ - int drm_vblank_get(struct drm_device *dev, int crtc) - { -- unsigned long irqflags; -+ unsigned long irqflags, irqflags2; - int ret = 0; - - spin_lock_irqsave(&dev->vbl_lock, irqflags); - /* Going from 0->1 means we have to enable interrupts again */ - if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) { -+ /* Disable preemption while holding vblank_time_lock. Do -+ * it explicitely to guard against PREEMPT_RT kernel. -+ */ -+ preempt_disable(); -+ spin_lock_irqsave(&dev->vblank_time_lock, irqflags2); - if (!dev->vblank_enabled[crtc]) { -+ /* Enable vblank irqs under vblank_time_lock protection. -+ * All vblank count & timestamp updates are held off -+ * until we are done reinitializing master counter and -+ * timestamps. Filtercode in drm_handle_vblank() will -+ * prevent double-accounting of same vblank interval. -+ */ - ret = dev->driver->enable_vblank(dev, crtc); -- DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); -+ DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", -+ crtc, ret); - if (ret) - atomic_dec(&dev->vblank_refcount[crtc]); - else { -@@ -445,6 +905,8 @@ - drm_update_vblank_count(dev, crtc); - } - } -+ spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2); -+ preempt_enable(); - } else { - if (!dev->vblank_enabled[crtc]) { - atomic_dec(&dev->vblank_refcount[crtc]); -@@ -463,15 +925,17 @@ - * @crtc: which counter to give up - * - * Release ownership of a given vblank counter, turning off interrupts -- * if possible. -+ * if possible. Disable interrupts after drm_vblank_offdelay milliseconds. - */ - void drm_vblank_put(struct drm_device *dev, int crtc) - { -- BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0); -+ BUG_ON(atomic_read(&dev->vblank_refcount[crtc]) == 0); - - /* Last user schedules interrupt disable */ -- if (atomic_dec_and_test(&dev->vblank_refcount[crtc])) -- mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ); -+ if (atomic_dec_and_test(&dev->vblank_refcount[crtc]) && -+ (drm_vblank_offdelay > 0)) -+ mod_timer(&dev->vblank_disable_timer, -+ jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000)); - } - EXPORT_SYMBOL(drm_vblank_put); - -@@ -480,10 +944,8 @@ - unsigned long irqflags; - - spin_lock_irqsave(&dev->vbl_lock, irqflags); -- dev->driver->disable_vblank(dev, crtc); -+ vblank_disable_and_save(dev, crtc); - DRM_WAKEUP(&dev->vbl_queue[crtc]); -- dev->vblank_enabled[crtc] = 0; -- dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); - spin_unlock_irqrestore(&dev->vbl_lock, irqflags); - } - EXPORT_SYMBOL(drm_vblank_off); -@@ -599,7 +1061,6 @@ - e->base.file_priv = file_priv; - e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; - -- do_gettimeofday(&now); - spin_lock_irqsave(&dev->event_lock, flags); - - if (file_priv->event_space < sizeof e->event) { -@@ -609,7 +1070,8 @@ - } - - file_priv->event_space -= sizeof e->event; -- seq = drm_vblank_count(dev, pipe); -+ seq = drm_vblank_count_and_time(dev, pipe, &now); -+ - if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) && - (seq - vblwait->request.sequence) <= (1 << 23)) { - vblwait->request.sequence = seq + 1; -@@ -718,11 +1180,10 @@ - if (ret != -EINTR) { - struct timeval now; - -- do_gettimeofday(&now); -- -+ vblwait->reply.sequence = drm_vblank_count_and_time(dev, crtc, &now); - vblwait->reply.tval_sec = now.tv_sec; - vblwait->reply.tval_usec = now.tv_usec; -- vblwait->reply.sequence = drm_vblank_count(dev, crtc); -+ - DRM_DEBUG("returning %d to client\n", - vblwait->reply.sequence); - } else { -@@ -741,8 +1202,7 @@ - unsigned long flags; - unsigned int seq; - -- do_gettimeofday(&now); -- seq = drm_vblank_count(dev, crtc); -+ seq = drm_vblank_count_and_time(dev, crtc, &now); - - spin_lock_irqsave(&dev->event_lock, flags); - -@@ -780,11 +1240,64 @@ - */ - void drm_handle_vblank(struct drm_device *dev, int crtc) - { -+ u32 vblcount; -+ s64 diff_ns; -+ struct timeval tvblank; -+ unsigned long irqflags; -+ - if (!dev->num_crtcs) - return; - -- atomic_inc(&dev->_vblank_count[crtc]); -+ /* Need timestamp lock to prevent concurrent execution with -+ * vblank enable/disable, as this would cause inconsistent -+ * or corrupted timestamps and vblank counts. -+ */ -+ spin_lock_irqsave(&dev->vblank_time_lock, irqflags); -+ -+ /* Vblank irq handling disabled. Nothing to do. */ -+ if (!dev->vblank_enabled[crtc]) { -+ spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); -+ return; -+ } -+ -+ /* Fetch corresponding timestamp for this vblank interval from -+ * driver and store it in proper slot of timestamp ringbuffer. -+ */ -+ -+ /* Get current timestamp and count. */ -+ vblcount = atomic_read(&dev->_vblank_count[crtc]); -+ drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ); -+ -+ /* Compute time difference to timestamp of last vblank */ -+ diff_ns = timeval_to_ns(&tvblank) - -+ timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); -+ -+ /* Update vblank timestamp and count if at least -+ * DRM_REDUNDANT_VBLIRQ_THRESH_NS nanoseconds -+ * difference between last stored timestamp and current -+ * timestamp. A smaller difference means basically -+ * identical timestamps. Happens if this vblank has -+ * been already processed and this is a redundant call, -+ * e.g., due to spurious vblank interrupts. We need to -+ * ignore those for accounting. -+ */ -+ if (abs(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS) { -+ /* Store new timestamp in ringbuffer. */ -+ vblanktimestamp(dev, crtc, vblcount + 1) = tvblank; -+ smp_wmb(); -+ -+ /* Increment cooked vblank count. This also atomically commits -+ * the timestamp computed above. -+ */ -+ atomic_inc(&dev->_vblank_count[crtc]); -+ } else { -+ DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n", -+ crtc, (int) diff_ns); -+ } -+ - DRM_WAKEUP(&dev->vbl_queue[crtc]); - drm_handle_vblank_events(dev, crtc); -+ -+ spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); - } - EXPORT_SYMBOL(drm_handle_vblank); -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/drm_stub.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/drm_stub.c ---- linux-2.6.37-rc3/drivers/gpu/drm/drm_stub.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/drm_stub.c 2011-01-07 14:22:17.000000000 +0100 -@@ -40,12 +40,22 @@ - unsigned int drm_debug = 0; /* 1 to enable debug output */ - EXPORT_SYMBOL(drm_debug); - -+unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */ -+EXPORT_SYMBOL(drm_vblank_offdelay); -+ -+unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */ -+EXPORT_SYMBOL(drm_timestamp_precision); -+ - MODULE_AUTHOR(CORE_AUTHOR); - MODULE_DESCRIPTION(CORE_DESC); - MODULE_LICENSE("GPL and additional rights"); - MODULE_PARM_DESC(debug, "Enable debug output"); -+MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]"); -+MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]"); - - module_param_named(debug, drm_debug, int, 0600); -+module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); -+module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); - - struct idr drm_minors_idr; - -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/Kconfig linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/Kconfig ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/Kconfig 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/Kconfig 2011-01-07 14:22:17.000000000 +0100 -@@ -10,7 +10,7 @@ - select FB - select FRAMEBUFFER_CONSOLE if !EMBEDDED - select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT -- select ACPI_VIDEO if ACPI -+ select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL && INPUT - help - Choose this option for open-source nVidia support. - -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/Makefile linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/Makefile ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/Makefile 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/Makefile 2011-01-07 14:22:17.000000000 +0100 -@@ -5,27 +5,32 @@ - ccflags-y := -Iinclude/drm - nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ - nouveau_object.o nouveau_irq.o nouveau_notifier.o \ -- nouveau_sgdma.o nouveau_dma.o \ -+ nouveau_sgdma.o nouveau_dma.o nouveau_util.o \ - nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ - nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ - nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ - nouveau_dp.o nouveau_ramht.o \ - nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \ -+ nouveau_mm.o nouveau_vm.o \ - nv04_timer.o \ - nv04_mc.o nv40_mc.o nv50_mc.o \ - nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ - nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o nvc0_fifo.o \ - nv04_graph.o nv10_graph.o nv20_graph.o \ - nv40_graph.o nv50_graph.o nvc0_graph.o \ -- nv40_grctx.o nv50_grctx.o \ -+ nv40_grctx.o nv50_grctx.o nvc0_grctx.o \ -+ nv84_crypt.o \ - nv04_instmem.o nv50_instmem.o nvc0_instmem.o \ -- nv50_crtc.o nv50_dac.o nv50_sor.o \ -- nv50_cursor.o nv50_display.o nv50_fbcon.o \ -+ nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \ -+ nv50_cursor.o nv50_display.o \ - nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ -- nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \ -+ nv04_crtc.o nv04_display.o nv04_cursor.o \ -+ nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \ - nv10_gpio.o nv50_gpio.o \ - nv50_calc.o \ -- nv04_pm.o nv50_pm.o nva3_pm.o -+ nv04_pm.o nv50_pm.o nva3_pm.o \ -+ nv50_vram.o nvc0_vram.o \ -+ nv50_vm.o nvc0_vm.o - - nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o - nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_bios.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_bios.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_bios.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_bios.c 2011-01-07 14:22:17.000000000 +0100 -@@ -6053,52 +6053,17 @@ - return entry; - } - --static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads) -+static void fabricate_dcb_output(struct dcb_table *dcb, int type, int i2c, -+ int heads, int or) - { - struct dcb_entry *entry = new_dcb_entry(dcb); - -- entry->type = 0; -+ entry->type = type; - entry->i2c_index = i2c; - entry->heads = heads; -- entry->location = DCB_LOC_ON_CHIP; -- entry->or = 1; --} -- --static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads) --{ -- struct dcb_entry *entry = new_dcb_entry(dcb); -- -- entry->type = 2; -- entry->i2c_index = LEGACY_I2C_PANEL; -- entry->heads = twoHeads ? 3 : 1; -- entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */ -- entry->or = 1; /* means |0x10 gets set on CRE_LCD__INDEX */ -- entry->duallink_possible = false; /* SiI164 and co. are single link */ -- --#if 0 -- /* -- * For dvi-a either crtc probably works, but my card appears to only -- * support dvi-d. "nvidia" still attempts to program it for dvi-a, -- * doing the full fp output setup (program 0x6808.. fp dimension regs, -- * setting 0x680848 to 0x10000111 to enable, maybe setting 0x680880); -- * the monitor picks up the mode res ok and lights up, but no pixel -- * data appears, so the board manufacturer probably connected up the -- * sync lines, but missed the video traces / components -- * -- * with this introduction, dvi-a left as an exercise for the reader. -- */ -- fabricate_vga_output(dcb, LEGACY_I2C_PANEL, entry->heads); --#endif --} -- --static void fabricate_tv_output(struct dcb_table *dcb, bool twoHeads) --{ -- struct dcb_entry *entry = new_dcb_entry(dcb); -- -- entry->type = 1; -- entry->i2c_index = LEGACY_I2C_TV; -- entry->heads = twoHeads ? 3 : 1; -- entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */ -+ if (type != OUTPUT_ANALOG) -+ entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */ -+ entry->or = or; - } - - static bool -@@ -6365,8 +6330,36 @@ - return true; - } - -+static void -+fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios) -+{ -+ struct dcb_table *dcb = &bios->dcb; -+ int all_heads = (nv_two_heads(dev) ? 3 : 1); -+ -+#ifdef __powerpc__ -+ /* Apple iMac G4 NV17 */ -+ if (of_machine_is_compatible("PowerMac4,5")) { -+ fabricate_dcb_output(dcb, OUTPUT_TMDS, 0, all_heads, 1); -+ fabricate_dcb_output(dcb, OUTPUT_ANALOG, 1, all_heads, 2); -+ return; -+ } -+#endif -+ -+ /* Make up some sane defaults */ -+ fabricate_dcb_output(dcb, OUTPUT_ANALOG, LEGACY_I2C_CRT, 1, 1); -+ -+ if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0) -+ fabricate_dcb_output(dcb, OUTPUT_TV, LEGACY_I2C_TV, -+ all_heads, 0); -+ -+ else if (bios->tmds.output0_script_ptr || -+ bios->tmds.output1_script_ptr) -+ fabricate_dcb_output(dcb, OUTPUT_TMDS, LEGACY_I2C_PANEL, -+ all_heads, 1); -+} -+ - static int --parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) -+parse_dcb_table(struct drm_device *dev, struct nvbios *bios) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct dcb_table *dcb = &bios->dcb; -@@ -6386,12 +6379,7 @@ - - /* this situation likely means a really old card, pre DCB */ - if (dcbptr == 0x0) { -- NV_INFO(dev, "Assuming a CRT output exists\n"); -- fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1); -- -- if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0) -- fabricate_tv_output(dcb, twoHeads); -- -+ fabricate_dcb_encoder_table(dev, bios); - return 0; - } - -@@ -6451,21 +6439,7 @@ - */ - NV_TRACEWARN(dev, "No useful information in BIOS output table; " - "adding all possible outputs\n"); -- fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1); -- -- /* -- * Attempt to detect TV before DVI because the test -- * for the former is more accurate and it rules the -- * latter out. -- */ -- if (nv04_tv_identify(dev, -- bios->legacy.i2c_indices.tv) >= 0) -- fabricate_tv_output(dcb, twoHeads); -- -- else if (bios->tmds.output0_script_ptr || -- bios->tmds.output1_script_ptr) -- fabricate_dvi_i_output(dcb, twoHeads); -- -+ fabricate_dcb_encoder_table(dev, bios); - return 0; - } - -@@ -6859,7 +6833,7 @@ - if (ret) - return ret; - -- ret = parse_dcb_table(dev, bios, nv_two_heads(dev)); -+ ret = parse_dcb_table(dev, bios); - if (ret) - return ret; - -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_bo.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_bo.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_bo.c 2011-01-07 14:22:17.000000000 +0100 -@@ -32,6 +32,8 @@ - #include "nouveau_drm.h" - #include "nouveau_drv.h" - #include "nouveau_dma.h" -+#include "nouveau_mm.h" -+#include "nouveau_vm.h" - - #include - #include -@@ -46,82 +48,51 @@ - if (unlikely(nvbo->gem)) - DRM_ERROR("bo %p still attached to GEM object\n", bo); - -- if (nvbo->tile) -- nv10_mem_expire_tiling(dev, nvbo->tile, NULL); -- -+ nv10_mem_put_tile_region(dev, nvbo->tile, NULL); -+ nouveau_vm_put(&nvbo->vma); - kfree(nvbo); - } - - static void --nouveau_bo_fixup_align(struct drm_device *dev, -- uint32_t tile_mode, uint32_t tile_flags, -- int *align, int *size) -+nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size, -+ int *page_shift) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- -- /* -- * Some of the tile_flags have a periodic structure of N*4096 bytes, -- * align to to that as well as the page size. Align the size to the -- * appropriate boundaries. This does imply that sizes are rounded up -- * 3-7 pages, so be aware of this and do not waste memory by allocating -- * many small buffers. -- */ -- if (dev_priv->card_type == NV_50) { -- uint32_t block_size = dev_priv->vram_size >> 15; -- int i; -- -- switch (tile_flags) { -- case 0x1800: -- case 0x2800: -- case 0x4800: -- case 0x7a00: -- if (is_power_of_2(block_size)) { -- for (i = 1; i < 10; i++) { -- *align = 12 * i * block_size; -- if (!(*align % 65536)) -- break; -- } -- } else { -- for (i = 1; i < 10; i++) { -- *align = 8 * i * block_size; -- if (!(*align % 65536)) -- break; -- } -- } -- *size = roundup(*size, *align); -- break; -- default: -- break; -- } -+ struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); - -- } else { -- if (tile_mode) { -+ if (dev_priv->card_type < NV_50) { -+ if (nvbo->tile_mode) { - if (dev_priv->chipset >= 0x40) { - *align = 65536; -- *size = roundup(*size, 64 * tile_mode); -+ *size = roundup(*size, 64 * nvbo->tile_mode); - - } else if (dev_priv->chipset >= 0x30) { - *align = 32768; -- *size = roundup(*size, 64 * tile_mode); -+ *size = roundup(*size, 64 * nvbo->tile_mode); - - } else if (dev_priv->chipset >= 0x20) { - *align = 16384; -- *size = roundup(*size, 64 * tile_mode); -+ *size = roundup(*size, 64 * nvbo->tile_mode); - - } else if (dev_priv->chipset >= 0x10) { - *align = 16384; -- *size = roundup(*size, 32 * tile_mode); -+ *size = roundup(*size, 32 * nvbo->tile_mode); - } - } -+ } else { -+ if (likely(dev_priv->chan_vm)) { -+ if (*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); - } - -- /* ALIGN works only on powers of two. */ - *size = roundup(*size, PAGE_SIZE); -- -- if (dev_priv->card_type == NV_50) { -- *size = roundup(*size, 65536); -- *align = max(65536, *align); -- } - } - - int -@@ -132,7 +103,7 @@ - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_bo *nvbo; -- int ret = 0; -+ int ret = 0, page_shift = 0; - - nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL); - if (!nvbo) -@@ -145,10 +116,18 @@ - nvbo->tile_flags = tile_flags; - nvbo->bo.bdev = &dev_priv->ttm.bdev; - -- nouveau_bo_fixup_align(dev, tile_mode, nouveau_bo_tile_layout(nvbo), -- &align, &size); -+ nouveau_bo_fixup_align(nvbo, &align, &size, &page_shift); - align >>= PAGE_SHIFT; - -+ if (!nvbo->no_vm && 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; -+ } -+ } -+ - nouveau_bo_placement_set(nvbo, flags, 0); - - nvbo->channel = chan; -@@ -161,6 +140,11 @@ - } - nvbo->channel = NULL; - -+ if (nvbo->vma.node) { -+ if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) -+ nvbo->bo.offset = nvbo->vma.offset; -+ } -+ - *pnvbo = nvbo; - return 0; - } -@@ -244,7 +228,7 @@ - - nouveau_bo_placement_set(nvbo, memtype, 0); - -- ret = ttm_bo_validate(bo, &nvbo->placement, false, false, false); -+ ret = nouveau_bo_validate(nvbo, false, false, false); - if (ret == 0) { - switch (bo->mem.mem_type) { - case TTM_PL_VRAM: -@@ -280,7 +264,7 @@ - - nouveau_bo_placement_set(nvbo, bo->mem.placement, 0); - -- ret = ttm_bo_validate(bo, &nvbo->placement, false, false, false); -+ ret = nouveau_bo_validate(nvbo, false, false, false); - if (ret == 0) { - switch (bo->mem.mem_type) { - case TTM_PL_VRAM: -@@ -319,6 +303,25 @@ - ttm_bo_kunmap(&nvbo->kmap); - } - -+int -+nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible, -+ bool no_wait_reserve, bool no_wait_gpu) -+{ -+ int ret; -+ -+ ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, interruptible, -+ no_wait_reserve, no_wait_gpu); -+ if (ret) -+ return ret; -+ -+ if (nvbo->vma.node) { -+ if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) -+ nvbo->bo.offset = nvbo->vma.offset; -+ } -+ -+ return 0; -+} -+ - u16 - nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index) - { -@@ -410,37 +413,40 @@ - man->default_caching = TTM_PL_FLAG_CACHED; - break; - case TTM_PL_VRAM: -- man->func = &ttm_bo_manager_func; -+ if (dev_priv->card_type >= NV_50) { -+ man->func = &nouveau_vram_manager; -+ man->io_reserve_fastpath = false; -+ man->use_io_reserve_lru = true; -+ } else { -+ man->func = &ttm_bo_manager_func; -+ } - man->flags = TTM_MEMTYPE_FLAG_FIXED | - TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; -- if (dev_priv->card_type == NV_50) -- man->gpu_offset = 0x40000000; -- else -- man->gpu_offset = 0; - break; - case TTM_PL_TT: - man->func = &ttm_bo_manager_func; - switch (dev_priv->gart_info.type) { - case NOUVEAU_GART_AGP: - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; -- man->available_caching = TTM_PL_FLAG_UNCACHED; -- man->default_caching = TTM_PL_FLAG_UNCACHED; -+ man->available_caching = TTM_PL_FLAG_UNCACHED | -+ TTM_PL_FLAG_WC; -+ man->default_caching = TTM_PL_FLAG_WC; - break; - case NOUVEAU_GART_SGDMA: - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | - 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", - dev_priv->gart_info.type); - return -EINVAL; - } -- man->gpu_offset = dev_priv->vm_gart_base; - break; - default: - NV_ERROR(dev, "Unsupported memory type %u\n", (unsigned)type); -@@ -485,16 +491,9 @@ - if (ret) - return ret; - -- if (nvbo->channel) { -- ret = nouveau_fence_sync(fence, nvbo->channel); -- if (ret) -- goto out; -- } -- - ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, evict, - no_wait_reserve, no_wait_gpu, new_mem); --out: -- nouveau_fence_unref((void *)&fence); -+ nouveau_fence_unref(&fence); - return ret; - } - -@@ -516,6 +515,58 @@ - } - - static int -+nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, -+ struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) -+{ -+ struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); -+ struct nouveau_bo *nvbo = nouveau_bo(bo); -+ u64 src_offset = old_mem->start << PAGE_SHIFT; -+ u64 dst_offset = new_mem->start << PAGE_SHIFT; -+ u32 page_count = new_mem->num_pages; -+ int ret; -+ -+ if (!nvbo->no_vm) { -+ if (old_mem->mem_type == TTM_PL_VRAM) -+ src_offset = nvbo->vma.offset; -+ else -+ src_offset += dev_priv->gart_info.aper_base; -+ -+ if (new_mem->mem_type == TTM_PL_VRAM) -+ dst_offset = nvbo->vma.offset; -+ else -+ dst_offset += dev_priv->gart_info.aper_base; -+ } -+ -+ page_count = new_mem->num_pages; -+ while (page_count) { -+ int line_count = (page_count > 2047) ? 2047 : page_count; -+ -+ ret = RING_SPACE(chan, 12); -+ if (ret) -+ return ret; -+ -+ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0238, 2); -+ OUT_RING (chan, upper_32_bits(dst_offset)); -+ OUT_RING (chan, lower_32_bits(dst_offset)); -+ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x030c, 6); -+ OUT_RING (chan, upper_32_bits(src_offset)); -+ OUT_RING (chan, lower_32_bits(src_offset)); -+ OUT_RING (chan, PAGE_SIZE); /* src_pitch */ -+ OUT_RING (chan, PAGE_SIZE); /* dst_pitch */ -+ OUT_RING (chan, PAGE_SIZE); /* line_length */ -+ OUT_RING (chan, line_count); -+ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0300, 1); -+ OUT_RING (chan, 0x00100110); -+ -+ page_count -= line_count; -+ src_offset += (PAGE_SIZE * line_count); -+ dst_offset += (PAGE_SIZE * line_count); -+ } -+ -+ return 0; -+} -+ -+static int - nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, - struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) - { -@@ -529,14 +580,14 @@ - dst_offset = new_mem->start << PAGE_SHIFT; - if (!nvbo->no_vm) { - if (old_mem->mem_type == TTM_PL_VRAM) -- src_offset += dev_priv->vm_vram_base; -+ src_offset = nvbo->vma.offset; - else -- src_offset += dev_priv->vm_gart_base; -+ src_offset += dev_priv->gart_info.aper_base; - - if (new_mem->mem_type == TTM_PL_VRAM) -- dst_offset += dev_priv->vm_vram_base; -+ dst_offset = nvbo->vma.offset; - else -- dst_offset += dev_priv->vm_gart_base; -+ dst_offset += dev_priv->gart_info.aper_base; - } - - ret = RING_SPACE(chan, 3); -@@ -683,17 +734,27 @@ - int ret; - - chan = nvbo->channel; -- if (!chan || nvbo->no_vm) -+ if (!chan || nvbo->no_vm) { - chan = dev_priv->channel; -+ mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX); -+ } - - if (dev_priv->card_type < NV_50) - ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem); - else -+ if (dev_priv->card_type < NV_C0) - ret = nv50_bo_move_m2mf(chan, bo, &bo->mem, new_mem); -- if (ret) -- return ret; -+ else -+ ret = nvc0_bo_move_m2mf(chan, bo, &bo->mem, new_mem); -+ if (ret == 0) { -+ ret = nouveau_bo_move_accel_cleanup(chan, nvbo, evict, -+ no_wait_reserve, -+ no_wait_gpu, new_mem); -+ } - -- return nouveau_bo_move_accel_cleanup(chan, nvbo, evict, no_wait_reserve, no_wait_gpu, new_mem); -+ if (chan == dev_priv->channel) -+ mutex_unlock(&chan->mutex); -+ return ret; - } - - static int -@@ -771,7 +832,6 @@ - struct drm_device *dev = dev_priv->dev; - struct nouveau_bo *nvbo = nouveau_bo(bo); - uint64_t offset; -- int ret; - - if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) { - /* Nothing to do. */ -@@ -781,18 +841,12 @@ - - offset = new_mem->start << PAGE_SHIFT; - -- if (dev_priv->card_type == NV_50) { -- ret = nv50_mem_vm_bind_linear(dev, -- offset + dev_priv->vm_vram_base, -- new_mem->size, -- nouveau_bo_tile_layout(nvbo), -- offset); -- if (ret) -- return ret; -- -+ if (dev_priv->chan_vm) { -+ nouveau_vm_map(&nvbo->vma, new_mem->mm_node); - } else if (dev_priv->card_type >= NV_10) { - *new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size, -- nvbo->tile_mode); -+ nvbo->tile_mode, -+ nvbo->tile_flags); - } - - return 0; -@@ -808,9 +862,7 @@ - - if (dev_priv->card_type >= NV_10 && - dev_priv->card_type < NV_50) { -- if (*old_tile) -- nv10_mem_expire_tiling(dev, *old_tile, bo->sync_obj); -- -+ nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj); - *old_tile = new_tile; - } - } -@@ -879,6 +931,7 @@ - struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; - struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); - struct drm_device *dev = dev_priv->dev; -+ int ret; - - mem->bus.addr = NULL; - mem->bus.offset = 0; -@@ -901,9 +954,40 @@ - #endif - break; - case TTM_PL_VRAM: -- mem->bus.offset = mem->start << PAGE_SHIFT; -+ { -+ struct nouveau_vram *vram = mem->mm_node; -+ u8 page_shift; -+ -+ if (!dev_priv->bar1_vm) { -+ mem->bus.offset = mem->start << PAGE_SHIFT; -+ mem->bus.base = pci_resource_start(dev->pdev, 1); -+ mem->bus.is_iomem = true; -+ break; -+ } -+ -+ if (dev_priv->card_type == NV_C0) -+ page_shift = vram->page_shift; -+ else -+ page_shift = 12; -+ -+ ret = nouveau_vm_get(dev_priv->bar1_vm, mem->bus.size, -+ page_shift, NV_MEM_ACCESS_RW, -+ &vram->bar_vma); -+ if (ret) -+ return ret; -+ -+ nouveau_vm_map(&vram->bar_vma, vram); -+ if (ret) { -+ nouveau_vm_put(&vram->bar_vma); -+ return ret; -+ } -+ -+ mem->bus.offset = vram->bar_vma.offset; -+ if (dev_priv->card_type == NV_50) /*XXX*/ -+ mem->bus.offset -= 0x0020000000ULL; - mem->bus.base = pci_resource_start(dev->pdev, 1); - mem->bus.is_iomem = true; -+ } - break; - default: - return -EINVAL; -@@ -914,6 +998,17 @@ - static void - nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) - { -+ struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); -+ struct nouveau_vram *vram = mem->mm_node; -+ -+ if (!dev_priv->bar1_vm || mem->mem_type != TTM_PL_VRAM) -+ return; -+ -+ if (!vram->bar_vma.node) -+ return; -+ -+ nouveau_vm_unmap(&vram->bar_vma); -+ nouveau_vm_put(&vram->bar_vma); - } - - static int -@@ -939,7 +1034,23 @@ - nvbo->placement.fpfn = 0; - nvbo->placement.lpfn = dev_priv->fb_mappable_pages; - nouveau_bo_placement_set(nvbo, TTM_PL_VRAM, 0); -- return ttm_bo_validate(bo, &nvbo->placement, false, true, false); -+ return nouveau_bo_validate(nvbo, false, true, false); -+} -+ -+void -+nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) -+{ -+ struct nouveau_fence *old_fence; -+ -+ if (likely(fence)) -+ nouveau_fence_ref(fence); -+ -+ spin_lock(&nvbo->bo.bdev->fence_lock); -+ old_fence = nvbo->bo.sync_obj; -+ nvbo->bo.sync_obj = fence; -+ spin_unlock(&nvbo->bo.bdev->fence_lock); -+ -+ nouveau_fence_unref(&old_fence); - } - - struct ttm_bo_driver nouveau_bo_driver = { -@@ -949,11 +1060,11 @@ - .evict_flags = nouveau_bo_evict_flags, - .move = nouveau_bo_move, - .verify_access = nouveau_bo_verify_access, -- .sync_obj_signaled = nouveau_fence_signalled, -- .sync_obj_wait = nouveau_fence_wait, -- .sync_obj_flush = nouveau_fence_flush, -- .sync_obj_unref = nouveau_fence_unref, -- .sync_obj_ref = nouveau_fence_ref, -+ .sync_obj_signaled = __nouveau_fence_signalled, -+ .sync_obj_wait = __nouveau_fence_wait, -+ .sync_obj_flush = __nouveau_fence_flush, -+ .sync_obj_unref = __nouveau_fence_unref, -+ .sync_obj_ref = __nouveau_fence_ref, - .fault_reserve_notify = &nouveau_ttm_fault_reserve_notify, - .io_mem_reserve = &nouveau_ttm_io_mem_reserve, - .io_mem_free = &nouveau_ttm_io_mem_free, -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_channel.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_channel.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_channel.c 2011-01-07 14:22:17.000000000 +0100 -@@ -38,23 +38,28 @@ - int ret; - - if (dev_priv->card_type >= NV_50) { -- ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, -- dev_priv->vm_end, NV_DMA_ACCESS_RO, -- NV_DMA_TARGET_AGP, &pushbuf); -+ if (dev_priv->card_type < NV_C0) { -+ ret = nouveau_gpuobj_dma_new(chan, -+ NV_CLASS_DMA_IN_MEMORY, 0, -+ (1ULL << 40), -+ NV_MEM_ACCESS_RO, -+ NV_MEM_TARGET_VM, -+ &pushbuf); -+ } - chan->pushbuf_base = pb->bo.offset; - } else - if (pb->bo.mem.mem_type == TTM_PL_TT) { -- ret = nouveau_gpuobj_gart_dma_new(chan, 0, -- dev_priv->gart_info.aper_size, -- NV_DMA_ACCESS_RO, &pushbuf, -- NULL); -+ 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; - } else - if (dev_priv->card_type != NV_04) { - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, - dev_priv->fb_available_size, -- NV_DMA_ACCESS_RO, -- NV_DMA_TARGET_VIDMEM, &pushbuf); -+ NV_MEM_ACCESS_RO, -+ NV_MEM_TARGET_VRAM, &pushbuf); - chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; - } else { - /* NV04 cmdbuf hack, from original ddx.. not sure of it's -@@ -62,17 +67,16 @@ - * VRAM. - */ - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, -- pci_resource_start(dev->pdev, -- 1), -+ pci_resource_start(dev->pdev, 1), - dev_priv->fb_available_size, -- NV_DMA_ACCESS_RO, -- NV_DMA_TARGET_PCI, &pushbuf); -+ NV_MEM_ACCESS_RO, -+ NV_MEM_TARGET_PCI, &pushbuf); - chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; - } - - nouveau_gpuobj_ref(pushbuf, &chan->pushbuf); - nouveau_gpuobj_ref(NULL, &pushbuf); -- return 0; -+ return ret; - } - - static struct nouveau_bo * -@@ -100,6 +104,13 @@ - return NULL; - } - -+ ret = nouveau_bo_map(pushbuf); -+ if (ret) { -+ nouveau_bo_unpin(pushbuf); -+ nouveau_bo_ref(NULL, &pushbuf); -+ return NULL; -+ } -+ - return pushbuf; - } - -@@ -107,74 +118,59 @@ - int - nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, - struct drm_file *file_priv, -- uint32_t vram_handle, uint32_t tt_handle) -+ uint32_t vram_handle, uint32_t gart_handle) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; - struct nouveau_channel *chan; -- int channel, user; -+ unsigned long flags; - int ret; - -- /* -- * Alright, here is the full story -- * Nvidia cards have multiple hw fifo contexts (praise them for that, -- * no complicated crash-prone context switches) -- * We allocate a new context for each app and let it write to it -- * directly (woo, full userspace command submission !) -- * When there are no more contexts, you lost -- */ -- for (channel = 0; channel < pfifo->channels; channel++) { -- if (dev_priv->fifos[channel] == NULL) -+ /* allocate and lock channel structure */ -+ chan = kzalloc(sizeof(*chan), GFP_KERNEL); -+ if (!chan) -+ return -ENOMEM; -+ chan->dev = dev; -+ chan->file_priv = file_priv; -+ chan->vram_handle = vram_handle; -+ chan->gart_handle = gart_handle; -+ -+ kref_init(&chan->ref); -+ atomic_set(&chan->users, 1); -+ mutex_init(&chan->mutex); -+ mutex_lock(&chan->mutex); -+ -+ /* allocate hw channel id */ -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); -+ for (chan->id = 0; chan->id < pfifo->channels; chan->id++) { -+ if (!dev_priv->channels.ptr[chan->id]) { -+ nouveau_channel_ref(chan, &dev_priv->channels.ptr[chan->id]); - break; -+ } - } -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - -- /* no more fifos. you lost. */ -- if (channel == pfifo->channels) -- return -EINVAL; -+ if (chan->id == pfifo->channels) { -+ mutex_unlock(&chan->mutex); -+ kfree(chan); -+ return -ENODEV; -+ } - -- dev_priv->fifos[channel] = kzalloc(sizeof(struct nouveau_channel), -- GFP_KERNEL); -- if (!dev_priv->fifos[channel]) -- return -ENOMEM; -- chan = dev_priv->fifos[channel]; -+ NV_DEBUG(dev, "initialising channel %d\n", chan->id); - INIT_LIST_HEAD(&chan->nvsw.vbl_wait); -+ INIT_LIST_HEAD(&chan->nvsw.flip); - INIT_LIST_HEAD(&chan->fence.pending); -- chan->dev = dev; -- chan->id = channel; -- chan->file_priv = file_priv; -- chan->vram_handle = vram_handle; -- chan->gart_handle = tt_handle; -- -- NV_INFO(dev, "Allocating FIFO number %d\n", channel); - - /* 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); -- nouveau_channel_free(chan); -+ nouveau_channel_put(&chan); - return ret; - } - - nouveau_dma_pre_init(chan); -- -- /* Locate channel's user control regs */ -- if (dev_priv->card_type < NV_40) -- user = NV03_USER(channel); -- else -- if (dev_priv->card_type < NV_50) -- user = NV40_USER(channel); -- else -- user = NV50_USER(channel); -- -- chan->user = ioremap(pci_resource_start(dev->pdev, 0) + user, -- PAGE_SIZE); -- if (!chan->user) { -- NV_ERROR(dev, "ioremap of regs failed.\n"); -- nouveau_channel_free(chan); -- return -ENOMEM; -- } - chan->user_put = 0x40; - chan->user_get = 0x44; - -@@ -182,15 +178,15 @@ - ret = nouveau_notifier_init_channel(chan); - if (ret) { - NV_ERROR(dev, "ntfy %d\n", ret); -- nouveau_channel_free(chan); -+ nouveau_channel_put(&chan); - return ret; - } - - /* Setup channel's default objects */ -- ret = nouveau_gpuobj_channel_init(chan, vram_handle, tt_handle); -+ ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle); - if (ret) { - NV_ERROR(dev, "gpuobj %d\n", ret); -- nouveau_channel_free(chan); -+ nouveau_channel_put(&chan); - return ret; - } - -@@ -198,24 +194,17 @@ - ret = nouveau_channel_pushbuf_ctxdma_init(chan); - if (ret) { - NV_ERROR(dev, "pbctxdma %d\n", ret); -- nouveau_channel_free(chan); -+ nouveau_channel_put(&chan); - return ret; - } - - /* disable the fifo caches */ - pfifo->reassign(dev, false); - -- /* Create a graphics context for new channel */ -- ret = pgraph->create_context(chan); -- if (ret) { -- nouveau_channel_free(chan); -- return ret; -- } -- - /* Construct inital RAMFC for new channel */ - ret = pfifo->create_context(chan); - if (ret) { -- nouveau_channel_free(chan); -+ nouveau_channel_put(&chan); - return ret; - } - -@@ -225,83 +214,111 @@ - if (!ret) - ret = nouveau_fence_channel_init(chan); - if (ret) { -- nouveau_channel_free(chan); -+ nouveau_channel_put(&chan); - return ret; - } - - nouveau_debugfs_channel_init(chan); - -- NV_INFO(dev, "%s: initialised FIFO %d\n", __func__, channel); -+ NV_DEBUG(dev, "channel %d initialised\n", chan->id); - *chan_ret = chan; - return 0; - } - --/* stops a fifo */ -+struct nouveau_channel * -+nouveau_channel_get_unlocked(struct nouveau_channel *ref) -+{ -+ struct nouveau_channel *chan = NULL; -+ -+ if (likely(ref && atomic_inc_not_zero(&ref->users))) -+ nouveau_channel_ref(ref, &chan); -+ -+ return chan; -+} -+ -+struct nouveau_channel * -+nouveau_channel_get(struct drm_device *dev, struct drm_file *file_priv, int id) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *chan; -+ 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); -+ } -+ -+ mutex_lock(&chan->mutex); -+ return chan; -+} -+ - void --nouveau_channel_free(struct nouveau_channel *chan) -+nouveau_channel_put_unlocked(struct nouveau_channel **pchan) - { -+ struct nouveau_channel *chan = *pchan; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -+ struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt; - unsigned long flags; -- int ret; - -- NV_INFO(dev, "%s: freeing fifo %d\n", __func__, chan->id); -+ /* decrement the refcount, and we're done if there's still refs */ -+ if (likely(!atomic_dec_and_test(&chan->users))) { -+ nouveau_channel_ref(NULL, pchan); -+ return; -+ } - -+ /* noone wants the channel anymore */ -+ NV_DEBUG(dev, "freeing channel %d\n", chan->id); - nouveau_debugfs_channel_fini(chan); - -- /* Give outstanding push buffers a chance to complete */ -- nouveau_fence_update(chan); -- if (chan->fence.sequence != chan->fence.sequence_ack) { -- struct nouveau_fence *fence = NULL; -- -- ret = nouveau_fence_new(chan, &fence, true); -- if (ret == 0) { -- ret = nouveau_fence_wait(fence, NULL, false, false); -- nouveau_fence_unref((void *)&fence); -- } -- -- if (ret) -- NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id); -- } -+ /* give it chance to idle */ -+ nouveau_channel_idle(chan); - -- /* Ensure all outstanding fences are signaled. They should be if the -+ /* ensure all outstanding fences are signaled. they should be if the - * above attempts at idling were OK, but if we failed this'll tell TTM - * we're done with the buffers. - */ - nouveau_fence_channel_fini(chan); - -- /* This will prevent pfifo from switching channels. */ -+ /* boot it off the hardware */ - pfifo->reassign(dev, false); - -- /* We want to give pgraph a chance to idle and get rid of all potential -- * errors. We need to do this before the lock, otherwise the irq handler -- * is unable to process them. -+ /* We want to give pgraph a chance to idle and get rid of all -+ * potential errors. We need to do this without the context -+ * switch lock held, otherwise the irq handler is unable to -+ * process them. - */ - if (pgraph->channel(dev) == chan) - nouveau_wait_for_idle(dev); - -- spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- -- pgraph->fifo_access(dev, false); -- if (pgraph->channel(dev) == chan) -- pgraph->unload_context(dev); -- pgraph->destroy_context(chan); -- pgraph->fifo_access(dev, true); -- -- if (pfifo->channel_id(dev) == chan->id) { -- pfifo->disable(dev); -- pfifo->unload_context(dev); -- pfifo->enable(dev); -- } -+ /* destroy the engine specific contexts */ - pfifo->destroy_context(chan); -+ pgraph->destroy_context(chan); -+ if (pcrypt->destroy_context) -+ pcrypt->destroy_context(chan); - - pfifo->reassign(dev, true); - -- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ /* aside from its resources, the channel should now be dead, -+ * remove it from the channel list -+ */ -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); -+ nouveau_channel_ref(NULL, &dev_priv->channels.ptr[chan->id]); -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - -- /* Release the channel's resources */ -+ /* destroy any resources the channel owned */ - nouveau_gpuobj_ref(NULL, &chan->pushbuf); - if (chan->pushbuf_bo) { - nouveau_bo_unmap(chan->pushbuf_bo); -@@ -310,44 +327,80 @@ - } - nouveau_gpuobj_channel_takedown(chan); - nouveau_notifier_takedown_channel(chan); -- if (chan->user) -- iounmap(chan->user); - -- dev_priv->fifos[chan->id] = NULL; -+ nouveau_channel_ref(NULL, pchan); -+} -+ -+void -+nouveau_channel_put(struct nouveau_channel **pchan) -+{ -+ mutex_unlock(&(*pchan)->mutex); -+ nouveau_channel_put_unlocked(pchan); -+} -+ -+static void -+nouveau_channel_del(struct kref *ref) -+{ -+ struct nouveau_channel *chan = -+ container_of(ref, struct nouveau_channel, ref); -+ - kfree(chan); - } - -+void -+nouveau_channel_ref(struct nouveau_channel *chan, -+ struct nouveau_channel **pchan) -+{ -+ if (chan) -+ kref_get(&chan->ref); -+ -+ if (*pchan) -+ kref_put(&(*pchan)->ref, nouveau_channel_del); -+ -+ *pchan = chan; -+} -+ -+void -+nouveau_channel_idle(struct nouveau_channel *chan) -+{ -+ struct drm_device *dev = chan->dev; -+ struct nouveau_fence *fence = NULL; -+ int ret; -+ -+ nouveau_fence_update(chan); -+ -+ if (chan->fence.sequence != chan->fence.sequence_ack) { -+ ret = nouveau_fence_new(chan, &fence, true); -+ if (!ret) { -+ ret = nouveau_fence_wait(fence, false, false); -+ nouveau_fence_unref(&fence); -+ } -+ -+ if (ret) -+ NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id); -+ } -+} -+ - /* cleans up all the fifos from file_priv */ - void - nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine = &dev_priv->engine; -+ struct nouveau_channel *chan; - int i; - - NV_DEBUG(dev, "clearing FIFO enables from file_priv\n"); - for (i = 0; i < engine->fifo.channels; i++) { -- struct nouveau_channel *chan = dev_priv->fifos[i]; -+ chan = nouveau_channel_get(dev, file_priv, i); -+ if (IS_ERR(chan)) -+ continue; - -- if (chan && chan->file_priv == file_priv) -- nouveau_channel_free(chan); -+ atomic_dec(&chan->users); -+ nouveau_channel_put(&chan); - } - } - --int --nouveau_channel_owner(struct drm_device *dev, struct drm_file *file_priv, -- int channel) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_engine *engine = &dev_priv->engine; -- -- if (channel >= engine->fifo.channels) -- return 0; -- if (dev_priv->fifos[channel] == NULL) -- return 0; -- -- return (dev_priv->fifos[channel]->file_priv == file_priv); --} - - /*********************************** - * ioctls wrapping the functions -@@ -383,36 +436,44 @@ - else - init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART; - -- init->subchan[0].handle = NvM2MF; -- if (dev_priv->card_type < NV_50) -- init->subchan[0].grclass = 0x0039; -- else -- init->subchan[0].grclass = 0x5039; -- init->subchan[1].handle = NvSw; -- init->subchan[1].grclass = NV_SW; -- init->nr_subchan = 2; -+ if (dev_priv->card_type < NV_C0) { -+ init->subchan[0].handle = NvM2MF; -+ if (dev_priv->card_type < NV_50) -+ init->subchan[0].grclass = 0x0039; -+ else -+ init->subchan[0].grclass = 0x5039; -+ init->subchan[1].handle = NvSw; -+ init->subchan[1].grclass = NV_SW; -+ init->nr_subchan = 2; -+ } else { -+ init->subchan[0].handle = 0x9039; -+ init->subchan[0].grclass = 0x9039; -+ init->nr_subchan = 1; -+ } - - /* Named memory object area */ - ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem, - &init->notifier_handle); -- if (ret) { -- nouveau_channel_free(chan); -- return ret; -- } - -- return 0; -+ if (ret == 0) -+ atomic_inc(&chan->users); /* userspace reference */ -+ nouveau_channel_put(&chan); -+ return ret; - } - - static int - nouveau_ioctl_fifo_free(struct drm_device *dev, void *data, - struct drm_file *file_priv) - { -- struct drm_nouveau_channel_free *cfree = data; -+ struct drm_nouveau_channel_free *req = data; - struct nouveau_channel *chan; - -- NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan); -+ chan = nouveau_channel_get(dev, file_priv, req->channel); -+ if (IS_ERR(chan)) -+ return PTR_ERR(chan); - -- nouveau_channel_free(chan); -+ atomic_dec(&chan->users); -+ nouveau_channel_put(&chan); - return 0; - } - -@@ -421,18 +482,18 @@ - ***********************************/ - - struct drm_ioctl_desc nouveau_ioctls[] = { -- DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), -- DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH), -- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_UNLOCKED|DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_UNLOCKED|DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_UNLOCKED|DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH), -+ DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH), - }; - - int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls); -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_connector.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_connector.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_connector.c 2011-01-07 14:22:17.000000000 +0100 -@@ -37,6 +37,8 @@ - #include "nouveau_connector.h" - #include "nouveau_hw.h" - -+static void nouveau_connector_hotplug(void *, int); -+ - static struct nouveau_encoder * - find_encoder_by_type(struct drm_connector *connector, int type) - { -@@ -94,22 +96,30 @@ - } - - static void --nouveau_connector_destroy(struct drm_connector *drm_connector) -+nouveau_connector_destroy(struct drm_connector *connector) - { -- struct nouveau_connector *nv_connector = -- nouveau_connector(drm_connector); -+ struct nouveau_connector *nv_connector = nouveau_connector(connector); -+ struct drm_nouveau_private *dev_priv; -+ struct nouveau_gpio_engine *pgpio; - struct drm_device *dev; - - if (!nv_connector) - return; - - dev = nv_connector->base.dev; -+ dev_priv = dev->dev_private; - NV_DEBUG_KMS(dev, "\n"); - -+ pgpio = &dev_priv->engine.gpio; -+ if (pgpio->irq_unregister) { -+ pgpio->irq_unregister(dev, nv_connector->dcb->gpio_tag, -+ nouveau_connector_hotplug, connector); -+ } -+ - kfree(nv_connector->edid); -- drm_sysfs_connector_remove(drm_connector); -- drm_connector_cleanup(drm_connector); -- kfree(drm_connector); -+ drm_sysfs_connector_remove(connector); -+ drm_connector_cleanup(connector); -+ kfree(connector); - } - - static struct nouveau_i2c_chan * -@@ -760,6 +770,7 @@ - { - const struct drm_connector_funcs *funcs = &nouveau_connector_funcs; - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - struct nouveau_connector *nv_connector = NULL; - struct dcb_connector_table_entry *dcb = NULL; - struct drm_connector *connector; -@@ -876,6 +887,11 @@ - break; - } - -+ if (pgpio->irq_register) { -+ pgpio->irq_register(dev, nv_connector->dcb->gpio_tag, -+ nouveau_connector_hotplug, connector); -+ } -+ - drm_sysfs_connector_add(connector); - dcb->drm = connector; - return dcb->drm; -@@ -886,3 +902,29 @@ - return ERR_PTR(ret); - - } -+ -+static void -+nouveau_connector_hotplug(void *data, int plugged) -+{ -+ struct drm_connector *connector = data; -+ struct drm_device *dev = connector->dev; -+ -+ NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un", -+ drm_get_connector_name(connector)); -+ -+ if (connector->encoder && connector->encoder->crtc && -+ connector->encoder->crtc->enabled) { -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(connector->encoder); -+ struct drm_encoder_helper_funcs *helper = -+ connector->encoder->helper_private; -+ -+ if (nv_encoder->dcb->type == OUTPUT_DP) { -+ if (plugged) -+ helper->dpms(connector->encoder, DRM_MODE_DPMS_ON); -+ else -+ helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF); -+ } -+ } -+ -+ drm_helper_hpd_irq_event(dev); -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_display.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_display.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_display.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_display.c 2011-01-07 14:22:17.000000000 +0100 -@@ -29,6 +29,9 @@ - #include "nouveau_drv.h" - #include "nouveau_fb.h" - #include "nouveau_fbcon.h" -+#include "nouveau_hw.h" -+#include "nouveau_crtc.h" -+#include "nouveau_dma.h" - - static void - nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) -@@ -104,3 +107,207 @@ - .output_poll_changed = nouveau_fbcon_output_poll_changed, - }; - -+int -+nouveau_vblank_enable(struct drm_device *dev, int crtc) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->card_type >= NV_50) -+ nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, 0, -+ NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc)); -+ else -+ NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, -+ NV_PCRTC_INTR_0_VBLANK); -+ -+ return 0; -+} -+ -+void -+nouveau_vblank_disable(struct drm_device *dev, int crtc) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->card_type >= NV_50) -+ nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, -+ NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0); -+ else -+ NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0); -+} -+ -+static int -+nouveau_page_flip_reserve(struct nouveau_bo *old_bo, -+ struct nouveau_bo *new_bo) -+{ -+ int ret; -+ -+ ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM); -+ if (ret) -+ return ret; -+ -+ ret = ttm_bo_reserve(&new_bo->bo, false, false, false, 0); -+ if (ret) -+ goto fail; -+ -+ ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0); -+ if (ret) -+ goto fail_unreserve; -+ -+ return 0; -+ -+fail_unreserve: -+ ttm_bo_unreserve(&new_bo->bo); -+fail: -+ nouveau_bo_unpin(new_bo); -+ return ret; -+} -+ -+static void -+nouveau_page_flip_unreserve(struct nouveau_bo *old_bo, -+ struct nouveau_bo *new_bo, -+ struct nouveau_fence *fence) -+{ -+ nouveau_bo_fence(new_bo, fence); -+ ttm_bo_unreserve(&new_bo->bo); -+ -+ nouveau_bo_fence(old_bo, fence); -+ ttm_bo_unreserve(&old_bo->bo); -+ -+ nouveau_bo_unpin(old_bo); -+} -+ -+static int -+nouveau_page_flip_emit(struct nouveau_channel *chan, -+ struct nouveau_bo *old_bo, -+ struct nouveau_bo *new_bo, -+ struct nouveau_page_flip_state *s, -+ struct nouveau_fence **pfence) -+{ -+ struct drm_device *dev = chan->dev; -+ unsigned long flags; -+ int ret; -+ -+ /* Queue it to the pending list */ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ list_add_tail(&s->head, &chan->nvsw.flip); -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ -+ /* Synchronize with the old framebuffer */ -+ ret = nouveau_fence_sync(old_bo->bo.sync_obj, chan); -+ if (ret) -+ goto fail; -+ -+ /* Emit the pageflip */ -+ ret = RING_SPACE(chan, 2); -+ if (ret) -+ goto fail; -+ -+ BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); -+ OUT_RING(chan, 0); -+ FIRE_RING(chan); -+ -+ ret = nouveau_fence_new(chan, pfence, true); -+ if (ret) -+ goto fail; -+ -+ return 0; -+fail: -+ spin_lock_irqsave(&dev->event_lock, flags); -+ list_del(&s->head); -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ return ret; -+} -+ -+int -+nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, -+ struct drm_pending_vblank_event *event) -+{ -+ struct drm_device *dev = crtc->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo; -+ struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; -+ struct nouveau_page_flip_state *s; -+ struct nouveau_channel *chan; -+ struct nouveau_fence *fence; -+ int ret; -+ -+ if (dev_priv->engine.graph.accel_blocked) -+ return -ENODEV; -+ -+ s = kzalloc(sizeof(*s), GFP_KERNEL); -+ if (!s) -+ return -ENOMEM; -+ -+ /* Don't let the buffers go away while we flip */ -+ ret = nouveau_page_flip_reserve(old_bo, new_bo); -+ if (ret) -+ goto fail_free; -+ -+ /* Initialize a page flip struct */ -+ *s = (struct nouveau_page_flip_state) -+ { { }, s->event, nouveau_crtc(crtc)->index, -+ fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y, -+ new_bo->bo.offset }; -+ -+ /* Choose the channel the flip will be handled in */ -+ chan = nouveau_fence_channel(new_bo->bo.sync_obj); -+ if (!chan) -+ chan = nouveau_channel_get_unlocked(dev_priv->channel); -+ mutex_lock(&chan->mutex); -+ -+ /* Emit a page flip */ -+ ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); -+ nouveau_channel_put(&chan); -+ if (ret) -+ goto fail_unreserve; -+ -+ /* Update the crtc struct and cleanup */ -+ crtc->fb = fb; -+ -+ nouveau_page_flip_unreserve(old_bo, new_bo, fence); -+ nouveau_fence_unref(&fence); -+ return 0; -+ -+fail_unreserve: -+ nouveau_page_flip_unreserve(old_bo, new_bo, NULL); -+fail_free: -+ kfree(s); -+ return ret; -+} -+ -+int -+nouveau_finish_page_flip(struct nouveau_channel *chan, -+ struct nouveau_page_flip_state *ps) -+{ -+ struct drm_device *dev = chan->dev; -+ struct nouveau_page_flip_state *s; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ -+ if (list_empty(&chan->nvsw.flip)) { -+ NV_ERROR(dev, "Unexpected pageflip in channel %d.\n", chan->id); -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ return -EINVAL; -+ } -+ -+ s = list_first_entry(&chan->nvsw.flip, -+ struct nouveau_page_flip_state, head); -+ if (s->event) { -+ struct drm_pending_vblank_event *e = s->event; -+ struct timeval now; -+ -+ do_gettimeofday(&now); -+ e->event.sequence = 0; -+ e->event.tv_sec = now.tv_sec; -+ e->event.tv_usec = now.tv_usec; -+ list_add_tail(&e->base.link, &e->base.file_priv->event_list); -+ wake_up_interruptible(&e->base.file_priv->event_wait); -+ } -+ -+ list_del(&s->head); -+ *ps = *s; -+ kfree(s); -+ -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ return 0; -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_dma.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_dma.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_dma.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_dma.c 2011-01-07 14:22:17.000000000 +0100 -@@ -36,7 +36,7 @@ - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nouveau_bo *pushbuf = chan->pushbuf_bo; - -- if (dev_priv->card_type == NV_50) { -+ if (dev_priv->card_type >= NV_50) { - const int ib_size = pushbuf->bo.mem.size / 2; - - chan->dma.ib_base = (pushbuf->bo.mem.size - ib_size) >> 2; -@@ -59,17 +59,26 @@ - { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *obj = NULL; - int ret, i; - -- /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */ -- ret = nouveau_gpuobj_gr_new(chan, dev_priv->card_type < NV_50 ? -- 0x0039 : 0x5039, &obj); -- if (ret) -- return ret; -+ if (dev_priv->card_type >= NV_C0) { -+ ret = nouveau_gpuobj_gr_new(chan, 0x9039, 0x9039); -+ if (ret) -+ return ret; -+ -+ ret = RING_SPACE(chan, 2); -+ if (ret) -+ return ret; -+ -+ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0000, 1); -+ OUT_RING (chan, 0x00009039); -+ FIRE_RING (chan); -+ return 0; -+ } - -- ret = nouveau_ramht_insert(chan, NvM2MF, obj); -- nouveau_gpuobj_ref(NULL, &obj); -+ /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */ -+ ret = nouveau_gpuobj_gr_new(chan, NvM2MF, dev_priv->card_type < NV_50 ? -+ 0x0039 : 0x5039); - if (ret) - return ret; - -@@ -78,11 +87,6 @@ - if (ret) - return ret; - -- /* Map push buffer */ -- ret = nouveau_bo_map(chan->pushbuf_bo); -- if (ret) -- return ret; -- - /* Insert NOPS for NOUVEAU_DMA_SKIPS */ - ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); - if (ret) -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_dma.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_dma.h ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_dma.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_dma.h 2011-01-07 14:22:17.000000000 +0100 -@@ -77,7 +77,8 @@ - /* G80+ display objects */ - NvEvoVRAM = 0x01000000, - NvEvoFB16 = 0x01000001, -- NvEvoFB32 = 0x01000002 -+ NvEvoFB32 = 0x01000002, -+ NvEvoVRAM_LP = 0x01000003 - }; - - #define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039 -@@ -125,6 +126,12 @@ - OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords); - - static inline void -+BEGIN_NVC0(struct nouveau_channel *chan, int op, int subc, int mthd, int size) -+{ -+ OUT_RING(chan, (op << 28) | (size << 16) | (subc << 13) | (mthd >> 2)); -+} -+ -+static inline void - BEGIN_RING(struct nouveau_channel *chan, int subc, int mthd, int size) - { - OUT_RING(chan, (subc << 13) | (size << 18) | mthd); -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_dp.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_dp.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_dp.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_dp.c 2011-01-07 14:22:17.000000000 +0100 -@@ -279,7 +279,7 @@ - struct bit_displayport_encoder_table *dpe; - int dpe_headerlen; - uint8_t config[4], status[3]; -- bool cr_done, cr_max_vs, eq_done; -+ bool cr_done, cr_max_vs, eq_done, hpd_state; - int ret = 0, i, tries, voltage; - - NV_DEBUG_KMS(dev, "link training!!\n"); -@@ -297,7 +297,7 @@ - /* disable hotplug detect, this flips around on some panels during - * link training. - */ -- pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); -+ hpd_state = pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); - - if (dpe->script0) { - NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); -@@ -439,7 +439,7 @@ - } - - /* re-enable hotplug detect */ -- pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); -+ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, hpd_state); - - return eq_done; - } -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_drv.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_drv.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_drv.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_drv.c 2011-01-07 14:22:17.000000000 +0100 -@@ -115,6 +115,10 @@ - int nouveau_perflvl_wr; - module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); - -+MODULE_PARM_DESC(msi, "Enable MSI (default: off)\n"); -+int nouveau_msi; -+module_param_named(msi, nouveau_msi, int, 0400); -+ - int nouveau_fbpercrtc; - #if 0 - module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400); -@@ -193,23 +197,10 @@ - - NV_INFO(dev, "Idling channels...\n"); - for (i = 0; i < pfifo->channels; i++) { -- struct nouveau_fence *fence = NULL; -- -- chan = dev_priv->fifos[i]; -- if (!chan || (dev_priv->card_type >= NV_50 && -- chan == dev_priv->fifos[0])) -- continue; -- -- ret = nouveau_fence_new(chan, &fence, true); -- if (ret == 0) { -- ret = nouveau_fence_wait(fence, NULL, false, false); -- nouveau_fence_unref((void *)&fence); -- } -+ chan = dev_priv->channels.ptr[i]; - -- if (ret) { -- NV_ERROR(dev, "Failed to idle channel %d for suspend\n", -- chan->id); -- } -+ if (chan && chan->pushbuf_bo) -+ nouveau_channel_idle(chan); - } - - pgraph->fifo_access(dev, false); -@@ -219,17 +210,17 @@ - pfifo->unload_context(dev); - pgraph->unload_context(dev); - -- NV_INFO(dev, "Suspending GPU objects...\n"); -- ret = nouveau_gpuobj_suspend(dev); -+ ret = pinstmem->suspend(dev); - if (ret) { - NV_ERROR(dev, "... failed: %d\n", ret); - goto out_abort; - } - -- ret = pinstmem->suspend(dev); -+ NV_INFO(dev, "Suspending GPU objects...\n"); -+ ret = nouveau_gpuobj_suspend(dev); - if (ret) { - NV_ERROR(dev, "... failed: %d\n", ret); -- nouveau_gpuobj_suspend_cleanup(dev); -+ pinstmem->resume(dev); - goto out_abort; - } - -@@ -294,17 +285,18 @@ - } - } - -+ NV_INFO(dev, "Restoring GPU objects...\n"); -+ nouveau_gpuobj_resume(dev); -+ - NV_INFO(dev, "Reinitialising engines...\n"); - engine->instmem.resume(dev); - engine->mc.init(dev); - engine->timer.init(dev); - engine->fb.init(dev); - engine->graph.init(dev); -+ engine->crypt.init(dev); - engine->fifo.init(dev); - -- NV_INFO(dev, "Restoring GPU objects...\n"); -- nouveau_gpuobj_resume(dev); -- - nouveau_irq_postinstall(dev); - - /* Re-write SKIPS, they'll have been lost over the suspend */ -@@ -313,7 +305,7 @@ - int j; - - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- chan = dev_priv->fifos[i]; -+ chan = dev_priv->channels.ptr[i]; - if (!chan || !chan->pushbuf_bo) - continue; - -@@ -347,13 +339,11 @@ - - 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; - -- nv_crtc->cursor.set_offset(nv_crtc, -- nv_crtc->cursor.nvbo->bo.offset - -- dev_priv->vm_vram_base); -- -+ nv_crtc->cursor.set_offset(nv_crtc, offset); - nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x, -- nv_crtc->cursor_saved_y); -+ nv_crtc->cursor_saved_y); - } - - /* Force CLUT to get re-loaded during modeset */ -@@ -393,6 +383,9 @@ - .irq_postinstall = nouveau_irq_postinstall, - .irq_uninstall = nouveau_irq_uninstall, - .irq_handler = nouveau_irq_handler, -+ .get_vblank_counter = drm_vblank_count, -+ .enable_vblank = nouveau_vblank_enable, -+ .disable_vblank = nouveau_vblank_disable, - .reclaim_buffers = drm_core_reclaim_buffers, - .ioctls = nouveau_ioctls, - .fops = { -@@ -403,6 +396,7 @@ - .mmap = nouveau_ttm_mmap, - .poll = drm_poll, - .fasync = drm_fasync, -+ .read = drm_read, - #if defined(CONFIG_COMPAT) - .compat_ioctl = nouveau_compat_ioctl, - #endif -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_drv.h ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_drv.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_drv.h 2011-01-07 14:22:17.000000000 +0100 -@@ -54,22 +54,37 @@ - #include "nouveau_drm.h" - #include "nouveau_reg.h" - #include "nouveau_bios.h" -+#include "nouveau_util.h" -+ - struct nouveau_grctx; -+struct nouveau_vram; -+#include "nouveau_vm.h" - - #define MAX_NUM_DCB_ENTRIES 16 - - #define NOUVEAU_MAX_CHANNEL_NR 128 - #define NOUVEAU_MAX_TILE_NR 15 - --#define NV50_VM_MAX_VRAM (2*1024*1024*1024ULL) --#define NV50_VM_BLOCK (512*1024*1024ULL) --#define NV50_VM_VRAM_NR (NV50_VM_MAX_VRAM / NV50_VM_BLOCK) -+struct nouveau_vram { -+ struct drm_device *dev; -+ -+ struct nouveau_vma bar_vma; -+ u8 page_shift; -+ -+ struct list_head regions; -+ u32 memtype; -+ u64 offset; -+ u64 size; -+}; - - struct nouveau_tile_reg { -- struct nouveau_fence *fence; -- uint32_t addr; -- uint32_t size; - bool used; -+ uint32_t addr; -+ uint32_t limit; -+ uint32_t pitch; -+ uint32_t zcomp; -+ struct drm_mm_node *tag_mem; -+ struct nouveau_fence *fence; - }; - - struct nouveau_bo { -@@ -88,6 +103,7 @@ - - struct nouveau_channel *channel; - -+ struct nouveau_vma vma; - bool mappable; - bool no_vm; - -@@ -96,7 +112,6 @@ - struct nouveau_tile_reg *tile; - - struct drm_gem_object *gem; -- struct drm_file *cpu_filp; - int pin_refcnt; - }; - -@@ -133,20 +148,28 @@ - - #define NVOBJ_ENGINE_SW 0 - #define NVOBJ_ENGINE_GR 1 --#define NVOBJ_ENGINE_DISPLAY 2 -+#define NVOBJ_ENGINE_PPP 2 -+#define NVOBJ_ENGINE_COPY 3 -+#define NVOBJ_ENGINE_VP 4 -+#define NVOBJ_ENGINE_CRYPT 5 -+#define NVOBJ_ENGINE_BSP 6 -+#define NVOBJ_ENGINE_DISPLAY 0xcafe0001 - #define NVOBJ_ENGINE_INT 0xdeadbeef - -+#define NVOBJ_FLAG_DONT_MAP (1 << 0) - #define NVOBJ_FLAG_ZERO_ALLOC (1 << 1) - #define NVOBJ_FLAG_ZERO_FREE (1 << 2) -+#define NVOBJ_FLAG_VM (1 << 3) -+ -+#define NVOBJ_CINST_GLOBAL 0xdeadbeef -+ - struct nouveau_gpuobj { - struct drm_device *dev; - struct kref refcount; - struct list_head list; - -- struct drm_mm_node *im_pramin; -- struct nouveau_bo *im_backing; -- uint32_t *im_backing_suspend; -- int im_bound; -+ void *node; -+ u32 *suspend; - - uint32_t flags; - -@@ -162,10 +185,29 @@ - void *priv; - }; - -+struct nouveau_page_flip_state { -+ struct list_head head; -+ struct drm_pending_vblank_event *event; -+ int crtc, bpp, pitch, x, y; -+ uint64_t offset; -+}; -+ -+enum nouveau_channel_mutex_class { -+ NOUVEAU_UCHANNEL_MUTEX, -+ NOUVEAU_KCHANNEL_MUTEX -+}; -+ - struct nouveau_channel { - struct drm_device *dev; - int id; - -+ /* references to the channel data structure */ -+ struct kref ref; -+ /* users of the hardware channel resources, the hardware -+ * context will be kicked off when it reaches zero. */ -+ atomic_t users; -+ struct mutex mutex; -+ - /* owner of this fifo */ - struct drm_file *file_priv; - /* mapping of the fifo itself */ -@@ -198,16 +240,17 @@ - /* PFIFO context */ - struct nouveau_gpuobj *ramfc; - struct nouveau_gpuobj *cache; -+ void *fifo_priv; - - /* PGRAPH context */ - /* XXX may be merge 2 pointers as private data ??? */ - struct nouveau_gpuobj *ramin_grctx; -+ struct nouveau_gpuobj *crypt_ctx; - void *pgraph_ctx; - - /* NV50 VM */ -+ struct nouveau_vm *vm; - struct nouveau_gpuobj *vm_pd; -- struct nouveau_gpuobj *vm_gart_pt; -- struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; - - /* Objects */ - struct nouveau_gpuobj *ramin; /* Private instmem */ -@@ -238,9 +281,11 @@ - - struct { - struct nouveau_gpuobj *vblsem; -+ uint32_t vblsem_head; - uint32_t vblsem_offset; - uint32_t vblsem_rval; - struct list_head vbl_wait; -+ struct list_head flip; - } nvsw; - - struct { -@@ -258,11 +303,11 @@ - int (*suspend)(struct drm_device *dev); - void (*resume)(struct drm_device *dev); - -- int (*populate)(struct drm_device *, struct nouveau_gpuobj *, -- uint32_t *size); -- void (*clear)(struct drm_device *, struct nouveau_gpuobj *); -- int (*bind)(struct drm_device *, struct nouveau_gpuobj *); -- int (*unbind)(struct drm_device *, struct nouveau_gpuobj *); -+ int (*get)(struct nouveau_gpuobj *, u32 size, u32 align); -+ void (*put)(struct nouveau_gpuobj *); -+ int (*map)(struct nouveau_gpuobj *); -+ void (*unmap)(struct nouveau_gpuobj *); -+ - void (*flush)(struct drm_device *); - }; - -@@ -279,15 +324,21 @@ - - struct nouveau_fb_engine { - int num_tiles; -+ struct drm_mm tag_heap; -+ void *priv; - - int (*init)(struct drm_device *dev); - void (*takedown)(struct drm_device *dev); - -- void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch); -+ void (*init_tile_region)(struct drm_device *dev, int i, -+ uint32_t addr, uint32_t size, -+ uint32_t pitch, uint32_t flags); -+ void (*set_tile_region)(struct drm_device *dev, int i); -+ void (*free_tile_region)(struct drm_device *dev, int i); - }; - - struct nouveau_fifo_engine { -+ void *priv; - int channels; - - struct nouveau_gpuobj *playlist[2]; -@@ -310,22 +361,11 @@ - void (*tlb_flush)(struct drm_device *dev); - }; - --struct nouveau_pgraph_object_method { -- int id; -- int (*exec)(struct nouveau_channel *chan, int grclass, int mthd, -- uint32_t data); --}; -- --struct nouveau_pgraph_object_class { -- int id; -- bool software; -- struct nouveau_pgraph_object_method *methods; --}; -- - struct nouveau_pgraph_engine { -- struct nouveau_pgraph_object_class *grclass; - bool accel_blocked; -+ bool registered; - int grctx_size; -+ void *priv; - - /* NV2x/NV3x context table (0x400780) */ - struct nouveau_gpuobj *ctx_table; -@@ -342,8 +382,7 @@ - int (*unload_context)(struct drm_device *); - void (*tlb_flush)(struct drm_device *dev); - -- void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch); -+ void (*set_tile_region)(struct drm_device *dev, int i); - }; - - struct nouveau_display_engine { -@@ -355,13 +394,19 @@ - }; - - struct nouveau_gpio_engine { -+ void *priv; -+ - int (*init)(struct drm_device *); - void (*takedown)(struct drm_device *); - - int (*get)(struct drm_device *, enum dcb_gpio_tag); - int (*set)(struct drm_device *, enum dcb_gpio_tag, int state); - -- void (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on); -+ int (*irq_register)(struct drm_device *, enum dcb_gpio_tag, -+ void (*)(void *, int), void *); -+ void (*irq_unregister)(struct drm_device *, enum dcb_gpio_tag, -+ void (*)(void *, int), void *); -+ bool (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on); - }; - - struct nouveau_pm_voltage_level { -@@ -437,6 +482,7 @@ - struct nouveau_pm_level *cur; - - struct device *hwmon; -+ struct notifier_block acpi_nb; - - int (*clock_get)(struct drm_device *, u32 id); - void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *, -@@ -449,6 +495,25 @@ - int (*temp_get)(struct drm_device *); - }; - -+struct nouveau_crypt_engine { -+ bool registered; -+ -+ int (*init)(struct drm_device *); -+ void (*takedown)(struct drm_device *); -+ int (*create_context)(struct nouveau_channel *); -+ void (*destroy_context)(struct nouveau_channel *); -+ void (*tlb_flush)(struct drm_device *dev); -+}; -+ -+struct nouveau_vram_engine { -+ int (*init)(struct drm_device *); -+ int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, -+ u32 type, struct nouveau_vram **); -+ void (*put)(struct drm_device *, struct nouveau_vram **); -+ -+ bool (*flags_valid)(struct drm_device *, u32 tile_flags); -+}; -+ - struct nouveau_engine { - struct nouveau_instmem_engine instmem; - struct nouveau_mc_engine mc; -@@ -459,6 +524,8 @@ - struct nouveau_display_engine display; - struct nouveau_gpio_engine gpio; - struct nouveau_pm_engine pm; -+ struct nouveau_crypt_engine crypt; -+ struct nouveau_vram_engine vram; - }; - - struct nouveau_pll_vals { -@@ -577,18 +644,15 @@ - bool ramin_available; - struct drm_mm ramin_heap; - struct list_head gpuobj_list; -+ struct list_head classes; - - struct nouveau_bo *vga_ram; - -+ /* interrupt handling */ -+ void (*irq_handler[32])(struct drm_device *); -+ bool msi_enabled; - struct workqueue_struct *wq; - struct work_struct irq_work; -- struct work_struct hpd_work; -- -- struct { -- spinlock_t lock; -- uint32_t hpd0_bits; -- uint32_t hpd1_bits; -- } hpd_state; - - struct list_head vbl_waiting; - -@@ -605,8 +669,10 @@ - struct nouveau_bo *bo; - } fence; - -- int fifo_alloc_count; -- struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR]; -+ struct { -+ spinlock_t lock; -+ struct nouveau_channel *ptr[NOUVEAU_MAX_CHANNEL_NR]; -+ } channels; - - struct nouveau_engine engine; - struct nouveau_channel *channel; -@@ -632,12 +698,14 @@ - uint64_t aper_free; - - struct nouveau_gpuobj *sg_ctxdma; -- struct page *sg_dummy_page; -- dma_addr_t sg_dummy_bus; -+ struct nouveau_vma vma; - } gart_info; - - /* nv10-nv40 tiling regions */ -- struct nouveau_tile_reg tile[NOUVEAU_MAX_TILE_NR]; -+ struct { -+ struct nouveau_tile_reg reg[NOUVEAU_MAX_TILE_NR]; -+ spinlock_t lock; -+ } tile; - - /* VRAM/fb configuration */ - uint64_t vram_size; -@@ -650,14 +718,12 @@ - uint64_t fb_aper_free; - int fb_mtrr; - -+ /* BAR control (NV50-) */ -+ struct nouveau_vm *bar1_vm; -+ struct nouveau_vm *bar3_vm; -+ - /* G8x/G9x virtual address space */ -- uint64_t vm_gart_base; -- uint64_t vm_gart_size; -- uint64_t vm_vram_base; -- uint64_t vm_vram_size; -- uint64_t vm_end; -- struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; -- int vm_vram_pt_nr; -+ struct nouveau_vm *chan_vm; - - struct nvbios vbios; - -@@ -674,6 +740,7 @@ - struct backlight_device *backlight; - - struct nouveau_channel *evo; -+ u32 evo_alloc; - struct { - struct dcb_entry *dcb; - u16 script; -@@ -719,16 +786,6 @@ - return 0; - } - --#define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id, cl, ch) do { \ -- struct drm_nouveau_private *nv = dev->dev_private; \ -- if (!nouveau_channel_owner(dev, (cl), (id))) { \ -- NV_ERROR(dev, "pid %d doesn't own channel %d\n", \ -- DRM_CURRENTPID, (id)); \ -- return -EPERM; \ -- } \ -- (ch) = nv->fifos[(id)]; \ --} while (0) -- - /* nouveau_drv.c */ - extern int nouveau_agpmode; - extern int nouveau_duallink; -@@ -748,6 +805,7 @@ - extern int nouveau_override_conntype; - extern char *nouveau_perflvl; - extern int nouveau_perflvl_wr; -+extern int nouveau_msi; - - extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state); - extern int nouveau_pci_resume(struct pci_dev *pdev); -@@ -762,8 +820,10 @@ - struct drm_file *); - extern int nouveau_ioctl_setparam(struct drm_device *, void *data, - struct drm_file *); --extern bool nouveau_wait_until(struct drm_device *, uint64_t timeout, -- uint32_t reg, uint32_t mask, uint32_t val); -+extern bool nouveau_wait_eq(struct drm_device *, uint64_t timeout, -+ 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_for_idle(struct drm_device *); - extern int nouveau_card_init(struct drm_device *); - -@@ -775,18 +835,18 @@ - extern int nouveau_mem_init_agp(struct drm_device *); - extern int nouveau_mem_reset_agp(struct drm_device *); - extern void nouveau_mem_close(struct drm_device *); --extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev, -- uint32_t addr, -- uint32_t size, -- uint32_t pitch); --extern void nv10_mem_expire_tiling(struct drm_device *dev, -- struct nouveau_tile_reg *tile, -- struct nouveau_fence *fence); --extern int nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt, -- uint32_t size, uint32_t flags, -- uint64_t phys); --extern void nv50_mem_vm_unbind(struct drm_device *, uint64_t virt, -- uint32_t size); -+extern int nouveau_mem_detect(struct drm_device *); -+extern bool nouveau_mem_flags_valid(struct drm_device *, u32 tile_flags); -+extern struct nouveau_tile_reg *nv10_mem_set_tiling( -+ struct drm_device *dev, uint32_t addr, uint32_t size, -+ uint32_t pitch, uint32_t flags); -+extern void nv10_mem_put_tile_region(struct drm_device *dev, -+ struct nouveau_tile_reg *tile, -+ struct nouveau_fence *fence); -+extern const struct ttm_mem_type_manager_func nouveau_vram_manager; -+ -+/* nvc0_vram.c */ -+extern const struct ttm_mem_type_manager_func nvc0_vram_manager; - - /* nouveau_notifier.c */ - extern int nouveau_notifier_init_channel(struct nouveau_channel *); -@@ -803,21 +863,44 @@ - extern struct drm_ioctl_desc nouveau_ioctls[]; - extern int nouveau_max_ioctl; - extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *); --extern int nouveau_channel_owner(struct drm_device *, struct drm_file *, -- int channel); - extern int nouveau_channel_alloc(struct drm_device *dev, - struct nouveau_channel **chan, - struct drm_file *file_priv, - uint32_t fb_ctxdma, uint32_t tt_ctxdma); --extern void nouveau_channel_free(struct nouveau_channel *); -+extern struct nouveau_channel * -+nouveau_channel_get_unlocked(struct nouveau_channel *); -+extern struct nouveau_channel * -+nouveau_channel_get(struct drm_device *, struct drm_file *, int id); -+extern void nouveau_channel_put_unlocked(struct nouveau_channel **); -+extern void nouveau_channel_put(struct nouveau_channel **); -+extern void nouveau_channel_ref(struct nouveau_channel *chan, -+ struct nouveau_channel **pchan); -+extern void nouveau_channel_idle(struct nouveau_channel *chan); - - /* nouveau_object.c */ -+#define NVOBJ_CLASS(d,c,e) do { \ -+ int ret = nouveau_gpuobj_class_new((d), (c), NVOBJ_ENGINE_##e); \ -+ if (ret) \ -+ return ret; \ -+} while(0) -+ -+#define NVOBJ_MTHD(d,c,m,e) do { \ -+ int ret = nouveau_gpuobj_mthd_new((d), (c), (m), (e)); \ -+ if (ret) \ -+ return ret; \ -+} while(0) -+ - extern int nouveau_gpuobj_early_init(struct drm_device *); - extern int nouveau_gpuobj_init(struct drm_device *); - extern void nouveau_gpuobj_takedown(struct drm_device *); - extern int nouveau_gpuobj_suspend(struct drm_device *dev); --extern void nouveau_gpuobj_suspend_cleanup(struct drm_device *dev); - extern void nouveau_gpuobj_resume(struct drm_device *dev); -+extern int nouveau_gpuobj_class_new(struct drm_device *, u32 class, u32 eng); -+extern int nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd, -+ int (*exec)(struct nouveau_channel *, -+ u32 class, u32 mthd, u32 data)); -+extern int nouveau_gpuobj_mthd_call(struct nouveau_channel *, u32, u32, u32); -+extern int nouveau_gpuobj_mthd_call2(struct drm_device *, int, u32, u32, u32); - extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, - uint32_t vram_h, uint32_t tt_h); - extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *); -@@ -832,21 +915,25 @@ - extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class, - uint64_t offset, uint64_t size, int access, - int target, struct nouveau_gpuobj **); --extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *, -- uint64_t offset, uint64_t size, -- int access, struct nouveau_gpuobj **, -- uint32_t *o_ret); --extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class, -- struct nouveau_gpuobj **); --extern int nouveau_gpuobj_sw_new(struct nouveau_channel *, int class, -- struct nouveau_gpuobj **); -+extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, u32 handle, int class); -+extern int nv50_gpuobj_dma_new(struct nouveau_channel *, int class, u64 base, -+ u64 size, int target, int access, u32 type, -+ u32 comp, struct nouveau_gpuobj **pobj); -+extern void nv50_gpuobj_dma_init(struct nouveau_gpuobj *, u32 offset, -+ int class, u64 base, u64 size, int target, -+ int access, u32 type, u32 comp); - extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data, - struct drm_file *); - extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data, - struct drm_file *); - - /* nouveau_irq.c */ -+extern int nouveau_irq_init(struct drm_device *); -+extern void nouveau_irq_fini(struct drm_device *); - extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); -+extern void nouveau_irq_register(struct drm_device *, int status_bit, -+ void (*)(struct drm_device *)); -+extern void nouveau_irq_unregister(struct drm_device *, int status_bit); - extern void nouveau_irq_preinstall(struct drm_device *); - extern int nouveau_irq_postinstall(struct drm_device *); - extern void nouveau_irq_uninstall(struct drm_device *); -@@ -854,8 +941,8 @@ - /* nouveau_sgdma.c */ - extern int nouveau_sgdma_init(struct drm_device *); - extern void nouveau_sgdma_takedown(struct drm_device *); --extern int nouveau_sgdma_get_page(struct drm_device *, uint32_t offset, -- uint32_t *page); -+extern uint32_t nouveau_sgdma_get_physical(struct drm_device *, -+ uint32_t offset); - extern struct ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *); - - /* nouveau_debugfs.c */ -@@ -966,18 +1053,25 @@ - /* nv10_fb.c */ - extern int nv10_fb_init(struct drm_device *); - extern void nv10_fb_takedown(struct drm_device *); --extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t, -- uint32_t, uint32_t); -+extern void nv10_fb_init_tile_region(struct drm_device *dev, int i, -+ uint32_t addr, uint32_t size, -+ uint32_t pitch, uint32_t flags); -+extern void nv10_fb_set_tile_region(struct drm_device *dev, int i); -+extern void nv10_fb_free_tile_region(struct drm_device *dev, int i); - - /* nv30_fb.c */ - extern int nv30_fb_init(struct drm_device *); - extern void nv30_fb_takedown(struct drm_device *); -+extern void nv30_fb_init_tile_region(struct drm_device *dev, int i, -+ uint32_t addr, uint32_t size, -+ uint32_t pitch, uint32_t flags); -+extern void nv30_fb_free_tile_region(struct drm_device *dev, int i); - - /* nv40_fb.c */ - extern int nv40_fb_init(struct drm_device *); - extern void nv40_fb_takedown(struct drm_device *); --extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t, -- uint32_t, uint32_t); -+extern void nv40_fb_set_tile_region(struct drm_device *dev, int i); -+ - /* nv50_fb.c */ - extern int nv50_fb_init(struct drm_device *); - extern void nv50_fb_takedown(struct drm_device *); -@@ -989,6 +1083,7 @@ - - /* nv04_fifo.c */ - extern int nv04_fifo_init(struct drm_device *); -+extern void nv04_fifo_fini(struct drm_device *); - extern void nv04_fifo_disable(struct drm_device *); - extern void nv04_fifo_enable(struct drm_device *); - extern bool nv04_fifo_reassign(struct drm_device *, bool); -@@ -998,19 +1093,18 @@ - extern void nv04_fifo_destroy_context(struct nouveau_channel *); - extern int nv04_fifo_load_context(struct nouveau_channel *); - extern int nv04_fifo_unload_context(struct drm_device *); -+extern void nv04_fifo_isr(struct drm_device *); - - /* nv10_fifo.c */ - extern int nv10_fifo_init(struct drm_device *); - extern int nv10_fifo_channel_id(struct drm_device *); - extern int nv10_fifo_create_context(struct nouveau_channel *); --extern void nv10_fifo_destroy_context(struct nouveau_channel *); - extern int nv10_fifo_load_context(struct nouveau_channel *); - extern int nv10_fifo_unload_context(struct drm_device *); - - /* nv40_fifo.c */ - extern int nv40_fifo_init(struct drm_device *); - extern int nv40_fifo_create_context(struct nouveau_channel *); --extern void nv40_fifo_destroy_context(struct nouveau_channel *); - extern int nv40_fifo_load_context(struct nouveau_channel *); - extern int nv40_fifo_unload_context(struct drm_device *); - -@@ -1038,7 +1132,6 @@ - extern int nvc0_fifo_unload_context(struct drm_device *); - - /* nv04_graph.c */ --extern struct nouveau_pgraph_object_class nv04_graph_grclass[]; - extern int nv04_graph_init(struct drm_device *); - extern void nv04_graph_takedown(struct drm_device *); - extern void nv04_graph_fifo_access(struct drm_device *, bool); -@@ -1047,10 +1140,11 @@ - extern void nv04_graph_destroy_context(struct nouveau_channel *); - extern int nv04_graph_load_context(struct nouveau_channel *); - extern int nv04_graph_unload_context(struct drm_device *); --extern void nv04_graph_context_switch(struct drm_device *); -+extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data); -+extern struct nouveau_bitfield nv04_graph_nsource[]; - - /* nv10_graph.c */ --extern struct nouveau_pgraph_object_class nv10_graph_grclass[]; - extern int nv10_graph_init(struct drm_device *); - extern void nv10_graph_takedown(struct drm_device *); - extern struct nouveau_channel *nv10_graph_channel(struct drm_device *); -@@ -1058,13 +1152,11 @@ - extern void nv10_graph_destroy_context(struct nouveau_channel *); - extern int nv10_graph_load_context(struct nouveau_channel *); - extern int nv10_graph_unload_context(struct drm_device *); --extern void nv10_graph_context_switch(struct drm_device *); --extern void nv10_graph_set_region_tiling(struct drm_device *, int, uint32_t, -- uint32_t, uint32_t); -+extern void nv10_graph_set_tile_region(struct drm_device *dev, int i); -+extern struct nouveau_bitfield nv10_graph_intr[]; -+extern struct nouveau_bitfield nv10_graph_nstatus[]; - - /* nv20_graph.c */ --extern struct nouveau_pgraph_object_class nv20_graph_grclass[]; --extern struct nouveau_pgraph_object_class nv30_graph_grclass[]; - extern int nv20_graph_create_context(struct nouveau_channel *); - extern void nv20_graph_destroy_context(struct nouveau_channel *); - extern int nv20_graph_load_context(struct nouveau_channel *); -@@ -1072,11 +1164,9 @@ - extern int nv20_graph_init(struct drm_device *); - extern void nv20_graph_takedown(struct drm_device *); - extern int nv30_graph_init(struct drm_device *); --extern void nv20_graph_set_region_tiling(struct drm_device *, int, uint32_t, -- uint32_t, uint32_t); -+extern void nv20_graph_set_tile_region(struct drm_device *dev, int i); - - /* nv40_graph.c */ --extern struct nouveau_pgraph_object_class nv40_graph_grclass[]; - extern int nv40_graph_init(struct drm_device *); - extern void nv40_graph_takedown(struct drm_device *); - extern struct nouveau_channel *nv40_graph_channel(struct drm_device *); -@@ -1085,11 +1175,9 @@ - extern int nv40_graph_load_context(struct nouveau_channel *); - extern int nv40_graph_unload_context(struct drm_device *); - extern void nv40_grctx_init(struct nouveau_grctx *); --extern void nv40_graph_set_region_tiling(struct drm_device *, int, uint32_t, -- uint32_t, uint32_t); -+extern void nv40_graph_set_tile_region(struct drm_device *dev, int i); - - /* nv50_graph.c */ --extern struct nouveau_pgraph_object_class nv50_graph_grclass[]; - extern int nv50_graph_init(struct drm_device *); - extern void nv50_graph_takedown(struct drm_device *); - extern void nv50_graph_fifo_access(struct drm_device *, bool); -@@ -1098,10 +1186,10 @@ - extern void nv50_graph_destroy_context(struct nouveau_channel *); - extern int nv50_graph_load_context(struct nouveau_channel *); - extern int nv50_graph_unload_context(struct drm_device *); --extern void nv50_graph_context_switch(struct drm_device *); - extern int nv50_grctx_init(struct nouveau_grctx *); - extern void nv50_graph_tlb_flush(struct drm_device *dev); - extern void nv86_graph_tlb_flush(struct drm_device *dev); -+extern struct nouveau_enum nv50_data_error_names[]; - - /* nvc0_graph.c */ - extern int nvc0_graph_init(struct drm_device *); -@@ -1113,16 +1201,22 @@ - extern int nvc0_graph_load_context(struct nouveau_channel *); - extern int nvc0_graph_unload_context(struct drm_device *); - -+/* nv84_crypt.c */ -+extern int nv84_crypt_init(struct drm_device *dev); -+extern void nv84_crypt_fini(struct drm_device *dev); -+extern int nv84_crypt_create_context(struct nouveau_channel *); -+extern void nv84_crypt_destroy_context(struct nouveau_channel *); -+extern void nv84_crypt_tlb_flush(struct drm_device *dev); -+ - /* nv04_instmem.c */ - extern int nv04_instmem_init(struct drm_device *); - extern void nv04_instmem_takedown(struct drm_device *); - extern int nv04_instmem_suspend(struct drm_device *); - extern void nv04_instmem_resume(struct drm_device *); --extern int nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, -- uint32_t *size); --extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); --extern int nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); --extern int nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); -+extern int nv04_instmem_get(struct nouveau_gpuobj *, 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 *); - extern void nv04_instmem_flush(struct drm_device *); - - /* nv50_instmem.c */ -@@ -1130,26 +1224,18 @@ - 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_populate(struct drm_device *, struct nouveau_gpuobj *, -- uint32_t *size); --extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); --extern int nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); --extern int nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); -+extern int nv50_instmem_get(struct nouveau_gpuobj *, 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 *); - extern void nv50_instmem_flush(struct drm_device *); - extern void nv84_instmem_flush(struct drm_device *); --extern void nv50_vm_flush(struct drm_device *, int engine); - - /* nvc0_instmem.c */ - extern int nvc0_instmem_init(struct drm_device *); - extern void nvc0_instmem_takedown(struct drm_device *); - extern int nvc0_instmem_suspend(struct drm_device *); - extern void nvc0_instmem_resume(struct drm_device *); --extern int nvc0_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, -- uint32_t *size); --extern void nvc0_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); --extern int nvc0_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); --extern int nvc0_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); --extern void nvc0_instmem_flush(struct drm_device *); - - /* nv04_mc.c */ - extern int nv04_mc_init(struct drm_device *); -@@ -1219,6 +1305,9 @@ - extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); - extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); - extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); -+extern void nouveau_bo_fence(struct nouveau_bo *, struct nouveau_fence *); -+extern int nouveau_bo_validate(struct nouveau_bo *, bool interruptible, -+ bool no_wait_reserve, bool no_wait_gpu); - - /* nouveau_fence.c */ - struct nouveau_fence; -@@ -1234,12 +1323,35 @@ - void (*work)(void *priv, bool signalled), - void *priv); - struct nouveau_channel *nouveau_fence_channel(struct nouveau_fence *); --extern bool nouveau_fence_signalled(void *obj, void *arg); --extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); -+ -+extern bool __nouveau_fence_signalled(void *obj, void *arg); -+extern int __nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); -+extern int __nouveau_fence_flush(void *obj, void *arg); -+extern void __nouveau_fence_unref(void **obj); -+extern void *__nouveau_fence_ref(void *obj); -+ -+static inline bool nouveau_fence_signalled(struct nouveau_fence *obj) -+{ -+ return __nouveau_fence_signalled(obj, NULL); -+} -+static inline int -+nouveau_fence_wait(struct nouveau_fence *obj, bool lazy, bool intr) -+{ -+ return __nouveau_fence_wait(obj, NULL, lazy, intr); -+} - extern int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *); --extern int nouveau_fence_flush(void *obj, void *arg); --extern void nouveau_fence_unref(void **obj); --extern void *nouveau_fence_ref(void *obj); -+static inline int nouveau_fence_flush(struct nouveau_fence *obj) -+{ -+ return __nouveau_fence_flush(obj, NULL); -+} -+static inline void nouveau_fence_unref(struct nouveau_fence **obj) -+{ -+ __nouveau_fence_unref((void **)obj); -+} -+static inline struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *obj) -+{ -+ return __nouveau_fence_ref(obj); -+} - - /* nouveau_gem.c */ - extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, -@@ -1259,15 +1371,28 @@ - extern int nouveau_gem_ioctl_info(struct drm_device *, void *, - struct drm_file *); - -+/* nouveau_display.c */ -+int nouveau_vblank_enable(struct drm_device *dev, int crtc); -+void nouveau_vblank_disable(struct drm_device *dev, int crtc); -+int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, -+ struct drm_pending_vblank_event *event); -+int nouveau_finish_page_flip(struct nouveau_channel *, -+ struct nouveau_page_flip_state *); -+ - /* nv10_gpio.c */ - int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); - int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); - - /* nv50_gpio.c */ - int nv50_gpio_init(struct drm_device *dev); -+void nv50_gpio_fini(struct drm_device *dev); - int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); - int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); --void nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on); -+int nv50_gpio_irq_register(struct drm_device *, enum dcb_gpio_tag, -+ void (*)(void *, int), void *); -+void nv50_gpio_irq_unregister(struct drm_device *, enum dcb_gpio_tag, -+ void (*)(void *, int), void *); -+bool nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on); - - /* nv50_calc. */ - int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk, -@@ -1334,7 +1459,9 @@ - } - - #define nv_wait(dev, reg, mask, val) \ -- nouveau_wait_until(dev, 2000000000ULL, (reg), (mask), (val)) -+ nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val)) -+#define nv_wait_ne(dev, reg, mask, val) \ -+ nouveau_wait_ne(dev, 2000000000ULL, (reg), (mask), (val)) - - /* PRAMIN access */ - static inline u32 nv_ri32(struct drm_device *dev, unsigned offset) -@@ -1447,6 +1574,23 @@ - dev->pdev->subsystem_device == sub_device; - } - -+/* memory type/access flags, do not match hardware values */ -+#define NV_MEM_ACCESS_RO 1 -+#define NV_MEM_ACCESS_WO 2 -+#define NV_MEM_ACCESS_RW (NV_MEM_ACCESS_RO | NV_MEM_ACCESS_WO) -+#define NV_MEM_ACCESS_SYS 4 -+#define NV_MEM_ACCESS_VM 8 -+ -+#define NV_MEM_TARGET_VRAM 0 -+#define NV_MEM_TARGET_PCI 1 -+#define NV_MEM_TARGET_PCI_NOSNOOP 2 -+#define NV_MEM_TARGET_VM 3 -+#define NV_MEM_TARGET_GART 4 -+ -+#define NV_MEM_TYPE_VM 0x7f -+#define NV_MEM_COMP_VM 0x03 -+ -+/* NV_SW object class */ - #define NV_SW 0x0000506e - #define NV_SW_DMA_SEMAPHORE 0x00000060 - #define NV_SW_SEMAPHORE_OFFSET 0x00000064 -@@ -1457,5 +1601,6 @@ - #define NV_SW_VBLSEM_OFFSET 0x00000400 - #define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404 - #define NV_SW_VBLSEM_RELEASE 0x00000408 -+#define NV_SW_PAGE_FLIP 0x00000500 - - #endif /* __NOUVEAU_DRV_H__ */ -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_fbcon.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2011-01-07 14:22:17.000000000 +0100 -@@ -49,6 +49,102 @@ - #include "nouveau_fbcon.h" - #include "nouveau_dma.h" - -+static void -+nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) -+{ -+ struct nouveau_fbdev *nfbdev = info->par; -+ struct drm_device *dev = nfbdev->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int ret; -+ -+ if (info->state != FBINFO_STATE_RUNNING) -+ return; -+ -+ ret = -ENODEV; -+ if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && -+ mutex_trylock(&dev_priv->channel->mutex)) { -+ if (dev_priv->card_type < NV_50) -+ ret = nv04_fbcon_fillrect(info, rect); -+ else -+ if (dev_priv->card_type < NV_C0) -+ ret = nv50_fbcon_fillrect(info, rect); -+ else -+ ret = nvc0_fbcon_fillrect(info, rect); -+ mutex_unlock(&dev_priv->channel->mutex); -+ } -+ -+ if (ret == 0) -+ return; -+ -+ if (ret != -ENODEV) -+ nouveau_fbcon_gpu_lockup(info); -+ cfb_fillrect(info, rect); -+} -+ -+static void -+nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image) -+{ -+ struct nouveau_fbdev *nfbdev = info->par; -+ struct drm_device *dev = nfbdev->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int ret; -+ -+ if (info->state != FBINFO_STATE_RUNNING) -+ return; -+ -+ ret = -ENODEV; -+ if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && -+ mutex_trylock(&dev_priv->channel->mutex)) { -+ if (dev_priv->card_type < NV_50) -+ ret = nv04_fbcon_copyarea(info, image); -+ else -+ if (dev_priv->card_type < NV_C0) -+ ret = nv50_fbcon_copyarea(info, image); -+ else -+ ret = nvc0_fbcon_copyarea(info, image); -+ mutex_unlock(&dev_priv->channel->mutex); -+ } -+ -+ if (ret == 0) -+ return; -+ -+ if (ret != -ENODEV) -+ nouveau_fbcon_gpu_lockup(info); -+ cfb_copyarea(info, image); -+} -+ -+static void -+nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) -+{ -+ struct nouveau_fbdev *nfbdev = info->par; -+ struct drm_device *dev = nfbdev->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int ret; -+ -+ if (info->state != FBINFO_STATE_RUNNING) -+ return; -+ -+ ret = -ENODEV; -+ if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && -+ mutex_trylock(&dev_priv->channel->mutex)) { -+ if (dev_priv->card_type < NV_50) -+ ret = nv04_fbcon_imageblit(info, image); -+ else -+ if (dev_priv->card_type < NV_C0) -+ ret = nv50_fbcon_imageblit(info, image); -+ else -+ ret = nvc0_fbcon_imageblit(info, image); -+ mutex_unlock(&dev_priv->channel->mutex); -+ } -+ -+ if (ret == 0) -+ return; -+ -+ if (ret != -ENODEV) -+ nouveau_fbcon_gpu_lockup(info); -+ cfb_imageblit(info, image); -+} -+ - static int - nouveau_fbcon_sync(struct fb_info *info) - { -@@ -58,22 +154,36 @@ - struct nouveau_channel *chan = dev_priv->channel; - int ret, i; - -- if (!chan || !chan->accel_done || -+ if (!chan || !chan->accel_done || in_interrupt() || - info->state != FBINFO_STATE_RUNNING || - info->flags & FBINFO_HWACCEL_DISABLED) - return 0; - -- if (RING_SPACE(chan, 4)) { -+ if (!mutex_trylock(&chan->mutex)) -+ return 0; -+ -+ ret = RING_SPACE(chan, 4); -+ if (ret) { -+ mutex_unlock(&chan->mutex); - nouveau_fbcon_gpu_lockup(info); - return 0; - } - -- BEGIN_RING(chan, 0, 0x0104, 1); -- OUT_RING(chan, 0); -- BEGIN_RING(chan, 0, 0x0100, 1); -- OUT_RING(chan, 0); -+ if (dev_priv->card_type >= NV_C0) { -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x010c, 1); -+ OUT_RING (chan, 0); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0100, 1); -+ OUT_RING (chan, 0); -+ } else { -+ BEGIN_RING(chan, 0, 0x0104, 1); -+ OUT_RING (chan, 0); -+ BEGIN_RING(chan, 0, 0x0100, 1); -+ OUT_RING (chan, 0); -+ } -+ - nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy + 3, 0xffffffff); - FIRE_RING(chan); -+ mutex_unlock(&chan->mutex); - - ret = -EBUSY; - for (i = 0; i < 100000; i++) { -@@ -97,9 +207,9 @@ - .owner = THIS_MODULE, - .fb_check_var = drm_fb_helper_check_var, - .fb_set_par = drm_fb_helper_set_par, -- .fb_fillrect = cfb_fillrect, -- .fb_copyarea = cfb_copyarea, -- .fb_imageblit = cfb_imageblit, -+ .fb_fillrect = nouveau_fbcon_fillrect, -+ .fb_copyarea = nouveau_fbcon_copyarea, -+ .fb_imageblit = nouveau_fbcon_imageblit, - .fb_sync = nouveau_fbcon_sync, - .fb_pan_display = drm_fb_helper_pan_display, - .fb_blank = drm_fb_helper_blank, -@@ -108,29 +218,13 @@ - .fb_debug_leave = drm_fb_helper_debug_leave, - }; - --static struct fb_ops nv04_fbcon_ops = { -+static struct fb_ops nouveau_fbcon_sw_ops = { - .owner = THIS_MODULE, - .fb_check_var = drm_fb_helper_check_var, - .fb_set_par = drm_fb_helper_set_par, -- .fb_fillrect = nv04_fbcon_fillrect, -- .fb_copyarea = nv04_fbcon_copyarea, -- .fb_imageblit = nv04_fbcon_imageblit, -- .fb_sync = nouveau_fbcon_sync, -- .fb_pan_display = drm_fb_helper_pan_display, -- .fb_blank = drm_fb_helper_blank, -- .fb_setcmap = drm_fb_helper_setcmap, -- .fb_debug_enter = drm_fb_helper_debug_enter, -- .fb_debug_leave = drm_fb_helper_debug_leave, --}; -- --static struct fb_ops nv50_fbcon_ops = { -- .owner = THIS_MODULE, -- .fb_check_var = drm_fb_helper_check_var, -- .fb_set_par = drm_fb_helper_set_par, -- .fb_fillrect = nv50_fbcon_fillrect, -- .fb_copyarea = nv50_fbcon_copyarea, -- .fb_imageblit = nv50_fbcon_imageblit, -- .fb_sync = nouveau_fbcon_sync, -+ .fb_fillrect = cfb_fillrect, -+ .fb_copyarea = cfb_copyarea, -+ .fb_imageblit = cfb_imageblit, - .fb_pan_display = drm_fb_helper_pan_display, - .fb_blank = drm_fb_helper_blank, - .fb_setcmap = drm_fb_helper_setcmap, -@@ -257,9 +351,9 @@ - FBINFO_HWACCEL_FILLRECT | - FBINFO_HWACCEL_IMAGEBLIT; - info->flags |= FBINFO_CAN_FORCE_OUTPUT; -- info->fbops = &nouveau_fbcon_ops; -- info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset - -- dev_priv->vm_vram_base; -+ info->fbops = &nouveau_fbcon_sw_ops; -+ info->fix.smem_start = dev->mode_config.fb_base + -+ (nvbo->bo.mem.start << PAGE_SHIFT); - info->fix.smem_len = size; - - info->screen_base = nvbo_kmap_obj_iovirtual(nouveau_fb->nvbo); -@@ -285,19 +379,20 @@ - info->pixmap.flags = FB_PIXMAP_SYSTEM; - info->pixmap.scan_align = 1; - -+ mutex_unlock(&dev->struct_mutex); -+ - if (dev_priv->channel && !nouveau_nofbaccel) { -- switch (dev_priv->card_type) { -- case NV_C0: -- break; -- case NV_50: -- nv50_fbcon_accel_init(info); -- info->fbops = &nv50_fbcon_ops; -- break; -- default: -- nv04_fbcon_accel_init(info); -- info->fbops = &nv04_fbcon_ops; -- break; -- }; -+ ret = -ENODEV; -+ if (dev_priv->card_type < NV_50) -+ ret = nv04_fbcon_accel_init(info); -+ else -+ if (dev_priv->card_type < NV_C0) -+ ret = nv50_fbcon_accel_init(info); -+ else -+ ret = nvc0_fbcon_accel_init(info); -+ -+ if (ret == 0) -+ info->fbops = &nouveau_fbcon_ops; - } - - nouveau_fbcon_zfill(dev, nfbdev); -@@ -308,7 +403,6 @@ - nouveau_fb->base.height, - nvbo->bo.offset, nvbo); - -- mutex_unlock(&dev->struct_mutex); - vga_switcheroo_client_fb_set(dev->pdev, info); - return 0; - -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_fbcon.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_fbcon.h ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_fbcon.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_fbcon.h 2011-01-07 14:22:17.000000000 +0100 -@@ -40,15 +40,21 @@ - - void nouveau_fbcon_restore(void); - --void nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); --void nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); --void nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); -+int nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); -+int nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); -+int nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); - int nv04_fbcon_accel_init(struct fb_info *info); --void nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); --void nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); --void nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); -+ -+int nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); -+int nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); -+int nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); - int nv50_fbcon_accel_init(struct fb_info *info); - -+int nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); -+int nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); -+int nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); -+int nvc0_fbcon_accel_init(struct fb_info *info); -+ - void nouveau_fbcon_gpu_lockup(struct fb_info *info); - - int nouveau_fbcon_init(struct drm_device *dev); -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_fence.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_fence.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_fence.c 2011-01-07 14:22:17.000000000 +0100 -@@ -32,7 +32,8 @@ - #include "nouveau_dma.h" - - #define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10) --#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17) -+#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17 && \ -+ nouveau_private(dev)->card_type < NV_C0) - - struct nouveau_fence { - struct nouveau_channel *channel; -@@ -64,6 +65,7 @@ - struct nouveau_fence *fence = - container_of(ref, struct nouveau_fence, refcount); - -+ nouveau_channel_ref(NULL, &fence->channel); - kfree(fence); - } - -@@ -76,14 +78,17 @@ - - spin_lock(&chan->fence.lock); - -- if (USE_REFCNT(dev)) -- sequence = nvchan_rd32(chan, 0x48); -- else -- sequence = atomic_read(&chan->fence.last_sequence_irq); -- -- if (chan->fence.sequence_ack == sequence) -- goto out; -- chan->fence.sequence_ack = sequence; -+ /* Fetch the last sequence if the channel is still up and running */ -+ if (likely(!list_empty(&chan->fence.pending))) { -+ if (USE_REFCNT(dev)) -+ sequence = nvchan_rd32(chan, 0x48); -+ else -+ sequence = atomic_read(&chan->fence.last_sequence_irq); -+ -+ if (chan->fence.sequence_ack == sequence) -+ goto out; -+ chan->fence.sequence_ack = sequence; -+ } - - list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { - sequence = fence->sequence; -@@ -113,13 +118,13 @@ - if (!fence) - return -ENOMEM; - kref_init(&fence->refcount); -- fence->channel = chan; -+ nouveau_channel_ref(chan, &fence->channel); - - if (emit) - ret = nouveau_fence_emit(fence); - - if (ret) -- nouveau_fence_unref((void *)&fence); -+ nouveau_fence_unref(&fence); - *pfence = fence; - return ret; - } -@@ -127,7 +132,7 @@ - struct nouveau_channel * - nouveau_fence_channel(struct nouveau_fence *fence) - { -- return fence ? fence->channel : NULL; -+ return fence ? nouveau_channel_get_unlocked(fence->channel) : NULL; - } - - int -@@ -135,6 +140,7 @@ - { - struct nouveau_channel *chan = fence->channel; - struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; - int ret; - - ret = RING_SPACE(chan, 2); -@@ -155,8 +161,15 @@ - list_add_tail(&fence->entry, &chan->fence.pending); - spin_unlock(&chan->fence.lock); - -- BEGIN_RING(chan, NvSubSw, USE_REFCNT(dev) ? 0x0050 : 0x0150, 1); -- OUT_RING(chan, fence->sequence); -+ if (USE_REFCNT(dev)) { -+ if (dev_priv->card_type < NV_C0) -+ BEGIN_RING(chan, NvSubSw, 0x0050, 1); -+ else -+ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0050, 1); -+ } else { -+ BEGIN_RING(chan, NvSubSw, 0x0150, 1); -+ } -+ OUT_RING (chan, fence->sequence); - FIRE_RING(chan); - - return 0; -@@ -182,7 +195,7 @@ - } - - void --nouveau_fence_unref(void **sync_obj) -+__nouveau_fence_unref(void **sync_obj) - { - struct nouveau_fence *fence = nouveau_fence(*sync_obj); - -@@ -192,7 +205,7 @@ - } - - void * --nouveau_fence_ref(void *sync_obj) -+__nouveau_fence_ref(void *sync_obj) - { - struct nouveau_fence *fence = nouveau_fence(sync_obj); - -@@ -201,7 +214,7 @@ - } - - bool --nouveau_fence_signalled(void *sync_obj, void *sync_arg) -+__nouveau_fence_signalled(void *sync_obj, void *sync_arg) - { - struct nouveau_fence *fence = nouveau_fence(sync_obj); - struct nouveau_channel *chan = fence->channel; -@@ -214,13 +227,14 @@ - } - - int --nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) -+__nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) - { - unsigned long timeout = jiffies + (3 * DRM_HZ); -+ unsigned long sleep_time = jiffies + 1; - int ret = 0; - - while (1) { -- if (nouveau_fence_signalled(sync_obj, sync_arg)) -+ if (__nouveau_fence_signalled(sync_obj, sync_arg)) - break; - - if (time_after_eq(jiffies, timeout)) { -@@ -230,7 +244,7 @@ - - __set_current_state(intr ? TASK_INTERRUPTIBLE - : TASK_UNINTERRUPTIBLE); -- if (lazy) -+ if (lazy && time_after_eq(jiffies, sleep_time)) - schedule_timeout(1); - - if (intr && signal_pending(current)) { -@@ -368,7 +382,7 @@ - - kref_get(&sema->ref); - nouveau_fence_work(fence, semaphore_work, sema); -- nouveau_fence_unref((void *)&fence); -+ nouveau_fence_unref(&fence); - - return 0; - } -@@ -380,33 +394,49 @@ - struct nouveau_channel *chan = nouveau_fence_channel(fence); - struct drm_device *dev = wchan->dev; - struct nouveau_semaphore *sema; -- int ret; -+ int ret = 0; - -- if (likely(!fence || chan == wchan || -- nouveau_fence_signalled(fence, NULL))) -- return 0; -+ if (likely(!chan || chan == wchan || -+ nouveau_fence_signalled(fence))) -+ goto out; - - sema = alloc_semaphore(dev); - if (!sema) { - /* Early card or broken userspace, fall back to - * software sync. */ -- return nouveau_fence_wait(fence, NULL, false, false); -+ ret = nouveau_fence_wait(fence, true, false); -+ goto out; -+ } -+ -+ /* try to take chan's mutex, if we can't take it right away -+ * we have to fallback to software sync to prevent locking -+ * order issues -+ */ -+ if (!mutex_trylock(&chan->mutex)) { -+ ret = nouveau_fence_wait(fence, true, false); -+ goto out_unref; - } - - /* Make wchan wait until it gets signalled */ - ret = emit_semaphore(wchan, NV_SW_SEMAPHORE_ACQUIRE, sema); - if (ret) -- goto out; -+ goto out_unlock; - - /* Signal the semaphore from chan */ - ret = emit_semaphore(chan, NV_SW_SEMAPHORE_RELEASE, sema); --out: -+ -+out_unlock: -+ mutex_unlock(&chan->mutex); -+out_unref: - kref_put(&sema->ref, free_semaphore); -+out: -+ if (chan) -+ nouveau_channel_put_unlocked(&chan); - return ret; - } - - int --nouveau_fence_flush(void *sync_obj, void *sync_arg) -+__nouveau_fence_flush(void *sync_obj, void *sync_arg) - { - return 0; - } -@@ -420,30 +450,27 @@ - int ret; - - /* Create an NV_SW object for various sync purposes */ -- ret = nouveau_gpuobj_sw_new(chan, NV_SW, &obj); -- if (ret) -- return ret; -- -- ret = nouveau_ramht_insert(chan, NvSw, obj); -- nouveau_gpuobj_ref(NULL, &obj); -+ ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW); - if (ret) - return ret; - -- ret = RING_SPACE(chan, 2); -- if (ret) -- return ret; -- BEGIN_RING(chan, NvSubSw, 0, 1); -- OUT_RING(chan, NvSw); -+ /* we leave subchannel empty for nvc0 */ -+ if (dev_priv->card_type < NV_C0) { -+ ret = RING_SPACE(chan, 2); -+ if (ret) -+ return ret; -+ BEGIN_RING(chan, NvSubSw, 0, 1); -+ OUT_RING(chan, NvSw); -+ } - - /* Create a DMA object for the shared cross-channel sync area. */ - if (USE_SEMA(dev)) { -- struct drm_mm_node *mem = dev_priv->fence.bo->bo.mem.mm_node; -+ struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem; - - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - mem->start << PAGE_SHIFT, -- mem->size << PAGE_SHIFT, -- NV_DMA_ACCESS_RW, -- NV_DMA_TARGET_VIDMEM, &obj); -+ mem->size, NV_MEM_ACCESS_RW, -+ NV_MEM_TARGET_VRAM, &obj); - if (ret) - return ret; - -@@ -473,6 +500,8 @@ - { - 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); -@@ -482,6 +511,8 @@ - - kref_put(&fence->refcount, nouveau_fence_del); - } -+ -+ spin_unlock(&chan->fence.lock); - } - - int -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_gem.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_gem.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_gem.c 2011-01-07 14:22:17.000000000 +0100 -@@ -48,9 +48,6 @@ - return; - nvbo->gem = NULL; - -- if (unlikely(nvbo->cpu_filp)) -- ttm_bo_synccpu_write_release(bo); -- - if (unlikely(nvbo->pin_refcnt)) { - nvbo->pin_refcnt = 1; - nouveau_bo_unpin(nvbo); -@@ -106,32 +103,6 @@ - return 0; - } - --static bool --nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- -- if (dev_priv->card_type >= NV_50) { -- switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) { -- case 0x0000: -- case 0x1800: -- case 0x2800: -- case 0x4800: -- case 0x7000: -- case 0x7400: -- case 0x7a00: -- case 0xe000: -- return true; -- } -- } else { -- if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK)) -- return true; -- } -- -- NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags); -- return false; --} -- - int - nouveau_gem_ioctl_new(struct drm_device *dev, void *data, - struct drm_file *file_priv) -@@ -146,11 +117,6 @@ - if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) - dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; - -- if (req->channel_hint) { -- NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel_hint, -- file_priv, chan); -- } -- - if (req->info.domain & NOUVEAU_GEM_DOMAIN_VRAM) - flags |= TTM_PL_FLAG_VRAM; - if (req->info.domain & NOUVEAU_GEM_DOMAIN_GART) -@@ -158,13 +124,23 @@ - if (!flags || req->info.domain & NOUVEAU_GEM_DOMAIN_CPU) - flags |= TTM_PL_FLAG_SYSTEM; - -- if (!nouveau_gem_tile_flags_valid(dev, req->info.tile_flags)) -+ if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) { -+ NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); - return -EINVAL; -+ } -+ -+ if (req->channel_hint) { -+ chan = nouveau_channel_get(dev, file_priv, req->channel_hint); -+ if (IS_ERR(chan)) -+ return PTR_ERR(chan); -+ } - - ret = nouveau_gem_new(dev, chan, req->info.size, req->align, flags, - req->info.tile_mode, req->info.tile_flags, false, - (req->info.domain & NOUVEAU_GEM_DOMAIN_MAPPABLE), - &nvbo); -+ if (chan) -+ nouveau_channel_put(&chan); - if (ret) - return ret; - -@@ -231,15 +207,8 @@ - - list_for_each_safe(entry, tmp, list) { - nvbo = list_entry(entry, struct nouveau_bo, entry); -- if (likely(fence)) { -- struct nouveau_fence *prev_fence; - -- spin_lock(&nvbo->bo.lock); -- prev_fence = nvbo->bo.sync_obj; -- nvbo->bo.sync_obj = nouveau_fence_ref(fence); -- spin_unlock(&nvbo->bo.lock); -- nouveau_fence_unref((void *)&prev_fence); -- } -+ nouveau_bo_fence(nvbo, fence); - - if (unlikely(nvbo->validate_mapped)) { - ttm_bo_kunmap(&nvbo->kmap); -@@ -299,14 +268,15 @@ - return -EINVAL; - } - -- ret = ttm_bo_reserve(&nvbo->bo, false, false, true, sequence); -+ ret = ttm_bo_reserve(&nvbo->bo, true, false, true, sequence); - if (ret) { - validate_fini(op, NULL); -- if (ret == -EAGAIN) -- ret = ttm_bo_wait_unreserved(&nvbo->bo, false); -+ if (unlikely(ret == -EAGAIN)) -+ ret = ttm_bo_wait_unreserved(&nvbo->bo, true); - drm_gem_object_unreference_unlocked(gem); -- if (ret) { -- NV_ERROR(dev, "fail reserve\n"); -+ if (unlikely(ret)) { -+ if (ret != -ERESTARTSYS) -+ NV_ERROR(dev, "fail reserve\n"); - return ret; - } - goto retry; -@@ -331,25 +301,6 @@ - validate_fini(op, NULL); - return -EINVAL; - } -- -- if (unlikely(atomic_read(&nvbo->bo.cpu_writers) > 0)) { -- validate_fini(op, NULL); -- -- if (nvbo->cpu_filp == file_priv) { -- NV_ERROR(dev, "bo %p mapped by process trying " -- "to validate it!\n", nvbo); -- return -EINVAL; -- } -- -- mutex_unlock(&drm_global_mutex); -- ret = ttm_bo_wait_cpu(&nvbo->bo, false); -- mutex_lock(&drm_global_mutex); -- if (ret) { -- NV_ERROR(dev, "fail wait_cpu\n"); -- return ret; -- } -- goto retry; -- } - } - - return 0; -@@ -383,11 +334,11 @@ - } - - nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan; -- ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, -- false, false, false); -+ ret = nouveau_bo_validate(nvbo, true, false, false); - nvbo->channel = NULL; - if (unlikely(ret)) { -- NV_ERROR(dev, "fail ttm_validate\n"); -+ if (ret != -ERESTARTSYS) -+ NV_ERROR(dev, "fail ttm_validate\n"); - return ret; - } - -@@ -439,13 +390,15 @@ - - ret = validate_init(chan, file_priv, pbbo, nr_buffers, op); - if (unlikely(ret)) { -- NV_ERROR(dev, "validate_init\n"); -+ if (ret != -ERESTARTSYS) -+ NV_ERROR(dev, "validate_init\n"); - return ret; - } - - ret = validate_list(chan, &op->vram_list, pbbo, user_buffers); - if (unlikely(ret < 0)) { -- NV_ERROR(dev, "validate vram_list\n"); -+ if (ret != -ERESTARTSYS) -+ NV_ERROR(dev, "validate vram_list\n"); - validate_fini(op, NULL); - return ret; - } -@@ -453,7 +406,8 @@ - - ret = validate_list(chan, &op->gart_list, pbbo, user_buffers); - if (unlikely(ret < 0)) { -- NV_ERROR(dev, "validate gart_list\n"); -+ if (ret != -ERESTARTSYS) -+ NV_ERROR(dev, "validate gart_list\n"); - validate_fini(op, NULL); - return ret; - } -@@ -461,7 +415,8 @@ - - ret = validate_list(chan, &op->both_list, pbbo, user_buffers); - if (unlikely(ret < 0)) { -- NV_ERROR(dev, "validate both_list\n"); -+ if (ret != -ERESTARTSYS) -+ NV_ERROR(dev, "validate both_list\n"); - validate_fini(op, NULL); - return ret; - } -@@ -557,9 +512,9 @@ - data |= r->vor; - } - -- spin_lock(&nvbo->bo.lock); -+ spin_lock(&nvbo->bo.bdev->fence_lock); - ret = ttm_bo_wait(&nvbo->bo, false, false, false); -- spin_unlock(&nvbo->bo.lock); -+ spin_unlock(&nvbo->bo.bdev->fence_lock); - if (ret) { - NV_ERROR(dev, "reloc wait_idle failed: %d\n", ret); - break; -@@ -585,7 +540,9 @@ - struct nouveau_fence *fence = NULL; - int i, j, ret = 0, do_reloc = 0; - -- NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan); -+ chan = nouveau_channel_get(dev, file_priv, req->channel); -+ if (IS_ERR(chan)) -+ return PTR_ERR(chan); - - req->vram_available = dev_priv->fb_aper_free; - req->gart_available = dev_priv->gart_info.aper_free; -@@ -595,28 +552,34 @@ - if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) { - NV_ERROR(dev, "pushbuf push count exceeds limit: %d max %d\n", - req->nr_push, NOUVEAU_GEM_MAX_PUSH); -+ nouveau_channel_put(&chan); - return -EINVAL; - } - - if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) { - NV_ERROR(dev, "pushbuf bo count exceeds limit: %d max %d\n", - req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS); -+ nouveau_channel_put(&chan); - return -EINVAL; - } - - if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) { - NV_ERROR(dev, "pushbuf reloc count exceeds limit: %d max %d\n", - req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS); -+ nouveau_channel_put(&chan); - return -EINVAL; - } - - push = u_memcpya(req->push, req->nr_push, sizeof(*push)); -- if (IS_ERR(push)) -+ if (IS_ERR(push)) { -+ nouveau_channel_put(&chan); - return PTR_ERR(push); -+ } - - bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo)); - if (IS_ERR(bo)) { - kfree(push); -+ nouveau_channel_put(&chan); - return PTR_ERR(bo); - } - -@@ -639,7 +602,8 @@ - ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers, - req->nr_buffers, &op, &do_reloc); - if (ret) { -- NV_ERROR(dev, "validate: %d\n", ret); -+ if (ret != -ERESTARTSYS) -+ NV_ERROR(dev, "validate: %d\n", ret); - goto out; - } - -@@ -732,7 +696,7 @@ - - out: - validate_fini(&op, fence); -- nouveau_fence_unref((void**)&fence); -+ nouveau_fence_unref(&fence); - kfree(bo); - kfree(push); - -@@ -750,6 +714,7 @@ - req->suffix1 = 0x00000000; - } - -+ nouveau_channel_put(&chan); - return ret; - } - -@@ -781,26 +746,9 @@ - return -ENOENT; - nvbo = nouveau_gem_object(gem); - -- if (nvbo->cpu_filp) { -- if (nvbo->cpu_filp == file_priv) -- goto out; -- -- ret = ttm_bo_wait_cpu(&nvbo->bo, no_wait); -- if (ret) -- goto out; -- } -- -- if (req->flags & NOUVEAU_GEM_CPU_PREP_NOBLOCK) { -- spin_lock(&nvbo->bo.lock); -- ret = ttm_bo_wait(&nvbo->bo, false, false, no_wait); -- spin_unlock(&nvbo->bo.lock); -- } else { -- ret = ttm_bo_synccpu_write_grab(&nvbo->bo, no_wait); -- if (ret == 0) -- nvbo->cpu_filp = file_priv; -- } -- --out: -+ spin_lock(&nvbo->bo.bdev->fence_lock); -+ ret = ttm_bo_wait(&nvbo->bo, true, true, no_wait); -+ spin_unlock(&nvbo->bo.bdev->fence_lock); - drm_gem_object_unreference_unlocked(gem); - return ret; - } -@@ -809,26 +757,7 @@ - nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data, - struct drm_file *file_priv) - { -- struct drm_nouveau_gem_cpu_prep *req = data; -- struct drm_gem_object *gem; -- struct nouveau_bo *nvbo; -- int ret = -EINVAL; -- -- gem = drm_gem_object_lookup(dev, file_priv, req->handle); -- if (!gem) -- return -ENOENT; -- nvbo = nouveau_gem_object(gem); -- -- if (nvbo->cpu_filp != file_priv) -- goto out; -- nvbo->cpu_filp = NULL; -- -- ttm_bo_synccpu_write_release(&nvbo->bo); -- ret = 0; -- --out: -- drm_gem_object_unreference_unlocked(gem); -- return ret; -+ return 0; - } - - int -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_hw.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_hw.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_hw.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_hw.c 2011-01-07 14:22:17.000000000 +0100 -@@ -953,7 +953,7 @@ - NVWriteCRTC(dev, head, NV_PCRTC_850, regp->crtc_850); - - reg900 = NVReadRAMDAC(dev, head, NV_PRAMDAC_900); -- if (regp->crtc_cfg == NV_PCRTC_CONFIG_START_ADDRESS_HSYNC) -+ if (regp->crtc_cfg == NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC) - NVWriteRAMDAC(dev, head, NV_PRAMDAC_900, reg900 | 0x10000); - else - NVWriteRAMDAC(dev, head, NV_PRAMDAC_900, reg900 & ~0x10000); -@@ -999,8 +999,8 @@ - if (dev_priv->card_type == NV_10) { - /* Not waiting for vertical retrace before modifying - CRE_53/CRE_54 causes lockups. */ -- nouveau_wait_until(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8); -- nouveau_wait_until(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0); -+ nouveau_wait_eq(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8); -+ nouveau_wait_eq(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0); - } - - wr_cio_state(dev, head, regp, NV_CIO_CRE_53); -@@ -1017,8 +1017,9 @@ - - NVWriteCRTC(dev, head, NV_PCRTC_START, regp->fb_start); - -- /* Setting 1 on this value gives you interrupts for every vblank period. */ -- NVWriteCRTC(dev, head, NV_PCRTC_INTR_EN_0, 0); -+ /* Enable vblank interrupts. */ -+ NVWriteCRTC(dev, head, NV_PCRTC_INTR_EN_0, -+ (dev->vblank_enabled[head] ? 1 : 0)); - NVWriteCRTC(dev, head, NV_PCRTC_INTR_0, NV_PCRTC_INTR_0_VBLANK); - } - -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_irq.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_irq.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_irq.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_irq.c 2011-01-07 14:22:17.000000000 +0100 -@@ -36,18 +36,7 @@ - #include "nouveau_drv.h" - #include "nouveau_reg.h" - #include "nouveau_ramht.h" --#include -- --/* needed for hotplug irq */ --#include "nouveau_connector.h" --#include "nv50_display.h" -- --static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); -- --static int nouveau_ratelimit(void) --{ -- return __ratelimit(&nouveau_ratelimit_state); --} -+#include "nouveau_util.h" - - void - nouveau_irq_preinstall(struct drm_device *dev) -@@ -57,19 +46,19 @@ - /* Master disable */ - nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); - -- if (dev_priv->card_type >= NV_50) { -- INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); -- INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh); -- spin_lock_init(&dev_priv->hpd_state.lock); -- INIT_LIST_HEAD(&dev_priv->vbl_waiting); -- } -+ INIT_LIST_HEAD(&dev_priv->vbl_waiting); - } - - int - nouveau_irq_postinstall(struct drm_device *dev) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ - /* Master enable */ - nv_wr32(dev, NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE); -+ if (dev_priv->msi_enabled) -+ nv_wr08(dev, 0x00088068, 0xff); -+ - return 0; - } - -@@ -80,1178 +69,83 @@ - nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); - } - --static int --nouveau_call_method(struct nouveau_channel *chan, int class, int mthd, int data) --{ -- struct drm_nouveau_private *dev_priv = chan->dev->dev_private; -- struct nouveau_pgraph_object_method *grm; -- struct nouveau_pgraph_object_class *grc; -- -- grc = dev_priv->engine.graph.grclass; -- while (grc->id) { -- if (grc->id == class) -- break; -- grc++; -- } -- -- if (grc->id != class || !grc->methods) -- return -ENOENT; -- -- grm = grc->methods; -- while (grm->id) { -- if (grm->id == mthd) -- return grm->exec(chan, class, mthd, data); -- grm++; -- } -- -- return -ENOENT; --} -- --static bool --nouveau_fifo_swmthd(struct nouveau_channel *chan, uint32_t addr, uint32_t data) --{ -- struct drm_device *dev = chan->dev; -- const int subc = (addr >> 13) & 0x7; -- const int mthd = addr & 0x1ffc; -- -- if (mthd == 0x0000) { -- struct nouveau_gpuobj *gpuobj; -- -- gpuobj = nouveau_ramht_find(chan, data); -- if (!gpuobj) -- return false; -- -- if (gpuobj->engine != NVOBJ_ENGINE_SW) -- return false; -- -- chan->sw_subchannel[subc] = gpuobj->class; -- nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_rd32(dev, -- NV04_PFIFO_CACHE1_ENGINE) & ~(0xf << subc * 4)); -- return true; -- } -- -- /* hw object */ -- if (nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE) & (1 << (subc*4))) -- return false; -- -- if (nouveau_call_method(chan, chan->sw_subchannel[subc], mthd, data)) -- return false; -- -- return true; --} -- --static void --nouveau_fifo_irq_handler(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_engine *engine = &dev_priv->engine; -- uint32_t status, reassign; -- int cnt = 0; -- -- reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1; -- while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) { -- struct nouveau_channel *chan = NULL; -- uint32_t chid, get; -- -- nv_wr32(dev, NV03_PFIFO_CACHES, 0); -- -- chid = engine->fifo.channel_id(dev); -- if (chid >= 0 && chid < engine->fifo.channels) -- chan = dev_priv->fifos[chid]; -- get = nv_rd32(dev, NV03_PFIFO_CACHE1_GET); -- -- if (status & NV_PFIFO_INTR_CACHE_ERROR) { -- uint32_t mthd, data; -- int ptr; -- -- /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before -- * wrapping on my G80 chips, but CACHE1 isn't big -- * enough for this much data.. Tests show that it -- * wraps around to the start at GET=0x800.. No clue -- * as to why.. -- */ -- ptr = (get & 0x7ff) >> 2; -- -- if (dev_priv->card_type < NV_40) { -- mthd = nv_rd32(dev, -- NV04_PFIFO_CACHE1_METHOD(ptr)); -- data = nv_rd32(dev, -- NV04_PFIFO_CACHE1_DATA(ptr)); -- } else { -- mthd = nv_rd32(dev, -- NV40_PFIFO_CACHE1_METHOD(ptr)); -- data = nv_rd32(dev, -- NV40_PFIFO_CACHE1_DATA(ptr)); -- } -- -- if (!chan || !nouveau_fifo_swmthd(chan, mthd, data)) { -- NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d " -- "Mthd 0x%04x Data 0x%08x\n", -- chid, (mthd >> 13) & 7, mthd & 0x1ffc, -- data); -- } -- -- nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0); -- nv_wr32(dev, NV03_PFIFO_INTR_0, -- NV_PFIFO_INTR_CACHE_ERROR); -- -- nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, -- nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) & ~1); -- nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); -- nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, -- nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) | 1); -- nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); -- -- nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, -- nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); -- nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); -- -- status &= ~NV_PFIFO_INTR_CACHE_ERROR; -- } -- -- if (status & NV_PFIFO_INTR_DMA_PUSHER) { -- u32 dma_get = nv_rd32(dev, 0x003244); -- u32 dma_put = nv_rd32(dev, 0x003240); -- u32 push = nv_rd32(dev, 0x003220); -- u32 state = nv_rd32(dev, 0x003228); -- -- if (dev_priv->card_type == NV_50) { -- u32 ho_get = nv_rd32(dev, 0x003328); -- u32 ho_put = nv_rd32(dev, 0x003320); -- u32 ib_get = nv_rd32(dev, 0x003334); -- u32 ib_put = nv_rd32(dev, 0x003330); -- -- if (nouveau_ratelimit()) -- NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x " -- "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " -- "State 0x%08x Push 0x%08x\n", -- chid, ho_get, dma_get, ho_put, -- dma_put, ib_get, ib_put, state, -- push); -- -- /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ -- nv_wr32(dev, 0x003364, 0x00000000); -- if (dma_get != dma_put || ho_get != ho_put) { -- nv_wr32(dev, 0x003244, dma_put); -- nv_wr32(dev, 0x003328, ho_put); -- } else -- if (ib_get != ib_put) { -- nv_wr32(dev, 0x003334, ib_put); -- } -- } else { -- NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " -- "Put 0x%08x State 0x%08x Push 0x%08x\n", -- chid, dma_get, dma_put, state, push); -- -- if (dma_get != dma_put) -- nv_wr32(dev, 0x003244, dma_put); -- } -- -- nv_wr32(dev, 0x003228, 0x00000000); -- nv_wr32(dev, 0x003220, 0x00000001); -- nv_wr32(dev, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); -- status &= ~NV_PFIFO_INTR_DMA_PUSHER; -- } -- -- if (status & NV_PFIFO_INTR_SEMAPHORE) { -- uint32_t sem; -- -- status &= ~NV_PFIFO_INTR_SEMAPHORE; -- nv_wr32(dev, NV03_PFIFO_INTR_0, -- NV_PFIFO_INTR_SEMAPHORE); -- -- sem = nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE); -- nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1); -- -- nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); -- nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); -- } -- -- if (dev_priv->card_type == NV_50) { -- if (status & 0x00000010) { -- nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT"); -- status &= ~0x00000010; -- nv_wr32(dev, 0x002100, 0x00000010); -- } -- } -- -- if (status) { -- if (nouveau_ratelimit()) -- NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", -- status, chid); -- nv_wr32(dev, NV03_PFIFO_INTR_0, status); -- status = 0; -- } -- -- nv_wr32(dev, NV03_PFIFO_CACHES, reassign); -- } -- -- if (status) { -- NV_INFO(dev, "PFIFO still angry after %d spins, halt\n", cnt); -- nv_wr32(dev, 0x2140, 0); -- nv_wr32(dev, 0x140, 0); -- } -- -- nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING); --} -- --struct nouveau_bitfield_names { -- uint32_t mask; -- const char *name; --}; -- --static struct nouveau_bitfield_names nstatus_names[] = --{ -- { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, -- { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, -- { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, -- { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" } --}; -- --static struct nouveau_bitfield_names nstatus_names_nv10[] = --{ -- { NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, -- { NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, -- { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, -- { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" } --}; -- --static struct nouveau_bitfield_names nsource_names[] = --{ -- { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" }, -- { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" }, -- { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" }, -- { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION, "RANGE_EXCEPTION" }, -- { NV03_PGRAPH_NSOURCE_LIMIT_COLOR, "LIMIT_COLOR" }, -- { NV03_PGRAPH_NSOURCE_LIMIT_ZETA, "LIMIT_ZETA" }, -- { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD, "ILLEGAL_MTHD" }, -- { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION, "DMA_R_PROTECTION" }, -- { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION, "DMA_W_PROTECTION" }, -- { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION, "FORMAT_EXCEPTION" }, -- { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION, "PATCH_EXCEPTION" }, -- { NV03_PGRAPH_NSOURCE_STATE_INVALID, "STATE_INVALID" }, -- { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY, "DOUBLE_NOTIFY" }, -- { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE, "NOTIFY_IN_USE" }, -- { NV03_PGRAPH_NSOURCE_METHOD_CNT, "METHOD_CNT" }, -- { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION, "BFR_NOTIFICATION" }, -- { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" }, -- { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A, "DMA_WIDTH_A" }, -- { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B, "DMA_WIDTH_B" }, --}; -- --static void --nouveau_print_bitfield_names_(uint32_t value, -- const struct nouveau_bitfield_names *namelist, -- const int namelist_len) --{ -- /* -- * Caller must have already printed the KERN_* log level for us. -- * Also the caller is responsible for adding the newline. -- */ -- int i; -- for (i = 0; i < namelist_len; ++i) { -- uint32_t mask = namelist[i].mask; -- if (value & mask) { -- printk(" %s", namelist[i].name); -- value &= ~mask; -- } -- } -- if (value) -- printk(" (unknown bits 0x%08x)", value); --} --#define nouveau_print_bitfield_names(val, namelist) \ -- nouveau_print_bitfield_names_((val), (namelist), ARRAY_SIZE(namelist)) -- --struct nouveau_enum_names { -- uint32_t value; -- const char *name; --}; -- --static void --nouveau_print_enum_names_(uint32_t value, -- const struct nouveau_enum_names *namelist, -- const int namelist_len) --{ -- /* -- * Caller must have already printed the KERN_* log level for us. -- * Also the caller is responsible for adding the newline. -- */ -- int i; -- for (i = 0; i < namelist_len; ++i) { -- if (value == namelist[i].value) { -- printk("%s", namelist[i].name); -- return; -- } -- } -- printk("unknown value 0x%08x", value); --} --#define nouveau_print_enum_names(val, namelist) \ -- nouveau_print_enum_names_((val), (namelist), ARRAY_SIZE(namelist)) -- --static int --nouveau_graph_chid_from_grctx(struct drm_device *dev) -+irqreturn_t -+nouveau_irq_handler(DRM_IRQ_ARGS) - { -+ struct drm_device *dev = (struct drm_device *)arg; - struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t inst; -+ unsigned long flags; -+ u32 stat; - int i; - -- if (dev_priv->card_type < NV_40) -- return dev_priv->engine.fifo.channels; -- else -- if (dev_priv->card_type < NV_50) { -- inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 4; -- -- for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- struct nouveau_channel *chan = dev_priv->fifos[i]; -- -- if (!chan || !chan->ramin_grctx) -- continue; -- -- if (inst == chan->ramin_grctx->pinst) -- break; -- } -- } else { -- inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 12; -- -- for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- struct nouveau_channel *chan = dev_priv->fifos[i]; -- -- if (!chan || !chan->ramin) -- continue; -- -- if (inst == chan->ramin->vinst) -- break; -- } -- } -- -- -- return i; --} -- --static int --nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_engine *engine = &dev_priv->engine; -- int channel; -- -- if (dev_priv->card_type < NV_10) -- channel = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0xf; -- else -- if (dev_priv->card_type < NV_40) -- channel = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; -- else -- channel = nouveau_graph_chid_from_grctx(dev); -- -- if (channel >= engine->fifo.channels || !dev_priv->fifos[channel]) { -- NV_ERROR(dev, "AIII, invalid/inactive channel id %d\n", channel); -- return -EINVAL; -- } -- -- *channel_ret = channel; -- return 0; --} -- --struct nouveau_pgraph_trap { -- int channel; -- int class; -- int subc, mthd, size; -- uint32_t data, data2; -- uint32_t nsource, nstatus; --}; -- --static void --nouveau_graph_trap_info(struct drm_device *dev, -- struct nouveau_pgraph_trap *trap) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t address; -- -- trap->nsource = trap->nstatus = 0; -- if (dev_priv->card_type < NV_50) { -- trap->nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); -- trap->nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); -- } -- -- if (nouveau_graph_trapped_channel(dev, &trap->channel)) -- trap->channel = -1; -- address = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); -- -- trap->mthd = address & 0x1FFC; -- trap->data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); -- if (dev_priv->card_type < NV_10) { -- trap->subc = (address >> 13) & 0x7; -- } else { -- trap->subc = (address >> 16) & 0x7; -- trap->data2 = nv_rd32(dev, NV10_PGRAPH_TRAPPED_DATA_HIGH); -- } -- -- if (dev_priv->card_type < NV_10) -- trap->class = nv_rd32(dev, 0x400180 + trap->subc*4) & 0xFF; -- else if (dev_priv->card_type < NV_40) -- trap->class = nv_rd32(dev, 0x400160 + trap->subc*4) & 0xFFF; -- else if (dev_priv->card_type < NV_50) -- trap->class = nv_rd32(dev, 0x400160 + trap->subc*4) & 0xFFFF; -- else -- trap->class = nv_rd32(dev, 0x400814); --} -- --static void --nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id, -- struct nouveau_pgraph_trap *trap) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t nsource = trap->nsource, nstatus = trap->nstatus; -- -- if (dev_priv->card_type < NV_50) { -- NV_INFO(dev, "%s - nSource:", id); -- nouveau_print_bitfield_names(nsource, nsource_names); -- printk(", nStatus:"); -- if (dev_priv->card_type < NV_10) -- nouveau_print_bitfield_names(nstatus, nstatus_names); -- else -- nouveau_print_bitfield_names(nstatus, nstatus_names_nv10); -- printk("\n"); -- } -- -- NV_INFO(dev, "%s - Ch %d/%d Class 0x%04x Mthd 0x%04x " -- "Data 0x%08x:0x%08x\n", -- id, trap->channel, trap->subc, -- trap->class, trap->mthd, -- trap->data2, trap->data); --} -- --static int --nouveau_pgraph_intr_swmthd(struct drm_device *dev, -- struct nouveau_pgraph_trap *trap) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- -- if (trap->channel < 0 || -- trap->channel >= dev_priv->engine.fifo.channels || -- !dev_priv->fifos[trap->channel]) -- return -ENODEV; -- -- return nouveau_call_method(dev_priv->fifos[trap->channel], -- trap->class, trap->mthd, trap->data); --} -- --static inline void --nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource) --{ -- struct nouveau_pgraph_trap trap; -- int unhandled = 0; -+ stat = nv_rd32(dev, NV03_PMC_INTR_0); -+ if (!stat) -+ return IRQ_NONE; - -- nouveau_graph_trap_info(dev, &trap); -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ for (i = 0; i < 32 && stat; i++) { -+ if (!(stat & (1 << i)) || !dev_priv->irq_handler[i]) -+ continue; - -- if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { -- if (nouveau_pgraph_intr_swmthd(dev, &trap)) -- unhandled = 1; -- } else { -- unhandled = 1; -+ dev_priv->irq_handler[i](dev); -+ stat &= ~(1 << i); - } - -- if (unhandled) -- nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap); --} -- -- --static inline void --nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource) --{ -- struct nouveau_pgraph_trap trap; -- int unhandled = 0; -- -- nouveau_graph_trap_info(dev, &trap); -- trap.nsource = nsource; -- -- if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { -- if (nouveau_pgraph_intr_swmthd(dev, &trap)) -- unhandled = 1; -- } else if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) { -- uint32_t v = nv_rd32(dev, 0x402000); -- nv_wr32(dev, 0x402000, v); -- -- /* dump the error anyway for now: it's useful for -- Gallium development */ -- unhandled = 1; -- } else { -- unhandled = 1; -- } -+ if (dev_priv->msi_enabled) -+ nv_wr08(dev, 0x00088068, 0xff); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - -- if (unhandled && nouveau_ratelimit()) -- nouveau_graph_dump_trap_info(dev, "PGRAPH_ERROR", &trap); -+ if (stat && nouveau_ratelimit()) -+ NV_ERROR(dev, "PMC - unhandled INTR 0x%08x\n", stat); -+ return IRQ_HANDLED; - } - --static inline void --nouveau_pgraph_intr_context_switch(struct drm_device *dev) -+int -+nouveau_irq_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_engine *engine = &dev_priv->engine; -- uint32_t chid; -- -- chid = engine->fifo.channel_id(dev); -- NV_DEBUG(dev, "PGRAPH context switch interrupt channel %x\n", chid); -- -- switch (dev_priv->card_type) { -- case NV_04: -- nv04_graph_context_switch(dev); -- break; -- case NV_10: -- nv10_graph_context_switch(dev); -- break; -- default: -- NV_ERROR(dev, "Context switch not implemented\n"); -- break; -- } --} -- --static void --nouveau_pgraph_irq_handler(struct drm_device *dev) --{ -- uint32_t status; -- -- while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) { -- uint32_t nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); -- -- if (status & NV_PGRAPH_INTR_NOTIFY) { -- nouveau_pgraph_intr_notify(dev, nsource); -- -- status &= ~NV_PGRAPH_INTR_NOTIFY; -- nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY); -- } -- -- if (status & NV_PGRAPH_INTR_ERROR) { -- nouveau_pgraph_intr_error(dev, nsource); -- -- status &= ~NV_PGRAPH_INTR_ERROR; -- nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR); -- } -- -- if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) { -- status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; -- nv_wr32(dev, NV03_PGRAPH_INTR, -- NV_PGRAPH_INTR_CONTEXT_SWITCH); -+ int ret; - -- nouveau_pgraph_intr_context_switch(dev); -+ if (nouveau_msi != 0 && dev_priv->card_type >= NV_50) { -+ ret = pci_enable_msi(dev->pdev); -+ if (ret == 0) { -+ NV_INFO(dev, "enabled MSI\n"); -+ dev_priv->msi_enabled = true; - } -- -- if (status) { -- NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n", status); -- nv_wr32(dev, NV03_PGRAPH_INTR, status); -- } -- -- if ((nv_rd32(dev, NV04_PGRAPH_FIFO) & (1 << 0)) == 0) -- nv_wr32(dev, NV04_PGRAPH_FIFO, 1); - } - -- nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); -+ return drm_irq_install(dev); - } - --static struct nouveau_enum_names nv50_mp_exec_error_names[] = --{ -- { 3, "STACK_UNDERFLOW" }, -- { 4, "QUADON_ACTIVE" }, -- { 8, "TIMEOUT" }, -- { 0x10, "INVALID_OPCODE" }, -- { 0x40, "BREAKPOINT" }, --}; -- --static void --nv50_pgraph_mp_trap(struct drm_device *dev, int tpid, int display) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t units = nv_rd32(dev, 0x1540); -- uint32_t addr, mp10, status, pc, oplow, ophigh; -- int i; -- int mps = 0; -- for (i = 0; i < 4; i++) { -- if (!(units & 1 << (i+24))) -- continue; -- if (dev_priv->chipset < 0xa0) -- addr = 0x408200 + (tpid << 12) + (i << 7); -- else -- addr = 0x408100 + (tpid << 11) + (i << 7); -- mp10 = nv_rd32(dev, addr + 0x10); -- status = nv_rd32(dev, addr + 0x14); -- if (!status) -- continue; -- if (display) { -- nv_rd32(dev, addr + 0x20); -- pc = nv_rd32(dev, addr + 0x24); -- oplow = nv_rd32(dev, addr + 0x70); -- ophigh= nv_rd32(dev, addr + 0x74); -- NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - " -- "TP %d MP %d: ", tpid, i); -- nouveau_print_enum_names(status, -- nv50_mp_exec_error_names); -- printk(" at %06x warp %d, opcode %08x %08x\n", -- pc&0xffffff, pc >> 24, -- oplow, ophigh); -- } -- nv_wr32(dev, addr + 0x10, mp10); -- nv_wr32(dev, addr + 0x14, 0); -- mps++; -- } -- if (!mps && display) -- NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - TP %d: " -- "No MPs claiming errors?\n", tpid); --} -- --static void --nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, -- uint32_t ustatus_new, int display, const char *name) -+void -+nouveau_irq_fini(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- int tps = 0; -- uint32_t units = nv_rd32(dev, 0x1540); -- int i, r; -- uint32_t ustatus_addr, ustatus; -- for (i = 0; i < 16; i++) { -- if (!(units & (1 << i))) -- continue; -- if (dev_priv->chipset < 0xa0) -- ustatus_addr = ustatus_old + (i << 12); -- else -- ustatus_addr = ustatus_new + (i << 11); -- ustatus = nv_rd32(dev, ustatus_addr) & 0x7fffffff; -- if (!ustatus) -- continue; -- tps++; -- switch (type) { -- case 6: /* texture error... unknown for now */ -- nv50_fb_vm_trap(dev, display, name); -- if (display) { -- NV_ERROR(dev, "magic set %d:\n", i); -- for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) -- NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, -- nv_rd32(dev, r)); -- } -- break; -- case 7: /* MP error */ -- if (ustatus & 0x00010000) { -- nv50_pgraph_mp_trap(dev, i, display); -- ustatus &= ~0x00010000; -- } -- break; -- case 8: /* TPDMA error */ -- { -- uint32_t e0c = nv_rd32(dev, ustatus_addr + 4); -- uint32_t e10 = nv_rd32(dev, ustatus_addr + 8); -- uint32_t e14 = nv_rd32(dev, ustatus_addr + 0xc); -- uint32_t e18 = nv_rd32(dev, ustatus_addr + 0x10); -- uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); -- uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); -- uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); -- nv50_fb_vm_trap(dev, display, name); -- /* 2d engine destination */ -- if (ustatus & 0x00000010) { -- if (display) { -- NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n", -- i, e14, e10); -- NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", -- i, e0c, e18, e1c, e20, e24); -- } -- ustatus &= ~0x00000010; -- } -- /* Render target */ -- if (ustatus & 0x00000040) { -- if (display) { -- NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n", -- i, e14, e10); -- NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", -- i, e0c, e18, e1c, e20, e24); -- } -- ustatus &= ~0x00000040; -- } -- /* CUDA memory: l[], g[] or stack. */ -- if (ustatus & 0x00000080) { -- if (display) { -- if (e18 & 0x80000000) { -- /* g[] read fault? */ -- NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n", -- i, e14, e10 | ((e18 >> 24) & 0x1f)); -- e18 &= ~0x1f000000; -- } else if (e18 & 0xc) { -- /* g[] write fault? */ -- NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n", -- i, e14, e10 | ((e18 >> 7) & 0x1f)); -- e18 &= ~0x00000f80; -- } else { -- NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n", -- i, e14, e10); -- } -- NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", -- i, e0c, e18, e1c, e20, e24); -- } -- ustatus &= ~0x00000080; -- } -- } -- break; -- } -- if (ustatus) { -- if (display) -- NV_INFO(dev, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus); -- } -- nv_wr32(dev, ustatus_addr, 0xc0000000); -- } -- -- if (!tps && display) -- NV_INFO(dev, "%s - No TPs claiming errors?\n", name); --} -- --static void --nv50_pgraph_trap_handler(struct drm_device *dev) --{ -- struct nouveau_pgraph_trap trap; -- uint32_t status = nv_rd32(dev, 0x400108); -- uint32_t ustatus; -- int display = nouveau_ratelimit(); -- -- -- if (!status && display) { -- nouveau_graph_trap_info(dev, &trap); -- nouveau_graph_dump_trap_info(dev, "PGRAPH_TRAP", &trap); -- NV_INFO(dev, "PGRAPH_TRAP - no units reporting traps?\n"); -- } -- -- /* DISPATCH: Relays commands to other units and handles NOTIFY, -- * COND, QUERY. If you get a trap from it, the command is still stuck -- * in DISPATCH and you need to do something about it. */ -- if (status & 0x001) { -- ustatus = nv_rd32(dev, 0x400804) & 0x7fffffff; -- if (!ustatus && display) { -- NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - no ustatus?\n"); -- } -- -- /* Known to be triggered by screwed up NOTIFY and COND... */ -- if (ustatus & 0x00000001) { -- nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_FAULT"); -- nv_wr32(dev, 0x400500, 0); -- if (nv_rd32(dev, 0x400808) & 0x80000000) { -- if (display) { -- if (nouveau_graph_trapped_channel(dev, &trap.channel)) -- trap.channel = -1; -- trap.class = nv_rd32(dev, 0x400814); -- trap.mthd = nv_rd32(dev, 0x400808) & 0x1ffc; -- trap.subc = (nv_rd32(dev, 0x400808) >> 16) & 0x7; -- trap.data = nv_rd32(dev, 0x40080c); -- trap.data2 = nv_rd32(dev, 0x400810); -- nouveau_graph_dump_trap_info(dev, -- "PGRAPH_TRAP_DISPATCH_FAULT", &trap); -- NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - 400808: %08x\n", nv_rd32(dev, 0x400808)); -- NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - 400848: %08x\n", nv_rd32(dev, 0x400848)); -- } -- nv_wr32(dev, 0x400808, 0); -- } else if (display) { -- NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - No stuck command?\n"); -- } -- nv_wr32(dev, 0x4008e8, nv_rd32(dev, 0x4008e8) & 3); -- nv_wr32(dev, 0x400848, 0); -- ustatus &= ~0x00000001; -- } -- if (ustatus & 0x00000002) { -- nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_QUERY"); -- nv_wr32(dev, 0x400500, 0); -- if (nv_rd32(dev, 0x40084c) & 0x80000000) { -- if (display) { -- if (nouveau_graph_trapped_channel(dev, &trap.channel)) -- trap.channel = -1; -- trap.class = nv_rd32(dev, 0x400814); -- trap.mthd = nv_rd32(dev, 0x40084c) & 0x1ffc; -- trap.subc = (nv_rd32(dev, 0x40084c) >> 16) & 0x7; -- trap.data = nv_rd32(dev, 0x40085c); -- trap.data2 = 0; -- nouveau_graph_dump_trap_info(dev, -- "PGRAPH_TRAP_DISPATCH_QUERY", &trap); -- NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_QUERY - 40084c: %08x\n", nv_rd32(dev, 0x40084c)); -- } -- nv_wr32(dev, 0x40084c, 0); -- } else if (display) { -- NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_QUERY - No stuck command?\n"); -- } -- ustatus &= ~0x00000002; -- } -- if (ustatus && display) -- NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - Unhandled ustatus 0x%08x\n", ustatus); -- nv_wr32(dev, 0x400804, 0xc0000000); -- nv_wr32(dev, 0x400108, 0x001); -- status &= ~0x001; -- } -- -- /* TRAPs other than dispatch use the "normal" trap regs. */ -- if (status && display) { -- nouveau_graph_trap_info(dev, &trap); -- nouveau_graph_dump_trap_info(dev, -- "PGRAPH_TRAP", &trap); -- } -- -- /* M2MF: Memory to memory copy engine. */ -- if (status & 0x002) { -- ustatus = nv_rd32(dev, 0x406800) & 0x7fffffff; -- if (!ustatus && display) { -- NV_INFO(dev, "PGRAPH_TRAP_M2MF - no ustatus?\n"); -- } -- if (ustatus & 0x00000001) { -- nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_NOTIFY"); -- ustatus &= ~0x00000001; -- } -- if (ustatus & 0x00000002) { -- nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_IN"); -- ustatus &= ~0x00000002; -- } -- if (ustatus & 0x00000004) { -- nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_OUT"); -- ustatus &= ~0x00000004; -- } -- NV_INFO (dev, "PGRAPH_TRAP_M2MF - %08x %08x %08x %08x\n", -- nv_rd32(dev, 0x406804), -- nv_rd32(dev, 0x406808), -- nv_rd32(dev, 0x40680c), -- nv_rd32(dev, 0x406810)); -- if (ustatus && display) -- NV_INFO(dev, "PGRAPH_TRAP_M2MF - Unhandled ustatus 0x%08x\n", ustatus); -- /* No sane way found yet -- just reset the bugger. */ -- nv_wr32(dev, 0x400040, 2); -- nv_wr32(dev, 0x400040, 0); -- nv_wr32(dev, 0x406800, 0xc0000000); -- nv_wr32(dev, 0x400108, 0x002); -- status &= ~0x002; -- } -- -- /* VFETCH: Fetches data from vertex buffers. */ -- if (status & 0x004) { -- ustatus = nv_rd32(dev, 0x400c04) & 0x7fffffff; -- if (!ustatus && display) { -- NV_INFO(dev, "PGRAPH_TRAP_VFETCH - no ustatus?\n"); -- } -- if (ustatus & 0x00000001) { -- nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_VFETCH_FAULT"); -- NV_INFO (dev, "PGRAPH_TRAP_VFETCH_FAULT - %08x %08x %08x %08x\n", -- nv_rd32(dev, 0x400c00), -- nv_rd32(dev, 0x400c08), -- nv_rd32(dev, 0x400c0c), -- nv_rd32(dev, 0x400c10)); -- ustatus &= ~0x00000001; -- } -- if (ustatus && display) -- NV_INFO(dev, "PGRAPH_TRAP_VFETCH - Unhandled ustatus 0x%08x\n", ustatus); -- nv_wr32(dev, 0x400c04, 0xc0000000); -- nv_wr32(dev, 0x400108, 0x004); -- status &= ~0x004; -- } -- -- /* STRMOUT: DirectX streamout / OpenGL transform feedback. */ -- if (status & 0x008) { -- ustatus = nv_rd32(dev, 0x401800) & 0x7fffffff; -- if (!ustatus && display) { -- NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - no ustatus?\n"); -- } -- if (ustatus & 0x00000001) { -- nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_STRMOUT_FAULT"); -- NV_INFO (dev, "PGRAPH_TRAP_STRMOUT_FAULT - %08x %08x %08x %08x\n", -- nv_rd32(dev, 0x401804), -- nv_rd32(dev, 0x401808), -- nv_rd32(dev, 0x40180c), -- nv_rd32(dev, 0x401810)); -- ustatus &= ~0x00000001; -- } -- if (ustatus && display) -- NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - Unhandled ustatus 0x%08x\n", ustatus); -- /* No sane way found yet -- just reset the bugger. */ -- nv_wr32(dev, 0x400040, 0x80); -- nv_wr32(dev, 0x400040, 0); -- nv_wr32(dev, 0x401800, 0xc0000000); -- nv_wr32(dev, 0x400108, 0x008); -- status &= ~0x008; -- } -- -- /* CCACHE: Handles code and c[] caches and fills them. */ -- if (status & 0x010) { -- ustatus = nv_rd32(dev, 0x405018) & 0x7fffffff; -- if (!ustatus && display) { -- NV_INFO(dev, "PGRAPH_TRAP_CCACHE - no ustatus?\n"); -- } -- if (ustatus & 0x00000001) { -- nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_CCACHE_FAULT"); -- NV_INFO (dev, "PGRAPH_TRAP_CCACHE_FAULT - %08x %08x %08x %08x %08x %08x %08x\n", -- nv_rd32(dev, 0x405800), -- nv_rd32(dev, 0x405804), -- nv_rd32(dev, 0x405808), -- nv_rd32(dev, 0x40580c), -- nv_rd32(dev, 0x405810), -- nv_rd32(dev, 0x405814), -- nv_rd32(dev, 0x40581c)); -- ustatus &= ~0x00000001; -- } -- if (ustatus && display) -- NV_INFO(dev, "PGRAPH_TRAP_CCACHE - Unhandled ustatus 0x%08x\n", ustatus); -- nv_wr32(dev, 0x405018, 0xc0000000); -- nv_wr32(dev, 0x400108, 0x010); -- status &= ~0x010; -- } -- -- /* Unknown, not seen yet... 0x402000 is the only trap status reg -- * remaining, so try to handle it anyway. Perhaps related to that -- * unknown DMA slot on tesla? */ -- if (status & 0x20) { -- nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_UNKC04"); -- ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff; -- if (display) -- NV_INFO(dev, "PGRAPH_TRAP_UNKC04 - Unhandled ustatus 0x%08x\n", ustatus); -- nv_wr32(dev, 0x402000, 0xc0000000); -- /* no status modifiction on purpose */ -- } -- -- /* TEXTURE: CUDA texturing units */ -- if (status & 0x040) { -- nv50_pgraph_tp_trap (dev, 6, 0x408900, 0x408600, display, -- "PGRAPH_TRAP_TEXTURE"); -- nv_wr32(dev, 0x400108, 0x040); -- status &= ~0x040; -- } -- -- /* MP: CUDA execution engines. */ -- if (status & 0x080) { -- nv50_pgraph_tp_trap (dev, 7, 0x408314, 0x40831c, display, -- "PGRAPH_TRAP_MP"); -- nv_wr32(dev, 0x400108, 0x080); -- status &= ~0x080; -- } -- -- /* TPDMA: Handles TP-initiated uncached memory accesses: -- * l[], g[], stack, 2d surfaces, render targets. */ -- if (status & 0x100) { -- nv50_pgraph_tp_trap (dev, 8, 0x408e08, 0x408708, display, -- "PGRAPH_TRAP_TPDMA"); -- nv_wr32(dev, 0x400108, 0x100); -- status &= ~0x100; -- } - -- if (status) { -- if (display) -- NV_INFO(dev, "PGRAPH_TRAP - Unknown trap 0x%08x\n", -- status); -- nv_wr32(dev, 0x400108, status); -- } -+ drm_irq_uninstall(dev); -+ if (dev_priv->msi_enabled) -+ pci_disable_msi(dev->pdev); - } - --/* There must be a *lot* of these. Will take some time to gather them up. */ --static struct nouveau_enum_names nv50_data_error_names[] = --{ -- { 4, "INVALID_VALUE" }, -- { 5, "INVALID_ENUM" }, -- { 8, "INVALID_OBJECT" }, -- { 0xc, "INVALID_BITFIELD" }, -- { 0x28, "MP_NO_REG_SPACE" }, -- { 0x2b, "MP_BLOCK_SIZE_MISMATCH" }, --}; -- --static void --nv50_pgraph_irq_handler(struct drm_device *dev) --{ -- struct nouveau_pgraph_trap trap; -- int unhandled = 0; -- uint32_t status; -- -- while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) { -- /* NOTIFY: You've set a NOTIFY an a command and it's done. */ -- if (status & 0x00000001) { -- nouveau_graph_trap_info(dev, &trap); -- if (nouveau_ratelimit()) -- nouveau_graph_dump_trap_info(dev, -- "PGRAPH_NOTIFY", &trap); -- status &= ~0x00000001; -- nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000001); -- } -- -- /* COMPUTE_QUERY: Purpose and exact cause unknown, happens -- * when you write 0x200 to 0x50c0 method 0x31c. */ -- if (status & 0x00000002) { -- nouveau_graph_trap_info(dev, &trap); -- if (nouveau_ratelimit()) -- nouveau_graph_dump_trap_info(dev, -- "PGRAPH_COMPUTE_QUERY", &trap); -- status &= ~0x00000002; -- nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000002); -- } -- -- /* Unknown, never seen: 0x4 */ -- -- /* ILLEGAL_MTHD: You used a wrong method for this class. */ -- if (status & 0x00000010) { -- nouveau_graph_trap_info(dev, &trap); -- if (nouveau_pgraph_intr_swmthd(dev, &trap)) -- unhandled = 1; -- if (unhandled && nouveau_ratelimit()) -- nouveau_graph_dump_trap_info(dev, -- "PGRAPH_ILLEGAL_MTHD", &trap); -- status &= ~0x00000010; -- nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000010); -- } -- -- /* ILLEGAL_CLASS: You used a wrong class. */ -- if (status & 0x00000020) { -- nouveau_graph_trap_info(dev, &trap); -- if (nouveau_ratelimit()) -- nouveau_graph_dump_trap_info(dev, -- "PGRAPH_ILLEGAL_CLASS", &trap); -- status &= ~0x00000020; -- nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000020); -- } -- -- /* DOUBLE_NOTIFY: You tried to set a NOTIFY on another NOTIFY. */ -- if (status & 0x00000040) { -- nouveau_graph_trap_info(dev, &trap); -- if (nouveau_ratelimit()) -- nouveau_graph_dump_trap_info(dev, -- "PGRAPH_DOUBLE_NOTIFY", &trap); -- status &= ~0x00000040; -- nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000040); -- } -- -- /* CONTEXT_SWITCH: PGRAPH needs us to load a new context */ -- if (status & 0x00001000) { -- nv_wr32(dev, 0x400500, 0x00000000); -- nv_wr32(dev, NV03_PGRAPH_INTR, -- NV_PGRAPH_INTR_CONTEXT_SWITCH); -- nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev, -- NV40_PGRAPH_INTR_EN) & -- ~NV_PGRAPH_INTR_CONTEXT_SWITCH); -- nv_wr32(dev, 0x400500, 0x00010001); -- -- nv50_graph_context_switch(dev); -- -- status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; -- } -- -- /* BUFFER_NOTIFY: Your m2mf transfer finished */ -- if (status & 0x00010000) { -- nouveau_graph_trap_info(dev, &trap); -- if (nouveau_ratelimit()) -- nouveau_graph_dump_trap_info(dev, -- "PGRAPH_BUFFER_NOTIFY", &trap); -- status &= ~0x00010000; -- nv_wr32(dev, NV03_PGRAPH_INTR, 0x00010000); -- } -- -- /* DATA_ERROR: Invalid value for this method, or invalid -- * state in current PGRAPH context for this operation */ -- if (status & 0x00100000) { -- nouveau_graph_trap_info(dev, &trap); -- if (nouveau_ratelimit()) { -- nouveau_graph_dump_trap_info(dev, -- "PGRAPH_DATA_ERROR", &trap); -- NV_INFO (dev, "PGRAPH_DATA_ERROR - "); -- nouveau_print_enum_names(nv_rd32(dev, 0x400110), -- nv50_data_error_names); -- printk("\n"); -- } -- status &= ~0x00100000; -- nv_wr32(dev, NV03_PGRAPH_INTR, 0x00100000); -- } -- -- /* TRAP: Something bad happened in the middle of command -- * execution. Has a billion types, subtypes, and even -- * subsubtypes. */ -- if (status & 0x00200000) { -- nv50_pgraph_trap_handler(dev); -- status &= ~0x00200000; -- nv_wr32(dev, NV03_PGRAPH_INTR, 0x00200000); -- } -- -- /* Unknown, never seen: 0x00400000 */ -- -- /* SINGLE_STEP: Happens on every method if you turned on -- * single stepping in 40008c */ -- if (status & 0x01000000) { -- nouveau_graph_trap_info(dev, &trap); -- if (nouveau_ratelimit()) -- nouveau_graph_dump_trap_info(dev, -- "PGRAPH_SINGLE_STEP", &trap); -- status &= ~0x01000000; -- nv_wr32(dev, NV03_PGRAPH_INTR, 0x01000000); -- } -- -- /* 0x02000000 happens when you pause a ctxprog... -- * but the only way this can happen that I know is by -- * poking the relevant MMIO register, and we don't -- * do that. */ -- -- if (status) { -- NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n", -- status); -- nv_wr32(dev, NV03_PGRAPH_INTR, status); -- } -- -- { -- const int isb = (1 << 16) | (1 << 0); -- -- if ((nv_rd32(dev, 0x400500) & isb) != isb) -- nv_wr32(dev, 0x400500, -- nv_rd32(dev, 0x400500) | isb); -- } -- } -- -- nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); -- if (nv_rd32(dev, 0x400824) & (1 << 31)) -- nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31)); --} -- --static void --nouveau_crtc_irq_handler(struct drm_device *dev, int crtc) -+void -+nouveau_irq_register(struct drm_device *dev, int status_bit, -+ void (*handler)(struct drm_device *)) - { -- if (crtc & 1) -- nv_wr32(dev, NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK); -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ unsigned long flags; - -- if (crtc & 2) -- nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK); -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ dev_priv->irq_handler[status_bit] = handler; -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - } - --irqreturn_t --nouveau_irq_handler(DRM_IRQ_ARGS) -+void -+nouveau_irq_unregister(struct drm_device *dev, int status_bit) - { -- struct drm_device *dev = (struct drm_device *)arg; - struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t status; - unsigned long flags; - -- status = nv_rd32(dev, NV03_PMC_INTR_0); -- if (!status) -- return IRQ_NONE; -- - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- -- if (status & NV_PMC_INTR_0_PFIFO_PENDING) { -- nouveau_fifo_irq_handler(dev); -- status &= ~NV_PMC_INTR_0_PFIFO_PENDING; -- } -- -- if (status & NV_PMC_INTR_0_PGRAPH_PENDING) { -- if (dev_priv->card_type >= NV_50) -- nv50_pgraph_irq_handler(dev); -- else -- nouveau_pgraph_irq_handler(dev); -- -- status &= ~NV_PMC_INTR_0_PGRAPH_PENDING; -- } -- -- if (status & NV_PMC_INTR_0_CRTCn_PENDING) { -- nouveau_crtc_irq_handler(dev, (status>>24)&3); -- status &= ~NV_PMC_INTR_0_CRTCn_PENDING; -- } -- -- if (status & (NV_PMC_INTR_0_NV50_DISPLAY_PENDING | -- NV_PMC_INTR_0_NV50_I2C_PENDING)) { -- nv50_display_irq_handler(dev); -- status &= ~(NV_PMC_INTR_0_NV50_DISPLAY_PENDING | -- NV_PMC_INTR_0_NV50_I2C_PENDING); -- } -- -- if (status) -- NV_ERROR(dev, "Unhandled PMC INTR status bits 0x%08x\n", status); -- -+ dev_priv->irq_handler[status_bit] = NULL; - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -- -- return IRQ_HANDLED; - } -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_mem.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_mem.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_mem.c 2011-01-07 14:22:17.000000000 +0100 -@@ -36,183 +36,112 @@ - - #include "nouveau_drv.h" - #include "nouveau_pm.h" -+#include "nouveau_mm.h" -+#include "nouveau_vm.h" - - /* - * NV10-NV40 tiling helpers - */ - - static void --nv10_mem_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch) -+nv10_mem_update_tile_region(struct drm_device *dev, -+ struct nouveau_tile_reg *tile, uint32_t addr, -+ uint32_t size, uint32_t pitch, uint32_t flags) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -- struct nouveau_tile_reg *tile = &dev_priv->tile[i]; -+ int i = tile - dev_priv->tile.reg; -+ unsigned long save; - -- tile->addr = addr; -- tile->size = size; -- tile->used = !!pitch; -- nouveau_fence_unref((void **)&tile->fence); -+ nouveau_fence_unref(&tile->fence); - -+ if (tile->pitch) -+ pfb->free_tile_region(dev, i); -+ -+ if (pitch) -+ pfb->init_tile_region(dev, i, addr, size, pitch, flags); -+ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, save); - pfifo->reassign(dev, false); - pfifo->cache_pull(dev, false); - - nouveau_wait_for_idle(dev); - -- pgraph->set_region_tiling(dev, i, addr, size, pitch); -- pfb->set_region_tiling(dev, i, addr, size, pitch); -+ pfb->set_tile_region(dev, i); -+ pgraph->set_tile_region(dev, i); - - pfifo->cache_pull(dev, true); - pfifo->reassign(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, save); - } - --struct nouveau_tile_reg * --nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size, -- uint32_t pitch) -+static struct nouveau_tile_reg * -+nv10_mem_get_tile_region(struct drm_device *dev, int i) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; -- struct nouveau_tile_reg *found = NULL; -- unsigned long i, flags; -- -- spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- -- for (i = 0; i < pfb->num_tiles; i++) { -- struct nouveau_tile_reg *tile = &dev_priv->tile[i]; -- -- if (tile->used) -- /* Tile region in use. */ -- continue; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - -- if (tile->fence && -- !nouveau_fence_signalled(tile->fence, NULL)) -- /* Pending tile region. */ -- continue; -- -- if (max(tile->addr, addr) < -- min(tile->addr + tile->size, addr + size)) -- /* Kill an intersecting tile region. */ -- nv10_mem_set_region_tiling(dev, i, 0, 0, 0); -- -- if (pitch && !found) { -- /* Free tile region. */ -- nv10_mem_set_region_tiling(dev, i, addr, size, pitch); -- found = tile; -- } -- } -+ spin_lock(&dev_priv->tile.lock); - -- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ if (!tile->used && -+ (!tile->fence || nouveau_fence_signalled(tile->fence))) -+ tile->used = true; -+ else -+ tile = NULL; - -- return found; -+ spin_unlock(&dev_priv->tile.lock); -+ return tile; - } - - void --nv10_mem_expire_tiling(struct drm_device *dev, struct nouveau_tile_reg *tile, -- struct nouveau_fence *fence) --{ -- if (fence) { -- /* Mark it as pending. */ -- tile->fence = fence; -- nouveau_fence_ref(fence); -- } -- -- tile->used = false; --} -- --/* -- * NV50 VM helpers -- */ --int --nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, -- uint32_t flags, uint64_t phys) -+nv10_mem_put_tile_region(struct drm_device *dev, struct nouveau_tile_reg *tile, -+ struct nouveau_fence *fence) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *pgt; -- unsigned block; -- int i; -- -- virt = ((virt - dev_priv->vm_vram_base) >> 16) << 1; -- size = (size >> 16) << 1; -- -- phys |= ((uint64_t)flags << 32); -- phys |= 1; -- if (dev_priv->vram_sys_base) { -- phys += dev_priv->vram_sys_base; -- phys |= 0x30; -- } - -- while (size) { -- unsigned offset_h = upper_32_bits(phys); -- unsigned offset_l = lower_32_bits(phys); -- unsigned pte, end; -- -- for (i = 7; i >= 0; i--) { -- block = 1 << (i + 1); -- if (size >= block && !(virt & (block - 1))) -- break; -+ if (tile) { -+ spin_lock(&dev_priv->tile.lock); -+ if (fence) { -+ /* Mark it as pending. */ -+ tile->fence = fence; -+ nouveau_fence_ref(fence); - } -- offset_l |= (i << 7); -- -- phys += block << 15; -- size -= block; - -- while (block) { -- pgt = dev_priv->vm_vram_pt[virt >> 14]; -- pte = virt & 0x3ffe; -- -- end = pte + block; -- if (end > 16384) -- end = 16384; -- block -= (end - pte); -- virt += (end - pte); -- -- while (pte < end) { -- nv_wo32(pgt, (pte * 4) + 0, offset_l); -- nv_wo32(pgt, (pte * 4) + 4, offset_h); -- pte += 2; -- } -- } -+ tile->used = false; -+ spin_unlock(&dev_priv->tile.lock); - } -- -- dev_priv->engine.instmem.flush(dev); -- dev_priv->engine.fifo.tlb_flush(dev); -- dev_priv->engine.graph.tlb_flush(dev); -- nv50_vm_flush(dev, 6); -- return 0; - } - --void --nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) -+struct nouveau_tile_reg * -+nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size, -+ uint32_t pitch, uint32_t flags) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *pgt; -- unsigned pages, pte, end; -- -- virt -= dev_priv->vm_vram_base; -- pages = (size >> 16) << 1; -+ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; -+ struct nouveau_tile_reg *tile, *found = NULL; -+ int i; - -- while (pages) { -- pgt = dev_priv->vm_vram_pt[virt >> 29]; -- pte = (virt & 0x1ffe0000ULL) >> 15; -+ for (i = 0; i < pfb->num_tiles; i++) { -+ tile = nv10_mem_get_tile_region(dev, i); - -- end = pte + pages; -- if (end > 16384) -- end = 16384; -- pages -= (end - pte); -- virt += (end - pte) << 15; -+ if (pitch && !found) { -+ found = tile; -+ continue; - -- while (pte < end) { -- nv_wo32(pgt, (pte * 4), 0); -- pte++; -+ } else if (tile && tile->pitch) { -+ /* Kill an unused tile region. */ -+ nv10_mem_update_tile_region(dev, tile, 0, 0, 0, 0); - } -+ -+ nv10_mem_put_tile_region(dev, tile, NULL); - } - -- dev_priv->engine.instmem.flush(dev); -- dev_priv->engine.fifo.tlb_flush(dev); -- dev_priv->engine.graph.tlb_flush(dev); -- nv50_vm_flush(dev, 6); -+ if (found) -+ nv10_mem_update_tile_region(dev, found, addr, size, -+ pitch, flags); -+ return found; - } - - /* -@@ -312,62 +241,7 @@ - return 0; - } - --static void --nv50_vram_preinit(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- int i, parts, colbits, rowbitsa, rowbitsb, banks; -- u64 rowsize, predicted; -- u32 r0, r4, rt, ru; -- -- r0 = nv_rd32(dev, 0x100200); -- r4 = nv_rd32(dev, 0x100204); -- rt = nv_rd32(dev, 0x100250); -- ru = nv_rd32(dev, 0x001540); -- NV_DEBUG(dev, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru); -- -- for (i = 0, parts = 0; i < 8; i++) { -- if (ru & (0x00010000 << i)) -- parts++; -- } -- -- colbits = (r4 & 0x0000f000) >> 12; -- rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; -- rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; -- banks = ((r4 & 0x01000000) ? 8 : 4); -- -- rowsize = parts * banks * (1 << colbits) * 8; -- predicted = rowsize << rowbitsa; -- if (r0 & 0x00000004) -- predicted += rowsize << rowbitsb; -- -- if (predicted != dev_priv->vram_size) { -- NV_WARN(dev, "memory controller reports %dMiB VRAM\n", -- (u32)(dev_priv->vram_size >> 20)); -- NV_WARN(dev, "we calculated %dMiB VRAM\n", -- (u32)(predicted >> 20)); -- } -- -- dev_priv->vram_rblock_size = rowsize >> 12; -- if (rt & 1) -- dev_priv->vram_rblock_size *= 3; -- -- NV_DEBUG(dev, "rblock %lld bytes\n", -- (u64)dev_priv->vram_rblock_size << 12); --} -- --static void --nvaa_vram_preinit(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- -- /* To our knowledge, there's no large scale reordering of pages -- * that occurs on IGP chipsets. -- */ -- dev_priv->vram_rblock_size = 1; --} -- --static int -+int - nouveau_mem_detect(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -@@ -381,33 +255,6 @@ - if (dev_priv->card_type < NV_50) { - dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); - dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; -- } else -- if (dev_priv->card_type < NV_C0) { -- dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); -- dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; -- dev_priv->vram_size &= 0xffffffff00ll; -- -- switch (dev_priv->chipset) { -- case 0xaa: -- case 0xac: -- case 0xaf: -- dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10); -- dev_priv->vram_sys_base <<= 12; -- nvaa_vram_preinit(dev); -- break; -- default: -- nv50_vram_preinit(dev); -- break; -- } -- } else { -- dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; -- dev_priv->vram_size *= nv_rd32(dev, 0x121c74); -- } -- -- NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); -- if (dev_priv->vram_sys_base) { -- NV_INFO(dev, "Stolen system memory at: 0x%010llx\n", -- dev_priv->vram_sys_base); - } - - if (dev_priv->vram_size) -@@ -415,6 +262,15 @@ - return -ENOMEM; - } - -+bool -+nouveau_mem_flags_valid(struct drm_device *dev, u32 tile_flags) -+{ -+ if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK)) -+ return true; -+ -+ return false; -+} -+ - #if __OS_HAS_AGP - static unsigned long - get_agp_mode(struct drm_device *dev, unsigned long mode) -@@ -547,10 +403,6 @@ - if (ret) - return ret; - -- ret = nouveau_mem_detect(dev); -- if (ret) -- return ret; -- - dev_priv->fb_phys = pci_resource_start(dev->pdev, 1); - - ret = nouveau_ttm_global_init(dev_priv); -@@ -566,13 +418,6 @@ - return ret; - } - -- dev_priv->fb_available_size = dev_priv->vram_size; -- dev_priv->fb_mappable_pages = dev_priv->fb_available_size; -- if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1)) -- dev_priv->fb_mappable_pages = -- pci_resource_len(dev->pdev, 1); -- dev_priv->fb_mappable_pages >>= PAGE_SHIFT; -- - /* reserve space at end of VRAM for PRAMIN */ - if (dev_priv->chipset == 0x40 || dev_priv->chipset == 0x47 || - dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) -@@ -583,6 +428,22 @@ - 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", -+ dev_priv->vram_sys_base); -+ } -+ -+ dev_priv->fb_available_size = dev_priv->vram_size; -+ dev_priv->fb_mappable_pages = dev_priv->fb_available_size; -+ if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1)) -+ dev_priv->fb_mappable_pages = pci_resource_len(dev->pdev, 1); -+ dev_priv->fb_mappable_pages >>= PAGE_SHIFT; -+ - dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram; - dev_priv->fb_aper_free = dev_priv->fb_available_size; - -@@ -799,3 +660,118 @@ - - kfree(mem->timing); - } -+ -+static int -+nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size) -+{ -+ struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); -+ struct nouveau_mm *mm; -+ u32 b_size; -+ int ret; -+ -+ p_size = (p_size << PAGE_SHIFT) >> 12; -+ b_size = dev_priv->vram_rblock_size >> 12; -+ -+ ret = nouveau_mm_init(&mm, 0, p_size, b_size); -+ if (ret) -+ return ret; -+ -+ man->priv = mm; -+ return 0; -+} -+ -+static int -+nouveau_vram_manager_fini(struct ttm_mem_type_manager *man) -+{ -+ struct nouveau_mm *mm = man->priv; -+ int ret; -+ -+ ret = nouveau_mm_fini(&mm); -+ if (ret) -+ return ret; -+ -+ man->priv = NULL; -+ return 0; -+} -+ -+static void -+nouveau_vram_manager_del(struct ttm_mem_type_manager *man, -+ struct ttm_mem_reg *mem) -+{ -+ struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); -+ struct nouveau_vram_engine *vram = &dev_priv->engine.vram; -+ struct drm_device *dev = dev_priv->dev; -+ -+ vram->put(dev, (struct nouveau_vram **)&mem->mm_node); -+} -+ -+static int -+nouveau_vram_manager_new(struct ttm_mem_type_manager *man, -+ struct ttm_buffer_object *bo, -+ struct ttm_placement *placement, -+ struct ttm_mem_reg *mem) -+{ -+ struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); -+ struct nouveau_vram_engine *vram = &dev_priv->engine.vram; -+ struct drm_device *dev = dev_priv->dev; -+ struct nouveau_bo *nvbo = nouveau_bo(bo); -+ struct nouveau_vram *node; -+ u32 size_nc = 0; -+ int ret; -+ -+ if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) -+ size_nc = 1 << nvbo->vma.node->type; -+ -+ ret = vram->get(dev, mem->num_pages << PAGE_SHIFT, -+ mem->page_alignment << PAGE_SHIFT, size_nc, -+ (nvbo->tile_flags >> 8) & 0xff, &node); -+ if (ret) -+ return ret; -+ -+ node->page_shift = 12; -+ if (nvbo->vma.node) -+ node->page_shift = nvbo->vma.node->type; -+ -+ mem->mm_node = node; -+ mem->start = node->offset >> PAGE_SHIFT; -+ return 0; -+} -+ -+void -+nouveau_vram_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) -+{ -+ struct nouveau_mm *mm = man->priv; -+ struct nouveau_mm_node *r; -+ u64 total = 0, ttotal[3] = {}, tused[3] = {}, tfree[3] = {}; -+ int i; -+ -+ mutex_lock(&mm->mutex); -+ list_for_each_entry(r, &mm->nodes, nl_entry) { -+ printk(KERN_DEBUG "%s %s-%d: 0x%010llx 0x%010llx\n", -+ prefix, r->free ? "free" : "used", r->type, -+ ((u64)r->offset << 12), -+ (((u64)r->offset + r->length) << 12)); -+ total += r->length; -+ ttotal[r->type] += r->length; -+ if (r->free) -+ tfree[r->type] += r->length; -+ else -+ tused[r->type] += r->length; -+ } -+ mutex_unlock(&mm->mutex); -+ -+ printk(KERN_DEBUG "%s total: 0x%010llx\n", prefix, total << 12); -+ for (i = 0; i < 3; i++) { -+ printk(KERN_DEBUG "%s type %d: 0x%010llx, " -+ "used 0x%010llx, free 0x%010llx\n", prefix, -+ i, ttotal[i] << 12, tused[i] << 12, tfree[i] << 12); -+ } -+} -+ -+const struct ttm_mem_type_manager_func nouveau_vram_manager = { -+ nouveau_vram_manager_init, -+ nouveau_vram_manager_fini, -+ nouveau_vram_manager_new, -+ nouveau_vram_manager_del, -+ nouveau_vram_manager_debug -+}; -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_mm.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_mm.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_mm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_mm.c 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,271 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+#include "nouveau_drv.h" -+#include "nouveau_mm.h" -+ -+static inline void -+region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a) -+{ -+ list_del(&a->nl_entry); -+ list_del(&a->fl_entry); -+ kfree(a); -+} -+ -+static struct nouveau_mm_node * -+region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size) -+{ -+ struct nouveau_mm_node *b; -+ -+ if (a->length == size) -+ return a; -+ -+ b = kmalloc(sizeof(*b), GFP_KERNEL); -+ if (unlikely(b == NULL)) -+ return NULL; -+ -+ b->offset = a->offset; -+ b->length = size; -+ b->free = a->free; -+ b->type = a->type; -+ a->offset += size; -+ a->length -= size; -+ list_add_tail(&b->nl_entry, &a->nl_entry); -+ if (b->free) -+ list_add_tail(&b->fl_entry, &a->fl_entry); -+ return b; -+} -+ -+static struct nouveau_mm_node * -+nouveau_mm_merge(struct nouveau_mm *rmm, struct nouveau_mm_node *this) -+{ -+ struct nouveau_mm_node *prev, *next; -+ -+ /* try to merge with free adjacent entries of same type */ -+ prev = list_entry(this->nl_entry.prev, struct nouveau_mm_node, nl_entry); -+ if (this->nl_entry.prev != &rmm->nodes) { -+ if (prev->free && prev->type == this->type) { -+ prev->length += this->length; -+ region_put(rmm, this); -+ this = prev; -+ } -+ } -+ -+ next = list_entry(this->nl_entry.next, struct nouveau_mm_node, nl_entry); -+ if (this->nl_entry.next != &rmm->nodes) { -+ if (next->free && next->type == this->type) { -+ next->offset = this->offset; -+ next->length += this->length; -+ region_put(rmm, this); -+ this = next; -+ } -+ } -+ -+ return this; -+} -+ -+void -+nouveau_mm_put(struct nouveau_mm *rmm, struct nouveau_mm_node *this) -+{ -+ u32 block_s, block_l; -+ -+ this->free = true; -+ list_add(&this->fl_entry, &rmm->free); -+ this = nouveau_mm_merge(rmm, this); -+ -+ /* any entirely free blocks now? we'll want to remove typing -+ * on them now so they can be use for any memory allocation -+ */ -+ block_s = roundup(this->offset, rmm->block_size); -+ if (block_s + rmm->block_size > this->offset + this->length) -+ return; -+ -+ /* split off any still-typed region at the start */ -+ if (block_s != this->offset) { -+ if (!region_split(rmm, this, block_s - this->offset)) -+ return; -+ } -+ -+ /* split off the soon-to-be-untyped block(s) */ -+ block_l = rounddown(this->length, rmm->block_size); -+ if (block_l != this->length) { -+ this = region_split(rmm, this, block_l); -+ if (!this) -+ return; -+ } -+ -+ /* mark as having no type, and retry merge with any adjacent -+ * untyped blocks -+ */ -+ this->type = 0; -+ nouveau_mm_merge(rmm, this); -+} -+ -+int -+nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, -+ u32 align, struct nouveau_mm_node **pnode) -+{ -+ struct nouveau_mm_node *this, *tmp, *next; -+ u32 splitoff, avail, alloc; -+ -+ list_for_each_entry_safe(this, tmp, &rmm->free, fl_entry) { -+ next = list_entry(this->nl_entry.next, struct nouveau_mm_node, nl_entry); -+ if (this->nl_entry.next == &rmm->nodes) -+ next = NULL; -+ -+ /* skip wrongly typed blocks */ -+ if (this->type && this->type != type) -+ continue; -+ -+ /* account for alignment */ -+ splitoff = this->offset & (align - 1); -+ if (splitoff) -+ splitoff = align - splitoff; -+ -+ if (this->length <= splitoff) -+ continue; -+ -+ /* determine total memory available from this, and -+ * the next block (if appropriate) -+ */ -+ avail = this->length; -+ if (next && next->free && (!next->type || next->type == type)) -+ avail += next->length; -+ -+ avail -= splitoff; -+ -+ /* determine allocation size */ -+ if (size_nc) { -+ alloc = min(avail, size); -+ alloc = rounddown(alloc, size_nc); -+ if (alloc == 0) -+ continue; -+ } else { -+ alloc = size; -+ if (avail < alloc) -+ continue; -+ } -+ -+ /* untyped block, split off a chunk that's a multiple -+ * of block_size and type it -+ */ -+ if (!this->type) { -+ u32 block = roundup(alloc + splitoff, rmm->block_size); -+ if (this->length < block) -+ continue; -+ -+ this = region_split(rmm, this, block); -+ if (!this) -+ return -ENOMEM; -+ -+ this->type = type; -+ } -+ -+ /* stealing memory from adjacent block */ -+ if (alloc > this->length) { -+ u32 amount = alloc - (this->length - splitoff); -+ -+ if (!next->type) { -+ amount = roundup(amount, rmm->block_size); -+ -+ next = region_split(rmm, next, amount); -+ if (!next) -+ return -ENOMEM; -+ -+ next->type = type; -+ } -+ -+ this->length += amount; -+ next->offset += amount; -+ next->length -= amount; -+ if (!next->length) { -+ list_del(&next->nl_entry); -+ list_del(&next->fl_entry); -+ kfree(next); -+ } -+ } -+ -+ if (splitoff) { -+ if (!region_split(rmm, this, splitoff)) -+ return -ENOMEM; -+ } -+ -+ this = region_split(rmm, this, alloc); -+ if (this == NULL) -+ return -ENOMEM; -+ -+ this->free = false; -+ list_del(&this->fl_entry); -+ *pnode = this; -+ return 0; -+ } -+ -+ return -ENOMEM; -+} -+ -+int -+nouveau_mm_init(struct nouveau_mm **prmm, u32 offset, u32 length, u32 block) -+{ -+ struct nouveau_mm *rmm; -+ struct nouveau_mm_node *heap; -+ -+ heap = kzalloc(sizeof(*heap), GFP_KERNEL); -+ if (!heap) -+ return -ENOMEM; -+ heap->free = true; -+ heap->offset = roundup(offset, block); -+ heap->length = rounddown(offset + length, block) - heap->offset; -+ -+ rmm = kzalloc(sizeof(*rmm), GFP_KERNEL); -+ if (!rmm) { -+ kfree(heap); -+ return -ENOMEM; -+ } -+ rmm->block_size = block; -+ mutex_init(&rmm->mutex); -+ INIT_LIST_HEAD(&rmm->nodes); -+ INIT_LIST_HEAD(&rmm->free); -+ list_add(&heap->nl_entry, &rmm->nodes); -+ list_add(&heap->fl_entry, &rmm->free); -+ -+ *prmm = rmm; -+ return 0; -+} -+ -+int -+nouveau_mm_fini(struct nouveau_mm **prmm) -+{ -+ struct nouveau_mm *rmm = *prmm; -+ struct nouveau_mm_node *heap = -+ list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry); -+ -+ if (!list_is_singular(&rmm->nodes)) -+ return -EBUSY; -+ -+ kfree(heap); -+ kfree(rmm); -+ *prmm = NULL; -+ return 0; -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_mm.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_mm.h ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_mm.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_mm.h 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,67 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#ifndef __NOUVEAU_REGION_H__ -+#define __NOUVEAU_REGION_H__ -+ -+struct nouveau_mm_node { -+ struct list_head nl_entry; -+ struct list_head fl_entry; -+ struct list_head rl_entry; -+ -+ bool free; -+ int type; -+ -+ u32 offset; -+ u32 length; -+}; -+ -+struct nouveau_mm { -+ struct list_head nodes; -+ struct list_head free; -+ -+ struct mutex mutex; -+ -+ u32 block_size; -+}; -+ -+int nouveau_mm_init(struct nouveau_mm **, u32 offset, u32 length, u32 block); -+int nouveau_mm_fini(struct nouveau_mm **); -+int nouveau_mm_pre(struct nouveau_mm *); -+int nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc, -+ u32 align, struct nouveau_mm_node **); -+void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *); -+ -+int nv50_vram_init(struct drm_device *); -+int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc, -+ u32 memtype, struct nouveau_vram **); -+void nv50_vram_del(struct drm_device *, struct nouveau_vram **); -+bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags); -+ -+int nvc0_vram_init(struct drm_device *); -+int nvc0_vram_new(struct drm_device *, u64 size, u32 align, u32 ncmin, -+ u32 memtype, struct nouveau_vram **); -+bool nvc0_vram_flags_valid(struct drm_device *, u32 tile_flags); -+ -+#endif -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_notifier.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_notifier.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_notifier.c 2011-01-07 14:22:17.000000000 +0100 -@@ -99,7 +99,6 @@ - int size, uint32_t *b_offset) - { - struct drm_device *dev = chan->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *nobj = NULL; - struct drm_mm_node *mem; - uint32_t offset; -@@ -113,31 +112,15 @@ - return -ENOMEM; - } - -- offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; -- if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) { -- target = NV_DMA_TARGET_VIDMEM; -- } else -- if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_TT) { -- if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA && -- dev_priv->card_type < NV_50) { -- ret = nouveau_sgdma_get_page(dev, offset, &offset); -- if (ret) -- return ret; -- target = NV_DMA_TARGET_PCI; -- } else { -- target = NV_DMA_TARGET_AGP; -- if (dev_priv->card_type >= NV_50) -- offset += dev_priv->vm_gart_base; -- } -- } else { -- NV_ERROR(dev, "Bad DMA target, mem_type %d!\n", -- chan->notifier_bo->bo.mem.mem_type); -- return -EINVAL; -- } -+ if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) -+ target = NV_MEM_TARGET_VRAM; -+ else -+ target = NV_MEM_TARGET_GART; -+ offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; - offset += mem->start; - - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset, -- mem->size, NV_DMA_ACCESS_RW, target, -+ mem->size, NV_MEM_ACCESS_RW, target, - &nobj); - if (ret) { - drm_mm_put_block(mem); -@@ -181,15 +164,20 @@ - nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, - struct drm_file *file_priv) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; - struct drm_nouveau_notifierobj_alloc *na = data; - struct nouveau_channel *chan; - int ret; - -- NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan); -+ /* completely unnecessary for these chipsets... */ -+ if (unlikely(dev_priv->card_type >= NV_C0)) -+ return -EINVAL; - -- ret = nouveau_notifier_alloc(chan, na->handle, na->size, &na->offset); -- if (ret) -- return ret; -+ chan = nouveau_channel_get(dev, file_priv, na->channel); -+ if (IS_ERR(chan)) -+ return PTR_ERR(chan); - -- return 0; -+ ret = nouveau_notifier_alloc(chan, na->handle, na->size, &na->offset); -+ nouveau_channel_put(&chan); -+ return ret; - } -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_object.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_object.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_object.c 2011-01-07 14:22:17.000000000 +0100 -@@ -35,6 +35,102 @@ - #include "nouveau_drv.h" - #include "nouveau_drm.h" - #include "nouveau_ramht.h" -+#include "nouveau_vm.h" -+ -+struct nouveau_gpuobj_method { -+ struct list_head head; -+ u32 mthd; -+ int (*exec)(struct nouveau_channel *, u32 class, u32 mthd, u32 data); -+}; -+ -+struct nouveau_gpuobj_class { -+ struct list_head head; -+ struct list_head methods; -+ u32 id; -+ u32 engine; -+}; -+ -+int -+nouveau_gpuobj_class_new(struct drm_device *dev, u32 class, u32 engine) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj_class *oc; -+ -+ oc = kzalloc(sizeof(*oc), GFP_KERNEL); -+ if (!oc) -+ return -ENOMEM; -+ -+ INIT_LIST_HEAD(&oc->methods); -+ oc->id = class; -+ oc->engine = engine; -+ list_add(&oc->head, &dev_priv->classes); -+ return 0; -+} -+ -+int -+nouveau_gpuobj_mthd_new(struct drm_device *dev, u32 class, u32 mthd, -+ int (*exec)(struct nouveau_channel *, u32, u32, u32)) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj_method *om; -+ struct nouveau_gpuobj_class *oc; -+ -+ list_for_each_entry(oc, &dev_priv->classes, head) { -+ if (oc->id == class) -+ goto found; -+ } -+ -+ return -EINVAL; -+ -+found: -+ om = kzalloc(sizeof(*om), GFP_KERNEL); -+ if (!om) -+ return -ENOMEM; -+ -+ om->mthd = mthd; -+ om->exec = exec; -+ list_add(&om->head, &oc->methods); -+ return 0; -+} -+ -+int -+nouveau_gpuobj_mthd_call(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) -+{ -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; -+ struct nouveau_gpuobj_method *om; -+ struct nouveau_gpuobj_class *oc; -+ -+ list_for_each_entry(oc, &dev_priv->classes, head) { -+ if (oc->id != class) -+ continue; -+ -+ list_for_each_entry(om, &oc->methods, head) { -+ if (om->mthd == mthd) -+ return om->exec(chan, class, mthd, data); -+ } -+ } -+ -+ return -ENOENT; -+} -+ -+int -+nouveau_gpuobj_mthd_call2(struct drm_device *dev, int chid, -+ u32 class, u32 mthd, u32 data) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *chan = NULL; -+ unsigned long flags; -+ int ret = -EINVAL; -+ -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); -+ 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); -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); -+ return ret; -+} - - /* NVidia uses context objects to drive drawing operations. - -@@ -73,17 +169,14 @@ - struct nouveau_gpuobj **gpuobj_ret) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_engine *engine = &dev_priv->engine; -+ struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; - struct nouveau_gpuobj *gpuobj; - struct drm_mm_node *ramin = NULL; -- int ret; -+ int ret, i; - - NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n", - chan ? chan->id : -1, size, align, flags); - -- if (!dev_priv || !gpuobj_ret || *gpuobj_ret != NULL) -- return -EINVAL; -- - gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); - if (!gpuobj) - return -ENOMEM; -@@ -98,88 +191,41 @@ - spin_unlock(&dev_priv->ramin_lock); - - if (chan) { -- NV_DEBUG(dev, "channel heap\n"); -- - ramin = drm_mm_search_free(&chan->ramin_heap, size, align, 0); - if (ramin) - ramin = drm_mm_get_block(ramin, size, align); -- - if (!ramin) { - nouveau_gpuobj_ref(NULL, &gpuobj); - return -ENOMEM; - } -- } else { -- NV_DEBUG(dev, "global heap\n"); -- -- /* allocate backing pages, sets vinst */ -- ret = engine->instmem.populate(dev, gpuobj, &size); -- if (ret) { -- nouveau_gpuobj_ref(NULL, &gpuobj); -- return ret; -- } - -- /* try and get aperture space */ -- do { -- if (drm_mm_pre_get(&dev_priv->ramin_heap)) -- return -ENOMEM; -- -- spin_lock(&dev_priv->ramin_lock); -- ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, -- align, 0); -- if (ramin == NULL) { -- spin_unlock(&dev_priv->ramin_lock); -- nouveau_gpuobj_ref(NULL, &gpuobj); -- return -ENOMEM; -- } -- -- ramin = drm_mm_get_block_atomic(ramin, size, align); -- spin_unlock(&dev_priv->ramin_lock); -- } while (ramin == NULL); -- -- /* on nv50 it's ok to fail, we have a fallback path */ -- if (!ramin && dev_priv->card_type < NV_50) { -- nouveau_gpuobj_ref(NULL, &gpuobj); -- return -ENOMEM; -- } -- } -+ gpuobj->pinst = chan->ramin->pinst; -+ if (gpuobj->pinst != ~0) -+ gpuobj->pinst += ramin->start; - -- /* if we got a chunk of the aperture, map pages into it */ -- gpuobj->im_pramin = ramin; -- if (!chan && gpuobj->im_pramin && dev_priv->ramin_available) { -- ret = engine->instmem.bind(dev, gpuobj); -+ gpuobj->cinst = ramin->start; -+ gpuobj->vinst = ramin->start + chan->ramin->vinst; -+ gpuobj->node = ramin; -+ } else { -+ ret = instmem->get(gpuobj, size, align); - if (ret) { - nouveau_gpuobj_ref(NULL, &gpuobj); - return ret; - } -- } -- -- /* calculate the various different addresses for the object */ -- if (chan) { -- gpuobj->pinst = chan->ramin->pinst; -- if (gpuobj->pinst != ~0) -- gpuobj->pinst += gpuobj->im_pramin->start; - -- if (dev_priv->card_type < NV_50) { -- gpuobj->cinst = gpuobj->pinst; -- } else { -- gpuobj->cinst = gpuobj->im_pramin->start; -- gpuobj->vinst = gpuobj->im_pramin->start + -- chan->ramin->vinst; -- } -- } else { -- if (gpuobj->im_pramin) -- gpuobj->pinst = gpuobj->im_pramin->start; -- else -+ ret = -ENOSYS; -+ if (!(flags & NVOBJ_FLAG_DONT_MAP)) -+ ret = instmem->map(gpuobj); -+ if (ret) - gpuobj->pinst = ~0; -- gpuobj->cinst = 0xdeadbeef; -+ -+ gpuobj->cinst = NVOBJ_CINST_GLOBAL; - } - - if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { -- int i; -- - for (i = 0; i < gpuobj->size; i += 4) - nv_wo32(gpuobj, i, 0); -- engine->instmem.flush(dev); -+ instmem->flush(dev); - } - - -@@ -195,6 +241,7 @@ - NV_DEBUG(dev, "\n"); - - INIT_LIST_HEAD(&dev_priv->gpuobj_list); -+ INIT_LIST_HEAD(&dev_priv->classes); - spin_lock_init(&dev_priv->ramin_lock); - dev_priv->ramin_base = ~0; - -@@ -205,9 +252,20 @@ - nouveau_gpuobj_takedown(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj_method *om, *tm; -+ struct nouveau_gpuobj_class *oc, *tc; - - NV_DEBUG(dev, "\n"); - -+ list_for_each_entry_safe(oc, tc, &dev_priv->classes, head) { -+ list_for_each_entry_safe(om, tm, &oc->methods, head) { -+ list_del(&om->head); -+ kfree(om); -+ } -+ list_del(&oc->head); -+ kfree(oc); -+ } -+ - BUG_ON(!list_empty(&dev_priv->gpuobj_list)); - } - -@@ -219,26 +277,34 @@ - container_of(ref, struct nouveau_gpuobj, refcount); - struct drm_device *dev = gpuobj->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_engine *engine = &dev_priv->engine; -+ struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; - int i; - - NV_DEBUG(dev, "gpuobj %p\n", gpuobj); - -- if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) { -+ if (gpuobj->node && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) { - for (i = 0; i < gpuobj->size; i += 4) - nv_wo32(gpuobj, i, 0); -- engine->instmem.flush(dev); -+ instmem->flush(dev); - } - - if (gpuobj->dtor) - gpuobj->dtor(dev, gpuobj); - -- if (gpuobj->im_backing) -- engine->instmem.clear(dev, gpuobj); -+ if (gpuobj->cinst == NVOBJ_CINST_GLOBAL) { -+ if (gpuobj->node) { -+ instmem->unmap(gpuobj); -+ instmem->put(gpuobj); -+ } -+ } else { -+ if (gpuobj->node) { -+ spin_lock(&dev_priv->ramin_lock); -+ drm_mm_put_block(gpuobj->node); -+ spin_unlock(&dev_priv->ramin_lock); -+ } -+ } - - spin_lock(&dev_priv->ramin_lock); -- if (gpuobj->im_pramin) -- drm_mm_put_block(gpuobj->im_pramin); - list_del(&gpuobj->list); - spin_unlock(&dev_priv->ramin_lock); - -@@ -278,7 +344,7 @@ - kref_init(&gpuobj->refcount); - gpuobj->size = size; - gpuobj->pinst = pinst; -- gpuobj->cinst = 0xdeadbeef; -+ gpuobj->cinst = NVOBJ_CINST_GLOBAL; - gpuobj->vinst = vinst; - - if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { -@@ -335,113 +401,150 @@ - The method below creates a DMA object in instance RAM and returns a handle - to it that can be used to set up context objects. - */ --int --nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, -- uint64_t offset, uint64_t size, int access, -- int target, struct nouveau_gpuobj **gpuobj) --{ -- struct drm_device *dev = chan->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; -- int ret; - -- NV_DEBUG(dev, "ch%d class=0x%04x offset=0x%llx size=0x%llx\n", -- chan->id, class, offset, size); -- NV_DEBUG(dev, "access=%d target=%d\n", access, target); -+void -+nv50_gpuobj_dma_init(struct nouveau_gpuobj *obj, u32 offset, int class, -+ u64 base, u64 size, int target, int access, -+ u32 type, u32 comp) -+{ -+ struct drm_nouveau_private *dev_priv = obj->dev->dev_private; -+ struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; -+ u32 flags0; -+ -+ flags0 = (comp << 29) | (type << 22) | class; -+ flags0 |= 0x00100000; -+ -+ switch (access) { -+ case NV_MEM_ACCESS_RO: flags0 |= 0x00040000; break; -+ case NV_MEM_ACCESS_RW: -+ case NV_MEM_ACCESS_WO: flags0 |= 0x00080000; break; -+ default: -+ break; -+ } - - switch (target) { -- case NV_DMA_TARGET_AGP: -- offset += dev_priv->gart_info.aper_base; -+ case NV_MEM_TARGET_VRAM: -+ flags0 |= 0x00010000; -+ break; -+ case NV_MEM_TARGET_PCI: -+ flags0 |= 0x00020000; -+ break; -+ case NV_MEM_TARGET_PCI_NOSNOOP: -+ flags0 |= 0x00030000; - break; -+ case NV_MEM_TARGET_GART: -+ base += dev_priv->gart_info.aper_base; - default: -+ flags0 &= ~0x00100000; - break; - } - -- ret = nouveau_gpuobj_new(dev, chan, -- nouveau_gpuobj_class_instmem_size(dev, class), -- 16, NVOBJ_FLAG_ZERO_ALLOC | -- NVOBJ_FLAG_ZERO_FREE, gpuobj); -- if (ret) { -- NV_ERROR(dev, "Error creating gpuobj: %d\n", ret); -- return ret; -- } -+ /* convert to base + limit */ -+ size = (base + size) - 1; - -- if (dev_priv->card_type < NV_50) { -- uint32_t frame, adjust, pte_flags = 0; -+ nv_wo32(obj, offset + 0x00, flags0); -+ nv_wo32(obj, offset + 0x04, lower_32_bits(size)); -+ nv_wo32(obj, offset + 0x08, lower_32_bits(base)); -+ nv_wo32(obj, offset + 0x0c, upper_32_bits(size) << 24 | -+ upper_32_bits(base)); -+ nv_wo32(obj, offset + 0x10, 0x00000000); -+ nv_wo32(obj, offset + 0x14, 0x00000000); - -- if (access != NV_DMA_ACCESS_RO) -- pte_flags |= (1<<1); -- adjust = offset & 0x00000fff; -- frame = offset & ~0x00000fff; -- -- nv_wo32(*gpuobj, 0, ((1<<12) | (1<<13) | (adjust << 20) | -- (access << 14) | (target << 16) | -- class)); -- nv_wo32(*gpuobj, 4, size - 1); -- nv_wo32(*gpuobj, 8, frame | pte_flags); -- nv_wo32(*gpuobj, 12, frame | pte_flags); -- } else { -- uint64_t limit = offset + size - 1; -- uint32_t flags0, flags5; -- -- if (target == NV_DMA_TARGET_VIDMEM) { -- flags0 = 0x00190000; -- flags5 = 0x00010000; -- } else { -- flags0 = 0x7fc00000; -- flags5 = 0x00080000; -- } -+ pinstmem->flush(obj->dev); -+} - -- nv_wo32(*gpuobj, 0, flags0 | class); -- nv_wo32(*gpuobj, 4, lower_32_bits(limit)); -- nv_wo32(*gpuobj, 8, lower_32_bits(offset)); -- nv_wo32(*gpuobj, 12, ((upper_32_bits(limit) & 0xff) << 24) | -- (upper_32_bits(offset) & 0xff)); -- nv_wo32(*gpuobj, 20, flags5); -- } -+int -+nv50_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base, u64 size, -+ int target, int access, u32 type, u32 comp, -+ struct nouveau_gpuobj **pobj) -+{ -+ struct drm_device *dev = chan->dev; -+ int ret; - -- instmem->flush(dev); -+ ret = nouveau_gpuobj_new(dev, chan, 24, 16, NVOBJ_FLAG_ZERO_FREE, pobj); -+ if (ret) -+ return ret; - -- (*gpuobj)->engine = NVOBJ_ENGINE_SW; -- (*gpuobj)->class = class; -+ nv50_gpuobj_dma_init(*pobj, 0, class, base, size, target, -+ access, type, comp); - return 0; - } - - int --nouveau_gpuobj_gart_dma_new(struct nouveau_channel *chan, -- uint64_t offset, uint64_t size, int access, -- struct nouveau_gpuobj **gpuobj, -- uint32_t *o_ret) -+nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base, -+ u64 size, int access, int target, -+ struct nouveau_gpuobj **pobj) - { -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct drm_device *dev = chan->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj *obj; -+ u32 flags0, flags2; - int ret; - -- if (dev_priv->gart_info.type == NOUVEAU_GART_AGP || -- (dev_priv->card_type >= NV_50 && -- dev_priv->gart_info.type == NOUVEAU_GART_SGDMA)) { -- ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, -- offset + dev_priv->vm_gart_base, -- size, access, NV_DMA_TARGET_AGP, -- gpuobj); -- if (o_ret) -- *o_ret = 0; -- } else -- if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA) { -- nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, gpuobj); -- if (offset & ~0xffffffffULL) { -- NV_ERROR(dev, "obj offset exceeds 32-bits\n"); -- return -EINVAL; -- } -- if (o_ret) -- *o_ret = (uint32_t)offset; -- ret = (*gpuobj != NULL) ? 0 : -EINVAL; -- } else { -- NV_ERROR(dev, "Invalid GART type %d\n", dev_priv->gart_info.type); -- return -EINVAL; -+ if (dev_priv->card_type >= NV_50) { -+ u32 comp = (target == NV_MEM_TARGET_VM) ? NV_MEM_COMP_VM : 0; -+ u32 type = (target == NV_MEM_TARGET_VM) ? NV_MEM_TYPE_VM : 0; -+ -+ return nv50_gpuobj_dma_new(chan, class, base, size, -+ target, access, type, comp, pobj); - } - -- return ret; -+ if (target == NV_MEM_TARGET_GART) { -+ if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { -+ target = NV_MEM_TARGET_PCI_NOSNOOP; -+ base += dev_priv->gart_info.aper_base; -+ } else -+ if (base != 0) { -+ base = nouveau_sgdma_get_physical(dev, base); -+ target = NV_MEM_TARGET_PCI; -+ } else { -+ nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, pobj); -+ return 0; -+ } -+ } -+ -+ flags0 = class; -+ flags0 |= 0x00003000; /* PT present, PT linear */ -+ flags2 = 0; -+ -+ switch (target) { -+ case NV_MEM_TARGET_PCI: -+ flags0 |= 0x00020000; -+ break; -+ case NV_MEM_TARGET_PCI_NOSNOOP: -+ flags0 |= 0x00030000; -+ break; -+ default: -+ break; -+ } -+ -+ switch (access) { -+ case NV_MEM_ACCESS_RO: -+ flags0 |= 0x00004000; -+ break; -+ case NV_MEM_ACCESS_WO: -+ flags0 |= 0x00008000; -+ default: -+ flags2 |= 0x00000002; -+ break; -+ } -+ -+ flags0 |= (base & 0x00000fff) << 20; -+ flags2 |= (base & 0xfffff000); -+ -+ ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj); -+ if (ret) -+ return ret; -+ -+ nv_wo32(obj, 0x00, flags0); -+ nv_wo32(obj, 0x04, size - 1); -+ nv_wo32(obj, 0x08, flags2); -+ nv_wo32(obj, 0x0c, flags2); -+ -+ obj->engine = NVOBJ_ENGINE_SW; -+ obj->class = class; -+ *pobj = obj; -+ return 0; - } - - /* Context objects in the instance RAM have the following structure. -@@ -495,82 +598,130 @@ - entry[5]: - set to 0? - */ -+static int -+nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, -+ struct nouveau_gpuobj **gpuobj_ret) -+{ -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; -+ struct nouveau_gpuobj *gpuobj; -+ -+ gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); -+ if (!gpuobj) -+ return -ENOMEM; -+ gpuobj->dev = chan->dev; -+ gpuobj->engine = NVOBJ_ENGINE_SW; -+ gpuobj->class = class; -+ kref_init(&gpuobj->refcount); -+ gpuobj->cinst = 0x40; -+ -+ spin_lock(&dev_priv->ramin_lock); -+ list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); -+ spin_unlock(&dev_priv->ramin_lock); -+ *gpuobj_ret = gpuobj; -+ return 0; -+} -+ - int --nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, -- struct nouveau_gpuobj **gpuobj) -+nouveau_gpuobj_gr_new(struct nouveau_channel *chan, u32 handle, int class) - { -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct drm_device *dev = chan->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj_class *oc; -+ struct nouveau_gpuobj *gpuobj; - int ret; - - NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class); - -+ list_for_each_entry(oc, &dev_priv->classes, head) { -+ if (oc->id == class) -+ goto found; -+ } -+ -+ NV_ERROR(dev, "illegal object class: 0x%x\n", class); -+ return -EINVAL; -+ -+found: -+ switch (oc->engine) { -+ case NVOBJ_ENGINE_SW: -+ if (dev_priv->card_type < NV_C0) { -+ ret = nouveau_gpuobj_sw_new(chan, class, &gpuobj); -+ if (ret) -+ return ret; -+ goto insert; -+ } -+ break; -+ case NVOBJ_ENGINE_GR: -+ if ((dev_priv->card_type >= NV_20 && !chan->ramin_grctx) || -+ (dev_priv->card_type < NV_20 && !chan->pgraph_ctx)) { -+ struct nouveau_pgraph_engine *pgraph = -+ &dev_priv->engine.graph; -+ -+ ret = pgraph->create_context(chan); -+ if (ret) -+ return ret; -+ } -+ break; -+ case NVOBJ_ENGINE_CRYPT: -+ if (!chan->crypt_ctx) { -+ struct nouveau_crypt_engine *pcrypt = -+ &dev_priv->engine.crypt; -+ -+ ret = pcrypt->create_context(chan); -+ if (ret) -+ return ret; -+ } -+ break; -+ } -+ -+ /* we're done if this is fermi */ -+ if (dev_priv->card_type >= NV_C0) -+ return 0; -+ - ret = nouveau_gpuobj_new(dev, chan, - nouveau_gpuobj_class_instmem_size(dev, class), - 16, - NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, -- gpuobj); -+ &gpuobj); - if (ret) { -- NV_ERROR(dev, "Error creating gpuobj: %d\n", ret); -+ NV_ERROR(dev, "error creating gpuobj: %d\n", ret); - return ret; - } - - if (dev_priv->card_type >= NV_50) { -- nv_wo32(*gpuobj, 0, class); -- nv_wo32(*gpuobj, 20, 0x00010000); -+ nv_wo32(gpuobj, 0, class); -+ nv_wo32(gpuobj, 20, 0x00010000); - } else { - switch (class) { - case NV_CLASS_NULL: -- nv_wo32(*gpuobj, 0, 0x00001030); -- nv_wo32(*gpuobj, 4, 0xFFFFFFFF); -+ nv_wo32(gpuobj, 0, 0x00001030); -+ nv_wo32(gpuobj, 4, 0xFFFFFFFF); - break; - default: - if (dev_priv->card_type >= NV_40) { -- nv_wo32(*gpuobj, 0, class); -+ nv_wo32(gpuobj, 0, class); - #ifdef __BIG_ENDIAN -- nv_wo32(*gpuobj, 8, 0x01000000); -+ nv_wo32(gpuobj, 8, 0x01000000); - #endif - } else { - #ifdef __BIG_ENDIAN -- nv_wo32(*gpuobj, 0, class | 0x00080000); -+ nv_wo32(gpuobj, 0, class | 0x00080000); - #else -- nv_wo32(*gpuobj, 0, class); -+ nv_wo32(gpuobj, 0, class); - #endif - } - } - } - dev_priv->engine.instmem.flush(dev); - -- (*gpuobj)->engine = NVOBJ_ENGINE_GR; -- (*gpuobj)->class = class; -- return 0; --} -- --int --nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, -- struct nouveau_gpuobj **gpuobj_ret) --{ -- struct drm_nouveau_private *dev_priv; -- struct nouveau_gpuobj *gpuobj; -- -- if (!chan || !gpuobj_ret || *gpuobj_ret != NULL) -- return -EINVAL; -- dev_priv = chan->dev->dev_private; -+ gpuobj->engine = oc->engine; -+ gpuobj->class = oc->id; - -- gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); -- if (!gpuobj) -- return -ENOMEM; -- gpuobj->dev = chan->dev; -- gpuobj->engine = NVOBJ_ENGINE_SW; -- gpuobj->class = class; -- kref_init(&gpuobj->refcount); -- gpuobj->cinst = 0x40; -- -- spin_lock(&dev_priv->ramin_lock); -- list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); -- spin_unlock(&dev_priv->ramin_lock); -- *gpuobj_ret = gpuobj; -- return 0; -+insert: -+ ret = nouveau_ramht_insert(chan, handle, gpuobj); -+ if (ret) -+ NV_ERROR(dev, "error adding gpuobj to RAMHT: %d\n", ret); -+ nouveau_gpuobj_ref(NULL, &gpuobj); -+ return ret; - } - - static int -@@ -585,7 +736,7 @@ - NV_DEBUG(dev, "ch%d\n", chan->id); - - /* Base amount for object storage (4KiB enough?) */ -- size = 0x1000; -+ size = 0x2000; - base = 0; - - /* PGRAPH context */ -@@ -624,12 +775,30 @@ - { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; - struct nouveau_gpuobj *vram = NULL, *tt = NULL; -- int ret, i; -+ int ret; - - NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); - -+ if (dev_priv->card_type == NV_C0) { -+ struct nouveau_vm *vm = dev_priv->chan_vm; -+ struct nouveau_vm_pgd *vpgd; -+ -+ ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0, -+ &chan->ramin); -+ if (ret) -+ return ret; -+ -+ nouveau_vm_ref(vm, &chan->vm, NULL); -+ -+ vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head); -+ nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst)); -+ nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst)); -+ nv_wo32(chan->ramin, 0x0208, 0xffffffff); -+ nv_wo32(chan->ramin, 0x020c, 0x000000ff); -+ return 0; -+ } -+ - /* Allocate a chunk of memory for per-channel object storage */ - ret = nouveau_gpuobj_channel_init_pramin(chan); - if (ret) { -@@ -639,14 +808,12 @@ - - /* NV50 VM - * - Allocate per-channel page-directory -- * - Map GART and VRAM into the channel's address space at the -- * locations determined during init. -+ * - Link with shared channel VM - */ -- if (dev_priv->card_type >= NV_50) { -+ if (dev_priv->chan_vm) { - u32 pgd_offs = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; - u64 vm_vinst = chan->ramin->vinst + pgd_offs; - u32 vm_pinst = chan->ramin->pinst; -- u32 pde; - - if (vm_pinst != ~0) - vm_pinst += pgd_offs; -@@ -655,29 +822,8 @@ - 0, &chan->vm_pd); - if (ret) - return ret; -- for (i = 0; i < 0x4000; i += 8) { -- nv_wo32(chan->vm_pd, i + 0, 0x00000000); -- nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe); -- } -- -- nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, -- &chan->vm_gart_pt); -- pde = (dev_priv->vm_gart_base / (512*1024*1024)) * 8; -- nv_wo32(chan->vm_pd, pde + 0, chan->vm_gart_pt->vinst | 3); -- nv_wo32(chan->vm_pd, pde + 4, 0x00000000); -- -- pde = (dev_priv->vm_vram_base / (512*1024*1024)) * 8; -- for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { -- nouveau_gpuobj_ref(dev_priv->vm_vram_pt[i], -- &chan->vm_vram_pt[i]); -- -- nv_wo32(chan->vm_pd, pde + 0, -- chan->vm_vram_pt[i]->vinst | 0x61); -- nv_wo32(chan->vm_pd, pde + 4, 0x00000000); -- pde += 8; -- } - -- instmem->flush(dev); -+ nouveau_vm_ref(dev_priv->chan_vm, &chan->vm, chan->vm_pd); - } - - /* RAMHT */ -@@ -700,9 +846,8 @@ - /* VRAM ctxdma */ - if (dev_priv->card_type >= NV_50) { - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, -- 0, dev_priv->vm_end, -- NV_DMA_ACCESS_RW, -- NV_DMA_TARGET_AGP, &vram); -+ 0, (1ULL << 40), NV_MEM_ACCESS_RW, -+ NV_MEM_TARGET_VM, &vram); - if (ret) { - NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret); - return ret; -@@ -710,8 +855,8 @@ - } else { - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - 0, dev_priv->fb_available_size, -- NV_DMA_ACCESS_RW, -- NV_DMA_TARGET_VIDMEM, &vram); -+ NV_MEM_ACCESS_RW, -+ NV_MEM_TARGET_VRAM, &vram); - if (ret) { - NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret); - return ret; -@@ -728,21 +873,13 @@ - /* TT memory ctxdma */ - if (dev_priv->card_type >= NV_50) { - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, -- 0, dev_priv->vm_end, -- NV_DMA_ACCESS_RW, -- NV_DMA_TARGET_AGP, &tt); -- if (ret) { -- NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret); -- return ret; -- } -- } else -- if (dev_priv->gart_info.type != NOUVEAU_GART_NONE) { -- ret = nouveau_gpuobj_gart_dma_new(chan, 0, -- dev_priv->gart_info.aper_size, -- NV_DMA_ACCESS_RW, &tt, NULL); -+ 0, (1ULL << 40), NV_MEM_ACCESS_RW, -+ NV_MEM_TARGET_VM, &tt); - } else { -- NV_ERROR(dev, "Invalid GART type %d\n", dev_priv->gart_info.type); -- ret = -EINVAL; -+ ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, -+ 0, dev_priv->gart_info.aper_size, -+ NV_MEM_ACCESS_RW, -+ NV_MEM_TARGET_GART, &tt); - } - - if (ret) { -@@ -763,21 +900,14 @@ - void - nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) - { -- struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct drm_device *dev = chan->dev; -- int i; - - NV_DEBUG(dev, "ch%d\n", chan->id); - -- if (!chan->ramht) -- return; -- - nouveau_ramht_ref(NULL, &chan->ramht, chan); - -+ nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); - nouveau_gpuobj_ref(NULL, &chan->vm_pd); -- nouveau_gpuobj_ref(NULL, &chan->vm_gart_pt); -- for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) -- nouveau_gpuobj_ref(NULL, &chan->vm_vram_pt[i]); - - if (chan->ramin_heap.free_stack.next) - drm_mm_takedown(&chan->ramin_heap); -@@ -791,147 +921,91 @@ - struct nouveau_gpuobj *gpuobj; - int i; - -- if (dev_priv->card_type < NV_50) { -- dev_priv->susres.ramin_copy = vmalloc(dev_priv->ramin_rsvd_vram); -- if (!dev_priv->susres.ramin_copy) -- return -ENOMEM; -- -- for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4) -- dev_priv->susres.ramin_copy[i/4] = nv_ri32(dev, i); -- return 0; -- } -- - list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) { -- if (!gpuobj->im_backing) -+ if (gpuobj->cinst != NVOBJ_CINST_GLOBAL) - continue; - -- gpuobj->im_backing_suspend = vmalloc(gpuobj->size); -- if (!gpuobj->im_backing_suspend) { -+ gpuobj->suspend = vmalloc(gpuobj->size); -+ if (!gpuobj->suspend) { - nouveau_gpuobj_resume(dev); - return -ENOMEM; - } - - for (i = 0; i < gpuobj->size; i += 4) -- gpuobj->im_backing_suspend[i/4] = nv_ro32(gpuobj, i); -+ gpuobj->suspend[i/4] = nv_ro32(gpuobj, i); - } - - return 0; - } - - void --nouveau_gpuobj_suspend_cleanup(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *gpuobj; -- -- if (dev_priv->card_type < NV_50) { -- vfree(dev_priv->susres.ramin_copy); -- dev_priv->susres.ramin_copy = NULL; -- return; -- } -- -- list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) { -- if (!gpuobj->im_backing_suspend) -- continue; -- -- vfree(gpuobj->im_backing_suspend); -- gpuobj->im_backing_suspend = NULL; -- } --} -- --void - nouveau_gpuobj_resume(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gpuobj; - int i; - -- if (dev_priv->card_type < NV_50) { -- for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4) -- nv_wi32(dev, i, dev_priv->susres.ramin_copy[i/4]); -- nouveau_gpuobj_suspend_cleanup(dev); -- return; -- } -- - list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) { -- if (!gpuobj->im_backing_suspend) -+ if (!gpuobj->suspend) - continue; - - for (i = 0; i < gpuobj->size; i += 4) -- nv_wo32(gpuobj, i, gpuobj->im_backing_suspend[i/4]); -- dev_priv->engine.instmem.flush(dev); -+ nv_wo32(gpuobj, i, gpuobj->suspend[i/4]); -+ -+ vfree(gpuobj->suspend); -+ gpuobj->suspend = NULL; - } - -- nouveau_gpuobj_suspend_cleanup(dev); -+ dev_priv->engine.instmem.flush(dev); - } - - int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, - struct drm_file *file_priv) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; - struct drm_nouveau_grobj_alloc *init = data; -- struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -- struct nouveau_pgraph_object_class *grc; -- struct nouveau_gpuobj *gr = NULL; - struct nouveau_channel *chan; - int ret; - -- NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan); -- - if (init->handle == ~0) - return -EINVAL; - -- grc = pgraph->grclass; -- while (grc->id) { -- if (grc->id == init->class) -- break; -- grc++; -- } -+ chan = nouveau_channel_get(dev, file_priv, init->channel); -+ if (IS_ERR(chan)) -+ return PTR_ERR(chan); - -- if (!grc->id) { -- NV_ERROR(dev, "Illegal object class: 0x%x\n", init->class); -- return -EPERM; -+ if (nouveau_ramht_find(chan, init->handle)) { -+ ret = -EEXIST; -+ goto out; - } - -- if (nouveau_ramht_find(chan, init->handle)) -- return -EEXIST; -- -- if (!grc->software) -- ret = nouveau_gpuobj_gr_new(chan, grc->id, &gr); -- else -- ret = nouveau_gpuobj_sw_new(chan, grc->id, &gr); -+ ret = nouveau_gpuobj_gr_new(chan, init->handle, init->class); - if (ret) { - NV_ERROR(dev, "Error creating object: %d (%d/0x%08x)\n", - ret, init->channel, init->handle); -- return ret; - } - -- ret = nouveau_ramht_insert(chan, init->handle, gr); -- nouveau_gpuobj_ref(NULL, &gr); -- if (ret) { -- NV_ERROR(dev, "Error referencing object: %d (%d/0x%08x)\n", -- ret, init->channel, init->handle); -- return ret; -- } -- -- return 0; -+out: -+ nouveau_channel_put(&chan); -+ return ret; - } - - int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data, - struct drm_file *file_priv) - { - struct drm_nouveau_gpuobj_free *objfree = data; -- struct nouveau_gpuobj *gpuobj; - struct nouveau_channel *chan; -+ int ret; - -- NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan); -+ chan = nouveau_channel_get(dev, file_priv, objfree->channel); -+ if (IS_ERR(chan)) -+ return PTR_ERR(chan); - -- gpuobj = nouveau_ramht_find(chan, objfree->handle); -- if (!gpuobj) -- return -ENOENT; -+ /* Synchronize with the user channel */ -+ nouveau_channel_idle(chan); - -- nouveau_ramht_remove(chan, objfree->handle); -- return 0; -+ ret = nouveau_ramht_remove(chan, objfree->handle); -+ nouveau_channel_put(&chan); -+ return ret; - } - - u32 -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_pm.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_pm.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_pm.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_pm.c 2011-01-07 14:22:17.000000000 +0100 -@@ -27,6 +27,10 @@ - #include "nouveau_drv.h" - #include "nouveau_pm.h" - -+#ifdef CONFIG_ACPI -+#include -+#endif -+#include - #include - #include - -@@ -418,8 +422,7 @@ - return ret; - } - dev_set_drvdata(hwmon_dev, dev); -- ret = sysfs_create_group(&hwmon_dev->kobj, -- &hwmon_attrgroup); -+ ret = sysfs_create_group(&dev->pdev->dev.kobj, &hwmon_attrgroup); - if (ret) { - NV_ERROR(dev, - "Unable to create hwmon sysfs file: %d\n", ret); -@@ -446,6 +449,25 @@ - #endif - } - -+#ifdef CONFIG_ACPI -+static int -+nouveau_pm_acpi_event(struct notifier_block *nb, unsigned long val, void *data) -+{ -+ struct drm_nouveau_private *dev_priv = -+ container_of(nb, struct drm_nouveau_private, engine.pm.acpi_nb); -+ struct drm_device *dev = dev_priv->dev; -+ struct acpi_bus_event *entry = (struct acpi_bus_event *)data; -+ -+ if (strcmp(entry->device_class, "ac_adapter") == 0) { -+ bool ac = power_supply_is_system_supplied(); -+ -+ NV_DEBUG(dev, "power supply changed: %s\n", ac ? "AC" : "DC"); -+ } -+ -+ return NOTIFY_OK; -+} -+#endif -+ - int - nouveau_pm_init(struct drm_device *dev) - { -@@ -485,6 +507,10 @@ - - nouveau_sysfs_init(dev); - nouveau_hwmon_init(dev); -+#ifdef CONFIG_ACPI -+ pm->acpi_nb.notifier_call = nouveau_pm_acpi_event; -+ register_acpi_notifier(&pm->acpi_nb); -+#endif - - return 0; - } -@@ -503,6 +529,9 @@ - nouveau_perf_fini(dev); - nouveau_volt_fini(dev); - -+#ifdef CONFIG_ACPI -+ unregister_acpi_notifier(&pm->acpi_nb); -+#endif - nouveau_hwmon_fini(dev); - nouveau_sysfs_fini(dev); - } -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_ramht.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_ramht.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_ramht.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_ramht.c 2011-01-07 14:22:17.000000000 +0100 -@@ -104,17 +104,17 @@ - nouveau_gpuobj_ref(gpuobj, &entry->gpuobj); - - if (dev_priv->card_type < NV_40) { -- ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->cinst >> 4) | -+ ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->pinst >> 4) | - (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | - (gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT); - } else - if (dev_priv->card_type < NV_50) { -- ctx = (gpuobj->cinst >> 4) | -+ ctx = (gpuobj->pinst >> 4) | - (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | - (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); - } else { - if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { -- ctx = (gpuobj->cinst << 10) | 2; -+ ctx = (gpuobj->cinst << 10) | chan->id; - } else { - ctx = (gpuobj->cinst >> 4) | - ((gpuobj->engine << -@@ -214,18 +214,19 @@ - spin_unlock_irqrestore(&chan->ramht->lock, flags); - } - --void -+int - nouveau_ramht_remove(struct nouveau_channel *chan, u32 handle) - { - struct nouveau_ramht_entry *entry; - - entry = nouveau_ramht_remove_entry(chan, handle); - if (!entry) -- return; -+ return -ENOENT; - - nouveau_ramht_remove_hash(chan, entry->handle); - nouveau_gpuobj_ref(NULL, &entry->gpuobj); - kfree(entry); -+ return 0; - } - - struct nouveau_gpuobj * -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_ramht.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_ramht.h ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_ramht.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_ramht.h 2011-01-07 14:22:17.000000000 +0100 -@@ -48,7 +48,7 @@ - - extern int nouveau_ramht_insert(struct nouveau_channel *, u32 handle, - struct nouveau_gpuobj *); --extern void nouveau_ramht_remove(struct nouveau_channel *, u32 handle); -+extern int nouveau_ramht_remove(struct nouveau_channel *, u32 handle); - extern struct nouveau_gpuobj * - nouveau_ramht_find(struct nouveau_channel *chan, u32 handle); - -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_reg.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_reg.h ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_reg.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_reg.h 2011-01-07 14:22:17.000000000 +0100 -@@ -45,6 +45,11 @@ - # define NV04_PFB_REF_CMD_REFRESH (1 << 0) - #define NV04_PFB_PRE 0x001002d4 - # define NV04_PFB_PRE_CMD_PRECHARGE (1 << 0) -+#define NV20_PFB_ZCOMP(i) (0x00100300 + 4*(i)) -+# define NV20_PFB_ZCOMP_MODE_32 (4 << 24) -+# define NV20_PFB_ZCOMP_EN (1 << 31) -+# define NV25_PFB_ZCOMP_MODE_16 (1 << 20) -+# define NV25_PFB_ZCOMP_MODE_32 (2 << 20) - #define NV10_PFB_CLOSE_PAGE2 0x0010033c - #define NV04_PFB_SCRAMBLE(i) (0x00100400 + 4 * (i)) - #define NV40_PFB_TILE(i) (0x00100600 + (i*16)) -@@ -74,17 +79,6 @@ - # define NV40_RAMHT_CONTEXT_ENGINE_SHIFT 20 - # define NV40_RAMHT_CONTEXT_INSTANCE_SHIFT 0 - --/* DMA object defines */ --#define NV_DMA_ACCESS_RW 0 --#define NV_DMA_ACCESS_RO 1 --#define NV_DMA_ACCESS_WO 2 --#define NV_DMA_TARGET_VIDMEM 0 --#define NV_DMA_TARGET_PCI 2 --#define NV_DMA_TARGET_AGP 3 --/* The following is not a real value used by the card, it's changed by -- * nouveau_object_dma_create */ --#define NV_DMA_TARGET_PCI_NONLINEAR 8 -- - /* Some object classes we care about in the drm */ - #define NV_CLASS_DMA_FROM_MEMORY 0x00000002 - #define NV_CLASS_DMA_TO_MEMORY 0x00000003 -@@ -332,6 +326,7 @@ - #define NV04_PGRAPH_BSWIZZLE5 0x004006A0 - #define NV03_PGRAPH_STATUS 0x004006B0 - #define NV04_PGRAPH_STATUS 0x00400700 -+# define NV40_PGRAPH_STATUS_SYNC_STALL 0x00004000 - #define NV04_PGRAPH_TRAPPED_ADDR 0x00400704 - #define NV04_PGRAPH_TRAPPED_DATA 0x00400708 - #define NV04_PGRAPH_SURFACE 0x0040070C -@@ -378,6 +373,7 @@ - #define NV20_PGRAPH_TLIMIT(i) (0x00400904 + (i*16)) - #define NV20_PGRAPH_TSIZE(i) (0x00400908 + (i*16)) - #define NV20_PGRAPH_TSTATUS(i) (0x0040090C + (i*16)) -+#define NV20_PGRAPH_ZCOMP(i) (0x00400980 + 4*(i)) - #define NV10_PGRAPH_TILE(i) (0x00400B00 + (i*16)) - #define NV10_PGRAPH_TLIMIT(i) (0x00400B04 + (i*16)) - #define NV10_PGRAPH_TSIZE(i) (0x00400B08 + (i*16)) -@@ -714,31 +710,32 @@ - #define NV50_PDISPLAY_INTR_1_CLK_UNK10 0x00000010 - #define NV50_PDISPLAY_INTR_1_CLK_UNK20 0x00000020 - #define NV50_PDISPLAY_INTR_1_CLK_UNK40 0x00000040 --#define NV50_PDISPLAY_INTR_EN 0x0061002c --#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC 0x0000000c --#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(n) (1 << ((n) + 2)) --#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_0 0x00000004 --#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_1 0x00000008 --#define NV50_PDISPLAY_INTR_EN_CLK_UNK10 0x00000010 --#define NV50_PDISPLAY_INTR_EN_CLK_UNK20 0x00000020 --#define NV50_PDISPLAY_INTR_EN_CLK_UNK40 0x00000040 -+#define NV50_PDISPLAY_INTR_EN_0 0x00610028 -+#define NV50_PDISPLAY_INTR_EN_1 0x0061002c -+#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC 0x0000000c -+#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(n) (1 << ((n) + 2)) -+#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_0 0x00000004 -+#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_1 0x00000008 -+#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 0x00000010 -+#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 0x00000020 -+#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK40 0x00000040 - #define NV50_PDISPLAY_UNK30_CTRL 0x00610030 - #define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK0 0x00000200 - #define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK1 0x00000400 - #define NV50_PDISPLAY_UNK30_CTRL_PENDING 0x80000000 --#define NV50_PDISPLAY_TRAPPED_ADDR 0x00610080 --#define NV50_PDISPLAY_TRAPPED_DATA 0x00610084 --#define NV50_PDISPLAY_CHANNEL_STAT(i) ((i) * 0x10 + 0x00610200) --#define NV50_PDISPLAY_CHANNEL_STAT_DMA 0x00000010 --#define NV50_PDISPLAY_CHANNEL_STAT_DMA_DISABLED 0x00000000 --#define NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED 0x00000010 --#define NV50_PDISPLAY_CHANNEL_DMA_CB(i) ((i) * 0x10 + 0x00610204) --#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION 0x00000002 --#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM 0x00000000 --#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_SYSTEM 0x00000002 --#define NV50_PDISPLAY_CHANNEL_DMA_CB_VALID 0x00000001 --#define NV50_PDISPLAY_CHANNEL_UNK2(i) ((i) * 0x10 + 0x00610208) --#define NV50_PDISPLAY_CHANNEL_UNK3(i) ((i) * 0x10 + 0x0061020c) -+#define NV50_PDISPLAY_TRAPPED_ADDR(i) ((i) * 0x08 + 0x00610080) -+#define NV50_PDISPLAY_TRAPPED_DATA(i) ((i) * 0x08 + 0x00610084) -+#define NV50_PDISPLAY_EVO_CTRL(i) ((i) * 0x10 + 0x00610200) -+#define NV50_PDISPLAY_EVO_CTRL_DMA 0x00000010 -+#define NV50_PDISPLAY_EVO_CTRL_DMA_DISABLED 0x00000000 -+#define NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED 0x00000010 -+#define NV50_PDISPLAY_EVO_DMA_CB(i) ((i) * 0x10 + 0x00610204) -+#define NV50_PDISPLAY_EVO_DMA_CB_LOCATION 0x00000002 -+#define NV50_PDISPLAY_EVO_DMA_CB_LOCATION_VRAM 0x00000000 -+#define NV50_PDISPLAY_EVO_DMA_CB_LOCATION_SYSTEM 0x00000002 -+#define NV50_PDISPLAY_EVO_DMA_CB_VALID 0x00000001 -+#define NV50_PDISPLAY_EVO_UNK2(i) ((i) * 0x10 + 0x00610208) -+#define NV50_PDISPLAY_EVO_HASH_TAG(i) ((i) * 0x10 + 0x0061020c) - - #define NV50_PDISPLAY_CURSOR 0x00610270 - #define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i) ((i) * 0x10 + 0x00610270) -@@ -746,15 +743,11 @@ - #define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS 0x00030000 - #define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE 0x00010000 - --#define NV50_PDISPLAY_CTRL_STATE 0x00610300 --#define NV50_PDISPLAY_CTRL_STATE_PENDING 0x80000000 --#define NV50_PDISPLAY_CTRL_STATE_METHOD 0x00001ffc --#define NV50_PDISPLAY_CTRL_STATE_ENABLE 0x00000001 --#define NV50_PDISPLAY_CTRL_VAL 0x00610304 --#define NV50_PDISPLAY_UNK_380 0x00610380 --#define NV50_PDISPLAY_RAM_AMOUNT 0x00610384 --#define NV50_PDISPLAY_UNK_388 0x00610388 --#define NV50_PDISPLAY_UNK_38C 0x0061038c -+#define NV50_PDISPLAY_PIO_CTRL 0x00610300 -+#define NV50_PDISPLAY_PIO_CTRL_PENDING 0x80000000 -+#define NV50_PDISPLAY_PIO_CTRL_MTHD 0x00001ffc -+#define NV50_PDISPLAY_PIO_CTRL_ENABLED 0x00000001 -+#define NV50_PDISPLAY_PIO_DATA 0x00610304 - - #define NV50_PDISPLAY_CRTC_P(i, r) ((i) * 0x540 + NV50_PDISPLAY_CRTC_##r) - #define NV50_PDISPLAY_CRTC_C(i, r) (4 + (i) * 0x540 + NV50_PDISPLAY_CRTC_##r) -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_sgdma.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2011-01-07 14:22:17.000000000 +0100 -@@ -14,7 +14,7 @@ - dma_addr_t *pages; - unsigned nr_pages; - -- unsigned pte_start; -+ u64 offset; - bool bound; - }; - -@@ -74,18 +74,6 @@ - } - } - --static inline unsigned --nouveau_sgdma_pte(struct drm_device *dev, uint64_t offset) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- unsigned pte = (offset >> NV_CTXDMA_PAGE_SHIFT); -- -- if (dev_priv->card_type < NV_50) -- return pte + 2; -- -- return pte << 1; --} -- - static int - nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) - { -@@ -97,32 +85,17 @@ - - NV_DEBUG(dev, "pg=0x%lx\n", mem->start); - -- pte = nouveau_sgdma_pte(nvbe->dev, mem->start << PAGE_SHIFT); -- nvbe->pte_start = pte; -+ nvbe->offset = mem->start << PAGE_SHIFT; -+ pte = (nvbe->offset >> NV_CTXDMA_PAGE_SHIFT) + 2; - for (i = 0; i < nvbe->nr_pages; i++) { - dma_addr_t dma_offset = nvbe->pages[i]; - uint32_t offset_l = lower_32_bits(dma_offset); -- uint32_t offset_h = upper_32_bits(dma_offset); -- -- for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) { -- if (dev_priv->card_type < NV_50) { -- nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 3); -- pte += 1; -- } else { -- nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 0x21); -- nv_wo32(gpuobj, (pte * 4) + 4, offset_h & 0xff); -- pte += 2; -- } - -+ for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++, pte++) { -+ nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 3); - dma_offset += NV_CTXDMA_PAGE_SIZE; - } - } -- dev_priv->engine.instmem.flush(nvbe->dev); -- -- if (dev_priv->card_type == NV_50) { -- dev_priv->engine.fifo.tlb_flush(dev); -- dev_priv->engine.graph.tlb_flush(dev); -- } - - nvbe->bound = true; - return 0; -@@ -142,28 +115,10 @@ - if (!nvbe->bound) - return 0; - -- pte = nvbe->pte_start; -+ pte = (nvbe->offset >> NV_CTXDMA_PAGE_SHIFT) + 2; - for (i = 0; i < nvbe->nr_pages; i++) { -- dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus; -- -- for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) { -- if (dev_priv->card_type < NV_50) { -- nv_wo32(gpuobj, (pte * 4) + 0, dma_offset | 3); -- pte += 1; -- } else { -- nv_wo32(gpuobj, (pte * 4) + 0, 0x00000000); -- nv_wo32(gpuobj, (pte * 4) + 4, 0x00000000); -- pte += 2; -- } -- -- dma_offset += NV_CTXDMA_PAGE_SIZE; -- } -- } -- dev_priv->engine.instmem.flush(nvbe->dev); -- -- if (dev_priv->card_type == NV_50) { -- dev_priv->engine.fifo.tlb_flush(dev); -- dev_priv->engine.graph.tlb_flush(dev); -+ for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++, pte++) -+ nv_wo32(gpuobj, (pte * 4) + 0, 0x00000000); - } - - nvbe->bound = false; -@@ -186,6 +141,35 @@ - } - } - -+static int -+nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) -+{ -+ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; -+ struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; -+ -+ nvbe->offset = mem->start << PAGE_SHIFT; -+ -+ nouveau_vm_map_sg(&dev_priv->gart_info.vma, nvbe->offset, -+ nvbe->nr_pages << PAGE_SHIFT, nvbe->pages); -+ nvbe->bound = true; -+ return 0; -+} -+ -+static int -+nv50_sgdma_unbind(struct ttm_backend *be) -+{ -+ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; -+ struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; -+ -+ if (!nvbe->bound) -+ return 0; -+ -+ nouveau_vm_unmap_at(&dev_priv->gart_info.vma, nvbe->offset, -+ nvbe->nr_pages << PAGE_SHIFT); -+ nvbe->bound = false; -+ return 0; -+} -+ - static struct ttm_backend_func nouveau_sgdma_backend = { - .populate = nouveau_sgdma_populate, - .clear = nouveau_sgdma_clear, -@@ -194,23 +178,30 @@ - .destroy = nouveau_sgdma_destroy - }; - -+static struct ttm_backend_func nv50_sgdma_backend = { -+ .populate = nouveau_sgdma_populate, -+ .clear = nouveau_sgdma_clear, -+ .bind = nv50_sgdma_bind, -+ .unbind = nv50_sgdma_unbind, -+ .destroy = nouveau_sgdma_destroy -+}; -+ - struct ttm_backend * - nouveau_sgdma_init_ttm(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_sgdma_be *nvbe; - -- if (!dev_priv->gart_info.sg_ctxdma) -- return NULL; -- - nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL); - if (!nvbe) - return NULL; - - nvbe->dev = dev; - -- nvbe->backend.func = &nouveau_sgdma_backend; -- -+ if (dev_priv->card_type < NV_50) -+ nvbe->backend.func = &nouveau_sgdma_backend; -+ else -+ nvbe->backend.func = &nv50_sgdma_backend; - return &nvbe->backend; - } - -@@ -218,7 +209,6 @@ - nouveau_sgdma_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct pci_dev *pdev = dev->pdev; - struct nouveau_gpuobj *gpuobj = NULL; - uint32_t aper_size, obj_size; - int i, ret; -@@ -231,68 +221,40 @@ - - obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4; - obj_size += 8; /* ctxdma header */ -- } else { -- /* 1 entire VM page table */ -- aper_size = (512 * 1024 * 1024); -- obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 8; -- } -- -- ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, -- NVOBJ_FLAG_ZERO_ALLOC | -- NVOBJ_FLAG_ZERO_FREE, &gpuobj); -- if (ret) { -- NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); -- return ret; -- } - -- dev_priv->gart_info.sg_dummy_page = -- alloc_page(GFP_KERNEL|__GFP_DMA32|__GFP_ZERO); -- if (!dev_priv->gart_info.sg_dummy_page) { -- nouveau_gpuobj_ref(NULL, &gpuobj); -- return -ENOMEM; -- } -- -- set_bit(PG_locked, &dev_priv->gart_info.sg_dummy_page->flags); -- dev_priv->gart_info.sg_dummy_bus = -- pci_map_page(pdev, dev_priv->gart_info.sg_dummy_page, 0, -- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); -- if (pci_dma_mapping_error(pdev, dev_priv->gart_info.sg_dummy_bus)) { -- nouveau_gpuobj_ref(NULL, &gpuobj); -- return -EFAULT; -- } -+ ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, -+ NVOBJ_FLAG_ZERO_ALLOC | -+ NVOBJ_FLAG_ZERO_FREE, &gpuobj); -+ if (ret) { -+ NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); -+ return ret; -+ } - -- if (dev_priv->card_type < NV_50) { -- /* special case, allocated from global instmem heap so -- * cinst is invalid, we use it on all channels though so -- * cinst needs to be valid, set it the same as pinst -- */ -- gpuobj->cinst = gpuobj->pinst; -- -- /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and -- * confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE -- * on those cards? */ - nv_wo32(gpuobj, 0, NV_CLASS_DMA_IN_MEMORY | - (1 << 12) /* PT present */ | - (0 << 13) /* PT *not* linear */ | -- (NV_DMA_ACCESS_RW << 14) | -- (NV_DMA_TARGET_PCI << 16)); -+ (0 << 14) /* RW */ | -+ (2 << 16) /* PCI */); - nv_wo32(gpuobj, 4, aper_size - 1); -- for (i = 2; i < 2 + (aper_size >> 12); i++) { -- nv_wo32(gpuobj, i * 4, -- dev_priv->gart_info.sg_dummy_bus | 3); -- } -- } else { -- for (i = 0; i < obj_size; i += 8) { -- nv_wo32(gpuobj, i + 0, 0x00000000); -- nv_wo32(gpuobj, i + 4, 0x00000000); -- } -+ for (i = 2; i < 2 + (aper_size >> 12); i++) -+ nv_wo32(gpuobj, i * 4, 0x00000000); -+ -+ dev_priv->gart_info.sg_ctxdma = gpuobj; -+ dev_priv->gart_info.aper_base = 0; -+ dev_priv->gart_info.aper_size = aper_size; -+ } else -+ if (dev_priv->chan_vm) { -+ ret = nouveau_vm_get(dev_priv->chan_vm, 512 * 1024 * 1024, -+ 12, NV_MEM_ACCESS_RW, -+ &dev_priv->gart_info.vma); -+ if (ret) -+ return ret; -+ -+ dev_priv->gart_info.aper_base = dev_priv->gart_info.vma.offset; -+ dev_priv->gart_info.aper_size = 512 * 1024 * 1024; - } -- dev_priv->engine.instmem.flush(dev); - - dev_priv->gart_info.type = NOUVEAU_GART_SGDMA; -- dev_priv->gart_info.aper_base = 0; -- dev_priv->gart_info.aper_size = aper_size; -- dev_priv->gart_info.sg_ctxdma = gpuobj; - return 0; - } - -@@ -301,31 +263,19 @@ - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - -- if (dev_priv->gart_info.sg_dummy_page) { -- pci_unmap_page(dev->pdev, dev_priv->gart_info.sg_dummy_bus, -- NV_CTXDMA_PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); -- unlock_page(dev_priv->gart_info.sg_dummy_page); -- __free_page(dev_priv->gart_info.sg_dummy_page); -- dev_priv->gart_info.sg_dummy_page = NULL; -- dev_priv->gart_info.sg_dummy_bus = 0; -- } -- - nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma); -+ nouveau_vm_put(&dev_priv->gart_info.vma); - } - --int --nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page) -+uint32_t -+nouveau_sgdma_get_physical(struct drm_device *dev, uint32_t offset) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; -- int pte; -+ int pte = (offset >> NV_CTXDMA_PAGE_SHIFT) + 2; - -- pte = (offset >> NV_CTXDMA_PAGE_SHIFT) << 2; -- if (dev_priv->card_type < NV_50) { -- *page = nv_ro32(gpuobj, (pte + 8)) & ~NV_CTXDMA_PAGE_MASK; -- return 0; -- } -+ BUG_ON(dev_priv->card_type >= NV_50); - -- NV_ERROR(dev, "Unimplemented on NV50\n"); -- return -EINVAL; -+ return (nv_ro32(gpuobj, 4 * pte) & ~NV_CTXDMA_PAGE_MASK) | -+ (offset & NV_CTXDMA_PAGE_MASK); - } -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_state.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_state.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_state.c 2011-01-07 14:22:17.000000000 +0100 -@@ -53,10 +53,10 @@ - engine->instmem.takedown = nv04_instmem_takedown; - engine->instmem.suspend = nv04_instmem_suspend; - engine->instmem.resume = nv04_instmem_resume; -- engine->instmem.populate = nv04_instmem_populate; -- engine->instmem.clear = nv04_instmem_clear; -- engine->instmem.bind = nv04_instmem_bind; -- engine->instmem.unbind = nv04_instmem_unbind; -+ engine->instmem.get = nv04_instmem_get; -+ engine->instmem.put = nv04_instmem_put; -+ engine->instmem.map = nv04_instmem_map; -+ engine->instmem.unmap = nv04_instmem_unmap; - engine->instmem.flush = nv04_instmem_flush; - engine->mc.init = nv04_mc_init; - engine->mc.takedown = nv04_mc_takedown; -@@ -65,7 +65,6 @@ - engine->timer.takedown = nv04_timer_takedown; - engine->fb.init = nv04_fb_init; - engine->fb.takedown = nv04_fb_takedown; -- engine->graph.grclass = nv04_graph_grclass; - engine->graph.init = nv04_graph_init; - engine->graph.takedown = nv04_graph_takedown; - engine->graph.fifo_access = nv04_graph_fifo_access; -@@ -76,7 +75,7 @@ - engine->graph.unload_context = nv04_graph_unload_context; - engine->fifo.channels = 16; - engine->fifo.init = nv04_fifo_init; -- engine->fifo.takedown = nouveau_stub_takedown; -+ engine->fifo.takedown = nv04_fifo_fini; - engine->fifo.disable = nv04_fifo_disable; - engine->fifo.enable = nv04_fifo_enable; - engine->fifo.reassign = nv04_fifo_reassign; -@@ -99,16 +98,20 @@ - engine->pm.clock_get = nv04_pm_clock_get; - engine->pm.clock_pre = nv04_pm_clock_pre; - engine->pm.clock_set = nv04_pm_clock_set; -+ engine->crypt.init = nouveau_stub_init; -+ engine->crypt.takedown = nouveau_stub_takedown; -+ engine->vram.init = nouveau_mem_detect; -+ engine->vram.flags_valid = nouveau_mem_flags_valid; - break; - case 0x10: - engine->instmem.init = nv04_instmem_init; - engine->instmem.takedown = nv04_instmem_takedown; - engine->instmem.suspend = nv04_instmem_suspend; - engine->instmem.resume = nv04_instmem_resume; -- engine->instmem.populate = nv04_instmem_populate; -- engine->instmem.clear = nv04_instmem_clear; -- engine->instmem.bind = nv04_instmem_bind; -- engine->instmem.unbind = nv04_instmem_unbind; -+ engine->instmem.get = nv04_instmem_get; -+ engine->instmem.put = nv04_instmem_put; -+ engine->instmem.map = nv04_instmem_map; -+ engine->instmem.unmap = nv04_instmem_unmap; - engine->instmem.flush = nv04_instmem_flush; - engine->mc.init = nv04_mc_init; - engine->mc.takedown = nv04_mc_takedown; -@@ -117,8 +120,9 @@ - engine->timer.takedown = nv04_timer_takedown; - engine->fb.init = nv10_fb_init; - engine->fb.takedown = nv10_fb_takedown; -- engine->fb.set_region_tiling = nv10_fb_set_region_tiling; -- engine->graph.grclass = nv10_graph_grclass; -+ engine->fb.init_tile_region = nv10_fb_init_tile_region; -+ engine->fb.set_tile_region = nv10_fb_set_tile_region; -+ engine->fb.free_tile_region = nv10_fb_free_tile_region; - engine->graph.init = nv10_graph_init; - engine->graph.takedown = nv10_graph_takedown; - engine->graph.channel = nv10_graph_channel; -@@ -127,17 +131,17 @@ - engine->graph.fifo_access = nv04_graph_fifo_access; - engine->graph.load_context = nv10_graph_load_context; - engine->graph.unload_context = nv10_graph_unload_context; -- engine->graph.set_region_tiling = nv10_graph_set_region_tiling; -+ engine->graph.set_tile_region = nv10_graph_set_tile_region; - engine->fifo.channels = 32; - engine->fifo.init = nv10_fifo_init; -- engine->fifo.takedown = nouveau_stub_takedown; -+ engine->fifo.takedown = nv04_fifo_fini; - engine->fifo.disable = nv04_fifo_disable; - engine->fifo.enable = nv04_fifo_enable; - engine->fifo.reassign = nv04_fifo_reassign; - engine->fifo.cache_pull = nv04_fifo_cache_pull; - engine->fifo.channel_id = nv10_fifo_channel_id; - engine->fifo.create_context = nv10_fifo_create_context; -- engine->fifo.destroy_context = nv10_fifo_destroy_context; -+ engine->fifo.destroy_context = nv04_fifo_destroy_context; - engine->fifo.load_context = nv10_fifo_load_context; - engine->fifo.unload_context = nv10_fifo_unload_context; - engine->display.early_init = nv04_display_early_init; -@@ -153,16 +157,20 @@ - engine->pm.clock_get = nv04_pm_clock_get; - engine->pm.clock_pre = nv04_pm_clock_pre; - engine->pm.clock_set = nv04_pm_clock_set; -+ engine->crypt.init = nouveau_stub_init; -+ engine->crypt.takedown = nouveau_stub_takedown; -+ engine->vram.init = nouveau_mem_detect; -+ engine->vram.flags_valid = nouveau_mem_flags_valid; - break; - case 0x20: - engine->instmem.init = nv04_instmem_init; - engine->instmem.takedown = nv04_instmem_takedown; - engine->instmem.suspend = nv04_instmem_suspend; - engine->instmem.resume = nv04_instmem_resume; -- engine->instmem.populate = nv04_instmem_populate; -- engine->instmem.clear = nv04_instmem_clear; -- engine->instmem.bind = nv04_instmem_bind; -- engine->instmem.unbind = nv04_instmem_unbind; -+ engine->instmem.get = nv04_instmem_get; -+ engine->instmem.put = nv04_instmem_put; -+ engine->instmem.map = nv04_instmem_map; -+ engine->instmem.unmap = nv04_instmem_unmap; - engine->instmem.flush = nv04_instmem_flush; - engine->mc.init = nv04_mc_init; - engine->mc.takedown = nv04_mc_takedown; -@@ -171,8 +179,9 @@ - engine->timer.takedown = nv04_timer_takedown; - engine->fb.init = nv10_fb_init; - engine->fb.takedown = nv10_fb_takedown; -- engine->fb.set_region_tiling = nv10_fb_set_region_tiling; -- engine->graph.grclass = nv20_graph_grclass; -+ engine->fb.init_tile_region = nv10_fb_init_tile_region; -+ engine->fb.set_tile_region = nv10_fb_set_tile_region; -+ engine->fb.free_tile_region = nv10_fb_free_tile_region; - engine->graph.init = nv20_graph_init; - engine->graph.takedown = nv20_graph_takedown; - engine->graph.channel = nv10_graph_channel; -@@ -181,17 +190,17 @@ - engine->graph.fifo_access = nv04_graph_fifo_access; - engine->graph.load_context = nv20_graph_load_context; - engine->graph.unload_context = nv20_graph_unload_context; -- engine->graph.set_region_tiling = nv20_graph_set_region_tiling; -+ engine->graph.set_tile_region = nv20_graph_set_tile_region; - engine->fifo.channels = 32; - engine->fifo.init = nv10_fifo_init; -- engine->fifo.takedown = nouveau_stub_takedown; -+ engine->fifo.takedown = nv04_fifo_fini; - engine->fifo.disable = nv04_fifo_disable; - engine->fifo.enable = nv04_fifo_enable; - engine->fifo.reassign = nv04_fifo_reassign; - engine->fifo.cache_pull = nv04_fifo_cache_pull; - engine->fifo.channel_id = nv10_fifo_channel_id; - engine->fifo.create_context = nv10_fifo_create_context; -- engine->fifo.destroy_context = nv10_fifo_destroy_context; -+ engine->fifo.destroy_context = nv04_fifo_destroy_context; - engine->fifo.load_context = nv10_fifo_load_context; - engine->fifo.unload_context = nv10_fifo_unload_context; - engine->display.early_init = nv04_display_early_init; -@@ -207,16 +216,20 @@ - engine->pm.clock_get = nv04_pm_clock_get; - engine->pm.clock_pre = nv04_pm_clock_pre; - engine->pm.clock_set = nv04_pm_clock_set; -+ engine->crypt.init = nouveau_stub_init; -+ engine->crypt.takedown = nouveau_stub_takedown; -+ engine->vram.init = nouveau_mem_detect; -+ engine->vram.flags_valid = nouveau_mem_flags_valid; - break; - case 0x30: - engine->instmem.init = nv04_instmem_init; - engine->instmem.takedown = nv04_instmem_takedown; - engine->instmem.suspend = nv04_instmem_suspend; - engine->instmem.resume = nv04_instmem_resume; -- engine->instmem.populate = nv04_instmem_populate; -- engine->instmem.clear = nv04_instmem_clear; -- engine->instmem.bind = nv04_instmem_bind; -- engine->instmem.unbind = nv04_instmem_unbind; -+ engine->instmem.get = nv04_instmem_get; -+ engine->instmem.put = nv04_instmem_put; -+ engine->instmem.map = nv04_instmem_map; -+ engine->instmem.unmap = nv04_instmem_unmap; - engine->instmem.flush = nv04_instmem_flush; - engine->mc.init = nv04_mc_init; - engine->mc.takedown = nv04_mc_takedown; -@@ -225,8 +238,9 @@ - engine->timer.takedown = nv04_timer_takedown; - engine->fb.init = nv30_fb_init; - engine->fb.takedown = nv30_fb_takedown; -- engine->fb.set_region_tiling = nv10_fb_set_region_tiling; -- engine->graph.grclass = nv30_graph_grclass; -+ engine->fb.init_tile_region = nv30_fb_init_tile_region; -+ engine->fb.set_tile_region = nv10_fb_set_tile_region; -+ engine->fb.free_tile_region = nv30_fb_free_tile_region; - engine->graph.init = nv30_graph_init; - engine->graph.takedown = nv20_graph_takedown; - engine->graph.fifo_access = nv04_graph_fifo_access; -@@ -235,17 +249,17 @@ - engine->graph.destroy_context = nv20_graph_destroy_context; - engine->graph.load_context = nv20_graph_load_context; - engine->graph.unload_context = nv20_graph_unload_context; -- engine->graph.set_region_tiling = nv20_graph_set_region_tiling; -+ engine->graph.set_tile_region = nv20_graph_set_tile_region; - engine->fifo.channels = 32; - engine->fifo.init = nv10_fifo_init; -- engine->fifo.takedown = nouveau_stub_takedown; -+ engine->fifo.takedown = nv04_fifo_fini; - engine->fifo.disable = nv04_fifo_disable; - engine->fifo.enable = nv04_fifo_enable; - engine->fifo.reassign = nv04_fifo_reassign; - engine->fifo.cache_pull = nv04_fifo_cache_pull; - engine->fifo.channel_id = nv10_fifo_channel_id; - engine->fifo.create_context = nv10_fifo_create_context; -- engine->fifo.destroy_context = nv10_fifo_destroy_context; -+ engine->fifo.destroy_context = nv04_fifo_destroy_context; - engine->fifo.load_context = nv10_fifo_load_context; - engine->fifo.unload_context = nv10_fifo_unload_context; - engine->display.early_init = nv04_display_early_init; -@@ -263,6 +277,10 @@ - engine->pm.clock_set = nv04_pm_clock_set; - engine->pm.voltage_get = nouveau_voltage_gpio_get; - engine->pm.voltage_set = nouveau_voltage_gpio_set; -+ engine->crypt.init = nouveau_stub_init; -+ engine->crypt.takedown = nouveau_stub_takedown; -+ engine->vram.init = nouveau_mem_detect; -+ engine->vram.flags_valid = nouveau_mem_flags_valid; - break; - case 0x40: - case 0x60: -@@ -270,10 +288,10 @@ - engine->instmem.takedown = nv04_instmem_takedown; - engine->instmem.suspend = nv04_instmem_suspend; - engine->instmem.resume = nv04_instmem_resume; -- engine->instmem.populate = nv04_instmem_populate; -- engine->instmem.clear = nv04_instmem_clear; -- engine->instmem.bind = nv04_instmem_bind; -- engine->instmem.unbind = nv04_instmem_unbind; -+ engine->instmem.get = nv04_instmem_get; -+ engine->instmem.put = nv04_instmem_put; -+ engine->instmem.map = nv04_instmem_map; -+ engine->instmem.unmap = nv04_instmem_unmap; - engine->instmem.flush = nv04_instmem_flush; - engine->mc.init = nv40_mc_init; - engine->mc.takedown = nv40_mc_takedown; -@@ -282,8 +300,9 @@ - engine->timer.takedown = nv04_timer_takedown; - engine->fb.init = nv40_fb_init; - engine->fb.takedown = nv40_fb_takedown; -- engine->fb.set_region_tiling = nv40_fb_set_region_tiling; -- engine->graph.grclass = nv40_graph_grclass; -+ engine->fb.init_tile_region = nv30_fb_init_tile_region; -+ engine->fb.set_tile_region = nv40_fb_set_tile_region; -+ engine->fb.free_tile_region = nv30_fb_free_tile_region; - engine->graph.init = nv40_graph_init; - engine->graph.takedown = nv40_graph_takedown; - engine->graph.fifo_access = nv04_graph_fifo_access; -@@ -292,17 +311,17 @@ - engine->graph.destroy_context = nv40_graph_destroy_context; - engine->graph.load_context = nv40_graph_load_context; - engine->graph.unload_context = nv40_graph_unload_context; -- engine->graph.set_region_tiling = nv40_graph_set_region_tiling; -+ engine->graph.set_tile_region = nv40_graph_set_tile_region; - engine->fifo.channels = 32; - engine->fifo.init = nv40_fifo_init; -- engine->fifo.takedown = nouveau_stub_takedown; -+ engine->fifo.takedown = nv04_fifo_fini; - engine->fifo.disable = nv04_fifo_disable; - engine->fifo.enable = nv04_fifo_enable; - engine->fifo.reassign = nv04_fifo_reassign; - engine->fifo.cache_pull = nv04_fifo_cache_pull; - engine->fifo.channel_id = nv10_fifo_channel_id; - engine->fifo.create_context = nv40_fifo_create_context; -- engine->fifo.destroy_context = nv40_fifo_destroy_context; -+ engine->fifo.destroy_context = nv04_fifo_destroy_context; - engine->fifo.load_context = nv40_fifo_load_context; - engine->fifo.unload_context = nv40_fifo_unload_context; - engine->display.early_init = nv04_display_early_init; -@@ -321,6 +340,10 @@ - engine->pm.voltage_get = nouveau_voltage_gpio_get; - engine->pm.voltage_set = nouveau_voltage_gpio_set; - engine->pm.temp_get = nv40_temp_get; -+ engine->crypt.init = nouveau_stub_init; -+ engine->crypt.takedown = nouveau_stub_takedown; -+ engine->vram.init = nouveau_mem_detect; -+ engine->vram.flags_valid = nouveau_mem_flags_valid; - break; - case 0x50: - case 0x80: /* gotta love NVIDIA's consistency.. */ -@@ -330,10 +353,10 @@ - engine->instmem.takedown = nv50_instmem_takedown; - engine->instmem.suspend = nv50_instmem_suspend; - engine->instmem.resume = nv50_instmem_resume; -- engine->instmem.populate = nv50_instmem_populate; -- engine->instmem.clear = nv50_instmem_clear; -- engine->instmem.bind = nv50_instmem_bind; -- engine->instmem.unbind = nv50_instmem_unbind; -+ engine->instmem.get = nv50_instmem_get; -+ engine->instmem.put = nv50_instmem_put; -+ engine->instmem.map = nv50_instmem_map; -+ engine->instmem.unmap = nv50_instmem_unmap; - if (dev_priv->chipset == 0x50) - engine->instmem.flush = nv50_instmem_flush; - else -@@ -345,7 +368,6 @@ - engine->timer.takedown = nv04_timer_takedown; - engine->fb.init = nv50_fb_init; - engine->fb.takedown = nv50_fb_takedown; -- engine->graph.grclass = nv50_graph_grclass; - engine->graph.init = nv50_graph_init; - engine->graph.takedown = nv50_graph_takedown; - engine->graph.fifo_access = nv50_graph_fifo_access; -@@ -381,24 +403,32 @@ - engine->display.init = nv50_display_init; - engine->display.destroy = nv50_display_destroy; - engine->gpio.init = nv50_gpio_init; -- engine->gpio.takedown = nouveau_stub_takedown; -+ engine->gpio.takedown = nv50_gpio_fini; - engine->gpio.get = nv50_gpio_get; - engine->gpio.set = nv50_gpio_set; -+ engine->gpio.irq_register = nv50_gpio_irq_register; -+ engine->gpio.irq_unregister = nv50_gpio_irq_unregister; - engine->gpio.irq_enable = nv50_gpio_irq_enable; - switch (dev_priv->chipset) { -- case 0xa3: -- case 0xa5: -- case 0xa8: -- case 0xaf: -- engine->pm.clock_get = nva3_pm_clock_get; -- engine->pm.clock_pre = nva3_pm_clock_pre; -- engine->pm.clock_set = nva3_pm_clock_set; -- break; -- default: -+ case 0x84: -+ case 0x86: -+ case 0x92: -+ case 0x94: -+ case 0x96: -+ case 0x98: -+ case 0xa0: -+ case 0xaa: -+ case 0xac: -+ case 0x50: - engine->pm.clock_get = nv50_pm_clock_get; - engine->pm.clock_pre = nv50_pm_clock_pre; - engine->pm.clock_set = nv50_pm_clock_set; - break; -+ default: -+ engine->pm.clock_get = nva3_pm_clock_get; -+ engine->pm.clock_pre = nva3_pm_clock_pre; -+ engine->pm.clock_set = nva3_pm_clock_set; -+ break; - } - engine->pm.voltage_get = nouveau_voltage_gpio_get; - engine->pm.voltage_set = nouveau_voltage_gpio_set; -@@ -406,17 +436,39 @@ - engine->pm.temp_get = nv84_temp_get; - else - engine->pm.temp_get = nv40_temp_get; -+ switch (dev_priv->chipset) { -+ case 0x84: -+ case 0x86: -+ case 0x92: -+ case 0x94: -+ case 0x96: -+ case 0xa0: -+ engine->crypt.init = nv84_crypt_init; -+ engine->crypt.takedown = nv84_crypt_fini; -+ engine->crypt.create_context = nv84_crypt_create_context; -+ engine->crypt.destroy_context = nv84_crypt_destroy_context; -+ engine->crypt.tlb_flush = nv84_crypt_tlb_flush; -+ break; -+ default: -+ engine->crypt.init = nouveau_stub_init; -+ engine->crypt.takedown = nouveau_stub_takedown; -+ break; -+ } -+ engine->vram.init = nv50_vram_init; -+ engine->vram.get = nv50_vram_new; -+ engine->vram.put = nv50_vram_del; -+ engine->vram.flags_valid = nv50_vram_flags_valid; - break; - case 0xC0: - engine->instmem.init = nvc0_instmem_init; - engine->instmem.takedown = nvc0_instmem_takedown; - engine->instmem.suspend = nvc0_instmem_suspend; - engine->instmem.resume = nvc0_instmem_resume; -- engine->instmem.populate = nvc0_instmem_populate; -- engine->instmem.clear = nvc0_instmem_clear; -- engine->instmem.bind = nvc0_instmem_bind; -- engine->instmem.unbind = nvc0_instmem_unbind; -- engine->instmem.flush = nvc0_instmem_flush; -+ engine->instmem.get = nv50_instmem_get; -+ engine->instmem.put = nv50_instmem_put; -+ engine->instmem.map = nv50_instmem_map; -+ engine->instmem.unmap = nv50_instmem_unmap; -+ engine->instmem.flush = nv84_instmem_flush; - engine->mc.init = nv50_mc_init; - engine->mc.takedown = nv50_mc_takedown; - engine->timer.init = nv04_timer_init; -@@ -424,7 +476,6 @@ - engine->timer.takedown = nv04_timer_takedown; - engine->fb.init = nvc0_fb_init; - engine->fb.takedown = nvc0_fb_takedown; -- engine->graph.grclass = NULL; //nvc0_graph_grclass; - engine->graph.init = nvc0_graph_init; - engine->graph.takedown = nvc0_graph_takedown; - engine->graph.fifo_access = nvc0_graph_fifo_access; -@@ -453,7 +504,15 @@ - engine->gpio.takedown = nouveau_stub_takedown; - engine->gpio.get = nv50_gpio_get; - engine->gpio.set = nv50_gpio_set; -+ engine->gpio.irq_register = nv50_gpio_irq_register; -+ engine->gpio.irq_unregister = nv50_gpio_irq_unregister; - engine->gpio.irq_enable = nv50_gpio_irq_enable; -+ engine->crypt.init = nouveau_stub_init; -+ engine->crypt.takedown = nouveau_stub_takedown; -+ engine->vram.init = nvc0_vram_init; -+ engine->vram.get = nvc0_vram_new; -+ engine->vram.put = nv50_vram_del; -+ engine->vram.flags_valid = nvc0_vram_flags_valid; - break; - default: - NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); -@@ -493,9 +552,13 @@ - if (ret) - return ret; - -+ /* no dma objects on fermi... */ -+ if (dev_priv->card_type >= NV_C0) -+ goto out_done; -+ - ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, - 0, dev_priv->vram_size, -- NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, -+ NV_MEM_ACCESS_RW, NV_MEM_TARGET_VRAM, - &gpuobj); - if (ret) - goto out_err; -@@ -505,9 +568,10 @@ - if (ret) - goto out_err; - -- ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0, -- dev_priv->gart_info.aper_size, -- NV_DMA_ACCESS_RW, &gpuobj, NULL); -+ ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, -+ 0, dev_priv->gart_info.aper_size, -+ NV_MEM_ACCESS_RW, NV_MEM_TARGET_GART, -+ &gpuobj); - if (ret) - goto out_err; - -@@ -516,11 +580,12 @@ - if (ret) - goto out_err; - -+out_done: -+ mutex_unlock(&dev_priv->channel->mutex); - return 0; - - out_err: -- nouveau_channel_free(dev_priv->channel); -- dev_priv->channel = NULL; -+ nouveau_channel_put(&dev_priv->channel); - return ret; - } - -@@ -567,6 +632,8 @@ - if (ret) - goto out; - engine = &dev_priv->engine; -+ spin_lock_init(&dev_priv->channels.lock); -+ spin_lock_init(&dev_priv->tile.lock); - spin_lock_init(&dev_priv->context_switch_lock); - - /* Make the CRTCs and I2C buses accessible */ -@@ -625,26 +692,28 @@ - if (ret) - goto out_fb; - -+ /* PCRYPT */ -+ ret = engine->crypt.init(dev); -+ if (ret) -+ goto out_graph; -+ - /* PFIFO */ - ret = engine->fifo.init(dev); - if (ret) -- goto out_graph; -+ goto out_crypt; - } - - ret = engine->display.create(dev); - if (ret) - goto out_fifo; - -- /* this call irq_preinstall, register irq handler and -- * call irq_postinstall -- */ -- ret = drm_irq_install(dev); -+ ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1); - if (ret) -- goto out_display; -+ goto out_vblank; - -- ret = drm_vblank_init(dev, 0); -+ ret = nouveau_irq_init(dev); - if (ret) -- goto out_irq; -+ goto out_vblank; - - /* what about PVIDEO/PCRTC/PRAMDAC etc? */ - -@@ -669,12 +738,16 @@ - out_fence: - nouveau_fence_fini(dev); - out_irq: -- drm_irq_uninstall(dev); --out_display: -+ nouveau_irq_fini(dev); -+out_vblank: -+ drm_vblank_cleanup(dev); - engine->display.destroy(dev); - out_fifo: - if (!nouveau_noaccel) - engine->fifo.takedown(dev); -+out_crypt: -+ if (!nouveau_noaccel) -+ engine->crypt.takedown(dev); - out_graph: - if (!nouveau_noaccel) - engine->graph.takedown(dev); -@@ -713,12 +786,12 @@ - - if (!engine->graph.accel_blocked) { - nouveau_fence_fini(dev); -- nouveau_channel_free(dev_priv->channel); -- dev_priv->channel = NULL; -+ nouveau_channel_put_unlocked(&dev_priv->channel); - } - - if (!nouveau_noaccel) { - engine->fifo.takedown(dev); -+ engine->crypt.takedown(dev); - engine->graph.takedown(dev); - } - engine->fb.takedown(dev); -@@ -737,7 +810,8 @@ - nouveau_gpuobj_takedown(dev); - nouveau_mem_vram_fini(dev); - -- drm_irq_uninstall(dev); -+ nouveau_irq_fini(dev); -+ drm_vblank_cleanup(dev); - - nouveau_pm_fini(dev); - nouveau_bios_takedown(dev); -@@ -1024,21 +1098,6 @@ - else - getparam->value = NV_PCI; - break; -- case NOUVEAU_GETPARAM_FB_PHYSICAL: -- getparam->value = dev_priv->fb_phys; -- break; -- case NOUVEAU_GETPARAM_AGP_PHYSICAL: -- getparam->value = dev_priv->gart_info.aper_base; -- break; -- case NOUVEAU_GETPARAM_PCI_PHYSICAL: -- if (dev->sg) { -- getparam->value = (unsigned long)dev->sg->virtual; -- } else { -- NV_ERROR(dev, "Requested PCIGART address, " -- "while no PCIGART was created\n"); -- return -EINVAL; -- } -- break; - case NOUVEAU_GETPARAM_FB_SIZE: - getparam->value = dev_priv->fb_available_size; - break; -@@ -1046,7 +1105,7 @@ - getparam->value = dev_priv->gart_info.aper_size; - break; - case NOUVEAU_GETPARAM_VM_VRAM_BASE: -- getparam->value = dev_priv->vm_vram_base; -+ getparam->value = 0; /* deprecated */ - break; - case NOUVEAU_GETPARAM_PTIMER_TIME: - getparam->value = dev_priv->engine.timer.read(dev); -@@ -1054,6 +1113,9 @@ - case NOUVEAU_GETPARAM_HAS_BO_USAGE: - getparam->value = 1; - break; -+ case NOUVEAU_GETPARAM_HAS_PAGEFLIP: -+ getparam->value = (dev_priv->card_type < NV_50); -+ break; - case NOUVEAU_GETPARAM_GRAPH_UNITS: - /* NV40 and NV50 versions are quite different, but register - * address is the same. User is supposed to know the card -@@ -1087,8 +1149,9 @@ - } - - /* Wait until (value(reg) & mask) == val, up until timeout has hit */ --bool nouveau_wait_until(struct drm_device *dev, uint64_t timeout, -- uint32_t reg, uint32_t mask, uint32_t val) -+bool -+nouveau_wait_eq(struct drm_device *dev, uint64_t timeout, -+ uint32_t reg, uint32_t mask, uint32_t val) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; -@@ -1102,10 +1165,33 @@ - return false; - } - -+/* Wait until (value(reg) & mask) != val, up until timeout has hit */ -+bool -+nouveau_wait_ne(struct drm_device *dev, uint64_t timeout, -+ uint32_t reg, uint32_t mask, uint32_t val) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; -+ uint64_t start = ptimer->read(dev); -+ -+ do { -+ if ((nv_rd32(dev, reg) & mask) != val) -+ 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) - { -- if (!nv_wait(dev, NV04_PGRAPH_STATUS, 0xffffffff, 0x00000000)) { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ uint32_t mask = ~0; -+ -+ if (dev_priv->card_type == NV_40) -+ mask &= ~NV40_PGRAPH_STATUS_SYNC_STALL; -+ -+ if (!nv_wait(dev, NV04_PGRAPH_STATUS, mask, 0)) { - NV_ERROR(dev, "PGRAPH idle timed out with status 0x%08x\n", - nv_rd32(dev, NV04_PGRAPH_STATUS)); - return false; -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_util.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_util.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_util.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_util.c 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,69 @@ -+/* -+ * Copyright (C) 2010 Nouveau Project -+ * -+ * All Rights Reserved. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, 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 (including the -+ * next paragraph) shall be included in all copies or substantial -+ * portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE -+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ * -+ */ -+ -+#include -+ -+#include "nouveau_util.h" -+ -+static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); -+ -+void -+nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value) -+{ -+ while (bf->name) { -+ if (value & bf->mask) { -+ printk(" %s", bf->name); -+ value &= ~bf->mask; -+ } -+ -+ bf++; -+ } -+ -+ if (value) -+ printk(" (unknown bits 0x%08x)", value); -+} -+ -+void -+nouveau_enum_print(const struct nouveau_enum *en, u32 value) -+{ -+ while (en->name) { -+ if (value == en->value) { -+ printk("%s", en->name); -+ return; -+ } -+ -+ en++; -+ } -+ -+ printk("(unknown enum 0x%08x)", value); -+} -+ -+int -+nouveau_ratelimit(void) -+{ -+ return __ratelimit(&nouveau_ratelimit_state); -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_util.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_util.h ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_util.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_util.h 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,45 @@ -+/* -+ * Copyright (C) 2010 Nouveau Project -+ * -+ * All Rights Reserved. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, 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 (including the -+ * next paragraph) shall be included in all copies or substantial -+ * portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE -+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ * -+ */ -+ -+#ifndef __NOUVEAU_UTIL_H__ -+#define __NOUVEAU_UTIL_H__ -+ -+struct nouveau_bitfield { -+ u32 mask; -+ const char *name; -+}; -+ -+struct nouveau_enum { -+ u32 value; -+ const char *name; -+}; -+ -+void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value); -+void nouveau_enum_print(const struct nouveau_enum *, u32 value); -+int nouveau_ratelimit(void); -+ -+#endif -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_vm.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_vm.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_vm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_vm.c 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,439 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+#include "nouveau_drv.h" -+#include "nouveau_mm.h" -+#include "nouveau_vm.h" -+ -+void -+nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) -+{ -+ struct nouveau_vm *vm = vma->vm; -+ struct nouveau_mm_node *r; -+ int big = vma->node->type != vm->spg_shift; -+ u32 offset = vma->node->offset + (delta >> 12); -+ u32 bits = vma->node->type - 12; -+ u32 pde = (offset >> vm->pgt_bits) - vm->fpde; -+ u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; -+ u32 max = 1 << (vm->pgt_bits - bits); -+ u32 end, len; -+ -+ list_for_each_entry(r, &vram->regions, rl_entry) { -+ u64 phys = (u64)r->offset << 12; -+ u32 num = r->length >> bits; -+ -+ while (num) { -+ struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big]; -+ -+ end = (pte + num); -+ if (unlikely(end >= max)) -+ end = max; -+ len = end - pte; -+ -+ vm->map(vma, pgt, vram, pte, len, phys); -+ -+ num -= len; -+ pte += len; -+ if (unlikely(end >= max)) { -+ pde++; -+ pte = 0; -+ } -+ } -+ } -+ -+ vm->flush(vm); -+} -+ -+void -+nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_vram *vram) -+{ -+ nouveau_vm_map_at(vma, 0, vram); -+} -+ -+void -+nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, -+ dma_addr_t *list) -+{ -+ struct nouveau_vm *vm = vma->vm; -+ int big = vma->node->type != vm->spg_shift; -+ u32 offset = vma->node->offset + (delta >> 12); -+ u32 bits = vma->node->type - 12; -+ u32 num = length >> vma->node->type; -+ u32 pde = (offset >> vm->pgt_bits) - vm->fpde; -+ u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; -+ u32 max = 1 << (vm->pgt_bits - bits); -+ u32 end, len; -+ -+ while (num) { -+ struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big]; -+ -+ end = (pte + num); -+ if (unlikely(end >= max)) -+ end = max; -+ len = end - pte; -+ -+ vm->map_sg(vma, pgt, pte, list, len); -+ -+ num -= len; -+ pte += len; -+ list += len; -+ if (unlikely(end >= max)) { -+ pde++; -+ pte = 0; -+ } -+ } -+ -+ vm->flush(vm); -+} -+ -+void -+nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) -+{ -+ struct nouveau_vm *vm = vma->vm; -+ int big = vma->node->type != vm->spg_shift; -+ u32 offset = vma->node->offset + (delta >> 12); -+ u32 bits = vma->node->type - 12; -+ u32 num = length >> vma->node->type; -+ u32 pde = (offset >> vm->pgt_bits) - vm->fpde; -+ u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; -+ u32 max = 1 << (vm->pgt_bits - bits); -+ u32 end, len; -+ -+ while (num) { -+ struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big]; -+ -+ end = (pte + num); -+ if (unlikely(end >= max)) -+ end = max; -+ len = end - pte; -+ -+ vm->unmap(pgt, pte, len); -+ -+ num -= len; -+ pte += len; -+ if (unlikely(end >= max)) { -+ pde++; -+ pte = 0; -+ } -+ } -+ -+ vm->flush(vm); -+} -+ -+void -+nouveau_vm_unmap(struct nouveau_vma *vma) -+{ -+ nouveau_vm_unmap_at(vma, 0, (u64)vma->node->length << 12); -+} -+ -+static void -+nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde) -+{ -+ struct nouveau_vm_pgd *vpgd; -+ struct nouveau_vm_pgt *vpgt; -+ struct nouveau_gpuobj *pgt; -+ u32 pde; -+ -+ for (pde = fpde; pde <= lpde; pde++) { -+ vpgt = &vm->pgt[pde - vm->fpde]; -+ if (--vpgt->refcount[big]) -+ continue; -+ -+ pgt = vpgt->obj[big]; -+ vpgt->obj[big] = NULL; -+ -+ list_for_each_entry(vpgd, &vm->pgd_list, head) { -+ vm->map_pgt(vpgd->obj, pde, vpgt->obj); -+ } -+ -+ mutex_unlock(&vm->mm->mutex); -+ nouveau_gpuobj_ref(NULL, &pgt); -+ mutex_lock(&vm->mm->mutex); -+ } -+} -+ -+static int -+nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type) -+{ -+ struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; -+ struct nouveau_vm_pgd *vpgd; -+ struct nouveau_gpuobj *pgt; -+ int big = (type != vm->spg_shift); -+ u32 pgt_size; -+ int ret; -+ -+ pgt_size = (1 << (vm->pgt_bits + 12)) >> type; -+ pgt_size *= 8; -+ -+ mutex_unlock(&vm->mm->mutex); -+ ret = nouveau_gpuobj_new(vm->dev, NULL, pgt_size, 0x1000, -+ NVOBJ_FLAG_ZERO_ALLOC, &pgt); -+ mutex_lock(&vm->mm->mutex); -+ if (unlikely(ret)) -+ return ret; -+ -+ /* someone beat us to filling the PDE while we didn't have the lock */ -+ if (unlikely(vpgt->refcount[big]++)) { -+ mutex_unlock(&vm->mm->mutex); -+ nouveau_gpuobj_ref(NULL, &pgt); -+ mutex_lock(&vm->mm->mutex); -+ return 0; -+ } -+ -+ vpgt->obj[big] = pgt; -+ list_for_each_entry(vpgd, &vm->pgd_list, head) { -+ vm->map_pgt(vpgd->obj, pde, vpgt->obj); -+ } -+ -+ return 0; -+} -+ -+int -+nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, -+ u32 access, struct nouveau_vma *vma) -+{ -+ u32 align = (1 << page_shift) >> 12; -+ u32 msize = size >> 12; -+ u32 fpde, lpde, pde; -+ int ret; -+ -+ mutex_lock(&vm->mm->mutex); -+ ret = nouveau_mm_get(vm->mm, page_shift, msize, 0, align, &vma->node); -+ if (unlikely(ret != 0)) { -+ mutex_unlock(&vm->mm->mutex); -+ return ret; -+ } -+ -+ fpde = (vma->node->offset >> vm->pgt_bits); -+ lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits; -+ for (pde = fpde; pde <= lpde; pde++) { -+ struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; -+ int big = (vma->node->type != vm->spg_shift); -+ -+ if (likely(vpgt->refcount[big])) { -+ vpgt->refcount[big]++; -+ continue; -+ } -+ -+ ret = nouveau_vm_map_pgt(vm, pde, vma->node->type); -+ if (ret) { -+ if (pde != fpde) -+ nouveau_vm_unmap_pgt(vm, big, fpde, pde - 1); -+ nouveau_mm_put(vm->mm, vma->node); -+ mutex_unlock(&vm->mm->mutex); -+ vma->node = NULL; -+ return ret; -+ } -+ } -+ mutex_unlock(&vm->mm->mutex); -+ -+ vma->vm = vm; -+ vma->offset = (u64)vma->node->offset << 12; -+ vma->access = access; -+ return 0; -+} -+ -+void -+nouveau_vm_put(struct nouveau_vma *vma) -+{ -+ struct nouveau_vm *vm = vma->vm; -+ u32 fpde, lpde; -+ -+ if (unlikely(vma->node == NULL)) -+ return; -+ fpde = (vma->node->offset >> vm->pgt_bits); -+ lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits; -+ -+ mutex_lock(&vm->mm->mutex); -+ nouveau_vm_unmap_pgt(vm, vma->node->type != vm->spg_shift, fpde, lpde); -+ nouveau_mm_put(vm->mm, vma->node); -+ vma->node = NULL; -+ mutex_unlock(&vm->mm->mutex); -+} -+ -+int -+nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset, -+ struct nouveau_vm **pvm) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_vm *vm; -+ u64 mm_length = (offset + length) - mm_offset; -+ u32 block, pgt_bits; -+ int ret; -+ -+ vm = kzalloc(sizeof(*vm), GFP_KERNEL); -+ if (!vm) -+ return -ENOMEM; -+ -+ if (dev_priv->card_type == NV_50) { -+ vm->map_pgt = nv50_vm_map_pgt; -+ vm->map = nv50_vm_map; -+ vm->map_sg = nv50_vm_map_sg; -+ vm->unmap = nv50_vm_unmap; -+ vm->flush = nv50_vm_flush; -+ vm->spg_shift = 12; -+ vm->lpg_shift = 16; -+ -+ pgt_bits = 29; -+ block = (1 << pgt_bits); -+ if (length < block) -+ block = length; -+ -+ } else -+ if (dev_priv->card_type == NV_C0) { -+ vm->map_pgt = nvc0_vm_map_pgt; -+ vm->map = nvc0_vm_map; -+ vm->map_sg = nvc0_vm_map_sg; -+ vm->unmap = nvc0_vm_unmap; -+ vm->flush = nvc0_vm_flush; -+ vm->spg_shift = 12; -+ vm->lpg_shift = 17; -+ pgt_bits = 27; -+ -+ /* Should be 4096 everywhere, this is a hack that's -+ * currently necessary to avoid an elusive bug that -+ * causes corruption when mixing small/large pages -+ */ -+ if (length < (1ULL << 40)) -+ block = 4096; -+ else { -+ block = (1 << pgt_bits); -+ if (length < block) -+ block = length; -+ } -+ } else { -+ kfree(vm); -+ return -ENOSYS; -+ } -+ -+ vm->fpde = offset >> pgt_bits; -+ vm->lpde = (offset + length - 1) >> pgt_bits; -+ vm->pgt = kcalloc(vm->lpde - vm->fpde + 1, sizeof(*vm->pgt), GFP_KERNEL); -+ if (!vm->pgt) { -+ kfree(vm); -+ return -ENOMEM; -+ } -+ -+ INIT_LIST_HEAD(&vm->pgd_list); -+ vm->dev = dev; -+ vm->refcount = 1; -+ vm->pgt_bits = pgt_bits - 12; -+ -+ ret = nouveau_mm_init(&vm->mm, mm_offset >> 12, mm_length >> 12, -+ block >> 12); -+ if (ret) { -+ kfree(vm); -+ return ret; -+ } -+ -+ *pvm = vm; -+ return 0; -+} -+ -+static int -+nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd) -+{ -+ struct nouveau_vm_pgd *vpgd; -+ int i; -+ -+ if (!pgd) -+ return 0; -+ -+ vpgd = kzalloc(sizeof(*vpgd), GFP_KERNEL); -+ if (!vpgd) -+ return -ENOMEM; -+ -+ nouveau_gpuobj_ref(pgd, &vpgd->obj); -+ -+ mutex_lock(&vm->mm->mutex); -+ for (i = vm->fpde; i <= vm->lpde; i++) -+ vm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj); -+ list_add(&vpgd->head, &vm->pgd_list); -+ mutex_unlock(&vm->mm->mutex); -+ return 0; -+} -+ -+static void -+nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd) -+{ -+ struct nouveau_vm_pgd *vpgd, *tmp; -+ -+ if (!pgd) -+ 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); -+ } -+ mutex_unlock(&vm->mm->mutex); -+} -+ -+static void -+nouveau_vm_del(struct nouveau_vm *vm) -+{ -+ struct nouveau_vm_pgd *vpgd, *tmp; -+ -+ 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); -+ -+ kfree(vm->pgt); -+ kfree(vm); -+} -+ -+int -+nouveau_vm_ref(struct nouveau_vm *ref, struct nouveau_vm **ptr, -+ struct nouveau_gpuobj *pgd) -+{ -+ struct nouveau_vm *vm; -+ int ret; -+ -+ vm = ref; -+ if (vm) { -+ ret = nouveau_vm_link(vm, pgd); -+ if (ret) -+ return ret; -+ -+ vm->refcount++; -+ } -+ -+ vm = *ptr; -+ *ptr = ref; -+ -+ if (vm) { -+ nouveau_vm_unlink(vm, pgd); -+ -+ if (--vm->refcount == 0) -+ nouveau_vm_del(vm); -+ } -+ -+ return 0; -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_vm.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_vm.h ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nouveau_vm.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nouveau_vm.h 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,113 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#ifndef __NOUVEAU_VM_H__ -+#define __NOUVEAU_VM_H__ -+ -+#include "drmP.h" -+ -+#include "nouveau_drv.h" -+#include "nouveau_mm.h" -+ -+struct nouveau_vm_pgt { -+ struct nouveau_gpuobj *obj[2]; -+ u32 refcount[2]; -+}; -+ -+struct nouveau_vm_pgd { -+ struct list_head head; -+ struct nouveau_gpuobj *obj; -+}; -+ -+struct nouveau_vma { -+ struct nouveau_vm *vm; -+ struct nouveau_mm_node *node; -+ u64 offset; -+ u32 access; -+}; -+ -+struct nouveau_vm { -+ struct drm_device *dev; -+ struct nouveau_mm *mm; -+ int refcount; -+ -+ struct list_head pgd_list; -+ atomic_t pgraph_refs; -+ atomic_t pcrypt_refs; -+ -+ struct nouveau_vm_pgt *pgt; -+ u32 fpde; -+ u32 lpde; -+ -+ u32 pgt_bits; -+ u8 spg_shift; -+ u8 lpg_shift; -+ -+ void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde, -+ struct nouveau_gpuobj *pgt[2]); -+ void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *, -+ struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); -+ void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, -+ u32 pte, dma_addr_t *, u32 cnt); -+ void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt); -+ void (*flush)(struct nouveau_vm *); -+}; -+ -+/* nouveau_vm.c */ -+int nouveau_vm_new(struct drm_device *, u64 offset, u64 length, u64 mm_offset, -+ struct nouveau_vm **); -+int nouveau_vm_ref(struct nouveau_vm *, struct nouveau_vm **, -+ struct nouveau_gpuobj *pgd); -+int nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift, -+ u32 access, struct nouveau_vma *); -+void nouveau_vm_put(struct nouveau_vma *); -+void nouveau_vm_map(struct nouveau_vma *, struct nouveau_vram *); -+void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_vram *); -+void nouveau_vm_unmap(struct nouveau_vma *); -+void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); -+void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, -+ dma_addr_t *); -+ -+/* nv50_vm.c */ -+void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, -+ struct nouveau_gpuobj *pgt[2]); -+void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, -+ struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); -+void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, -+ u32 pte, dma_addr_t *, u32 cnt); -+void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); -+void nv50_vm_flush(struct nouveau_vm *); -+void nv50_vm_flush_engine(struct drm_device *, int engine); -+ -+/* nvc0_vm.c */ -+void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, -+ struct nouveau_gpuobj *pgt[2]); -+void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, -+ struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); -+void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, -+ u32 pte, dma_addr_t *, u32 cnt); -+void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); -+void nvc0_vm_flush(struct nouveau_vm *); -+ -+#endif -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv04_crtc.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_crtc.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv04_crtc.c 2011-01-07 14:22:17.000000000 +0100 -@@ -551,7 +551,10 @@ - if (dev_priv->card_type >= NV_30) - regp->gpio_ext = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT); - -- regp->crtc_cfg = NV_PCRTC_CONFIG_START_ADDRESS_HSYNC; -+ if (dev_priv->card_type >= NV_10) -+ regp->crtc_cfg = NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC; -+ else -+ regp->crtc_cfg = NV04_PCRTC_CONFIG_START_ADDRESS_HSYNC; - - /* Some misc regs */ - if (dev_priv->card_type == NV_40) { -@@ -669,6 +672,7 @@ - if (nv_two_heads(dev)) - NVSetOwner(dev, nv_crtc->index); - -+ drm_vblank_pre_modeset(dev, nv_crtc->index); - funcs->dpms(crtc, DRM_MODE_DPMS_OFF); - - NVBlankScreen(dev, nv_crtc->index, true); -@@ -701,6 +705,7 @@ - #endif - - funcs->dpms(crtc, DRM_MODE_DPMS_ON); -+ drm_vblank_post_modeset(dev, nv_crtc->index); - } - - static void nv_crtc_destroy(struct drm_crtc *crtc) -@@ -986,6 +991,7 @@ - .cursor_move = nv04_crtc_cursor_move, - .gamma_set = nv_crtc_gamma_set, - .set_config = drm_crtc_helper_set_config, -+ .page_flip = nouveau_crtc_page_flip, - .destroy = nv_crtc_destroy, - }; - -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_dac.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv04_dac.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_dac.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv04_dac.c 2011-01-07 14:22:17.000000000 +0100 -@@ -74,14 +74,14 @@ - * use a 10ms timeout (guards against crtc being inactive, in - * which case blank state would never change) - */ -- if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR, -- 0x00000001, 0x00000000)) -+ if (!nouveau_wait_eq(dev, 10000000, NV_PRMCIO_INP0__COLOR, -+ 0x00000001, 0x00000000)) - return -EBUSY; -- if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR, -- 0x00000001, 0x00000001)) -+ if (!nouveau_wait_eq(dev, 10000000, NV_PRMCIO_INP0__COLOR, -+ 0x00000001, 0x00000001)) - return -EBUSY; -- if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR, -- 0x00000001, 0x00000000)) -+ if (!nouveau_wait_eq(dev, 10000000, NV_PRMCIO_INP0__COLOR, -+ 0x00000001, 0x00000000)) - return -EBUSY; - - udelay(100); -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_display.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv04_display.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_display.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv04_display.c 2011-01-07 14:22:17.000000000 +0100 -@@ -32,6 +32,9 @@ - #include "nouveau_encoder.h" - #include "nouveau_connector.h" - -+static void nv04_vblank_crtc0_isr(struct drm_device *); -+static void nv04_vblank_crtc1_isr(struct drm_device *); -+ - static void - nv04_display_store_initial_head_owner(struct drm_device *dev) - { -@@ -197,6 +200,8 @@ - func->save(encoder); - } - -+ nouveau_irq_register(dev, 24, nv04_vblank_crtc0_isr); -+ nouveau_irq_register(dev, 25, nv04_vblank_crtc1_isr); - return 0; - } - -@@ -208,6 +213,9 @@ - - NV_DEBUG_KMS(dev, "\n"); - -+ nouveau_irq_unregister(dev, 24); -+ nouveau_irq_unregister(dev, 25); -+ - /* Turn every CRTC off. */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct drm_mode_set modeset = { -@@ -258,3 +266,16 @@ - return 0; - } - -+static void -+nv04_vblank_crtc0_isr(struct drm_device *dev) -+{ -+ nv_wr32(dev, NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK); -+ drm_handle_vblank(dev, 0); -+} -+ -+static void -+nv04_vblank_crtc1_isr(struct drm_device *dev) -+{ -+ nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK); -+ drm_handle_vblank(dev, 1); -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_fbcon.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv04_fbcon.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_fbcon.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv04_fbcon.c 2011-01-07 14:22:17.000000000 +0100 -@@ -28,52 +28,39 @@ - #include "nouveau_ramht.h" - #include "nouveau_fbcon.h" - --void -+int - nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) - { - struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; -+ int ret; - -- if (info->state != FBINFO_STATE_RUNNING) -- return; -- -- if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 4)) { -- nouveau_fbcon_gpu_lockup(info); -- } -- -- if (info->flags & FBINFO_HWACCEL_DISABLED) { -- cfb_copyarea(info, region); -- return; -- } -+ ret = RING_SPACE(chan, 4); -+ if (ret) -+ return ret; - - BEGIN_RING(chan, NvSubImageBlit, 0x0300, 3); - OUT_RING(chan, (region->sy << 16) | region->sx); - OUT_RING(chan, (region->dy << 16) | region->dx); - OUT_RING(chan, (region->height << 16) | region->width); - FIRE_RING(chan); -+ return 0; - } - --void -+int - nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) - { - struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; -+ int ret; - -- if (info->state != FBINFO_STATE_RUNNING) -- return; -- -- if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 7)) { -- nouveau_fbcon_gpu_lockup(info); -- } -- -- if (info->flags & FBINFO_HWACCEL_DISABLED) { -- cfb_fillrect(info, rect); -- return; -- } -+ ret = RING_SPACE(chan, 7); -+ if (ret) -+ return ret; - - BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1); - OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3); -@@ -87,9 +74,10 @@ - OUT_RING(chan, (rect->dx << 16) | rect->dy); - OUT_RING(chan, (rect->width << 16) | rect->height); - FIRE_RING(chan); -+ return 0; - } - --void -+int - nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) - { - struct nouveau_fbdev *nfbdev = info->par; -@@ -101,23 +89,14 @@ - uint32_t dsize; - uint32_t width; - uint32_t *data = (uint32_t *)image->data; -+ int ret; - -- if (info->state != FBINFO_STATE_RUNNING) -- return; -- -- if (image->depth != 1) { -- cfb_imageblit(info, image); -- return; -- } -- -- if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 8)) { -- nouveau_fbcon_gpu_lockup(info); -- } -+ if (image->depth != 1) -+ return -ENODEV; - -- if (info->flags & FBINFO_HWACCEL_DISABLED) { -- cfb_imageblit(info, image); -- return; -- } -+ ret = RING_SPACE(chan, 8); -+ if (ret) -+ return ret; - - width = ALIGN(image->width, 8); - dsize = ALIGN(width * image->height, 32) >> 5; -@@ -144,11 +123,9 @@ - while (dsize) { - int iter_len = dsize > 128 ? 128 : dsize; - -- if (RING_SPACE(chan, iter_len + 1)) { -- nouveau_fbcon_gpu_lockup(info); -- cfb_imageblit(info, image); -- return; -- } -+ ret = RING_SPACE(chan, iter_len + 1); -+ if (ret) -+ return ret; - - BEGIN_RING(chan, NvSubGdiRect, 0x0c00, iter_len); - OUT_RINGp(chan, data, iter_len); -@@ -157,22 +134,7 @@ - } - - FIRE_RING(chan); --} -- --static int --nv04_fbcon_grobj_new(struct drm_device *dev, int class, uint32_t handle) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *obj = NULL; -- int ret; -- -- ret = nouveau_gpuobj_gr_new(dev_priv->channel, class, &obj); -- if (ret) -- return ret; -- -- ret = nouveau_ramht_insert(dev_priv->channel, handle, obj); -- nouveau_gpuobj_ref(NULL, &obj); -- return ret; -+ return 0; - } - - int -@@ -214,29 +176,31 @@ - return -EINVAL; - } - -- ret = nv04_fbcon_grobj_new(dev, dev_priv->card_type >= NV_10 ? -- 0x0062 : 0x0042, NvCtxSurf2D); -+ ret = nouveau_gpuobj_gr_new(chan, NvCtxSurf2D, -+ dev_priv->card_type >= NV_10 ? -+ 0x0062 : 0x0042); - if (ret) - return ret; - -- ret = nv04_fbcon_grobj_new(dev, 0x0019, NvClipRect); -+ ret = nouveau_gpuobj_gr_new(chan, NvClipRect, 0x0019); - if (ret) - return ret; - -- ret = nv04_fbcon_grobj_new(dev, 0x0043, NvRop); -+ ret = nouveau_gpuobj_gr_new(chan, NvRop, 0x0043); - if (ret) - return ret; - -- ret = nv04_fbcon_grobj_new(dev, 0x0044, NvImagePatt); -+ ret = nouveau_gpuobj_gr_new(chan, NvImagePatt, 0x0044); - if (ret) - return ret; - -- ret = nv04_fbcon_grobj_new(dev, 0x004a, NvGdiRect); -+ ret = nouveau_gpuobj_gr_new(chan, NvGdiRect, 0x004a); - if (ret) - return ret; - -- ret = nv04_fbcon_grobj_new(dev, dev_priv->chipset >= 0x11 ? -- 0x009f : 0x005f, NvImageBlit); -+ ret = nouveau_gpuobj_gr_new(chan, NvImageBlit, -+ dev_priv->chipset >= 0x11 ? -+ 0x009f : 0x005f); - if (ret) - return ret; - -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_fifo.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv04_fifo.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_fifo.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv04_fifo.c 2011-01-07 14:22:17.000000000 +0100 -@@ -28,6 +28,7 @@ - #include "drm.h" - #include "nouveau_drv.h" - #include "nouveau_ramht.h" -+#include "nouveau_util.h" - - #define NV04_RAMFC(c) (dev_priv->ramfc->pinst + ((c) * NV04_RAMFC__SIZE)) - #define NV04_RAMFC__SIZE 32 -@@ -128,6 +129,11 @@ - if (ret) - return ret; - -+ chan->user = ioremap(pci_resource_start(dev->pdev, 0) + -+ NV03_USER(chan->id), PAGE_SIZE); -+ if (!chan->user) -+ return -ENOMEM; -+ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - - /* Setup initial state */ -@@ -151,10 +157,31 @@ - nv04_fifo_destroy_context(struct nouveau_channel *chan) - { - struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; -+ unsigned long flags; - -- nv_wr32(dev, NV04_PFIFO_MODE, -- nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ pfifo->reassign(dev, false); - -+ /* Unload the context if it's the currently active one */ -+ if (pfifo->channel_id(dev) == chan->id) { -+ pfifo->disable(dev); -+ pfifo->unload_context(dev); -+ pfifo->enable(dev); -+ } -+ -+ /* Keep it from being rescheduled */ -+ nv_mask(dev, NV04_PFIFO_MODE, 1 << chan->id, 0); -+ -+ pfifo->reassign(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ -+ /* Free the channel resources */ -+ if (chan->user) { -+ iounmap(chan->user); -+ chan->user = NULL; -+ } - nouveau_gpuobj_ref(NULL, &chan->ramfc); - } - -@@ -208,7 +235,7 @@ - if (chid < 0 || chid >= dev_priv->engine.fifo.channels) - return 0; - -- chan = dev_priv->fifos[chid]; -+ chan = dev_priv->channels.ptr[chid]; - if (!chan) { - NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid); - return -EINVAL; -@@ -267,6 +294,7 @@ - static void - nv04_fifo_init_intr(struct drm_device *dev) - { -+ nouveau_irq_register(dev, 8, nv04_fifo_isr); - nv_wr32(dev, 0x002100, 0xffffffff); - nv_wr32(dev, 0x002140, 0xffffffff); - } -@@ -289,7 +317,7 @@ - pfifo->reassign(dev, true); - - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- if (dev_priv->fifos[i]) { -+ if (dev_priv->channels.ptr[i]) { - uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); - nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); - } -@@ -298,3 +326,207 @@ - return 0; - } - -+void -+nv04_fifo_fini(struct drm_device *dev) -+{ -+ nv_wr32(dev, 0x2140, 0x00000000); -+ nouveau_irq_unregister(dev, 8); -+} -+ -+static bool -+nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *chan = NULL; -+ struct nouveau_gpuobj *obj; -+ unsigned long flags; -+ const int subc = (addr >> 13) & 0x7; -+ const int mthd = addr & 0x1ffc; -+ bool handled = false; -+ u32 engine; -+ -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); -+ if (likely(chid >= 0 && chid < dev_priv->engine.fifo.channels)) -+ chan = dev_priv->channels.ptr[chid]; -+ if (unlikely(!chan)) -+ goto out; -+ -+ switch (mthd) { -+ case 0x0000: /* bind object to subchannel */ -+ obj = nouveau_ramht_find(chan, data); -+ if (unlikely(!obj || obj->engine != NVOBJ_ENGINE_SW)) -+ break; -+ -+ chan->sw_subchannel[subc] = obj->class; -+ engine = 0x0000000f << (subc * 4); -+ -+ nv_mask(dev, NV04_PFIFO_CACHE1_ENGINE, engine, 0x00000000); -+ handled = true; -+ break; -+ default: -+ engine = nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE); -+ if (unlikely(((engine >> (subc * 4)) & 0xf) != 0)) -+ break; -+ -+ if (!nouveau_gpuobj_mthd_call(chan, chan->sw_subchannel[subc], -+ mthd, data)) -+ handled = true; -+ break; -+ } -+ -+out: -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); -+ return handled; -+} -+ -+void -+nv04_fifo_isr(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_engine *engine = &dev_priv->engine; -+ uint32_t status, reassign; -+ int cnt = 0; -+ -+ reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1; -+ while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) { -+ uint32_t chid, get; -+ -+ nv_wr32(dev, NV03_PFIFO_CACHES, 0); -+ -+ chid = engine->fifo.channel_id(dev); -+ get = nv_rd32(dev, NV03_PFIFO_CACHE1_GET); -+ -+ if (status & NV_PFIFO_INTR_CACHE_ERROR) { -+ uint32_t mthd, data; -+ int ptr; -+ -+ /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before -+ * wrapping on my G80 chips, but CACHE1 isn't big -+ * enough for this much data.. Tests show that it -+ * wraps around to the start at GET=0x800.. No clue -+ * as to why.. -+ */ -+ ptr = (get & 0x7ff) >> 2; -+ -+ if (dev_priv->card_type < NV_40) { -+ mthd = nv_rd32(dev, -+ NV04_PFIFO_CACHE1_METHOD(ptr)); -+ data = nv_rd32(dev, -+ NV04_PFIFO_CACHE1_DATA(ptr)); -+ } else { -+ mthd = nv_rd32(dev, -+ NV40_PFIFO_CACHE1_METHOD(ptr)); -+ data = nv_rd32(dev, -+ NV40_PFIFO_CACHE1_DATA(ptr)); -+ } -+ -+ if (!nouveau_fifo_swmthd(dev, chid, mthd, data)) { -+ NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d " -+ "Mthd 0x%04x Data 0x%08x\n", -+ chid, (mthd >> 13) & 7, mthd & 0x1ffc, -+ data); -+ } -+ -+ nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0); -+ nv_wr32(dev, NV03_PFIFO_INTR_0, -+ NV_PFIFO_INTR_CACHE_ERROR); -+ -+ nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, -+ nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) & ~1); -+ nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); -+ nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, -+ nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) | 1); -+ nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); -+ -+ nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, -+ nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); -+ nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); -+ -+ status &= ~NV_PFIFO_INTR_CACHE_ERROR; -+ } -+ -+ if (status & NV_PFIFO_INTR_DMA_PUSHER) { -+ u32 dma_get = nv_rd32(dev, 0x003244); -+ u32 dma_put = nv_rd32(dev, 0x003240); -+ u32 push = nv_rd32(dev, 0x003220); -+ u32 state = nv_rd32(dev, 0x003228); -+ -+ if (dev_priv->card_type == NV_50) { -+ u32 ho_get = nv_rd32(dev, 0x003328); -+ u32 ho_put = nv_rd32(dev, 0x003320); -+ u32 ib_get = nv_rd32(dev, 0x003334); -+ u32 ib_put = nv_rd32(dev, 0x003330); -+ -+ if (nouveau_ratelimit()) -+ NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x " -+ "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " -+ "State 0x%08x Push 0x%08x\n", -+ chid, ho_get, dma_get, ho_put, -+ dma_put, ib_get, ib_put, state, -+ push); -+ -+ /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ -+ nv_wr32(dev, 0x003364, 0x00000000); -+ if (dma_get != dma_put || ho_get != ho_put) { -+ nv_wr32(dev, 0x003244, dma_put); -+ nv_wr32(dev, 0x003328, ho_put); -+ } else -+ if (ib_get != ib_put) { -+ nv_wr32(dev, 0x003334, ib_put); -+ } -+ } else { -+ NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " -+ "Put 0x%08x State 0x%08x Push 0x%08x\n", -+ chid, dma_get, dma_put, state, push); -+ -+ if (dma_get != dma_put) -+ nv_wr32(dev, 0x003244, dma_put); -+ } -+ -+ nv_wr32(dev, 0x003228, 0x00000000); -+ nv_wr32(dev, 0x003220, 0x00000001); -+ nv_wr32(dev, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); -+ status &= ~NV_PFIFO_INTR_DMA_PUSHER; -+ } -+ -+ if (status & NV_PFIFO_INTR_SEMAPHORE) { -+ uint32_t sem; -+ -+ status &= ~NV_PFIFO_INTR_SEMAPHORE; -+ nv_wr32(dev, NV03_PFIFO_INTR_0, -+ NV_PFIFO_INTR_SEMAPHORE); -+ -+ sem = nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE); -+ nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1); -+ -+ nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); -+ nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); -+ } -+ -+ if (dev_priv->card_type == NV_50) { -+ if (status & 0x00000010) { -+ nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT"); -+ status &= ~0x00000010; -+ nv_wr32(dev, 0x002100, 0x00000010); -+ } -+ } -+ -+ if (status) { -+ if (nouveau_ratelimit()) -+ NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", -+ status, chid); -+ nv_wr32(dev, NV03_PFIFO_INTR_0, status); -+ status = 0; -+ } -+ -+ nv_wr32(dev, NV03_PFIFO_CACHES, reassign); -+ } -+ -+ if (status) { -+ NV_INFO(dev, "PFIFO still angry after %d spins, halt\n", cnt); -+ nv_wr32(dev, 0x2140, 0); -+ nv_wr32(dev, 0x140, 0); -+ } -+ -+ nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING); -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_graph.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv04_graph.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_graph.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv04_graph.c 2011-01-07 14:22:17.000000000 +0100 -@@ -26,6 +26,11 @@ - #include "drm.h" - #include "nouveau_drm.h" - #include "nouveau_drv.h" -+#include "nouveau_hw.h" -+#include "nouveau_util.h" -+ -+static int nv04_graph_register(struct drm_device *dev); -+static void nv04_graph_isr(struct drm_device *dev); - - static uint32_t nv04_graph_ctx_regs[] = { - 0x0040053c, -@@ -357,10 +362,10 @@ - if (chid >= dev_priv->engine.fifo.channels) - return NULL; - -- return dev_priv->fifos[chid]; -+ return dev_priv->channels.ptr[chid]; - } - --void -+static void - nv04_graph_context_switch(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -@@ -368,7 +373,6 @@ - struct nouveau_channel *chan = NULL; - int chid; - -- pgraph->fifo_access(dev, false); - nouveau_wait_for_idle(dev); - - /* If previous context is valid, we need to save it */ -@@ -376,11 +380,9 @@ - - /* Load context for next channel */ - chid = dev_priv->engine.fifo.channel_id(dev); -- chan = dev_priv->fifos[chid]; -+ chan = dev_priv->channels.ptr[chid]; - if (chan) - nv04_graph_load_context(chan); -- -- pgraph->fifo_access(dev, true); - } - - static uint32_t *ctx_reg(struct graph_state *ctx, uint32_t reg) -@@ -412,10 +414,25 @@ - - void nv04_graph_destroy_context(struct nouveau_channel *chan) - { -+ struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - struct graph_state *pgraph_ctx = chan->pgraph_ctx; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ pgraph->fifo_access(dev, false); -+ -+ /* Unload the context if it's the currently active one */ -+ if (pgraph->channel(dev) == chan) -+ pgraph->unload_context(dev); - -+ /* Free the context resources */ - kfree(pgraph_ctx); - chan->pgraph_ctx = NULL; -+ -+ pgraph->fifo_access(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - } - - int nv04_graph_load_context(struct nouveau_channel *chan) -@@ -468,13 +485,19 @@ - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t tmp; -+ int ret; - - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & - ~NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | - NV_PMC_ENABLE_PGRAPH); - -+ ret = nv04_graph_register(dev); -+ if (ret) -+ return ret; -+ - /* Enable PGRAPH interrupts */ -+ nouveau_irq_register(dev, 12, nv04_graph_isr); - nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - -@@ -510,6 +533,8 @@ - - void nv04_graph_takedown(struct drm_device *dev) - { -+ nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); -+ nouveau_irq_unregister(dev, 12); - } - - void -@@ -524,13 +549,27 @@ - } - - static int --nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_set_ref(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - atomic_set(&chan->fence.last_sequence_irq, data); - return 0; - } - -+int -+nv04_graph_mthd_page_flip(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) -+{ -+ struct drm_device *dev = chan->dev; -+ struct nouveau_page_flip_state s; -+ -+ if (!nouveau_finish_page_flip(chan, &s)) -+ nv_set_crtc_base(dev, s.crtc, -+ s.offset + s.y * s.pitch + s.x * s.bpp / 8); -+ -+ return 0; -+} -+ - /* - * Software methods, why they are needed, and how they all work: - * -@@ -606,12 +645,12 @@ - */ - - static void --nv04_graph_set_ctx1(struct nouveau_channel *chan, uint32_t mask, uint32_t value) -+nv04_graph_set_ctx1(struct nouveau_channel *chan, u32 mask, u32 value) - { - struct drm_device *dev = chan->dev; -- uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; -+ u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; - int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; -- uint32_t tmp; -+ u32 tmp; - - tmp = nv_ri32(dev, instance); - tmp &= ~mask; -@@ -623,11 +662,11 @@ - } - - static void --nv04_graph_set_ctx_val(struct nouveau_channel *chan, uint32_t mask, uint32_t value) -+nv04_graph_set_ctx_val(struct nouveau_channel *chan, u32 mask, u32 value) - { - struct drm_device *dev = chan->dev; -- uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; -- uint32_t tmp, ctx1; -+ u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; -+ u32 tmp, ctx1; - int class, op, valid = 1; - - ctx1 = nv_ri32(dev, instance); -@@ -672,13 +711,13 @@ - } - - static int --nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_set_operation(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - if (data > 5) - return 1; - /* Old versions of the objects only accept first three operations. */ -- if (data > 2 && grclass < 0x40) -+ if (data > 2 && class < 0x40) - return 1; - nv04_graph_set_ctx1(chan, 0x00038000, data << 15); - /* changing operation changes set of objects needed for validation */ -@@ -687,8 +726,8 @@ - } - - static int --nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - uint32_t min = data & 0xffff, max; - uint32_t w = data >> 16; -@@ -706,8 +745,8 @@ - } - - static int --nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - uint32_t min = data & 0xffff, max; - uint32_t w = data >> 16; -@@ -725,8 +764,8 @@ - } - - static int --nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -742,8 +781,8 @@ - } - - static int --nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -763,8 +802,8 @@ - } - - static int --nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -778,8 +817,8 @@ - } - - static int --nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -793,8 +832,8 @@ - } - - static int --nv04_graph_mthd_bind_rop(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_rop(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -808,8 +847,8 @@ - } - - static int --nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -823,8 +862,8 @@ - } - - static int --nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -838,8 +877,8 @@ - } - - static int --nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -853,8 +892,8 @@ - } - - static int --nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -868,8 +907,8 @@ - } - - static int --nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -883,8 +922,8 @@ - } - - static int --nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -898,8 +937,8 @@ - } - - static int --nv04_graph_mthd_bind_clip(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_clip(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -913,8 +952,8 @@ - } - - static int --nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - switch (nv_ri32(chan->dev, data << 4) & 0xff) { - case 0x30: -@@ -930,194 +969,346 @@ - return 1; - } - --static struct nouveau_pgraph_object_method nv04_graph_mthds_sw[] = { -- { 0x0150, nv04_graph_mthd_set_ref }, -- {} --}; -- --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_gdirect[] = { -- { 0x0184, nv04_graph_mthd_bind_nv01_patt }, -- { 0x0188, nv04_graph_mthd_bind_rop }, -- { 0x018c, nv04_graph_mthd_bind_beta1 }, -- { 0x0190, nv04_graph_mthd_bind_surf_dst }, -- { 0x02fc, nv04_graph_mthd_set_operation }, -- {}, --}; -- --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_gdirect[] = { -- { 0x0188, nv04_graph_mthd_bind_nv04_patt }, -- { 0x018c, nv04_graph_mthd_bind_rop }, -- { 0x0190, nv04_graph_mthd_bind_beta1 }, -- { 0x0194, nv04_graph_mthd_bind_beta4 }, -- { 0x0198, nv04_graph_mthd_bind_surf2d }, -- { 0x02fc, nv04_graph_mthd_set_operation }, -- {}, --}; -- --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_imageblit[] = { -- { 0x0184, nv04_graph_mthd_bind_chroma }, -- { 0x0188, nv04_graph_mthd_bind_clip }, -- { 0x018c, nv04_graph_mthd_bind_nv01_patt }, -- { 0x0190, nv04_graph_mthd_bind_rop }, -- { 0x0194, nv04_graph_mthd_bind_beta1 }, -- { 0x0198, nv04_graph_mthd_bind_surf_dst }, -- { 0x019c, nv04_graph_mthd_bind_surf_src }, -- { 0x02fc, nv04_graph_mthd_set_operation }, -- {}, --}; -- --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_imageblit_ifc[] = { -- { 0x0184, nv04_graph_mthd_bind_chroma }, -- { 0x0188, nv04_graph_mthd_bind_clip }, -- { 0x018c, nv04_graph_mthd_bind_nv04_patt }, -- { 0x0190, nv04_graph_mthd_bind_rop }, -- { 0x0194, nv04_graph_mthd_bind_beta1 }, -- { 0x0198, nv04_graph_mthd_bind_beta4 }, -- { 0x019c, nv04_graph_mthd_bind_surf2d }, -- { 0x02fc, nv04_graph_mthd_set_operation }, -- {}, --}; -- --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_iifc[] = { -- { 0x0188, nv04_graph_mthd_bind_chroma }, -- { 0x018c, nv04_graph_mthd_bind_clip }, -- { 0x0190, nv04_graph_mthd_bind_nv04_patt }, -- { 0x0194, nv04_graph_mthd_bind_rop }, -- { 0x0198, nv04_graph_mthd_bind_beta1 }, -- { 0x019c, nv04_graph_mthd_bind_beta4 }, -- { 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf }, -- { 0x03e4, nv04_graph_mthd_set_operation }, -- {}, --}; -- --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_ifc[] = { -- { 0x0184, nv04_graph_mthd_bind_chroma }, -- { 0x0188, nv04_graph_mthd_bind_clip }, -- { 0x018c, nv04_graph_mthd_bind_nv01_patt }, -- { 0x0190, nv04_graph_mthd_bind_rop }, -- { 0x0194, nv04_graph_mthd_bind_beta1 }, -- { 0x0198, nv04_graph_mthd_bind_surf_dst }, -- { 0x02fc, nv04_graph_mthd_set_operation }, -- {}, --}; -- --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_sifc[] = { -- { 0x0184, nv04_graph_mthd_bind_chroma }, -- { 0x0188, nv04_graph_mthd_bind_nv01_patt }, -- { 0x018c, nv04_graph_mthd_bind_rop }, -- { 0x0190, nv04_graph_mthd_bind_beta1 }, -- { 0x0194, nv04_graph_mthd_bind_surf_dst }, -- { 0x02fc, nv04_graph_mthd_set_operation }, -- {}, --}; -+static int -+nv04_graph_register(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; - --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_sifc[] = { -- { 0x0184, nv04_graph_mthd_bind_chroma }, -- { 0x0188, nv04_graph_mthd_bind_nv04_patt }, -- { 0x018c, nv04_graph_mthd_bind_rop }, -- { 0x0190, nv04_graph_mthd_bind_beta1 }, -- { 0x0194, nv04_graph_mthd_bind_beta4 }, -- { 0x0198, nv04_graph_mthd_bind_surf2d }, -- { 0x02fc, nv04_graph_mthd_set_operation }, -- {}, --}; -+ if (dev_priv->engine.graph.registered) -+ return 0; - --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_sifm[] = { -- { 0x0188, nv04_graph_mthd_bind_nv01_patt }, -- { 0x018c, nv04_graph_mthd_bind_rop }, -- { 0x0190, nv04_graph_mthd_bind_beta1 }, -- { 0x0194, nv04_graph_mthd_bind_surf_dst }, -- { 0x0304, nv04_graph_mthd_set_operation }, -- {}, --}; -+ /* dvd subpicture */ -+ NVOBJ_CLASS(dev, 0x0038, GR); - --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_sifm[] = { -- { 0x0188, nv04_graph_mthd_bind_nv04_patt }, -- { 0x018c, nv04_graph_mthd_bind_rop }, -- { 0x0190, nv04_graph_mthd_bind_beta1 }, -- { 0x0194, nv04_graph_mthd_bind_beta4 }, -- { 0x0198, nv04_graph_mthd_bind_surf2d_swzsurf }, -- { 0x0304, nv04_graph_mthd_set_operation }, -- {}, --}; -+ /* m2mf */ -+ NVOBJ_CLASS(dev, 0x0039, GR); - --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_shape[] = { -- { 0x0184, nv04_graph_mthd_bind_clip }, -- { 0x0188, nv04_graph_mthd_bind_nv01_patt }, -- { 0x018c, nv04_graph_mthd_bind_rop }, -- { 0x0190, nv04_graph_mthd_bind_beta1 }, -- { 0x0194, nv04_graph_mthd_bind_surf_dst }, -- { 0x02fc, nv04_graph_mthd_set_operation }, -- {}, --}; -+ /* nv03 gdirect */ -+ NVOBJ_CLASS(dev, 0x004b, GR); -+ NVOBJ_MTHD (dev, 0x004b, 0x0184, nv04_graph_mthd_bind_nv01_patt); -+ NVOBJ_MTHD (dev, 0x004b, 0x0188, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x004b, 0x018c, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x004b, 0x0190, nv04_graph_mthd_bind_surf_dst); -+ NVOBJ_MTHD (dev, 0x004b, 0x02fc, nv04_graph_mthd_set_operation); -+ -+ /* nv04 gdirect */ -+ NVOBJ_CLASS(dev, 0x004a, GR); -+ NVOBJ_MTHD (dev, 0x004a, 0x0188, nv04_graph_mthd_bind_nv04_patt); -+ NVOBJ_MTHD (dev, 0x004a, 0x018c, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x004a, 0x0190, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x004a, 0x0194, nv04_graph_mthd_bind_beta4); -+ NVOBJ_MTHD (dev, 0x004a, 0x0198, nv04_graph_mthd_bind_surf2d); -+ NVOBJ_MTHD (dev, 0x004a, 0x02fc, nv04_graph_mthd_set_operation); -+ -+ /* nv01 imageblit */ -+ NVOBJ_CLASS(dev, 0x001f, GR); -+ NVOBJ_MTHD (dev, 0x001f, 0x0184, nv04_graph_mthd_bind_chroma); -+ NVOBJ_MTHD (dev, 0x001f, 0x0188, nv04_graph_mthd_bind_clip); -+ NVOBJ_MTHD (dev, 0x001f, 0x018c, nv04_graph_mthd_bind_nv01_patt); -+ NVOBJ_MTHD (dev, 0x001f, 0x0190, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x001f, 0x0194, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x001f, 0x0198, nv04_graph_mthd_bind_surf_dst); -+ NVOBJ_MTHD (dev, 0x001f, 0x019c, nv04_graph_mthd_bind_surf_src); -+ NVOBJ_MTHD (dev, 0x001f, 0x02fc, nv04_graph_mthd_set_operation); -+ -+ /* nv04 imageblit */ -+ NVOBJ_CLASS(dev, 0x005f, GR); -+ NVOBJ_MTHD (dev, 0x005f, 0x0184, nv04_graph_mthd_bind_chroma); -+ NVOBJ_MTHD (dev, 0x005f, 0x0188, nv04_graph_mthd_bind_clip); -+ NVOBJ_MTHD (dev, 0x005f, 0x018c, nv04_graph_mthd_bind_nv04_patt); -+ NVOBJ_MTHD (dev, 0x005f, 0x0190, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x005f, 0x0194, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x005f, 0x0198, nv04_graph_mthd_bind_beta4); -+ NVOBJ_MTHD (dev, 0x005f, 0x019c, nv04_graph_mthd_bind_surf2d); -+ NVOBJ_MTHD (dev, 0x005f, 0x02fc, nv04_graph_mthd_set_operation); -+ -+ /* nv04 iifc */ -+ NVOBJ_CLASS(dev, 0x0060, GR); -+ NVOBJ_MTHD (dev, 0x0060, 0x0188, nv04_graph_mthd_bind_chroma); -+ NVOBJ_MTHD (dev, 0x0060, 0x018c, nv04_graph_mthd_bind_clip); -+ NVOBJ_MTHD (dev, 0x0060, 0x0190, nv04_graph_mthd_bind_nv04_patt); -+ NVOBJ_MTHD (dev, 0x0060, 0x0194, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x0060, 0x0198, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x0060, 0x019c, nv04_graph_mthd_bind_beta4); -+ NVOBJ_MTHD (dev, 0x0060, 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf); -+ NVOBJ_MTHD (dev, 0x0060, 0x03e4, nv04_graph_mthd_set_operation); -+ -+ /* nv05 iifc */ -+ NVOBJ_CLASS(dev, 0x0064, GR); -+ -+ /* nv01 ifc */ -+ NVOBJ_CLASS(dev, 0x0021, GR); -+ NVOBJ_MTHD (dev, 0x0021, 0x0184, nv04_graph_mthd_bind_chroma); -+ NVOBJ_MTHD (dev, 0x0021, 0x0188, nv04_graph_mthd_bind_clip); -+ NVOBJ_MTHD (dev, 0x0021, 0x018c, nv04_graph_mthd_bind_nv01_patt); -+ NVOBJ_MTHD (dev, 0x0021, 0x0190, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x0021, 0x0194, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x0021, 0x0198, nv04_graph_mthd_bind_surf_dst); -+ NVOBJ_MTHD (dev, 0x0021, 0x02fc, nv04_graph_mthd_set_operation); -+ -+ /* nv04 ifc */ -+ NVOBJ_CLASS(dev, 0x0061, GR); -+ NVOBJ_MTHD (dev, 0x0061, 0x0184, nv04_graph_mthd_bind_chroma); -+ NVOBJ_MTHD (dev, 0x0061, 0x0188, nv04_graph_mthd_bind_clip); -+ NVOBJ_MTHD (dev, 0x0061, 0x018c, nv04_graph_mthd_bind_nv04_patt); -+ NVOBJ_MTHD (dev, 0x0061, 0x0190, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x0061, 0x0194, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x0061, 0x0198, nv04_graph_mthd_bind_beta4); -+ NVOBJ_MTHD (dev, 0x0061, 0x019c, nv04_graph_mthd_bind_surf2d); -+ NVOBJ_MTHD (dev, 0x0061, 0x02fc, nv04_graph_mthd_set_operation); -+ -+ /* nv05 ifc */ -+ NVOBJ_CLASS(dev, 0x0065, GR); -+ -+ /* nv03 sifc */ -+ NVOBJ_CLASS(dev, 0x0036, GR); -+ NVOBJ_MTHD (dev, 0x0036, 0x0184, nv04_graph_mthd_bind_chroma); -+ NVOBJ_MTHD (dev, 0x0036, 0x0188, nv04_graph_mthd_bind_nv01_patt); -+ NVOBJ_MTHD (dev, 0x0036, 0x018c, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x0036, 0x0190, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x0036, 0x0194, nv04_graph_mthd_bind_surf_dst); -+ NVOBJ_MTHD (dev, 0x0036, 0x02fc, nv04_graph_mthd_set_operation); -+ -+ /* nv04 sifc */ -+ NVOBJ_CLASS(dev, 0x0076, GR); -+ NVOBJ_MTHD (dev, 0x0076, 0x0184, nv04_graph_mthd_bind_chroma); -+ NVOBJ_MTHD (dev, 0x0076, 0x0188, nv04_graph_mthd_bind_nv04_patt); -+ NVOBJ_MTHD (dev, 0x0076, 0x018c, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x0076, 0x0190, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x0076, 0x0194, nv04_graph_mthd_bind_beta4); -+ NVOBJ_MTHD (dev, 0x0076, 0x0198, nv04_graph_mthd_bind_surf2d); -+ NVOBJ_MTHD (dev, 0x0076, 0x02fc, nv04_graph_mthd_set_operation); -+ -+ /* nv05 sifc */ -+ NVOBJ_CLASS(dev, 0x0066, GR); -+ -+ /* nv03 sifm */ -+ NVOBJ_CLASS(dev, 0x0037, GR); -+ NVOBJ_MTHD (dev, 0x0037, 0x0188, nv04_graph_mthd_bind_nv01_patt); -+ NVOBJ_MTHD (dev, 0x0037, 0x018c, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x0037, 0x0190, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x0037, 0x0194, nv04_graph_mthd_bind_surf_dst); -+ NVOBJ_MTHD (dev, 0x0037, 0x0304, nv04_graph_mthd_set_operation); -+ -+ /* nv04 sifm */ -+ NVOBJ_CLASS(dev, 0x0077, GR); -+ NVOBJ_MTHD (dev, 0x0077, 0x0188, nv04_graph_mthd_bind_nv04_patt); -+ NVOBJ_MTHD (dev, 0x0077, 0x018c, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x0077, 0x0190, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x0077, 0x0194, nv04_graph_mthd_bind_beta4); -+ NVOBJ_MTHD (dev, 0x0077, 0x0198, nv04_graph_mthd_bind_surf2d_swzsurf); -+ NVOBJ_MTHD (dev, 0x0077, 0x0304, nv04_graph_mthd_set_operation); -+ -+ /* null */ -+ NVOBJ_CLASS(dev, 0x0030, GR); -+ -+ /* surf2d */ -+ NVOBJ_CLASS(dev, 0x0042, GR); -+ -+ /* rop */ -+ NVOBJ_CLASS(dev, 0x0043, GR); -+ -+ /* beta1 */ -+ NVOBJ_CLASS(dev, 0x0012, GR); -+ -+ /* beta4 */ -+ NVOBJ_CLASS(dev, 0x0072, GR); -+ -+ /* cliprect */ -+ NVOBJ_CLASS(dev, 0x0019, GR); -+ -+ /* nv01 pattern */ -+ NVOBJ_CLASS(dev, 0x0018, GR); -+ -+ /* nv04 pattern */ -+ NVOBJ_CLASS(dev, 0x0044, GR); -+ -+ /* swzsurf */ -+ NVOBJ_CLASS(dev, 0x0052, GR); -+ -+ /* surf3d */ -+ NVOBJ_CLASS(dev, 0x0053, GR); -+ NVOBJ_MTHD (dev, 0x0053, 0x02f8, nv04_graph_mthd_surf3d_clip_h); -+ NVOBJ_MTHD (dev, 0x0053, 0x02fc, nv04_graph_mthd_surf3d_clip_v); -+ -+ /* nv03 tex_tri */ -+ NVOBJ_CLASS(dev, 0x0048, GR); -+ NVOBJ_MTHD (dev, 0x0048, 0x0188, nv04_graph_mthd_bind_clip); -+ NVOBJ_MTHD (dev, 0x0048, 0x018c, nv04_graph_mthd_bind_surf_color); -+ NVOBJ_MTHD (dev, 0x0048, 0x0190, nv04_graph_mthd_bind_surf_zeta); -+ -+ /* tex_tri */ -+ NVOBJ_CLASS(dev, 0x0054, GR); -+ -+ /* multitex_tri */ -+ NVOBJ_CLASS(dev, 0x0055, GR); -+ -+ /* nv01 chroma */ -+ NVOBJ_CLASS(dev, 0x0017, GR); -+ -+ /* nv04 chroma */ -+ NVOBJ_CLASS(dev, 0x0057, GR); -+ -+ /* surf_dst */ -+ NVOBJ_CLASS(dev, 0x0058, GR); -+ -+ /* surf_src */ -+ NVOBJ_CLASS(dev, 0x0059, GR); -+ -+ /* surf_color */ -+ NVOBJ_CLASS(dev, 0x005a, GR); -+ -+ /* surf_zeta */ -+ NVOBJ_CLASS(dev, 0x005b, GR); -+ -+ /* nv01 line */ -+ NVOBJ_CLASS(dev, 0x001c, GR); -+ NVOBJ_MTHD (dev, 0x001c, 0x0184, nv04_graph_mthd_bind_clip); -+ NVOBJ_MTHD (dev, 0x001c, 0x0188, nv04_graph_mthd_bind_nv01_patt); -+ NVOBJ_MTHD (dev, 0x001c, 0x018c, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x001c, 0x0190, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x001c, 0x0194, nv04_graph_mthd_bind_surf_dst); -+ NVOBJ_MTHD (dev, 0x001c, 0x02fc, nv04_graph_mthd_set_operation); -+ -+ /* nv04 line */ -+ NVOBJ_CLASS(dev, 0x005c, GR); -+ NVOBJ_MTHD (dev, 0x005c, 0x0184, nv04_graph_mthd_bind_clip); -+ NVOBJ_MTHD (dev, 0x005c, 0x0188, nv04_graph_mthd_bind_nv04_patt); -+ NVOBJ_MTHD (dev, 0x005c, 0x018c, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x005c, 0x0190, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x005c, 0x0194, nv04_graph_mthd_bind_beta4); -+ NVOBJ_MTHD (dev, 0x005c, 0x0198, nv04_graph_mthd_bind_surf2d); -+ NVOBJ_MTHD (dev, 0x005c, 0x02fc, nv04_graph_mthd_set_operation); -+ -+ /* nv01 tri */ -+ NVOBJ_CLASS(dev, 0x001d, GR); -+ NVOBJ_MTHD (dev, 0x001d, 0x0184, nv04_graph_mthd_bind_clip); -+ NVOBJ_MTHD (dev, 0x001d, 0x0188, nv04_graph_mthd_bind_nv01_patt); -+ NVOBJ_MTHD (dev, 0x001d, 0x018c, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x001d, 0x0190, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x001d, 0x0194, nv04_graph_mthd_bind_surf_dst); -+ NVOBJ_MTHD (dev, 0x001d, 0x02fc, nv04_graph_mthd_set_operation); -+ -+ /* nv04 tri */ -+ NVOBJ_CLASS(dev, 0x005d, GR); -+ NVOBJ_MTHD (dev, 0x005d, 0x0184, nv04_graph_mthd_bind_clip); -+ NVOBJ_MTHD (dev, 0x005d, 0x0188, nv04_graph_mthd_bind_nv04_patt); -+ NVOBJ_MTHD (dev, 0x005d, 0x018c, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x005d, 0x0190, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x005d, 0x0194, nv04_graph_mthd_bind_beta4); -+ NVOBJ_MTHD (dev, 0x005d, 0x0198, nv04_graph_mthd_bind_surf2d); -+ NVOBJ_MTHD (dev, 0x005d, 0x02fc, nv04_graph_mthd_set_operation); -+ -+ /* nv01 rect */ -+ NVOBJ_CLASS(dev, 0x001e, GR); -+ NVOBJ_MTHD (dev, 0x001e, 0x0184, nv04_graph_mthd_bind_clip); -+ NVOBJ_MTHD (dev, 0x001e, 0x0188, nv04_graph_mthd_bind_nv01_patt); -+ NVOBJ_MTHD (dev, 0x001e, 0x018c, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x001e, 0x0190, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x001e, 0x0194, nv04_graph_mthd_bind_surf_dst); -+ NVOBJ_MTHD (dev, 0x001e, 0x02fc, nv04_graph_mthd_set_operation); -+ -+ /* nv04 rect */ -+ NVOBJ_CLASS(dev, 0x005e, GR); -+ NVOBJ_MTHD (dev, 0x005e, 0x0184, nv04_graph_mthd_bind_clip); -+ NVOBJ_MTHD (dev, 0x005e, 0x0188, nv04_graph_mthd_bind_nv04_patt); -+ NVOBJ_MTHD (dev, 0x005e, 0x018c, nv04_graph_mthd_bind_rop); -+ NVOBJ_MTHD (dev, 0x005e, 0x0190, nv04_graph_mthd_bind_beta1); -+ NVOBJ_MTHD (dev, 0x005e, 0x0194, nv04_graph_mthd_bind_beta4); -+ NVOBJ_MTHD (dev, 0x005e, 0x0198, nv04_graph_mthd_bind_surf2d); -+ NVOBJ_MTHD (dev, 0x005e, 0x02fc, nv04_graph_mthd_set_operation); -+ -+ /* nvsw */ -+ NVOBJ_CLASS(dev, 0x506e, SW); -+ NVOBJ_MTHD (dev, 0x506e, 0x0150, nv04_graph_mthd_set_ref); -+ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); - --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_shape[] = { -- { 0x0184, nv04_graph_mthd_bind_clip }, -- { 0x0188, nv04_graph_mthd_bind_nv04_patt }, -- { 0x018c, nv04_graph_mthd_bind_rop }, -- { 0x0190, nv04_graph_mthd_bind_beta1 }, -- { 0x0194, nv04_graph_mthd_bind_beta4 }, -- { 0x0198, nv04_graph_mthd_bind_surf2d }, -- { 0x02fc, nv04_graph_mthd_set_operation }, -- {}, -+ dev_priv->engine.graph.registered = true; -+ return 0; - }; - --static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_tex_tri[] = { -- { 0x0188, nv04_graph_mthd_bind_clip }, -- { 0x018c, nv04_graph_mthd_bind_surf_color }, -- { 0x0190, nv04_graph_mthd_bind_surf_zeta }, -- {}, -+static struct nouveau_bitfield nv04_graph_intr[] = { -+ { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, -+ {} - }; - --static struct nouveau_pgraph_object_method nv04_graph_mthds_surf3d[] = { -- { 0x02f8, nv04_graph_mthd_surf3d_clip_h }, -- { 0x02fc, nv04_graph_mthd_surf3d_clip_v }, -- {}, -+static struct nouveau_bitfield nv04_graph_nstatus[] = -+{ -+ { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, -+ { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, -+ { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, -+ { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" }, -+ {} - }; - --struct nouveau_pgraph_object_class nv04_graph_grclass[] = { -- { 0x0038, false, NULL }, /* dvd subpicture */ -- { 0x0039, false, NULL }, /* m2mf */ -- { 0x004b, false, nv04_graph_mthds_nv03_gdirect }, /* nv03 gdirect */ -- { 0x004a, false, nv04_graph_mthds_nv04_gdirect }, /* nv04 gdirect */ -- { 0x001f, false, nv04_graph_mthds_nv01_imageblit }, /* nv01 imageblit */ -- { 0x005f, false, nv04_graph_mthds_nv04_imageblit_ifc }, /* nv04 imageblit */ -- { 0x0060, false, nv04_graph_mthds_nv04_iifc }, /* nv04 iifc */ -- { 0x0064, false, NULL }, /* nv05 iifc */ -- { 0x0021, false, nv04_graph_mthds_nv01_ifc }, /* nv01 ifc */ -- { 0x0061, false, nv04_graph_mthds_nv04_imageblit_ifc }, /* nv04 ifc */ -- { 0x0065, false, NULL }, /* nv05 ifc */ -- { 0x0036, false, nv04_graph_mthds_nv03_sifc }, /* nv03 sifc */ -- { 0x0076, false, nv04_graph_mthds_nv04_sifc }, /* nv04 sifc */ -- { 0x0066, false, NULL }, /* nv05 sifc */ -- { 0x0037, false, nv04_graph_mthds_nv03_sifm }, /* nv03 sifm */ -- { 0x0077, false, nv04_graph_mthds_nv04_sifm }, /* nv04 sifm */ -- { 0x0030, false, NULL }, /* null */ -- { 0x0042, false, NULL }, /* surf2d */ -- { 0x0043, false, NULL }, /* rop */ -- { 0x0012, false, NULL }, /* beta1 */ -- { 0x0072, false, NULL }, /* beta4 */ -- { 0x0019, false, NULL }, /* cliprect */ -- { 0x0018, false, NULL }, /* nv01 pattern */ -- { 0x0044, false, NULL }, /* nv04 pattern */ -- { 0x0052, false, NULL }, /* swzsurf */ -- { 0x0053, false, nv04_graph_mthds_surf3d }, /* surf3d */ -- { 0x0048, false, nv04_graph_mthds_nv03_tex_tri }, /* nv03 tex_tri */ -- { 0x0054, false, NULL }, /* tex_tri */ -- { 0x0055, false, NULL }, /* multitex_tri */ -- { 0x0017, false, NULL }, /* nv01 chroma */ -- { 0x0057, false, NULL }, /* nv04 chroma */ -- { 0x0058, false, NULL }, /* surf_dst */ -- { 0x0059, false, NULL }, /* surf_src */ -- { 0x005a, false, NULL }, /* surf_color */ -- { 0x005b, false, NULL }, /* surf_zeta */ -- { 0x001c, false, nv04_graph_mthds_nv01_shape }, /* nv01 line */ -- { 0x005c, false, nv04_graph_mthds_nv04_shape }, /* nv04 line */ -- { 0x001d, false, nv04_graph_mthds_nv01_shape }, /* nv01 tri */ -- { 0x005d, false, nv04_graph_mthds_nv04_shape }, /* nv04 tri */ -- { 0x001e, false, nv04_graph_mthds_nv01_shape }, /* nv01 rect */ -- { 0x005e, false, nv04_graph_mthds_nv04_shape }, /* nv04 rect */ -- { 0x506e, true, nv04_graph_mthds_sw }, -+struct nouveau_bitfield nv04_graph_nsource[] = -+{ -+ { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" }, -+ { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" }, -+ { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" }, -+ { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION, "RANGE_EXCEPTION" }, -+ { NV03_PGRAPH_NSOURCE_LIMIT_COLOR, "LIMIT_COLOR" }, -+ { NV03_PGRAPH_NSOURCE_LIMIT_ZETA, "LIMIT_ZETA" }, -+ { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD, "ILLEGAL_MTHD" }, -+ { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION, "DMA_R_PROTECTION" }, -+ { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION, "DMA_W_PROTECTION" }, -+ { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION, "FORMAT_EXCEPTION" }, -+ { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION, "PATCH_EXCEPTION" }, -+ { NV03_PGRAPH_NSOURCE_STATE_INVALID, "STATE_INVALID" }, -+ { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY, "DOUBLE_NOTIFY" }, -+ { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE, "NOTIFY_IN_USE" }, -+ { NV03_PGRAPH_NSOURCE_METHOD_CNT, "METHOD_CNT" }, -+ { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION, "BFR_NOTIFICATION" }, -+ { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" }, -+ { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A, "DMA_WIDTH_A" }, -+ { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B, "DMA_WIDTH_B" }, - {} - }; - -+static void -+nv04_graph_isr(struct drm_device *dev) -+{ -+ u32 stat; -+ -+ while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { -+ u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); -+ u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); -+ u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); -+ u32 chid = (addr & 0x0f000000) >> 24; -+ u32 subc = (addr & 0x0000e000) >> 13; -+ u32 mthd = (addr & 0x00001ffc); -+ u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); -+ u32 class = nv_rd32(dev, 0x400180 + subc * 4) & 0xff; -+ u32 show = stat; -+ -+ if (stat & NV_PGRAPH_INTR_NOTIFY) { -+ if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { -+ if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) -+ show &= ~NV_PGRAPH_INTR_NOTIFY; -+ } -+ } -+ -+ if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { -+ nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); -+ stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; -+ show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; -+ nv04_graph_context_switch(dev); -+ } -+ -+ nv_wr32(dev, NV03_PGRAPH_INTR, stat); -+ nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); -+ -+ if (show && nouveau_ratelimit()) { -+ NV_INFO(dev, "PGRAPH -"); -+ nouveau_bitfield_print(nv04_graph_intr, show); -+ printk(" nsource:"); -+ nouveau_bitfield_print(nv04_graph_nsource, nsource); -+ printk(" nstatus:"); -+ nouveau_bitfield_print(nv04_graph_nstatus, nstatus); -+ printk("\n"); -+ NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x " -+ "mthd 0x%04x data 0x%08x\n", -+ chid, subc, class, mthd, data); -+ } -+ } -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_instmem.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv04_instmem.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv04_instmem.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv04_instmem.c 2011-01-07 14:22:17.000000000 +0100 -@@ -98,42 +98,66 @@ - } - - int --nv04_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, -- uint32_t *sz) -+nv04_instmem_suspend(struct drm_device *dev) - { - return 0; - } - - void --nv04_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) -+nv04_instmem_resume(struct drm_device *dev) - { - } - - int --nv04_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) -+nv04_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align) - { -- return 0; --} -+ struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; -+ struct drm_mm_node *ramin = NULL; - --int --nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) --{ -+ do { -+ if (drm_mm_pre_get(&dev_priv->ramin_heap)) -+ return -ENOMEM; -+ -+ spin_lock(&dev_priv->ramin_lock); -+ ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0); -+ if (ramin == NULL) { -+ spin_unlock(&dev_priv->ramin_lock); -+ return -ENOMEM; -+ } -+ -+ ramin = drm_mm_get_block_atomic(ramin, size, align); -+ spin_unlock(&dev_priv->ramin_lock); -+ } while (ramin == NULL); -+ -+ gpuobj->node = ramin; -+ gpuobj->vinst = ramin->start; - return 0; - } - - void --nv04_instmem_flush(struct drm_device *dev) -+nv04_instmem_put(struct nouveau_gpuobj *gpuobj) - { -+ struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; -+ -+ spin_lock(&dev_priv->ramin_lock); -+ drm_mm_put_block(gpuobj->node); -+ gpuobj->node = NULL; -+ spin_unlock(&dev_priv->ramin_lock); - } - - int --nv04_instmem_suspend(struct drm_device *dev) -+nv04_instmem_map(struct nouveau_gpuobj *gpuobj) - { -+ gpuobj->pinst = gpuobj->vinst; - return 0; - } - - void --nv04_instmem_resume(struct drm_device *dev) -+nv04_instmem_unmap(struct nouveau_gpuobj *gpuobj) - { - } - -+void -+nv04_instmem_flush(struct drm_device *dev) -+{ -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv10_fb.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv10_fb.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv10_fb.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv10_fb.c 2011-01-07 14:22:17.000000000 +0100 -@@ -3,23 +3,109 @@ - #include "nouveau_drv.h" - #include "nouveau_drm.h" - -+static struct drm_mm_node * -+nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; -+ struct drm_mm_node *mem; -+ int ret; -+ -+ ret = drm_mm_pre_get(&pfb->tag_heap); -+ if (ret) -+ return NULL; -+ -+ spin_lock(&dev_priv->tile.lock); -+ mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0); -+ if (mem) -+ mem = drm_mm_get_block_atomic(mem, size, 0); -+ spin_unlock(&dev_priv->tile.lock); -+ -+ return mem; -+} -+ -+static void -+nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node *mem) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ spin_lock(&dev_priv->tile.lock); -+ drm_mm_put_block(mem); -+ spin_unlock(&dev_priv->tile.lock); -+} -+ -+void -+nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, -+ uint32_t size, uint32_t pitch, uint32_t flags) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; -+ int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16); -+ -+ tile->addr = addr; -+ tile->limit = max(1u, addr + size) - 1; -+ tile->pitch = pitch; -+ -+ if (dev_priv->card_type == NV_20) { -+ if (flags & NOUVEAU_GEM_TILE_ZETA) { -+ /* -+ * Allocate some of the on-die tag memory, -+ * used to store Z compression meta-data (most -+ * likely just a bitmap determining if a given -+ * tile is compressed or not). -+ */ -+ tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256); -+ -+ if (tile->tag_mem) { -+ /* Enable Z compression */ -+ if (dev_priv->chipset >= 0x25) -+ tile->zcomp = tile->tag_mem->start | -+ (bpp == 16 ? -+ NV25_PFB_ZCOMP_MODE_16 : -+ NV25_PFB_ZCOMP_MODE_32); -+ else -+ tile->zcomp = tile->tag_mem->start | -+ NV20_PFB_ZCOMP_EN | -+ (bpp == 16 ? 0 : -+ NV20_PFB_ZCOMP_MODE_32); -+ } -+ -+ tile->addr |= 3; -+ } else { -+ tile->addr |= 1; -+ } -+ -+ } else { -+ tile->addr |= 1 << 31; -+ } -+} -+ - void --nv10_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch) -+nv10_fb_free_tile_region(struct drm_device *dev, int i) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t limit = max(1u, addr + size) - 1; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - -- if (pitch) { -- if (dev_priv->card_type >= NV_20) -- addr |= 1; -- else -- addr |= 1 << 31; -+ if (tile->tag_mem) { -+ nv20_fb_free_tag(dev, tile->tag_mem); -+ tile->tag_mem = NULL; - } - -- nv_wr32(dev, NV10_PFB_TLIMIT(i), limit); -- nv_wr32(dev, NV10_PFB_TSIZE(i), pitch); -- nv_wr32(dev, NV10_PFB_TILE(i), addr); -+ tile->addr = tile->limit = tile->pitch = tile->zcomp = 0; -+} -+ -+void -+nv10_fb_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, NV10_PFB_TLIMIT(i), tile->limit); -+ nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); -+ nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); -+ -+ if (dev_priv->card_type == NV_20) -+ nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp); - } - - int -@@ -31,9 +117,14 @@ - - pfb->num_tiles = NV10_PFB_TILE__SIZE; - -+ if (dev_priv->card_type == NV_20) -+ drm_mm_init(&pfb->tag_heap, 0, -+ (dev_priv->chipset >= 0x25 ? -+ 64 * 1024 : 32 * 1024)); -+ - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) -- pfb->set_region_tiling(dev, i, 0, 0, 0); -+ pfb->set_tile_region(dev, i); - - return 0; - } -@@ -41,4 +132,13 @@ - void - nv10_fb_takedown(struct drm_device *dev) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; -+ int i; -+ -+ for (i = 0; i < pfb->num_tiles; i++) -+ pfb->free_tile_region(dev, i); -+ -+ if (dev_priv->card_type == NV_20) -+ drm_mm_takedown(&pfb->tag_heap); - } -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv10_fifo.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv10_fifo.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv10_fifo.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv10_fifo.c 2011-01-07 14:22:17.000000000 +0100 -@@ -53,6 +53,11 @@ - if (ret) - return ret; - -+ chan->user = ioremap(pci_resource_start(dev->pdev, 0) + -+ NV03_USER(chan->id), PAGE_SIZE); -+ if (!chan->user) -+ return -ENOMEM; -+ - /* Fill entries that are seen filled in dumps of nvidia driver just - * after channel's is put into DMA mode - */ -@@ -73,17 +78,6 @@ - return 0; - } - --void --nv10_fifo_destroy_context(struct nouveau_channel *chan) --{ -- struct drm_device *dev = chan->dev; -- -- nv_wr32(dev, NV04_PFIFO_MODE, -- nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); -- -- nouveau_gpuobj_ref(NULL, &chan->ramfc); --} -- - static void - nv10_fifo_do_load_context(struct drm_device *dev, int chid) - { -@@ -219,6 +213,7 @@ - static void - nv10_fifo_init_intr(struct drm_device *dev) - { -+ nouveau_irq_register(dev, 8, nv04_fifo_isr); - nv_wr32(dev, 0x002100, 0xffffffff); - nv_wr32(dev, 0x002140, 0xffffffff); - } -@@ -241,7 +236,7 @@ - pfifo->reassign(dev, true); - - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- if (dev_priv->fifos[i]) { -+ if (dev_priv->channels.ptr[i]) { - uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); - nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); - } -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv10_graph.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv10_graph.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv10_graph.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv10_graph.c 2011-01-07 14:22:17.000000000 +0100 -@@ -26,6 +26,10 @@ - #include "drm.h" - #include "nouveau_drm.h" - #include "nouveau_drv.h" -+#include "nouveau_util.h" -+ -+static int nv10_graph_register(struct drm_device *); -+static void nv10_graph_isr(struct drm_device *); - - #define NV10_FIFO_NUMBER 32 - -@@ -786,15 +790,13 @@ - return 0; - } - --void -+static void - nv10_graph_context_switch(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - struct nouveau_channel *chan = NULL; - int chid; - -- pgraph->fifo_access(dev, false); - nouveau_wait_for_idle(dev); - - /* If previous context is valid, we need to save it */ -@@ -802,11 +804,9 @@ - - /* Load context for next channel */ - chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; -- chan = dev_priv->fifos[chid]; -+ chan = dev_priv->channels.ptr[chid]; - if (chan && chan->pgraph_ctx) - nv10_graph_load_context(chan); -- -- pgraph->fifo_access(dev, true); - } - - #define NV_WRITE_CTX(reg, val) do { \ -@@ -833,7 +833,7 @@ - if (chid >= dev_priv->engine.fifo.channels) - return NULL; - -- return dev_priv->fifos[chid]; -+ return dev_priv->channels.ptr[chid]; - } - - int nv10_graph_create_context(struct nouveau_channel *chan) -@@ -875,37 +875,54 @@ - - void nv10_graph_destroy_context(struct nouveau_channel *chan) - { -+ struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - struct graph_state *pgraph_ctx = chan->pgraph_ctx; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ pgraph->fifo_access(dev, false); -+ -+ /* Unload the context if it's the currently active one */ -+ if (pgraph->channel(dev) == chan) -+ pgraph->unload_context(dev); - -+ /* Free the context resources */ - kfree(pgraph_ctx); - chan->pgraph_ctx = NULL; -+ -+ pgraph->fifo_access(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - } - - void --nv10_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch) -+nv10_graph_set_tile_region(struct drm_device *dev, int i) - { -- uint32_t limit = max(1u, addr + size) - 1; -- -- if (pitch) -- addr |= 1 << 31; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - -- nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), limit); -- nv_wr32(dev, NV10_PGRAPH_TSIZE(i), pitch); -- nv_wr32(dev, NV10_PGRAPH_TILE(i), addr); -+ nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), tile->limit); -+ nv_wr32(dev, NV10_PGRAPH_TSIZE(i), tile->pitch); -+ nv_wr32(dev, NV10_PGRAPH_TILE(i), tile->addr); - } - - int nv10_graph_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t tmp; -- int i; -+ int ret, i; - - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & - ~NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | - NV_PMC_ENABLE_PGRAPH); - -+ ret = nv10_graph_register(dev); -+ if (ret) -+ return ret; -+ -+ nouveau_irq_register(dev, 12, nv10_graph_isr); - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - -@@ -928,7 +945,7 @@ - - /* Turn all the tiling regions off. */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) -- nv10_graph_set_region_tiling(dev, i, 0, 0, 0); -+ nv10_graph_set_tile_region(dev, i); - - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000); - nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000); -@@ -948,17 +965,17 @@ - - void nv10_graph_takedown(struct drm_device *dev) - { -+ nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); -+ nouveau_irq_unregister(dev, 12); - } - - static int --nv17_graph_mthd_lma_window(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv17_graph_mthd_lma_window(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - struct drm_device *dev = chan->dev; - struct graph_state *ctx = chan->pgraph_ctx; - struct pipe_state *pipe = &ctx->pipe_state; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - uint32_t pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3]; - uint32_t xfmode0, xfmode1; - int i; -@@ -1025,18 +1042,14 @@ - - nouveau_wait_for_idle(dev); - -- pgraph->fifo_access(dev, true); -- - return 0; - } - - static int --nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - struct drm_device *dev = chan->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - - nouveau_wait_for_idle(dev); - -@@ -1045,40 +1058,118 @@ - nv_wr32(dev, 0x004006b0, - nv_rd32(dev, 0x004006b0) | 0x8 << 24); - -- pgraph->fifo_access(dev, true); -+ return 0; -+} -+ -+static int -+nv10_graph_register(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->engine.graph.registered) -+ return 0; -+ -+ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ -+ NVOBJ_CLASS(dev, 0x0030, GR); /* null */ -+ NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ -+ NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ -+ NVOBJ_CLASS(dev, 0x005f, GR); /* imageblit */ -+ NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ -+ NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ -+ NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ -+ NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ -+ NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ -+ NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ -+ NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ -+ NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ -+ NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ -+ NVOBJ_CLASS(dev, 0x0052, GR); /* swzsurf */ -+ NVOBJ_CLASS(dev, 0x0093, GR); /* surf3d */ -+ NVOBJ_CLASS(dev, 0x0094, GR); /* tex_tri */ -+ NVOBJ_CLASS(dev, 0x0095, GR); /* multitex_tri */ -+ -+ /* celcius */ -+ if (dev_priv->chipset <= 0x10) { -+ NVOBJ_CLASS(dev, 0x0056, GR); -+ } else -+ if (dev_priv->chipset < 0x17 || dev_priv->chipset == 0x1a) { -+ NVOBJ_CLASS(dev, 0x0096, GR); -+ } else { -+ NVOBJ_CLASS(dev, 0x0099, GR); -+ NVOBJ_MTHD (dev, 0x0099, 0x1638, nv17_graph_mthd_lma_window); -+ NVOBJ_MTHD (dev, 0x0099, 0x163c, nv17_graph_mthd_lma_window); -+ NVOBJ_MTHD (dev, 0x0099, 0x1640, nv17_graph_mthd_lma_window); -+ NVOBJ_MTHD (dev, 0x0099, 0x1644, nv17_graph_mthd_lma_window); -+ NVOBJ_MTHD (dev, 0x0099, 0x1658, nv17_graph_mthd_lma_enable); -+ } -+ -+ /* nvsw */ -+ NVOBJ_CLASS(dev, 0x506e, SW); -+ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); - -+ dev_priv->engine.graph.registered = true; - return 0; - } - --static struct nouveau_pgraph_object_method nv17_graph_celsius_mthds[] = { -- { 0x1638, nv17_graph_mthd_lma_window }, -- { 0x163c, nv17_graph_mthd_lma_window }, -- { 0x1640, nv17_graph_mthd_lma_window }, -- { 0x1644, nv17_graph_mthd_lma_window }, -- { 0x1658, nv17_graph_mthd_lma_enable }, -+struct nouveau_bitfield nv10_graph_intr[] = { -+ { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, -+ { NV_PGRAPH_INTR_ERROR, "ERROR" }, - {} - }; - --struct nouveau_pgraph_object_class nv10_graph_grclass[] = { -- { 0x0030, false, NULL }, /* null */ -- { 0x0039, false, NULL }, /* m2mf */ -- { 0x004a, false, NULL }, /* gdirect */ -- { 0x005f, false, NULL }, /* imageblit */ -- { 0x009f, false, NULL }, /* imageblit (nv12) */ -- { 0x008a, false, NULL }, /* ifc */ -- { 0x0089, false, NULL }, /* sifm */ -- { 0x0062, false, NULL }, /* surf2d */ -- { 0x0043, false, NULL }, /* rop */ -- { 0x0012, false, NULL }, /* beta1 */ -- { 0x0072, false, NULL }, /* beta4 */ -- { 0x0019, false, NULL }, /* cliprect */ -- { 0x0044, false, NULL }, /* pattern */ -- { 0x0052, false, NULL }, /* swzsurf */ -- { 0x0093, false, NULL }, /* surf3d */ -- { 0x0094, false, NULL }, /* tex_tri */ -- { 0x0095, false, NULL }, /* multitex_tri */ -- { 0x0056, false, NULL }, /* celcius (nv10) */ -- { 0x0096, false, NULL }, /* celcius (nv11) */ -- { 0x0099, false, nv17_graph_celsius_mthds }, /* celcius (nv17) */ -+struct nouveau_bitfield nv10_graph_nstatus[] = -+{ -+ { NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, -+ { NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, -+ { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, -+ { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" }, - {} - }; -+ -+static void -+nv10_graph_isr(struct drm_device *dev) -+{ -+ u32 stat; -+ -+ while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { -+ u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); -+ u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); -+ u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); -+ u32 chid = (addr & 0x01f00000) >> 20; -+ u32 subc = (addr & 0x00070000) >> 16; -+ u32 mthd = (addr & 0x00001ffc); -+ u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); -+ u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xfff; -+ u32 show = stat; -+ -+ if (stat & NV_PGRAPH_INTR_ERROR) { -+ if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { -+ if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) -+ show &= ~NV_PGRAPH_INTR_ERROR; -+ } -+ } -+ -+ if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { -+ nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); -+ stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; -+ show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; -+ nv10_graph_context_switch(dev); -+ } -+ -+ nv_wr32(dev, NV03_PGRAPH_INTR, stat); -+ nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); -+ -+ if (show && nouveau_ratelimit()) { -+ NV_INFO(dev, "PGRAPH -"); -+ nouveau_bitfield_print(nv10_graph_intr, show); -+ printk(" nsource:"); -+ nouveau_bitfield_print(nv04_graph_nsource, nsource); -+ printk(" nstatus:"); -+ nouveau_bitfield_print(nv10_graph_nstatus, nstatus); -+ printk("\n"); -+ NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x " -+ "mthd 0x%04x data 0x%08x\n", -+ chid, subc, class, mthd, data); -+ } -+ } -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv20_graph.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv20_graph.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv20_graph.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv20_graph.c 2011-01-07 14:22:17.000000000 +0100 -@@ -32,6 +32,10 @@ - #define NV34_GRCTX_SIZE (18140) - #define NV35_36_GRCTX_SIZE (22396) - -+static int nv20_graph_register(struct drm_device *); -+static int nv30_graph_register(struct drm_device *); -+static void nv20_graph_isr(struct drm_device *); -+ - static void - nv20_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) - { -@@ -425,9 +429,21 @@ - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -+ unsigned long flags; - -- nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ pgraph->fifo_access(dev, false); -+ -+ /* Unload the context if it's the currently active one */ -+ if (pgraph->channel(dev) == chan) -+ pgraph->unload_context(dev); -+ -+ pgraph->fifo_access(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ -+ /* Free the context resources */ - nv_wo32(pgraph->ctx_table, chan->id * 4, 0); -+ nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); - } - - int -@@ -496,24 +512,27 @@ - } - - void --nv20_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch) -+nv20_graph_set_tile_region(struct drm_device *dev, int i) - { -- uint32_t limit = max(1u, addr + size) - 1; -- -- if (pitch) -- addr |= 1; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - -- nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit); -- nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch); -- nv_wr32(dev, NV20_PGRAPH_TILE(i), addr); -+ nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); -+ nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); -+ nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); - - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i); -- nv_wr32(dev, NV10_PGRAPH_RDI_DATA, limit); -+ nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->limit); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i); -- nv_wr32(dev, NV10_PGRAPH_RDI_DATA, pitch); -+ nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->pitch); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i); -- nv_wr32(dev, NV10_PGRAPH_RDI_DATA, addr); -+ nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->addr); -+ -+ if (dev_priv->card_type == NV_20) { -+ nv_wr32(dev, NV20_PGRAPH_ZCOMP(i), tile->zcomp); -+ nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00ea0090 + 4 * i); -+ nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->zcomp); -+ } - } - - int -@@ -560,6 +579,13 @@ - - nv20_graph_rdi(dev); - -+ ret = nv20_graph_register(dev); -+ if (ret) { -+ nouveau_gpuobj_ref(NULL, &pgraph->ctx_table); -+ return ret; -+ } -+ -+ nouveau_irq_register(dev, 12, nv20_graph_isr); - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - -@@ -571,16 +597,17 @@ - nv_wr32(dev, 0x40009C , 0x00000040); - - if (dev_priv->chipset >= 0x25) { -- nv_wr32(dev, 0x400890, 0x00080000); -+ nv_wr32(dev, 0x400890, 0x00a8cfff); - nv_wr32(dev, 0x400610, 0x304B1FB6); -- nv_wr32(dev, 0x400B80, 0x18B82880); -+ nv_wr32(dev, 0x400B80, 0x1cbd3883); - nv_wr32(dev, 0x400B84, 0x44000000); - nv_wr32(dev, 0x400098, 0x40000080); - nv_wr32(dev, 0x400B88, 0x000000ff); -+ - } else { -- nv_wr32(dev, 0x400880, 0x00080000); /* 0x0008c7df */ -+ nv_wr32(dev, 0x400880, 0x0008c7df); - nv_wr32(dev, 0x400094, 0x00000005); -- nv_wr32(dev, 0x400B80, 0x45CAA208); /* 0x45eae20e */ -+ nv_wr32(dev, 0x400B80, 0x45eae20e); - nv_wr32(dev, 0x400B84, 0x24000000); - nv_wr32(dev, 0x400098, 0x00000040); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00038); -@@ -591,14 +618,8 @@ - - /* Turn all the tiling regions off. */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) -- nv20_graph_set_region_tiling(dev, i, 0, 0, 0); -+ nv20_graph_set_tile_region(dev, i); - -- for (i = 0; i < 8; i++) { -- nv_wr32(dev, 0x400980 + i * 4, nv_rd32(dev, 0x100300 + i * 4)); -- nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0090 + i * 4); -- nv_wr32(dev, NV10_PGRAPH_RDI_DATA, -- nv_rd32(dev, 0x100300 + i * 4)); -- } - nv_wr32(dev, 0x4009a0, nv_rd32(dev, 0x100324)); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA000C); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, nv_rd32(dev, 0x100324)); -@@ -642,6 +663,9 @@ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - -+ nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); -+ nouveau_irq_unregister(dev, 12); -+ - nouveau_gpuobj_ref(NULL, &pgraph->ctx_table); - } - -@@ -684,9 +708,16 @@ - return ret; - } - -+ ret = nv30_graph_register(dev); -+ if (ret) { -+ nouveau_gpuobj_ref(NULL, &pgraph->ctx_table); -+ return ret; -+ } -+ - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, - pgraph->ctx_table->pinst >> 4); - -+ nouveau_irq_register(dev, 12, nv20_graph_isr); - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); - -@@ -724,7 +755,7 @@ - - /* Turn all the tiling regions off. */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) -- nv20_graph_set_region_tiling(dev, i, 0, 0, 0); -+ nv20_graph_set_tile_region(dev, i); - - nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100); - nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); -@@ -744,46 +775,125 @@ - return 0; - } - --struct nouveau_pgraph_object_class nv20_graph_grclass[] = { -- { 0x0030, false, NULL }, /* null */ -- { 0x0039, false, NULL }, /* m2mf */ -- { 0x004a, false, NULL }, /* gdirect */ -- { 0x009f, false, NULL }, /* imageblit (nv12) */ -- { 0x008a, false, NULL }, /* ifc */ -- { 0x0089, false, NULL }, /* sifm */ -- { 0x0062, false, NULL }, /* surf2d */ -- { 0x0043, false, NULL }, /* rop */ -- { 0x0012, false, NULL }, /* beta1 */ -- { 0x0072, false, NULL }, /* beta4 */ -- { 0x0019, false, NULL }, /* cliprect */ -- { 0x0044, false, NULL }, /* pattern */ -- { 0x009e, false, NULL }, /* swzsurf */ -- { 0x0096, false, NULL }, /* celcius */ -- { 0x0097, false, NULL }, /* kelvin (nv20) */ -- { 0x0597, false, NULL }, /* kelvin (nv25) */ -- {} --}; -- --struct nouveau_pgraph_object_class nv30_graph_grclass[] = { -- { 0x0030, false, NULL }, /* null */ -- { 0x0039, false, NULL }, /* m2mf */ -- { 0x004a, false, NULL }, /* gdirect */ -- { 0x009f, false, NULL }, /* imageblit (nv12) */ -- { 0x008a, false, NULL }, /* ifc */ -- { 0x038a, false, NULL }, /* ifc (nv30) */ -- { 0x0089, false, NULL }, /* sifm */ -- { 0x0389, false, NULL }, /* sifm (nv30) */ -- { 0x0062, false, NULL }, /* surf2d */ -- { 0x0362, false, NULL }, /* surf2d (nv30) */ -- { 0x0043, false, NULL }, /* rop */ -- { 0x0012, false, NULL }, /* beta1 */ -- { 0x0072, false, NULL }, /* beta4 */ -- { 0x0019, false, NULL }, /* cliprect */ -- { 0x0044, false, NULL }, /* pattern */ -- { 0x039e, false, NULL }, /* swzsurf */ -- { 0x0397, false, NULL }, /* rankine (nv30) */ -- { 0x0497, false, NULL }, /* rankine (nv35) */ -- { 0x0697, false, NULL }, /* rankine (nv34) */ -- {} --}; -+static int -+nv20_graph_register(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; - -+ if (dev_priv->engine.graph.registered) -+ return 0; -+ -+ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ -+ NVOBJ_CLASS(dev, 0x0030, GR); /* null */ -+ NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ -+ NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ -+ NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ -+ NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ -+ NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ -+ NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ -+ NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ -+ NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ -+ NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ -+ NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ -+ NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ -+ NVOBJ_CLASS(dev, 0x009e, GR); /* swzsurf */ -+ NVOBJ_CLASS(dev, 0x0096, GR); /* celcius */ -+ -+ /* kelvin */ -+ if (dev_priv->chipset < 0x25) -+ NVOBJ_CLASS(dev, 0x0097, GR); -+ else -+ NVOBJ_CLASS(dev, 0x0597, GR); -+ -+ /* nvsw */ -+ NVOBJ_CLASS(dev, 0x506e, SW); -+ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); -+ -+ dev_priv->engine.graph.registered = true; -+ return 0; -+} -+ -+static int -+nv30_graph_register(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->engine.graph.registered) -+ return 0; -+ -+ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ -+ NVOBJ_CLASS(dev, 0x0030, GR); /* null */ -+ NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ -+ NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ -+ NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ -+ NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ -+ NVOBJ_CLASS(dev, 0x038a, GR); /* ifc (nv30) */ -+ NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ -+ NVOBJ_CLASS(dev, 0x0389, GR); /* sifm (nv30) */ -+ NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ -+ NVOBJ_CLASS(dev, 0x0362, GR); /* surf2d (nv30) */ -+ NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ -+ NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ -+ NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ -+ NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ -+ NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ -+ NVOBJ_CLASS(dev, 0x039e, GR); /* swzsurf */ -+ -+ /* rankine */ -+ if (0x00000003 & (1 << (dev_priv->chipset & 0x0f))) -+ NVOBJ_CLASS(dev, 0x0397, GR); -+ else -+ if (0x00000010 & (1 << (dev_priv->chipset & 0x0f))) -+ NVOBJ_CLASS(dev, 0x0697, GR); -+ else -+ if (0x000001e0 & (1 << (dev_priv->chipset & 0x0f))) -+ NVOBJ_CLASS(dev, 0x0497, GR); -+ -+ /* nvsw */ -+ NVOBJ_CLASS(dev, 0x506e, SW); -+ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); -+ -+ dev_priv->engine.graph.registered = true; -+ return 0; -+} -+ -+static void -+nv20_graph_isr(struct drm_device *dev) -+{ -+ u32 stat; -+ -+ while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { -+ u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); -+ u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); -+ u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); -+ u32 chid = (addr & 0x01f00000) >> 20; -+ u32 subc = (addr & 0x00070000) >> 16; -+ u32 mthd = (addr & 0x00001ffc); -+ u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); -+ u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xfff; -+ u32 show = stat; -+ -+ if (stat & NV_PGRAPH_INTR_ERROR) { -+ if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { -+ if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) -+ show &= ~NV_PGRAPH_INTR_ERROR; -+ } -+ } -+ -+ nv_wr32(dev, NV03_PGRAPH_INTR, stat); -+ nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); -+ -+ if (show && nouveau_ratelimit()) { -+ NV_INFO(dev, "PGRAPH -"); -+ nouveau_bitfield_print(nv10_graph_intr, show); -+ printk(" nsource:"); -+ nouveau_bitfield_print(nv04_graph_nsource, nsource); -+ printk(" nstatus:"); -+ nouveau_bitfield_print(nv10_graph_nstatus, nstatus); -+ printk("\n"); -+ NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x " -+ "mthd 0x%04x data 0x%08x\n", -+ chid, subc, class, mthd, data); -+ } -+ } -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv30_fb.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv30_fb.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv30_fb.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv30_fb.c 2011-01-07 14:22:17.000000000 +0100 -@@ -29,6 +29,27 @@ - #include "nouveau_drv.h" - #include "nouveau_drm.h" - -+void -+nv30_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, -+ uint32_t size, uint32_t pitch, uint32_t flags) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; -+ -+ tile->addr = addr | 1; -+ tile->limit = max(1u, addr + size) - 1; -+ tile->pitch = pitch; -+} -+ -+void -+nv30_fb_free_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]; -+ -+ tile->addr = tile->limit = tile->pitch = 0; -+} -+ - static int - calc_bias(struct drm_device *dev, int k, int i, int j) - { -@@ -65,7 +86,7 @@ - - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) -- pfb->set_region_tiling(dev, i, 0, 0, 0); -+ pfb->set_tile_region(dev, i); - - /* Init the memory timing regs at 0x10037c/0x1003ac */ - if (dev_priv->chipset == 0x30 || -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv40_fb.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv40_fb.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv40_fb.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv40_fb.c 2011-01-07 14:22:17.000000000 +0100 -@@ -4,26 +4,22 @@ - #include "nouveau_drm.h" - - void --nv40_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch) -+nv40_fb_set_tile_region(struct drm_device *dev, int i) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t limit = max(1u, addr + size) - 1; -- -- if (pitch) -- addr |= 1; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - switch (dev_priv->chipset) { - case 0x40: -- nv_wr32(dev, NV10_PFB_TLIMIT(i), limit); -- nv_wr32(dev, NV10_PFB_TSIZE(i), pitch); -- nv_wr32(dev, NV10_PFB_TILE(i), addr); -+ nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); -+ nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); -+ nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); - break; - - default: -- nv_wr32(dev, NV40_PFB_TLIMIT(i), limit); -- nv_wr32(dev, NV40_PFB_TSIZE(i), pitch); -- nv_wr32(dev, NV40_PFB_TILE(i), addr); -+ nv_wr32(dev, NV40_PFB_TLIMIT(i), tile->limit); -+ nv_wr32(dev, NV40_PFB_TSIZE(i), tile->pitch); -+ nv_wr32(dev, NV40_PFB_TILE(i), tile->addr); - break; - } - } -@@ -64,7 +60,7 @@ - - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) -- pfb->set_region_tiling(dev, i, 0, 0, 0); -+ pfb->set_tile_region(dev, i); - - return 0; - } -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv40_fifo.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv40_fifo.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv40_fifo.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv40_fifo.c 2011-01-07 14:22:17.000000000 +0100 -@@ -47,6 +47,11 @@ - if (ret) - return ret; - -+ chan->user = ioremap(pci_resource_start(dev->pdev, 0) + -+ NV40_USER(chan->id), PAGE_SIZE); -+ if (!chan->user) -+ return -ENOMEM; -+ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - - nv_wi32(dev, fc + 0, chan->pushbuf_base); -@@ -59,7 +64,6 @@ - NV_PFIFO_CACHE1_BIG_ENDIAN | - #endif - 0x30000000 /* no idea.. */); -- nv_wi32(dev, fc + 56, chan->ramin_grctx->pinst >> 4); - nv_wi32(dev, fc + 60, 0x0001FFFF); - - /* enable the fifo dma operation */ -@@ -70,17 +74,6 @@ - return 0; - } - --void --nv40_fifo_destroy_context(struct nouveau_channel *chan) --{ -- struct drm_device *dev = chan->dev; -- -- nv_wr32(dev, NV04_PFIFO_MODE, -- nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); -- -- nouveau_gpuobj_ref(NULL, &chan->ramfc); --} -- - static void - nv40_fifo_do_load_context(struct drm_device *dev, int chid) - { -@@ -279,6 +272,7 @@ - static void - nv40_fifo_init_intr(struct drm_device *dev) - { -+ nouveau_irq_register(dev, 8, nv04_fifo_isr); - nv_wr32(dev, 0x002100, 0xffffffff); - nv_wr32(dev, 0x002140, 0xffffffff); - } -@@ -301,7 +295,7 @@ - pfifo->reassign(dev, true); - - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- if (dev_priv->fifos[i]) { -+ if (dev_priv->channels.ptr[i]) { - uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); - nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); - } -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv40_graph.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv40_graph.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv40_graph.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv40_graph.c 2011-01-07 14:22:17.000000000 +0100 -@@ -29,6 +29,9 @@ - #include "nouveau_drv.h" - #include "nouveau_grctx.h" - -+static int nv40_graph_register(struct drm_device *); -+static void nv40_graph_isr(struct drm_device *); -+ - struct nouveau_channel * - nv40_graph_channel(struct drm_device *dev) - { -@@ -42,7 +45,7 @@ - inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4; - - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- struct nouveau_channel *chan = dev_priv->fifos[i]; -+ struct nouveau_channel *chan = dev_priv->channels.ptr[i]; - - if (chan && chan->ramin_grctx && - chan->ramin_grctx->pinst == inst) -@@ -59,6 +62,7 @@ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - struct nouveau_grctx ctx = {}; -+ unsigned long flags; - int ret; - - ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 16, -@@ -73,12 +77,39 @@ - nv40_grctx_init(&ctx); - - nv_wo32(chan->ramin_grctx, 0, chan->ramin_grctx->pinst); -+ -+ /* init grctx pointer in ramfc, and on PFIFO if channel is -+ * already active there -+ */ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ nv_wo32(chan->ramfc, 0x38, chan->ramin_grctx->pinst >> 4); -+ nv_mask(dev, 0x002500, 0x00000001, 0x00000000); -+ if ((nv_rd32(dev, 0x003204) & 0x0000001f) == chan->id) -+ nv_wr32(dev, 0x0032e0, chan->ramin_grctx->pinst >> 4); -+ nv_mask(dev, 0x002500, 0x00000001, 0x00000001); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - return 0; - } - - void - nv40_graph_destroy_context(struct nouveau_channel *chan) - { -+ struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ pgraph->fifo_access(dev, false); -+ -+ /* Unload the context if it's the currently active one */ -+ if (pgraph->channel(dev) == chan) -+ pgraph->unload_context(dev); -+ -+ pgraph->fifo_access(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ -+ /* Free the context resources */ - nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); - } - -@@ -174,43 +205,39 @@ - } - - void --nv40_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, -- uint32_t size, uint32_t pitch) -+nv40_graph_set_tile_region(struct drm_device *dev, int i) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t limit = max(1u, addr + size) - 1; -- -- if (pitch) -- addr |= 1; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - switch (dev_priv->chipset) { - case 0x44: - case 0x4a: - case 0x4e: -- nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch); -- nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit); -- nv_wr32(dev, NV20_PGRAPH_TILE(i), addr); -+ nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); -+ nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); -+ nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); - break; - - case 0x46: - case 0x47: - case 0x49: - case 0x4b: -- nv_wr32(dev, NV47_PGRAPH_TSIZE(i), pitch); -- nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), limit); -- nv_wr32(dev, NV47_PGRAPH_TILE(i), addr); -- nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch); -- nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit); -- nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr); -+ nv_wr32(dev, NV47_PGRAPH_TSIZE(i), tile->pitch); -+ nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), tile->limit); -+ nv_wr32(dev, NV47_PGRAPH_TILE(i), tile->addr); -+ nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch); -+ nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit); -+ nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr); - break; - - default: -- nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch); -- nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit); -- nv_wr32(dev, NV20_PGRAPH_TILE(i), addr); -- nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch); -- nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit); -- nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr); -+ nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); -+ nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); -+ nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); -+ nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch); -+ nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit); -+ nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr); - break; - } - } -@@ -232,7 +259,7 @@ - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nouveau_grctx ctx = {}; - uint32_t vramsz, *cp; -- int i, j; -+ int ret, i, j; - - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & - ~NV_PMC_ENABLE_PGRAPH); -@@ -256,9 +283,14 @@ - - kfree(cp); - -+ ret = nv40_graph_register(dev); -+ if (ret) -+ return ret; -+ - /* No context present currently */ - nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); - -+ nouveau_irq_register(dev, 12, nv40_graph_isr); - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); - -@@ -347,7 +379,7 @@ - - /* Turn all the tiling regions off. */ - for (i = 0; i < pfb->num_tiles; i++) -- nv40_graph_set_region_tiling(dev, i, 0, 0, 0); -+ nv40_graph_set_tile_region(dev, i); - - /* begin RAM config */ - vramsz = pci_resource_len(dev->pdev, 0) - 1; -@@ -390,26 +422,111 @@ - - void nv40_graph_takedown(struct drm_device *dev) - { -+ nouveau_irq_unregister(dev, 12); -+} -+ -+static int -+nv40_graph_register(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->engine.graph.registered) -+ return 0; -+ -+ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ -+ NVOBJ_CLASS(dev, 0x0030, GR); /* null */ -+ NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ -+ NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ -+ NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ -+ NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ -+ NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ -+ NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */ -+ NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ -+ NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */ -+ NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ -+ NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ -+ NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ -+ NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ -+ NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ -+ NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */ -+ -+ /* curie */ -+ if (dev_priv->chipset >= 0x60 || -+ 0x00005450 & (1 << (dev_priv->chipset & 0x0f))) -+ NVOBJ_CLASS(dev, 0x4497, GR); -+ else -+ NVOBJ_CLASS(dev, 0x4097, GR); -+ -+ /* nvsw */ -+ NVOBJ_CLASS(dev, 0x506e, SW); -+ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); -+ -+ dev_priv->engine.graph.registered = true; -+ return 0; -+} -+ -+static int -+nv40_graph_isr_chid(struct drm_device *dev, u32 inst) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *chan; -+ unsigned long flags; -+ int i; -+ -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); -+ for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -+ chan = dev_priv->channels.ptr[i]; -+ if (!chan || !chan->ramin_grctx) -+ continue; -+ -+ if (inst == chan->ramin_grctx->pinst) -+ break; -+ } -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); -+ return i; - } - --struct nouveau_pgraph_object_class nv40_graph_grclass[] = { -- { 0x0030, false, NULL }, /* null */ -- { 0x0039, false, NULL }, /* m2mf */ -- { 0x004a, false, NULL }, /* gdirect */ -- { 0x009f, false, NULL }, /* imageblit (nv12) */ -- { 0x008a, false, NULL }, /* ifc */ -- { 0x0089, false, NULL }, /* sifm */ -- { 0x3089, false, NULL }, /* sifm (nv40) */ -- { 0x0062, false, NULL }, /* surf2d */ -- { 0x3062, false, NULL }, /* surf2d (nv40) */ -- { 0x0043, false, NULL }, /* rop */ -- { 0x0012, false, NULL }, /* beta1 */ -- { 0x0072, false, NULL }, /* beta4 */ -- { 0x0019, false, NULL }, /* cliprect */ -- { 0x0044, false, NULL }, /* pattern */ -- { 0x309e, false, NULL }, /* swzsurf */ -- { 0x4097, false, NULL }, /* curie (nv40) */ -- { 0x4497, false, NULL }, /* curie (nv44) */ -- {} --}; -+static void -+nv40_graph_isr(struct drm_device *dev) -+{ -+ u32 stat; -+ -+ while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { -+ u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); -+ u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); -+ u32 inst = (nv_rd32(dev, 0x40032c) & 0x000fffff) << 4; -+ u32 chid = nv40_graph_isr_chid(dev, inst); -+ u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); -+ u32 subc = (addr & 0x00070000) >> 16; -+ u32 mthd = (addr & 0x00001ffc); -+ u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); -+ u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xffff; -+ u32 show = stat; -+ -+ if (stat & NV_PGRAPH_INTR_ERROR) { -+ if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { -+ if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) -+ show &= ~NV_PGRAPH_INTR_ERROR; -+ } else -+ if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) { -+ nv_mask(dev, 0x402000, 0, 0); -+ } -+ } -+ -+ nv_wr32(dev, NV03_PGRAPH_INTR, stat); -+ nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); - -+ if (show && nouveau_ratelimit()) { -+ NV_INFO(dev, "PGRAPH -"); -+ nouveau_bitfield_print(nv10_graph_intr, show); -+ printk(" nsource:"); -+ nouveau_bitfield_print(nv04_graph_nsource, nsource); -+ printk(" nstatus:"); -+ nouveau_bitfield_print(nv10_graph_nstatus, nstatus); -+ printk("\n"); -+ NV_INFO(dev, "PGRAPH - ch %d (0x%08x) subc %d " -+ "class 0x%04x mthd 0x%04x data 0x%08x\n", -+ chid, inst, subc, class, mthd, data); -+ } -+ } -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_crtc.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_crtc.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_crtc.c 2011-01-07 14:22:17.000000000 +0100 -@@ -115,15 +115,16 @@ - OUT_RING(evo, 0); - BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1); - if (dev_priv->chipset != 0x50) -- if (nv_crtc->fb.tile_flags == 0x7a00) -+ if (nv_crtc->fb.tile_flags == 0x7a00 || -+ nv_crtc->fb.tile_flags == 0xfe00) - OUT_RING(evo, NvEvoFB32); - else - if (nv_crtc->fb.tile_flags == 0x7000) - OUT_RING(evo, NvEvoFB16); - else -- OUT_RING(evo, NvEvoVRAM); -+ OUT_RING(evo, NvEvoVRAM_LP); - else -- OUT_RING(evo, NvEvoVRAM); -+ OUT_RING(evo, NvEvoVRAM_LP); - } - - nv_crtc->fb.blanked = blanked; -@@ -345,7 +346,6 @@ - uint32_t buffer_handle, uint32_t width, uint32_t height) - { - struct drm_device *dev = crtc->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - struct nouveau_bo *cursor = NULL; - struct drm_gem_object *gem; -@@ -374,8 +374,7 @@ - - nouveau_bo_unmap(cursor); - -- nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset - -- dev_priv->vm_vram_base); -+ nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT); - nv_crtc->cursor.show(nv_crtc, true); - - out: -@@ -437,6 +436,7 @@ - .cursor_move = nv50_crtc_cursor_move, - .gamma_set = nv50_crtc_gamma_set, - .set_config = drm_crtc_helper_set_config, -+ .page_flip = nouveau_crtc_page_flip, - .destroy = nv50_crtc_destroy, - }; - -@@ -453,6 +453,7 @@ - - NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); - -+ drm_vblank_pre_modeset(dev, nv_crtc->index); - nv50_crtc_blank(nv_crtc, true); - } - -@@ -468,6 +469,7 @@ - NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); - - nv50_crtc_blank(nv_crtc, false); -+ drm_vblank_post_modeset(dev, nv_crtc->index); - - ret = RING_SPACE(evo, 2); - if (ret) { -@@ -545,7 +547,7 @@ - return -EINVAL; - } - -- nv_crtc->fb.offset = fb->nvbo->bo.offset - dev_priv->vm_vram_base; -+ nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT; - 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) { -@@ -554,13 +556,14 @@ - return ret; - - BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1); -- if (nv_crtc->fb.tile_flags == 0x7a00) -+ if (nv_crtc->fb.tile_flags == 0x7a00 || -+ nv_crtc->fb.tile_flags == 0xfe00) - OUT_RING(evo, NvEvoFB32); - else - if (nv_crtc->fb.tile_flags == 0x7000) - OUT_RING(evo, NvEvoFB16); - else -- OUT_RING(evo, NvEvoVRAM); -+ OUT_RING(evo, NvEvoVRAM_LP); - } - - ret = RING_SPACE(evo, 12); -@@ -574,8 +577,10 @@ - if (!nv_crtc->fb.tile_flags) { - OUT_RING(evo, drm_fb->pitch | (1 << 20)); - } else { -- OUT_RING(evo, ((drm_fb->pitch / 4) << 4) | -- fb->nvbo->tile_mode); -+ u32 tile_mode = fb->nvbo->tile_mode; -+ if (dev_priv->card_type >= NV_C0) -+ tile_mode >>= 4; -+ OUT_RING(evo, ((drm_fb->pitch / 4) << 4) | tile_mode); - } - if (dev_priv->chipset == 0x50) - OUT_RING(evo, (nv_crtc->fb.tile_flags << 8) | format); -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_display.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_display.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_display.c 2011-01-07 14:22:17.000000000 +0100 -@@ -33,6 +33,8 @@ - #include "nouveau_ramht.h" - #include "drm_crtc_helper.h" - -+static void nv50_display_isr(struct drm_device *); -+ - static inline int - nv50_sor_nr(struct drm_device *dev) - { -@@ -46,159 +48,6 @@ - return 4; - } - --static void --nv50_evo_channel_del(struct nouveau_channel **pchan) --{ -- struct nouveau_channel *chan = *pchan; -- -- if (!chan) -- return; -- *pchan = NULL; -- -- nouveau_gpuobj_channel_takedown(chan); -- nouveau_bo_unmap(chan->pushbuf_bo); -- nouveau_bo_ref(NULL, &chan->pushbuf_bo); -- -- if (chan->user) -- iounmap(chan->user); -- -- kfree(chan); --} -- --static int --nv50_evo_dmaobj_new(struct nouveau_channel *evo, uint32_t class, uint32_t name, -- uint32_t tile_flags, uint32_t magic_flags, -- uint32_t offset, uint32_t limit) --{ -- struct drm_nouveau_private *dev_priv = evo->dev->dev_private; -- struct drm_device *dev = evo->dev; -- struct nouveau_gpuobj *obj = NULL; -- int ret; -- -- ret = nouveau_gpuobj_new(dev, evo, 6*4, 32, 0, &obj); -- if (ret) -- return ret; -- obj->engine = NVOBJ_ENGINE_DISPLAY; -- -- nv_wo32(obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); -- nv_wo32(obj, 4, limit); -- nv_wo32(obj, 8, offset); -- nv_wo32(obj, 12, 0x00000000); -- nv_wo32(obj, 16, 0x00000000); -- if (dev_priv->card_type < NV_C0) -- nv_wo32(obj, 20, 0x00010000); -- else -- nv_wo32(obj, 20, 0x00020000); -- dev_priv->engine.instmem.flush(dev); -- -- ret = nouveau_ramht_insert(evo, name, obj); -- nouveau_gpuobj_ref(NULL, &obj); -- if (ret) { -- return ret; -- } -- -- return 0; --} -- --static int --nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *ramht = NULL; -- struct nouveau_channel *chan; -- int ret; -- -- chan = kzalloc(sizeof(struct nouveau_channel), GFP_KERNEL); -- if (!chan) -- return -ENOMEM; -- *pchan = chan; -- -- chan->id = -1; -- chan->dev = dev; -- chan->user_get = 4; -- chan->user_put = 0; -- -- ret = nouveau_gpuobj_new(dev, NULL, 32768, 0x1000, -- NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin); -- if (ret) { -- NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); -- nv50_evo_channel_del(pchan); -- return ret; -- } -- -- ret = drm_mm_init(&chan->ramin_heap, 0, 32768); -- if (ret) { -- NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); -- nv50_evo_channel_del(pchan); -- return ret; -- } -- -- ret = nouveau_gpuobj_new(dev, chan, 4096, 16, 0, &ramht); -- if (ret) { -- NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); -- nv50_evo_channel_del(pchan); -- return ret; -- } -- -- ret = nouveau_ramht_new(dev, ramht, &chan->ramht); -- nouveau_gpuobj_ref(NULL, &ramht); -- if (ret) { -- nv50_evo_channel_del(pchan); -- return ret; -- } -- -- if (dev_priv->chipset != 0x50) { -- ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB16, 0x70, 0x19, -- 0, 0xffffffff); -- if (ret) { -- nv50_evo_channel_del(pchan); -- return ret; -- } -- -- -- ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB32, 0x7a, 0x19, -- 0, 0xffffffff); -- if (ret) { -- nv50_evo_channel_del(pchan); -- return ret; -- } -- } -- -- ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoVRAM, 0, 0x19, -- 0, dev_priv->vram_size); -- if (ret) { -- nv50_evo_channel_del(pchan); -- return ret; -- } -- -- ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, -- false, true, &chan->pushbuf_bo); -- if (ret == 0) -- ret = nouveau_bo_pin(chan->pushbuf_bo, TTM_PL_FLAG_VRAM); -- if (ret) { -- NV_ERROR(dev, "Error creating EVO DMA push buffer: %d\n", ret); -- nv50_evo_channel_del(pchan); -- return ret; -- } -- -- ret = nouveau_bo_map(chan->pushbuf_bo); -- if (ret) { -- NV_ERROR(dev, "Error mapping EVO DMA push buffer: %d\n", ret); -- nv50_evo_channel_del(pchan); -- return ret; -- } -- -- chan->user = ioremap(pci_resource_start(dev->pdev, 0) + -- NV50_PDISPLAY_USER(0), PAGE_SIZE); -- if (!chan->user) { -- NV_ERROR(dev, "Error mapping EVO control regs.\n"); -- nv50_evo_channel_del(pchan); -- return -ENOMEM; -- } -- -- return 0; --} -- - int - nv50_display_early_init(struct drm_device *dev) - { -@@ -214,17 +63,16 @@ - nv50_display_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -- struct nouveau_channel *evo = dev_priv->evo; - struct drm_connector *connector; -- uint32_t val, ram_amount; -- uint64_t start; -+ struct nouveau_channel *evo; - int ret, i; -+ u32 val; - - NV_DEBUG_KMS(dev, "\n"); - - nv_wr32(dev, 0x00610184, nv_rd32(dev, 0x00614004)); -+ - /* - * I think the 0x006101XX range is some kind of main control area - * that enables things. -@@ -240,16 +88,19 @@ - val = nv_rd32(dev, 0x0061610c + (i * 0x800)); - nv_wr32(dev, 0x0061019c + (i * 0x10), val); - } -+ - /* DAC */ - for (i = 0; i < 3; i++) { - val = nv_rd32(dev, 0x0061a000 + (i * 0x800)); - nv_wr32(dev, 0x006101d0 + (i * 0x04), val); - } -+ - /* SOR */ - for (i = 0; i < nv50_sor_nr(dev); i++) { - val = nv_rd32(dev, 0x0061c000 + (i * 0x800)); - nv_wr32(dev, 0x006101e0 + (i * 0x04), val); - } -+ - /* EXT */ - for (i = 0; i < 3; i++) { - val = nv_rd32(dev, 0x0061e000 + (i * 0x800)); -@@ -262,17 +113,6 @@ - nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(i), 0x00000001); - } - -- /* This used to be in crtc unblank, but seems out of place there. */ -- nv_wr32(dev, NV50_PDISPLAY_UNK_380, 0); -- /* RAM is clamped to 256 MiB. */ -- ram_amount = dev_priv->vram_size; -- NV_DEBUG_KMS(dev, "ram_amount %d\n", ram_amount); -- if (ram_amount > 256*1024*1024) -- ram_amount = 256*1024*1024; -- nv_wr32(dev, NV50_PDISPLAY_RAM_AMOUNT, ram_amount - 1); -- nv_wr32(dev, NV50_PDISPLAY_UNK_388, 0x150000); -- nv_wr32(dev, NV50_PDISPLAY_UNK_38C, 0); -- - /* The precise purpose is unknown, i suspect it has something to do - * with text mode. - */ -@@ -287,37 +127,6 @@ - } - } - -- /* taken from nv bug #12637, attempts to un-wedge the hw if it's -- * stuck in some unspecified state -- */ -- start = ptimer->read(dev); -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x2b00); -- while ((val = nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))) & 0x1e0000) { -- if ((val & 0x9f0000) == 0x20000) -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), -- val | 0x800000); -- -- if ((val & 0x3f0000) == 0x30000) -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), -- val | 0x200000); -- -- if (ptimer->read(dev) - start > 1000000000ULL) { -- NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) != 0\n"); -- NV_ERROR(dev, "0x610200 = 0x%08x\n", val); -- return -EBUSY; -- } -- } -- -- nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, NV50_PDISPLAY_CTRL_STATE_ENABLE); -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1000b03); -- if (!nv_wait(dev, NV50_PDISPLAY_CHANNEL_STAT(0), -- 0x40000000, 0x40000000)) { -- NV_ERROR(dev, "timeout: (0x610200 & 0x40000000) == 0x40000000\n"); -- NV_ERROR(dev, "0x610200 = 0x%08x\n", -- nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); -- return -EBUSY; -- } -- - for (i = 0; i < 2; i++) { - nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000); - if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), -@@ -341,39 +150,31 @@ - } - } - -- nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); -+ nv_wr32(dev, NV50_PDISPLAY_PIO_CTRL, 0x00000000); -+ nv_mask(dev, NV50_PDISPLAY_INTR_0, 0x00000000, 0x00000000); -+ nv_wr32(dev, NV50_PDISPLAY_INTR_EN_0, 0x00000000); -+ nv_mask(dev, NV50_PDISPLAY_INTR_1, 0x00000000, 0x00000000); -+ nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, -+ NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 | -+ NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 | -+ NV50_PDISPLAY_INTR_EN_1_CLK_UNK40); -+ -+ /* enable hotplug interrupts */ -+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -+ struct nouveau_connector *conn = nouveau_connector(connector); - -- /* initialise fifo */ -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_DMA_CB(0), -- ((evo->pushbuf_bo->bo.mem.start << PAGE_SHIFT) >> 8) | -- NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM | -- NV50_PDISPLAY_CHANNEL_DMA_CB_VALID); -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK2(0), 0x00010000); -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK3(0), 0x00000002); -- if (!nv_wait(dev, 0x610200, 0x80000000, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x610200 & 0x80000000) == 0\n"); -- NV_ERROR(dev, "0x610200 = 0x%08x\n", nv_rd32(dev, 0x610200)); -- return -EBUSY; -- } -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), -- (nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0)) & ~0x00000003) | -- NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED); -- nv_wr32(dev, NV50_PDISPLAY_USER_PUT(0), 0); -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x01000003 | -- NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED); -- nv_wr32(dev, 0x610300, nv_rd32(dev, 0x610300) & ~1); -- -- evo->dma.max = (4096/4) - 2; -- evo->dma.put = 0; -- evo->dma.cur = evo->dma.put; -- evo->dma.free = evo->dma.max - evo->dma.cur; -+ if (conn->dcb->gpio_tag == 0xff) -+ continue; - -- ret = RING_SPACE(evo, NOUVEAU_DMA_SKIPS); -+ pgpio->irq_enable(dev, conn->dcb->gpio_tag, true); -+ } -+ -+ ret = nv50_evo_init(dev); - if (ret) - return ret; -+ evo = dev_priv->evo; - -- for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) -- OUT_RING(evo, 0); -+ nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); - - ret = RING_SPACE(evo, 11); - if (ret) -@@ -393,21 +194,6 @@ - if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2)) - NV_ERROR(dev, "evo pushbuf stalled\n"); - -- /* enable clock change interrupts. */ -- nv_wr32(dev, 0x610028, 0x00010001); -- nv_wr32(dev, NV50_PDISPLAY_INTR_EN, (NV50_PDISPLAY_INTR_EN_CLK_UNK10 | -- NV50_PDISPLAY_INTR_EN_CLK_UNK20 | -- NV50_PDISPLAY_INTR_EN_CLK_UNK40)); -- -- /* enable hotplug interrupts */ -- list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -- struct nouveau_connector *conn = nouveau_connector(connector); -- -- if (conn->dcb->gpio_tag == 0xff) -- continue; -- -- pgpio->irq_enable(dev, conn->dcb->gpio_tag, true); -- } - - return 0; - } -@@ -452,13 +238,7 @@ - } - } - -- nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0); -- nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, 0); -- if (!nv_wait(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1e0000, 0)) { -- NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) == 0\n"); -- NV_ERROR(dev, "0x610200 = 0x%08x\n", -- nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); -- } -+ nv50_evo_fini(dev); - - for (i = 0; i < 3; i++) { - if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_STATE(i), -@@ -470,7 +250,7 @@ - } - - /* disable interrupts. */ -- nv_wr32(dev, NV50_PDISPLAY_INTR_EN, 0x00000000); -+ nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, 0x00000000); - - /* disable hotplug interrupts */ - nv_wr32(dev, 0xe054, 0xffffffff); -@@ -508,13 +288,6 @@ - - dev->mode_config.fb_base = dev_priv->fb_phys; - -- /* Create EVO channel */ -- ret = nv50_evo_channel_new(dev, &dev_priv->evo); -- if (ret) { -- NV_ERROR(dev, "Error creating EVO channel: %d\n", ret); -- return ret; -- } -- - /* Create CRTC objects */ - for (i = 0; i < 2; i++) - nv50_crtc_create(dev, i); -@@ -557,6 +330,9 @@ - } - } - -+ INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); -+ nouveau_irq_register(dev, 26, nv50_display_isr); -+ - ret = nv50_display_init(dev); - if (ret) { - nv50_display_destroy(dev); -@@ -569,14 +345,12 @@ - void - nv50_display_destroy(struct drm_device *dev) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- - NV_DEBUG_KMS(dev, "\n"); - - drm_mode_config_cleanup(dev); - - nv50_display_disable(dev); -- nv50_evo_channel_del(&dev_priv->evo); -+ nouveau_irq_unregister(dev, 26); - } - - static u16 -@@ -660,32 +434,32 @@ - nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *chan; -- struct list_head *entry, *tmp; -+ struct nouveau_channel *chan, *tmp; - -- list_for_each_safe(entry, tmp, &dev_priv->vbl_waiting) { -- chan = list_entry(entry, struct nouveau_channel, nvsw.vbl_wait); -+ list_for_each_entry_safe(chan, tmp, &dev_priv->vbl_waiting, -+ nvsw.vbl_wait) { -+ if (chan->nvsw.vblsem_head != crtc) -+ continue; - - nouveau_bo_wr32(chan->notifier_bo, chan->nvsw.vblsem_offset, - chan->nvsw.vblsem_rval); - list_del(&chan->nvsw.vbl_wait); -+ drm_vblank_put(dev, crtc); - } -+ -+ drm_handle_vblank(dev, crtc); - } - - static void - nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr) - { -- intr &= NV50_PDISPLAY_INTR_1_VBLANK_CRTC; -- - if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_0) - nv50_display_vblank_crtc_handler(dev, 0); - - if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_1) - nv50_display_vblank_crtc_handler(dev, 1); - -- nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev, -- NV50_PDISPLAY_INTR_EN) & ~intr); -- nv_wr32(dev, NV50_PDISPLAY_INTR_1, intr); -+ nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_VBLANK_CRTC); - } - - static void -@@ -1011,108 +785,31 @@ - static void - nv50_display_error_handler(struct drm_device *dev) - { -- uint32_t addr, data; -- -- nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000); -- addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR); -- data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA); -- -- NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x (0x%04x 0x%02x)\n", -- 0, addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf); -- -- nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000); --} -- --void --nv50_display_irq_hotplug_bh(struct work_struct *work) --{ -- struct drm_nouveau_private *dev_priv = -- container_of(work, struct drm_nouveau_private, hpd_work); -- struct drm_device *dev = dev_priv->dev; -- struct drm_connector *connector; -- const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; -- uint32_t unplug_mask, plug_mask, change_mask; -- uint32_t hpd0, hpd1; -- -- spin_lock_irq(&dev_priv->hpd_state.lock); -- hpd0 = dev_priv->hpd_state.hpd0_bits; -- dev_priv->hpd_state.hpd0_bits = 0; -- hpd1 = dev_priv->hpd_state.hpd1_bits; -- dev_priv->hpd_state.hpd1_bits = 0; -- spin_unlock_irq(&dev_priv->hpd_state.lock); -- -- hpd0 &= nv_rd32(dev, 0xe050); -- if (dev_priv->chipset >= 0x90) -- hpd1 &= nv_rd32(dev, 0xe070); -- -- plug_mask = (hpd0 & 0x0000ffff) | (hpd1 << 16); -- unplug_mask = (hpd0 >> 16) | (hpd1 & 0xffff0000); -- change_mask = plug_mask | unplug_mask; -- -- list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -- struct drm_encoder_helper_funcs *helper; -- struct nouveau_connector *nv_connector = -- nouveau_connector(connector); -- struct nouveau_encoder *nv_encoder; -- struct dcb_gpio_entry *gpio; -- uint32_t reg; -- bool plugged; -- -- if (!nv_connector->dcb) -- continue; -- -- gpio = nouveau_bios_gpio_entry(dev, nv_connector->dcb->gpio_tag); -- if (!gpio || !(change_mask & (1 << gpio->line))) -- continue; -+ u32 channels = (nv_rd32(dev, NV50_PDISPLAY_INTR_0) & 0x001f0000) >> 16; -+ u32 addr, data; -+ int chid; -+ -+ for (chid = 0; chid < 5; chid++) { -+ if (!(channels & (1 << chid))) -+ continue; -+ -+ nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000 << chid); -+ addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid)); -+ data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA(chid)); -+ NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x " -+ "(0x%04x 0x%02x)\n", chid, -+ addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf); - -- reg = nv_rd32(dev, gpio_reg[gpio->line >> 3]); -- plugged = !!(reg & (4 << ((gpio->line & 7) << 2))); -- NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un", -- drm_get_connector_name(connector)) ; -- -- if (!connector->encoder || !connector->encoder->crtc || -- !connector->encoder->crtc->enabled) -- continue; -- nv_encoder = nouveau_encoder(connector->encoder); -- helper = connector->encoder->helper_private; -- -- if (nv_encoder->dcb->type != OUTPUT_DP) -- continue; -- -- if (plugged) -- helper->dpms(connector->encoder, DRM_MODE_DPMS_ON); -- else -- helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF); -+ nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid), 0x90000000); - } -- -- drm_helper_hpd_irq_event(dev); - } - --void --nv50_display_irq_handler(struct drm_device *dev) -+static void -+nv50_display_isr(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t delayed = 0; - -- if (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) { -- uint32_t hpd0_bits, hpd1_bits = 0; -- -- hpd0_bits = nv_rd32(dev, 0xe054); -- nv_wr32(dev, 0xe054, hpd0_bits); -- -- if (dev_priv->chipset >= 0x90) { -- hpd1_bits = nv_rd32(dev, 0xe074); -- nv_wr32(dev, 0xe074, hpd1_bits); -- } -- -- spin_lock(&dev_priv->hpd_state.lock); -- dev_priv->hpd_state.hpd0_bits |= hpd0_bits; -- dev_priv->hpd_state.hpd1_bits |= hpd1_bits; -- spin_unlock(&dev_priv->hpd_state.lock); -- -- queue_work(dev_priv->wq, &dev_priv->hpd_work); -- } -- - while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { - uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); - uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1); -@@ -1123,9 +820,9 @@ - if (!intr0 && !(intr1 & ~delayed)) - break; - -- if (intr0 & 0x00010000) { -+ if (intr0 & 0x001f0000) { - nv50_display_error_handler(dev); -- intr0 &= ~0x00010000; -+ intr0 &= ~0x001f0000; - } - - if (intr1 & NV50_PDISPLAY_INTR_1_VBLANK_CRTC) { -@@ -1156,4 +853,3 @@ - } - } - } -- -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_display.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_display.h ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_display.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_display.h 2011-01-07 14:22:17.000000000 +0100 -@@ -35,9 +35,7 @@ - #include "nouveau_crtc.h" - #include "nv50_evo.h" - --void nv50_display_irq_handler(struct drm_device *dev); - void nv50_display_irq_handler_bh(struct work_struct *work); --void nv50_display_irq_hotplug_bh(struct work_struct *work); - int nv50_display_early_init(struct drm_device *dev); - void nv50_display_late_takedown(struct drm_device *dev); - int nv50_display_create(struct drm_device *dev); -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_evo.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_evo.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_evo.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_evo.c 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,345 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+ -+#include "nouveau_drv.h" -+#include "nouveau_dma.h" -+#include "nouveau_ramht.h" -+ -+static void -+nv50_evo_channel_del(struct nouveau_channel **pevo) -+{ -+ struct drm_nouveau_private *dev_priv; -+ struct nouveau_channel *evo = *pevo; -+ -+ if (!evo) -+ return; -+ *pevo = NULL; -+ -+ dev_priv = evo->dev->dev_private; -+ dev_priv->evo_alloc &= ~(1 << evo->id); -+ -+ nouveau_gpuobj_channel_takedown(evo); -+ nouveau_bo_unmap(evo->pushbuf_bo); -+ nouveau_bo_ref(NULL, &evo->pushbuf_bo); -+ -+ if (evo->user) -+ iounmap(evo->user); -+ -+ kfree(evo); -+} -+ -+int -+nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 class, u32 name, -+ u32 tile_flags, u32 magic_flags, u32 offset, u32 limit, -+ u32 flags5) -+{ -+ struct drm_nouveau_private *dev_priv = evo->dev->dev_private; -+ struct drm_device *dev = evo->dev; -+ struct nouveau_gpuobj *obj = NULL; -+ int ret; -+ -+ ret = nouveau_gpuobj_new(dev, dev_priv->evo, 6*4, 32, 0, &obj); -+ if (ret) -+ return ret; -+ obj->engine = NVOBJ_ENGINE_DISPLAY; -+ -+ nv_wo32(obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); -+ nv_wo32(obj, 4, limit); -+ nv_wo32(obj, 8, offset); -+ nv_wo32(obj, 12, 0x00000000); -+ nv_wo32(obj, 16, 0x00000000); -+ nv_wo32(obj, 20, flags5); -+ dev_priv->engine.instmem.flush(dev); -+ -+ ret = nouveau_ramht_insert(evo, name, obj); -+ nouveau_gpuobj_ref(NULL, &obj); -+ if (ret) { -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int -+nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *evo; -+ int ret; -+ -+ evo = kzalloc(sizeof(struct nouveau_channel), GFP_KERNEL); -+ if (!evo) -+ return -ENOMEM; -+ *pevo = evo; -+ -+ for (evo->id = 0; evo->id < 5; evo->id++) { -+ if (dev_priv->evo_alloc & (1 << evo->id)) -+ continue; -+ -+ dev_priv->evo_alloc |= (1 << evo->id); -+ break; -+ } -+ -+ if (evo->id == 5) { -+ kfree(evo); -+ return -ENODEV; -+ } -+ -+ evo->dev = dev; -+ evo->user_get = 4; -+ evo->user_put = 0; -+ -+ ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, -+ false, true, &evo->pushbuf_bo); -+ if (ret == 0) -+ ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM); -+ if (ret) { -+ NV_ERROR(dev, "Error creating EVO DMA push buffer: %d\n", ret); -+ nv50_evo_channel_del(pevo); -+ return ret; -+ } -+ -+ ret = nouveau_bo_map(evo->pushbuf_bo); -+ if (ret) { -+ NV_ERROR(dev, "Error mapping EVO DMA push buffer: %d\n", ret); -+ nv50_evo_channel_del(pevo); -+ return ret; -+ } -+ -+ evo->user = ioremap(pci_resource_start(dev->pdev, 0) + -+ NV50_PDISPLAY_USER(evo->id), PAGE_SIZE); -+ if (!evo->user) { -+ NV_ERROR(dev, "Error mapping EVO control regs.\n"); -+ nv50_evo_channel_del(pevo); -+ return -ENOMEM; -+ } -+ -+ /* bind primary evo channel's ramht to the channel */ -+ if (dev_priv->evo && evo != dev_priv->evo) -+ nouveau_ramht_ref(dev_priv->evo->ramht, &evo->ramht, NULL); -+ -+ return 0; -+} -+ -+static int -+nv50_evo_channel_init(struct nouveau_channel *evo) -+{ -+ struct drm_device *dev = evo->dev; -+ int id = evo->id, ret, i; -+ u64 pushbuf = evo->pushbuf_bo->bo.mem.start << PAGE_SHIFT; -+ u32 tmp; -+ -+ tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)); -+ if ((tmp & 0x009f0000) == 0x00020000) -+ nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00800000); -+ -+ tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)); -+ if ((tmp & 0x003f0000) == 0x00030000) -+ nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00600000); -+ -+ /* initialise fifo */ -+ nv_wr32(dev, NV50_PDISPLAY_EVO_DMA_CB(id), pushbuf >> 8 | -+ NV50_PDISPLAY_EVO_DMA_CB_LOCATION_VRAM | -+ NV50_PDISPLAY_EVO_DMA_CB_VALID); -+ nv_wr32(dev, NV50_PDISPLAY_EVO_UNK2(id), 0x00010000); -+ nv_wr32(dev, NV50_PDISPLAY_EVO_HASH_TAG(id), id); -+ nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), NV50_PDISPLAY_EVO_CTRL_DMA, -+ NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED); -+ -+ nv_wr32(dev, NV50_PDISPLAY_USER_PUT(id), 0x00000000); -+ nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x01000003 | -+ NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED); -+ if (!nv_wait(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x80000000, 0x00000000)) { -+ NV_ERROR(dev, "EvoCh %d init timeout: 0x%08x\n", id, -+ nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id))); -+ return -EBUSY; -+ } -+ -+ /* enable error reporting on the channel */ -+ nv_mask(dev, 0x610028, 0x00000000, 0x00010001 << id); -+ -+ evo->dma.max = (4096/4) - 2; -+ evo->dma.put = 0; -+ evo->dma.cur = evo->dma.put; -+ evo->dma.free = evo->dma.max - evo->dma.cur; -+ -+ ret = RING_SPACE(evo, NOUVEAU_DMA_SKIPS); -+ if (ret) -+ return ret; -+ -+ for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) -+ OUT_RING(evo, 0); -+ -+ return 0; -+} -+ -+static void -+nv50_evo_channel_fini(struct nouveau_channel *evo) -+{ -+ struct drm_device *dev = evo->dev; -+ int id = evo->id; -+ -+ nv_mask(dev, 0x610028, 0x00010001 << id, 0x00000000); -+ nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x00001010, 0x00001000); -+ nv_wr32(dev, NV50_PDISPLAY_INTR_0, (1 << id)); -+ nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x00000003, 0x00000000); -+ if (!nv_wait(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x001e0000, 0x00000000)) { -+ NV_ERROR(dev, "EvoCh %d takedown timeout: 0x%08x\n", id, -+ nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id))); -+ } -+} -+ -+static int -+nv50_evo_create(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj *ramht = NULL; -+ struct nouveau_channel *evo; -+ int ret; -+ -+ /* create primary evo channel, the one we use for modesetting -+ * purporses -+ */ -+ ret = nv50_evo_channel_new(dev, &dev_priv->evo); -+ if (ret) -+ return ret; -+ evo = dev_priv->evo; -+ -+ /* setup object management on it, any other evo channel will -+ * use this also as there's no per-channel support on the -+ * hardware -+ */ -+ ret = nouveau_gpuobj_new(dev, NULL, 32768, 65536, -+ NVOBJ_FLAG_ZERO_ALLOC, &evo->ramin); -+ if (ret) { -+ NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ -+ ret = drm_mm_init(&evo->ramin_heap, 0, 32768); -+ if (ret) { -+ NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ -+ ret = nouveau_gpuobj_new(dev, evo, 4096, 16, 0, &ramht); -+ if (ret) { -+ NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ -+ ret = nouveau_ramht_new(dev, ramht, &evo->ramht); -+ nouveau_gpuobj_ref(NULL, &ramht); -+ if (ret) { -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ -+ /* create some default objects for the scanout memtypes we support */ -+ if (dev_priv->card_type >= NV_C0) { -+ ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0xfe, 0x19, -+ 0, 0xffffffff, 0x00000000); -+ if (ret) { -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ -+ ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19, -+ 0, dev_priv->vram_size, 0x00020000); -+ if (ret) { -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ -+ ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19, -+ 0, dev_priv->vram_size, 0x00000000); -+ if (ret) { -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ } else -+ if (dev_priv->chipset != 0x50) { -+ ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB16, 0x70, 0x19, -+ 0, 0xffffffff, 0x00010000); -+ if (ret) { -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ -+ -+ ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0x7a, 0x19, -+ 0, 0xffffffff, 0x00010000); -+ if (ret) { -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ -+ ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19, -+ 0, dev_priv->vram_size, 0x00010000); -+ if (ret) { -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ -+ ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19, -+ 0, dev_priv->vram_size, 0x00010000); -+ if (ret) { -+ nv50_evo_channel_del(&dev_priv->evo); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+int -+nv50_evo_init(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int ret; -+ -+ if (!dev_priv->evo) { -+ ret = nv50_evo_create(dev); -+ if (ret) -+ return ret; -+ } -+ -+ return nv50_evo_channel_init(dev_priv->evo); -+} -+ -+void -+nv50_evo_fini(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->evo) { -+ nv50_evo_channel_fini(dev_priv->evo); -+ nv50_evo_channel_del(&dev_priv->evo); -+ } -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_evo.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_evo.h ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_evo.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_evo.h 2011-01-07 14:22:17.000000000 +0100 -@@ -24,6 +24,15 @@ - * - */ - -+#ifndef __NV50_EVO_H__ -+#define __NV50_EVO_H__ -+ -+int nv50_evo_init(struct drm_device *dev); -+void nv50_evo_fini(struct drm_device *dev); -+int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 class, u32 name, -+ u32 tile_flags, u32 magic_flags, -+ u32 offset, u32 limit); -+ - #define NV50_EVO_UPDATE 0x00000080 - #define NV50_EVO_UNK84 0x00000084 - #define NV50_EVO_UNK84_NOTIFY 0x40000000 -@@ -111,3 +120,4 @@ - #define NV50_EVO_CRTC_SCALE_RES1 0x000008d8 - #define NV50_EVO_CRTC_SCALE_RES2 0x000008dc - -+#endif -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_fb.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_fb.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_fb.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_fb.c 2011-01-07 14:22:17.000000000 +0100 -@@ -3,30 +3,75 @@ - #include "nouveau_drv.h" - #include "nouveau_drm.h" - -+struct nv50_fb_priv { -+ struct page *r100c08_page; -+ dma_addr_t r100c08; -+}; -+ -+static int -+nv50_fb_create(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nv50_fb_priv *priv; -+ -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); -+ if (!priv->r100c08_page) { -+ kfree(priv); -+ return -ENOMEM; -+ } -+ -+ priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0, -+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); -+ if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) { -+ __free_page(priv->r100c08_page); -+ kfree(priv); -+ return -EFAULT; -+ } -+ -+ dev_priv->engine.fb.priv = priv; -+ return 0; -+} -+ - int - nv50_fb_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nv50_fb_priv *priv; -+ int ret; -+ -+ if (!dev_priv->engine.fb.priv) { -+ ret = nv50_fb_create(dev); -+ if (ret) -+ return ret; -+ } -+ priv = dev_priv->engine.fb.priv; - - /* Not a clue what this is exactly. Without pointing it at a - * scratch page, VRAM->GART blits with M2MF (as in DDX DFS) - * cause IOMMU "read from address 0" errors (rh#561267) - */ -- nv_wr32(dev, 0x100c08, dev_priv->gart_info.sg_dummy_bus >> 8); -+ nv_wr32(dev, 0x100c08, priv->r100c08 >> 8); - - /* This is needed to get meaningful information from 100c90 - * on traps. No idea what these values mean exactly. */ - switch (dev_priv->chipset) { - case 0x50: -- nv_wr32(dev, 0x100c90, 0x0707ff); -+ nv_wr32(dev, 0x100c90, 0x000707ff); - break; - case 0xa3: - case 0xa5: - case 0xa8: -- nv_wr32(dev, 0x100c90, 0x0d0fff); -+ nv_wr32(dev, 0x100c90, 0x000d0fff); -+ break; -+ case 0xaf: -+ nv_wr32(dev, 0x100c90, 0x089d1fff); - break; - default: -- nv_wr32(dev, 0x100c90, 0x1d07ff); -+ nv_wr32(dev, 0x100c90, 0x001d07ff); - break; - } - -@@ -36,12 +81,25 @@ - void - nv50_fb_takedown(struct drm_device *dev) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nv50_fb_priv *priv; -+ -+ priv = dev_priv->engine.fb.priv; -+ if (!priv) -+ return; -+ dev_priv->engine.fb.priv = NULL; -+ -+ pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, -+ PCI_DMA_BIDIRECTIONAL); -+ __free_page(priv->r100c08_page); -+ kfree(priv); - } - - void - nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ unsigned long flags; - u32 trap[6], idx, chinst; - int i, ch; - -@@ -60,8 +118,10 @@ - return; - - chinst = (trap[2] << 16) | trap[1]; -+ -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) { -- struct nouveau_channel *chan = dev_priv->fifos[ch]; -+ struct nouveau_channel *chan = dev_priv->channels.ptr[ch]; - - if (!chan || !chan->ramin) - continue; -@@ -69,6 +129,7 @@ - if (chinst == chan->ramin->vinst >> 12) - break; - } -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - - NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x " - "channel %d (0x%08x)\n", -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_fbcon.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_fbcon.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_fbcon.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_fbcon.c 2011-01-07 14:22:17.000000000 +0100 -@@ -1,29 +1,46 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ - #include "drmP.h" - #include "nouveau_drv.h" - #include "nouveau_dma.h" - #include "nouveau_ramht.h" - #include "nouveau_fbcon.h" -+#include "nouveau_mm.h" - --void -+int - nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) - { - struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; -+ int ret; - -- if (info->state != FBINFO_STATE_RUNNING) -- return; -- -- if (!(info->flags & FBINFO_HWACCEL_DISABLED) && -- RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11)) { -- nouveau_fbcon_gpu_lockup(info); -- } -- -- if (info->flags & FBINFO_HWACCEL_DISABLED) { -- cfb_fillrect(info, rect); -- return; -- } -+ ret = RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11); -+ if (ret) -+ return ret; - - if (rect->rop != ROP_COPY) { - BEGIN_RING(chan, NvSub2D, 0x02ac, 1); -@@ -45,27 +62,21 @@ - OUT_RING(chan, 3); - } - FIRE_RING(chan); -+ return 0; - } - --void -+int - nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) - { - struct nouveau_fbdev *nfbdev = info->par; - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; -+ int ret; - -- if (info->state != FBINFO_STATE_RUNNING) -- return; -- -- if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 12)) { -- nouveau_fbcon_gpu_lockup(info); -- } -- -- if (info->flags & FBINFO_HWACCEL_DISABLED) { -- cfb_copyarea(info, region); -- return; -- } -+ ret = RING_SPACE(chan, 12); -+ if (ret) -+ return ret; - - BEGIN_RING(chan, NvSub2D, 0x0110, 1); - OUT_RING(chan, 0); -@@ -80,9 +91,10 @@ - OUT_RING(chan, 0); - OUT_RING(chan, region->sy); - FIRE_RING(chan); -+ return 0; - } - --void -+int - nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) - { - struct nouveau_fbdev *nfbdev = info->par; -@@ -92,23 +104,14 @@ - uint32_t width, dwords, *data = (uint32_t *)image->data; - uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); - uint32_t *palette = info->pseudo_palette; -+ int ret; - -- if (info->state != FBINFO_STATE_RUNNING) -- return; -- -- if (image->depth != 1) { -- cfb_imageblit(info, image); -- return; -- } -+ if (image->depth != 1) -+ return -ENODEV; - -- if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 11)) { -- nouveau_fbcon_gpu_lockup(info); -- } -- -- if (info->flags & FBINFO_HWACCEL_DISABLED) { -- cfb_imageblit(info, image); -- return; -- } -+ ret = RING_SPACE(chan, 11); -+ if (ret) -+ return ret; - - width = ALIGN(image->width, 32); - dwords = (width * image->height) >> 5; -@@ -134,11 +137,9 @@ - while (dwords) { - int push = dwords > 2047 ? 2047 : dwords; - -- if (RING_SPACE(chan, push + 1)) { -- nouveau_fbcon_gpu_lockup(info); -- cfb_imageblit(info, image); -- return; -- } -+ ret = RING_SPACE(chan, push + 1); -+ if (ret) -+ return ret; - - dwords -= push; - -@@ -148,6 +149,7 @@ - } - - FIRE_RING(chan); -+ return 0; - } - - int -@@ -157,12 +159,9 @@ - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; -- struct nouveau_gpuobj *eng2d = NULL; -- uint64_t fb; -+ struct nouveau_bo *nvbo = nfbdev->nouveau_fb.nvbo; - int ret, format; - -- fb = info->fix.smem_start - dev_priv->fb_phys + dev_priv->vm_vram_base; -- - switch (info->var.bits_per_pixel) { - case 8: - format = 0xf3; -@@ -190,12 +189,7 @@ - return -EINVAL; - } - -- ret = nouveau_gpuobj_gr_new(dev_priv->channel, 0x502d, &eng2d); -- if (ret) -- return ret; -- -- ret = nouveau_ramht_insert(dev_priv->channel, Nv2D, eng2d); -- nouveau_gpuobj_ref(NULL, &eng2d); -+ ret = nouveau_gpuobj_gr_new(dev_priv->channel, Nv2D, 0x502d); - if (ret) - return ret; - -@@ -253,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(fb)); -- OUT_RING(chan, lower_32_bits(fb)); -+ OUT_RING(chan, upper_32_bits(nvbo->vma.offset)); -+ OUT_RING(chan, lower_32_bits(nvbo->vma.offset)); - BEGIN_RING(chan, NvSub2D, 0x0230, 2); - OUT_RING(chan, format); - OUT_RING(chan, 1); -@@ -262,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(fb)); -- OUT_RING(chan, lower_32_bits(fb)); -+ OUT_RING(chan, upper_32_bits(nvbo->vma.offset)); -+ OUT_RING(chan, lower_32_bits(nvbo->vma.offset)); - - return 0; - } -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_fifo.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_fifo.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_fifo.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_fifo.c 2011-01-07 14:22:17.000000000 +0100 -@@ -28,6 +28,7 @@ - #include "drm.h" - #include "nouveau_drv.h" - #include "nouveau_ramht.h" -+#include "nouveau_vm.h" - - static void - nv50_fifo_playlist_update(struct drm_device *dev) -@@ -44,7 +45,8 @@ - - /* We never schedule channel 0 or 127 */ - for (i = 1, nr = 0; i < 127; i++) { -- if (dev_priv->fifos[i] && dev_priv->fifos[i]->ramfc) { -+ if (dev_priv->channels.ptr[i] && -+ dev_priv->channels.ptr[i]->ramfc) { - nv_wo32(cur, (nr * 4), i); - nr++; - } -@@ -60,7 +62,7 @@ - nv50_fifo_channel_enable(struct drm_device *dev, int channel) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *chan = dev_priv->fifos[channel]; -+ struct nouveau_channel *chan = dev_priv->channels.ptr[channel]; - uint32_t inst; - - NV_DEBUG(dev, "ch%d\n", channel); -@@ -105,6 +107,7 @@ - { - NV_DEBUG(dev, "\n"); - -+ nouveau_irq_register(dev, 8, nv04_fifo_isr); - nv_wr32(dev, NV03_PFIFO_INTR_0, 0xFFFFFFFF); - nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF); - } -@@ -118,7 +121,7 @@ - NV_DEBUG(dev, "\n"); - - for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++) { -- if (dev_priv->fifos[i]) -+ if (dev_priv->channels.ptr[i]) - nv50_fifo_channel_enable(dev, i); - else - nv50_fifo_channel_disable(dev, i); -@@ -206,6 +209,9 @@ - if (!pfifo->playlist[0]) - return; - -+ nv_wr32(dev, 0x2140, 0x00000000); -+ nouveau_irq_unregister(dev, 8); -+ - nouveau_gpuobj_ref(NULL, &pfifo->playlist[0]); - nouveau_gpuobj_ref(NULL, &pfifo->playlist[1]); - } -@@ -256,6 +262,11 @@ - } - ramfc = chan->ramfc; - -+ chan->user = ioremap(pci_resource_start(dev->pdev, 0) + -+ NV50_USER(chan->id), PAGE_SIZE); -+ if (!chan->user) -+ return -ENOMEM; -+ - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - - nv_wo32(ramfc, 0x48, chan->pushbuf->cinst >> 4); -@@ -291,10 +302,23 @@ - nv50_fifo_destroy_context(struct nouveau_channel *chan) - { - struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; - struct nouveau_gpuobj *ramfc = NULL; -+ unsigned long flags; - - NV_DEBUG(dev, "ch%d\n", chan->id); - -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ pfifo->reassign(dev, false); -+ -+ /* Unload the context if it's the currently active one */ -+ if (pfifo->channel_id(dev) == chan->id) { -+ pfifo->disable(dev); -+ pfifo->unload_context(dev); -+ pfifo->enable(dev); -+ } -+ - /* This will ensure the channel is seen as disabled. */ - nouveau_gpuobj_ref(chan->ramfc, &ramfc); - nouveau_gpuobj_ref(NULL, &chan->ramfc); -@@ -305,6 +329,14 @@ - nv50_fifo_channel_disable(dev, 127); - nv50_fifo_playlist_update(dev); - -+ pfifo->reassign(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ -+ /* Free the channel resources */ -+ if (chan->user) { -+ iounmap(chan->user); -+ chan->user = NULL; -+ } - nouveau_gpuobj_ref(NULL, &ramfc); - nouveau_gpuobj_ref(NULL, &chan->cache); - } -@@ -392,7 +424,7 @@ - if (chid < 1 || chid >= dev_priv->engine.fifo.channels - 1) - return 0; - -- chan = dev_priv->fifos[chid]; -+ chan = dev_priv->channels.ptr[chid]; - if (!chan) { - NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid); - return -EINVAL; -@@ -467,5 +499,5 @@ - void - nv50_fifo_tlb_flush(struct drm_device *dev) - { -- nv50_vm_flush(dev, 5); -+ nv50_vm_flush_engine(dev, 5); - } -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_gpio.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_gpio.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_gpio.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_gpio.c 2011-01-07 14:22:17.000000000 +0100 -@@ -26,6 +26,28 @@ - #include "nouveau_drv.h" - #include "nouveau_hw.h" - -+#include "nv50_display.h" -+ -+static void nv50_gpio_isr(struct drm_device *dev); -+static void nv50_gpio_isr_bh(struct work_struct *work); -+ -+struct nv50_gpio_priv { -+ struct list_head handlers; -+ spinlock_t lock; -+}; -+ -+struct nv50_gpio_handler { -+ struct drm_device *dev; -+ struct list_head head; -+ struct work_struct work; -+ bool inhibit; -+ -+ struct dcb_gpio_entry *gpio; -+ -+ void (*handler)(void *data, int state); -+ void *data; -+}; -+ - static int - nv50_gpio_location(struct dcb_gpio_entry *gpio, uint32_t *reg, uint32_t *shift) - { -@@ -75,29 +97,123 @@ - return 0; - } - -+int -+nv50_gpio_irq_register(struct drm_device *dev, enum dcb_gpio_tag tag, -+ void (*handler)(void *, int), void *data) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -+ struct nv50_gpio_priv *priv = pgpio->priv; -+ struct nv50_gpio_handler *gpioh; -+ struct dcb_gpio_entry *gpio; -+ unsigned long flags; -+ -+ gpio = nouveau_bios_gpio_entry(dev, tag); -+ if (!gpio) -+ return -ENOENT; -+ -+ gpioh = kzalloc(sizeof(*gpioh), GFP_KERNEL); -+ if (!gpioh) -+ return -ENOMEM; -+ -+ INIT_WORK(&gpioh->work, nv50_gpio_isr_bh); -+ gpioh->dev = dev; -+ gpioh->gpio = gpio; -+ gpioh->handler = handler; -+ gpioh->data = data; -+ -+ spin_lock_irqsave(&priv->lock, flags); -+ list_add(&gpioh->head, &priv->handlers); -+ spin_unlock_irqrestore(&priv->lock, flags); -+ return 0; -+} -+ - void --nv50_gpio_irq_enable(struct drm_device *dev, enum dcb_gpio_tag tag, bool on) -+nv50_gpio_irq_unregister(struct drm_device *dev, enum dcb_gpio_tag tag, -+ void (*handler)(void *, int), void *data) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -+ struct nv50_gpio_priv *priv = pgpio->priv; -+ struct nv50_gpio_handler *gpioh, *tmp; - struct dcb_gpio_entry *gpio; -- u32 reg, mask; -+ unsigned long flags; - - gpio = nouveau_bios_gpio_entry(dev, tag); -- if (!gpio) { -- NV_ERROR(dev, "gpio tag 0x%02x not found\n", tag); -+ if (!gpio) - return; -+ -+ spin_lock_irqsave(&priv->lock, flags); -+ list_for_each_entry_safe(gpioh, tmp, &priv->handlers, head) { -+ if (gpioh->gpio != gpio || -+ gpioh->handler != handler || -+ gpioh->data != data) -+ continue; -+ list_del(&gpioh->head); -+ kfree(gpioh); - } -+ spin_unlock_irqrestore(&priv->lock, flags); -+} -+ -+bool -+nv50_gpio_irq_enable(struct drm_device *dev, enum dcb_gpio_tag tag, bool on) -+{ -+ struct dcb_gpio_entry *gpio; -+ u32 reg, mask; -+ -+ gpio = nouveau_bios_gpio_entry(dev, tag); -+ if (!gpio) -+ return false; - - reg = gpio->line < 16 ? 0xe050 : 0xe070; - mask = 0x00010001 << (gpio->line & 0xf); - - nv_wr32(dev, reg + 4, mask); -- nv_mask(dev, reg + 0, mask, on ? mask : 0); -+ reg = nv_mask(dev, reg + 0, mask, on ? mask : 0); -+ return (reg & mask) == mask; -+} -+ -+static int -+nv50_gpio_create(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -+ struct nv50_gpio_priv *priv; -+ -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ INIT_LIST_HEAD(&priv->handlers); -+ spin_lock_init(&priv->lock); -+ pgpio->priv = priv; -+ return 0; -+} -+ -+static void -+nv50_gpio_destroy(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -+ -+ kfree(pgpio->priv); -+ pgpio->priv = NULL; - } - - int - nv50_gpio_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -+ struct nv50_gpio_priv *priv; -+ int ret; -+ -+ if (!pgpio->priv) { -+ ret = nv50_gpio_create(dev); -+ if (ret) -+ return ret; -+ } -+ priv = pgpio->priv; - - /* disable, and ack any pending gpio interrupts */ - nv_wr32(dev, 0xe050, 0x00000000); -@@ -107,5 +223,77 @@ - nv_wr32(dev, 0xe074, 0xffffffff); - } - -+ nouveau_irq_register(dev, 21, nv50_gpio_isr); - return 0; - } -+ -+void -+nv50_gpio_fini(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ nv_wr32(dev, 0xe050, 0x00000000); -+ if (dev_priv->chipset >= 0x90) -+ nv_wr32(dev, 0xe070, 0x00000000); -+ nouveau_irq_unregister(dev, 21); -+ -+ nv50_gpio_destroy(dev); -+} -+ -+static void -+nv50_gpio_isr_bh(struct work_struct *work) -+{ -+ struct nv50_gpio_handler *gpioh = -+ container_of(work, struct nv50_gpio_handler, work); -+ struct drm_nouveau_private *dev_priv = gpioh->dev->dev_private; -+ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -+ struct nv50_gpio_priv *priv = pgpio->priv; -+ unsigned long flags; -+ int state; -+ -+ state = pgpio->get(gpioh->dev, gpioh->gpio->tag); -+ if (state < 0) -+ return; -+ -+ gpioh->handler(gpioh->data, state); -+ -+ spin_lock_irqsave(&priv->lock, flags); -+ gpioh->inhibit = false; -+ spin_unlock_irqrestore(&priv->lock, flags); -+} -+ -+static void -+nv50_gpio_isr(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -+ struct nv50_gpio_priv *priv = pgpio->priv; -+ struct nv50_gpio_handler *gpioh; -+ u32 intr0, intr1 = 0; -+ u32 hi, lo, ch; -+ -+ intr0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050); -+ if (dev_priv->chipset >= 0x90) -+ intr1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070); -+ -+ hi = (intr0 & 0x0000ffff) | (intr1 << 16); -+ lo = (intr0 >> 16) | (intr1 & 0xffff0000); -+ ch = hi | lo; -+ -+ nv_wr32(dev, 0xe054, intr0); -+ if (dev_priv->chipset >= 0x90) -+ nv_wr32(dev, 0xe074, intr1); -+ -+ spin_lock(&priv->lock); -+ list_for_each_entry(gpioh, &priv->handlers, head) { -+ if (!(ch & (1 << gpioh->gpio->line))) -+ continue; -+ -+ if (gpioh->inhibit) -+ continue; -+ gpioh->inhibit = true; -+ -+ queue_work(dev_priv->wq, &gpioh->work); -+ } -+ spin_unlock(&priv->lock); -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_graph.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_graph.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_graph.c 2011-01-07 14:22:17.000000000 +0100 -@@ -29,6 +29,12 @@ - #include "nouveau_drv.h" - #include "nouveau_ramht.h" - #include "nouveau_grctx.h" -+#include "nouveau_dma.h" -+#include "nouveau_vm.h" -+#include "nv50_evo.h" -+ -+static int nv50_graph_register(struct drm_device *); -+static void nv50_graph_isr(struct drm_device *); - - static void - nv50_graph_init_reset(struct drm_device *dev) -@@ -46,6 +52,7 @@ - { - NV_DEBUG(dev, "\n"); - -+ nouveau_irq_register(dev, 12, nv50_graph_isr); - nv_wr32(dev, NV03_PGRAPH_INTR, 0xffffffff); - nv_wr32(dev, 0x400138, 0xffffffff); - nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xffffffff); -@@ -145,12 +152,15 @@ - nv50_graph_init_reset(dev); - nv50_graph_init_regs__nv(dev); - nv50_graph_init_regs(dev); -- nv50_graph_init_intr(dev); - - ret = nv50_graph_init_ctxctl(dev); - if (ret) - return ret; - -+ ret = nv50_graph_register(dev); -+ if (ret) -+ return ret; -+ nv50_graph_init_intr(dev); - return 0; - } - -@@ -158,6 +168,8 @@ - nv50_graph_takedown(struct drm_device *dev) - { - NV_DEBUG(dev, "\n"); -+ nv_wr32(dev, 0x40013c, 0x00000000); -+ nouveau_irq_unregister(dev, 12); - } - - void -@@ -190,7 +202,7 @@ - inst = (inst & NV50_PGRAPH_CTXCTL_CUR_INSTANCE) << 12; - - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- struct nouveau_channel *chan = dev_priv->fifos[i]; -+ struct nouveau_channel *chan = dev_priv->channels.ptr[i]; - - if (chan && chan->ramin && chan->ramin->vinst == inst) - return chan; -@@ -211,7 +223,7 @@ - - NV_DEBUG(dev, "ch%d\n", chan->id); - -- ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 0x1000, -+ ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 0, - NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx); - if (ret) -@@ -234,6 +246,7 @@ - nv_wo32(chan->ramin_grctx, 0x00000, chan->ramin->vinst >> 12); - - dev_priv->engine.instmem.flush(dev); -+ atomic_inc(&chan->vm->pgraph_refs); - return 0; - } - -@@ -242,18 +255,31 @@ - { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; -+ unsigned long flags; - - NV_DEBUG(dev, "ch%d\n", chan->id); - - if (!chan->ramin) - return; - -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ pgraph->fifo_access(dev, false); -+ -+ if (pgraph->channel(dev) == chan) -+ pgraph->unload_context(dev); -+ - for (i = hdr; i < hdr + 24; i += 4) - nv_wo32(chan->ramin, i, 0); - dev_priv->engine.instmem.flush(dev); - -+ pgraph->fifo_access(dev, true); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ - nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); -+ -+ atomic_dec(&chan->vm->pgraph_refs); - } - - static int -@@ -306,7 +332,7 @@ - return 0; - } - --void -+static void - nv50_graph_context_switch(struct drm_device *dev) - { - uint32_t inst; -@@ -322,8 +348,8 @@ - } - - static int --nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - struct nouveau_gpuobj *gpuobj; - -@@ -340,8 +366,8 @@ - } - - static int --nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - if (nouveau_notifier_offset(chan->nvsw.vblsem, &data)) - return -ERANGE; -@@ -351,16 +377,16 @@ - } - - static int --nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - chan->nvsw.vblsem_rval = data; - return 0; - } - - static int --nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan, int grclass, -- int mthd, uint32_t data) -+nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) - { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -@@ -368,45 +394,85 @@ - if (!chan->nvsw.vblsem || chan->nvsw.vblsem_offset == ~0 || data > 1) - return -EINVAL; - -- if (!(nv_rd32(dev, NV50_PDISPLAY_INTR_EN) & -- NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data))) { -- nv_wr32(dev, NV50_PDISPLAY_INTR_1, -- NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(data)); -- nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev, -- NV50_PDISPLAY_INTR_EN) | -- NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data)); -- } -+ drm_vblank_get(dev, data); - -+ chan->nvsw.vblsem_head = data; - list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting); -+ - return 0; - } - --static struct nouveau_pgraph_object_method nv50_graph_nvsw_methods[] = { -- { 0x018c, nv50_graph_nvsw_dma_vblsem }, -- { 0x0400, nv50_graph_nvsw_vblsem_offset }, -- { 0x0404, nv50_graph_nvsw_vblsem_release_val }, -- { 0x0408, nv50_graph_nvsw_vblsem_release }, -- {} --}; -+static int -+nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) -+{ -+ struct nouveau_page_flip_state s; - --struct nouveau_pgraph_object_class nv50_graph_grclass[] = { -- { 0x506e, true, nv50_graph_nvsw_methods }, /* nvsw */ -- { 0x0030, false, NULL }, /* null */ -- { 0x5039, false, NULL }, /* m2mf */ -- { 0x502d, false, NULL }, /* 2d */ -- { 0x50c0, false, NULL }, /* compute */ -- { 0x85c0, false, NULL }, /* compute (nva3, nva5, nva8) */ -- { 0x5097, false, NULL }, /* tesla (nv50) */ -- { 0x8297, false, NULL }, /* tesla (nv8x/nv9x) */ -- { 0x8397, false, NULL }, /* tesla (nva0, nvaa, nvac) */ -- { 0x8597, false, NULL }, /* tesla (nva3, nva5, nva8) */ -- {} --}; -+ if (!nouveau_finish_page_flip(chan, &s)) { -+ /* XXX - Do something here */ -+ } -+ -+ return 0; -+} -+ -+static int -+nv50_graph_register(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->engine.graph.registered) -+ return 0; -+ -+ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ -+ NVOBJ_MTHD (dev, 0x506e, 0x018c, nv50_graph_nvsw_dma_vblsem); -+ NVOBJ_MTHD (dev, 0x506e, 0x0400, nv50_graph_nvsw_vblsem_offset); -+ NVOBJ_MTHD (dev, 0x506e, 0x0404, nv50_graph_nvsw_vblsem_release_val); -+ NVOBJ_MTHD (dev, 0x506e, 0x0408, nv50_graph_nvsw_vblsem_release); -+ NVOBJ_MTHD (dev, 0x506e, 0x0500, nv50_graph_nvsw_mthd_page_flip); -+ -+ NVOBJ_CLASS(dev, 0x0030, GR); /* null */ -+ NVOBJ_CLASS(dev, 0x5039, GR); /* m2mf */ -+ NVOBJ_CLASS(dev, 0x502d, GR); /* 2d */ -+ -+ /* tesla */ -+ if (dev_priv->chipset == 0x50) -+ NVOBJ_CLASS(dev, 0x5097, GR); /* tesla (nv50) */ -+ else -+ if (dev_priv->chipset < 0xa0) -+ NVOBJ_CLASS(dev, 0x8297, GR); /* tesla (nv8x/nv9x) */ -+ else { -+ switch (dev_priv->chipset) { -+ case 0xa0: -+ case 0xaa: -+ case 0xac: -+ NVOBJ_CLASS(dev, 0x8397, GR); -+ break; -+ case 0xa3: -+ case 0xa5: -+ case 0xa8: -+ NVOBJ_CLASS(dev, 0x8597, GR); -+ break; -+ case 0xaf: -+ NVOBJ_CLASS(dev, 0x8697, GR); -+ break; -+ } -+ } -+ -+ /* compute */ -+ NVOBJ_CLASS(dev, 0x50c0, GR); -+ if (dev_priv->chipset > 0xa0 && -+ dev_priv->chipset != 0xaa && -+ dev_priv->chipset != 0xac) -+ NVOBJ_CLASS(dev, 0x85c0, GR); -+ -+ dev_priv->engine.graph.registered = true; -+ return 0; -+} - - void - nv50_graph_tlb_flush(struct drm_device *dev) - { -- nv50_vm_flush(dev, 0); -+ nv50_vm_flush_engine(dev, 0); - } - - void -@@ -449,8 +515,535 @@ - nv_rd32(dev, 0x400384), nv_rd32(dev, 0x400388)); - } - -- nv50_vm_flush(dev, 0); -+ nv50_vm_flush_engine(dev, 0); - - nv_mask(dev, 0x400500, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - } -+ -+static struct nouveau_enum nv50_mp_exec_error_names[] = -+{ -+ { 3, "STACK_UNDERFLOW" }, -+ { 4, "QUADON_ACTIVE" }, -+ { 8, "TIMEOUT" }, -+ { 0x10, "INVALID_OPCODE" }, -+ { 0x40, "BREAKPOINT" }, -+ {} -+}; -+ -+static struct nouveau_bitfield nv50_graph_trap_m2mf[] = { -+ { 0x00000001, "NOTIFY" }, -+ { 0x00000002, "IN" }, -+ { 0x00000004, "OUT" }, -+ {} -+}; -+ -+static struct nouveau_bitfield nv50_graph_trap_vfetch[] = { -+ { 0x00000001, "FAULT" }, -+ {} -+}; -+ -+static struct nouveau_bitfield nv50_graph_trap_strmout[] = { -+ { 0x00000001, "FAULT" }, -+ {} -+}; -+ -+static struct nouveau_bitfield nv50_graph_trap_ccache[] = { -+ { 0x00000001, "FAULT" }, -+ {} -+}; -+ -+/* There must be a *lot* of these. Will take some time to gather them up. */ -+struct nouveau_enum nv50_data_error_names[] = { -+ { 0x00000003, "INVALID_QUERY_OR_TEXTURE" }, -+ { 0x00000004, "INVALID_VALUE" }, -+ { 0x00000005, "INVALID_ENUM" }, -+ { 0x00000008, "INVALID_OBJECT" }, -+ { 0x00000009, "READ_ONLY_OBJECT" }, -+ { 0x0000000a, "SUPERVISOR_OBJECT" }, -+ { 0x0000000b, "INVALID_ADDRESS_ALIGNMENT" }, -+ { 0x0000000c, "INVALID_BITFIELD" }, -+ { 0x0000000d, "BEGIN_END_ACTIVE" }, -+ { 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT" }, -+ { 0x0000000f, "VIEWPORT_ID_NEEDS_GP" }, -+ { 0x00000010, "RT_DOUBLE_BIND" }, -+ { 0x00000011, "RT_TYPES_MISMATCH" }, -+ { 0x00000012, "RT_LINEAR_WITH_ZETA" }, -+ { 0x00000015, "FP_TOO_FEW_REGS" }, -+ { 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH" }, -+ { 0x00000017, "RT_LINEAR_WITH_MSAA" }, -+ { 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT" }, -+ { 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT" }, -+ { 0x0000001a, "RT_INVALID_ALIGNMENT" }, -+ { 0x0000001b, "SAMPLER_OVER_LIMIT" }, -+ { 0x0000001c, "TEXTURE_OVER_LIMIT" }, -+ { 0x0000001e, "GP_TOO_MANY_OUTPUTS" }, -+ { 0x0000001f, "RT_BPP128_WITH_MS8" }, -+ { 0x00000021, "Z_OUT_OF_BOUNDS" }, -+ { 0x00000023, "XY_OUT_OF_BOUNDS" }, -+ { 0x00000027, "CP_MORE_PARAMS_THAN_SHARED" }, -+ { 0x00000028, "CP_NO_REG_SPACE_STRIPED" }, -+ { 0x00000029, "CP_NO_REG_SPACE_PACKED" }, -+ { 0x0000002a, "CP_NOT_ENOUGH_WARPS" }, -+ { 0x0000002b, "CP_BLOCK_SIZE_MISMATCH" }, -+ { 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS" }, -+ { 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS" }, -+ { 0x0000002e, "CP_NO_BLOCKDIM_LATCH" }, -+ { 0x00000031, "ENG2D_FORMAT_MISMATCH" }, -+ { 0x0000003f, "PRIMITIVE_ID_NEEDS_GP" }, -+ { 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT" }, -+ { 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT" }, -+ { 0x00000046, "LAYER_ID_NEEDS_GP" }, -+ { 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT" }, -+ { 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT" }, -+ {} -+}; -+ -+static struct nouveau_bitfield nv50_graph_intr[] = { -+ { 0x00000001, "NOTIFY" }, -+ { 0x00000002, "COMPUTE_QUERY" }, -+ { 0x00000010, "ILLEGAL_MTHD" }, -+ { 0x00000020, "ILLEGAL_CLASS" }, -+ { 0x00000040, "DOUBLE_NOTIFY" }, -+ { 0x00001000, "CONTEXT_SWITCH" }, -+ { 0x00010000, "BUFFER_NOTIFY" }, -+ { 0x00100000, "DATA_ERROR" }, -+ { 0x00200000, "TRAP" }, -+ { 0x01000000, "SINGLE_STEP" }, -+ {} -+}; -+ -+static void -+nv50_pgraph_mp_trap(struct drm_device *dev, int tpid, int display) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ uint32_t units = nv_rd32(dev, 0x1540); -+ uint32_t addr, mp10, status, pc, oplow, ophigh; -+ int i; -+ int mps = 0; -+ for (i = 0; i < 4; i++) { -+ if (!(units & 1 << (i+24))) -+ continue; -+ if (dev_priv->chipset < 0xa0) -+ addr = 0x408200 + (tpid << 12) + (i << 7); -+ else -+ addr = 0x408100 + (tpid << 11) + (i << 7); -+ mp10 = nv_rd32(dev, addr + 0x10); -+ status = nv_rd32(dev, addr + 0x14); -+ if (!status) -+ continue; -+ if (display) { -+ nv_rd32(dev, addr + 0x20); -+ pc = nv_rd32(dev, addr + 0x24); -+ oplow = nv_rd32(dev, addr + 0x70); -+ ophigh= nv_rd32(dev, addr + 0x74); -+ NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - " -+ "TP %d MP %d: ", tpid, i); -+ nouveau_enum_print(nv50_mp_exec_error_names, status); -+ printk(" at %06x warp %d, opcode %08x %08x\n", -+ pc&0xffffff, pc >> 24, -+ oplow, ophigh); -+ } -+ nv_wr32(dev, addr + 0x10, mp10); -+ nv_wr32(dev, addr + 0x14, 0); -+ mps++; -+ } -+ if (!mps && display) -+ NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - TP %d: " -+ "No MPs claiming errors?\n", tpid); -+} -+ -+static void -+nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, -+ uint32_t ustatus_new, int display, const char *name) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int tps = 0; -+ uint32_t units = nv_rd32(dev, 0x1540); -+ int i, r; -+ uint32_t ustatus_addr, ustatus; -+ for (i = 0; i < 16; i++) { -+ if (!(units & (1 << i))) -+ continue; -+ if (dev_priv->chipset < 0xa0) -+ ustatus_addr = ustatus_old + (i << 12); -+ else -+ ustatus_addr = ustatus_new + (i << 11); -+ ustatus = nv_rd32(dev, ustatus_addr) & 0x7fffffff; -+ if (!ustatus) -+ continue; -+ tps++; -+ switch (type) { -+ case 6: /* texture error... unknown for now */ -+ nv50_fb_vm_trap(dev, display, name); -+ if (display) { -+ NV_ERROR(dev, "magic set %d:\n", i); -+ for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) -+ NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, -+ nv_rd32(dev, r)); -+ } -+ break; -+ case 7: /* MP error */ -+ if (ustatus & 0x00010000) { -+ nv50_pgraph_mp_trap(dev, i, display); -+ ustatus &= ~0x00010000; -+ } -+ break; -+ case 8: /* TPDMA error */ -+ { -+ uint32_t e0c = nv_rd32(dev, ustatus_addr + 4); -+ uint32_t e10 = nv_rd32(dev, ustatus_addr + 8); -+ uint32_t e14 = nv_rd32(dev, ustatus_addr + 0xc); -+ uint32_t e18 = nv_rd32(dev, ustatus_addr + 0x10); -+ uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); -+ uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); -+ uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); -+ nv50_fb_vm_trap(dev, display, name); -+ /* 2d engine destination */ -+ if (ustatus & 0x00000010) { -+ if (display) { -+ NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n", -+ i, e14, e10); -+ NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", -+ i, e0c, e18, e1c, e20, e24); -+ } -+ ustatus &= ~0x00000010; -+ } -+ /* Render target */ -+ if (ustatus & 0x00000040) { -+ if (display) { -+ NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n", -+ i, e14, e10); -+ NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", -+ i, e0c, e18, e1c, e20, e24); -+ } -+ ustatus &= ~0x00000040; -+ } -+ /* CUDA memory: l[], g[] or stack. */ -+ if (ustatus & 0x00000080) { -+ if (display) { -+ if (e18 & 0x80000000) { -+ /* g[] read fault? */ -+ NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n", -+ i, e14, e10 | ((e18 >> 24) & 0x1f)); -+ e18 &= ~0x1f000000; -+ } else if (e18 & 0xc) { -+ /* g[] write fault? */ -+ NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n", -+ i, e14, e10 | ((e18 >> 7) & 0x1f)); -+ e18 &= ~0x00000f80; -+ } else { -+ NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n", -+ i, e14, e10); -+ } -+ NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", -+ i, e0c, e18, e1c, e20, e24); -+ } -+ ustatus &= ~0x00000080; -+ } -+ } -+ break; -+ } -+ if (ustatus) { -+ if (display) -+ NV_INFO(dev, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus); -+ } -+ nv_wr32(dev, ustatus_addr, 0xc0000000); -+ } -+ -+ if (!tps && display) -+ NV_INFO(dev, "%s - No TPs claiming errors?\n", name); -+} -+ -+static int -+nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid) -+{ -+ u32 status = nv_rd32(dev, 0x400108); -+ u32 ustatus; -+ -+ if (!status && display) { -+ NV_INFO(dev, "PGRAPH - TRAP: no units reporting traps?\n"); -+ return 1; -+ } -+ -+ /* DISPATCH: Relays commands to other units and handles NOTIFY, -+ * COND, QUERY. If you get a trap from it, the command is still stuck -+ * in DISPATCH and you need to do something about it. */ -+ if (status & 0x001) { -+ ustatus = nv_rd32(dev, 0x400804) & 0x7fffffff; -+ if (!ustatus && display) { -+ NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - no ustatus?\n"); -+ } -+ -+ nv_wr32(dev, 0x400500, 0x00000000); -+ -+ /* Known to be triggered by screwed up NOTIFY and COND... */ -+ if (ustatus & 0x00000001) { -+ u32 addr = nv_rd32(dev, 0x400808); -+ u32 subc = (addr & 0x00070000) >> 16; -+ u32 mthd = (addr & 0x00001ffc); -+ u32 datal = nv_rd32(dev, 0x40080c); -+ u32 datah = nv_rd32(dev, 0x400810); -+ u32 class = nv_rd32(dev, 0x400814); -+ u32 r848 = nv_rd32(dev, 0x400848); -+ -+ NV_INFO(dev, "PGRAPH - TRAP DISPATCH_FAULT\n"); -+ if (display && (addr & 0x80000000)) { -+ NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) " -+ "subc %d class 0x%04x mthd 0x%04x " -+ "data 0x%08x%08x " -+ "400808 0x%08x 400848 0x%08x\n", -+ chid, inst, subc, class, mthd, datah, -+ datal, addr, r848); -+ } else -+ if (display) { -+ NV_INFO(dev, "PGRAPH - no stuck command?\n"); -+ } -+ -+ nv_wr32(dev, 0x400808, 0); -+ nv_wr32(dev, 0x4008e8, nv_rd32(dev, 0x4008e8) & 3); -+ nv_wr32(dev, 0x400848, 0); -+ ustatus &= ~0x00000001; -+ } -+ -+ if (ustatus & 0x00000002) { -+ u32 addr = nv_rd32(dev, 0x40084c); -+ u32 subc = (addr & 0x00070000) >> 16; -+ u32 mthd = (addr & 0x00001ffc); -+ u32 data = nv_rd32(dev, 0x40085c); -+ u32 class = nv_rd32(dev, 0x400814); -+ -+ NV_INFO(dev, "PGRAPH - TRAP DISPATCH_QUERY\n"); -+ if (display && (addr & 0x80000000)) { -+ NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) " -+ "subc %d class 0x%04x mthd 0x%04x " -+ "data 0x%08x 40084c 0x%08x\n", -+ chid, inst, subc, class, mthd, -+ data, addr); -+ } else -+ if (display) { -+ NV_INFO(dev, "PGRAPH - no stuck command?\n"); -+ } -+ -+ nv_wr32(dev, 0x40084c, 0); -+ ustatus &= ~0x00000002; -+ } -+ -+ if (ustatus && display) { -+ NV_INFO(dev, "PGRAPH - TRAP_DISPATCH (unknown " -+ "0x%08x)\n", ustatus); -+ } -+ -+ nv_wr32(dev, 0x400804, 0xc0000000); -+ nv_wr32(dev, 0x400108, 0x001); -+ status &= ~0x001; -+ if (!status) -+ return 0; -+ } -+ -+ /* M2MF: Memory to memory copy engine. */ -+ if (status & 0x002) { -+ u32 ustatus = nv_rd32(dev, 0x406800) & 0x7fffffff; -+ if (display) { -+ NV_INFO(dev, "PGRAPH - TRAP_M2MF"); -+ nouveau_bitfield_print(nv50_graph_trap_m2mf, ustatus); -+ printk("\n"); -+ NV_INFO(dev, "PGRAPH - TRAP_M2MF %08x %08x %08x %08x\n", -+ nv_rd32(dev, 0x406804), nv_rd32(dev, 0x406808), -+ nv_rd32(dev, 0x40680c), nv_rd32(dev, 0x406810)); -+ -+ } -+ -+ /* No sane way found yet -- just reset the bugger. */ -+ nv_wr32(dev, 0x400040, 2); -+ nv_wr32(dev, 0x400040, 0); -+ nv_wr32(dev, 0x406800, 0xc0000000); -+ nv_wr32(dev, 0x400108, 0x002); -+ status &= ~0x002; -+ } -+ -+ /* VFETCH: Fetches data from vertex buffers. */ -+ if (status & 0x004) { -+ u32 ustatus = nv_rd32(dev, 0x400c04) & 0x7fffffff; -+ if (display) { -+ NV_INFO(dev, "PGRAPH - TRAP_VFETCH"); -+ nouveau_bitfield_print(nv50_graph_trap_vfetch, ustatus); -+ printk("\n"); -+ NV_INFO(dev, "PGRAPH - TRAP_VFETCH %08x %08x %08x %08x\n", -+ nv_rd32(dev, 0x400c00), nv_rd32(dev, 0x400c08), -+ nv_rd32(dev, 0x400c0c), nv_rd32(dev, 0x400c10)); -+ } -+ -+ nv_wr32(dev, 0x400c04, 0xc0000000); -+ nv_wr32(dev, 0x400108, 0x004); -+ status &= ~0x004; -+ } -+ -+ /* STRMOUT: DirectX streamout / OpenGL transform feedback. */ -+ if (status & 0x008) { -+ ustatus = nv_rd32(dev, 0x401800) & 0x7fffffff; -+ if (display) { -+ NV_INFO(dev, "PGRAPH - TRAP_STRMOUT"); -+ nouveau_bitfield_print(nv50_graph_trap_strmout, ustatus); -+ printk("\n"); -+ NV_INFO(dev, "PGRAPH - TRAP_STRMOUT %08x %08x %08x %08x\n", -+ nv_rd32(dev, 0x401804), nv_rd32(dev, 0x401808), -+ nv_rd32(dev, 0x40180c), nv_rd32(dev, 0x401810)); -+ -+ } -+ -+ /* No sane way found yet -- just reset the bugger. */ -+ nv_wr32(dev, 0x400040, 0x80); -+ nv_wr32(dev, 0x400040, 0); -+ nv_wr32(dev, 0x401800, 0xc0000000); -+ nv_wr32(dev, 0x400108, 0x008); -+ status &= ~0x008; -+ } -+ -+ /* CCACHE: Handles code and c[] caches and fills them. */ -+ if (status & 0x010) { -+ ustatus = nv_rd32(dev, 0x405018) & 0x7fffffff; -+ if (display) { -+ NV_INFO(dev, "PGRAPH - TRAP_CCACHE"); -+ nouveau_bitfield_print(nv50_graph_trap_ccache, ustatus); -+ printk("\n"); -+ NV_INFO(dev, "PGRAPH - TRAP_CCACHE %08x %08x %08x %08x" -+ " %08x %08x %08x\n", -+ nv_rd32(dev, 0x405800), nv_rd32(dev, 0x405804), -+ nv_rd32(dev, 0x405808), nv_rd32(dev, 0x40580c), -+ nv_rd32(dev, 0x405810), nv_rd32(dev, 0x405814), -+ nv_rd32(dev, 0x40581c)); -+ -+ } -+ -+ nv_wr32(dev, 0x405018, 0xc0000000); -+ nv_wr32(dev, 0x400108, 0x010); -+ status &= ~0x010; -+ } -+ -+ /* Unknown, not seen yet... 0x402000 is the only trap status reg -+ * remaining, so try to handle it anyway. Perhaps related to that -+ * unknown DMA slot on tesla? */ -+ if (status & 0x20) { -+ ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff; -+ if (display) -+ NV_INFO(dev, "PGRAPH - TRAP_UNKC04 0x%08x\n", ustatus); -+ nv_wr32(dev, 0x402000, 0xc0000000); -+ /* no status modifiction on purpose */ -+ } -+ -+ /* TEXTURE: CUDA texturing units */ -+ if (status & 0x040) { -+ nv50_pgraph_tp_trap(dev, 6, 0x408900, 0x408600, display, -+ "PGRAPH - TRAP_TEXTURE"); -+ nv_wr32(dev, 0x400108, 0x040); -+ status &= ~0x040; -+ } -+ -+ /* MP: CUDA execution engines. */ -+ if (status & 0x080) { -+ nv50_pgraph_tp_trap(dev, 7, 0x408314, 0x40831c, display, -+ "PGRAPH - TRAP_MP"); -+ nv_wr32(dev, 0x400108, 0x080); -+ status &= ~0x080; -+ } -+ -+ /* TPDMA: Handles TP-initiated uncached memory accesses: -+ * l[], g[], stack, 2d surfaces, render targets. */ -+ if (status & 0x100) { -+ nv50_pgraph_tp_trap(dev, 8, 0x408e08, 0x408708, display, -+ "PGRAPH - TRAP_TPDMA"); -+ nv_wr32(dev, 0x400108, 0x100); -+ status &= ~0x100; -+ } -+ -+ if (status) { -+ if (display) -+ NV_INFO(dev, "PGRAPH - TRAP: unknown 0x%08x\n", status); -+ nv_wr32(dev, 0x400108, status); -+ } -+ -+ return 1; -+} -+ -+static int -+nv50_graph_isr_chid(struct drm_device *dev, u64 inst) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *chan; -+ unsigned long flags; -+ int i; -+ -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); -+ for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -+ chan = dev_priv->channels.ptr[i]; -+ if (!chan || !chan->ramin) -+ continue; -+ -+ if (inst == chan->ramin->vinst) -+ break; -+ } -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); -+ return i; -+} -+ -+static void -+nv50_graph_isr(struct drm_device *dev) -+{ -+ u32 stat; -+ -+ while ((stat = nv_rd32(dev, 0x400100))) { -+ u64 inst = (u64)(nv_rd32(dev, 0x40032c) & 0x0fffffff) << 12; -+ u32 chid = nv50_graph_isr_chid(dev, inst); -+ u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); -+ u32 subc = (addr & 0x00070000) >> 16; -+ u32 mthd = (addr & 0x00001ffc); -+ u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); -+ u32 class = nv_rd32(dev, 0x400814); -+ u32 show = stat; -+ -+ if (stat & 0x00000010) { -+ if (!nouveau_gpuobj_mthd_call2(dev, chid, class, -+ mthd, data)) -+ show &= ~0x00000010; -+ } -+ -+ if (stat & 0x00001000) { -+ nv_wr32(dev, 0x400500, 0x00000000); -+ nv_wr32(dev, 0x400100, 0x00001000); -+ nv_mask(dev, 0x40013c, 0x00001000, 0x00000000); -+ nv50_graph_context_switch(dev); -+ stat &= ~0x00001000; -+ show &= ~0x00001000; -+ } -+ -+ show = (show && nouveau_ratelimit()) ? show : 0; -+ -+ if (show & 0x00100000) { -+ u32 ecode = nv_rd32(dev, 0x400110); -+ NV_INFO(dev, "PGRAPH - DATA_ERROR "); -+ nouveau_enum_print(nv50_data_error_names, ecode); -+ printk("\n"); -+ } -+ -+ if (stat & 0x00200000) { -+ if (!nv50_pgraph_trap_handler(dev, show, inst, chid)) -+ show &= ~0x00200000; -+ } -+ -+ nv_wr32(dev, 0x400100, stat); -+ nv_wr32(dev, 0x400500, 0x00010001); -+ -+ if (show) { -+ NV_INFO(dev, "PGRAPH -"); -+ nouveau_bitfield_print(nv50_graph_intr, show); -+ printk("\n"); -+ NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) subc %d " -+ "class 0x%04x mthd 0x%04x data 0x%08x\n", -+ chid, inst, subc, class, mthd, data); -+ } -+ } -+ -+ if (nv_rd32(dev, 0x400824) & (1 << 31)) -+ nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31)); -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_instmem.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_instmem.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_instmem.c 2011-01-07 14:22:17.000000000 +0100 -@@ -27,14 +27,20 @@ - - #include "drmP.h" - #include "drm.h" -+ - #include "nouveau_drv.h" -+#include "nouveau_vm.h" -+ -+#define BAR1_VM_BASE 0x0020000000ULL -+#define BAR1_VM_SIZE pci_resource_len(dev->pdev, 1) -+#define BAR3_VM_BASE 0x0000000000ULL -+#define BAR3_VM_SIZE pci_resource_len(dev->pdev, 3) - - struct nv50_instmem_priv { - uint32_t save1700[5]; /* 0x1700->0x1710 */ - -- struct nouveau_gpuobj *pramin_pt; -- struct nouveau_gpuobj *pramin_bar; -- struct nouveau_gpuobj *fb_bar; -+ struct nouveau_gpuobj *bar1_dmaobj; -+ struct nouveau_gpuobj *bar3_dmaobj; - }; - - static void -@@ -48,6 +54,7 @@ - return; - - nouveau_gpuobj_ref(NULL, &chan->ramfc); -+ nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); - nouveau_gpuobj_ref(NULL, &chan->vm_pd); - if (chan->ramin_heap.free_stack.next) - drm_mm_takedown(&chan->ramin_heap); -@@ -56,14 +63,14 @@ - } - - static int --nv50_channel_new(struct drm_device *dev, u32 size, -+nv50_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm, - struct nouveau_channel **pchan) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 pgd = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; - u32 fc = (dev_priv->chipset == 0x50) ? 0x0000 : 0x4200; - struct nouveau_channel *chan; -- int ret; -+ int ret, i; - - chan = kzalloc(sizeof(*chan), GFP_KERNEL); - if (!chan) -@@ -92,6 +99,17 @@ - return ret; - } - -+ for (i = 0; i < 0x4000; i += 8) { -+ nv_wo32(chan->vm_pd, i + 0, 0x00000000); -+ nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe); -+ } -+ -+ ret = nouveau_vm_ref(vm, &chan->vm, chan->vm_pd); -+ if (ret) { -+ nv50_channel_del(&chan); -+ return ret; -+ } -+ - ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 : - chan->ramin->pinst + fc, - chan->ramin->vinst + fc, 0x100, -@@ -111,6 +129,7 @@ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_instmem_priv *priv; - struct nouveau_channel *chan; -+ struct nouveau_vm *vm; - int ret, i; - u32 tmp; - -@@ -127,112 +146,87 @@ - ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_size); - if (ret) { - NV_ERROR(dev, "Failed to init RAMIN heap\n"); -- return -ENOMEM; -+ goto error; - } - -- /* we need a channel to plug into the hw to control the BARs */ -- ret = nv50_channel_new(dev, 128*1024, &dev_priv->fifos[0]); -+ /* BAR3 */ -+ ret = nouveau_vm_new(dev, BAR3_VM_BASE, BAR3_VM_SIZE, BAR3_VM_BASE, -+ &dev_priv->bar3_vm); - if (ret) -- return ret; -- chan = dev_priv->fifos[127] = dev_priv->fifos[0]; -+ goto error; - -- /* allocate page table for PRAMIN BAR */ -- ret = nouveau_gpuobj_new(dev, chan, (dev_priv->ramin_size >> 12) * 8, -- 0x1000, NVOBJ_FLAG_ZERO_ALLOC, -- &priv->pramin_pt); -+ ret = nouveau_gpuobj_new(dev, NULL, (BAR3_VM_SIZE >> 12) * 8, -+ 0x1000, NVOBJ_FLAG_DONT_MAP | -+ NVOBJ_FLAG_ZERO_ALLOC, -+ &dev_priv->bar3_vm->pgt[0].obj[0]); - if (ret) -- return ret; -+ goto error; -+ dev_priv->bar3_vm->pgt[0].refcount[0] = 1; - -- nv_wo32(chan->vm_pd, 0x0000, priv->pramin_pt->vinst | 0x63); -- nv_wo32(chan->vm_pd, 0x0004, 0); -+ nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]); - -- /* DMA object for PRAMIN BAR */ -- ret = nouveau_gpuobj_new(dev, chan, 6*4, 16, 0, &priv->pramin_bar); -+ ret = nv50_channel_new(dev, 128 * 1024, dev_priv->bar3_vm, &chan); - if (ret) -- return ret; -- nv_wo32(priv->pramin_bar, 0x00, 0x7fc00000); -- nv_wo32(priv->pramin_bar, 0x04, dev_priv->ramin_size - 1); -- nv_wo32(priv->pramin_bar, 0x08, 0x00000000); -- nv_wo32(priv->pramin_bar, 0x0c, 0x00000000); -- nv_wo32(priv->pramin_bar, 0x10, 0x00000000); -- nv_wo32(priv->pramin_bar, 0x14, 0x00000000); -+ goto error; -+ dev_priv->channels.ptr[0] = dev_priv->channels.ptr[127] = chan; - -- /* map channel into PRAMIN, gpuobj didn't do it for us */ -- ret = nv50_instmem_bind(dev, chan->ramin); -+ ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR3_VM_BASE, BAR3_VM_SIZE, -+ NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM, -+ NV_MEM_TYPE_VM, NV_MEM_COMP_VM, -+ &priv->bar3_dmaobj); - if (ret) -- return ret; -+ goto error; - -- /* poke regs... */ - nv_wr32(dev, 0x001704, 0x00000000 | (chan->ramin->vinst >> 12)); - nv_wr32(dev, 0x001704, 0x40000000 | (chan->ramin->vinst >> 12)); -- nv_wr32(dev, 0x00170c, 0x80000000 | (priv->pramin_bar->cinst >> 4)); -- -- tmp = nv_ri32(dev, 0); -- nv_wi32(dev, 0, ~tmp); -- if (nv_ri32(dev, 0) != ~tmp) { -- NV_ERROR(dev, "PRAMIN readback failed\n"); -- return -EIO; -- } -- nv_wi32(dev, 0, tmp); -+ nv_wr32(dev, 0x00170c, 0x80000000 | (priv->bar3_dmaobj->cinst >> 4)); - -+ dev_priv->engine.instmem.flush(dev); - dev_priv->ramin_available = true; - -- /* Determine VM layout */ -- dev_priv->vm_gart_base = roundup(NV50_VM_BLOCK, NV50_VM_BLOCK); -- dev_priv->vm_gart_size = NV50_VM_BLOCK; -- -- dev_priv->vm_vram_base = dev_priv->vm_gart_base + dev_priv->vm_gart_size; -- dev_priv->vm_vram_size = dev_priv->vram_size; -- if (dev_priv->vm_vram_size > NV50_VM_MAX_VRAM) -- dev_priv->vm_vram_size = NV50_VM_MAX_VRAM; -- dev_priv->vm_vram_size = roundup(dev_priv->vm_vram_size, NV50_VM_BLOCK); -- dev_priv->vm_vram_pt_nr = dev_priv->vm_vram_size / NV50_VM_BLOCK; -- -- dev_priv->vm_end = dev_priv->vm_vram_base + dev_priv->vm_vram_size; -- -- NV_DEBUG(dev, "NV50VM: GART 0x%016llx-0x%016llx\n", -- dev_priv->vm_gart_base, -- dev_priv->vm_gart_base + dev_priv->vm_gart_size - 1); -- NV_DEBUG(dev, "NV50VM: VRAM 0x%016llx-0x%016llx\n", -- dev_priv->vm_vram_base, -- dev_priv->vm_vram_base + dev_priv->vm_vram_size - 1); -- -- /* VRAM page table(s), mapped into VM at +1GiB */ -- for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { -- ret = nouveau_gpuobj_new(dev, NULL, NV50_VM_BLOCK / 0x10000 * 8, -- 0, NVOBJ_FLAG_ZERO_ALLOC, -- &chan->vm_vram_pt[i]); -- if (ret) { -- NV_ERROR(dev, "Error creating VRAM PGT: %d\n", ret); -- dev_priv->vm_vram_pt_nr = i; -- return ret; -- } -- dev_priv->vm_vram_pt[i] = chan->vm_vram_pt[i]; -- -- nv_wo32(chan->vm_pd, 0x10 + (i*8), -- chan->vm_vram_pt[i]->vinst | 0x61); -- nv_wo32(chan->vm_pd, 0x14 + (i*8), 0); -+ tmp = nv_ro32(chan->ramin, 0); -+ nv_wo32(chan->ramin, 0, ~tmp); -+ if (nv_ro32(chan->ramin, 0) != ~tmp) { -+ NV_ERROR(dev, "PRAMIN readback failed\n"); -+ ret = -EIO; -+ goto error; - } -+ nv_wo32(chan->ramin, 0, tmp); - -- /* DMA object for FB BAR */ -- ret = nouveau_gpuobj_new(dev, chan, 6*4, 16, 0, &priv->fb_bar); -+ /* BAR1 */ -+ ret = nouveau_vm_new(dev, BAR1_VM_BASE, BAR1_VM_SIZE, BAR1_VM_BASE, &vm); - if (ret) -- return ret; -- nv_wo32(priv->fb_bar, 0x00, 0x7fc00000); -- nv_wo32(priv->fb_bar, 0x04, 0x40000000 + -- pci_resource_len(dev->pdev, 1) - 1); -- nv_wo32(priv->fb_bar, 0x08, 0x40000000); -- nv_wo32(priv->fb_bar, 0x0c, 0x00000000); -- nv_wo32(priv->fb_bar, 0x10, 0x00000000); -- nv_wo32(priv->fb_bar, 0x14, 0x00000000); -+ goto error; - -- dev_priv->engine.instmem.flush(dev); -+ ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, chan->vm_pd); -+ if (ret) -+ goto error; -+ nouveau_vm_ref(NULL, &vm, NULL); -+ -+ ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR1_VM_BASE, BAR1_VM_SIZE, -+ NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM, -+ NV_MEM_TYPE_VM, NV_MEM_COMP_VM, -+ &priv->bar1_dmaobj); -+ if (ret) -+ goto error; - -- nv_wr32(dev, 0x001708, 0x80000000 | (priv->fb_bar->cinst >> 4)); -+ nv_wr32(dev, 0x001708, 0x80000000 | (priv->bar1_dmaobj->cinst >> 4)); - for (i = 0; i < 8; i++) - nv_wr32(dev, 0x1900 + (i*4), 0); - -+ /* Create shared channel VM, space is reserved at the beginning -+ * to catch "NULL pointer" references -+ */ -+ ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL, -+ &dev_priv->chan_vm); -+ if (ret) -+ return ret; -+ - return 0; -+ -+error: -+ nv50_instmem_takedown(dev); -+ return ret; - } - - void -@@ -240,7 +234,7 @@ - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; -- struct nouveau_channel *chan = dev_priv->fifos[0]; -+ struct nouveau_channel *chan = dev_priv->channels.ptr[0]; - int i; - - NV_DEBUG(dev, "\n"); -@@ -250,23 +244,23 @@ - - dev_priv->ramin_available = false; - -- /* Restore state from before init */ -+ nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL); -+ - for (i = 0x1700; i <= 0x1710; i += 4) - nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]); - -- nouveau_gpuobj_ref(NULL, &priv->fb_bar); -- nouveau_gpuobj_ref(NULL, &priv->pramin_bar); -- nouveau_gpuobj_ref(NULL, &priv->pramin_pt); -- -- /* Destroy dummy channel */ -- if (chan) { -- for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) -- nouveau_gpuobj_ref(NULL, &chan->vm_vram_pt[i]); -- dev_priv->vm_vram_pt_nr = 0; -+ nouveau_gpuobj_ref(NULL, &priv->bar3_dmaobj); -+ nouveau_gpuobj_ref(NULL, &priv->bar1_dmaobj); - -- nv50_channel_del(&dev_priv->fifos[0]); -- dev_priv->fifos[127] = NULL; -- } -+ nouveau_vm_ref(NULL, &dev_priv->bar1_vm, chan->vm_pd); -+ dev_priv->channels.ptr[127] = 0; -+ nv50_channel_del(&dev_priv->channels.ptr[0]); -+ -+ nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]); -+ nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL); -+ -+ if (dev_priv->ramin_heap.free_stack.next) -+ drm_mm_takedown(&dev_priv->ramin_heap); - - dev_priv->engine.instmem.priv = NULL; - kfree(priv); -@@ -276,16 +270,8 @@ - nv50_instmem_suspend(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *chan = dev_priv->fifos[0]; -- struct nouveau_gpuobj *ramin = chan->ramin; -- int i; - -- ramin->im_backing_suspend = vmalloc(ramin->size); -- if (!ramin->im_backing_suspend) -- return -ENOMEM; -- -- for (i = 0; i < ramin->size; i += 4) -- ramin->im_backing_suspend[i/4] = nv_ri32(dev, i); -+ dev_priv->ramin_available = false; - return 0; - } - -@@ -294,146 +280,121 @@ - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; -- struct nouveau_channel *chan = dev_priv->fifos[0]; -- struct nouveau_gpuobj *ramin = chan->ramin; -+ struct nouveau_channel *chan = dev_priv->channels.ptr[0]; - int i; - -- dev_priv->ramin_available = false; -- dev_priv->ramin_base = ~0; -- for (i = 0; i < ramin->size; i += 4) -- nv_wo32(ramin, i, ramin->im_backing_suspend[i/4]); -- dev_priv->ramin_available = true; -- vfree(ramin->im_backing_suspend); -- ramin->im_backing_suspend = NULL; -- - /* Poke the relevant regs, and pray it works :) */ - nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12)); - nv_wr32(dev, NV50_PUNK_UNK1710, 0); - nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12) | - NV50_PUNK_BAR_CFG_BASE_VALID); -- nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->fb_bar->cinst >> 4) | -+ nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->bar1_dmaobj->cinst >> 4) | - NV50_PUNK_BAR1_CTXDMA_VALID); -- nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->cinst >> 4) | -+ nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->bar3_dmaobj->cinst >> 4) | - NV50_PUNK_BAR3_CTXDMA_VALID); - - for (i = 0; i < 8; i++) - nv_wr32(dev, 0x1900 + (i*4), 0); -+ -+ dev_priv->ramin_available = true; - } - -+struct nv50_gpuobj_node { -+ struct nouveau_vram *vram; -+ struct nouveau_vma chan_vma; -+ u32 align; -+}; -+ -+ - int --nv50_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, -- uint32_t *sz) -+nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align) - { -+ struct drm_device *dev = gpuobj->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_vram_engine *vram = &dev_priv->engine.vram; -+ struct nv50_gpuobj_node *node = NULL; - int ret; - -- if (gpuobj->im_backing) -- return -EINVAL; -+ node = kzalloc(sizeof(*node), GFP_KERNEL); -+ if (!node) -+ return -ENOMEM; -+ node->align = align; - -- *sz = ALIGN(*sz, 4096); -- if (*sz == 0) -- return -EINVAL; -+ size = (size + 4095) & ~4095; -+ align = max(align, (u32)4096); - -- ret = nouveau_bo_new(dev, NULL, *sz, 0, TTM_PL_FLAG_VRAM, 0, 0x0000, -- true, false, &gpuobj->im_backing); -+ ret = vram->get(dev, size, align, 0, 0, &node->vram); - if (ret) { -- NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret); -+ kfree(node); - return ret; - } - -- ret = nouveau_bo_pin(gpuobj->im_backing, TTM_PL_FLAG_VRAM); -- if (ret) { -- NV_ERROR(dev, "error pinning PRAMIN backing VRAM: %d\n", ret); -- nouveau_bo_ref(NULL, &gpuobj->im_backing); -- return ret; -+ gpuobj->vinst = node->vram->offset; -+ -+ if (gpuobj->flags & NVOBJ_FLAG_VM) { -+ ret = nouveau_vm_get(dev_priv->chan_vm, size, 12, -+ NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, -+ &node->chan_vma); -+ if (ret) { -+ vram->put(dev, &node->vram); -+ kfree(node); -+ return ret; -+ } -+ -+ nouveau_vm_map(&node->chan_vma, node->vram); -+ gpuobj->vinst = node->chan_vma.offset; - } - -- gpuobj->vinst = gpuobj->im_backing->bo.mem.start << PAGE_SHIFT; -+ gpuobj->size = size; -+ gpuobj->node = node; - return 0; - } - - void --nv50_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) -+nv50_instmem_put(struct nouveau_gpuobj *gpuobj) - { -+ struct drm_device *dev = gpuobj->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_vram_engine *vram = &dev_priv->engine.vram; -+ struct nv50_gpuobj_node *node; -+ -+ node = gpuobj->node; -+ gpuobj->node = NULL; - -- if (gpuobj && gpuobj->im_backing) { -- if (gpuobj->im_bound) -- dev_priv->engine.instmem.unbind(dev, gpuobj); -- nouveau_bo_unpin(gpuobj->im_backing); -- nouveau_bo_ref(NULL, &gpuobj->im_backing); -- gpuobj->im_backing = NULL; -+ if (node->chan_vma.node) { -+ nouveau_vm_unmap(&node->chan_vma); -+ nouveau_vm_put(&node->chan_vma); - } -+ vram->put(dev, &node->vram); -+ kfree(node); - } - - int --nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) -+nv50_instmem_map(struct nouveau_gpuobj *gpuobj) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; -- struct nouveau_gpuobj *pramin_pt = priv->pramin_pt; -- uint32_t pte, pte_end; -- uint64_t vram; -- -- if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) -- return -EINVAL; -- -- NV_DEBUG(dev, "st=0x%lx sz=0x%lx\n", -- gpuobj->im_pramin->start, gpuobj->im_pramin->size); -- -- pte = (gpuobj->im_pramin->start >> 12) << 1; -- pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; -- vram = gpuobj->vinst; -- -- NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", -- gpuobj->im_pramin->start, pte, pte_end); -- NV_DEBUG(dev, "first vram page: 0x%010llx\n", gpuobj->vinst); -- -- vram |= 1; -- if (dev_priv->vram_sys_base) { -- vram += dev_priv->vram_sys_base; -- vram |= 0x30; -- } -- -- while (pte < pte_end) { -- nv_wo32(pramin_pt, (pte * 4) + 0, lower_32_bits(vram)); -- nv_wo32(pramin_pt, (pte * 4) + 4, upper_32_bits(vram)); -- vram += 0x1000; -- pte += 2; -- } -- dev_priv->engine.instmem.flush(dev); -+ struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; -+ struct nv50_gpuobj_node *node = gpuobj->node; -+ int ret; - -- nv50_vm_flush(dev, 6); -+ ret = nouveau_vm_get(dev_priv->bar3_vm, gpuobj->size, 12, -+ NV_MEM_ACCESS_RW, &node->vram->bar_vma); -+ if (ret) -+ return ret; - -- gpuobj->im_bound = 1; -+ nouveau_vm_map(&node->vram->bar_vma, node->vram); -+ gpuobj->pinst = node->vram->bar_vma.offset; - return 0; - } - --int --nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) -+void -+nv50_instmem_unmap(struct nouveau_gpuobj *gpuobj) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; -- uint32_t pte, pte_end; -- -- if (gpuobj->im_bound == 0) -- return -EINVAL; -+ struct nv50_gpuobj_node *node = gpuobj->node; - -- /* can happen during late takedown */ -- if (unlikely(!dev_priv->ramin_available)) -- return 0; -- -- pte = (gpuobj->im_pramin->start >> 12) << 1; -- pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; -- -- while (pte < pte_end) { -- nv_wo32(priv->pramin_pt, (pte * 4) + 0, 0x00000000); -- nv_wo32(priv->pramin_pt, (pte * 4) + 4, 0x00000000); -- pte += 2; -+ if (node->vram->bar_vma.node) { -+ nouveau_vm_unmap(&node->vram->bar_vma); -+ nouveau_vm_put(&node->vram->bar_vma); - } -- dev_priv->engine.instmem.flush(dev); -- -- gpuobj->im_bound = 0; -- return 0; - } - - void -@@ -452,11 +413,3 @@ - NV_ERROR(dev, "PRAMIN flush timeout\n"); - } - --void --nv50_vm_flush(struct drm_device *dev, int engine) --{ -- nv_wr32(dev, 0x100c80, (engine << 16) | 1); -- if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000)) -- NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); --} -- -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_vm.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_vm.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_vm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_vm.c 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,180 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+ -+#include "nouveau_drv.h" -+#include "nouveau_vm.h" -+ -+void -+nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, -+ struct nouveau_gpuobj *pgt[2]) -+{ -+ struct drm_nouveau_private *dev_priv = pgd->dev->dev_private; -+ u64 phys = 0xdeadcafe00000000ULL; -+ u32 coverage = 0; -+ -+ if (pgt[0]) { -+ phys = 0x00000003 | pgt[0]->vinst; /* present, 4KiB pages */ -+ coverage = (pgt[0]->size >> 3) << 12; -+ } else -+ if (pgt[1]) { -+ phys = 0x00000001 | pgt[1]->vinst; /* present */ -+ coverage = (pgt[1]->size >> 3) << 16; -+ } -+ -+ if (phys & 1) { -+ if (dev_priv->vram_sys_base) { -+ phys += dev_priv->vram_sys_base; -+ phys |= 0x30; -+ } -+ -+ if (coverage <= 32 * 1024 * 1024) -+ phys |= 0x60; -+ else if (coverage <= 64 * 1024 * 1024) -+ phys |= 0x40; -+ else if (coverage < 128 * 1024 * 1024) -+ phys |= 0x20; -+ } -+ -+ nv_wo32(pgd, (pde * 8) + 0, lower_32_bits(phys)); -+ nv_wo32(pgd, (pde * 8) + 4, upper_32_bits(phys)); -+} -+ -+static inline u64 -+nv50_vm_addr(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, -+ u64 phys, u32 memtype, u32 target) -+{ -+ struct drm_nouveau_private *dev_priv = pgt->dev->dev_private; -+ -+ phys |= 1; /* present */ -+ phys |= (u64)memtype << 40; -+ -+ /* IGPs don't have real VRAM, re-target to stolen system memory */ -+ if (target == 0 && dev_priv->vram_sys_base) { -+ phys += dev_priv->vram_sys_base; -+ target = 3; -+ } -+ -+ phys |= target << 4; -+ -+ if (vma->access & NV_MEM_ACCESS_SYS) -+ phys |= (1 << 6); -+ -+ if (!(vma->access & NV_MEM_ACCESS_WO)) -+ phys |= (1 << 3); -+ -+ return phys; -+} -+ -+void -+nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, -+ struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys) -+{ -+ u32 block; -+ int i; -+ -+ phys = nv50_vm_addr(vma, pgt, phys, mem->memtype, 0); -+ pte <<= 3; -+ cnt <<= 3; -+ -+ while (cnt) { -+ u32 offset_h = upper_32_bits(phys); -+ u32 offset_l = lower_32_bits(phys); -+ -+ for (i = 7; i >= 0; i--) { -+ block = 1 << (i + 3); -+ if (cnt >= block && !(pte & (block - 1))) -+ break; -+ } -+ offset_l |= (i << 7); -+ -+ phys += block << (vma->node->type - 3); -+ cnt -= block; -+ -+ while (block) { -+ nv_wo32(pgt, pte + 0, offset_l); -+ nv_wo32(pgt, pte + 4, offset_h); -+ pte += 8; -+ block -= 8; -+ } -+ } -+} -+ -+void -+nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, -+ u32 pte, dma_addr_t *list, u32 cnt) -+{ -+ pte <<= 3; -+ while (cnt--) { -+ u64 phys = nv50_vm_addr(vma, pgt, (u64)*list++, 0, 2); -+ nv_wo32(pgt, pte + 0, lower_32_bits(phys)); -+ nv_wo32(pgt, pte + 4, upper_32_bits(phys)); -+ pte += 8; -+ } -+} -+ -+void -+nv50_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) -+{ -+ pte <<= 3; -+ while (cnt--) { -+ nv_wo32(pgt, pte + 0, 0x00000000); -+ nv_wo32(pgt, pte + 4, 0x00000000); -+ pte += 8; -+ } -+} -+ -+void -+nv50_vm_flush(struct nouveau_vm *vm) -+{ -+ struct drm_nouveau_private *dev_priv = vm->dev->dev_private; -+ struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; -+ struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -+ struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt; -+ -+ pinstmem->flush(vm->dev); -+ -+ /* BAR */ -+ if (vm != dev_priv->chan_vm) { -+ nv50_vm_flush_engine(vm->dev, 6); -+ return; -+ } -+ -+ pfifo->tlb_flush(vm->dev); -+ -+ if (atomic_read(&vm->pgraph_refs)) -+ pgraph->tlb_flush(vm->dev); -+ if (atomic_read(&vm->pcrypt_refs)) -+ pcrypt->tlb_flush(vm->dev); -+} -+ -+void -+nv50_vm_flush_engine(struct drm_device *dev, int engine) -+{ -+ nv_wr32(dev, 0x100c80, (engine << 16) | 1); -+ if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000)) -+ NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_vram.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_vram.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv50_vram.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv50_vram.c 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,190 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+#include "nouveau_drv.h" -+#include "nouveau_mm.h" -+ -+static int types[0x80] = { -+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, -+ 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, -+ 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2, -+ 1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0 -+}; -+ -+bool -+nv50_vram_flags_valid(struct drm_device *dev, u32 tile_flags) -+{ -+ int type = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; -+ -+ if (likely(type < ARRAY_SIZE(types) && types[type])) -+ return true; -+ return false; -+} -+ -+void -+nv50_vram_del(struct drm_device *dev, struct nouveau_vram **pvram) -+{ -+ 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_node *this; -+ struct nouveau_vram *vram; -+ -+ vram = *pvram; -+ *pvram = NULL; -+ if (unlikely(vram == NULL)) -+ return; -+ -+ mutex_lock(&mm->mutex); -+ while (!list_empty(&vram->regions)) { -+ this = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); -+ -+ list_del(&this->rl_entry); -+ nouveau_mm_put(mm, this); -+ } -+ mutex_unlock(&mm->mutex); -+ -+ kfree(vram); -+} -+ -+int -+nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, -+ u32 type, struct nouveau_vram **pvram) -+{ -+ 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_node *r; -+ struct nouveau_vram *vram; -+ int ret; -+ -+ if (!types[type]) -+ return -EINVAL; -+ size >>= 12; -+ align >>= 12; -+ size_nc >>= 12; -+ -+ vram = kzalloc(sizeof(*vram), GFP_KERNEL); -+ if (!vram) -+ return -ENOMEM; -+ -+ INIT_LIST_HEAD(&vram->regions); -+ vram->dev = dev_priv->dev; -+ vram->memtype = type; -+ vram->size = size; -+ -+ mutex_lock(&mm->mutex); -+ do { -+ ret = nouveau_mm_get(mm, types[type], size, size_nc, align, &r); -+ if (ret) { -+ mutex_unlock(&mm->mutex); -+ nv50_vram_del(dev, &vram); -+ return ret; -+ } -+ -+ list_add_tail(&r->rl_entry, &vram->regions); -+ size -= r->length; -+ } while (size); -+ mutex_unlock(&mm->mutex); -+ -+ r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); -+ vram->offset = (u64)r->offset << 12; -+ *pvram = vram; -+ return 0; -+} -+ -+static u32 -+nv50_vram_rblock(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int i, parts, colbits, rowbitsa, rowbitsb, banks; -+ u64 rowsize, predicted; -+ u32 r0, r4, rt, ru, rblock_size; -+ -+ r0 = nv_rd32(dev, 0x100200); -+ r4 = nv_rd32(dev, 0x100204); -+ rt = nv_rd32(dev, 0x100250); -+ ru = nv_rd32(dev, 0x001540); -+ NV_DEBUG(dev, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru); -+ -+ for (i = 0, parts = 0; i < 8; i++) { -+ if (ru & (0x00010000 << i)) -+ parts++; -+ } -+ -+ colbits = (r4 & 0x0000f000) >> 12; -+ rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; -+ rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; -+ banks = ((r4 & 0x01000000) ? 8 : 4); -+ -+ rowsize = parts * banks * (1 << colbits) * 8; -+ predicted = rowsize << rowbitsa; -+ if (r0 & 0x00000004) -+ predicted += rowsize << rowbitsb; -+ -+ if (predicted != dev_priv->vram_size) { -+ NV_WARN(dev, "memory controller reports %dMiB VRAM\n", -+ (u32)(dev_priv->vram_size >> 20)); -+ NV_WARN(dev, "we calculated %dMiB VRAM\n", -+ (u32)(predicted >> 20)); -+ } -+ -+ rblock_size = rowsize; -+ if (rt & 1) -+ rblock_size *= 3; -+ -+ NV_DEBUG(dev, "rblock %d bytes\n", rblock_size); -+ return rblock_size; -+} -+ -+int -+nv50_vram_init(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ 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: -+ 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; -+ } -+ -+ return 0; -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv84_crypt.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv84_crypt.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nv84_crypt.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nv84_crypt.c 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,140 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+#include "nouveau_drv.h" -+#include "nouveau_util.h" -+#include "nouveau_vm.h" -+ -+static void nv84_crypt_isr(struct drm_device *); -+ -+int -+nv84_crypt_create_context(struct nouveau_channel *chan) -+{ -+ struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj *ramin = chan->ramin; -+ int ret; -+ -+ NV_DEBUG(dev, "ch%d\n", chan->id); -+ -+ ret = nouveau_gpuobj_new(dev, chan, 256, 0, -+ NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, -+ &chan->crypt_ctx); -+ if (ret) -+ return ret; -+ -+ nv_wo32(ramin, 0xa0, 0x00190000); -+ nv_wo32(ramin, 0xa4, chan->crypt_ctx->vinst + 0xff); -+ nv_wo32(ramin, 0xa8, chan->crypt_ctx->vinst); -+ nv_wo32(ramin, 0xac, 0); -+ nv_wo32(ramin, 0xb0, 0); -+ nv_wo32(ramin, 0xb4, 0); -+ -+ dev_priv->engine.instmem.flush(dev); -+ atomic_inc(&chan->vm->pcrypt_refs); -+ return 0; -+} -+ -+void -+nv84_crypt_destroy_context(struct nouveau_channel *chan) -+{ -+ struct drm_device *dev = chan->dev; -+ u32 inst; -+ -+ if (!chan->crypt_ctx) -+ return; -+ -+ inst = (chan->ramin->vinst >> 12); -+ inst |= 0x80000000; -+ -+ /* mark context as invalid if still on the hardware, not -+ * doing this causes issues the next time PCRYPT is used, -+ * unsurprisingly :) -+ */ -+ nv_wr32(dev, 0x10200c, 0x00000000); -+ if (nv_rd32(dev, 0x102188) == inst) -+ nv_mask(dev, 0x102188, 0x80000000, 0x00000000); -+ if (nv_rd32(dev, 0x10218c) == inst) -+ nv_mask(dev, 0x10218c, 0x80000000, 0x00000000); -+ nv_wr32(dev, 0x10200c, 0x00000010); -+ -+ nouveau_gpuobj_ref(NULL, &chan->crypt_ctx); -+ atomic_dec(&chan->vm->pcrypt_refs); -+} -+ -+void -+nv84_crypt_tlb_flush(struct drm_device *dev) -+{ -+ nv50_vm_flush_engine(dev, 0x0a); -+} -+ -+int -+nv84_crypt_init(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt; -+ -+ if (!pcrypt->registered) { -+ NVOBJ_CLASS(dev, 0x74c1, CRYPT); -+ pcrypt->registered = true; -+ } -+ -+ nv_mask(dev, 0x000200, 0x00004000, 0x00000000); -+ nv_mask(dev, 0x000200, 0x00004000, 0x00004000); -+ -+ nouveau_irq_register(dev, 14, nv84_crypt_isr); -+ nv_wr32(dev, 0x102130, 0xffffffff); -+ nv_wr32(dev, 0x102140, 0xffffffbf); -+ -+ nv_wr32(dev, 0x10200c, 0x00000010); -+ return 0; -+} -+ -+void -+nv84_crypt_fini(struct drm_device *dev) -+{ -+ nv_wr32(dev, 0x102140, 0x00000000); -+ nouveau_irq_unregister(dev, 14); -+} -+ -+static void -+nv84_crypt_isr(struct drm_device *dev) -+{ -+ u32 stat = nv_rd32(dev, 0x102130); -+ u32 mthd = nv_rd32(dev, 0x102190); -+ u32 data = nv_rd32(dev, 0x102194); -+ u32 inst = nv_rd32(dev, 0x102188) & 0x7fffffff; -+ int show = nouveau_ratelimit(); -+ -+ if (show) { -+ NV_INFO(dev, "PCRYPT_INTR: 0x%08x 0x%08x 0x%08x 0x%08x\n", -+ stat, mthd, data, inst); -+ } -+ -+ nv_wr32(dev, 0x102130, stat); -+ nv_wr32(dev, 0x10200c, 0x10); -+ -+ nv50_fb_vm_trap(dev, show, "PCRYPT"); -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_fbcon.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_fbcon.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_fbcon.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_fbcon.c 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,269 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+#include "nouveau_drv.h" -+#include "nouveau_dma.h" -+#include "nouveau_ramht.h" -+#include "nouveau_fbcon.h" -+#include "nouveau_mm.h" -+ -+int -+nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) -+{ -+ struct nouveau_fbdev *nfbdev = info->par; -+ struct drm_device *dev = nfbdev->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *chan = dev_priv->channel; -+ int ret; -+ -+ ret = RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11); -+ if (ret) -+ return ret; -+ -+ if (rect->rop != ROP_COPY) { -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x02ac, 1); -+ OUT_RING (chan, 1); -+ } -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0588, 1); -+ if (info->fix.visual == FB_VISUAL_TRUECOLOR || -+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) -+ OUT_RING (chan, ((uint32_t *)info->pseudo_palette)[rect->color]); -+ else -+ OUT_RING (chan, rect->color); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0600, 4); -+ OUT_RING (chan, rect->dx); -+ OUT_RING (chan, rect->dy); -+ OUT_RING (chan, rect->dx + rect->width); -+ OUT_RING (chan, rect->dy + rect->height); -+ if (rect->rop != ROP_COPY) { -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x02ac, 1); -+ OUT_RING (chan, 3); -+ } -+ FIRE_RING(chan); -+ return 0; -+} -+ -+int -+nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) -+{ -+ struct nouveau_fbdev *nfbdev = info->par; -+ struct drm_device *dev = nfbdev->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *chan = dev_priv->channel; -+ int ret; -+ -+ ret = RING_SPACE(chan, 12); -+ if (ret) -+ return ret; -+ -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0110, 1); -+ OUT_RING (chan, 0); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x08b0, 4); -+ OUT_RING (chan, region->dx); -+ OUT_RING (chan, region->dy); -+ OUT_RING (chan, region->width); -+ OUT_RING (chan, region->height); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x08d0, 4); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, region->sx); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, region->sy); -+ FIRE_RING(chan); -+ return 0; -+} -+ -+int -+nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) -+{ -+ struct nouveau_fbdev *nfbdev = info->par; -+ struct drm_device *dev = nfbdev->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *chan = dev_priv->channel; -+ uint32_t width, dwords, *data = (uint32_t *)image->data; -+ uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); -+ uint32_t *palette = info->pseudo_palette; -+ int ret; -+ -+ if (image->depth != 1) -+ return -ENODEV; -+ -+ ret = RING_SPACE(chan, 11); -+ if (ret) -+ return ret; -+ -+ width = ALIGN(image->width, 32); -+ dwords = (width * image->height) >> 5; -+ -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0814, 2); -+ if (info->fix.visual == FB_VISUAL_TRUECOLOR || -+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) { -+ OUT_RING (chan, palette[image->bg_color] | mask); -+ OUT_RING (chan, palette[image->fg_color] | mask); -+ } else { -+ OUT_RING (chan, image->bg_color); -+ OUT_RING (chan, image->fg_color); -+ } -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0838, 2); -+ OUT_RING (chan, image->width); -+ OUT_RING (chan, image->height); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0850, 4); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, image->dx); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, image->dy); -+ -+ while (dwords) { -+ int push = dwords > 2047 ? 2047 : dwords; -+ -+ ret = RING_SPACE(chan, push + 1); -+ if (ret) -+ return ret; -+ -+ dwords -= push; -+ -+ BEGIN_NVC0(chan, 6, NvSub2D, 0x0860, push); -+ OUT_RINGp(chan, data, push); -+ data += push; -+ } -+ -+ FIRE_RING(chan); -+ return 0; -+} -+ -+int -+nvc0_fbcon_accel_init(struct fb_info *info) -+{ -+ struct nouveau_fbdev *nfbdev = info->par; -+ 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; -+ int ret, format; -+ -+ ret = nouveau_gpuobj_gr_new(chan, 0x902d, 0x902d); -+ if (ret) -+ return ret; -+ -+ switch (info->var.bits_per_pixel) { -+ case 8: -+ format = 0xf3; -+ break; -+ case 15: -+ format = 0xf8; -+ break; -+ case 16: -+ format = 0xe8; -+ break; -+ case 32: -+ switch (info->var.transp.length) { -+ case 0: /* depth 24 */ -+ case 8: /* depth 32, just use 24.. */ -+ format = 0xe6; -+ break; -+ case 2: /* depth 30 */ -+ format = 0xd1; -+ break; -+ default: -+ return -EINVAL; -+ } -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ ret = RING_SPACE(chan, 60); -+ if (ret) { -+ WARN_ON(1); -+ nouveau_fbcon_gpu_lockup(info); -+ return ret; -+ } -+ -+ 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)); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0290, 1); -+ OUT_RING (chan, 0); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0888, 1); -+ OUT_RING (chan, 1); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x02ac, 1); -+ OUT_RING (chan, 3); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x02a0, 1); -+ OUT_RING (chan, 0x55); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x08c0, 4); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, 1); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, 1); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0580, 2); -+ OUT_RING (chan, 4); -+ OUT_RING (chan, format); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x02e8, 2); -+ OUT_RING (chan, 2); -+ OUT_RING (chan, 1); -+ -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0804, 1); -+ OUT_RING (chan, format); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0800, 1); -+ OUT_RING (chan, 1); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0808, 3); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, 1); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x081c, 1); -+ OUT_RING (chan, 1); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0840, 4); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, 1); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, 1); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0200, 10); -+ OUT_RING (chan, format); -+ OUT_RING (chan, 1); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, 1); -+ OUT_RING (chan, 0); -+ 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)); -+ BEGIN_NVC0(chan, 2, NvSub2D, 0x0230, 10); -+ OUT_RING (chan, format); -+ OUT_RING (chan, 1); -+ OUT_RING (chan, 0); -+ OUT_RING (chan, 1); -+ OUT_RING (chan, 0); -+ 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)); -+ FIRE_RING (chan); -+ -+ return 0; -+} -+ -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_fifo.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_fifo.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_fifo.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_fifo.c 2011-01-07 14:22:17.000000000 +0100 -@@ -25,6 +25,49 @@ - #include "drmP.h" - - #include "nouveau_drv.h" -+#include "nouveau_mm.h" -+ -+static void nvc0_fifo_isr(struct drm_device *); -+ -+struct nvc0_fifo_priv { -+ struct nouveau_gpuobj *playlist[2]; -+ int cur_playlist; -+ struct nouveau_vma user_vma; -+ int spoon_nr; -+}; -+ -+struct nvc0_fifo_chan { -+ struct nouveau_bo *user; -+ struct nouveau_gpuobj *ramfc; -+}; -+ -+static void -+nvc0_fifo_playlist_update(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; -+ struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; -+ struct nvc0_fifo_priv *priv = pfifo->priv; -+ struct nouveau_gpuobj *cur; -+ int i, p; -+ -+ cur = priv->playlist[priv->cur_playlist]; -+ priv->cur_playlist = !priv->cur_playlist; -+ -+ for (i = 0, p = 0; i < 128; i++) { -+ if (!(nv_rd32(dev, 0x3004 + (i * 8)) & 1)) -+ continue; -+ nv_wo32(cur, p + 0, i); -+ nv_wo32(cur, p + 4, 0x00000004); -+ p += 8; -+ } -+ pinstmem->flush(dev); -+ -+ nv_wr32(dev, 0x002270, cur->vinst >> 12); -+ nv_wr32(dev, 0x002274, 0x01f00000 | (p >> 3)); -+ if (!nv_wait(dev, 0x00227c, 0x00100000, 0x00000000)) -+ NV_ERROR(dev, "PFIFO - playlist update failed\n"); -+} - - void - nvc0_fifo_disable(struct drm_device *dev) -@@ -57,12 +100,135 @@ - int - nvc0_fifo_create_context(struct nouveau_channel *chan) - { -+ struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; -+ struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; -+ struct nvc0_fifo_priv *priv = pfifo->priv; -+ struct nvc0_fifo_chan *fifoch; -+ u64 ib_virt, user_vinst; -+ int ret; -+ -+ chan->fifo_priv = kzalloc(sizeof(*fifoch), GFP_KERNEL); -+ if (!chan->fifo_priv) -+ return -ENOMEM; -+ fifoch = chan->fifo_priv; -+ -+ /* allocate vram for control regs, map into polling area */ -+ ret = nouveau_bo_new(dev, NULL, 0x1000, 0, TTM_PL_FLAG_VRAM, -+ 0, 0, true, true, &fifoch->user); -+ if (ret) -+ goto error; -+ -+ ret = nouveau_bo_pin(fifoch->user, TTM_PL_FLAG_VRAM); -+ if (ret) { -+ nouveau_bo_ref(NULL, &fifoch->user); -+ goto error; -+ } -+ -+ user_vinst = fifoch->user->bo.mem.start << PAGE_SHIFT; -+ -+ ret = nouveau_bo_map(fifoch->user); -+ if (ret) { -+ nouveau_bo_unpin(fifoch->user); -+ nouveau_bo_ref(NULL, &fifoch->user); -+ goto error; -+ } -+ -+ nouveau_vm_map_at(&priv->user_vma, chan->id * 0x1000, -+ fifoch->user->bo.mem.mm_node); -+ -+ chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) + -+ priv->user_vma.offset + (chan->id * 0x1000), -+ PAGE_SIZE); -+ if (!chan->user) { -+ ret = -ENOMEM; -+ goto error; -+ } -+ -+ ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4; -+ -+ /* zero channel regs */ -+ nouveau_bo_wr32(fifoch->user, 0x0040/4, 0); -+ nouveau_bo_wr32(fifoch->user, 0x0044/4, 0); -+ nouveau_bo_wr32(fifoch->user, 0x0048/4, 0); -+ nouveau_bo_wr32(fifoch->user, 0x004c/4, 0); -+ nouveau_bo_wr32(fifoch->user, 0x0050/4, 0); -+ nouveau_bo_wr32(fifoch->user, 0x0058/4, 0); -+ nouveau_bo_wr32(fifoch->user, 0x005c/4, 0); -+ nouveau_bo_wr32(fifoch->user, 0x0060/4, 0); -+ nouveau_bo_wr32(fifoch->user, 0x0088/4, 0); -+ nouveau_bo_wr32(fifoch->user, 0x008c/4, 0); -+ -+ /* ramfc */ -+ ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst, -+ chan->ramin->vinst, 0x100, -+ NVOBJ_FLAG_ZERO_ALLOC, &fifoch->ramfc); -+ if (ret) -+ goto error; -+ -+ nv_wo32(fifoch->ramfc, 0x08, lower_32_bits(user_vinst)); -+ nv_wo32(fifoch->ramfc, 0x0c, upper_32_bits(user_vinst)); -+ nv_wo32(fifoch->ramfc, 0x10, 0x0000face); -+ nv_wo32(fifoch->ramfc, 0x30, 0xfffff902); -+ nv_wo32(fifoch->ramfc, 0x48, lower_32_bits(ib_virt)); -+ nv_wo32(fifoch->ramfc, 0x4c, drm_order(chan->dma.ib_max + 1) << 16 | -+ upper_32_bits(ib_virt)); -+ nv_wo32(fifoch->ramfc, 0x54, 0x00000002); -+ nv_wo32(fifoch->ramfc, 0x84, 0x20400000); -+ nv_wo32(fifoch->ramfc, 0x94, 0x30000001); -+ nv_wo32(fifoch->ramfc, 0x9c, 0x00000100); -+ nv_wo32(fifoch->ramfc, 0xa4, 0x1f1f1f1f); -+ nv_wo32(fifoch->ramfc, 0xa8, 0x1f1f1f1f); -+ nv_wo32(fifoch->ramfc, 0xac, 0x0000001f); -+ nv_wo32(fifoch->ramfc, 0xb8, 0xf8000000); -+ nv_wo32(fifoch->ramfc, 0xf8, 0x10003080); /* 0x002310 */ -+ nv_wo32(fifoch->ramfc, 0xfc, 0x10000010); /* 0x002350 */ -+ pinstmem->flush(dev); -+ -+ nv_wr32(dev, 0x003000 + (chan->id * 8), 0xc0000000 | -+ (chan->ramin->vinst >> 12)); -+ nv_wr32(dev, 0x003004 + (chan->id * 8), 0x001f0001); -+ nvc0_fifo_playlist_update(dev); - return 0; -+ -+error: -+ pfifo->destroy_context(chan); -+ return ret; - } - - void - nvc0_fifo_destroy_context(struct nouveau_channel *chan) - { -+ struct drm_device *dev = chan->dev; -+ struct nvc0_fifo_chan *fifoch; -+ -+ nv_mask(dev, 0x003004 + (chan->id * 8), 0x00000001, 0x00000000); -+ nv_wr32(dev, 0x002634, chan->id); -+ if (!nv_wait(dev, 0x0002634, 0xffffffff, chan->id)) -+ NV_WARN(dev, "0x2634 != chid: 0x%08x\n", nv_rd32(dev, 0x2634)); -+ -+ nvc0_fifo_playlist_update(dev); -+ -+ nv_wr32(dev, 0x003000 + (chan->id * 8), 0x00000000); -+ -+ if (chan->user) { -+ iounmap(chan->user); -+ chan->user = NULL; -+ } -+ -+ fifoch = chan->fifo_priv; -+ chan->fifo_priv = NULL; -+ if (!fifoch) -+ return; -+ -+ nouveau_gpuobj_ref(NULL, &fifoch->ramfc); -+ if (fifoch->user) { -+ nouveau_bo_unmap(fifoch->user); -+ nouveau_bo_unpin(fifoch->user); -+ nouveau_bo_ref(NULL, &fifoch->user); -+ } -+ kfree(fifoch); - } - - int -@@ -77,14 +243,213 @@ - return 0; - } - -+static void -+nvc0_fifo_destroy(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; -+ struct nvc0_fifo_priv *priv; -+ -+ priv = pfifo->priv; -+ if (!priv) -+ return; -+ -+ nouveau_vm_put(&priv->user_vma); -+ nouveau_gpuobj_ref(NULL, &priv->playlist[1]); -+ nouveau_gpuobj_ref(NULL, &priv->playlist[0]); -+ kfree(priv); -+} -+ - void - nvc0_fifo_takedown(struct drm_device *dev) - { -+ nv_wr32(dev, 0x002140, 0x00000000); -+ nvc0_fifo_destroy(dev); -+} -+ -+static int -+nvc0_fifo_create(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; -+ struct nvc0_fifo_priv *priv; -+ int ret; -+ -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ pfifo->priv = priv; -+ -+ ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000, 0, -+ &priv->playlist[0]); -+ if (ret) -+ goto error; -+ -+ ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000, 0, -+ &priv->playlist[1]); -+ if (ret) -+ goto error; -+ -+ ret = nouveau_vm_get(dev_priv->bar1_vm, pfifo->channels * 0x1000, -+ 12, NV_MEM_ACCESS_RW, &priv->user_vma); -+ if (ret) -+ goto error; -+ -+ nouveau_irq_register(dev, 8, nvc0_fifo_isr); -+ NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ -+ return 0; -+ -+error: -+ nvc0_fifo_destroy(dev); -+ return ret; - } - - int - nvc0_fifo_init(struct drm_device *dev) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; -+ struct nvc0_fifo_priv *priv; -+ int ret, i; -+ -+ if (!pfifo->priv) { -+ ret = nvc0_fifo_create(dev); -+ if (ret) -+ return ret; -+ } -+ priv = pfifo->priv; -+ -+ /* reset PFIFO, enable all available PSUBFIFO areas */ -+ nv_mask(dev, 0x000200, 0x00000100, 0x00000000); -+ nv_mask(dev, 0x000200, 0x00000100, 0x00000100); -+ nv_wr32(dev, 0x000204, 0xffffffff); -+ nv_wr32(dev, 0x002204, 0xffffffff); -+ -+ priv->spoon_nr = hweight32(nv_rd32(dev, 0x002204)); -+ NV_DEBUG(dev, "PFIFO: %d subfifo(s)\n", priv->spoon_nr); -+ -+ /* assign engines to subfifos */ -+ if (priv->spoon_nr >= 3) { -+ nv_wr32(dev, 0x002208, ~(1 << 0)); /* PGRAPH */ -+ nv_wr32(dev, 0x00220c, ~(1 << 1)); /* PVP */ -+ nv_wr32(dev, 0x002210, ~(1 << 1)); /* PPP */ -+ nv_wr32(dev, 0x002214, ~(1 << 1)); /* PBSP */ -+ nv_wr32(dev, 0x002218, ~(1 << 2)); /* PCE0 */ -+ nv_wr32(dev, 0x00221c, ~(1 << 1)); /* PCE1 */ -+ } -+ -+ /* PSUBFIFO[n] */ -+ for (i = 0; i < 3; i++) { -+ nv_mask(dev, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); -+ nv_wr32(dev, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ -+ nv_wr32(dev, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTR_EN */ -+ } -+ -+ nv_mask(dev, 0x002200, 0x00000001, 0x00000001); -+ nv_wr32(dev, 0x002254, 0x10000000 | priv->user_vma.offset >> 12); -+ -+ nv_wr32(dev, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */ -+ nv_wr32(dev, 0x002100, 0xffffffff); -+ nv_wr32(dev, 0x002140, 0xbfffffff); - return 0; - } - -+struct nouveau_enum nvc0_fifo_fault_unit[] = { -+ { 0, "PGRAPH" }, -+ { 3, "PEEPHOLE" }, -+ { 4, "BAR1" }, -+ { 5, "BAR3" }, -+ { 7, "PFIFO" }, -+ {} -+}; -+ -+struct nouveau_enum nvc0_fifo_fault_reason[] = { -+ { 0, "PT_NOT_PRESENT" }, -+ { 1, "PT_TOO_SHORT" }, -+ { 2, "PAGE_NOT_PRESENT" }, -+ { 3, "VM_LIMIT_EXCEEDED" }, -+ {} -+}; -+ -+struct nouveau_bitfield nvc0_fifo_subfifo_intr[] = { -+/* { 0x00008000, "" } seen with null ib push */ -+ { 0x00200000, "ILLEGAL_MTHD" }, -+ { 0x00800000, "EMPTY_SUBC" }, -+ {} -+}; -+ -+static void -+nvc0_fifo_isr_vm_fault(struct drm_device *dev, int unit) -+{ -+ u32 inst = nv_rd32(dev, 0x2800 + (unit * 0x10)); -+ u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10)); -+ u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10)); -+ u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10)); -+ -+ NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [", -+ (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo); -+ nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f); -+ printk("] from "); -+ nouveau_enum_print(nvc0_fifo_fault_unit, unit); -+ printk(" on channel 0x%010llx\n", (u64)inst << 12); -+} -+ -+static void -+nvc0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit) -+{ -+ u32 stat = nv_rd32(dev, 0x040108 + (unit * 0x2000)); -+ u32 addr = nv_rd32(dev, 0x0400c0 + (unit * 0x2000)); -+ u32 data = nv_rd32(dev, 0x0400c4 + (unit * 0x2000)); -+ u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f; -+ u32 subc = (addr & 0x00070000); -+ u32 mthd = (addr & 0x00003ffc); -+ -+ NV_INFO(dev, "PSUBFIFO %d:", unit); -+ nouveau_bitfield_print(nvc0_fifo_subfifo_intr, stat); -+ NV_INFO(dev, "PSUBFIFO %d: ch %d subc %d mthd 0x%04x data 0x%08x\n", -+ unit, chid, subc, mthd, data); -+ -+ nv_wr32(dev, 0x0400c0 + (unit * 0x2000), 0x80600008); -+ nv_wr32(dev, 0x040108 + (unit * 0x2000), stat); -+} -+ -+static void -+nvc0_fifo_isr(struct drm_device *dev) -+{ -+ u32 stat = nv_rd32(dev, 0x002100); -+ -+ if (stat & 0x10000000) { -+ u32 units = nv_rd32(dev, 0x00259c); -+ u32 u = units; -+ -+ while (u) { -+ int i = ffs(u) - 1; -+ nvc0_fifo_isr_vm_fault(dev, i); -+ u &= ~(1 << i); -+ } -+ -+ nv_wr32(dev, 0x00259c, units); -+ stat &= ~0x10000000; -+ } -+ -+ if (stat & 0x20000000) { -+ u32 units = nv_rd32(dev, 0x0025a0); -+ u32 u = units; -+ -+ while (u) { -+ int i = ffs(u) - 1; -+ nvc0_fifo_isr_subfifo_intr(dev, i); -+ u &= ~(1 << i); -+ } -+ -+ nv_wr32(dev, 0x0025a0, units); -+ stat &= ~0x20000000; -+ } -+ -+ if (stat) { -+ NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat); -+ nv_wr32(dev, 0x002100, stat); -+ } -+ -+ nv_wr32(dev, 0x2140, 0); -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_graph.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_graph.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_graph.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_graph.c 2011-01-07 14:22:17.000000000 +0100 -@@ -22,9 +22,16 @@ - * Authors: Ben Skeggs - */ - -+#include -+ - #include "drmP.h" - - #include "nouveau_drv.h" -+#include "nouveau_mm.h" -+#include "nvc0_graph.h" -+ -+static void nvc0_graph_isr(struct drm_device *); -+static int nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan); - - void - nvc0_graph_fifo_access(struct drm_device *dev, bool enabled) -@@ -37,39 +44,735 @@ - return NULL; - } - -+static int -+nvc0_graph_construct_context(struct nouveau_channel *chan) -+{ -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; -+ struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; -+ struct nvc0_graph_chan *grch = chan->pgraph_ctx; -+ struct drm_device *dev = chan->dev; -+ int ret, i; -+ u32 *ctx; -+ -+ ctx = kmalloc(priv->grctx_size, GFP_KERNEL); -+ if (!ctx) -+ return -ENOMEM; -+ -+ 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); -+ -+ ret = nvc0_grctx_generate(chan); -+ if (ret) { -+ kfree(ctx); -+ return ret; -+ } -+ -+ ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst); -+ if (ret) { -+ kfree(ctx); -+ return ret; -+ } -+ -+ for (i = 0; i < priv->grctx_size; i += 4) -+ ctx[i / 4] = nv_ro32(grch->grctx, i); -+ -+ priv->grctx_vals = ctx; -+ return 0; -+} -+ -+static int -+nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) -+{ -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; -+ struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; -+ struct nvc0_graph_chan *grch = chan->pgraph_ctx; -+ struct drm_device *dev = chan->dev; -+ int i = 0, gpc, tp, ret; -+ u32 magic; -+ -+ ret = nouveau_gpuobj_new(dev, NULL, 0x2000, 256, NVOBJ_FLAG_VM, -+ &grch->unk408004); -+ if (ret) -+ return ret; -+ -+ ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 256, NVOBJ_FLAG_VM, -+ &grch->unk40800c); -+ if (ret) -+ return ret; -+ -+ ret = nouveau_gpuobj_new(dev, NULL, 384 * 1024, 4096, NVOBJ_FLAG_VM, -+ &grch->unk418810); -+ if (ret) -+ return ret; -+ -+ ret = nouveau_gpuobj_new(dev, NULL, 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, 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, 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, 0x00419848); -+ nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810->vinst >> 12); -+ -+ nv_wo32(grch->mmio, i++ * 4, 0x00419004); -+ nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->vinst >> 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, 0x0041880c); -+ nv_wo32(grch->mmio, i++ * 4, 0x80000018); -+ -+ magic = 0x02180000; -+ 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) { -+ u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800); -+ nv_wo32(grch->mmio, i++ * 4, reg); -+ nv_wo32(grch->mmio, i++ * 4, magic); -+ } -+ } -+ -+ grch->mmio_nr = i / 2; -+ return 0; -+} -+ - int - nvc0_graph_create_context(struct nouveau_channel *chan) - { -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; -+ struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -+ struct nvc0_graph_priv *priv = pgraph->priv; -+ struct nvc0_graph_chan *grch; -+ struct drm_device *dev = chan->dev; -+ struct nouveau_gpuobj *grctx; -+ int ret, i; -+ -+ chan->pgraph_ctx = kzalloc(sizeof(*grch), GFP_KERNEL); -+ if (!chan->pgraph_ctx) -+ return -ENOMEM; -+ grch = chan->pgraph_ctx; -+ -+ ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256, -+ NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC, -+ &grch->grctx); -+ if (ret) -+ goto error; -+ chan->ramin_grctx = grch->grctx; -+ grctx = grch->grctx; -+ -+ ret = nvc0_graph_create_context_mmio_list(chan); -+ 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)); -+ pinstmem->flush(dev); -+ -+ if (!priv->grctx_vals) { -+ ret = nvc0_graph_construct_context(chan); -+ if (ret) -+ goto error; -+ } -+ -+ 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); -+ pinstmem->flush(dev); - return 0; -+ -+error: -+ pgraph->destroy_context(chan); -+ return ret; - } - - void - nvc0_graph_destroy_context(struct nouveau_channel *chan) - { -+ struct nvc0_graph_chan *grch; -+ -+ grch = chan->pgraph_ctx; -+ chan->pgraph_ctx = NULL; -+ if (!grch) -+ return; -+ -+ nouveau_gpuobj_ref(NULL, &grch->mmio); -+ nouveau_gpuobj_ref(NULL, &grch->unk418810); -+ nouveau_gpuobj_ref(NULL, &grch->unk40800c); -+ nouveau_gpuobj_ref(NULL, &grch->unk408004); -+ nouveau_gpuobj_ref(NULL, &grch->grctx); -+ chan->ramin_grctx = NULL; - } - - int - nvc0_graph_load_context(struct nouveau_channel *chan) - { -+ struct drm_device *dev = chan->dev; -+ -+ nv_wr32(dev, 0x409840, 0x00000030); -+ nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); -+ nv_wr32(dev, 0x409504, 0x00000003); -+ if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) -+ NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); -+ -+ return 0; -+} -+ -+static int -+nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan) -+{ -+ nv_wr32(dev, 0x409840, 0x00000003); -+ nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12); -+ nv_wr32(dev, 0x409504, 0x00000009); -+ if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) { -+ NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n"); -+ return -EBUSY; -+ } -+ - return 0; - } - - int - nvc0_graph_unload_context(struct drm_device *dev) - { -- return 0; -+ u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12; -+ return nvc0_graph_unload_context_to(dev, inst); -+} -+ -+static void -+nvc0_graph_destroy(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -+ struct nvc0_graph_priv *priv; -+ -+ priv = pgraph->priv; -+ if (!priv) -+ return; -+ -+ nouveau_irq_unregister(dev, 12); -+ -+ nouveau_gpuobj_ref(NULL, &priv->unk4188b8); -+ nouveau_gpuobj_ref(NULL, &priv->unk4188b4); -+ -+ if (priv->grctx_vals) -+ kfree(priv->grctx_vals); -+ kfree(priv); - } - - void - nvc0_graph_takedown(struct drm_device *dev) - { -+ nvc0_graph_destroy(dev); -+} -+ -+static int -+nvc0_graph_create(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -+ struct nvc0_graph_priv *priv; -+ int ret, gpc, i; -+ -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ pgraph->priv = priv; -+ -+ ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); -+ if (ret) -+ goto error; -+ -+ ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8); -+ if (ret) -+ goto error; -+ -+ for (i = 0; i < 0x1000; i += 4) { -+ nv_wo32(priv->unk4188b4, i, 0x00000010); -+ nv_wo32(priv->unk4188b8, i, 0x00000010); -+ } -+ -+ priv->gpc_nr = nv_rd32(dev, 0x409604) & 0x0000001f; -+ priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16; -+ for (gpc = 0; gpc < priv->gpc_nr; gpc++) { -+ priv->tp_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608)); -+ priv->tp_total += priv->tp_nr[gpc]; -+ } -+ -+ /*XXX: these need figuring out... */ -+ switch (dev_priv->chipset) { -+ 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->magicgpc980[0] = 0x22111000; -+ priv->magicgpc980[1] = 0x00000233; -+ priv->magicgpc980[2] = 0x00000000; -+ priv->magicgpc980[3] = 0x00000000; -+ priv->magicgpc918 = 0x000ba2e9; -+ } else -+ if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */ -+ priv->magic_not_rop_nr = 0x05; -+ priv->magicgpc980[0] = 0x11110000; -+ priv->magicgpc980[1] = 0x00233222; -+ priv->magicgpc980[2] = 0x00000000; -+ priv->magicgpc980[3] = 0x00000000; -+ priv->magicgpc918 = 0x00092493; -+ } else -+ if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */ -+ priv->magic_not_rop_nr = 0x06; -+ priv->magicgpc980[0] = 0x11110000; -+ priv->magicgpc980[1] = 0x03332222; -+ priv->magicgpc980[2] = 0x00000000; -+ priv->magicgpc980[3] = 0x00000000; -+ priv->magicgpc918 = 0x00088889; -+ } -+ break; -+ case 0xc3: /* 450, 4/0/0/0, 2 */ -+ priv->magic_not_rop_nr = 0x03; -+ priv->magicgpc980[0] = 0x00003210; -+ priv->magicgpc980[1] = 0x00000000; -+ priv->magicgpc980[2] = 0x00000000; -+ priv->magicgpc980[3] = 0x00000000; -+ priv->magicgpc918 = 0x00200000; -+ break; -+ case 0xc4: /* 460, 3/4/0/0, 4 */ -+ priv->magic_not_rop_nr = 0x01; -+ priv->magicgpc980[0] = 0x02321100; -+ priv->magicgpc980[1] = 0x00000000; -+ priv->magicgpc980[2] = 0x00000000; -+ priv->magicgpc980[3] = 0x00000000; -+ priv->magicgpc918 = 0x00124925; -+ break; -+ } -+ -+ if (!priv->magic_not_rop_nr) { -+ NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n", -+ priv->tp_nr[0], priv->tp_nr[1], priv->tp_nr[2], -+ priv->tp_nr[3], priv->rop_nr); -+ /* use 0xc3's values... */ -+ priv->magic_not_rop_nr = 0x03; -+ priv->magicgpc980[0] = 0x00003210; -+ priv->magicgpc980[1] = 0x00000000; -+ priv->magicgpc980[2] = 0x00000000; -+ priv->magicgpc980[3] = 0x00000000; -+ priv->magicgpc918 = 0x00200000; -+ } -+ -+ nouveau_irq_register(dev, 12, nvc0_graph_isr); -+ NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ -+ NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ -+ NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ -+ NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ -+ return 0; -+ -+error: -+ nvc0_graph_destroy(dev); -+ return ret; -+} -+ -+static void -+nvc0_graph_init_obj418880(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -+ struct nvc0_graph_priv *priv = pgraph->priv; -+ int i; -+ -+ nv_wr32(dev, GPC_BCAST(0x0880), 0x00000000); -+ nv_wr32(dev, GPC_BCAST(0x08a4), 0x00000000); -+ for (i = 0; i < 4; i++) -+ nv_wr32(dev, GPC_BCAST(0x0888) + (i * 4), 0x00000000); -+ nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->vinst >> 8); -+ nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->vinst >> 8); -+} -+ -+static void -+nvc0_graph_init_regs(struct drm_device *dev) -+{ -+ nv_wr32(dev, 0x400080, 0x003083c2); -+ nv_wr32(dev, 0x400088, 0x00006fe7); -+ nv_wr32(dev, 0x40008c, 0x00000000); -+ nv_wr32(dev, 0x400090, 0x00000030); -+ nv_wr32(dev, 0x40013c, 0x013901f7); -+ nv_wr32(dev, 0x400140, 0x00000100); -+ nv_wr32(dev, 0x400144, 0x00000000); -+ nv_wr32(dev, 0x400148, 0x00000110); -+ nv_wr32(dev, 0x400138, 0x00000000); -+ nv_wr32(dev, 0x400130, 0x00000000); -+ nv_wr32(dev, 0x400134, 0x00000000); -+ nv_wr32(dev, 0x400124, 0x00000002); -+} -+ -+static void -+nvc0_graph_init_gpc_0(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; -+ int gpc; -+ -+ // TP ROP UNKVAL(magic_not_rop_nr) -+ // 450: 4/0/0/0 2 3 -+ // 460: 3/4/0/0 4 1 -+ // 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 -+ -+ /* filled values up to tp_total, remainder 0 */ -+ // 450: 00003210 00000000 00000000 00000000 -+ // 460: 02321100 00000000 00000000 00000000 -+ // 465: 22111000 00000233 00000000 00000000 -+ // 470: 11110000 00233222 00000000 00000000 -+ // 480: 11110000 03332222 00000000 00000000 -+ -+ nv_wr32(dev, GPC_BCAST(0x0980), priv->magicgpc980[0]); -+ nv_wr32(dev, GPC_BCAST(0x0984), priv->magicgpc980[1]); -+ nv_wr32(dev, GPC_BCAST(0x0988), priv->magicgpc980[2]); -+ nv_wr32(dev, GPC_BCAST(0x098c), priv->magicgpc980[3]); -+ -+ for (gpc = 0; gpc < priv->gpc_nr; gpc++) { -+ 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_BCAST(0x1bd4), priv->magicgpc918); -+ nv_wr32(dev, GPC_BCAST(0x08ac), priv->rop_nr); -+} -+ -+static void -+nvc0_graph_init_units(struct drm_device *dev) -+{ -+ nv_wr32(dev, 0x409c24, 0x000f0000); -+ nv_wr32(dev, 0x404000, 0xc0000000); /* DISPATCH */ -+ nv_wr32(dev, 0x404600, 0xc0000000); /* M2MF */ -+ nv_wr32(dev, 0x408030, 0xc0000000); -+ nv_wr32(dev, 0x40601c, 0xc0000000); -+ nv_wr32(dev, 0x404490, 0xc0000000); /* MACRO */ -+ nv_wr32(dev, 0x406018, 0xc0000000); -+ nv_wr32(dev, 0x405840, 0xc0000000); -+ nv_wr32(dev, 0x405844, 0x00ffffff); -+ nv_mask(dev, 0x419cc0, 0x00000008, 0x00000008); -+ nv_mask(dev, 0x419eb4, 0x00001000, 0x00001000); -+} -+ -+static void -+nvc0_graph_init_gpc_1(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; -+ int gpc, tp; -+ -+ for (gpc = 0; gpc < priv->gpc_nr; gpc++) { -+ nv_wr32(dev, GPC_UNIT(gpc, 0x0420), 0xc0000000); -+ nv_wr32(dev, GPC_UNIT(gpc, 0x0900), 0xc0000000); -+ nv_wr32(dev, GPC_UNIT(gpc, 0x1028), 0xc0000000); -+ nv_wr32(dev, GPC_UNIT(gpc, 0x0824), 0xc0000000); -+ for (tp = 0; tp < priv->tp_nr[gpc]; tp++) { -+ nv_wr32(dev, TP_UNIT(gpc, tp, 0x508), 0xffffffff); -+ nv_wr32(dev, TP_UNIT(gpc, tp, 0x50c), 0xffffffff); -+ nv_wr32(dev, TP_UNIT(gpc, tp, 0x224), 0xc0000000); -+ nv_wr32(dev, TP_UNIT(gpc, tp, 0x48c), 0xc0000000); -+ nv_wr32(dev, TP_UNIT(gpc, tp, 0x084), 0xc0000000); -+ nv_wr32(dev, TP_UNIT(gpc, tp, 0xe44), 0x001ffffe); -+ nv_wr32(dev, TP_UNIT(gpc, tp, 0xe4c), 0x0000000f); -+ } -+ nv_wr32(dev, GPC_UNIT(gpc, 0x2c90), 0xffffffff); -+ nv_wr32(dev, GPC_UNIT(gpc, 0x2c94), 0xffffffff); -+ } -+} -+ -+static void -+nvc0_graph_init_rop(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; -+ int rop; -+ -+ for (rop = 0; rop < priv->rop_nr; rop++) { -+ nv_wr32(dev, ROP_UNIT(rop, 0x144), 0xc0000000); -+ nv_wr32(dev, ROP_UNIT(rop, 0x070), 0xc0000000); -+ nv_wr32(dev, ROP_UNIT(rop, 0x204), 0xffffffff); -+ nv_wr32(dev, ROP_UNIT(rop, 0x208), 0xffffffff); -+ } -+} -+ -+static int -+nvc0_fuc_load_fw(struct drm_device *dev, u32 fuc_base, -+ const char *code_fw, const char *data_fw) -+{ -+ const struct firmware *fw; -+ char name[32]; -+ int ret, i; -+ -+ snprintf(name, sizeof(name), "nouveau/%s", data_fw); -+ ret = request_firmware(&fw, name, &dev->pdev->dev); -+ if (ret) { -+ NV_ERROR(dev, "failed to load %s\n", data_fw); -+ return ret; -+ } -+ -+ nv_wr32(dev, fuc_base + 0x01c0, 0x01000000); -+ for (i = 0; i < fw->size / 4; i++) -+ nv_wr32(dev, fuc_base + 0x01c4, ((u32 *)fw->data)[i]); -+ release_firmware(fw); -+ -+ snprintf(name, sizeof(name), "nouveau/%s", code_fw); -+ ret = request_firmware(&fw, name, &dev->pdev->dev); -+ if (ret) { -+ NV_ERROR(dev, "failed to load %s\n", code_fw); -+ return ret; -+ } -+ -+ nv_wr32(dev, fuc_base + 0x0180, 0x01000000); -+ for (i = 0; i < fw->size / 4; i++) { -+ if ((i & 0x3f) == 0) -+ nv_wr32(dev, fuc_base + 0x0188, i >> 6); -+ nv_wr32(dev, fuc_base + 0x0184, ((u32 *)fw->data)[i]); -+ } -+ release_firmware(fw); -+ -+ return 0; -+} -+ -+static int -+nvc0_graph_init_ctxctl(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; -+ u32 r000260; -+ int ret; -+ -+ /* load fuc microcode */ -+ r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); -+ ret = nvc0_fuc_load_fw(dev, 0x409000, "fuc409c", "fuc409d"); -+ if (ret == 0) -+ ret = nvc0_fuc_load_fw(dev, 0x41a000, "fuc41ac", "fuc41ad"); -+ nv_wr32(dev, 0x000260, r000260); -+ -+ if (ret) -+ return ret; -+ -+ /* start both of them running */ -+ nv_wr32(dev, 0x409840, 0xffffffff); -+ nv_wr32(dev, 0x41a10c, 0x00000000); -+ nv_wr32(dev, 0x40910c, 0x00000000); -+ nv_wr32(dev, 0x41a100, 0x00000002); -+ nv_wr32(dev, 0x409100, 0x00000002); -+ if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000001)) -+ NV_INFO(dev, "0x409800 wait failed\n"); -+ -+ nv_wr32(dev, 0x409840, 0xffffffff); -+ nv_wr32(dev, 0x409500, 0x7fffffff); -+ nv_wr32(dev, 0x409504, 0x00000021); -+ -+ nv_wr32(dev, 0x409840, 0xffffffff); -+ nv_wr32(dev, 0x409500, 0x00000000); -+ nv_wr32(dev, 0x409504, 0x00000010); -+ if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { -+ NV_ERROR(dev, "fuc09 req 0x10 timeout\n"); -+ return -EBUSY; -+ } -+ priv->grctx_size = nv_rd32(dev, 0x409800); -+ -+ nv_wr32(dev, 0x409840, 0xffffffff); -+ nv_wr32(dev, 0x409500, 0x00000000); -+ nv_wr32(dev, 0x409504, 0x00000016); -+ if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { -+ NV_ERROR(dev, "fuc09 req 0x16 timeout\n"); -+ return -EBUSY; -+ } -+ -+ nv_wr32(dev, 0x409840, 0xffffffff); -+ nv_wr32(dev, 0x409500, 0x00000000); -+ nv_wr32(dev, 0x409504, 0x00000025); -+ if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { -+ NV_ERROR(dev, "fuc09 req 0x25 timeout\n"); -+ return -EBUSY; -+ } -+ -+ return 0; - } - - int - nvc0_graph_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -+ struct nvc0_graph_priv *priv; -+ int ret; -+ - dev_priv->engine.graph.accel_blocked = true; -+ -+ switch (dev_priv->chipset) { -+ case 0xc0: -+ case 0xc3: -+ case 0xc4: -+ break; -+ default: -+ NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n"); -+ if (nouveau_noaccel != 0) -+ return 0; -+ break; -+ } -+ -+ nv_mask(dev, 0x000200, 0x18001000, 0x00000000); -+ nv_mask(dev, 0x000200, 0x18001000, 0x18001000); -+ -+ if (!pgraph->priv) { -+ ret = nvc0_graph_create(dev); -+ if (ret) -+ return ret; -+ } -+ priv = pgraph->priv; -+ -+ nvc0_graph_init_obj418880(dev); -+ nvc0_graph_init_regs(dev); -+ //nvc0_graph_init_unitplemented_magics(dev); -+ nvc0_graph_init_gpc_0(dev); -+ //nvc0_graph_init_unitplemented_c242(dev); -+ -+ nv_wr32(dev, 0x400500, 0x00010001); -+ nv_wr32(dev, 0x400100, 0xffffffff); -+ nv_wr32(dev, 0x40013c, 0xffffffff); -+ -+ nvc0_graph_init_units(dev); -+ nvc0_graph_init_gpc_1(dev); -+ nvc0_graph_init_rop(dev); -+ -+ nv_wr32(dev, 0x400108, 0xffffffff); -+ nv_wr32(dev, 0x400138, 0xffffffff); -+ nv_wr32(dev, 0x400118, 0xffffffff); -+ nv_wr32(dev, 0x400130, 0xffffffff); -+ nv_wr32(dev, 0x40011c, 0xffffffff); -+ nv_wr32(dev, 0x400134, 0xffffffff); -+ nv_wr32(dev, 0x400054, 0x34ce3464); -+ -+ ret = nvc0_graph_init_ctxctl(dev); -+ if (ret == 0) -+ dev_priv->engine.graph.accel_blocked = false; - return 0; - } - -+static int -+nvc0_graph_isr_chid(struct drm_device *dev, u64 inst) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *chan; -+ unsigned long flags; -+ int i; -+ -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); -+ for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -+ chan = dev_priv->channels.ptr[i]; -+ if (!chan || !chan->ramin) -+ continue; -+ -+ if (inst == chan->ramin->vinst) -+ break; -+ } -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); -+ return i; -+} -+ -+static void -+nvc0_graph_isr(struct drm_device *dev) -+{ -+ u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12; -+ u32 chid = nvc0_graph_isr_chid(dev, inst); -+ u32 stat = nv_rd32(dev, 0x400100); -+ u32 addr = nv_rd32(dev, 0x400704); -+ u32 mthd = (addr & 0x00003ffc); -+ u32 subc = (addr & 0x00070000) >> 16; -+ u32 data = nv_rd32(dev, 0x400708); -+ u32 code = nv_rd32(dev, 0x400110); -+ u32 class = nv_rd32(dev, 0x404200 + (subc * 4)); -+ -+ if (stat & 0x00000010) { -+ NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] subc %d " -+ "class 0x%04x mthd 0x%04x data 0x%08x\n", -+ chid, inst, subc, class, mthd, data); -+ nv_wr32(dev, 0x400100, 0x00000010); -+ stat &= ~0x00000010; -+ } -+ -+ if (stat & 0x00000020) { -+ NV_INFO(dev, "PGRAPH: ILLEGAL_CLASS ch %d [0x%010llx] subc %d " -+ "class 0x%04x mthd 0x%04x data 0x%08x\n", -+ chid, inst, subc, class, mthd, data); -+ nv_wr32(dev, 0x400100, 0x00000020); -+ stat &= ~0x00000020; -+ } -+ -+ if (stat & 0x00100000) { -+ NV_INFO(dev, "PGRAPH: DATA_ERROR ["); -+ nouveau_enum_print(nv50_data_error_names, code); -+ printk("] ch %d [0x%010llx] subc %d class 0x%04x " -+ "mthd 0x%04x data 0x%08x\n", -+ chid, inst, subc, class, mthd, data); -+ nv_wr32(dev, 0x400100, 0x00100000); -+ stat &= ~0x00100000; -+ } -+ -+ if (stat & 0x00200000) { -+ u32 trap = nv_rd32(dev, 0x400108); -+ NV_INFO(dev, "PGRAPH: TRAP ch %d status 0x%08x\n", chid, trap); -+ nv_wr32(dev, 0x400108, trap); -+ nv_wr32(dev, 0x400100, 0x00200000); -+ stat &= ~0x00200000; -+ } -+ -+ if (stat & 0x00080000) { -+ u32 ustat = nv_rd32(dev, 0x409c18); -+ -+ NV_INFO(dev, "PGRAPH: CTXCTRL ustat 0x%08x\n", ustat); -+ -+ nv_wr32(dev, 0x409c20, ustat); -+ nv_wr32(dev, 0x400100, 0x00080000); -+ stat &= ~0x00080000; -+ } -+ -+ if (stat) { -+ NV_INFO(dev, "PGRAPH: unknown stat 0x%08x\n", stat); -+ nv_wr32(dev, 0x400100, stat); -+ } -+ -+ nv_wr32(dev, 0x400500, 0x00010001); -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_graph.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_graph.h ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_graph.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_graph.h 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,64 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#ifndef __NVC0_GRAPH_H__ -+#define __NVC0_GRAPH_H__ -+ -+#define GPC_MAX 4 -+#define TP_MAX 32 -+ -+#define ROP_BCAST(r) (0x408800 + (r)) -+#define ROP_UNIT(u,r) (0x410000 + (u) * 0x400 + (r)) -+#define GPC_BCAST(r) (0x418000 + (r)) -+#define GPC_UNIT(t,r) (0x500000 + (t) * 0x8000 + (r)) -+#define TP_UNIT(t,m,r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) -+ -+struct nvc0_graph_priv { -+ u8 gpc_nr; -+ u8 rop_nr; -+ u8 tp_nr[GPC_MAX]; -+ u8 tp_total; -+ -+ u32 grctx_size; -+ u32 *grctx_vals; -+ struct nouveau_gpuobj *unk4188b4; -+ struct nouveau_gpuobj *unk4188b8; -+ -+ u8 magic_not_rop_nr; -+ u32 magicgpc980[4]; -+ u32 magicgpc918; -+}; -+ -+struct nvc0_graph_chan { -+ struct nouveau_gpuobj *grctx; -+ struct nouveau_gpuobj *unk408004; // 0x418810 too -+ struct nouveau_gpuobj *unk40800c; // 0x419004 too -+ struct nouveau_gpuobj *unk418810; // 0x419848 too -+ struct nouveau_gpuobj *mmio; -+ int mmio_nr; -+}; -+ -+int nvc0_grctx_generate(struct nouveau_channel *); -+ -+#endif -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_grctx.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_grctx.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_grctx.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_grctx.c 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,2874 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+#include "nouveau_drv.h" -+#include "nouveau_mm.h" -+#include "nvc0_graph.h" -+ -+static void -+nv_icmd(struct drm_device *dev, u32 icmd, u32 data) -+{ -+ nv_wr32(dev, 0x400204, data); -+ nv_wr32(dev, 0x400200, icmd); -+ while (nv_rd32(dev, 0x400700) & 2) {} -+} -+ -+static void -+nv_mthd(struct drm_device *dev, u32 class, u32 mthd, u32 data) -+{ -+ nv_wr32(dev, 0x40448c, data); -+ nv_wr32(dev, 0x404488, 0x80000000 | (mthd << 14) | class); -+} -+ -+static void -+nvc0_grctx_generate_9097(struct drm_device *dev) -+{ -+ nv_mthd(dev, 0x9097, 0x0800, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0840, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0880, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x08c0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0900, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0940, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0980, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x09c0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0804, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0844, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0884, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x08c4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0904, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0944, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0984, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x09c4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0808, 0x00000400); -+ nv_mthd(dev, 0x9097, 0x0848, 0x00000400); -+ nv_mthd(dev, 0x9097, 0x0888, 0x00000400); -+ nv_mthd(dev, 0x9097, 0x08c8, 0x00000400); -+ nv_mthd(dev, 0x9097, 0x0908, 0x00000400); -+ nv_mthd(dev, 0x9097, 0x0948, 0x00000400); -+ nv_mthd(dev, 0x9097, 0x0988, 0x00000400); -+ nv_mthd(dev, 0x9097, 0x09c8, 0x00000400); -+ nv_mthd(dev, 0x9097, 0x080c, 0x00000300); -+ nv_mthd(dev, 0x9097, 0x084c, 0x00000300); -+ nv_mthd(dev, 0x9097, 0x088c, 0x00000300); -+ nv_mthd(dev, 0x9097, 0x08cc, 0x00000300); -+ nv_mthd(dev, 0x9097, 0x090c, 0x00000300); -+ nv_mthd(dev, 0x9097, 0x094c, 0x00000300); -+ nv_mthd(dev, 0x9097, 0x098c, 0x00000300); -+ nv_mthd(dev, 0x9097, 0x09cc, 0x00000300); -+ nv_mthd(dev, 0x9097, 0x0810, 0x000000cf); -+ nv_mthd(dev, 0x9097, 0x0850, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0890, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x08d0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0910, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0950, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0990, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x09d0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0814, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x0854, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x0894, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x08d4, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x0914, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x0954, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x0994, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x09d4, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x0818, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x0858, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x0898, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x08d8, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x0918, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x0958, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x0998, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x09d8, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x081c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x085c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x089c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x08dc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x091c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x095c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x099c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x09dc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0820, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0860, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x08a0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x08e0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0920, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0960, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x09a0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x09e0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2700, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2720, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2740, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2760, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2780, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x27a0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x27c0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x27e0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2704, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2724, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2744, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2764, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2784, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x27a4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x27c4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x27e4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2708, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2728, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2748, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2768, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2788, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x27a8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x27c8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x27e8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x270c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x272c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x274c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x276c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x278c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x27ac, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x27cc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x27ec, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2710, 0x00014000); -+ nv_mthd(dev, 0x9097, 0x2730, 0x00014000); -+ nv_mthd(dev, 0x9097, 0x2750, 0x00014000); -+ nv_mthd(dev, 0x9097, 0x2770, 0x00014000); -+ nv_mthd(dev, 0x9097, 0x2790, 0x00014000); -+ nv_mthd(dev, 0x9097, 0x27b0, 0x00014000); -+ nv_mthd(dev, 0x9097, 0x27d0, 0x00014000); -+ nv_mthd(dev, 0x9097, 0x27f0, 0x00014000); -+ nv_mthd(dev, 0x9097, 0x2714, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x2734, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x2754, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x2774, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x2794, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x27b4, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x27d4, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x27f4, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x1c00, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c10, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c20, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c30, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c40, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c50, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c60, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c70, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c80, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c90, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1ca0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cb0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cc0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cd0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1ce0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cf0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c04, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c14, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c24, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c34, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c44, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c54, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c64, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c74, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c84, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c94, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1ca4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cb4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cc4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cd4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1ce4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cf4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c08, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c18, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c28, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c38, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c48, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c58, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c68, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c78, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c88, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c98, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1ca8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cb8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cc8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cd8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1ce8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cf8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c0c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c1c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c2c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c3c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c4c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c5c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c6c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c7c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c8c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1c9c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cac, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cbc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1ccc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cdc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cec, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1cfc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d00, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d10, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d20, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d30, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d40, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d50, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d60, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d70, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d80, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d90, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1da0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1db0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1dc0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1dd0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1de0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1df0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d04, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d14, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d24, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d34, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d44, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d54, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d64, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d74, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d84, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d94, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1da4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1db4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1dc4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1dd4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1de4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1df4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d08, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d18, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d28, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d38, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d48, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d58, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d68, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d78, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d88, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d98, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1da8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1db8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1dc8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1dd8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1de8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1df8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d0c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d1c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d2c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d3c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d4c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d5c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d6c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d7c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d8c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1d9c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1dac, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1dbc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1dcc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1ddc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1dec, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1dfc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f00, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f08, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f10, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f18, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f20, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f28, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f30, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f38, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f40, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f48, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f50, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f58, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f60, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f68, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f70, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f78, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f04, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f0c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f14, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f1c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f24, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f2c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f34, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f3c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f44, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f4c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f54, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f5c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f64, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f6c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f74, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f7c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f80, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f88, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f90, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f98, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fa0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fa8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fb0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fb8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fc0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fc8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fd0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fd8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fe0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fe8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1ff0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1ff8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f84, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f8c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f94, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1f9c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fa4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fac, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fb4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fbc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fc4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fcc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fd4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fdc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fe4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1fec, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1ff4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1ffc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2200, 0x00000022); -+ nv_mthd(dev, 0x9097, 0x2210, 0x00000022); -+ nv_mthd(dev, 0x9097, 0x2220, 0x00000022); -+ nv_mthd(dev, 0x9097, 0x2230, 0x00000022); -+ nv_mthd(dev, 0x9097, 0x2240, 0x00000022); -+ nv_mthd(dev, 0x9097, 0x2000, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2040, 0x00000011); -+ nv_mthd(dev, 0x9097, 0x2080, 0x00000020); -+ nv_mthd(dev, 0x9097, 0x20c0, 0x00000030); -+ nv_mthd(dev, 0x9097, 0x2100, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x2140, 0x00000051); -+ nv_mthd(dev, 0x9097, 0x200c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x204c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x208c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x20cc, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x210c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x214c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x2010, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2050, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2090, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x20d0, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x2110, 0x00000003); -+ nv_mthd(dev, 0x9097, 0x2150, 0x00000004); -+ nv_mthd(dev, 0x9097, 0x0380, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x03a0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x03c0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x03e0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0384, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x03a4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x03c4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x03e4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0388, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x03a8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x03c8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x03e8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x038c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x03ac, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x03cc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x03ec, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0700, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0710, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0720, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0730, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0704, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0714, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0724, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0734, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0708, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0718, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0728, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0738, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2800, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2804, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2808, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x280c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2810, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2814, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2818, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x281c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2820, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2824, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2828, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x282c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2830, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2834, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2838, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x283c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2840, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2844, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2848, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x284c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2850, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2854, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2858, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x285c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2860, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2864, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2868, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x286c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2870, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2874, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2878, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x287c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2880, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2884, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2888, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x288c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2890, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2894, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2898, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x289c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28a0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28a4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28a8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28ac, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28b0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28b4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28b8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28bc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28c0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28c4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28c8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28cc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28d0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28d4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28d8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28dc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28e0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28e4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28e8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28ec, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28f0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28f4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28f8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x28fc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2900, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2904, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2908, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x290c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2910, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2914, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2918, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x291c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2920, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2924, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2928, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x292c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2930, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2934, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2938, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x293c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2940, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2944, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2948, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x294c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2950, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2954, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2958, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x295c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2960, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2964, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2968, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x296c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2970, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2974, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2978, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x297c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2980, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2984, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2988, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x298c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2990, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2994, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2998, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x299c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29a0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29a4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29a8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29ac, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29b0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29b4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29b8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29bc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29c0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29c4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29c8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29cc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29d0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29d4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29d8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29dc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29e0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29e4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29e8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29ec, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29f0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29f4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29f8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x29fc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a00, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a20, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a40, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a60, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a80, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0aa0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ac0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ae0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b00, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b20, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b40, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b60, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b80, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ba0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0bc0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0be0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a04, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a24, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a44, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a64, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a84, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0aa4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ac4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ae4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b04, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b24, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b44, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b64, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b84, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ba4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0bc4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0be4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a08, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a28, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a48, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a68, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a88, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0aa8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ac8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ae8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b08, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b28, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b48, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b68, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b88, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ba8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0bc8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0be8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a0c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a2c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a4c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a6c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a8c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0aac, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0acc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0aec, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b0c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b2c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b4c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b6c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b8c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0bac, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0bcc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0bec, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a10, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a30, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a50, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a70, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a90, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ab0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ad0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0af0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b10, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b30, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b50, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b70, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b90, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0bb0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0bd0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0bf0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a14, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a34, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a54, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a74, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0a94, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ab4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ad4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0af4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b14, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b34, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b54, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b74, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0b94, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0bb4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0bd4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0bf4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c00, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c10, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c20, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c30, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c40, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c50, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c60, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c70, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c80, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c90, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ca0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0cb0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0cc0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0cd0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ce0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0cf0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c04, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c14, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c24, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c34, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c44, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c54, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c64, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c74, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c84, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c94, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ca4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0cb4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0cc4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0cd4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ce4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0cf4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c08, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c18, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c28, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c38, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c48, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c58, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c68, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c78, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c88, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c98, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ca8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0cb8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0cc8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0cd8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ce8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0cf8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0c0c, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0c1c, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0c2c, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0c3c, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0c4c, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0c5c, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0c6c, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0c7c, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0c8c, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0c9c, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0cac, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0cbc, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0ccc, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0cdc, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0cec, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0cfc, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0d00, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d08, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d10, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d18, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d20, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d28, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d30, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d38, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d04, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d0c, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d14, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d1c, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d24, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d2c, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d34, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d3c, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e00, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0e10, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0e20, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0e30, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0e40, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0e50, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0e60, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0e70, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0e80, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0e90, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ea0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0eb0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ec0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ed0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ee0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ef0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0e04, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e14, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e24, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e34, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e44, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e54, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e64, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e74, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e84, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e94, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0ea4, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0eb4, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0ec4, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0ed4, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0ee4, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0ef4, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e08, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e18, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e28, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e38, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e48, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e58, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e68, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e78, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e88, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0e98, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0ea8, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0eb8, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0ec8, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0ed8, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0ee8, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0ef8, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d40, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0d48, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0d50, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0d58, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0d44, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0d4c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0d54, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0d5c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1e00, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e20, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e40, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e60, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e80, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1ea0, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1ec0, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1ee0, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e04, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e24, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e44, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e64, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e84, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1ea4, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1ec4, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1ee4, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e08, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1e28, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1e48, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1e68, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1e88, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1ea8, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1ec8, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1ee8, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1e0c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e2c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e4c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e6c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e8c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1eac, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1ecc, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1eec, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e10, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e30, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e50, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e70, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e90, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1eb0, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1ed0, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1ef0, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e14, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1e34, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1e54, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1e74, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1e94, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1eb4, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1ed4, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1ef4, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1e18, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e38, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e58, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e78, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1e98, 0x00000001); -+ 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); -+ nv_mthd(dev, 0x9097, 0x030c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1944, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1514, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0d68, 0x0000ffff); -+ nv_mthd(dev, 0x9097, 0x121c, 0x0fac6881); -+ nv_mthd(dev, 0x9097, 0x0fac, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1538, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x0fe0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0fe4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0fe8, 0x00000014); -+ nv_mthd(dev, 0x9097, 0x0fec, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x0ff0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x179c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1228, 0x00000400); -+ nv_mthd(dev, 0x9097, 0x122c, 0x00000300); -+ nv_mthd(dev, 0x9097, 0x1230, 0x00010001); -+ nv_mthd(dev, 0x9097, 0x07f8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x15b4, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x15cc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1534, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0fb0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x15d0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x153c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x16b4, 0x00000003); -+ nv_mthd(dev, 0x9097, 0x0fbc, 0x0000ffff); -+ nv_mthd(dev, 0x9097, 0x0fc0, 0x0000ffff); -+ nv_mthd(dev, 0x9097, 0x0fc4, 0x0000ffff); -+ nv_mthd(dev, 0x9097, 0x0fc8, 0x0000ffff); -+ nv_mthd(dev, 0x9097, 0x0df8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0dfc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1948, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1970, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x161c, 0x000009f0); -+ nv_mthd(dev, 0x9097, 0x0dcc, 0x00000010); -+ nv_mthd(dev, 0x9097, 0x163c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x15e4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1160, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x1164, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x1168, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x116c, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x1170, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x1174, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x1178, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x117c, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x1180, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x1184, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x1188, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x118c, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x1190, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x1194, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x1198, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x119c, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11a0, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11a4, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11a8, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11ac, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11b0, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11b4, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11b8, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11bc, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11c0, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11c4, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11c8, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11cc, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11d0, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11d4, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11d8, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x11dc, 0x25e00040); -+ nv_mthd(dev, 0x9097, 0x1880, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1884, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1888, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x188c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1890, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1894, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1898, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x189c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18a0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18a4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18a8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18ac, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18b0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18b4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18b8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18bc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18c0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18c4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18c8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18cc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18d0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18d4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18d8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18dc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18e0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18e4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18e8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18ec, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18f0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18f4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18f8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x18fc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0f84, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0f88, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x17c8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x17cc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x17d0, 0x000000ff); -+ nv_mthd(dev, 0x9097, 0x17d4, 0xffffffff); -+ nv_mthd(dev, 0x9097, 0x17d8, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x17dc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x15f4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x15f8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1434, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1438, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0d74, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0dec, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x13a4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1318, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1644, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0748, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0de8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1648, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x12a4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1120, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1124, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1128, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x112c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1118, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x164c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1658, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1910, 0x00000290); -+ nv_mthd(dev, 0x9097, 0x1518, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x165c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1520, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1604, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1570, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x13b0, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x13b4, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x020c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1670, 0x30201000); -+ nv_mthd(dev, 0x9097, 0x1674, 0x70605040); -+ nv_mthd(dev, 0x9097, 0x1678, 0xb8a89888); -+ nv_mthd(dev, 0x9097, 0x167c, 0xf8e8d8c8); -+ nv_mthd(dev, 0x9097, 0x166c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1680, 0x00ffff00); -+ nv_mthd(dev, 0x9097, 0x12d0, 0x00000003); -+ nv_mthd(dev, 0x9097, 0x12d4, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1684, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1688, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0dac, 0x00001b02); -+ nv_mthd(dev, 0x9097, 0x0db0, 0x00001b02); -+ nv_mthd(dev, 0x9097, 0x0db4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x168c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x15bc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x156c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x187c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1110, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x0dc0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0dc4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0dc8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1234, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1690, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x12ac, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x02c4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0790, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0794, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0798, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x079c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x07a0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x077c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1000, 0x00000010); -+ nv_mthd(dev, 0x9097, 0x10fc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1290, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0218, 0x00000010); -+ nv_mthd(dev, 0x9097, 0x12d8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x12dc, 0x00000010); -+ nv_mthd(dev, 0x9097, 0x0d94, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x155c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1560, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1564, 0x00001fff); -+ nv_mthd(dev, 0x9097, 0x1574, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1578, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x157c, 0x003fffff); -+ nv_mthd(dev, 0x9097, 0x1354, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1664, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1610, 0x00000012); -+ nv_mthd(dev, 0x9097, 0x1608, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x160c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x162c, 0x00000003); -+ nv_mthd(dev, 0x9097, 0x0210, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0320, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0324, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0328, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x032c, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0330, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0334, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0338, 0x3f800000); -+ nv_mthd(dev, 0x9097, 0x0750, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0760, 0x39291909); -+ nv_mthd(dev, 0x9097, 0x0764, 0x79695949); -+ nv_mthd(dev, 0x9097, 0x0768, 0xb9a99989); -+ nv_mthd(dev, 0x9097, 0x076c, 0xf9e9d9c9); -+ nv_mthd(dev, 0x9097, 0x0770, 0x30201000); -+ nv_mthd(dev, 0x9097, 0x0774, 0x70605040); -+ nv_mthd(dev, 0x9097, 0x0778, 0x00009080); -+ nv_mthd(dev, 0x9097, 0x0780, 0x39291909); -+ nv_mthd(dev, 0x9097, 0x0784, 0x79695949); -+ nv_mthd(dev, 0x9097, 0x0788, 0xb9a99989); -+ nv_mthd(dev, 0x9097, 0x078c, 0xf9e9d9c9); -+ nv_mthd(dev, 0x9097, 0x07d0, 0x30201000); -+ nv_mthd(dev, 0x9097, 0x07d4, 0x70605040); -+ nv_mthd(dev, 0x9097, 0x07d8, 0x00009080); -+ nv_mthd(dev, 0x9097, 0x037c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x0740, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0744, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x2600, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1918, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x191c, 0x00000900); -+ nv_mthd(dev, 0x9097, 0x1920, 0x00000405); -+ nv_mthd(dev, 0x9097, 0x1308, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1924, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x13ac, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x192c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x193c, 0x00002c1c); -+ nv_mthd(dev, 0x9097, 0x0d7c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0f8c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x02c0, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1510, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1940, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ff4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0ff8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x194c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1950, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1968, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1590, 0x0000003f); -+ nv_mthd(dev, 0x9097, 0x07e8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x07ec, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x07f0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x07f4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x196c, 0x00000011); -+ nv_mthd(dev, 0x9097, 0x197c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0fcc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0fd0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x02d8, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x1980, 0x00000080); -+ nv_mthd(dev, 0x9097, 0x1504, 0x00000080); -+ nv_mthd(dev, 0x9097, 0x1984, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0300, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x13a8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x12ec, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1310, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1314, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1380, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1384, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1388, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x138c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1390, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1394, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x139c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1398, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1594, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1598, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x159c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x15a0, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x15a4, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x0f54, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0f58, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0f5c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x19bc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0f9c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0fa0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x12cc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x12e8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x130c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1360, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1364, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1368, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x136c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1370, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1374, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1378, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x137c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x133c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1340, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1344, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1348, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x134c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1350, 0x00000002); -+ nv_mthd(dev, 0x9097, 0x1358, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x12e4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x131c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1320, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1324, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1328, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x19c0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1140, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x19c4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x19c8, 0x00001500); -+ nv_mthd(dev, 0x9097, 0x135c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0f90, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x19e0, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x19e4, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x19e8, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x19ec, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x19f0, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x19f4, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x19f8, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x19fc, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x19cc, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x15b8, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1a00, 0x00001111); -+ nv_mthd(dev, 0x9097, 0x1a04, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1a08, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1a0c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1a10, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1a14, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1a18, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1a1c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0d6c, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x0d70, 0xffff0000); -+ nv_mthd(dev, 0x9097, 0x10f8, 0x00001010); -+ nv_mthd(dev, 0x9097, 0x0d80, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0d84, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0d88, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0d8c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0d90, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0da0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1508, 0x80000000); -+ nv_mthd(dev, 0x9097, 0x150c, 0x40000000); -+ nv_mthd(dev, 0x9097, 0x1668, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0318, 0x00000008); -+ nv_mthd(dev, 0x9097, 0x031c, 0x00000008); -+ nv_mthd(dev, 0x9097, 0x0d9c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x07dc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x074c, 0x00000055); -+ nv_mthd(dev, 0x9097, 0x1420, 0x00000003); -+ nv_mthd(dev, 0x9097, 0x17bc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x17c0, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x17c4, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1008, 0x00000008); -+ nv_mthd(dev, 0x9097, 0x100c, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x1010, 0x0000012c); -+ nv_mthd(dev, 0x9097, 0x0d60, 0x00000040); -+ nv_mthd(dev, 0x9097, 0x075c, 0x00000003); -+ nv_mthd(dev, 0x9097, 0x1018, 0x00000020); -+ nv_mthd(dev, 0x9097, 0x101c, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1020, 0x00000020); -+ nv_mthd(dev, 0x9097, 0x1024, 0x00000001); -+ nv_mthd(dev, 0x9097, 0x1444, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x1448, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x144c, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0360, 0x20164010); -+ nv_mthd(dev, 0x9097, 0x0364, 0x00000020); -+ nv_mthd(dev, 0x9097, 0x0368, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0de4, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0204, 0x00000006); -+ nv_mthd(dev, 0x9097, 0x0208, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x02cc, 0x003fffff); -+ nv_mthd(dev, 0x9097, 0x02d0, 0x00000c48); -+ nv_mthd(dev, 0x9097, 0x1220, 0x00000005); -+ nv_mthd(dev, 0x9097, 0x0fdc, 0x00000000); -+ nv_mthd(dev, 0x9097, 0x0f98, 0x00300008); -+ nv_mthd(dev, 0x9097, 0x1284, 0x04000080); -+ nv_mthd(dev, 0x9097, 0x1450, 0x00300008); -+ nv_mthd(dev, 0x9097, 0x1454, 0x04000080); -+ nv_mthd(dev, 0x9097, 0x0214, 0x00000000); -+ /* in trace, right after 0x90c0, not here */ -+ nv_mthd(dev, 0x9097, 0x3410, 0x80002006); -+} -+ -+static void -+nvc0_grctx_generate_902d(struct drm_device *dev) -+{ -+ nv_mthd(dev, 0x902d, 0x0200, 0x000000cf); -+ nv_mthd(dev, 0x902d, 0x0204, 0x00000001); -+ nv_mthd(dev, 0x902d, 0x0208, 0x00000020); -+ nv_mthd(dev, 0x902d, 0x020c, 0x00000001); -+ nv_mthd(dev, 0x902d, 0x0210, 0x00000000); -+ nv_mthd(dev, 0x902d, 0x0214, 0x00000080); -+ nv_mthd(dev, 0x902d, 0x0218, 0x00000100); -+ nv_mthd(dev, 0x902d, 0x021c, 0x00000100); -+ nv_mthd(dev, 0x902d, 0x0220, 0x00000000); -+ nv_mthd(dev, 0x902d, 0x0224, 0x00000000); -+ nv_mthd(dev, 0x902d, 0x0230, 0x000000cf); -+ nv_mthd(dev, 0x902d, 0x0234, 0x00000001); -+ nv_mthd(dev, 0x902d, 0x0238, 0x00000020); -+ nv_mthd(dev, 0x902d, 0x023c, 0x00000001); -+ nv_mthd(dev, 0x902d, 0x0244, 0x00000080); -+ nv_mthd(dev, 0x902d, 0x0248, 0x00000100); -+ nv_mthd(dev, 0x902d, 0x024c, 0x00000100); -+} -+ -+static void -+nvc0_grctx_generate_9039(struct drm_device *dev) -+{ -+ nv_mthd(dev, 0x9039, 0x030c, 0x00000000); -+ nv_mthd(dev, 0x9039, 0x0310, 0x00000000); -+ nv_mthd(dev, 0x9039, 0x0314, 0x00000000); -+ nv_mthd(dev, 0x9039, 0x0320, 0x00000000); -+ nv_mthd(dev, 0x9039, 0x0238, 0x00000000); -+ nv_mthd(dev, 0x9039, 0x023c, 0x00000000); -+ nv_mthd(dev, 0x9039, 0x0318, 0x00000000); -+ nv_mthd(dev, 0x9039, 0x031c, 0x00000000); -+} -+ -+static void -+nvc0_grctx_generate_90c0(struct drm_device *dev) -+{ -+ nv_mthd(dev, 0x90c0, 0x270c, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x272c, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x274c, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x276c, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x278c, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x27ac, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x27cc, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x27ec, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x030c, 0x00000001); -+ nv_mthd(dev, 0x90c0, 0x1944, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x0758, 0x00000100); -+ nv_mthd(dev, 0x90c0, 0x02c4, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x0790, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x0794, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x0798, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x079c, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x07a0, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x077c, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x0204, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x0208, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x020c, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x0214, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x024c, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x0d94, 0x00000001); -+ nv_mthd(dev, 0x90c0, 0x1608, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x160c, 0x00000000); -+ nv_mthd(dev, 0x90c0, 0x1664, 0x00000000); -+} -+ -+static void -+nvc0_grctx_generate_dispatch(struct drm_device *dev) -+{ -+ int i; -+ -+ nv_wr32(dev, 0x404004, 0x00000000); -+ nv_wr32(dev, 0x404008, 0x00000000); -+ nv_wr32(dev, 0x40400c, 0x00000000); -+ nv_wr32(dev, 0x404010, 0x00000000); -+ nv_wr32(dev, 0x404014, 0x00000000); -+ nv_wr32(dev, 0x404018, 0x00000000); -+ nv_wr32(dev, 0x40401c, 0x00000000); -+ nv_wr32(dev, 0x404020, 0x00000000); -+ nv_wr32(dev, 0x404024, 0x00000000); -+ nv_wr32(dev, 0x404028, 0x00000000); -+ nv_wr32(dev, 0x40402c, 0x00000000); -+ nv_wr32(dev, 0x404044, 0x00000000); -+ nv_wr32(dev, 0x404094, 0x00000000); -+ nv_wr32(dev, 0x404098, 0x00000000); -+ nv_wr32(dev, 0x40409c, 0x00000000); -+ nv_wr32(dev, 0x4040a0, 0x00000000); -+ nv_wr32(dev, 0x4040a4, 0x00000000); -+ nv_wr32(dev, 0x4040a8, 0x00000000); -+ nv_wr32(dev, 0x4040ac, 0x00000000); -+ nv_wr32(dev, 0x4040b0, 0x00000000); -+ nv_wr32(dev, 0x4040b4, 0x00000000); -+ nv_wr32(dev, 0x4040b8, 0x00000000); -+ nv_wr32(dev, 0x4040bc, 0x00000000); -+ nv_wr32(dev, 0x4040c0, 0x00000000); -+ nv_wr32(dev, 0x4040c4, 0x00000000); -+ nv_wr32(dev, 0x4040c8, 0xf0000087); -+ nv_wr32(dev, 0x4040d4, 0x00000000); -+ nv_wr32(dev, 0x4040d8, 0x00000000); -+ nv_wr32(dev, 0x4040dc, 0x00000000); -+ nv_wr32(dev, 0x4040e0, 0x00000000); -+ nv_wr32(dev, 0x4040e4, 0x00000000); -+ nv_wr32(dev, 0x4040e8, 0x00001000); -+ nv_wr32(dev, 0x4040f8, 0x00000000); -+ nv_wr32(dev, 0x404130, 0x00000000); -+ nv_wr32(dev, 0x404134, 0x00000000); -+ nv_wr32(dev, 0x404138, 0x20000040); -+ nv_wr32(dev, 0x404150, 0x0000002e); -+ nv_wr32(dev, 0x404154, 0x00000400); -+ nv_wr32(dev, 0x404158, 0x00000200); -+ nv_wr32(dev, 0x404164, 0x00000055); -+ nv_wr32(dev, 0x404168, 0x00000000); -+ nv_wr32(dev, 0x404174, 0x00000000); -+ nv_wr32(dev, 0x404178, 0x00000000); -+ nv_wr32(dev, 0x40417c, 0x00000000); -+ for (i = 0; i < 8; i++) -+ nv_wr32(dev, 0x404200 + (i * 4), 0x00000000); /* subc */ -+} -+ -+static void -+nvc0_grctx_generate_macro(struct drm_device *dev) -+{ -+ nv_wr32(dev, 0x404404, 0x00000000); -+ nv_wr32(dev, 0x404408, 0x00000000); -+ nv_wr32(dev, 0x40440c, 0x00000000); -+ nv_wr32(dev, 0x404410, 0x00000000); -+ nv_wr32(dev, 0x404414, 0x00000000); -+ nv_wr32(dev, 0x404418, 0x00000000); -+ nv_wr32(dev, 0x40441c, 0x00000000); -+ nv_wr32(dev, 0x404420, 0x00000000); -+ nv_wr32(dev, 0x404424, 0x00000000); -+ nv_wr32(dev, 0x404428, 0x00000000); -+ nv_wr32(dev, 0x40442c, 0x00000000); -+ nv_wr32(dev, 0x404430, 0x00000000); -+ nv_wr32(dev, 0x404434, 0x00000000); -+ nv_wr32(dev, 0x404438, 0x00000000); -+ nv_wr32(dev, 0x404460, 0x00000000); -+ nv_wr32(dev, 0x404464, 0x00000000); -+ nv_wr32(dev, 0x404468, 0x00ffffff); -+ nv_wr32(dev, 0x40446c, 0x00000000); -+ nv_wr32(dev, 0x404480, 0x00000001); -+ nv_wr32(dev, 0x404498, 0x00000001); -+} -+ -+static void -+nvc0_grctx_generate_m2mf(struct drm_device *dev) -+{ -+ nv_wr32(dev, 0x404604, 0x00000015); -+ nv_wr32(dev, 0x404608, 0x00000000); -+ nv_wr32(dev, 0x40460c, 0x00002e00); -+ nv_wr32(dev, 0x404610, 0x00000100); -+ nv_wr32(dev, 0x404618, 0x00000000); -+ nv_wr32(dev, 0x40461c, 0x00000000); -+ nv_wr32(dev, 0x404620, 0x00000000); -+ nv_wr32(dev, 0x404624, 0x00000000); -+ nv_wr32(dev, 0x404628, 0x00000000); -+ nv_wr32(dev, 0x40462c, 0x00000000); -+ nv_wr32(dev, 0x404630, 0x00000000); -+ nv_wr32(dev, 0x404634, 0x00000000); -+ nv_wr32(dev, 0x404638, 0x00000004); -+ nv_wr32(dev, 0x40463c, 0x00000000); -+ nv_wr32(dev, 0x404640, 0x00000000); -+ nv_wr32(dev, 0x404644, 0x00000000); -+ nv_wr32(dev, 0x404648, 0x00000000); -+ nv_wr32(dev, 0x40464c, 0x00000000); -+ nv_wr32(dev, 0x404650, 0x00000000); -+ nv_wr32(dev, 0x404654, 0x00000000); -+ nv_wr32(dev, 0x404658, 0x00000000); -+ nv_wr32(dev, 0x40465c, 0x007f0100); -+ nv_wr32(dev, 0x404660, 0x00000000); -+ nv_wr32(dev, 0x404664, 0x00000000); -+ nv_wr32(dev, 0x404668, 0x00000000); -+ nv_wr32(dev, 0x40466c, 0x00000000); -+ nv_wr32(dev, 0x404670, 0x00000000); -+ nv_wr32(dev, 0x404674, 0x00000000); -+ nv_wr32(dev, 0x404678, 0x00000000); -+ nv_wr32(dev, 0x40467c, 0x00000002); -+ nv_wr32(dev, 0x404680, 0x00000000); -+ nv_wr32(dev, 0x404684, 0x00000000); -+ nv_wr32(dev, 0x404688, 0x00000000); -+ nv_wr32(dev, 0x40468c, 0x00000000); -+ nv_wr32(dev, 0x404690, 0x00000000); -+ nv_wr32(dev, 0x404694, 0x00000000); -+ nv_wr32(dev, 0x404698, 0x00000000); -+ nv_wr32(dev, 0x40469c, 0x00000000); -+ nv_wr32(dev, 0x4046a0, 0x007f0080); -+ nv_wr32(dev, 0x4046a4, 0x00000000); -+ nv_wr32(dev, 0x4046a8, 0x00000000); -+ nv_wr32(dev, 0x4046ac, 0x00000000); -+ nv_wr32(dev, 0x4046b0, 0x00000000); -+ nv_wr32(dev, 0x4046b4, 0x00000000); -+ nv_wr32(dev, 0x4046b8, 0x00000000); -+ nv_wr32(dev, 0x4046bc, 0x00000000); -+ nv_wr32(dev, 0x4046c0, 0x00000000); -+ nv_wr32(dev, 0x4046c4, 0x00000000); -+ nv_wr32(dev, 0x4046c8, 0x00000000); -+ nv_wr32(dev, 0x4046cc, 0x00000000); -+ nv_wr32(dev, 0x4046d0, 0x00000000); -+ nv_wr32(dev, 0x4046d4, 0x00000000); -+ nv_wr32(dev, 0x4046d8, 0x00000000); -+ nv_wr32(dev, 0x4046dc, 0x00000000); -+ nv_wr32(dev, 0x4046e0, 0x00000000); -+ nv_wr32(dev, 0x4046e4, 0x00000000); -+ nv_wr32(dev, 0x4046e8, 0x00000000); -+ nv_wr32(dev, 0x4046f0, 0x00000000); -+ nv_wr32(dev, 0x4046f4, 0x00000000); -+} -+ -+static void -+nvc0_grctx_generate_unk47xx(struct drm_device *dev) -+{ -+ nv_wr32(dev, 0x404700, 0x00000000); -+ nv_wr32(dev, 0x404704, 0x00000000); -+ nv_wr32(dev, 0x404708, 0x00000000); -+ nv_wr32(dev, 0x40470c, 0x00000000); -+ nv_wr32(dev, 0x404710, 0x00000000); -+ nv_wr32(dev, 0x404714, 0x00000000); -+ nv_wr32(dev, 0x404718, 0x00000000); -+ nv_wr32(dev, 0x40471c, 0x00000000); -+ nv_wr32(dev, 0x404720, 0x00000000); -+ nv_wr32(dev, 0x404724, 0x00000000); -+ nv_wr32(dev, 0x404728, 0x00000000); -+ nv_wr32(dev, 0x40472c, 0x00000000); -+ nv_wr32(dev, 0x404730, 0x00000000); -+ nv_wr32(dev, 0x404734, 0x00000100); -+ nv_wr32(dev, 0x404738, 0x00000000); -+ nv_wr32(dev, 0x40473c, 0x00000000); -+ nv_wr32(dev, 0x404740, 0x00000000); -+ nv_wr32(dev, 0x404744, 0x00000000); -+ nv_wr32(dev, 0x404748, 0x00000000); -+ nv_wr32(dev, 0x40474c, 0x00000000); -+ nv_wr32(dev, 0x404750, 0x00000000); -+ nv_wr32(dev, 0x404754, 0x00000000); -+} -+ -+static void -+nvc0_grctx_generate_shaders(struct drm_device *dev) -+{ -+ nv_wr32(dev, 0x405800, 0x078000bf); -+ nv_wr32(dev, 0x405830, 0x02180000); -+ nv_wr32(dev, 0x405834, 0x00000000); -+ nv_wr32(dev, 0x405838, 0x00000000); -+ nv_wr32(dev, 0x405854, 0x00000000); -+ nv_wr32(dev, 0x405870, 0x00000001); -+ nv_wr32(dev, 0x405874, 0x00000001); -+ nv_wr32(dev, 0x405878, 0x00000001); -+ nv_wr32(dev, 0x40587c, 0x00000001); -+ nv_wr32(dev, 0x405a00, 0x00000000); -+ nv_wr32(dev, 0x405a04, 0x00000000); -+ nv_wr32(dev, 0x405a18, 0x00000000); -+} -+ -+static void -+nvc0_grctx_generate_unk60xx(struct drm_device *dev) -+{ -+ nv_wr32(dev, 0x406020, 0x000103c1); -+ nv_wr32(dev, 0x406028, 0x00000001); -+ nv_wr32(dev, 0x40602c, 0x00000001); -+ nv_wr32(dev, 0x406030, 0x00000001); -+ nv_wr32(dev, 0x406034, 0x00000001); -+} -+ -+static void -+nvc0_grctx_generate_unk64xx(struct drm_device *dev) -+{ -+ nv_wr32(dev, 0x4064a8, 0x00000000); -+ nv_wr32(dev, 0x4064ac, 0x00003fff); -+ nv_wr32(dev, 0x4064b4, 0x00000000); -+ nv_wr32(dev, 0x4064b8, 0x00000000); -+} -+ -+static void -+nvc0_grctx_generate_tpbus(struct drm_device *dev) -+{ -+ nv_wr32(dev, 0x407804, 0x00000023); -+ nv_wr32(dev, 0x40780c, 0x0a418820); -+ nv_wr32(dev, 0x407810, 0x062080e6); -+ nv_wr32(dev, 0x407814, 0x020398a4); -+ nv_wr32(dev, 0x407818, 0x0e629062); -+ nv_wr32(dev, 0x40781c, 0x0a418820); -+ nv_wr32(dev, 0x407820, 0x000000e6); -+ nv_wr32(dev, 0x4078bc, 0x00000103); -+} -+ -+static void -+nvc0_grctx_generate_ccache(struct drm_device *dev) -+{ -+ nv_wr32(dev, 0x408000, 0x00000000); -+ nv_wr32(dev, 0x408004, 0x00000000); -+ nv_wr32(dev, 0x408008, 0x00000018); -+ nv_wr32(dev, 0x40800c, 0x00000000); -+ nv_wr32(dev, 0x408010, 0x00000000); -+ nv_wr32(dev, 0x408014, 0x00000069); -+ nv_wr32(dev, 0x408018, 0xe100e100); -+ nv_wr32(dev, 0x408064, 0x00000000); -+} -+ -+static void -+nvc0_grctx_generate_rop(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ // 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, 0x408908, 0x00c80929); -+ nv_wr32(dev, 0x40890c, 0x00000000); -+ nv_wr32(dev, 0x408980, 0x0000011d); -+} -+ -+static void -+nvc0_grctx_generate_gpc(struct drm_device *dev) -+{ -+ int i; -+ -+ // GPC_BROADCAST -+ nv_wr32(dev, 0x418380, 0x00000016); -+ nv_wr32(dev, 0x418400, 0x38004e00); -+ nv_wr32(dev, 0x418404, 0x71e0ffff); -+ nv_wr32(dev, 0x418408, 0x00000000); -+ nv_wr32(dev, 0x41840c, 0x00001008); -+ nv_wr32(dev, 0x418410, 0x0fff0fff); -+ nv_wr32(dev, 0x418414, 0x00200fff); -+ nv_wr32(dev, 0x418450, 0x00000000); -+ nv_wr32(dev, 0x418454, 0x00000000); -+ nv_wr32(dev, 0x418458, 0x00000000); -+ nv_wr32(dev, 0x41845c, 0x00000000); -+ nv_wr32(dev, 0x418460, 0x00000000); -+ nv_wr32(dev, 0x418464, 0x00000000); -+ nv_wr32(dev, 0x418468, 0x00000001); -+ nv_wr32(dev, 0x41846c, 0x00000000); -+ nv_wr32(dev, 0x418470, 0x00000000); -+ nv_wr32(dev, 0x418600, 0x0000001f); -+ nv_wr32(dev, 0x418684, 0x0000000f); -+ nv_wr32(dev, 0x418700, 0x00000002); -+ nv_wr32(dev, 0x418704, 0x00000080); -+ nv_wr32(dev, 0x418708, 0x00000000); -+ nv_wr32(dev, 0x41870c, 0x07c80000); -+ nv_wr32(dev, 0x418710, 0x00000000); -+ nv_wr32(dev, 0x418800, 0x0006860a); -+ nv_wr32(dev, 0x418808, 0x00000000); -+ nv_wr32(dev, 0x41880c, 0x00000000); -+ nv_wr32(dev, 0x418810, 0x00000000); -+ nv_wr32(dev, 0x418828, 0x00008442); -+ nv_wr32(dev, 0x418830, 0x00000001); -+ nv_wr32(dev, 0x4188d8, 0x00000008); -+ nv_wr32(dev, 0x4188e0, 0x01000000); -+ nv_wr32(dev, 0x4188e8, 0x00000000); -+ nv_wr32(dev, 0x4188ec, 0x00000000); -+ nv_wr32(dev, 0x4188f0, 0x00000000); -+ nv_wr32(dev, 0x4188f4, 0x00000000); -+ nv_wr32(dev, 0x4188f8, 0x00000000); -+ nv_wr32(dev, 0x4188fc, 0x00100000); -+ nv_wr32(dev, 0x41891c, 0x00ff00ff); -+ nv_wr32(dev, 0x418924, 0x00000000); -+ nv_wr32(dev, 0x418928, 0x00ffff00); -+ nv_wr32(dev, 0x41892c, 0x0000ff00); -+ for (i = 0; i < 8; i++) { -+ nv_wr32(dev, 0x418a00 + (i * 0x20), 0x00000000); -+ nv_wr32(dev, 0x418a04 + (i * 0x20), 0x00000000); -+ nv_wr32(dev, 0x418a08 + (i * 0x20), 0x00000000); -+ nv_wr32(dev, 0x418a0c + (i * 0x20), 0x00010000); -+ nv_wr32(dev, 0x418a10 + (i * 0x20), 0x00000000); -+ nv_wr32(dev, 0x418a14 + (i * 0x20), 0x00000000); -+ nv_wr32(dev, 0x418a18 + (i * 0x20), 0x00000000); -+ } -+ nv_wr32(dev, 0x418b00, 0x00000000); -+ nv_wr32(dev, 0x418b08, 0x0a418820); -+ nv_wr32(dev, 0x418b0c, 0x062080e6); -+ nv_wr32(dev, 0x418b10, 0x020398a4); -+ nv_wr32(dev, 0x418b14, 0x0e629062); -+ nv_wr32(dev, 0x418b18, 0x0a418820); -+ nv_wr32(dev, 0x418b1c, 0x000000e6); -+ nv_wr32(dev, 0x418bb8, 0x00000103); -+ nv_wr32(dev, 0x418c08, 0x00000001); -+ nv_wr32(dev, 0x418c10, 0x00000000); -+ nv_wr32(dev, 0x418c14, 0x00000000); -+ nv_wr32(dev, 0x418c18, 0x00000000); -+ nv_wr32(dev, 0x418c1c, 0x00000000); -+ nv_wr32(dev, 0x418c20, 0x00000000); -+ nv_wr32(dev, 0x418c24, 0x00000000); -+ nv_wr32(dev, 0x418c28, 0x00000000); -+ nv_wr32(dev, 0x418c2c, 0x00000000); -+ nv_wr32(dev, 0x418c80, 0x20200004); -+ nv_wr32(dev, 0x418c8c, 0x00000001); -+ nv_wr32(dev, 0x419000, 0x00000780); -+ nv_wr32(dev, 0x419004, 0x00000000); -+ nv_wr32(dev, 0x419008, 0x00000000); -+ nv_wr32(dev, 0x419014, 0x00000004); -+} -+ -+static void -+nvc0_grctx_generate_tp(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ // GPC_BROADCAST.TP_BROADCAST -+ nv_wr32(dev, 0x419848, 0x00000000); -+ nv_wr32(dev, 0x419864, 0x0000012a); -+ nv_wr32(dev, 0x419888, 0x00000000); -+ nv_wr32(dev, 0x419a00, 0x000001f0); -+ nv_wr32(dev, 0x419a04, 0x00000001); -+ nv_wr32(dev, 0x419a08, 0x00000023); -+ nv_wr32(dev, 0x419a0c, 0x00020000); -+ nv_wr32(dev, 0x419a10, 0x00000000); -+ 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 -+ nv_wr32(dev, 0x419b00, 0x0a418820); -+ nv_wr32(dev, 0x419b04, 0x062080e6); -+ nv_wr32(dev, 0x419b08, 0x020398a4); -+ nv_wr32(dev, 0x419b0c, 0x0e629062); -+ nv_wr32(dev, 0x419b10, 0x0a418820); -+ nv_wr32(dev, 0x419b14, 0x000000e6); -+ nv_wr32(dev, 0x419bd0, 0x00900103); -+ nv_wr32(dev, 0x419be0, 0x00000001); -+ 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, 0x419ce8, 0x00000000); -+ nv_wr32(dev, 0x419cf4, 0x00000183); -+ nv_wr32(dev, 0x419d20, 0x02180000); -+ nv_wr32(dev, 0x419d24, 0x00001fff); -+ nv_wr32(dev, 0x419e04, 0x00000000); -+ nv_wr32(dev, 0x419e08, 0x00000000); -+ nv_wr32(dev, 0x419e0c, 0x00000000); -+ nv_wr32(dev, 0x419e10, 0x00000002); -+ nv_wr32(dev, 0x419e44, 0x001beff2); -+ nv_wr32(dev, 0x419e48, 0x00000000); -+ nv_wr32(dev, 0x419e4c, 0x0000000f); -+ nv_wr32(dev, 0x419e50, 0x00000000); -+ nv_wr32(dev, 0x419e54, 0x00000000); -+ nv_wr32(dev, 0x419e58, 0x00000000); -+ nv_wr32(dev, 0x419e5c, 0x00000000); -+ nv_wr32(dev, 0x419e60, 0x00000000); -+ nv_wr32(dev, 0x419e64, 0x00000000); -+ nv_wr32(dev, 0x419e68, 0x00000000); -+ nv_wr32(dev, 0x419e6c, 0x00000000); -+ nv_wr32(dev, 0x419e70, 0x00000000); -+ nv_wr32(dev, 0x419e74, 0x00000000); -+ nv_wr32(dev, 0x419e78, 0x00000000); -+ nv_wr32(dev, 0x419e7c, 0x00000000); -+ nv_wr32(dev, 0x419e80, 0x00000000); -+ nv_wr32(dev, 0x419e84, 0x00000000); -+ nv_wr32(dev, 0x419e88, 0x00000000); -+ nv_wr32(dev, 0x419e8c, 0x00000000); -+ nv_wr32(dev, 0x419e90, 0x00000000); -+ nv_wr32(dev, 0x419e98, 0x00000000); -+ if (dev_priv->chipset != 0xc0) -+ nv_wr32(dev, 0x419ee0, 0x00011110); -+ nv_wr32(dev, 0x419f50, 0x00000000); -+ nv_wr32(dev, 0x419f54, 0x00000000); -+ if (dev_priv->chipset != 0xc0) -+ nv_wr32(dev, 0x419f58, 0x00000000); -+} -+ -+int -+nvc0_grctx_generate(struct nouveau_channel *chan) -+{ -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; -+ struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; -+ struct nvc0_graph_chan *grch = chan->pgraph_ctx; -+ struct drm_device *dev = chan->dev; -+ int i, gpc, tp, id; -+ u32 r000260, tmp; -+ -+ r000260 = nv_rd32(dev, 0x000260); -+ nv_wr32(dev, 0x000260, r000260 & ~1); -+ nv_wr32(dev, 0x400208, 0x00000000); -+ -+ nvc0_grctx_generate_dispatch(dev); -+ nvc0_grctx_generate_macro(dev); -+ nvc0_grctx_generate_m2mf(dev); -+ nvc0_grctx_generate_unk47xx(dev); -+ nvc0_grctx_generate_shaders(dev); -+ nvc0_grctx_generate_unk60xx(dev); -+ nvc0_grctx_generate_unk64xx(dev); -+ nvc0_grctx_generate_tpbus(dev); -+ nvc0_grctx_generate_ccache(dev); -+ nvc0_grctx_generate_rop(dev); -+ nvc0_grctx_generate_gpc(dev); -+ nvc0_grctx_generate_tp(dev); -+ -+ nv_wr32(dev, 0x404154, 0x00000000); -+ -+ /* fuc "mmio list" writes */ -+ for (i = 0; i < grch->mmio_nr * 8; i += 8) { -+ u32 reg = nv_ro32(grch->mmio, i + 0); -+ nv_wr32(dev, reg, nv_ro32(grch->mmio, i + 4)); -+ } -+ -+ for (tp = 0, id = 0; tp < 4; tp++) { -+ for (gpc = 0; gpc < priv->gpc_nr; gpc++) { -+ if (tp <= priv->tp_nr[gpc]) { -+ nv_wr32(dev, TP_UNIT(gpc, tp, 0x698), id); -+ nv_wr32(dev, TP_UNIT(gpc, tp, 0x4e8), id); -+ nv_wr32(dev, GPC_UNIT(gpc, 0x0c10 + tp * 4), id); -+ nv_wr32(dev, TP_UNIT(gpc, tp, 0x088), id); -+ id++; -+ } -+ -+ nv_wr32(dev, GPC_UNIT(gpc, 0x0c08), priv->tp_nr[gpc]); -+ nv_wr32(dev, GPC_UNIT(gpc, 0x0c8c), priv->tp_nr[gpc]); -+ } -+ } -+ -+ tmp = 0; -+ for (i = 0; i < priv->gpc_nr; i++) -+ tmp |= priv->tp_nr[i] << (i * 4); -+ nv_wr32(dev, 0x406028, tmp); -+ nv_wr32(dev, 0x405870, tmp); -+ -+ nv_wr32(dev, 0x40602c, 0x00000000); -+ nv_wr32(dev, 0x405874, 0x00000000); -+ nv_wr32(dev, 0x406030, 0x00000000); -+ nv_wr32(dev, 0x405878, 0x00000000); -+ nv_wr32(dev, 0x406034, 0x00000000); -+ nv_wr32(dev, 0x40587c, 0x00000000); -+ -+ if (1) { -+ const u8 chipset_tp_max[] = { 16, 0, 0, 4, 8 }; -+ u8 max = chipset_tp_max[dev_priv->chipset & 0x0f]; -+ u8 tpnr[GPC_MAX]; -+ u8 data[32]; -+ -+ memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); -+ memset(data, 0x1f, sizeof(data)); -+ -+ gpc = -1; -+ for (tp = 0; tp < priv->tp_total; tp++) { -+ do { -+ gpc = (gpc + 1) % priv->gpc_nr; -+ } while (!tpnr[gpc]); -+ tpnr[gpc]--; -+ data[tp] = gpc; -+ } -+ -+ for (i = 0; i < max / 4; i++) -+ nv_wr32(dev, 0x4060a8 + (i * 4), ((u32 *)data)[i]); -+ } -+ -+ if (1) { -+ u32 data[6] = {}, data2[2] = {}; -+ u8 tpnr[GPC_MAX]; -+ u8 shift, ntpcv; -+ -+ /* calculate first set of magics */ -+ memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); -+ -+ for (tp = 0; tp < priv->tp_total; tp++) { -+ do { -+ gpc = (gpc + 1) % priv->gpc_nr; -+ } while (!tpnr[gpc]); -+ tpnr[gpc]--; -+ -+ data[tp / 6] |= gpc << ((tp % 6) * 5); -+ } -+ -+ for (; tp < 32; tp++) -+ data[tp / 6] |= 7 << ((tp % 6) * 5); -+ -+ /* and the second... */ -+ shift = 0; -+ ntpcv = priv->tp_total; -+ while (!(ntpcv & (1 << 4))) { -+ ntpcv <<= 1; -+ shift++; -+ } -+ -+ data2[0] = (ntpcv << 16); -+ data2[0] |= (shift << 21); -+ data2[0] |= (((1 << (0 + 5)) % ntpcv) << 24); -+ for (i = 1; i < 7; i++) -+ data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5); -+ -+ // GPC_BROADCAST -+ nv_wr32(dev, 0x418bb8, (priv->tp_total << 8) | -+ priv->magic_not_rop_nr); -+ for (i = 0; i < 6; i++) -+ nv_wr32(dev, 0x418b08 + (i * 4), data[i]); -+ -+ // GPC_BROADCAST.TP_BROADCAST -+ nv_wr32(dev, 0x419bd0, (priv->tp_total << 8) | -+ priv->magic_not_rop_nr | -+ data2[0]); -+ nv_wr32(dev, 0x419be4, data2[1]); -+ for (i = 0; i < 6; i++) -+ nv_wr32(dev, 0x419b00 + (i * 4), data[i]); -+ -+ // UNK78xx -+ nv_wr32(dev, 0x4078bc, (priv->tp_total << 8) | -+ priv->magic_not_rop_nr); -+ for (i = 0; i < 6; i++) -+ nv_wr32(dev, 0x40780c + (i * 4), data[i]); -+ } -+ -+ if (1) { -+ u32 tp_mask = 0, tp_set = 0; -+ u8 tpnr[GPC_MAX]; -+ -+ memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); -+ for (gpc = 0; gpc < priv->gpc_nr; gpc++) -+ tp_mask |= ((1 << priv->tp_nr[gpc]) - 1) << (gpc * 8); -+ -+ gpc = -1; -+ for (i = 0, gpc = -1; i < 32; i++) { -+ int ltp = i * (priv->tp_total - 1) / 32; -+ -+ do { -+ gpc = (gpc + 1) % priv->gpc_nr; -+ } while (!tpnr[gpc]); -+ tp = priv->tp_nr[gpc] - tpnr[gpc]--; -+ -+ tp_set |= 1 << ((gpc * 8) + tp); -+ -+ do { -+ nv_wr32(dev, 0x406800 + (i * 0x20), tp_set); -+ tp_set ^= tp_mask; -+ nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set); -+ tp_set ^= tp_mask; -+ } while (ltp == (++i * (priv->tp_total - 1) / 32)); -+ i--; -+ } -+ } -+ -+ nv_wr32(dev, 0x400208, 0x80000000); -+ -+ nv_icmd(dev, 0x00001000, 0x00000004); -+ nv_icmd(dev, 0x000000a9, 0x0000ffff); -+ nv_icmd(dev, 0x00000038, 0x0fac6881); -+ nv_icmd(dev, 0x0000003d, 0x00000001); -+ nv_icmd(dev, 0x000000e8, 0x00000400); -+ nv_icmd(dev, 0x000000e9, 0x00000400); -+ nv_icmd(dev, 0x000000ea, 0x00000400); -+ nv_icmd(dev, 0x000000eb, 0x00000400); -+ nv_icmd(dev, 0x000000ec, 0x00000400); -+ nv_icmd(dev, 0x000000ed, 0x00000400); -+ nv_icmd(dev, 0x000000ee, 0x00000400); -+ nv_icmd(dev, 0x000000ef, 0x00000400); -+ nv_icmd(dev, 0x00000078, 0x00000300); -+ nv_icmd(dev, 0x00000079, 0x00000300); -+ nv_icmd(dev, 0x0000007a, 0x00000300); -+ nv_icmd(dev, 0x0000007b, 0x00000300); -+ nv_icmd(dev, 0x0000007c, 0x00000300); -+ nv_icmd(dev, 0x0000007d, 0x00000300); -+ nv_icmd(dev, 0x0000007e, 0x00000300); -+ nv_icmd(dev, 0x0000007f, 0x00000300); -+ nv_icmd(dev, 0x00000050, 0x00000011); -+ nv_icmd(dev, 0x00000058, 0x00000008); -+ nv_icmd(dev, 0x00000059, 0x00000008); -+ nv_icmd(dev, 0x0000005a, 0x00000008); -+ nv_icmd(dev, 0x0000005b, 0x00000008); -+ nv_icmd(dev, 0x0000005c, 0x00000008); -+ nv_icmd(dev, 0x0000005d, 0x00000008); -+ nv_icmd(dev, 0x0000005e, 0x00000008); -+ nv_icmd(dev, 0x0000005f, 0x00000008); -+ nv_icmd(dev, 0x00000208, 0x00000001); -+ nv_icmd(dev, 0x00000209, 0x00000001); -+ nv_icmd(dev, 0x0000020a, 0x00000001); -+ nv_icmd(dev, 0x0000020b, 0x00000001); -+ nv_icmd(dev, 0x0000020c, 0x00000001); -+ nv_icmd(dev, 0x0000020d, 0x00000001); -+ nv_icmd(dev, 0x0000020e, 0x00000001); -+ nv_icmd(dev, 0x0000020f, 0x00000001); -+ nv_icmd(dev, 0x00000081, 0x00000001); -+ nv_icmd(dev, 0x00000085, 0x00000004); -+ nv_icmd(dev, 0x00000088, 0x00000400); -+ nv_icmd(dev, 0x00000090, 0x00000300); -+ nv_icmd(dev, 0x00000098, 0x00001001); -+ nv_icmd(dev, 0x000000e3, 0x00000001); -+ nv_icmd(dev, 0x000000da, 0x00000001); -+ nv_icmd(dev, 0x000000f8, 0x00000003); -+ nv_icmd(dev, 0x000000fa, 0x00000001); -+ nv_icmd(dev, 0x0000009f, 0x0000ffff); -+ nv_icmd(dev, 0x000000a0, 0x0000ffff); -+ nv_icmd(dev, 0x000000a1, 0x0000ffff); -+ nv_icmd(dev, 0x000000a2, 0x0000ffff); -+ nv_icmd(dev, 0x000000b1, 0x00000001); -+ nv_icmd(dev, 0x000000b2, 0x00000000); -+ nv_icmd(dev, 0x000000b3, 0x00000000); -+ nv_icmd(dev, 0x000000b4, 0x00000000); -+ nv_icmd(dev, 0x000000b5, 0x00000000); -+ nv_icmd(dev, 0x000000b6, 0x00000000); -+ nv_icmd(dev, 0x000000b7, 0x00000000); -+ nv_icmd(dev, 0x000000b8, 0x00000000); -+ nv_icmd(dev, 0x000000b9, 0x00000000); -+ nv_icmd(dev, 0x000000ba, 0x00000000); -+ nv_icmd(dev, 0x000000bb, 0x00000000); -+ nv_icmd(dev, 0x000000bc, 0x00000000); -+ nv_icmd(dev, 0x000000bd, 0x00000000); -+ nv_icmd(dev, 0x000000be, 0x00000000); -+ nv_icmd(dev, 0x000000bf, 0x00000000); -+ nv_icmd(dev, 0x000000c0, 0x00000000); -+ nv_icmd(dev, 0x000000c1, 0x00000000); -+ nv_icmd(dev, 0x000000c2, 0x00000000); -+ nv_icmd(dev, 0x000000c3, 0x00000000); -+ nv_icmd(dev, 0x000000c4, 0x00000000); -+ nv_icmd(dev, 0x000000c5, 0x00000000); -+ nv_icmd(dev, 0x000000c6, 0x00000000); -+ nv_icmd(dev, 0x000000c7, 0x00000000); -+ nv_icmd(dev, 0x000000c8, 0x00000000); -+ nv_icmd(dev, 0x000000c9, 0x00000000); -+ nv_icmd(dev, 0x000000ca, 0x00000000); -+ nv_icmd(dev, 0x000000cb, 0x00000000); -+ nv_icmd(dev, 0x000000cc, 0x00000000); -+ nv_icmd(dev, 0x000000cd, 0x00000000); -+ nv_icmd(dev, 0x000000ce, 0x00000000); -+ nv_icmd(dev, 0x000000cf, 0x00000000); -+ nv_icmd(dev, 0x000000d0, 0x00000000); -+ nv_icmd(dev, 0x000000d1, 0x00000000); -+ nv_icmd(dev, 0x000000d2, 0x00000000); -+ nv_icmd(dev, 0x000000d3, 0x00000000); -+ nv_icmd(dev, 0x000000d4, 0x00000000); -+ nv_icmd(dev, 0x000000d5, 0x00000000); -+ nv_icmd(dev, 0x000000d6, 0x00000000); -+ nv_icmd(dev, 0x000000d7, 0x00000000); -+ nv_icmd(dev, 0x000000d8, 0x00000000); -+ nv_icmd(dev, 0x000000d9, 0x00000000); -+ nv_icmd(dev, 0x00000210, 0x00000040); -+ nv_icmd(dev, 0x00000211, 0x00000040); -+ nv_icmd(dev, 0x00000212, 0x00000040); -+ nv_icmd(dev, 0x00000213, 0x00000040); -+ nv_icmd(dev, 0x00000214, 0x00000040); -+ nv_icmd(dev, 0x00000215, 0x00000040); -+ nv_icmd(dev, 0x00000216, 0x00000040); -+ nv_icmd(dev, 0x00000217, 0x00000040); -+ nv_icmd(dev, 0x00000218, 0x0000c080); -+ nv_icmd(dev, 0x00000219, 0x0000c080); -+ nv_icmd(dev, 0x0000021a, 0x0000c080); -+ nv_icmd(dev, 0x0000021b, 0x0000c080); -+ nv_icmd(dev, 0x0000021c, 0x0000c080); -+ nv_icmd(dev, 0x0000021d, 0x0000c080); -+ nv_icmd(dev, 0x0000021e, 0x0000c080); -+ nv_icmd(dev, 0x0000021f, 0x0000c080); -+ nv_icmd(dev, 0x000000ad, 0x0000013e); -+ nv_icmd(dev, 0x000000e1, 0x00000010); -+ nv_icmd(dev, 0x00000290, 0x00000000); -+ nv_icmd(dev, 0x00000291, 0x00000000); -+ nv_icmd(dev, 0x00000292, 0x00000000); -+ nv_icmd(dev, 0x00000293, 0x00000000); -+ nv_icmd(dev, 0x00000294, 0x00000000); -+ nv_icmd(dev, 0x00000295, 0x00000000); -+ nv_icmd(dev, 0x00000296, 0x00000000); -+ nv_icmd(dev, 0x00000297, 0x00000000); -+ nv_icmd(dev, 0x00000298, 0x00000000); -+ nv_icmd(dev, 0x00000299, 0x00000000); -+ nv_icmd(dev, 0x0000029a, 0x00000000); -+ nv_icmd(dev, 0x0000029b, 0x00000000); -+ nv_icmd(dev, 0x0000029c, 0x00000000); -+ nv_icmd(dev, 0x0000029d, 0x00000000); -+ nv_icmd(dev, 0x0000029e, 0x00000000); -+ nv_icmd(dev, 0x0000029f, 0x00000000); -+ nv_icmd(dev, 0x000003b0, 0x00000000); -+ nv_icmd(dev, 0x000003b1, 0x00000000); -+ nv_icmd(dev, 0x000003b2, 0x00000000); -+ nv_icmd(dev, 0x000003b3, 0x00000000); -+ nv_icmd(dev, 0x000003b4, 0x00000000); -+ nv_icmd(dev, 0x000003b5, 0x00000000); -+ nv_icmd(dev, 0x000003b6, 0x00000000); -+ nv_icmd(dev, 0x000003b7, 0x00000000); -+ nv_icmd(dev, 0x000003b8, 0x00000000); -+ nv_icmd(dev, 0x000003b9, 0x00000000); -+ nv_icmd(dev, 0x000003ba, 0x00000000); -+ nv_icmd(dev, 0x000003bb, 0x00000000); -+ nv_icmd(dev, 0x000003bc, 0x00000000); -+ nv_icmd(dev, 0x000003bd, 0x00000000); -+ nv_icmd(dev, 0x000003be, 0x00000000); -+ nv_icmd(dev, 0x000003bf, 0x00000000); -+ nv_icmd(dev, 0x000002a0, 0x00000000); -+ nv_icmd(dev, 0x000002a1, 0x00000000); -+ nv_icmd(dev, 0x000002a2, 0x00000000); -+ nv_icmd(dev, 0x000002a3, 0x00000000); -+ nv_icmd(dev, 0x000002a4, 0x00000000); -+ nv_icmd(dev, 0x000002a5, 0x00000000); -+ nv_icmd(dev, 0x000002a6, 0x00000000); -+ nv_icmd(dev, 0x000002a7, 0x00000000); -+ nv_icmd(dev, 0x000002a8, 0x00000000); -+ nv_icmd(dev, 0x000002a9, 0x00000000); -+ nv_icmd(dev, 0x000002aa, 0x00000000); -+ nv_icmd(dev, 0x000002ab, 0x00000000); -+ nv_icmd(dev, 0x000002ac, 0x00000000); -+ nv_icmd(dev, 0x000002ad, 0x00000000); -+ nv_icmd(dev, 0x000002ae, 0x00000000); -+ nv_icmd(dev, 0x000002af, 0x00000000); -+ nv_icmd(dev, 0x00000420, 0x00000000); -+ nv_icmd(dev, 0x00000421, 0x00000000); -+ nv_icmd(dev, 0x00000422, 0x00000000); -+ nv_icmd(dev, 0x00000423, 0x00000000); -+ nv_icmd(dev, 0x00000424, 0x00000000); -+ nv_icmd(dev, 0x00000425, 0x00000000); -+ nv_icmd(dev, 0x00000426, 0x00000000); -+ nv_icmd(dev, 0x00000427, 0x00000000); -+ nv_icmd(dev, 0x00000428, 0x00000000); -+ nv_icmd(dev, 0x00000429, 0x00000000); -+ nv_icmd(dev, 0x0000042a, 0x00000000); -+ nv_icmd(dev, 0x0000042b, 0x00000000); -+ nv_icmd(dev, 0x0000042c, 0x00000000); -+ nv_icmd(dev, 0x0000042d, 0x00000000); -+ nv_icmd(dev, 0x0000042e, 0x00000000); -+ nv_icmd(dev, 0x0000042f, 0x00000000); -+ nv_icmd(dev, 0x000002b0, 0x00000000); -+ nv_icmd(dev, 0x000002b1, 0x00000000); -+ nv_icmd(dev, 0x000002b2, 0x00000000); -+ nv_icmd(dev, 0x000002b3, 0x00000000); -+ nv_icmd(dev, 0x000002b4, 0x00000000); -+ nv_icmd(dev, 0x000002b5, 0x00000000); -+ nv_icmd(dev, 0x000002b6, 0x00000000); -+ nv_icmd(dev, 0x000002b7, 0x00000000); -+ nv_icmd(dev, 0x000002b8, 0x00000000); -+ nv_icmd(dev, 0x000002b9, 0x00000000); -+ nv_icmd(dev, 0x000002ba, 0x00000000); -+ nv_icmd(dev, 0x000002bb, 0x00000000); -+ nv_icmd(dev, 0x000002bc, 0x00000000); -+ nv_icmd(dev, 0x000002bd, 0x00000000); -+ nv_icmd(dev, 0x000002be, 0x00000000); -+ nv_icmd(dev, 0x000002bf, 0x00000000); -+ nv_icmd(dev, 0x00000430, 0x00000000); -+ nv_icmd(dev, 0x00000431, 0x00000000); -+ nv_icmd(dev, 0x00000432, 0x00000000); -+ nv_icmd(dev, 0x00000433, 0x00000000); -+ nv_icmd(dev, 0x00000434, 0x00000000); -+ nv_icmd(dev, 0x00000435, 0x00000000); -+ nv_icmd(dev, 0x00000436, 0x00000000); -+ nv_icmd(dev, 0x00000437, 0x00000000); -+ nv_icmd(dev, 0x00000438, 0x00000000); -+ nv_icmd(dev, 0x00000439, 0x00000000); -+ nv_icmd(dev, 0x0000043a, 0x00000000); -+ nv_icmd(dev, 0x0000043b, 0x00000000); -+ nv_icmd(dev, 0x0000043c, 0x00000000); -+ nv_icmd(dev, 0x0000043d, 0x00000000); -+ nv_icmd(dev, 0x0000043e, 0x00000000); -+ nv_icmd(dev, 0x0000043f, 0x00000000); -+ nv_icmd(dev, 0x000002c0, 0x00000000); -+ nv_icmd(dev, 0x000002c1, 0x00000000); -+ nv_icmd(dev, 0x000002c2, 0x00000000); -+ nv_icmd(dev, 0x000002c3, 0x00000000); -+ nv_icmd(dev, 0x000002c4, 0x00000000); -+ nv_icmd(dev, 0x000002c5, 0x00000000); -+ nv_icmd(dev, 0x000002c6, 0x00000000); -+ nv_icmd(dev, 0x000002c7, 0x00000000); -+ nv_icmd(dev, 0x000002c8, 0x00000000); -+ nv_icmd(dev, 0x000002c9, 0x00000000); -+ nv_icmd(dev, 0x000002ca, 0x00000000); -+ nv_icmd(dev, 0x000002cb, 0x00000000); -+ nv_icmd(dev, 0x000002cc, 0x00000000); -+ nv_icmd(dev, 0x000002cd, 0x00000000); -+ nv_icmd(dev, 0x000002ce, 0x00000000); -+ nv_icmd(dev, 0x000002cf, 0x00000000); -+ nv_icmd(dev, 0x000004d0, 0x00000000); -+ nv_icmd(dev, 0x000004d1, 0x00000000); -+ nv_icmd(dev, 0x000004d2, 0x00000000); -+ nv_icmd(dev, 0x000004d3, 0x00000000); -+ nv_icmd(dev, 0x000004d4, 0x00000000); -+ nv_icmd(dev, 0x000004d5, 0x00000000); -+ nv_icmd(dev, 0x000004d6, 0x00000000); -+ nv_icmd(dev, 0x000004d7, 0x00000000); -+ nv_icmd(dev, 0x000004d8, 0x00000000); -+ nv_icmd(dev, 0x000004d9, 0x00000000); -+ nv_icmd(dev, 0x000004da, 0x00000000); -+ nv_icmd(dev, 0x000004db, 0x00000000); -+ nv_icmd(dev, 0x000004dc, 0x00000000); -+ nv_icmd(dev, 0x000004dd, 0x00000000); -+ nv_icmd(dev, 0x000004de, 0x00000000); -+ nv_icmd(dev, 0x000004df, 0x00000000); -+ nv_icmd(dev, 0x00000720, 0x00000000); -+ nv_icmd(dev, 0x00000721, 0x00000000); -+ nv_icmd(dev, 0x00000722, 0x00000000); -+ nv_icmd(dev, 0x00000723, 0x00000000); -+ nv_icmd(dev, 0x00000724, 0x00000000); -+ nv_icmd(dev, 0x00000725, 0x00000000); -+ nv_icmd(dev, 0x00000726, 0x00000000); -+ nv_icmd(dev, 0x00000727, 0x00000000); -+ nv_icmd(dev, 0x00000728, 0x00000000); -+ nv_icmd(dev, 0x00000729, 0x00000000); -+ nv_icmd(dev, 0x0000072a, 0x00000000); -+ nv_icmd(dev, 0x0000072b, 0x00000000); -+ nv_icmd(dev, 0x0000072c, 0x00000000); -+ nv_icmd(dev, 0x0000072d, 0x00000000); -+ nv_icmd(dev, 0x0000072e, 0x00000000); -+ nv_icmd(dev, 0x0000072f, 0x00000000); -+ nv_icmd(dev, 0x000008c0, 0x00000000); -+ nv_icmd(dev, 0x000008c1, 0x00000000); -+ nv_icmd(dev, 0x000008c2, 0x00000000); -+ nv_icmd(dev, 0x000008c3, 0x00000000); -+ nv_icmd(dev, 0x000008c4, 0x00000000); -+ nv_icmd(dev, 0x000008c5, 0x00000000); -+ nv_icmd(dev, 0x000008c6, 0x00000000); -+ nv_icmd(dev, 0x000008c7, 0x00000000); -+ nv_icmd(dev, 0x000008c8, 0x00000000); -+ nv_icmd(dev, 0x000008c9, 0x00000000); -+ nv_icmd(dev, 0x000008ca, 0x00000000); -+ nv_icmd(dev, 0x000008cb, 0x00000000); -+ nv_icmd(dev, 0x000008cc, 0x00000000); -+ nv_icmd(dev, 0x000008cd, 0x00000000); -+ nv_icmd(dev, 0x000008ce, 0x00000000); -+ nv_icmd(dev, 0x000008cf, 0x00000000); -+ nv_icmd(dev, 0x00000890, 0x00000000); -+ nv_icmd(dev, 0x00000891, 0x00000000); -+ nv_icmd(dev, 0x00000892, 0x00000000); -+ nv_icmd(dev, 0x00000893, 0x00000000); -+ nv_icmd(dev, 0x00000894, 0x00000000); -+ nv_icmd(dev, 0x00000895, 0x00000000); -+ nv_icmd(dev, 0x00000896, 0x00000000); -+ nv_icmd(dev, 0x00000897, 0x00000000); -+ nv_icmd(dev, 0x00000898, 0x00000000); -+ nv_icmd(dev, 0x00000899, 0x00000000); -+ nv_icmd(dev, 0x0000089a, 0x00000000); -+ nv_icmd(dev, 0x0000089b, 0x00000000); -+ nv_icmd(dev, 0x0000089c, 0x00000000); -+ nv_icmd(dev, 0x0000089d, 0x00000000); -+ nv_icmd(dev, 0x0000089e, 0x00000000); -+ nv_icmd(dev, 0x0000089f, 0x00000000); -+ nv_icmd(dev, 0x000008e0, 0x00000000); -+ nv_icmd(dev, 0x000008e1, 0x00000000); -+ nv_icmd(dev, 0x000008e2, 0x00000000); -+ nv_icmd(dev, 0x000008e3, 0x00000000); -+ nv_icmd(dev, 0x000008e4, 0x00000000); -+ nv_icmd(dev, 0x000008e5, 0x00000000); -+ nv_icmd(dev, 0x000008e6, 0x00000000); -+ nv_icmd(dev, 0x000008e7, 0x00000000); -+ nv_icmd(dev, 0x000008e8, 0x00000000); -+ nv_icmd(dev, 0x000008e9, 0x00000000); -+ nv_icmd(dev, 0x000008ea, 0x00000000); -+ nv_icmd(dev, 0x000008eb, 0x00000000); -+ nv_icmd(dev, 0x000008ec, 0x00000000); -+ nv_icmd(dev, 0x000008ed, 0x00000000); -+ nv_icmd(dev, 0x000008ee, 0x00000000); -+ nv_icmd(dev, 0x000008ef, 0x00000000); -+ nv_icmd(dev, 0x000008a0, 0x00000000); -+ nv_icmd(dev, 0x000008a1, 0x00000000); -+ nv_icmd(dev, 0x000008a2, 0x00000000); -+ nv_icmd(dev, 0x000008a3, 0x00000000); -+ nv_icmd(dev, 0x000008a4, 0x00000000); -+ nv_icmd(dev, 0x000008a5, 0x00000000); -+ nv_icmd(dev, 0x000008a6, 0x00000000); -+ nv_icmd(dev, 0x000008a7, 0x00000000); -+ nv_icmd(dev, 0x000008a8, 0x00000000); -+ nv_icmd(dev, 0x000008a9, 0x00000000); -+ nv_icmd(dev, 0x000008aa, 0x00000000); -+ nv_icmd(dev, 0x000008ab, 0x00000000); -+ nv_icmd(dev, 0x000008ac, 0x00000000); -+ nv_icmd(dev, 0x000008ad, 0x00000000); -+ nv_icmd(dev, 0x000008ae, 0x00000000); -+ nv_icmd(dev, 0x000008af, 0x00000000); -+ nv_icmd(dev, 0x000008f0, 0x00000000); -+ nv_icmd(dev, 0x000008f1, 0x00000000); -+ nv_icmd(dev, 0x000008f2, 0x00000000); -+ nv_icmd(dev, 0x000008f3, 0x00000000); -+ nv_icmd(dev, 0x000008f4, 0x00000000); -+ nv_icmd(dev, 0x000008f5, 0x00000000); -+ nv_icmd(dev, 0x000008f6, 0x00000000); -+ nv_icmd(dev, 0x000008f7, 0x00000000); -+ nv_icmd(dev, 0x000008f8, 0x00000000); -+ nv_icmd(dev, 0x000008f9, 0x00000000); -+ nv_icmd(dev, 0x000008fa, 0x00000000); -+ nv_icmd(dev, 0x000008fb, 0x00000000); -+ nv_icmd(dev, 0x000008fc, 0x00000000); -+ nv_icmd(dev, 0x000008fd, 0x00000000); -+ nv_icmd(dev, 0x000008fe, 0x00000000); -+ nv_icmd(dev, 0x000008ff, 0x00000000); -+ nv_icmd(dev, 0x0000094c, 0x000000ff); -+ nv_icmd(dev, 0x0000094d, 0xffffffff); -+ nv_icmd(dev, 0x0000094e, 0x00000002); -+ nv_icmd(dev, 0x000002ec, 0x00000001); -+ nv_icmd(dev, 0x00000303, 0x00000001); -+ nv_icmd(dev, 0x000002e6, 0x00000001); -+ nv_icmd(dev, 0x00000466, 0x00000052); -+ nv_icmd(dev, 0x00000301, 0x3f800000); -+ nv_icmd(dev, 0x00000304, 0x30201000); -+ nv_icmd(dev, 0x00000305, 0x70605040); -+ nv_icmd(dev, 0x00000306, 0xb8a89888); -+ nv_icmd(dev, 0x00000307, 0xf8e8d8c8); -+ nv_icmd(dev, 0x0000030a, 0x00ffff00); -+ nv_icmd(dev, 0x0000030b, 0x0000001a); -+ nv_icmd(dev, 0x0000030c, 0x00000001); -+ nv_icmd(dev, 0x00000318, 0x00000001); -+ nv_icmd(dev, 0x00000340, 0x00000000); -+ nv_icmd(dev, 0x00000375, 0x00000001); -+ nv_icmd(dev, 0x00000351, 0x00000100); -+ nv_icmd(dev, 0x0000037d, 0x00000006); -+ nv_icmd(dev, 0x000003a0, 0x00000002); -+ nv_icmd(dev, 0x000003aa, 0x00000001); -+ nv_icmd(dev, 0x000003a9, 0x00000001); -+ nv_icmd(dev, 0x00000380, 0x00000001); -+ nv_icmd(dev, 0x00000360, 0x00000040); -+ nv_icmd(dev, 0x00000366, 0x00000000); -+ nv_icmd(dev, 0x00000367, 0x00000000); -+ nv_icmd(dev, 0x00000368, 0x00001fff); -+ nv_icmd(dev, 0x00000370, 0x00000000); -+ nv_icmd(dev, 0x00000371, 0x00000000); -+ nv_icmd(dev, 0x00000372, 0x003fffff); -+ nv_icmd(dev, 0x0000037a, 0x00000012); -+ nv_icmd(dev, 0x000005e0, 0x00000022); -+ nv_icmd(dev, 0x000005e1, 0x00000022); -+ nv_icmd(dev, 0x000005e2, 0x00000022); -+ nv_icmd(dev, 0x000005e3, 0x00000022); -+ nv_icmd(dev, 0x000005e4, 0x00000022); -+ nv_icmd(dev, 0x00000619, 0x00000003); -+ nv_icmd(dev, 0x00000811, 0x00000003); -+ nv_icmd(dev, 0x00000812, 0x00000004); -+ nv_icmd(dev, 0x00000813, 0x00000006); -+ nv_icmd(dev, 0x00000814, 0x00000008); -+ nv_icmd(dev, 0x00000815, 0x0000000b); -+ nv_icmd(dev, 0x00000800, 0x00000001); -+ nv_icmd(dev, 0x00000801, 0x00000001); -+ nv_icmd(dev, 0x00000802, 0x00000001); -+ nv_icmd(dev, 0x00000803, 0x00000001); -+ nv_icmd(dev, 0x00000804, 0x00000001); -+ nv_icmd(dev, 0x00000805, 0x00000001); -+ nv_icmd(dev, 0x00000632, 0x00000001); -+ nv_icmd(dev, 0x00000633, 0x00000002); -+ nv_icmd(dev, 0x00000634, 0x00000003); -+ nv_icmd(dev, 0x00000635, 0x00000004); -+ nv_icmd(dev, 0x00000654, 0x3f800000); -+ nv_icmd(dev, 0x00000657, 0x3f800000); -+ nv_icmd(dev, 0x00000655, 0x3f800000); -+ nv_icmd(dev, 0x00000656, 0x3f800000); -+ nv_icmd(dev, 0x000006cd, 0x3f800000); -+ nv_icmd(dev, 0x000007f5, 0x3f800000); -+ nv_icmd(dev, 0x000007dc, 0x39291909); -+ nv_icmd(dev, 0x000007dd, 0x79695949); -+ nv_icmd(dev, 0x000007de, 0xb9a99989); -+ nv_icmd(dev, 0x000007df, 0xf9e9d9c9); -+ nv_icmd(dev, 0x000007e8, 0x00003210); -+ nv_icmd(dev, 0x000007e9, 0x00007654); -+ nv_icmd(dev, 0x000007ea, 0x00000098); -+ nv_icmd(dev, 0x000007ec, 0x39291909); -+ nv_icmd(dev, 0x000007ed, 0x79695949); -+ nv_icmd(dev, 0x000007ee, 0xb9a99989); -+ nv_icmd(dev, 0x000007ef, 0xf9e9d9c9); -+ nv_icmd(dev, 0x000007f0, 0x00003210); -+ nv_icmd(dev, 0x000007f1, 0x00007654); -+ nv_icmd(dev, 0x000007f2, 0x00000098); -+ nv_icmd(dev, 0x000005a5, 0x00000001); -+ nv_icmd(dev, 0x00000980, 0x00000000); -+ nv_icmd(dev, 0x00000981, 0x00000000); -+ nv_icmd(dev, 0x00000982, 0x00000000); -+ nv_icmd(dev, 0x00000983, 0x00000000); -+ nv_icmd(dev, 0x00000984, 0x00000000); -+ nv_icmd(dev, 0x00000985, 0x00000000); -+ nv_icmd(dev, 0x00000986, 0x00000000); -+ nv_icmd(dev, 0x00000987, 0x00000000); -+ nv_icmd(dev, 0x00000988, 0x00000000); -+ nv_icmd(dev, 0x00000989, 0x00000000); -+ nv_icmd(dev, 0x0000098a, 0x00000000); -+ nv_icmd(dev, 0x0000098b, 0x00000000); -+ nv_icmd(dev, 0x0000098c, 0x00000000); -+ nv_icmd(dev, 0x0000098d, 0x00000000); -+ nv_icmd(dev, 0x0000098e, 0x00000000); -+ nv_icmd(dev, 0x0000098f, 0x00000000); -+ nv_icmd(dev, 0x00000990, 0x00000000); -+ nv_icmd(dev, 0x00000991, 0x00000000); -+ nv_icmd(dev, 0x00000992, 0x00000000); -+ nv_icmd(dev, 0x00000993, 0x00000000); -+ nv_icmd(dev, 0x00000994, 0x00000000); -+ nv_icmd(dev, 0x00000995, 0x00000000); -+ nv_icmd(dev, 0x00000996, 0x00000000); -+ nv_icmd(dev, 0x00000997, 0x00000000); -+ nv_icmd(dev, 0x00000998, 0x00000000); -+ nv_icmd(dev, 0x00000999, 0x00000000); -+ nv_icmd(dev, 0x0000099a, 0x00000000); -+ nv_icmd(dev, 0x0000099b, 0x00000000); -+ nv_icmd(dev, 0x0000099c, 0x00000000); -+ nv_icmd(dev, 0x0000099d, 0x00000000); -+ nv_icmd(dev, 0x0000099e, 0x00000000); -+ nv_icmd(dev, 0x0000099f, 0x00000000); -+ nv_icmd(dev, 0x000009a0, 0x00000000); -+ nv_icmd(dev, 0x000009a1, 0x00000000); -+ nv_icmd(dev, 0x000009a2, 0x00000000); -+ nv_icmd(dev, 0x000009a3, 0x00000000); -+ nv_icmd(dev, 0x000009a4, 0x00000000); -+ nv_icmd(dev, 0x000009a5, 0x00000000); -+ nv_icmd(dev, 0x000009a6, 0x00000000); -+ nv_icmd(dev, 0x000009a7, 0x00000000); -+ nv_icmd(dev, 0x000009a8, 0x00000000); -+ nv_icmd(dev, 0x000009a9, 0x00000000); -+ nv_icmd(dev, 0x000009aa, 0x00000000); -+ nv_icmd(dev, 0x000009ab, 0x00000000); -+ nv_icmd(dev, 0x000009ac, 0x00000000); -+ nv_icmd(dev, 0x000009ad, 0x00000000); -+ nv_icmd(dev, 0x000009ae, 0x00000000); -+ nv_icmd(dev, 0x000009af, 0x00000000); -+ nv_icmd(dev, 0x000009b0, 0x00000000); -+ nv_icmd(dev, 0x000009b1, 0x00000000); -+ nv_icmd(dev, 0x000009b2, 0x00000000); -+ nv_icmd(dev, 0x000009b3, 0x00000000); -+ nv_icmd(dev, 0x000009b4, 0x00000000); -+ nv_icmd(dev, 0x000009b5, 0x00000000); -+ nv_icmd(dev, 0x000009b6, 0x00000000); -+ nv_icmd(dev, 0x000009b7, 0x00000000); -+ nv_icmd(dev, 0x000009b8, 0x00000000); -+ nv_icmd(dev, 0x000009b9, 0x00000000); -+ nv_icmd(dev, 0x000009ba, 0x00000000); -+ nv_icmd(dev, 0x000009bb, 0x00000000); -+ nv_icmd(dev, 0x000009bc, 0x00000000); -+ nv_icmd(dev, 0x000009bd, 0x00000000); -+ nv_icmd(dev, 0x000009be, 0x00000000); -+ nv_icmd(dev, 0x000009bf, 0x00000000); -+ nv_icmd(dev, 0x000009c0, 0x00000000); -+ nv_icmd(dev, 0x000009c1, 0x00000000); -+ nv_icmd(dev, 0x000009c2, 0x00000000); -+ nv_icmd(dev, 0x000009c3, 0x00000000); -+ nv_icmd(dev, 0x000009c4, 0x00000000); -+ nv_icmd(dev, 0x000009c5, 0x00000000); -+ nv_icmd(dev, 0x000009c6, 0x00000000); -+ nv_icmd(dev, 0x000009c7, 0x00000000); -+ nv_icmd(dev, 0x000009c8, 0x00000000); -+ nv_icmd(dev, 0x000009c9, 0x00000000); -+ nv_icmd(dev, 0x000009ca, 0x00000000); -+ nv_icmd(dev, 0x000009cb, 0x00000000); -+ nv_icmd(dev, 0x000009cc, 0x00000000); -+ nv_icmd(dev, 0x000009cd, 0x00000000); -+ nv_icmd(dev, 0x000009ce, 0x00000000); -+ nv_icmd(dev, 0x000009cf, 0x00000000); -+ nv_icmd(dev, 0x000009d0, 0x00000000); -+ nv_icmd(dev, 0x000009d1, 0x00000000); -+ nv_icmd(dev, 0x000009d2, 0x00000000); -+ nv_icmd(dev, 0x000009d3, 0x00000000); -+ nv_icmd(dev, 0x000009d4, 0x00000000); -+ nv_icmd(dev, 0x000009d5, 0x00000000); -+ nv_icmd(dev, 0x000009d6, 0x00000000); -+ nv_icmd(dev, 0x000009d7, 0x00000000); -+ nv_icmd(dev, 0x000009d8, 0x00000000); -+ nv_icmd(dev, 0x000009d9, 0x00000000); -+ nv_icmd(dev, 0x000009da, 0x00000000); -+ nv_icmd(dev, 0x000009db, 0x00000000); -+ nv_icmd(dev, 0x000009dc, 0x00000000); -+ nv_icmd(dev, 0x000009dd, 0x00000000); -+ nv_icmd(dev, 0x000009de, 0x00000000); -+ nv_icmd(dev, 0x000009df, 0x00000000); -+ nv_icmd(dev, 0x000009e0, 0x00000000); -+ nv_icmd(dev, 0x000009e1, 0x00000000); -+ nv_icmd(dev, 0x000009e2, 0x00000000); -+ nv_icmd(dev, 0x000009e3, 0x00000000); -+ nv_icmd(dev, 0x000009e4, 0x00000000); -+ nv_icmd(dev, 0x000009e5, 0x00000000); -+ nv_icmd(dev, 0x000009e6, 0x00000000); -+ nv_icmd(dev, 0x000009e7, 0x00000000); -+ nv_icmd(dev, 0x000009e8, 0x00000000); -+ nv_icmd(dev, 0x000009e9, 0x00000000); -+ nv_icmd(dev, 0x000009ea, 0x00000000); -+ nv_icmd(dev, 0x000009eb, 0x00000000); -+ nv_icmd(dev, 0x000009ec, 0x00000000); -+ nv_icmd(dev, 0x000009ed, 0x00000000); -+ nv_icmd(dev, 0x000009ee, 0x00000000); -+ nv_icmd(dev, 0x000009ef, 0x00000000); -+ nv_icmd(dev, 0x000009f0, 0x00000000); -+ nv_icmd(dev, 0x000009f1, 0x00000000); -+ nv_icmd(dev, 0x000009f2, 0x00000000); -+ nv_icmd(dev, 0x000009f3, 0x00000000); -+ nv_icmd(dev, 0x000009f4, 0x00000000); -+ nv_icmd(dev, 0x000009f5, 0x00000000); -+ nv_icmd(dev, 0x000009f6, 0x00000000); -+ nv_icmd(dev, 0x000009f7, 0x00000000); -+ nv_icmd(dev, 0x000009f8, 0x00000000); -+ nv_icmd(dev, 0x000009f9, 0x00000000); -+ nv_icmd(dev, 0x000009fa, 0x00000000); -+ nv_icmd(dev, 0x000009fb, 0x00000000); -+ nv_icmd(dev, 0x000009fc, 0x00000000); -+ nv_icmd(dev, 0x000009fd, 0x00000000); -+ nv_icmd(dev, 0x000009fe, 0x00000000); -+ nv_icmd(dev, 0x000009ff, 0x00000000); -+ nv_icmd(dev, 0x00000468, 0x00000004); -+ nv_icmd(dev, 0x0000046c, 0x00000001); -+ nv_icmd(dev, 0x00000470, 0x00000000); -+ nv_icmd(dev, 0x00000471, 0x00000000); -+ nv_icmd(dev, 0x00000472, 0x00000000); -+ nv_icmd(dev, 0x00000473, 0x00000000); -+ nv_icmd(dev, 0x00000474, 0x00000000); -+ nv_icmd(dev, 0x00000475, 0x00000000); -+ nv_icmd(dev, 0x00000476, 0x00000000); -+ nv_icmd(dev, 0x00000477, 0x00000000); -+ nv_icmd(dev, 0x00000478, 0x00000000); -+ nv_icmd(dev, 0x00000479, 0x00000000); -+ nv_icmd(dev, 0x0000047a, 0x00000000); -+ nv_icmd(dev, 0x0000047b, 0x00000000); -+ nv_icmd(dev, 0x0000047c, 0x00000000); -+ nv_icmd(dev, 0x0000047d, 0x00000000); -+ nv_icmd(dev, 0x0000047e, 0x00000000); -+ nv_icmd(dev, 0x0000047f, 0x00000000); -+ nv_icmd(dev, 0x00000480, 0x00000000); -+ nv_icmd(dev, 0x00000481, 0x00000000); -+ nv_icmd(dev, 0x00000482, 0x00000000); -+ nv_icmd(dev, 0x00000483, 0x00000000); -+ nv_icmd(dev, 0x00000484, 0x00000000); -+ nv_icmd(dev, 0x00000485, 0x00000000); -+ nv_icmd(dev, 0x00000486, 0x00000000); -+ nv_icmd(dev, 0x00000487, 0x00000000); -+ nv_icmd(dev, 0x00000488, 0x00000000); -+ nv_icmd(dev, 0x00000489, 0x00000000); -+ nv_icmd(dev, 0x0000048a, 0x00000000); -+ nv_icmd(dev, 0x0000048b, 0x00000000); -+ nv_icmd(dev, 0x0000048c, 0x00000000); -+ nv_icmd(dev, 0x0000048d, 0x00000000); -+ nv_icmd(dev, 0x0000048e, 0x00000000); -+ nv_icmd(dev, 0x0000048f, 0x00000000); -+ nv_icmd(dev, 0x00000490, 0x00000000); -+ nv_icmd(dev, 0x00000491, 0x00000000); -+ nv_icmd(dev, 0x00000492, 0x00000000); -+ nv_icmd(dev, 0x00000493, 0x00000000); -+ nv_icmd(dev, 0x00000494, 0x00000000); -+ nv_icmd(dev, 0x00000495, 0x00000000); -+ nv_icmd(dev, 0x00000496, 0x00000000); -+ nv_icmd(dev, 0x00000497, 0x00000000); -+ nv_icmd(dev, 0x00000498, 0x00000000); -+ nv_icmd(dev, 0x00000499, 0x00000000); -+ nv_icmd(dev, 0x0000049a, 0x00000000); -+ nv_icmd(dev, 0x0000049b, 0x00000000); -+ nv_icmd(dev, 0x0000049c, 0x00000000); -+ nv_icmd(dev, 0x0000049d, 0x00000000); -+ nv_icmd(dev, 0x0000049e, 0x00000000); -+ nv_icmd(dev, 0x0000049f, 0x00000000); -+ nv_icmd(dev, 0x000004a0, 0x00000000); -+ nv_icmd(dev, 0x000004a1, 0x00000000); -+ nv_icmd(dev, 0x000004a2, 0x00000000); -+ nv_icmd(dev, 0x000004a3, 0x00000000); -+ nv_icmd(dev, 0x000004a4, 0x00000000); -+ nv_icmd(dev, 0x000004a5, 0x00000000); -+ nv_icmd(dev, 0x000004a6, 0x00000000); -+ nv_icmd(dev, 0x000004a7, 0x00000000); -+ nv_icmd(dev, 0x000004a8, 0x00000000); -+ nv_icmd(dev, 0x000004a9, 0x00000000); -+ nv_icmd(dev, 0x000004aa, 0x00000000); -+ nv_icmd(dev, 0x000004ab, 0x00000000); -+ nv_icmd(dev, 0x000004ac, 0x00000000); -+ nv_icmd(dev, 0x000004ad, 0x00000000); -+ nv_icmd(dev, 0x000004ae, 0x00000000); -+ nv_icmd(dev, 0x000004af, 0x00000000); -+ nv_icmd(dev, 0x000004b0, 0x00000000); -+ nv_icmd(dev, 0x000004b1, 0x00000000); -+ nv_icmd(dev, 0x000004b2, 0x00000000); -+ nv_icmd(dev, 0x000004b3, 0x00000000); -+ nv_icmd(dev, 0x000004b4, 0x00000000); -+ nv_icmd(dev, 0x000004b5, 0x00000000); -+ nv_icmd(dev, 0x000004b6, 0x00000000); -+ nv_icmd(dev, 0x000004b7, 0x00000000); -+ nv_icmd(dev, 0x000004b8, 0x00000000); -+ nv_icmd(dev, 0x000004b9, 0x00000000); -+ nv_icmd(dev, 0x000004ba, 0x00000000); -+ nv_icmd(dev, 0x000004bb, 0x00000000); -+ nv_icmd(dev, 0x000004bc, 0x00000000); -+ nv_icmd(dev, 0x000004bd, 0x00000000); -+ nv_icmd(dev, 0x000004be, 0x00000000); -+ nv_icmd(dev, 0x000004bf, 0x00000000); -+ nv_icmd(dev, 0x000004c0, 0x00000000); -+ nv_icmd(dev, 0x000004c1, 0x00000000); -+ nv_icmd(dev, 0x000004c2, 0x00000000); -+ nv_icmd(dev, 0x000004c3, 0x00000000); -+ nv_icmd(dev, 0x000004c4, 0x00000000); -+ nv_icmd(dev, 0x000004c5, 0x00000000); -+ nv_icmd(dev, 0x000004c6, 0x00000000); -+ nv_icmd(dev, 0x000004c7, 0x00000000); -+ nv_icmd(dev, 0x000004c8, 0x00000000); -+ nv_icmd(dev, 0x000004c9, 0x00000000); -+ nv_icmd(dev, 0x000004ca, 0x00000000); -+ nv_icmd(dev, 0x000004cb, 0x00000000); -+ nv_icmd(dev, 0x000004cc, 0x00000000); -+ nv_icmd(dev, 0x000004cd, 0x00000000); -+ nv_icmd(dev, 0x000004ce, 0x00000000); -+ nv_icmd(dev, 0x000004cf, 0x00000000); -+ nv_icmd(dev, 0x00000510, 0x3f800000); -+ nv_icmd(dev, 0x00000511, 0x3f800000); -+ nv_icmd(dev, 0x00000512, 0x3f800000); -+ nv_icmd(dev, 0x00000513, 0x3f800000); -+ nv_icmd(dev, 0x00000514, 0x3f800000); -+ nv_icmd(dev, 0x00000515, 0x3f800000); -+ nv_icmd(dev, 0x00000516, 0x3f800000); -+ nv_icmd(dev, 0x00000517, 0x3f800000); -+ nv_icmd(dev, 0x00000518, 0x3f800000); -+ nv_icmd(dev, 0x00000519, 0x3f800000); -+ nv_icmd(dev, 0x0000051a, 0x3f800000); -+ nv_icmd(dev, 0x0000051b, 0x3f800000); -+ nv_icmd(dev, 0x0000051c, 0x3f800000); -+ nv_icmd(dev, 0x0000051d, 0x3f800000); -+ nv_icmd(dev, 0x0000051e, 0x3f800000); -+ nv_icmd(dev, 0x0000051f, 0x3f800000); -+ nv_icmd(dev, 0x00000520, 0x000002b6); -+ nv_icmd(dev, 0x00000529, 0x00000001); -+ nv_icmd(dev, 0x00000530, 0xffff0000); -+ nv_icmd(dev, 0x00000531, 0xffff0000); -+ nv_icmd(dev, 0x00000532, 0xffff0000); -+ nv_icmd(dev, 0x00000533, 0xffff0000); -+ nv_icmd(dev, 0x00000534, 0xffff0000); -+ nv_icmd(dev, 0x00000535, 0xffff0000); -+ nv_icmd(dev, 0x00000536, 0xffff0000); -+ nv_icmd(dev, 0x00000537, 0xffff0000); -+ nv_icmd(dev, 0x00000538, 0xffff0000); -+ nv_icmd(dev, 0x00000539, 0xffff0000); -+ nv_icmd(dev, 0x0000053a, 0xffff0000); -+ nv_icmd(dev, 0x0000053b, 0xffff0000); -+ nv_icmd(dev, 0x0000053c, 0xffff0000); -+ nv_icmd(dev, 0x0000053d, 0xffff0000); -+ nv_icmd(dev, 0x0000053e, 0xffff0000); -+ nv_icmd(dev, 0x0000053f, 0xffff0000); -+ nv_icmd(dev, 0x00000585, 0x0000003f); -+ nv_icmd(dev, 0x00000576, 0x00000003); -+ nv_icmd(dev, 0x00000586, 0x00000040); -+ nv_icmd(dev, 0x00000582, 0x00000080); -+ nv_icmd(dev, 0x00000583, 0x00000080); -+ nv_icmd(dev, 0x000005c2, 0x00000001); -+ nv_icmd(dev, 0x00000638, 0x00000001); -+ nv_icmd(dev, 0x00000639, 0x00000001); -+ nv_icmd(dev, 0x0000063a, 0x00000002); -+ nv_icmd(dev, 0x0000063b, 0x00000001); -+ nv_icmd(dev, 0x0000063c, 0x00000001); -+ nv_icmd(dev, 0x0000063d, 0x00000002); -+ nv_icmd(dev, 0x0000063e, 0x00000001); -+ nv_icmd(dev, 0x000008b8, 0x00000001); -+ nv_icmd(dev, 0x000008b9, 0x00000001); -+ nv_icmd(dev, 0x000008ba, 0x00000001); -+ nv_icmd(dev, 0x000008bb, 0x00000001); -+ nv_icmd(dev, 0x000008bc, 0x00000001); -+ nv_icmd(dev, 0x000008bd, 0x00000001); -+ nv_icmd(dev, 0x000008be, 0x00000001); -+ nv_icmd(dev, 0x000008bf, 0x00000001); -+ nv_icmd(dev, 0x00000900, 0x00000001); -+ nv_icmd(dev, 0x00000901, 0x00000001); -+ nv_icmd(dev, 0x00000902, 0x00000001); -+ nv_icmd(dev, 0x00000903, 0x00000001); -+ nv_icmd(dev, 0x00000904, 0x00000001); -+ nv_icmd(dev, 0x00000905, 0x00000001); -+ nv_icmd(dev, 0x00000906, 0x00000001); -+ nv_icmd(dev, 0x00000907, 0x00000001); -+ nv_icmd(dev, 0x00000908, 0x00000002); -+ nv_icmd(dev, 0x00000909, 0x00000002); -+ nv_icmd(dev, 0x0000090a, 0x00000002); -+ nv_icmd(dev, 0x0000090b, 0x00000002); -+ nv_icmd(dev, 0x0000090c, 0x00000002); -+ nv_icmd(dev, 0x0000090d, 0x00000002); -+ nv_icmd(dev, 0x0000090e, 0x00000002); -+ nv_icmd(dev, 0x0000090f, 0x00000002); -+ nv_icmd(dev, 0x00000910, 0x00000001); -+ nv_icmd(dev, 0x00000911, 0x00000001); -+ nv_icmd(dev, 0x00000912, 0x00000001); -+ nv_icmd(dev, 0x00000913, 0x00000001); -+ nv_icmd(dev, 0x00000914, 0x00000001); -+ nv_icmd(dev, 0x00000915, 0x00000001); -+ nv_icmd(dev, 0x00000916, 0x00000001); -+ nv_icmd(dev, 0x00000917, 0x00000001); -+ nv_icmd(dev, 0x00000918, 0x00000001); -+ nv_icmd(dev, 0x00000919, 0x00000001); -+ nv_icmd(dev, 0x0000091a, 0x00000001); -+ nv_icmd(dev, 0x0000091b, 0x00000001); -+ nv_icmd(dev, 0x0000091c, 0x00000001); -+ nv_icmd(dev, 0x0000091d, 0x00000001); -+ nv_icmd(dev, 0x0000091e, 0x00000001); -+ nv_icmd(dev, 0x0000091f, 0x00000001); -+ nv_icmd(dev, 0x00000920, 0x00000002); -+ nv_icmd(dev, 0x00000921, 0x00000002); -+ nv_icmd(dev, 0x00000922, 0x00000002); -+ nv_icmd(dev, 0x00000923, 0x00000002); -+ nv_icmd(dev, 0x00000924, 0x00000002); -+ nv_icmd(dev, 0x00000925, 0x00000002); -+ nv_icmd(dev, 0x00000926, 0x00000002); -+ nv_icmd(dev, 0x00000927, 0x00000002); -+ nv_icmd(dev, 0x00000928, 0x00000001); -+ nv_icmd(dev, 0x00000929, 0x00000001); -+ nv_icmd(dev, 0x0000092a, 0x00000001); -+ nv_icmd(dev, 0x0000092b, 0x00000001); -+ nv_icmd(dev, 0x0000092c, 0x00000001); -+ nv_icmd(dev, 0x0000092d, 0x00000001); -+ nv_icmd(dev, 0x0000092e, 0x00000001); -+ nv_icmd(dev, 0x0000092f, 0x00000001); -+ nv_icmd(dev, 0x00000648, 0x00000001); -+ nv_icmd(dev, 0x00000649, 0x00000001); -+ nv_icmd(dev, 0x0000064a, 0x00000001); -+ nv_icmd(dev, 0x0000064b, 0x00000001); -+ nv_icmd(dev, 0x0000064c, 0x00000001); -+ nv_icmd(dev, 0x0000064d, 0x00000001); -+ nv_icmd(dev, 0x0000064e, 0x00000001); -+ nv_icmd(dev, 0x0000064f, 0x00000001); -+ nv_icmd(dev, 0x00000650, 0x00000001); -+ nv_icmd(dev, 0x00000658, 0x0000000f); -+ nv_icmd(dev, 0x000007ff, 0x0000000a); -+ nv_icmd(dev, 0x0000066a, 0x40000000); -+ nv_icmd(dev, 0x0000066b, 0x10000000); -+ nv_icmd(dev, 0x0000066c, 0xffff0000); -+ nv_icmd(dev, 0x0000066d, 0xffff0000); -+ nv_icmd(dev, 0x000007af, 0x00000008); -+ nv_icmd(dev, 0x000007b0, 0x00000008); -+ nv_icmd(dev, 0x000007f6, 0x00000001); -+ nv_icmd(dev, 0x000006b2, 0x00000055); -+ nv_icmd(dev, 0x000007ad, 0x00000003); -+ nv_icmd(dev, 0x00000937, 0x00000001); -+ nv_icmd(dev, 0x00000971, 0x00000008); -+ nv_icmd(dev, 0x00000972, 0x00000040); -+ nv_icmd(dev, 0x00000973, 0x0000012c); -+ nv_icmd(dev, 0x0000097c, 0x00000040); -+ nv_icmd(dev, 0x00000979, 0x00000003); -+ nv_icmd(dev, 0x00000975, 0x00000020); -+ nv_icmd(dev, 0x00000976, 0x00000001); -+ nv_icmd(dev, 0x00000977, 0x00000020); -+ nv_icmd(dev, 0x00000978, 0x00000001); -+ nv_icmd(dev, 0x00000957, 0x00000003); -+ nv_icmd(dev, 0x0000095e, 0x20164010); -+ nv_icmd(dev, 0x0000095f, 0x00000020); -+ nv_icmd(dev, 0x00000683, 0x00000006); -+ nv_icmd(dev, 0x00000685, 0x003fffff); -+ nv_icmd(dev, 0x00000687, 0x00000c48); -+ nv_icmd(dev, 0x000006a0, 0x00000005); -+ nv_icmd(dev, 0x00000840, 0x00300008); -+ nv_icmd(dev, 0x00000841, 0x04000080); -+ nv_icmd(dev, 0x00000842, 0x00300008); -+ nv_icmd(dev, 0x00000843, 0x04000080); -+ nv_icmd(dev, 0x00000818, 0x00000000); -+ nv_icmd(dev, 0x00000819, 0x00000000); -+ nv_icmd(dev, 0x0000081a, 0x00000000); -+ nv_icmd(dev, 0x0000081b, 0x00000000); -+ nv_icmd(dev, 0x0000081c, 0x00000000); -+ nv_icmd(dev, 0x0000081d, 0x00000000); -+ nv_icmd(dev, 0x0000081e, 0x00000000); -+ nv_icmd(dev, 0x0000081f, 0x00000000); -+ nv_icmd(dev, 0x00000848, 0x00000000); -+ nv_icmd(dev, 0x00000849, 0x00000000); -+ nv_icmd(dev, 0x0000084a, 0x00000000); -+ nv_icmd(dev, 0x0000084b, 0x00000000); -+ nv_icmd(dev, 0x0000084c, 0x00000000); -+ nv_icmd(dev, 0x0000084d, 0x00000000); -+ nv_icmd(dev, 0x0000084e, 0x00000000); -+ nv_icmd(dev, 0x0000084f, 0x00000000); -+ nv_icmd(dev, 0x00000850, 0x00000000); -+ nv_icmd(dev, 0x00000851, 0x00000000); -+ nv_icmd(dev, 0x00000852, 0x00000000); -+ nv_icmd(dev, 0x00000853, 0x00000000); -+ nv_icmd(dev, 0x00000854, 0x00000000); -+ nv_icmd(dev, 0x00000855, 0x00000000); -+ nv_icmd(dev, 0x00000856, 0x00000000); -+ nv_icmd(dev, 0x00000857, 0x00000000); -+ nv_icmd(dev, 0x00000738, 0x00000000); -+ nv_icmd(dev, 0x000006aa, 0x00000001); -+ nv_icmd(dev, 0x000006ab, 0x00000002); -+ nv_icmd(dev, 0x000006ac, 0x00000080); -+ nv_icmd(dev, 0x000006ad, 0x00000100); -+ nv_icmd(dev, 0x000006ae, 0x00000100); -+ nv_icmd(dev, 0x000006b1, 0x00000011); -+ nv_icmd(dev, 0x000006bb, 0x000000cf); -+ nv_icmd(dev, 0x000006ce, 0x2a712488); -+ nv_icmd(dev, 0x00000739, 0x4085c000); -+ nv_icmd(dev, 0x0000073a, 0x00000080); -+ nv_icmd(dev, 0x00000786, 0x80000100); -+ nv_icmd(dev, 0x0000073c, 0x00010100); -+ nv_icmd(dev, 0x0000073d, 0x02800000); -+ nv_icmd(dev, 0x00000787, 0x000000cf); -+ nv_icmd(dev, 0x0000078c, 0x00000008); -+ nv_icmd(dev, 0x00000792, 0x00000001); -+ nv_icmd(dev, 0x00000794, 0x00000001); -+ nv_icmd(dev, 0x00000795, 0x00000001); -+ nv_icmd(dev, 0x00000796, 0x00000001); -+ nv_icmd(dev, 0x00000797, 0x000000cf); -+ nv_icmd(dev, 0x00000836, 0x00000001); -+ nv_icmd(dev, 0x0000079a, 0x00000002); -+ nv_icmd(dev, 0x00000833, 0x04444480); -+ nv_icmd(dev, 0x000007a1, 0x00000001); -+ nv_icmd(dev, 0x000007a3, 0x00000001); -+ nv_icmd(dev, 0x000007a4, 0x00000001); -+ nv_icmd(dev, 0x000007a5, 0x00000001); -+ nv_icmd(dev, 0x00000831, 0x00000004); -+ nv_icmd(dev, 0x0000080c, 0x00000002); -+ nv_icmd(dev, 0x0000080d, 0x00000100); -+ nv_icmd(dev, 0x0000080e, 0x00000100); -+ nv_icmd(dev, 0x0000080f, 0x00000001); -+ nv_icmd(dev, 0x00000823, 0x00000002); -+ nv_icmd(dev, 0x00000824, 0x00000100); -+ nv_icmd(dev, 0x00000825, 0x00000100); -+ nv_icmd(dev, 0x00000826, 0x00000001); -+ nv_icmd(dev, 0x0000095d, 0x00000001); -+ nv_icmd(dev, 0x0000082b, 0x00000004); -+ nv_icmd(dev, 0x00000942, 0x00010001); -+ nv_icmd(dev, 0x00000943, 0x00000001); -+ nv_icmd(dev, 0x00000944, 0x00000022); -+ nv_icmd(dev, 0x000007c5, 0x00010001); -+ nv_icmd(dev, 0x00000834, 0x00000001); -+ nv_icmd(dev, 0x000007c7, 0x00000001); -+ nv_icmd(dev, 0x0000c1b0, 0x0000000f); -+ nv_icmd(dev, 0x0000c1b1, 0x0000000f); -+ nv_icmd(dev, 0x0000c1b2, 0x0000000f); -+ nv_icmd(dev, 0x0000c1b3, 0x0000000f); -+ nv_icmd(dev, 0x0000c1b4, 0x0000000f); -+ nv_icmd(dev, 0x0000c1b5, 0x0000000f); -+ nv_icmd(dev, 0x0000c1b6, 0x0000000f); -+ nv_icmd(dev, 0x0000c1b7, 0x0000000f); -+ nv_icmd(dev, 0x0000c1b8, 0x0fac6881); -+ nv_icmd(dev, 0x0000c1b9, 0x00fac688); -+ nv_icmd(dev, 0x0001e100, 0x00000001); -+ nv_icmd(dev, 0x00001000, 0x00000002); -+ nv_icmd(dev, 0x000006aa, 0x00000001); -+ nv_icmd(dev, 0x000006ad, 0x00000100); -+ nv_icmd(dev, 0x000006ae, 0x00000100); -+ nv_icmd(dev, 0x000006b1, 0x00000011); -+ nv_icmd(dev, 0x0000078c, 0x00000008); -+ nv_icmd(dev, 0x00000792, 0x00000001); -+ nv_icmd(dev, 0x00000794, 0x00000001); -+ nv_icmd(dev, 0x00000795, 0x00000001); -+ nv_icmd(dev, 0x00000796, 0x00000001); -+ nv_icmd(dev, 0x00000797, 0x000000cf); -+ nv_icmd(dev, 0x0000079a, 0x00000002); -+ nv_icmd(dev, 0x00000833, 0x04444480); -+ nv_icmd(dev, 0x000007a1, 0x00000001); -+ nv_icmd(dev, 0x000007a3, 0x00000001); -+ nv_icmd(dev, 0x000007a4, 0x00000001); -+ nv_icmd(dev, 0x000007a5, 0x00000001); -+ nv_icmd(dev, 0x00000831, 0x00000004); -+ nv_icmd(dev, 0x0001e100, 0x00000001); -+ nv_icmd(dev, 0x00001000, 0x00000014); -+ nv_icmd(dev, 0x00000351, 0x00000100); -+ nv_icmd(dev, 0x00000957, 0x00000003); -+ nv_icmd(dev, 0x0000095d, 0x00000001); -+ nv_icmd(dev, 0x0000082b, 0x00000004); -+ nv_icmd(dev, 0x00000942, 0x00010001); -+ nv_icmd(dev, 0x00000943, 0x00000001); -+ nv_icmd(dev, 0x000007c5, 0x00010001); -+ nv_icmd(dev, 0x00000834, 0x00000001); -+ nv_icmd(dev, 0x000007c7, 0x00000001); -+ nv_icmd(dev, 0x0001e100, 0x00000001); -+ nv_icmd(dev, 0x00001000, 0x00000001); -+ nv_icmd(dev, 0x0000080c, 0x00000002); -+ nv_icmd(dev, 0x0000080d, 0x00000100); -+ nv_icmd(dev, 0x0000080e, 0x00000100); -+ nv_icmd(dev, 0x0000080f, 0x00000001); -+ nv_icmd(dev, 0x00000823, 0x00000002); -+ nv_icmd(dev, 0x00000824, 0x00000100); -+ nv_icmd(dev, 0x00000825, 0x00000100); -+ nv_icmd(dev, 0x00000826, 0x00000001); -+ nv_icmd(dev, 0x0001e100, 0x00000001); -+ nv_wr32(dev, 0x400208, 0x00000000); -+ nv_wr32(dev, 0x404154, 0x00000400); -+ -+ nvc0_grctx_generate_9097(dev); -+ nvc0_grctx_generate_902d(dev); -+ nvc0_grctx_generate_9039(dev); -+ nvc0_grctx_generate_90c0(dev); -+ -+ nv_wr32(dev, 0x000260, r000260); -+ return 0; -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_instmem.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_instmem.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_instmem.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_instmem.c 2011-01-07 14:22:17.000000000 +0100 -@@ -25,206 +25,207 @@ - #include "drmP.h" - - #include "nouveau_drv.h" -+#include "nouveau_vm.h" -+ -+struct nvc0_instmem_priv { -+ struct nouveau_gpuobj *bar1_pgd; -+ struct nouveau_channel *bar1; -+ struct nouveau_gpuobj *bar3_pgd; -+ struct nouveau_channel *bar3; -+ struct nouveau_gpuobj *chan_pgd; -+}; - - int --nvc0_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, -- uint32_t *size) -+nvc0_instmem_suspend(struct drm_device *dev) - { -- int ret; -- -- *size = ALIGN(*size, 4096); -- if (*size == 0) -- return -EINVAL; -- -- ret = nouveau_bo_new(dev, NULL, *size, 0, TTM_PL_FLAG_VRAM, 0, 0x0000, -- true, false, &gpuobj->im_backing); -- if (ret) { -- NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret); -- return ret; -- } -- -- ret = nouveau_bo_pin(gpuobj->im_backing, TTM_PL_FLAG_VRAM); -- if (ret) { -- NV_ERROR(dev, "error pinning PRAMIN backing VRAM: %d\n", ret); -- nouveau_bo_ref(NULL, &gpuobj->im_backing); -- return ret; -- } -+ struct drm_nouveau_private *dev_priv = dev->dev_private; - -- gpuobj->vinst = gpuobj->im_backing->bo.mem.start << PAGE_SHIFT; -+ dev_priv->ramin_available = false; - return 0; - } - - void --nvc0_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) -+nvc0_instmem_resume(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv; - -- if (gpuobj && gpuobj->im_backing) { -- if (gpuobj->im_bound) -- dev_priv->engine.instmem.unbind(dev, gpuobj); -- nouveau_bo_unpin(gpuobj->im_backing); -- nouveau_bo_ref(NULL, &gpuobj->im_backing); -- gpuobj->im_backing = NULL; -- } -+ nv_mask(dev, 0x100c80, 0x00000001, 0x00000000); -+ nv_wr32(dev, 0x001704, 0x80000000 | priv->bar1->ramin->vinst >> 12); -+ nv_wr32(dev, 0x001714, 0xc0000000 | priv->bar3->ramin->vinst >> 12); -+ dev_priv->ramin_available = true; - } - --int --nvc0_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) -+static void -+nvc0_channel_del(struct nouveau_channel **pchan) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t pte, pte_end; -- uint64_t vram; -+ struct nouveau_channel *chan; - -- if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) -- return -EINVAL; -+ chan = *pchan; -+ *pchan = NULL; -+ if (!chan) -+ return; - -- NV_DEBUG(dev, "st=0x%lx sz=0x%lx\n", -- gpuobj->im_pramin->start, gpuobj->im_pramin->size); -- -- pte = gpuobj->im_pramin->start >> 12; -- pte_end = (gpuobj->im_pramin->size >> 12) + pte; -- vram = gpuobj->vinst; -- -- NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", -- gpuobj->im_pramin->start, pte, pte_end); -- NV_DEBUG(dev, "first vram page: 0x%010llx\n", gpuobj->vinst); -- -- while (pte < pte_end) { -- nv_wr32(dev, 0x702000 + (pte * 8), (vram >> 8) | 1); -- nv_wr32(dev, 0x702004 + (pte * 8), 0); -- vram += 4096; -- pte++; -- } -- dev_priv->engine.instmem.flush(dev); -- -- if (1) { -- u32 chan = nv_rd32(dev, 0x1700) << 16; -- nv_wr32(dev, 0x100cb8, (chan + 0x1000) >> 8); -- nv_wr32(dev, 0x100cbc, 0x80000005); -- } -- -- gpuobj->im_bound = 1; -- return 0; -+ nouveau_vm_ref(NULL, &chan->vm, NULL); -+ if (chan->ramin_heap.free_stack.next) -+ drm_mm_takedown(&chan->ramin_heap); -+ nouveau_gpuobj_ref(NULL, &chan->ramin); -+ kfree(chan); - } - --int --nvc0_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) -+static int -+nvc0_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm, -+ struct nouveau_channel **pchan, -+ struct nouveau_gpuobj *pgd, u64 vm_size) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t pte, pte_end; -+ struct nouveau_channel *chan; -+ int ret; - -- if (gpuobj->im_bound == 0) -- return -EINVAL; -+ chan = kzalloc(sizeof(*chan), GFP_KERNEL); -+ if (!chan) -+ return -ENOMEM; -+ chan->dev = dev; - -- pte = gpuobj->im_pramin->start >> 12; -- pte_end = (gpuobj->im_pramin->size >> 12) + pte; -- while (pte < pte_end) { -- nv_wr32(dev, 0x702000 + (pte * 8), 0); -- nv_wr32(dev, 0x702004 + (pte * 8), 0); -- pte++; -+ ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin); -+ if (ret) { -+ nvc0_channel_del(&chan); -+ return ret; - } -- dev_priv->engine.instmem.flush(dev); - -- gpuobj->im_bound = 0; -- return 0; --} -- --void --nvc0_instmem_flush(struct drm_device *dev) --{ -- nv_wr32(dev, 0x070000, 1); -- if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000)) -- NV_ERROR(dev, "PRAMIN flush timeout\n"); --} -+ ret = drm_mm_init(&chan->ramin_heap, 0x1000, size - 0x1000); -+ if (ret) { -+ nvc0_channel_del(&chan); -+ return ret; -+ } - --int --nvc0_instmem_suspend(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- u32 *buf; -- int i; -+ ret = nouveau_vm_ref(vm, &chan->vm, NULL); -+ if (ret) { -+ nvc0_channel_del(&chan); -+ return ret; -+ } - -- dev_priv->susres.ramin_copy = vmalloc(65536); -- if (!dev_priv->susres.ramin_copy) -- return -ENOMEM; -- buf = dev_priv->susres.ramin_copy; -+ nv_wo32(chan->ramin, 0x0200, lower_32_bits(pgd->vinst)); -+ nv_wo32(chan->ramin, 0x0204, upper_32_bits(pgd->vinst)); -+ nv_wo32(chan->ramin, 0x0208, lower_32_bits(vm_size - 1)); -+ nv_wo32(chan->ramin, 0x020c, upper_32_bits(vm_size - 1)); - -- for (i = 0; i < 65536; i += 4) -- buf[i/4] = nv_rd32(dev, NV04_PRAMIN + i); -+ *pchan = chan; - return 0; - } - --void --nvc0_instmem_resume(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- u32 *buf = dev_priv->susres.ramin_copy; -- u64 chan; -- int i; -- -- chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram; -- nv_wr32(dev, 0x001700, chan >> 16); -- -- for (i = 0; i < 65536; i += 4) -- nv_wr32(dev, NV04_PRAMIN + i, buf[i/4]); -- vfree(dev_priv->susres.ramin_copy); -- dev_priv->susres.ramin_copy = NULL; -- -- nv_wr32(dev, 0x001714, 0xc0000000 | (chan >> 12)); --} -- - int - nvc0_instmem_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- u64 chan, pgt3, imem, lim3 = dev_priv->ramin_size - 1; -- int ret, i; -- -- dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024; -- chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram; -- imem = 4096 + 4096 + 32768; -- -- nv_wr32(dev, 0x001700, chan >> 16); -- -- /* channel setup */ -- nv_wr32(dev, 0x700200, lower_32_bits(chan + 0x1000)); -- nv_wr32(dev, 0x700204, upper_32_bits(chan + 0x1000)); -- nv_wr32(dev, 0x700208, lower_32_bits(lim3)); -- nv_wr32(dev, 0x70020c, upper_32_bits(lim3)); -- -- /* point pgd -> pgt */ -- nv_wr32(dev, 0x701000, 0); -- nv_wr32(dev, 0x701004, ((chan + 0x2000) >> 8) | 1); -- -- /* point pgt -> physical vram for channel */ -- pgt3 = 0x2000; -- for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4096, pgt3 += 8) { -- nv_wr32(dev, 0x700000 + pgt3, ((chan + i) >> 8) | 1); -- nv_wr32(dev, 0x700004 + pgt3, 0); -- } -+ struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; -+ struct pci_dev *pdev = dev->pdev; -+ struct nvc0_instmem_priv *priv; -+ struct nouveau_vm *vm = NULL; -+ int ret; - -- /* clear rest of pgt */ -- for (; i < dev_priv->ramin_size; i += 4096, pgt3 += 8) { -- nv_wr32(dev, 0x700000 + pgt3, 0); -- nv_wr32(dev, 0x700004 + pgt3, 0); -- } -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ pinstmem->priv = priv; - -- /* point bar3 at the channel */ -- nv_wr32(dev, 0x001714, 0xc0000000 | (chan >> 12)); -+ /* BAR3 VM */ -+ ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 3), 0, -+ &dev_priv->bar3_vm); -+ if (ret) -+ goto error; -+ -+ ret = nouveau_gpuobj_new(dev, NULL, -+ (pci_resource_len(pdev, 3) >> 12) * 8, 0, -+ NVOBJ_FLAG_DONT_MAP | -+ NVOBJ_FLAG_ZERO_ALLOC, -+ &dev_priv->bar3_vm->pgt[0].obj[0]); -+ if (ret) -+ goto error; -+ dev_priv->bar3_vm->pgt[0].refcount[0] = 1; -+ -+ nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]); -+ -+ ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, -+ NVOBJ_FLAG_ZERO_ALLOC, &priv->bar3_pgd); -+ if (ret) -+ goto error; -+ -+ ret = nouveau_vm_ref(dev_priv->bar3_vm, &vm, priv->bar3_pgd); -+ if (ret) -+ goto error; -+ nouveau_vm_ref(NULL, &vm, NULL); -+ -+ ret = nvc0_channel_new(dev, 8192, dev_priv->bar3_vm, &priv->bar3, -+ priv->bar3_pgd, pci_resource_len(dev->pdev, 3)); -+ if (ret) -+ goto error; -+ -+ /* BAR1 VM */ -+ ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 1), 0, &vm); -+ if (ret) -+ goto error; -+ -+ ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, -+ NVOBJ_FLAG_ZERO_ALLOC, &priv->bar1_pgd); -+ if (ret) -+ goto error; -+ -+ ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, priv->bar1_pgd); -+ if (ret) -+ goto error; -+ nouveau_vm_ref(NULL, &vm, NULL); -+ -+ ret = nvc0_channel_new(dev, 8192, dev_priv->bar1_vm, &priv->bar1, -+ priv->bar1_pgd, pci_resource_len(dev->pdev, 1)); -+ if (ret) -+ goto error; -+ -+ /* channel vm */ -+ ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, &vm); -+ if (ret) -+ goto error; -+ -+ ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, 0, &priv->chan_pgd); -+ if (ret) -+ goto error; - -- /* Global PRAMIN heap */ -- ret = drm_mm_init(&dev_priv->ramin_heap, imem, -- dev_priv->ramin_size - imem); -- if (ret) { -- NV_ERROR(dev, "Failed to init RAMIN heap\n"); -- return -ENOMEM; -- } -+ nouveau_vm_ref(vm, &dev_priv->chan_vm, priv->chan_pgd); -+ nouveau_vm_ref(NULL, &vm, NULL); - -+ nvc0_instmem_resume(dev); - return 0; -+error: -+ nvc0_instmem_takedown(dev); -+ return ret; - } - - void - nvc0_instmem_takedown(struct drm_device *dev) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv; -+ struct nouveau_vm *vm = NULL; -+ -+ nvc0_instmem_suspend(dev); -+ -+ 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); -+ -+ nvc0_channel_del(&priv->bar1); -+ nouveau_vm_ref(NULL, &dev_priv->bar1_vm, priv->bar1_pgd); -+ nouveau_gpuobj_ref(NULL, &priv->bar1_pgd); -+ -+ nvc0_channel_del(&priv->bar3); -+ nouveau_vm_ref(dev_priv->bar3_vm, &vm, NULL); -+ nouveau_vm_ref(NULL, &vm, priv->bar3_pgd); -+ nouveau_gpuobj_ref(NULL, &priv->bar3_pgd); -+ nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]); -+ nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL); -+ -+ dev_priv->engine.instmem.priv = NULL; -+ kfree(priv); - } - -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_vm.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_vm.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_vm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_vm.c 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,123 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+ -+#include "nouveau_drv.h" -+#include "nouveau_vm.h" -+ -+void -+nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 index, -+ struct nouveau_gpuobj *pgt[2]) -+{ -+ u32 pde[2] = { 0, 0 }; -+ -+ if (pgt[0]) -+ pde[1] = 0x00000001 | (pgt[0]->vinst >> 8); -+ if (pgt[1]) -+ pde[0] = 0x00000001 | (pgt[1]->vinst >> 8); -+ -+ nv_wo32(pgd, (index * 8) + 0, pde[0]); -+ nv_wo32(pgd, (index * 8) + 4, pde[1]); -+} -+ -+static inline u64 -+nvc0_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) -+{ -+ phys >>= 8; -+ -+ phys |= 0x00000001; /* present */ -+// if (vma->access & NV_MEM_ACCESS_SYS) -+// phys |= 0x00000002; -+ -+ phys |= ((u64)target << 32); -+ phys |= ((u64)memtype << 36); -+ -+ return phys; -+} -+ -+void -+nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, -+ struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys) -+{ -+ u32 next = 1 << (vma->node->type - 8); -+ -+ phys = nvc0_vm_addr(vma, phys, mem->memtype, 0); -+ pte <<= 3; -+ while (cnt--) { -+ nv_wo32(pgt, pte + 0, lower_32_bits(phys)); -+ nv_wo32(pgt, pte + 4, upper_32_bits(phys)); -+ phys += next; -+ pte += 8; -+ } -+} -+ -+void -+nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, -+ u32 pte, dma_addr_t *list, u32 cnt) -+{ -+ pte <<= 3; -+ while (cnt--) { -+ u64 phys = nvc0_vm_addr(vma, *list++, 0, 5); -+ nv_wo32(pgt, pte + 0, lower_32_bits(phys)); -+ nv_wo32(pgt, pte + 4, upper_32_bits(phys)); -+ pte += 8; -+ } -+} -+ -+void -+nvc0_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) -+{ -+ pte <<= 3; -+ while (cnt--) { -+ nv_wo32(pgt, pte + 0, 0x00000000); -+ nv_wo32(pgt, pte + 4, 0x00000000); -+ pte += 8; -+ } -+} -+ -+void -+nvc0_vm_flush(struct nouveau_vm *vm) -+{ -+ struct drm_nouveau_private *dev_priv = vm->dev->dev_private; -+ struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; -+ struct drm_device *dev = vm->dev; -+ struct nouveau_vm_pgd *vpgd; -+ u32 r100c80, engine; -+ -+ pinstmem->flush(vm->dev); -+ -+ if (vm == dev_priv->chan_vm) -+ engine = 1; -+ else -+ engine = 5; -+ -+ list_for_each_entry(vpgd, &vm->pgd_list, head) { -+ r100c80 = nv_rd32(dev, 0x100c80); -+ nv_wr32(dev, 0x100cb8, vpgd->obj->vinst >> 8); -+ nv_wr32(dev, 0x100cbc, 0x80000000 | engine); -+ if (!nv_wait(dev, 0x100c80, 0xffffffff, r100c80)) -+ NV_ERROR(dev, "vm flush timeout eng %d\n", engine); -+ } -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_vram.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_vram.c ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvc0_vram.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvc0_vram.c 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,99 @@ -+/* -+ * Copyright 2010 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+#include "nouveau_drv.h" -+#include "nouveau_mm.h" -+ -+bool -+nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags) -+{ -+ switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) { -+ case 0x0000: -+ case 0xfe00: -+ case 0xdb00: -+ case 0x1100: -+ return true; -+ default: -+ break; -+ } -+ -+ return false; -+} -+ -+int -+nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, -+ u32 type, struct nouveau_vram **pvram) -+{ -+ 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_node *r; -+ struct nouveau_vram *vram; -+ int ret; -+ -+ size >>= 12; -+ align >>= 12; -+ ncmin >>= 12; -+ -+ vram = kzalloc(sizeof(*vram), GFP_KERNEL); -+ if (!vram) -+ return -ENOMEM; -+ -+ INIT_LIST_HEAD(&vram->regions); -+ vram->dev = dev_priv->dev; -+ vram->memtype = type; -+ vram->size = size; -+ -+ mutex_lock(&mm->mutex); -+ do { -+ ret = nouveau_mm_get(mm, 1, size, ncmin, align, &r); -+ if (ret) { -+ mutex_unlock(&mm->mutex); -+ nv50_vram_del(dev, &vram); -+ return ret; -+ } -+ -+ list_add_tail(&r->rl_entry, &vram->regions); -+ size -= r->length; -+ } while (size); -+ mutex_unlock(&mm->mutex); -+ -+ r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); -+ vram->offset = (u64)r->offset << 12; -+ *pvram = vram; -+ return 0; -+} -+ -+int -+nvc0_vram_init(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ 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; -+} -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvreg.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvreg.h ---- linux-2.6.37-rc3/drivers/gpu/drm/nouveau/nvreg.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/nouveau/nvreg.h 2011-01-07 14:22:17.000000000 +0100 -@@ -153,7 +153,8 @@ - #define NV_PCRTC_START 0x00600800 - #define NV_PCRTC_CONFIG 0x00600804 - # define NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA (1 << 0) --# define NV_PCRTC_CONFIG_START_ADDRESS_HSYNC (2 << 0) -+# define NV04_PCRTC_CONFIG_START_ADDRESS_HSYNC (4 << 0) -+# define NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC (2 << 0) - #define NV_PCRTC_CURSOR_CONFIG 0x00600810 - # define NV_PCRTC_CURSOR_CONFIG_ENABLE_ENABLE (1 << 0) - # define NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE (1 << 4) -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/atombios.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/atombios.h ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/atombios.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/atombios.h 2011-01-07 14:22:17.000000000 +0100 -@@ -73,8 +73,18 @@ - #define ATOM_PPLL1 0 - #define ATOM_PPLL2 1 - #define ATOM_DCPLL 2 -+#define ATOM_PPLL0 2 -+#define ATOM_EXT_PLL1 8 -+#define ATOM_EXT_PLL2 9 -+#define ATOM_EXT_CLOCK 10 - #define ATOM_PPLL_INVALID 0xFF - -+#define ENCODER_REFCLK_SRC_P1PLL 0 -+#define ENCODER_REFCLK_SRC_P2PLL 1 -+#define ENCODER_REFCLK_SRC_DCPLL 2 -+#define ENCODER_REFCLK_SRC_EXTCLK 3 -+#define ENCODER_REFCLK_SRC_INVALID 0xFF -+ - #define ATOM_SCALER1 0 - #define ATOM_SCALER2 1 - -@@ -192,6 +202,9 @@ - /*Image can't be updated, while Driver needs to carry the new table! */ - }ATOM_COMMON_TABLE_HEADER; - -+/****************************************************************************/ -+// Structure stores the ROM header. -+/****************************************************************************/ - typedef struct _ATOM_ROM_HEADER - { - ATOM_COMMON_TABLE_HEADER sHeader; -@@ -221,6 +234,9 @@ - #define USHORT void* - #endif - -+/****************************************************************************/ -+// Structures used in Command.mtb -+/****************************************************************************/ - typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES{ - USHORT ASIC_Init; //Function Table, used by various SW components,latest version 1.1 - USHORT GetDisplaySurfaceSize; //Atomic Table, Used by Bios when enabling HW ICON -@@ -312,6 +328,7 @@ - #define SetUniphyInstance ASIC_StaticPwrMgtStatusChange - #define HPDInterruptService ReadHWAssistedI2CStatus - #define EnableVGA_Access GetSCLKOverMCLKRatio -+#define GetDispObjectInfo EnableYUV - - typedef struct _ATOM_MASTER_COMMAND_TABLE - { -@@ -357,6 +374,24 @@ - /****************************************************************************/ - #define COMPUTE_MEMORY_PLL_PARAM 1 - #define COMPUTE_ENGINE_PLL_PARAM 2 -+#define ADJUST_MC_SETTING_PARAM 3 -+ -+/****************************************************************************/ -+// Structures used by AdjustMemoryControllerTable -+/****************************************************************************/ -+typedef struct _ATOM_ADJUST_MEMORY_CLOCK_FREQ -+{ -+#if ATOM_BIG_ENDIAN -+ ULONG ulPointerReturnFlag:1; // BYTE_3[7]=1 - Return the pointer to the right Data Block; BYTE_3[7]=0 - Program the right Data Block -+ ULONG ulMemoryModuleNumber:7; // BYTE_3[6:0] -+ ULONG ulClockFreq:24; -+#else -+ ULONG ulClockFreq:24; -+ ULONG ulMemoryModuleNumber:7; // BYTE_3[6:0] -+ ULONG ulPointerReturnFlag:1; // BYTE_3[7]=1 - Return the pointer to the right Data Block; BYTE_3[7]=0 - Program the right Data Block -+#endif -+}ATOM_ADJUST_MEMORY_CLOCK_FREQ; -+#define POINTER_RETURN_FLAG 0x80 - - typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS - { -@@ -440,6 +475,26 @@ - #endif - }COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4; - -+typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5 -+{ -+ union -+ { -+ ATOM_COMPUTE_CLOCK_FREQ ulClock; //Input Parameter -+ ATOM_S_MPLL_FB_DIVIDER ulFbDiv; //Output Parameter -+ }; -+ UCHAR ucRefDiv; //Output Parameter -+ UCHAR ucPostDiv; //Output Parameter -+ union -+ { -+ UCHAR ucCntlFlag; //Output Flags -+ UCHAR ucInputFlag; //Input Flags. ucInputFlag[0] - Strobe(1)/Performance(0) mode -+ }; -+ UCHAR ucReserved; -+}COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5; -+ -+// ucInputFlag -+#define ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN 1 // 1-StrobeMode, 0-PerformanceMode -+ - typedef struct _DYNAMICE_MEMORY_SETTINGS_PARAMETER - { - ATOM_COMPUTE_CLOCK_FREQ ulClock; -@@ -583,6 +638,7 @@ - #define ATOM_ENCODER_CONFIG_DPLINKRATE_MASK 0x01 - #define ATOM_ENCODER_CONFIG_DPLINKRATE_1_62GHZ 0x00 - #define ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ 0x01 -+#define ATOM_ENCODER_CONFIG_DPLINKRATE_5_40GHZ 0x02 - #define ATOM_ENCODER_CONFIG_LINK_SEL_MASK 0x04 - #define ATOM_ENCODER_CONFIG_LINKA 0x00 - #define ATOM_ENCODER_CONFIG_LINKB 0x04 -@@ -608,6 +664,9 @@ - #define ATOM_ENCODER_MODE_TV 13 - #define ATOM_ENCODER_MODE_CV 14 - #define ATOM_ENCODER_MODE_CRT 15 -+#define ATOM_ENCODER_MODE_DVO 16 -+#define ATOM_ENCODER_MODE_DP_SST ATOM_ENCODER_MODE_DP // For DP1.2 -+#define ATOM_ENCODER_MODE_DP_MST 5 // For DP1.2 - - typedef struct _ATOM_DIG_ENCODER_CONFIG_V2 - { -@@ -661,6 +720,7 @@ - #define ATOM_ENCODER_CMD_DP_LINK_TRAINING_START 0x08 - #define ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1 0x09 - #define ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2 0x0a -+#define ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3 0x13 - #define ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE 0x0b - #define ATOM_ENCODER_CMD_DP_VIDEO_OFF 0x0c - #define ATOM_ENCODER_CMD_DP_VIDEO_ON 0x0d -@@ -671,24 +731,34 @@ - #define ATOM_ENCODER_STATUS_LINK_TRAINING_COMPLETE 0x10 - #define ATOM_ENCODER_STATUS_LINK_TRAINING_INCOMPLETE 0x00 - -+//ucTableFormatRevision=1 -+//ucTableContentRevision=3 - // Following function ENABLE sub-function will be used by driver when TMDS/HDMI/LVDS is used, disable function will be used by driver - typedef struct _ATOM_DIG_ENCODER_CONFIG_V3 - { - #if ATOM_BIG_ENDIAN - UCHAR ucReserved1:1; -- UCHAR ucDigSel:3; // =0: DIGA/B/C/D/E/F -+ UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F) - UCHAR ucReserved:3; - UCHAR ucDPLinkRate:1; // =0: 1.62Ghz, =1: 2.7Ghz - #else - UCHAR ucDPLinkRate:1; // =0: 1.62Ghz, =1: 2.7Ghz - UCHAR ucReserved:3; -- UCHAR ucDigSel:3; // =0: DIGA/B/C/D/E/F -+ UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F) - UCHAR ucReserved1:1; - #endif - }ATOM_DIG_ENCODER_CONFIG_V3; - -+#define ATOM_ENCODER_CONFIG_V3_DPLINKRATE_MASK 0x03 -+#define ATOM_ENCODER_CONFIG_V3_DPLINKRATE_1_62GHZ 0x00 -+#define ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ 0x01 - #define ATOM_ENCODER_CONFIG_V3_ENCODER_SEL 0x70 -- -+#define ATOM_ENCODER_CONFIG_V3_DIG0_ENCODER 0x00 -+#define ATOM_ENCODER_CONFIG_V3_DIG1_ENCODER 0x10 -+#define ATOM_ENCODER_CONFIG_V3_DIG2_ENCODER 0x20 -+#define ATOM_ENCODER_CONFIG_V3_DIG3_ENCODER 0x30 -+#define ATOM_ENCODER_CONFIG_V3_DIG4_ENCODER 0x40 -+#define ATOM_ENCODER_CONFIG_V3_DIG5_ENCODER 0x50 - - typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V3 - { -@@ -707,6 +777,56 @@ - UCHAR ucReserved; - }DIG_ENCODER_CONTROL_PARAMETERS_V3; - -+//ucTableFormatRevision=1 -+//ucTableContentRevision=4 -+// start from NI -+// Following function ENABLE sub-function will be used by driver when TMDS/HDMI/LVDS is used, disable function will be used by driver -+typedef struct _ATOM_DIG_ENCODER_CONFIG_V4 -+{ -+#if ATOM_BIG_ENDIAN -+ UCHAR ucReserved1:1; -+ UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F) -+ UCHAR ucReserved:2; -+ UCHAR ucDPLinkRate:2; // =0: 1.62Ghz, =1: 2.7Ghz, 2=5.4Ghz <= Changed comparing to previous version -+#else -+ UCHAR ucDPLinkRate:2; // =0: 1.62Ghz, =1: 2.7Ghz, 2=5.4Ghz <= Changed comparing to previous version -+ UCHAR ucReserved:2; -+ UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F) -+ UCHAR ucReserved1:1; -+#endif -+}ATOM_DIG_ENCODER_CONFIG_V4; -+ -+#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_MASK 0x03 -+#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ 0x00 -+#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ 0x01 -+#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ 0x02 -+#define ATOM_ENCODER_CONFIG_V4_ENCODER_SEL 0x70 -+#define ATOM_ENCODER_CONFIG_V4_DIG0_ENCODER 0x00 -+#define ATOM_ENCODER_CONFIG_V4_DIG1_ENCODER 0x10 -+#define ATOM_ENCODER_CONFIG_V4_DIG2_ENCODER 0x20 -+#define ATOM_ENCODER_CONFIG_V4_DIG3_ENCODER 0x30 -+#define ATOM_ENCODER_CONFIG_V4_DIG4_ENCODER 0x40 -+#define ATOM_ENCODER_CONFIG_V4_DIG5_ENCODER 0x50 -+ -+typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V4 -+{ -+ USHORT usPixelClock; // in 10KHz; for bios convenient -+ union{ -+ ATOM_DIG_ENCODER_CONFIG_V4 acConfig; -+ UCHAR ucConfig; -+ }; -+ UCHAR ucAction; -+ UCHAR ucEncoderMode; -+ // =0: DP encoder -+ // =1: LVDS encoder -+ // =2: DVI encoder -+ // =3: HDMI encoder -+ // =4: SDVO encoder -+ // =5: DP audio -+ UCHAR ucLaneNum; // how many lanes to enable -+ UCHAR ucBitPerColor; // only valid for DP mode when ucAction = ATOM_ENCODER_CMD_SETUP -+ UCHAR ucHPD_ID; // HPD ID (1-6). =0 means to skip HDP programming. New comparing to previous version -+}DIG_ENCODER_CONTROL_PARAMETERS_V4; - - // define ucBitPerColor: - #define PANEL_BPC_UNDEFINE 0x00 -@@ -893,6 +1013,7 @@ - #endif - }ATOM_DIG_TRANSMITTER_CONFIG_V3; - -+ - typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 - { - union -@@ -936,6 +1057,149 @@ - #define ATOM_TRANSMITTER_CONFIG_V3_TRANSMITTER2 0x40 //CD - #define ATOM_TRANSMITTER_CONFIG_V3_TRANSMITTER3 0x80 //EF - -+ -+/****************************************************************************/ -+// Structures used by UNIPHYTransmitterControlTable V1.4 -+// ASIC Families: NI -+// ucTableFormatRevision=1 -+// ucTableContentRevision=4 -+/****************************************************************************/ -+typedef struct _ATOM_DP_VS_MODE_V4 -+{ -+ UCHAR ucLaneSel; -+ union -+ { -+ UCHAR ucLaneSet; -+ struct { -+#if ATOM_BIG_ENDIAN -+ UCHAR ucPOST_CURSOR2:2; //Bit[7:6] Post Cursor2 Level <= New in V4 -+ UCHAR ucPRE_EMPHASIS:3; //Bit[5:3] Pre-emphasis Level -+ UCHAR ucVOLTAGE_SWING:3; //Bit[2:0] Voltage Swing Level -+#else -+ UCHAR ucVOLTAGE_SWING:3; //Bit[2:0] Voltage Swing Level -+ UCHAR ucPRE_EMPHASIS:3; //Bit[5:3] Pre-emphasis Level -+ UCHAR ucPOST_CURSOR2:2; //Bit[7:6] Post Cursor2 Level <= New in V4 -+#endif -+ }; -+ }; -+}ATOM_DP_VS_MODE_V4; -+ -+typedef struct _ATOM_DIG_TRANSMITTER_CONFIG_V4 -+{ -+#if ATOM_BIG_ENDIAN -+ UCHAR ucTransmitterSel:2; //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) -+ // =1 Dig Transmitter 2 ( Uniphy CD ) -+ // =2 Dig Transmitter 3 ( Uniphy EF ) -+ UCHAR ucRefClkSource:2; //bit5:4: PPLL1 =0, PPLL2=1, DCPLL=2, EXT_CLK=3 <= New -+ UCHAR ucEncoderSel:1; //bit3=0: Data/Clk path source from DIGA/C/E. =1: Data/clk path source from DIGB/D/F -+ UCHAR ucLinkSel:1; //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E -+ // =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F -+ UCHAR fCoherentMode:1; //bit1=1: Coherent Mode ( for DVI/HDMI mode ) -+ UCHAR fDualLinkConnector:1; //bit0=1: Dual Link DVI connector -+#else -+ UCHAR fDualLinkConnector:1; //bit0=1: Dual Link DVI connector -+ UCHAR fCoherentMode:1; //bit1=1: Coherent Mode ( for DVI/HDMI mode ) -+ UCHAR ucLinkSel:1; //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E -+ // =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F -+ UCHAR ucEncoderSel:1; //bit3=0: Data/Clk path source from DIGA/C/E. =1: Data/clk path source from DIGB/D/F -+ UCHAR ucRefClkSource:2; //bit5:4: PPLL1 =0, PPLL2=1, DCPLL=2, EXT_CLK=3 <= New -+ UCHAR ucTransmitterSel:2; //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) -+ // =1 Dig Transmitter 2 ( Uniphy CD ) -+ // =2 Dig Transmitter 3 ( Uniphy EF ) -+#endif -+}ATOM_DIG_TRANSMITTER_CONFIG_V4; -+ -+typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 -+{ -+ union -+ { -+ USHORT usPixelClock; // in 10KHz; for bios convenient -+ USHORT usInitInfo; // when init uniphy,lower 8bit is used for connector type defined in objectid.h -+ ATOM_DP_VS_MODE_V4 asMode; // DP Voltage swing mode Redefined comparing to previous version -+ }; -+ union -+ { -+ ATOM_DIG_TRANSMITTER_CONFIG_V4 acConfig; -+ UCHAR ucConfig; -+ }; -+ UCHAR ucAction; // define as ATOM_TRANSMITER_ACTION_XXX -+ UCHAR ucLaneNum; -+ UCHAR ucReserved[3]; -+}DIG_TRANSMITTER_CONTROL_PARAMETERS_V4; -+ -+//ucConfig -+//Bit0 -+#define ATOM_TRANSMITTER_CONFIG_V4_DUAL_LINK_CONNECTOR 0x01 -+//Bit1 -+#define ATOM_TRANSMITTER_CONFIG_V4_COHERENT 0x02 -+//Bit2 -+#define ATOM_TRANSMITTER_CONFIG_V4_LINK_SEL_MASK 0x04 -+#define ATOM_TRANSMITTER_CONFIG_V4_LINKA 0x00 -+#define ATOM_TRANSMITTER_CONFIG_V4_LINKB 0x04 -+// Bit3 -+#define ATOM_TRANSMITTER_CONFIG_V4_ENCODER_SEL_MASK 0x08 -+#define ATOM_TRANSMITTER_CONFIG_V4_DIG1_ENCODER 0x00 -+#define ATOM_TRANSMITTER_CONFIG_V4_DIG2_ENCODER 0x08 -+// Bit5:4 -+#define ATOM_TRANSMITTER_CONFIG_V4_REFCLK_SEL_MASK 0x30 -+#define ATOM_TRANSMITTER_CONFIG_V4_P1PLL 0x00 -+#define ATOM_TRANSMITTER_CONFIG_V4_P2PLL 0x10 -+#define ATOM_TRANSMITTER_CONFIG_V4_DCPLL 0x20 // New in _V4 -+#define ATOM_TRANSMITTER_CONFIG_V4_REFCLK_SRC_EXT 0x30 // Changed comparing to V3 -+// Bit7:6 -+#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER_SEL_MASK 0xC0 -+#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER1 0x00 //AB -+#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER2 0x40 //CD -+#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER3 0x80 //EF -+ -+ -+/****************************************************************************/ -+// Structures used by ExternalEncoderControlTable V1.3 -+// ASIC Families: Evergreen, Llano, NI -+// ucTableFormatRevision=1 -+// ucTableContentRevision=3 -+/****************************************************************************/ -+ -+typedef struct _EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 -+{ -+ union{ -+ USHORT usPixelClock; // pixel clock in 10Khz, valid when ucAction=SETUP/ENABLE_OUTPUT -+ USHORT usConnectorId; // connector id, valid when ucAction = INIT -+ }; -+ UCHAR ucConfig; // indicate which encoder, and DP link rate when ucAction = SETUP/ENABLE_OUTPUT -+ UCHAR ucAction; // -+ UCHAR ucEncoderMode; // encoder mode, only used when ucAction = SETUP/ENABLE_OUTPUT -+ UCHAR ucLaneNum; // lane number, only used when ucAction = SETUP/ENABLE_OUTPUT -+ UCHAR ucBitPerColor; // output bit per color, only valid when ucAction = SETUP/ENABLE_OUTPUT and ucEncodeMode= DP -+ UCHAR ucReserved; -+}EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3; -+ -+// ucAction -+#define EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT 0x00 -+#define EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT 0x01 -+#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT 0x07 -+#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP 0x0f -+#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF 0x10 -+#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING 0x11 -+#define EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION 0x12 -+ -+// ucConfig -+#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_MASK 0x03 -+#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_1_62GHZ 0x00 -+#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ 0x01 -+#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ 0x02 -+#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER_SEL_MASK 0x70 -+#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER1 0x00 -+#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER2 0x10 -+#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER3 0x20 -+ -+typedef struct _EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 -+{ -+ EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 sExtEncoder; -+ ULONG ulReserved[2]; -+}EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3; -+ -+ - /****************************************************************************/ - // Structures used by DAC1OuputControlTable - // DAC2OuputControlTable -@@ -1142,6 +1406,7 @@ - #define PIXEL_CLOCK_V4_MISC_SS_ENABLE 0x10 - #define PIXEL_CLOCK_V4_MISC_COHERENT_MODE 0x20 - -+ - typedef struct _PIXEL_CLOCK_PARAMETERS_V3 - { - USHORT usPixelClock; // in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div) -@@ -1202,6 +1467,55 @@ - #define PIXEL_CLOCK_V5_MISC_HDMI_32BPP 0x08 - #define PIXEL_CLOCK_V5_MISC_REF_DIV_SRC 0x10 - -+typedef struct _CRTC_PIXEL_CLOCK_FREQ -+{ -+#if ATOM_BIG_ENDIAN -+ ULONG ucCRTC:8; // ATOM_CRTC1~6, indicate the CRTC controller to -+ // drive the pixel clock. not used for DCPLL case. -+ ULONG ulPixelClock:24; // target the pixel clock to drive the CRTC timing. -+ // 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to previous version. -+#else -+ ULONG ulPixelClock:24; // target the pixel clock to drive the CRTC timing. -+ // 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to previous version. -+ ULONG ucCRTC:8; // ATOM_CRTC1~6, indicate the CRTC controller to -+ // drive the pixel clock. not used for DCPLL case. -+#endif -+}CRTC_PIXEL_CLOCK_FREQ; -+ -+typedef struct _PIXEL_CLOCK_PARAMETERS_V6 -+{ -+ union{ -+ CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq; // pixel clock and CRTC id frequency -+ ULONG ulDispEngClkFreq; // dispclk frequency -+ }; -+ USHORT usFbDiv; // feedback divider integer part. -+ UCHAR ucPostDiv; // post divider. -+ UCHAR ucRefDiv; // Reference divider -+ UCHAR ucPpll; // ATOM_PPLL1/ATOM_PPLL2/ATOM_DCPLL -+ UCHAR ucTransmitterID; // ASIC encoder id defined in objectId.h, -+ // indicate which graphic encoder will be used. -+ UCHAR ucEncoderMode; // Encoder mode: -+ UCHAR ucMiscInfo; // bit[0]= Force program PPLL -+ // bit[1]= when VGA timing is used. -+ // bit[3:2]= HDMI panel bit depth: =0: 24bpp =1:30bpp, =2:32bpp -+ // bit[4]= RefClock source for PPLL. -+ // =0: XTLAIN( default mode ) -+ // =1: other external clock source, which is pre-defined -+ // by VBIOS depend on the feature required. -+ // bit[7:5]: reserved. -+ ULONG ulFbDivDecFrac; // 20 bit feedback divider decimal fraction part, range from 1~999999 ( 0.000001 to 0.999999 ) -+ -+}PIXEL_CLOCK_PARAMETERS_V6; -+ -+#define PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL 0x01 -+#define PIXEL_CLOCK_V6_MISC_VGA_MODE 0x02 -+#define PIXEL_CLOCK_V6_MISC_HDMI_BPP_MASK 0x0c -+#define PIXEL_CLOCK_V6_MISC_HDMI_24BPP 0x00 -+#define PIXEL_CLOCK_V6_MISC_HDMI_36BPP 0x04 -+#define PIXEL_CLOCK_V6_MISC_HDMI_30BPP 0x08 -+#define PIXEL_CLOCK_V6_MISC_HDMI_48BPP 0x0c -+#define PIXEL_CLOCK_V6_MISC_REF_DIV_SRC 0x10 -+ - typedef struct _GET_DISP_PLL_STATUS_INPUT_PARAMETERS_V2 - { - PIXEL_CLOCK_PARAMETERS_V3 sDispClkInput; -@@ -1241,10 +1555,11 @@ - typedef struct _ADJUST_DISPLAY_PLL_INPUT_PARAMETERS_V3 - { - USHORT usPixelClock; // target pixel clock -- UCHAR ucTransmitterID; // transmitter id defined in objectid.h -+ UCHAR ucTransmitterID; // GPU transmitter id defined in objectid.h - UCHAR ucEncodeMode; // encoder mode: CRT, LVDS, DP, TMDS or HDMI - UCHAR ucDispPllConfig; // display pll configure parameter defined as following DISPPLL_CONFIG_XXXX -- UCHAR ucReserved[3]; -+ UCHAR ucExtTransmitterID; // external encoder id. -+ UCHAR ucReserved[2]; - }ADJUST_DISPLAY_PLL_INPUT_PARAMETERS_V3; - - // usDispPllConfig v1.2 for RoadRunner -@@ -1358,6 +1673,7 @@ - /**************************************************************************/ - #define SPEED_FAN_CONTROL_PS_ALLOCATION WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS - -+ - /****************************************************************************/ - // Structures used by PowerConnectorDetectionTable - /****************************************************************************/ -@@ -1438,6 +1754,31 @@ - #define ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK 0x0F00 - #define ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT 8 - -+// Used by DCE5.0 -+ typedef struct _ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 -+{ -+ USHORT usSpreadSpectrumAmountFrac; // SS_AMOUNT_DSFRAC New in DCE5.0 -+ UCHAR ucSpreadSpectrumType; // Bit[0]: 0-Down Spread,1-Center Spread. -+ // Bit[1]: 1-Ext. 0-Int. -+ // Bit[3:2]: =0 P1PLL =1 P2PLL =2 DCPLL -+ // Bits[7:4] reserved -+ UCHAR ucEnable; // ATOM_ENABLE or ATOM_DISABLE -+ USHORT usSpreadSpectrumAmount; // Includes SS_AMOUNT_FBDIV[7:0] and SS_AMOUNT_NFRAC_SLIP[11:8] -+ USHORT usSpreadSpectrumStep; // SS_STEP_SIZE_DSFRAC -+}ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3; -+ -+#define ATOM_PPLL_SS_TYPE_V3_DOWN_SPREAD 0x00 -+#define ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD 0x01 -+#define ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD 0x02 -+#define ATOM_PPLL_SS_TYPE_V3_PPLL_SEL_MASK 0x0c -+#define ATOM_PPLL_SS_TYPE_V3_P1PLL 0x00 -+#define ATOM_PPLL_SS_TYPE_V3_P2PLL 0x04 -+#define ATOM_PPLL_SS_TYPE_V3_DCPLL 0x08 -+#define ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK 0x00FF -+#define ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT 0 -+#define ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK 0x0F00 -+#define ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT 8 -+ - #define ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION ENABLE_SPREAD_SPECTRUM_ON_PPLL - - /**************************************************************************/ -@@ -1706,7 +2047,7 @@ - USHORT StandardVESA_Timing; // Only used by Bios - USHORT FirmwareInfo; // Shared by various SW components,latest version 1.4 - USHORT DAC_Info; // Will be obsolete from R600 -- USHORT LVDS_Info; // Shared by various SW components,latest version 1.1 -+ USHORT LCD_Info; // Shared by various SW components,latest version 1.3, was called LVDS_Info - USHORT TMDS_Info; // Will be obsolete from R600 - USHORT AnalogTV_Info; // Shared by various SW components,latest version 1.1 - USHORT SupportedDevicesInfo; // Will be obsolete from R600 -@@ -1736,12 +2077,16 @@ - USHORT PowerSourceInfo; // Shared by various SW components, latest versoin 1.1 - }ATOM_MASTER_LIST_OF_DATA_TABLES; - -+// For backward compatible -+#define LVDS_Info LCD_Info -+ - typedef struct _ATOM_MASTER_DATA_TABLE - { - ATOM_COMMON_TABLE_HEADER sHeader; - ATOM_MASTER_LIST_OF_DATA_TABLES ListOfDataTables; - }ATOM_MASTER_DATA_TABLE; - -+ - /****************************************************************************/ - // Structure used in MultimediaCapabilityInfoTable - /****************************************************************************/ -@@ -1776,6 +2121,7 @@ - UCHAR ucVideoInput4Info;// Video Input 4 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) - }ATOM_MULTIMEDIA_CONFIG_INFO; - -+ - /****************************************************************************/ - // Structures used in FirmwareInfoTable - /****************************************************************************/ -@@ -2031,8 +2377,47 @@ - UCHAR ucReserved4[3]; - }ATOM_FIRMWARE_INFO_V2_1; - -+//the structure below to be used from NI -+//ucTableFormatRevision=2 -+//ucTableContentRevision=2 -+typedef struct _ATOM_FIRMWARE_INFO_V2_2 -+{ -+ ATOM_COMMON_TABLE_HEADER sHeader; -+ ULONG ulFirmwareRevision; -+ ULONG ulDefaultEngineClock; //In 10Khz unit -+ ULONG ulDefaultMemoryClock; //In 10Khz unit -+ ULONG ulReserved[2]; -+ ULONG ulReserved1; //Was ulMaxEngineClockPLL_Output; //In 10Khz unit* -+ ULONG ulReserved2; //Was ulMaxMemoryClockPLL_Output; //In 10Khz unit* -+ ULONG ulMaxPixelClockPLL_Output; //In 10Khz unit -+ ULONG ulBinaryAlteredInfo; //Was ulASICMaxEngineClock ? -+ ULONG ulDefaultDispEngineClkFreq; //In 10Khz unit. This is the frequency before DCDTO, corresponding to usBootUpVDDCVoltage. -+ UCHAR ucReserved3; //Was ucASICMaxTemperature; -+ UCHAR ucMinAllowedBL_Level; -+ USHORT usBootUpVDDCVoltage; //In MV unit -+ USHORT usLcdMinPixelClockPLL_Output; // In MHz unit -+ USHORT usLcdMaxPixelClockPLL_Output; // In MHz unit -+ ULONG ulReserved4; //Was ulAsicMaximumVoltage -+ ULONG ulMinPixelClockPLL_Output; //In 10Khz unit -+ ULONG ulReserved5; //Was usMinEngineClockPLL_Input and usMaxEngineClockPLL_Input -+ ULONG ulReserved6; //Was usMinEngineClockPLL_Output and usMinMemoryClockPLL_Input -+ ULONG ulReserved7; //Was usMaxMemoryClockPLL_Input and usMinMemoryClockPLL_Output -+ USHORT usReserved11; //Was usMaxPixelClock; //In 10Khz unit, Max. Pclk used only for DAC -+ USHORT usMinPixelClockPLL_Input; //In 10Khz unit -+ USHORT usMaxPixelClockPLL_Input; //In 10Khz unit -+ USHORT usBootUpVDDCIVoltage; //In unit of mv; Was usMinPixelClockPLL_Output; -+ ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability; -+ USHORT usCoreReferenceClock; //In 10Khz unit -+ USHORT usMemoryReferenceClock; //In 10Khz unit -+ USHORT usUniphyDPModeExtClkFreq; //In 10Khz unit, if it is 0, In DP Mode Uniphy Input clock from internal PPLL, otherwise Input clock from external Spread clock -+ UCHAR ucMemoryModule_ID; //Indicate what is the board design -+ UCHAR ucReserved9[3]; -+ USHORT usBootUpMVDDCVoltage; //In unit of mv; Was usMinPixelClockPLL_Output; -+ USHORT usReserved12; -+ ULONG ulReserved10[3]; // New added comparing to previous version -+}ATOM_FIRMWARE_INFO_V2_2; - --#define ATOM_FIRMWARE_INFO_LAST ATOM_FIRMWARE_INFO_V2_1 -+#define ATOM_FIRMWARE_INFO_LAST ATOM_FIRMWARE_INFO_V2_2 - - /****************************************************************************/ - // Structures used in IntegratedSystemInfoTable -@@ -2212,7 +2597,7 @@ - ucDockingPinBit: which bit in this register to read the pin status; - ucDockingPinPolarity:Polarity of the pin when docked; - --ulCPUCapInfo: [7:0]=1:Griffin;[7:0]=2:Greyhound;[7:0]=3:K8, other bits reserved for now and must be 0x0 -+ulCPUCapInfo: [7:0]=1:Griffin;[7:0]=2:Greyhound;[7:0]=3:K8, [7:0]=4:Pharaoh, other bits reserved for now and must be 0x0 - - usNumberOfCyclesInPeriod:Indicate how many cycles when PWM duty is 100%. - -@@ -2250,6 +2635,14 @@ - usMinDownStreamHTLinkWidth: same as above. - */ - -+// ATOM_INTEGRATED_SYSTEM_INFO::ulCPUCapInfo - CPU type definition -+#define INTEGRATED_SYSTEM_INFO__UNKNOWN_CPU 0 -+#define INTEGRATED_SYSTEM_INFO__AMD_CPU__GRIFFIN 1 -+#define INTEGRATED_SYSTEM_INFO__AMD_CPU__GREYHOUND 2 -+#define INTEGRATED_SYSTEM_INFO__AMD_CPU__K8 3 -+#define INTEGRATED_SYSTEM_INFO__AMD_CPU__PHARAOH 4 -+ -+#define INTEGRATED_SYSTEM_INFO__AMD_CPU__MAX_CODE INTEGRATED_SYSTEM_INFO__AMD_CPU__PHARAOH // this deff reflects max defined CPU code - - #define SYSTEM_CONFIG_POWEREXPRESS_ENABLE 0x00000001 - #define SYSTEM_CONFIG_RUN_AT_OVERDRIVE_ENGINE 0x00000002 -@@ -2778,8 +3171,88 @@ - #define PANEL_RANDOM_DITHER 0x80 - #define PANEL_RANDOM_DITHER_MASK 0x80 - -+#define ATOM_LVDS_INFO_LAST ATOM_LVDS_INFO_V12 // no need to change this -+ -+/****************************************************************************/ -+// Structures used by LCD_InfoTable V1.3 Note: previous version was called ATOM_LVDS_INFO_V12 -+// ASIC Families: NI -+// ucTableFormatRevision=1 -+// ucTableContentRevision=3 -+/****************************************************************************/ -+typedef struct _ATOM_LCD_INFO_V13 -+{ -+ ATOM_COMMON_TABLE_HEADER sHeader; -+ ATOM_DTD_FORMAT sLCDTiming; -+ USHORT usExtInfoTableOffset; -+ USHORT usSupportedRefreshRate; //Refer to panel info table in ATOMBIOS extension Spec. -+ ULONG ulReserved0; -+ UCHAR ucLCD_Misc; // Reorganized in V13 -+ // Bit0: {=0:single, =1:dual}, -+ // Bit1: {=0:LDI format for RGB888, =1 FPDI format for RGB888} // was {=0:666RGB, =1:888RGB}, -+ // Bit3:2: {Grey level} -+ // Bit6:4 Color Bit Depth definition (see below definition in EDID V1.4 @BYTE 14h) -+ // Bit7 Reserved. was for ATOM_PANEL_MISC_API_ENABLED, still need it? -+ UCHAR ucPanelDefaultRefreshRate; -+ UCHAR ucPanelIdentification; -+ UCHAR ucSS_Id; -+ USHORT usLCDVenderID; -+ USHORT usLCDProductID; -+ UCHAR ucLCDPanel_SpecialHandlingCap; // Reorganized in V13 -+ // Bit0: Once DAL sees this CAP is set, it will read EDID from LCD on its own -+ // Bit1: See LCDPANEL_CAP_DRR_SUPPORTED -+ // Bit2: a quick reference whether an embadded panel (LCD1 ) is LVDS (0) or eDP (1) -+ // Bit7-3: Reserved -+ UCHAR ucPanelInfoSize; // start from ATOM_DTD_FORMAT to end of panel info, include ExtInfoTable -+ USHORT usBacklightPWM; // Backlight PWM in Hz. New in _V13 -+ -+ UCHAR ucPowerSequenceDIGONtoDE_in4Ms; -+ UCHAR ucPowerSequenceDEtoVARY_BL_in4Ms; -+ UCHAR ucPowerSequenceDEtoDIGON_in4Ms; -+ UCHAR ucPowerSequenceVARY_BLtoDE_in4Ms; -+ -+ UCHAR ucOffDelay_in4Ms; -+ UCHAR ucPowerSequenceVARY_BLtoBLON_in4Ms; -+ UCHAR ucPowerSequenceBLONtoVARY_BL_in4Ms; -+ UCHAR ucReserved1; -+ -+ ULONG ulReserved[4]; -+}ATOM_LCD_INFO_V13; -+ -+#define ATOM_LCD_INFO_LAST ATOM_LCD_INFO_V13 -+ -+//Definitions for ucLCD_Misc -+#define ATOM_PANEL_MISC_V13_DUAL 0x00000001 -+#define ATOM_PANEL_MISC_V13_FPDI 0x00000002 -+#define ATOM_PANEL_MISC_V13_GREY_LEVEL 0x0000000C -+#define ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT 2 -+#define ATOM_PANEL_MISC_V13_COLOR_BIT_DEPTH_MASK 0x70 -+#define ATOM_PANEL_MISC_V13_6BIT_PER_COLOR 0x10 -+#define ATOM_PANEL_MISC_V13_8BIT_PER_COLOR 0x20 -+ -+//Color Bit Depth definition in EDID V1.4 @BYTE 14h -+//Bit 6 5 4 -+ // 0 0 0 - Color bit depth is undefined -+ // 0 0 1 - 6 Bits per Primary Color -+ // 0 1 0 - 8 Bits per Primary Color -+ // 0 1 1 - 10 Bits per Primary Color -+ // 1 0 0 - 12 Bits per Primary Color -+ // 1 0 1 - 14 Bits per Primary Color -+ // 1 1 0 - 16 Bits per Primary Color -+ // 1 1 1 - Reserved -+ -+//Definitions for ucLCDPanel_SpecialHandlingCap: -+ -+//Once DAL sees this CAP is set, it will read EDID from LCD on its own instead of using sLCDTiming in ATOM_LVDS_INFO_V12. -+//Other entries in ATOM_LVDS_INFO_V12 are still valid/useful to DAL -+#define LCDPANEL_CAP_V13_READ_EDID 0x1 // = LCDPANEL_CAP_READ_EDID no change comparing to previous version - --#define ATOM_LVDS_INFO_LAST ATOM_LVDS_INFO_V12 -+//If a design supports DRR (dynamic refresh rate) on internal panels (LVDS or EDP), this cap is set in ucLCDPanel_SpecialHandlingCap together -+//with multiple supported refresh rates@usSupportedRefreshRate. This cap should not be set when only slow refresh rate is supported (static -+//refresh rate switch by SW. This is only valid from ATOM_LVDS_INFO_V12 -+#define LCDPANEL_CAP_V13_DRR_SUPPORTED 0x2 // = LCDPANEL_CAP_DRR_SUPPORTED no change comparing to previous version -+ -+//Use this cap bit for a quick reference whether an embadded panel (LCD1 ) is LVDS or eDP. -+#define LCDPANEL_CAP_V13_eDP 0x4 // = LCDPANEL_CAP_eDP no change comparing to previous version - - typedef struct _ATOM_PATCH_RECORD_MODE - { -@@ -2944,9 +3417,9 @@ - #define MAX_DTD_MODE_IN_VRAM 6 - #define ATOM_DTD_MODE_SUPPORT_TBL_SIZE (MAX_DTD_MODE_IN_VRAM*28) //28= (SIZEOF ATOM_DTD_FORMAT) - #define ATOM_STD_MODE_SUPPORT_TBL_SIZE 32*8 //32 is a predefined number,8= (SIZEOF ATOM_STD_FORMAT) --#define DFP_ENCODER_TYPE_OFFSET 0x80 --#define DP_ENCODER_LANE_NUM_OFFSET 0x84 --#define DP_ENCODER_LINK_RATE_OFFSET 0x88 -+//20 bytes for Encoder Type and DPCD in STD EDID area -+#define DFP_ENCODER_TYPE_OFFSET (ATOM_EDID_RAW_DATASIZE + ATOM_DTD_MODE_SUPPORT_TBL_SIZE + ATOM_STD_MODE_SUPPORT_TBL_SIZE - 20) -+#define ATOM_DP_DPCD_OFFSET (DFP_ENCODER_TYPE_OFFSET + 4 ) - - #define ATOM_HWICON1_SURFACE_ADDR 0 - #define ATOM_HWICON2_SURFACE_ADDR (ATOM_HWICON1_SURFACE_ADDR + ATOM_HWICON_SURFACE_SIZE) -@@ -2997,14 +3470,16 @@ - #define ATOM_DFP5_DTD_MODE_TBL_ADDR (ATOM_DFP5_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) - #define ATOM_DFP5_STD_MODE_TBL_ADDR (ATOM_DFP5_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) - --#define ATOM_DP_TRAINING_TBL_ADDR (ATOM_DFP5_STD_MODE_TBL_ADDR+ATOM_STD_MODE_SUPPORT_TBL_SIZE) -+#define ATOM_DP_TRAINING_TBL_ADDR (ATOM_DFP5_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) - --#define ATOM_STACK_STORAGE_START (ATOM_DP_TRAINING_TBL_ADDR+256) --#define ATOM_STACK_STORAGE_END ATOM_STACK_STORAGE_START+512 -+#define ATOM_STACK_STORAGE_START (ATOM_DP_TRAINING_TBL_ADDR + 1024) -+#define ATOM_STACK_STORAGE_END ATOM_STACK_STORAGE_START + 512 - - //The size below is in Kb! - #define ATOM_VRAM_RESERVE_SIZE ((((ATOM_STACK_STORAGE_END - ATOM_HWICON1_SURFACE_ADDR)>>10)+4)&0xFFFC) - -+#define ATOM_VRAM_RESERVE_V2_SIZE 32 -+ - #define ATOM_VRAM_OPERATION_FLAGS_MASK 0xC0000000L - #define ATOM_VRAM_OPERATION_FLAGS_SHIFT 30 - #define ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION 0x1 -@@ -3206,6 +3681,15 @@ - USHORT usGraphicObjIds[1]; //1st Encoder Obj source from GPU to last Graphic Obj destinate to connector. - }ATOM_DISPLAY_OBJECT_PATH; - -+typedef struct _ATOM_DISPLAY_EXTERNAL_OBJECT_PATH -+{ -+ USHORT usDeviceTag; //supported device -+ USHORT usSize; //the size of ATOM_DISPLAY_OBJECT_PATH -+ USHORT usConnObjectId; //Connector Object ID -+ USHORT usGPUObjectId; //GPU ID -+ USHORT usGraphicObjIds[2]; //usGraphicObjIds[0]= GPU internal encoder, usGraphicObjIds[1]= external encoder -+}ATOM_DISPLAY_EXTERNAL_OBJECT_PATH; -+ - typedef struct _ATOM_DISPLAY_OBJECT_PATH_TABLE - { - UCHAR ucNumOfDispPath; -@@ -3261,6 +3745,47 @@ - #define EXT_AUXDDC_LUTINDEX_7 7 - #define MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES (EXT_AUXDDC_LUTINDEX_7+1) - -+//ucChannelMapping are defined as following -+//for DP connector, eDP, DP to VGA/LVDS -+//Bit[1:0]: Define which pin connect to DP connector DP_Lane0, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 -+//Bit[3:2]: Define which pin connect to DP connector DP_Lane1, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 -+//Bit[5:4]: Define which pin connect to DP connector DP_Lane2, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 -+//Bit[7:6]: Define which pin connect to DP connector DP_Lane3, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 -+typedef struct _ATOM_DP_CONN_CHANNEL_MAPPING -+{ -+#if ATOM_BIG_ENDIAN -+ UCHAR ucDP_Lane3_Source:2; -+ UCHAR ucDP_Lane2_Source:2; -+ UCHAR ucDP_Lane1_Source:2; -+ UCHAR ucDP_Lane0_Source:2; -+#else -+ UCHAR ucDP_Lane0_Source:2; -+ UCHAR ucDP_Lane1_Source:2; -+ UCHAR ucDP_Lane2_Source:2; -+ UCHAR ucDP_Lane3_Source:2; -+#endif -+}ATOM_DP_CONN_CHANNEL_MAPPING; -+ -+//for DVI/HDMI, in dual link case, both links have to have same mapping. -+//Bit[1:0]: Define which pin connect to DVI connector data Lane2, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 -+//Bit[3:2]: Define which pin connect to DVI connector data Lane1, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 -+//Bit[5:4]: Define which pin connect to DVI connector data Lane0, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 -+//Bit[7:6]: Define which pin connect to DVI connector clock lane, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 -+typedef struct _ATOM_DVI_CONN_CHANNEL_MAPPING -+{ -+#if ATOM_BIG_ENDIAN -+ UCHAR ucDVI_CLK_Source:2; -+ UCHAR ucDVI_DATA0_Source:2; -+ UCHAR ucDVI_DATA1_Source:2; -+ UCHAR ucDVI_DATA2_Source:2; -+#else -+ UCHAR ucDVI_DATA2_Source:2; -+ UCHAR ucDVI_DATA1_Source:2; -+ UCHAR ucDVI_DATA0_Source:2; -+ UCHAR ucDVI_CLK_Source:2; -+#endif -+}ATOM_DVI_CONN_CHANNEL_MAPPING; -+ - typedef struct _EXT_DISPLAY_PATH - { - USHORT usDeviceTag; //A bit vector to show what devices are supported -@@ -3269,7 +3794,13 @@ - UCHAR ucExtAUXDDCLutIndex; //An index into external AUX/DDC channel LUT - UCHAR ucExtHPDPINLutIndex; //An index into external HPD pin LUT - USHORT usExtEncoderObjId; //external encoder object id -- USHORT usReserved[3]; -+ union{ -+ UCHAR ucChannelMapping; // if ucChannelMapping=0, using default one to one mapping -+ ATOM_DP_CONN_CHANNEL_MAPPING asDPMapping; -+ ATOM_DVI_CONN_CHANNEL_MAPPING asDVIMapping; -+ }; -+ UCHAR ucReserved; -+ USHORT usReserved[2]; - }EXT_DISPLAY_PATH; - - #define NUMBER_OF_UCHAR_FOR_GUID 16 -@@ -3281,7 +3812,8 @@ - UCHAR ucGuid [NUMBER_OF_UCHAR_FOR_GUID]; // a GUID is a 16 byte long string - EXT_DISPLAY_PATH sPath[MAX_NUMBER_OF_EXT_DISPLAY_PATH]; // total of fixed 7 entries. - UCHAR ucChecksum; // a simple Checksum of the sum of whole structure equal to 0x0. -- UCHAR Reserved [7]; // for potential expansion -+ UCHAR uc3DStereoPinId; // use for eDP panel -+ UCHAR Reserved [6]; // for potential expansion - }ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO; - - //Related definitions, all records are differnt but they have a commond header -@@ -3311,10 +3843,11 @@ - #define ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE 17 //This is for the case when connectors are not known to object table - #define ATOM_OBJECT_LINK_RECORD_TYPE 18 //Once this record is present under one object, it indicats the oobject is linked to another obj described by the record - #define ATOM_CONNECTOR_REMOTE_CAP_RECORD_TYPE 19 -+#define ATOM_ENCODER_CAP_RECORD_TYPE 20 - - - //Must be updated when new record type is added,equal to that record definition! --#define ATOM_MAX_OBJECT_RECORD_NUMBER ATOM_CONNECTOR_REMOTE_CAP_RECORD_TYPE -+#define ATOM_MAX_OBJECT_RECORD_NUMBER ATOM_ENCODER_CAP_RECORD_TYPE - - typedef struct _ATOM_I2C_RECORD - { -@@ -3441,6 +3974,26 @@ - UCHAR ucPadding[2]; - }ATOM_ENCODER_DVO_CF_RECORD; - -+// Bit maps for ATOM_ENCODER_CAP_RECORD.ucEncoderCap -+#define ATOM_ENCODER_CAP_RECORD_HBR2 0x01 // DP1.2 HBR2 is supported by this path -+ -+typedef struct _ATOM_ENCODER_CAP_RECORD -+{ -+ ATOM_COMMON_RECORD_HEADER sheader; -+ union { -+ USHORT usEncoderCap; -+ struct { -+#if ATOM_BIG_ENDIAN -+ USHORT usReserved:15; // Bit1-15 may be defined for other capability in future -+ USHORT usHBR2Cap:1; // Bit0 is for DP1.2 HBR2 capability. -+#else -+ USHORT usHBR2Cap:1; // Bit0 is for DP1.2 HBR2 capability. -+ USHORT usReserved:15; // Bit1-15 may be defined for other capability in future -+#endif -+ }; -+ }; -+}ATOM_ENCODER_CAP_RECORD; -+ - // value for ATOM_CONNECTOR_CF_RECORD.ucConnectedDvoBundle - #define ATOM_CONNECTOR_CF_RECORD_CONNECTED_UPPER12BITBUNDLEA 1 - #define ATOM_CONNECTOR_CF_RECORD_CONNECTED_LOWER12BITBUNDLEB 2 -@@ -3580,6 +4133,11 @@ - #define VOLTAGE_CONTROL_ID_DAC 0x02 //I2C control, used for R5xx/R6xx MVDDC,MVDDQ or VDDCI - #define VOLTAGE_CONTROL_ID_VT116xM 0x03 //I2C control, used for R6xx Core Voltage - #define VOLTAGE_CONTROL_ID_DS4402 0x04 -+#define VOLTAGE_CONTROL_ID_UP6266 0x05 -+#define VOLTAGE_CONTROL_ID_SCORPIO 0x06 -+#define VOLTAGE_CONTROL_ID_VT1556M 0x07 -+#define VOLTAGE_CONTROL_ID_CHL822x 0x08 -+#define VOLTAGE_CONTROL_ID_VT1586M 0x09 - - typedef struct _ATOM_VOLTAGE_OBJECT - { -@@ -3670,66 +4228,157 @@ - #define POWER_SENSOR_GPIO 0x01 - #define POWER_SENSOR_I2C 0x02 - -+typedef struct _ATOM_CLK_VOLT_CAPABILITY -+{ -+ ULONG ulVoltageIndex; // The Voltage Index indicated by FUSE, same voltage index shared with SCLK DPM fuse table -+ ULONG ulMaximumSupportedCLK; // Maximum clock supported with specified voltage index, unit in 10kHz -+}ATOM_CLK_VOLT_CAPABILITY; -+ -+typedef struct _ATOM_AVAILABLE_SCLK_LIST -+{ -+ ULONG ulSupportedSCLK; // Maximum clock supported with specified voltage index, unit in 10kHz -+ USHORT usVoltageIndex; // The Voltage Index indicated by FUSE for specified SCLK -+ USHORT usVoltageID; // The Voltage ID indicated by FUSE for specified SCLK -+}ATOM_AVAILABLE_SCLK_LIST; -+ -+// ATOM_INTEGRATED_SYSTEM_INFO_V6 ulSystemConfig cap definition -+#define ATOM_IGP_INFO_V6_SYSTEM_CONFIG__PCIE_POWER_GATING_ENABLE 1 // refer to ulSystemConfig bit[0] -+ -+// this IntegrateSystemInfoTable is used for Liano/Ontario APU - typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 - { - ATOM_COMMON_TABLE_HEADER sHeader; - ULONG ulBootUpEngineClock; - ULONG ulDentistVCOFreq; - ULONG ulBootUpUMAClock; -- ULONG ulReserved1[8]; -+ ATOM_CLK_VOLT_CAPABILITY sDISPCLK_Voltage[4]; - ULONG ulBootUpReqDisplayVector; - ULONG ulOtherDisplayMisc; - ULONG ulGPUCapInfo; -- ULONG ulReserved2[3]; -+ ULONG ulSB_MMIO_Base_Addr; -+ USHORT usRequestedPWMFreqInHz; -+ UCHAR ucHtcTmpLmt; -+ UCHAR ucHtcHystLmt; -+ ULONG ulMinEngineClock; - ULONG ulSystemConfig; - ULONG ulCPUCapInfo; -- USHORT usMaxNBVoltage; -- USHORT usMinNBVoltage; -- USHORT usBootUpNBVoltage; -- USHORT usExtDispConnInfoOffset; -- UCHAR ucHtcTmpLmt; -- UCHAR ucTjOffset; -+ USHORT usNBP0Voltage; -+ USHORT usNBP1Voltage; -+ USHORT usBootUpNBVoltage; -+ USHORT usExtDispConnInfoOffset; -+ USHORT usPanelRefreshRateRange; - UCHAR ucMemoryType; - UCHAR ucUMAChannelNumber; - ULONG ulCSR_M3_ARB_CNTL_DEFAULT[10]; - ULONG ulCSR_M3_ARB_CNTL_UVD[10]; - ULONG ulCSR_M3_ARB_CNTL_FS3D[10]; -- ULONG ulReserved3[42]; -+ ATOM_AVAILABLE_SCLK_LIST sAvail_SCLK[5]; -+ ULONG ulGMCRestoreResetTime; -+ ULONG ulMinimumNClk; -+ ULONG ulIdleNClk; -+ ULONG ulDDR_DLL_PowerUpTime; -+ ULONG ulDDR_PLL_PowerUpTime; -+ USHORT usPCIEClkSSPercentage; -+ USHORT usPCIEClkSSType; -+ USHORT usLvdsSSPercentage; -+ USHORT usLvdsSSpreadRateIn10Hz; -+ USHORT usHDMISSPercentage; -+ USHORT usHDMISSpreadRateIn10Hz; -+ USHORT usDVISSPercentage; -+ USHORT usDVISSpreadRateIn10Hz; -+ ULONG ulReserved3[21]; - ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO sExtDispConnInfo; - }ATOM_INTEGRATED_SYSTEM_INFO_V6; - -+// ulGPUCapInfo -+#define INTEGRATED_SYSTEM_INFO_V6_GPUCAPINFO__TMDSHDMI_COHERENT_SINGLEPLL_MODE 0x01 -+#define INTEGRATED_SYSTEM_INFO_V6_GPUCAPINFO__DISABLE_AUX_HW_MODE_DETECTION 0x08 -+ -+// ulOtherDisplayMisc -+#define INTEGRATED_SYSTEM_INFO__GET_EDID_CALLBACK_FUNC_SUPPORT 0x01 -+ -+ - /********************************************************************************************************************** --// ATOM_INTEGRATED_SYSTEM_INFO_V6 Description --//ulBootUpEngineClock: VBIOS bootup Engine clock frequency, in 10kHz unit. --//ulDentistVCOFreq: Dentist VCO clock in 10kHz unit. --//ulBootUpUMAClock: System memory boot up clock frequency in 10Khz unit. --//ulReserved1[8] Reserved by now, must be 0x0. --//ulBootUpReqDisplayVector VBIOS boot up display IDs --// ATOM_DEVICE_CRT1_SUPPORT 0x0001 --// ATOM_DEVICE_CRT2_SUPPORT 0x0010 --// ATOM_DEVICE_DFP1_SUPPORT 0x0008 --// ATOM_DEVICE_DFP6_SUPPORT 0x0040 --// ATOM_DEVICE_DFP2_SUPPORT 0x0080 --// ATOM_DEVICE_DFP3_SUPPORT 0x0200 --// ATOM_DEVICE_DFP4_SUPPORT 0x0400 --// ATOM_DEVICE_DFP5_SUPPORT 0x0800 --// ATOM_DEVICE_LCD1_SUPPORT 0x0002 --//ulOtherDisplayMisc Other display related flags, not defined yet. --//ulGPUCapInfo TBD --//ulReserved2[3] must be 0x0 for the reserved. --//ulSystemConfig TBD --//ulCPUCapInfo TBD --//usMaxNBVoltage High NB voltage in unit of mv, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse. --//usMinNBVoltage Low NB voltage in unit of mv, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse. --//usBootUpNBVoltage Boot up NB voltage in unit of mv. --//ucHtcTmpLmt Bit [22:16] of D24F3x64 Thermal Control (HTC) Register. --//ucTjOffset Bit [28:22] of D24F3xE4 Thermtrip Status Register,may not be needed. --//ucMemoryType [3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved. --//ucUMAChannelNumber System memory channel numbers. --//usExtDispConnectionInfoOffset ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO offset relative to beginning of this table. --//ulCSR_M3_ARB_CNTL_DEFAULT[10] Arrays with values for CSR M3 arbiter for default --//ulCSR_M3_ARB_CNTL_UVD[10] Arrays with values for CSR M3 arbiter for UVD playback. --//ulCSR_M3_ARB_CNTL_FS3D[10] Arrays with values for CSR M3 arbiter for Full Screen 3D applications. -+ ATOM_INTEGRATED_SYSTEM_INFO_V6 Description -+ulBootUpEngineClock: VBIOS bootup Engine clock frequency, in 10kHz unit. if it is equal 0, then VBIOS use pre-defined bootup engine clock -+ulDentistVCOFreq: Dentist VCO clock in 10kHz unit. -+ulBootUpUMAClock: System memory boot up clock frequency in 10Khz unit. -+sDISPCLK_Voltage: Report Display clock voltage requirement. -+ -+ulBootUpReqDisplayVector: VBIOS boot up display IDs, following are supported devices in Liano/Ontaio projects: -+ ATOM_DEVICE_CRT1_SUPPORT 0x0001 -+ ATOM_DEVICE_CRT2_SUPPORT 0x0010 -+ ATOM_DEVICE_DFP1_SUPPORT 0x0008 -+ ATOM_DEVICE_DFP6_SUPPORT 0x0040 -+ ATOM_DEVICE_DFP2_SUPPORT 0x0080 -+ ATOM_DEVICE_DFP3_SUPPORT 0x0200 -+ ATOM_DEVICE_DFP4_SUPPORT 0x0400 -+ ATOM_DEVICE_DFP5_SUPPORT 0x0800 -+ ATOM_DEVICE_LCD1_SUPPORT 0x0002 -+ulOtherDisplayMisc: Other display related flags, not defined yet. -+ulGPUCapInfo: bit[0]=0: TMDS/HDMI Coherent Mode use cascade PLL mode. -+ =1: TMDS/HDMI Coherent Mode use signel PLL mode. -+ bit[3]=0: Enable HW AUX mode detection logic -+ =1: Disable HW AUX mode dettion logic -+ulSB_MMIO_Base_Addr: Physical Base address to SB MMIO space. Driver needs to initialize it for SMU usage. -+ -+usRequestedPWMFreqInHz: When it's set to 0x0 by SBIOS: the LCD BackLight is not controlled by GPU(SW). -+ Any attempt to change BL using VBIOS function or enable VariBri from PP table is not effective since ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==0; -+ -+ When it's set to a non-zero frequency, the BackLight is controlled by GPU (SW) in one of two ways below: -+ 1. SW uses the GPU BL PWM output to control the BL, in chis case, this non-zero frequency determines what freq GPU should use; -+ VBIOS will set up proper PWM frequency and ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==1,as the result, -+ Changing BL using VBIOS function is functional in both driver and non-driver present environment; -+ and enabling VariBri under the driver environment from PP table is optional. -+ -+ 2. SW uses other means to control BL (like DPCD),this non-zero frequency serves as a flag only indicating -+ that BL control from GPU is expected. -+ VBIOS will NOT set up PWM frequency but make ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==1 -+ Changing BL using VBIOS function could be functional in both driver and non-driver present environment,but -+ it's per platform -+ and enabling VariBri under the driver environment from PP table is optional. -+ -+ucHtcTmpLmt: Refer to D18F3x64 bit[22:16], HtcTmpLmt. -+ Threshold on value to enter HTC_active state. -+ucHtcHystLmt: Refer to D18F3x64 bit[27:24], HtcHystLmt. -+ To calculate threshold off value to exit HTC_active state, which is Threshold on vlaue minus ucHtcHystLmt. -+ulMinEngineClock: Minimum SCLK allowed in 10kHz unit. This is calculated based on WRCK Fuse settings. -+ulSystemConfig: Bit[0]=0: PCIE Power Gating Disabled -+ =1: PCIE Power Gating Enabled -+ Bit[1]=0: DDR-DLL shut-down feature disabled. -+ 1: DDR-DLL shut-down feature enabled. -+ Bit[2]=0: DDR-PLL Power down feature disabled. -+ 1: DDR-PLL Power down feature enabled. -+ulCPUCapInfo: TBD -+usNBP0Voltage: VID for voltage on NB P0 State -+usNBP1Voltage: VID for voltage on NB P1 State -+usBootUpNBVoltage: Voltage Index of GNB voltage configured by SBIOS, which is suffcient to support VBIOS DISPCLK requirement. -+usExtDispConnInfoOffset: Offset to sExtDispConnInfo inside the structure -+usPanelRefreshRateRange: Bit vector for LCD supported refresh rate range. If DRR is requestd by the platform, at least two bits need to be set -+ to indicate a range. -+ SUPPORTED_LCD_REFRESHRATE_30Hz 0x0004 -+ SUPPORTED_LCD_REFRESHRATE_40Hz 0x0008 -+ SUPPORTED_LCD_REFRESHRATE_50Hz 0x0010 -+ SUPPORTED_LCD_REFRESHRATE_60Hz 0x0020 -+ucMemoryType: [3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved. -+ucUMAChannelNumber: System memory channel numbers. -+ulCSR_M3_ARB_CNTL_DEFAULT[10]: Arrays with values for CSR M3 arbiter for default -+ulCSR_M3_ARB_CNTL_UVD[10]: Arrays with values for CSR M3 arbiter for UVD playback. -+ulCSR_M3_ARB_CNTL_FS3D[10]: Arrays with values for CSR M3 arbiter for Full Screen 3D applications. -+sAvail_SCLK[5]: Arrays to provide availabe list of SLCK and corresponding voltage, order from low to high -+ulGMCRestoreResetTime: GMC power restore and GMC reset time to calculate data reconnection latency. Unit in ns. -+ulMinimumNClk: Minimum NCLK speed among all NB-Pstates to calcualte data reconnection latency. Unit in 10kHz. -+ulIdleNClk: NCLK speed while memory runs in self-refresh state. Unit in 10kHz. -+ulDDR_DLL_PowerUpTime: DDR PHY DLL power up time. Unit in ns. -+ulDDR_PLL_PowerUpTime: DDR PHY PLL power up time. Unit in ns. -+usPCIEClkSSPercentage: PCIE Clock Spred Spectrum Percentage in unit 0.01%; 100 mean 1%. -+usPCIEClkSSType: PCIE Clock Spred Spectrum Type. 0 for Down spread(default); 1 for Center spread. -+usLvdsSSPercentage: LVDS panel ( not include eDP ) Spread Spectrum Percentage in unit of 0.01%, =0, use VBIOS default setting. -+usLvdsSSpreadRateIn10Hz: LVDS panel ( not include eDP ) Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. -+usHDMISSPercentage: HDMI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%, =0, use VBIOS default setting. -+usHDMISSpreadRateIn10Hz: HDMI Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. -+usDVISSPercentage: DVI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%, =0, use VBIOS default setting. -+usDVISSpreadRateIn10Hz: DVI Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. - **********************************************************************************************************************/ - - /**************************************************************************/ -@@ -3790,6 +4439,7 @@ - #define ASIC_INTERNAL_SS_ON_LVDS 6 - #define ASIC_INTERNAL_SS_ON_DP 7 - #define ASIC_INTERNAL_SS_ON_DCPLL 8 -+#define ASIC_EXTERNAL_SS_ON_DP_CLOCK 9 - - typedef struct _ATOM_ASIC_SS_ASSIGNMENT_V2 - { -@@ -3903,6 +4553,7 @@ - #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_AC 1 - #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_DC 2 - #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LITEAC 3 -+#define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LIT2AC 4 - - //Byte aligned defintion for BIOS usage - #define ATOM_S0_CRT1_MONOb0 0x01 -@@ -4529,7 +5180,8 @@ - #define INDEX_ACCESS_RANGE_BEGIN (VALUE_DWORD + 1) - #define INDEX_ACCESS_RANGE_END (INDEX_ACCESS_RANGE_BEGIN + 1) - #define VALUE_INDEX_ACCESS_SINGLE (INDEX_ACCESS_RANGE_END + 1) -- -+//#define ACCESS_MCIODEBUGIND 0x40 //defined in BIOS code -+#define ACCESS_PLACEHOLDER 0x80 - - typedef struct _ATOM_MC_INIT_PARAM_TABLE - { -@@ -4554,6 +5206,10 @@ - #define _32Mx32 0x33 - #define _64Mx8 0x41 - #define _64Mx16 0x42 -+#define _64Mx32 0x43 -+#define _128Mx8 0x51 -+#define _128Mx16 0x52 -+#define _256Mx8 0x61 - - #define SAMSUNG 0x1 - #define INFINEON 0x2 -@@ -4569,10 +5225,11 @@ - #define QIMONDA INFINEON - #define PROMOS MOSEL - #define KRETON INFINEON -+#define ELIXIR NANYA - - /////////////Support for GDDR5 MC uCode to reside in upper 64K of ROM///////////// - --#define UCODE_ROM_START_ADDRESS 0x1c000 -+#define UCODE_ROM_START_ADDRESS 0x1b800 - #define UCODE_SIGNATURE 0x4375434d // 'MCuC' - MC uCode - - //uCode block header for reference -@@ -4903,7 +5560,34 @@ - ATOM_MEMORY_TIMING_FORMAT_V2 asMemTiming[5];//Memory Timing block sort from lower clock to higher clock - }ATOM_VRAM_MODULE_V6; - -- -+typedef struct _ATOM_VRAM_MODULE_V7 -+{ -+// Design Specific Values -+ ULONG ulChannelMapCfg; // mmMC_SHARED_CHREMAP -+ USHORT usModuleSize; // Size of ATOM_VRAM_MODULE_V7 -+ USHORT usPrivateReserved; // MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS) -+ USHORT usReserved; -+ UCHAR ucExtMemoryID; // Current memory module ID -+ UCHAR ucMemoryType; // MEM_TYPE_DDR2/DDR3/GDDR3/GDDR5 -+ UCHAR ucChannelNum; // Number of mem. channels supported in this module -+ UCHAR ucChannelWidth; // CHANNEL_16BIT/CHANNEL_32BIT/CHANNEL_64BIT -+ UCHAR ucDensity; // _8Mx32, _16Mx32, _16Mx16, _32Mx16 -+ UCHAR ucReserve; // Former container for Mx_FLAGS like DBI_AC_MODE_ENABLE_ASIC for GDDR4. Not used now. -+ UCHAR ucMisc; // RANK_OF_THISMEMORY etc. -+ UCHAR ucVREFI; // Not used. -+ UCHAR ucNPL_RT; // Round trip delay (MC_SEQ_CAS_TIMING [28:24]:TCL=CL+NPL_RT-2). Always 2. -+ UCHAR ucPreamble; // [7:4] Write Preamble, [3:0] Read Preamble -+ UCHAR ucMemorySize; // Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros -+ UCHAR ucReserved[3]; -+// Memory Module specific values -+ USHORT usEMRS2Value; // EMRS2/MR2 Value. -+ USHORT usEMRS3Value; // EMRS3/MR3 Value. -+ UCHAR ucMemoryVenderID; // [7:4] Revision, [3:0] Vendor code -+ UCHAR ucRefreshRateFactor; // [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms) -+ UCHAR ucFIFODepth; // FIFO depth can be detected during vendor detection, here is hardcoded per memory -+ UCHAR ucCDR_Bandwidth; // [0:3]=Read CDR bandwidth, [4:7] - Write CDR Bandwidth -+ char strMemPNString[20]; // part number end with '0'. -+}ATOM_VRAM_MODULE_V7; - - typedef struct _ATOM_VRAM_INFO_V2 - { -@@ -4942,6 +5626,20 @@ - // ATOM_INIT_REG_BLOCK aMemAdjust; - }ATOM_VRAM_INFO_V4; - -+typedef struct _ATOM_VRAM_INFO_HEADER_V2_1 -+{ -+ ATOM_COMMON_TABLE_HEADER sHeader; -+ USHORT usMemAdjustTblOffset; // offset of ATOM_INIT_REG_BLOCK structure for memory vendor specific MC adjust setting -+ USHORT usMemClkPatchTblOffset; // offset of ATOM_INIT_REG_BLOCK structure for memory clock specific MC setting -+ USHORT usReserved[4]; -+ UCHAR ucNumOfVRAMModule; // indicate number of VRAM module -+ UCHAR ucMemoryClkPatchTblVer; // version of memory AC timing register list -+ UCHAR ucVramModuleVer; // indicate ATOM_VRAM_MODUE version -+ UCHAR ucReserved; -+ ATOM_VRAM_MODULE_V7 aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE]; // just for allocation, real number of blocks is in ucNumOfVRAMModule; -+}ATOM_VRAM_INFO_HEADER_V2_1; -+ -+ - typedef struct _ATOM_VRAM_GPIO_DETECTION_INFO - { - ATOM_COMMON_TABLE_HEADER sHeader; -@@ -5182,6 +5880,16 @@ - UCHAR ucReserved; - }ASIC_TRANSMITTER_INFO; - -+#define ASIC_TRANSMITTER_INFO_CONFIG__DVO_SDR_MODE 0x01 -+#define ASIC_TRANSMITTER_INFO_CONFIG__COHERENT_MODE 0x02 -+#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODEROBJ_ID_MASK 0xc4 -+#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_A 0x00 -+#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_B 0x04 -+#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_C 0x40 -+#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_D 0x44 -+#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_E 0x80 -+#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_F 0x84 -+ - typedef struct _ASIC_ENCODER_INFO - { - UCHAR ucEncoderID; -@@ -5284,6 +5992,28 @@ - /* /obselete */ - #define DP_ENCODER_SERVICE_PS_ALLOCATION WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS - -+ -+typedef struct _DP_ENCODER_SERVICE_PARAMETERS_V2 -+{ -+ USHORT usExtEncoderObjId; // External Encoder Object Id, output parameter only, use when ucAction = DP_SERVICE_V2_ACTION_DET_EXT_CONNECTION -+ UCHAR ucAuxId; -+ UCHAR ucAction; -+ UCHAR ucSinkType; // Iput and Output parameters. -+ UCHAR ucHPDId; // Input parameter, used when ucAction = DP_SERVICE_V2_ACTION_DET_EXT_CONNECTION -+ UCHAR ucReserved[2]; -+}DP_ENCODER_SERVICE_PARAMETERS_V2; -+ -+typedef struct _DP_ENCODER_SERVICE_PS_ALLOCATION_V2 -+{ -+ DP_ENCODER_SERVICE_PARAMETERS_V2 asDPServiceParam; -+ PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 asAuxParam; -+}DP_ENCODER_SERVICE_PS_ALLOCATION_V2; -+ -+// ucAction -+#define DP_SERVICE_V2_ACTION_GET_SINK_TYPE 0x01 -+#define DP_SERVICE_V2_ACTION_DET_LCD_CONNECTION 0x02 -+ -+ - // DP_TRAINING_TABLE - #define DPCD_SET_LINKRATE_LANENUM_PATTERN1_TBL_ADDR ATOM_DP_TRAINING_TBL_ADDR - #define DPCD_SET_SS_CNTL_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 8 ) -@@ -5339,6 +6069,7 @@ - #define SELECT_DCIO_IMPCAL 4 - #define SELECT_DCIO_DIG 6 - #define SELECT_CRTC_PIXEL_RATE 7 -+#define SELECT_VGA_BLK 8 - - /****************************************************************************/ - //Portion VI: Definitinos for vbios MC scratch registers that driver used -@@ -5744,7 +6475,17 @@ - #define ATOM_PP_THERMALCONTROLLER_ADT7473 9 - #define ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO 11 - #define ATOM_PP_THERMALCONTROLLER_EVERGREEN 12 -+#define ATOM_PP_THERMALCONTROLLER_EMC2103 13 /* 0x0D */ // Only fan control will be implemented, do NOT show this in PPGen. -+#define ATOM_PP_THERMALCONTROLLER_SUMO 14 /* 0x0E */ // Sumo type, used internally -+#define ATOM_PP_THERMALCONTROLLER_NISLANDS 15 -+ -+// Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal. -+// We probably should reserve the bit 0x80 for this use. -+// To keep the number of these types low we should also use the same code for all ASICs (i.e. do not distinguish RV6xx and RV7xx Internal here). -+// The driver can pick the correct internal controller based on the ASIC. -+ - #define ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL 0x89 // ADT7473 Fan Control + Internal Thermal Controller -+#define ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL 0x8D // EMC2103 Fan Control + Internal Thermal Controller - - typedef struct _ATOM_PPLIB_STATE - { -@@ -5841,6 +6582,29 @@ - USHORT usExtendendedHeaderOffset; - } ATOM_PPLIB_POWERPLAYTABLE3, *LPATOM_PPLIB_POWERPLAYTABLE3; - -+typedef struct _ATOM_PPLIB_POWERPLAYTABLE4 -+{ -+ ATOM_PPLIB_POWERPLAYTABLE3 basicTable3; -+ ULONG ulGoldenPPID; // PPGen use only -+ ULONG ulGoldenRevision; // PPGen use only -+ USHORT usVddcDependencyOnSCLKOffset; -+ USHORT usVddciDependencyOnMCLKOffset; -+ USHORT usVddcDependencyOnMCLKOffset; -+ USHORT usMaxClockVoltageOnDCOffset; -+ USHORT usReserved[2]; -+} ATOM_PPLIB_POWERPLAYTABLE4, *LPATOM_PPLIB_POWERPLAYTABLE4; -+ -+typedef struct _ATOM_PPLIB_POWERPLAYTABLE5 -+{ -+ ATOM_PPLIB_POWERPLAYTABLE4 basicTable4; -+ ULONG ulTDPLimit; -+ ULONG ulNearTDPLimit; -+ ULONG ulSQRampingThreshold; -+ USHORT usCACLeakageTableOffset; // Points to ATOM_PPLIB_CAC_Leakage_Table -+ ULONG ulCACLeakage; // TBD, this parameter is still under discussion. Change to ulReserved if not needed. -+ ULONG ulReserved; -+} ATOM_PPLIB_POWERPLAYTABLE5, *LPATOM_PPLIB_POWERPLAYTABLE5; -+ - //// ATOM_PPLIB_NONCLOCK_INFO::usClassification - #define ATOM_PPLIB_CLASSIFICATION_UI_MASK 0x0007 - #define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT 0 -@@ -5864,6 +6628,10 @@ - #define ATOM_PPLIB_CLASSIFICATION_HDSTATE 0x4000 - #define ATOM_PPLIB_CLASSIFICATION_SDSTATE 0x8000 - -+//// ATOM_PPLIB_NONCLOCK_INFO::usClassification2 -+#define ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2 0x0001 -+#define ATOM_PPLIB_CLASSIFICATION2_ULV 0x0002 -+ - //// ATOM_PPLIB_NONCLOCK_INFO::ulCapsAndSettings - #define ATOM_PPLIB_SINGLE_DISPLAY_ONLY 0x00000001 - #define ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK 0x00000002 -@@ -5896,9 +6664,21 @@ - #define ATOM_PPLIB_M3ARB_MASK 0x00060000 - #define ATOM_PPLIB_M3ARB_SHIFT 17 - -+#define ATOM_PPLIB_ENABLE_DRR 0x00080000 -+ -+// remaining 16 bits are reserved -+typedef struct _ATOM_PPLIB_THERMAL_STATE -+{ -+ UCHAR ucMinTemperature; -+ UCHAR ucMaxTemperature; -+ UCHAR ucThermalAction; -+}ATOM_PPLIB_THERMAL_STATE, *LPATOM_PPLIB_THERMAL_STATE; -+ - // Contained in an array starting at the offset - // in ATOM_PPLIB_POWERPLAYTABLE::usNonClockInfoArrayOffset. - // referenced from ATOM_PPLIB_STATE_INFO::ucNonClockStateIndex -+#define ATOM_PPLIB_NONCLOCKINFO_VER1 12 -+#define ATOM_PPLIB_NONCLOCKINFO_VER2 24 - typedef struct _ATOM_PPLIB_NONCLOCK_INFO - { - USHORT usClassification; -@@ -5906,15 +6686,15 @@ - UCHAR ucMaxTemperature; - ULONG ulCapsAndSettings; - UCHAR ucRequiredPower; -- UCHAR ucUnused1[3]; -+ USHORT usClassification2; -+ ULONG ulVCLK; -+ ULONG ulDCLK; -+ UCHAR ucUnused[5]; - } ATOM_PPLIB_NONCLOCK_INFO; - - // Contained in an array starting at the offset - // in ATOM_PPLIB_POWERPLAYTABLE::usClockInfoArrayOffset. - // referenced from ATOM_PPLIB_STATE::ucClockStateIndices --#define ATOM_PPLIB_NONCLOCKINFO_VER1 12 --#define ATOM_PPLIB_NONCLOCKINFO_VER2 24 -- - typedef struct _ATOM_PPLIB_R600_CLOCK_INFO - { - USHORT usEngineClockLow; -@@ -5985,6 +6765,93 @@ - #define ATOM_PPLIB_RS780_HTLINKFREQ_LOW 1 - #define ATOM_PPLIB_RS780_HTLINKFREQ_HIGH 2 - -+typedef struct _ATOM_PPLIB_SUMO_CLOCK_INFO{ -+ USHORT usEngineClockLow; //clockfrequency & 0xFFFF. The unit is in 10khz -+ UCHAR ucEngineClockHigh; //clockfrequency >> 16. -+ UCHAR vddcIndex; //2-bit vddc index; -+ UCHAR leakage; //please use 8-bit absolute value, not the 6-bit % value -+ //please initalize to 0 -+ UCHAR rsv; -+ //please initalize to 0 -+ USHORT rsv1; -+ //please initialize to 0s -+ ULONG rsv2[2]; -+}ATOM_PPLIB_SUMO_CLOCK_INFO; -+ -+ -+ -+typedef struct _ATOM_PPLIB_STATE_V2 -+{ -+ //number of valid dpm levels in this state; Driver uses it to calculate the whole -+ //size of the state: sizeof(ATOM_PPLIB_STATE_V2) + (ucNumDPMLevels - 1) * sizeof(UCHAR) -+ UCHAR ucNumDPMLevels; -+ -+ //a index to the array of nonClockInfos -+ UCHAR nonClockInfoIndex; -+ /** -+ * Driver will read the first ucNumDPMLevels in this array -+ */ -+ UCHAR clockInfoIndex[1]; -+} ATOM_PPLIB_STATE_V2; -+ -+typedef struct StateArray{ -+ //how many states we have -+ UCHAR ucNumEntries; -+ -+ ATOM_PPLIB_STATE_V2 states[1]; -+}StateArray; -+ -+ -+typedef struct ClockInfoArray{ -+ //how many clock levels we have -+ UCHAR ucNumEntries; -+ -+ //sizeof(ATOM_PPLIB_SUMO_CLOCK_INFO) -+ UCHAR ucEntrySize; -+ -+ //this is for Sumo -+ ATOM_PPLIB_SUMO_CLOCK_INFO clockInfo[1]; -+}ClockInfoArray; -+ -+typedef struct NonClockInfoArray{ -+ -+ //how many non-clock levels we have. normally should be same as number of states -+ UCHAR ucNumEntries; -+ //sizeof(ATOM_PPLIB_NONCLOCK_INFO) -+ UCHAR ucEntrySize; -+ -+ ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[1]; -+}NonClockInfoArray; -+ -+typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Record -+{ -+ USHORT usClockLow; -+ UCHAR ucClockHigh; -+ USHORT usVoltage; -+}ATOM_PPLIB_Clock_Voltage_Dependency_Record; -+ -+typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Table -+{ -+ UCHAR ucNumEntries; // Number of entries. -+ ATOM_PPLIB_Clock_Voltage_Dependency_Record entries[1]; // Dynamically allocate entries. -+}ATOM_PPLIB_Clock_Voltage_Dependency_Table; -+ -+typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Record -+{ -+ USHORT usSclkLow; -+ UCHAR ucSclkHigh; -+ USHORT usMclkLow; -+ UCHAR ucMclkHigh; -+ USHORT usVddc; -+ USHORT usVddci; -+}ATOM_PPLIB_Clock_Voltage_Limit_Record; -+ -+typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Table -+{ -+ UCHAR ucNumEntries; // Number of entries. -+ ATOM_PPLIB_Clock_Voltage_Limit_Record entries[1]; // Dynamically allocate entries. -+}ATOM_PPLIB_Clock_Voltage_Limit_Table; -+ - /**************************************************************************/ - - -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/evergreen_blit_kms.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/evergreen_blit_kms.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/evergreen_blit_kms.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/evergreen_blit_kms.c 2011-01-07 14:22:17.000000000 +0100 -@@ -147,7 +147,8 @@ - radeon_ring_write(rdev, 0); - radeon_ring_write(rdev, SQ_TEX_VTX_VALID_BUFFER << 30); - -- if (rdev->family == CHIP_CEDAR) -+ if ((rdev->family == CHIP_CEDAR) || -+ (rdev->family == CHIP_PALM)) - cp_set_surface_sync(rdev, - PACKET3_TC_ACTION_ENA, 48, gpu_addr); - else -@@ -331,9 +332,31 @@ - num_hs_stack_entries = 85; - num_ls_stack_entries = 85; - break; -+ case CHIP_PALM: -+ num_ps_gprs = 93; -+ num_vs_gprs = 46; -+ num_temp_gprs = 4; -+ num_gs_gprs = 31; -+ num_es_gprs = 31; -+ num_hs_gprs = 23; -+ num_ls_gprs = 23; -+ num_ps_threads = 96; -+ num_vs_threads = 16; -+ num_gs_threads = 16; -+ num_es_threads = 16; -+ num_hs_threads = 16; -+ num_ls_threads = 16; -+ num_ps_stack_entries = 42; -+ num_vs_stack_entries = 42; -+ num_gs_stack_entries = 42; -+ num_es_stack_entries = 42; -+ num_hs_stack_entries = 42; -+ num_ls_stack_entries = 42; -+ break; - } - -- if (rdev->family == CHIP_CEDAR) -+ if ((rdev->family == CHIP_CEDAR) || -+ (rdev->family == CHIP_PALM)) - sq_config = 0; - else - sq_config = VC_ENABLE; -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/evergreen.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/evergreen.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/evergreen.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/evergreen.c 2011-01-07 14:22:17.000000000 +0100 -@@ -40,6 +40,61 @@ - static void evergreen_gpu_init(struct radeon_device *rdev); - void evergreen_fini(struct radeon_device *rdev); - -+void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) -+{ -+ struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; -+ u32 tmp; -+ -+ /* make sure flip is at vb rather than hb */ -+ tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); -+ tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN; -+ WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); -+ -+ /* set pageflip to happen anywhere in vblank interval */ -+ WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); -+ -+ /* enable the pflip int */ -+ radeon_irq_kms_pflip_irq_get(rdev, crtc); -+} -+ -+void evergreen_post_page_flip(struct radeon_device *rdev, int crtc) -+{ -+ /* disable the pflip int */ -+ radeon_irq_kms_pflip_irq_put(rdev, crtc); -+} -+ -+u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) -+{ -+ struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; -+ u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset); -+ -+ /* Lock the graphics update lock */ -+ tmp |= EVERGREEN_GRPH_UPDATE_LOCK; -+ WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); -+ -+ /* update the scanout addresses */ -+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, -+ upper_32_bits(crtc_base)); -+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, -+ (u32)crtc_base); -+ -+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, -+ upper_32_bits(crtc_base)); -+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, -+ (u32)crtc_base); -+ -+ /* Wait for update_pending to go high. */ -+ while (!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)); -+ DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); -+ -+ /* Unlock the lock, so double-buffering can take place inside vblank */ -+ tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK; -+ WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); -+ -+ /* Return current update_pending status: */ -+ return RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING; -+} -+ - /* get temperature in millidegrees */ - u32 evergreen_get_temp(struct radeon_device *rdev) - { -@@ -57,6 +112,14 @@ - return actual_temp * 1000; - } - -+u32 sumo_get_temp(struct radeon_device *rdev) -+{ -+ u32 temp = RREG32(CG_THERMAL_STATUS) & 0xff; -+ u32 actual_temp = (temp >> 1) & 0xff; -+ -+ return actual_temp * 1000; -+} -+ - void evergreen_pm_misc(struct radeon_device *rdev) - { - int req_ps_idx = rdev->pm.requested_power_state_index; -@@ -888,31 +951,39 @@ - save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); - save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); - save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); -- save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); -- save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); -- save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); -- save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); -+ if (!(rdev->flags & RADEON_IS_IGP)) { -+ save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); -+ save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); -+ save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); -+ save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); -+ } - - /* Stop all video */ - WREG32(VGA_RENDER_CONTROL, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); -+ if (!(rdev->flags & RADEON_IS_IGP)) { -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); -+ } - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -+ if (!(rdev->flags & RADEON_IS_IGP)) { -+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -+ } - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -+ if (!(rdev->flags & RADEON_IS_IGP)) { -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -+ } - - WREG32(D1VGA_CONTROL, 0); - WREG32(D2VGA_CONTROL, 0); -@@ -942,41 +1013,43 @@ - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -+ if (!(rdev->flags & RADEON_IS_IGP)) { -+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, -+ upper_32_bits(rdev->mc.vram_start)); -+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, -+ upper_32_bits(rdev->mc.vram_start)); -+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, -+ (u32)rdev->mc.vram_start); -+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, -+ (u32)rdev->mc.vram_start); -+ -+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, -+ upper_32_bits(rdev->mc.vram_start)); -+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, -+ upper_32_bits(rdev->mc.vram_start)); -+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, -+ (u32)rdev->mc.vram_start); -+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, -+ (u32)rdev->mc.vram_start); -+ -+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, -+ upper_32_bits(rdev->mc.vram_start)); -+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, -+ upper_32_bits(rdev->mc.vram_start)); -+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, -+ (u32)rdev->mc.vram_start); -+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, -+ (u32)rdev->mc.vram_start); -+ -+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, -+ upper_32_bits(rdev->mc.vram_start)); -+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, -+ upper_32_bits(rdev->mc.vram_start)); -+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, -+ (u32)rdev->mc.vram_start); -+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, -+ (u32)rdev->mc.vram_start); -+ } - - WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); -@@ -992,22 +1065,28 @@ - WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); -+ if (!(rdev->flags & RADEON_IS_IGP)) { -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); -+ } - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]); -+ if (!(rdev->flags & RADEON_IS_IGP)) { -+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]); -+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); -+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]); -+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]); -+ } - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -+ if (!(rdev->flags & RADEON_IS_IGP)) { -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -+ } - WREG32(VGA_RENDER_CONTROL, save->vga_render_control); - } - -@@ -1055,6 +1134,12 @@ - rdev->mc.vram_end >> 12); - } - WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); -+ if (rdev->flags & RADEON_IS_IGP) { -+ tmp = RREG32(MC_FUS_VM_FB_OFFSET) & 0x000FFFFF; -+ tmp |= ((rdev->mc.vram_end >> 20) & 0xF) << 24; -+ tmp |= ((rdev->mc.vram_start >> 20) & 0xF) << 20; -+ WREG32(MC_FUS_VM_FB_OFFSET, tmp); -+ } - tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; - tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); - WREG32(MC_VM_FB_LOCATION, tmp); -@@ -1283,6 +1368,7 @@ - switch (rdev->family) { - case CHIP_CEDAR: - case CHIP_REDWOOD: -+ case CHIP_PALM: - force_no_swizzle = false; - break; - case CHIP_CYPRESS: -@@ -1382,6 +1468,43 @@ - return backend_map; - } - -+static void evergreen_program_channel_remap(struct radeon_device *rdev) -+{ -+ u32 tcp_chan_steer_lo, tcp_chan_steer_hi, mc_shared_chremap, tmp; -+ -+ tmp = RREG32(MC_SHARED_CHMAP); -+ switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { -+ case 0: -+ case 1: -+ case 2: -+ case 3: -+ default: -+ /* default mapping */ -+ mc_shared_chremap = 0x00fac688; -+ break; -+ } -+ -+ switch (rdev->family) { -+ case CHIP_HEMLOCK: -+ case CHIP_CYPRESS: -+ tcp_chan_steer_lo = 0x54763210; -+ tcp_chan_steer_hi = 0x0000ba98; -+ break; -+ case CHIP_JUNIPER: -+ case CHIP_REDWOOD: -+ case CHIP_CEDAR: -+ case CHIP_PALM: -+ default: -+ tcp_chan_steer_lo = 0x76543210; -+ tcp_chan_steer_hi = 0x0000ba98; -+ break; -+ } -+ -+ WREG32(TCP_CHAN_STEER_LO, tcp_chan_steer_lo); -+ WREG32(TCP_CHAN_STEER_HI, tcp_chan_steer_hi); -+ WREG32(MC_SHARED_CHREMAP, mc_shared_chremap); -+} -+ - static void evergreen_gpu_init(struct radeon_device *rdev) - { - u32 cc_rb_backend_disable = 0; -@@ -1493,6 +1616,27 @@ - rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; - rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - break; -+ case CHIP_PALM: -+ rdev->config.evergreen.num_ses = 1; -+ rdev->config.evergreen.max_pipes = 2; -+ rdev->config.evergreen.max_tile_pipes = 2; -+ rdev->config.evergreen.max_simds = 2; -+ rdev->config.evergreen.max_backends = 1 * rdev->config.evergreen.num_ses; -+ rdev->config.evergreen.max_gprs = 256; -+ rdev->config.evergreen.max_threads = 192; -+ rdev->config.evergreen.max_gs_threads = 16; -+ rdev->config.evergreen.max_stack_entries = 256; -+ rdev->config.evergreen.sx_num_of_sets = 4; -+ rdev->config.evergreen.sx_max_export_size = 128; -+ rdev->config.evergreen.sx_max_export_pos_size = 32; -+ rdev->config.evergreen.sx_max_export_smx_size = 96; -+ rdev->config.evergreen.max_hw_contexts = 4; -+ rdev->config.evergreen.sq_num_cf_insts = 1; -+ -+ rdev->config.evergreen.sc_prim_fifo_size = 0x40; -+ rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; -+ rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; -+ break; - } - - /* Initialize HDP */ -@@ -1685,6 +1829,8 @@ - WREG32(DMIF_ADDR_CONFIG, gb_addr_config); - WREG32(HDP_ADDR_CONFIG, gb_addr_config); - -+ evergreen_program_channel_remap(rdev); -+ - num_shader_engines = ((RREG32(GB_ADDR_CONFIG) & NUM_SHADER_ENGINES(3)) >> 12) + 1; - grbm_gfx_index = INSTANCE_BROADCAST_WRITES; - -@@ -1767,9 +1913,15 @@ - GS_PRIO(2) | - ES_PRIO(3)); - -- if (rdev->family == CHIP_CEDAR) -+ switch (rdev->family) { -+ case CHIP_CEDAR: -+ case CHIP_PALM: - /* no vertex cache */ - sq_config &= ~VC_ENABLE; -+ break; -+ default: -+ break; -+ } - - sq_lds_resource_mgmt = RREG32(SQ_LDS_RESOURCE_MGMT); - -@@ -1781,10 +1933,15 @@ - sq_gpr_resource_mgmt_3 = NUM_HS_GPRS((rdev->config.evergreen.max_gprs - (4 * 2)) * 3 / 32); - sq_gpr_resource_mgmt_3 |= NUM_LS_GPRS((rdev->config.evergreen.max_gprs - (4 * 2)) * 3 / 32); - -- if (rdev->family == CHIP_CEDAR) -+ switch (rdev->family) { -+ case CHIP_CEDAR: -+ case CHIP_PALM: - ps_thread_count = 96; -- else -+ break; -+ default: - ps_thread_count = 128; -+ break; -+ } - - sq_thread_resource_mgmt = NUM_PS_THREADS(ps_thread_count); - sq_thread_resource_mgmt |= NUM_VS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); -@@ -1815,10 +1972,15 @@ - WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) | - FORCE_EOV_MAX_REZ_CNT(255))); - -- if (rdev->family == CHIP_CEDAR) -+ switch (rdev->family) { -+ case CHIP_CEDAR: -+ case CHIP_PALM: - vgt_cache_invalidation = CACHE_INVALIDATION(TC_ONLY); -- else -+ break; -+ default: - vgt_cache_invalidation = CACHE_INVALIDATION(VC_AND_TC); -+ break; -+ } - vgt_cache_invalidation |= AUTO_INVLD_EN(ES_AND_GS_AUTO); - WREG32(VGT_CACHE_INVALIDATION, vgt_cache_invalidation); - -@@ -1902,12 +2064,18 @@ - rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); - rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); - /* Setup GPU memory space */ -- /* size in MB on evergreen */ -- rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; -- rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; -+ if (rdev->flags & RADEON_IS_IGP) { -+ /* size in bytes on fusion */ -+ rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); -+ rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); -+ } else { -+ /* size in MB on evergreen */ -+ rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; -+ rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; -+ } - rdev->mc.visible_vram_size = rdev->mc.aper_size; - rdev->mc.active_vram_size = rdev->mc.visible_vram_size; -- r600_vram_gtt_location(rdev, &rdev->mc); -+ r700_vram_gtt_location(rdev, &rdev->mc); - radeon_update_bandwidth_info(rdev); - - return 0; -@@ -2024,17 +2192,21 @@ - WREG32(GRBM_INT_CNTL, 0); - WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); - WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -- WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -- WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -- WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -- WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -+ if (!(rdev->flags & RADEON_IS_IGP)) { -+ WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -+ WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -+ WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -+ WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -+ } - - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -+ if (!(rdev->flags & RADEON_IS_IGP)) { -+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -+ } - - WREG32(DACA_AUTODETECT_INT_CONTROL, 0); - WREG32(DACB_AUTODETECT_INT_CONTROL, 0); -@@ -2060,6 +2232,7 @@ - u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; - u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; - u32 grbm_int_cntl = 0; -+ u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; - - if (!rdev->irq.installed) { - WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); -@@ -2085,27 +2258,33 @@ - cp_int_cntl |= RB_INT_ENABLE; - cp_int_cntl |= TIME_STAMP_INT_ENABLE; - } -- if (rdev->irq.crtc_vblank_int[0]) { -+ if (rdev->irq.crtc_vblank_int[0] || -+ rdev->irq.pflip[0]) { - DRM_DEBUG("evergreen_irq_set: vblank 0\n"); - crtc1 |= VBLANK_INT_MASK; - } -- if (rdev->irq.crtc_vblank_int[1]) { -+ if (rdev->irq.crtc_vblank_int[1] || -+ rdev->irq.pflip[1]) { - DRM_DEBUG("evergreen_irq_set: vblank 1\n"); - crtc2 |= VBLANK_INT_MASK; - } -- if (rdev->irq.crtc_vblank_int[2]) { -+ if (rdev->irq.crtc_vblank_int[2] || -+ rdev->irq.pflip[2]) { - DRM_DEBUG("evergreen_irq_set: vblank 2\n"); - crtc3 |= VBLANK_INT_MASK; - } -- if (rdev->irq.crtc_vblank_int[3]) { -+ if (rdev->irq.crtc_vblank_int[3] || -+ rdev->irq.pflip[3]) { - DRM_DEBUG("evergreen_irq_set: vblank 3\n"); - crtc4 |= VBLANK_INT_MASK; - } -- if (rdev->irq.crtc_vblank_int[4]) { -+ if (rdev->irq.crtc_vblank_int[4] || -+ rdev->irq.pflip[4]) { - DRM_DEBUG("evergreen_irq_set: vblank 4\n"); - crtc5 |= VBLANK_INT_MASK; - } -- if (rdev->irq.crtc_vblank_int[5]) { -+ if (rdev->irq.crtc_vblank_int[5] || -+ rdev->irq.pflip[5]) { - DRM_DEBUG("evergreen_irq_set: vblank 5\n"); - crtc6 |= VBLANK_INT_MASK; - } -@@ -2143,10 +2322,19 @@ - - WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, crtc1); - WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, crtc2); -- WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, crtc3); -- WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, crtc4); -- WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, crtc5); -- WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6); -+ if (!(rdev->flags & RADEON_IS_IGP)) { -+ WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, crtc3); -+ WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, crtc4); -+ WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, crtc5); -+ WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6); -+ } -+ -+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1); -+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2); -+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3); -+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4); -+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5); -+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6); - - WREG32(DC_HPD1_INT_CONTROL, hpd1); - WREG32(DC_HPD2_INT_CONTROL, hpd2); -@@ -2158,79 +2346,92 @@ - return 0; - } - --static inline void evergreen_irq_ack(struct radeon_device *rdev, -- u32 *disp_int, -- u32 *disp_int_cont, -- u32 *disp_int_cont2, -- u32 *disp_int_cont3, -- u32 *disp_int_cont4, -- u32 *disp_int_cont5) -+static inline void evergreen_irq_ack(struct radeon_device *rdev) - { - u32 tmp; - -- *disp_int = RREG32(DISP_INTERRUPT_STATUS); -- *disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); -- *disp_int_cont2 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE2); -- *disp_int_cont3 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE3); -- *disp_int_cont4 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE4); -- *disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5); -+ rdev->irq.stat_regs.evergreen.disp_int = RREG32(DISP_INTERRUPT_STATUS); -+ rdev->irq.stat_regs.evergreen.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); -+ rdev->irq.stat_regs.evergreen.disp_int_cont2 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE2); -+ rdev->irq.stat_regs.evergreen.disp_int_cont3 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE3); -+ rdev->irq.stat_regs.evergreen.disp_int_cont4 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE4); -+ rdev->irq.stat_regs.evergreen.disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5); -+ rdev->irq.stat_regs.evergreen.d1grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET); -+ rdev->irq.stat_regs.evergreen.d2grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET); -+ rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET); -+ rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET); -+ rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET); -+ rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); -+ -+ if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED) -+ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); -+ if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED) -+ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); -+ if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED) -+ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); -+ if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED) -+ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); -+ if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED) -+ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); -+ if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED) -+ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); - -- if (*disp_int & LB_D1_VBLANK_INTERRUPT) -+ if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) - WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK); -- if (*disp_int & LB_D1_VLINE_INTERRUPT) -+ if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) - WREG32(VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VLINE_ACK); - -- if (*disp_int_cont & LB_D2_VBLANK_INTERRUPT) -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) - WREG32(VBLANK_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VBLANK_ACK); -- if (*disp_int_cont & LB_D2_VLINE_INTERRUPT) -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) - WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK); - -- if (*disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) - WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK); -- if (*disp_int_cont2 & LB_D3_VLINE_INTERRUPT) -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) - WREG32(VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VLINE_ACK); - -- if (*disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) - WREG32(VBLANK_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VBLANK_ACK); -- if (*disp_int_cont3 & LB_D4_VLINE_INTERRUPT) -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) - WREG32(VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VLINE_ACK); - -- if (*disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) - WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK); -- if (*disp_int_cont4 & LB_D5_VLINE_INTERRUPT) -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) - WREG32(VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VLINE_ACK); - -- if (*disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) - WREG32(VBLANK_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VBLANK_ACK); -- if (*disp_int_cont5 & LB_D6_VLINE_INTERRUPT) -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) - WREG32(VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VLINE_ACK); - -- if (*disp_int & DC_HPD1_INTERRUPT) { -+ if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { - tmp = RREG32(DC_HPD1_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; - WREG32(DC_HPD1_INT_CONTROL, tmp); - } -- if (*disp_int_cont & DC_HPD2_INTERRUPT) { -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { - tmp = RREG32(DC_HPD2_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; - WREG32(DC_HPD2_INT_CONTROL, tmp); - } -- if (*disp_int_cont2 & DC_HPD3_INTERRUPT) { -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { - tmp = RREG32(DC_HPD3_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; - WREG32(DC_HPD3_INT_CONTROL, tmp); - } -- if (*disp_int_cont3 & DC_HPD4_INTERRUPT) { -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { - tmp = RREG32(DC_HPD4_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; - WREG32(DC_HPD4_INT_CONTROL, tmp); - } -- if (*disp_int_cont4 & DC_HPD5_INTERRUPT) { -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { - tmp = RREG32(DC_HPD5_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; - WREG32(DC_HPD5_INT_CONTROL, tmp); - } -- if (*disp_int_cont5 & DC_HPD6_INTERRUPT) { -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { - tmp = RREG32(DC_HPD5_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; - WREG32(DC_HPD6_INT_CONTROL, tmp); -@@ -2239,14 +2440,10 @@ - - void evergreen_irq_disable(struct radeon_device *rdev) - { -- u32 disp_int, disp_int_cont, disp_int_cont2; -- u32 disp_int_cont3, disp_int_cont4, disp_int_cont5; -- - r600_disable_interrupts(rdev); - /* Wait and acknowledge irq */ - mdelay(1); -- evergreen_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2, -- &disp_int_cont3, &disp_int_cont4, &disp_int_cont5); -+ evergreen_irq_ack(rdev); - evergreen_disable_interrupt_state(rdev); - } - -@@ -2286,8 +2483,6 @@ - u32 rptr = rdev->ih.rptr; - u32 src_id, src_data; - u32 ring_index; -- u32 disp_int, disp_int_cont, disp_int_cont2; -- u32 disp_int_cont3, disp_int_cont4, disp_int_cont5; - unsigned long flags; - bool queue_hotplug = false; - -@@ -2308,8 +2503,7 @@ - - restart_ih: - /* display interrupts */ -- evergreen_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2, -- &disp_int_cont3, &disp_int_cont4, &disp_int_cont5); -+ evergreen_irq_ack(rdev); - - rdev->ih.wptr = wptr; - while (rptr != wptr) { -@@ -2322,17 +2516,21 @@ - case 1: /* D1 vblank/vline */ - switch (src_data) { - case 0: /* D1 vblank */ -- if (disp_int & LB_D1_VBLANK_INTERRUPT) { -- drm_handle_vblank(rdev->ddev, 0); -- rdev->pm.vblank_sync = true; -- wake_up(&rdev->irq.vblank_queue); -- disp_int &= ~LB_D1_VBLANK_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) { -+ if (rdev->irq.crtc_vblank_int[0]) { -+ drm_handle_vblank(rdev->ddev, 0); -+ rdev->pm.vblank_sync = true; -+ wake_up(&rdev->irq.vblank_queue); -+ } -+ if (rdev->irq.pflip[0]) -+ radeon_crtc_handle_flip(rdev, 0); -+ rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D1 vblank\n"); - } - break; - case 1: /* D1 vline */ -- if (disp_int & LB_D1_VLINE_INTERRUPT) { -- disp_int &= ~LB_D1_VLINE_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) { -+ rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; - DRM_DEBUG("IH: D1 vline\n"); - } - break; -@@ -2344,17 +2542,21 @@ - case 2: /* D2 vblank/vline */ - switch (src_data) { - case 0: /* D2 vblank */ -- if (disp_int_cont & LB_D2_VBLANK_INTERRUPT) { -- drm_handle_vblank(rdev->ddev, 1); -- rdev->pm.vblank_sync = true; -- wake_up(&rdev->irq.vblank_queue); -- disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) { -+ if (rdev->irq.crtc_vblank_int[1]) { -+ drm_handle_vblank(rdev->ddev, 1); -+ rdev->pm.vblank_sync = true; -+ wake_up(&rdev->irq.vblank_queue); -+ } -+ if (rdev->irq.pflip[1]) -+ radeon_crtc_handle_flip(rdev, 1); -+ rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D2 vblank\n"); - } - break; - case 1: /* D2 vline */ -- if (disp_int_cont & LB_D2_VLINE_INTERRUPT) { -- disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) { -+ rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; - DRM_DEBUG("IH: D2 vline\n"); - } - break; -@@ -2366,17 +2568,21 @@ - case 3: /* D3 vblank/vline */ - switch (src_data) { - case 0: /* D3 vblank */ -- if (disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { -- drm_handle_vblank(rdev->ddev, 2); -- rdev->pm.vblank_sync = true; -- wake_up(&rdev->irq.vblank_queue); -- disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { -+ if (rdev->irq.crtc_vblank_int[2]) { -+ drm_handle_vblank(rdev->ddev, 2); -+ rdev->pm.vblank_sync = true; -+ wake_up(&rdev->irq.vblank_queue); -+ } -+ if (rdev->irq.pflip[2]) -+ radeon_crtc_handle_flip(rdev, 2); -+ rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D3 vblank\n"); - } - break; - case 1: /* D3 vline */ -- if (disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { -- disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { -+ rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; - DRM_DEBUG("IH: D3 vline\n"); - } - break; -@@ -2388,17 +2594,21 @@ - case 4: /* D4 vblank/vline */ - switch (src_data) { - case 0: /* D4 vblank */ -- if (disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { -- drm_handle_vblank(rdev->ddev, 3); -- rdev->pm.vblank_sync = true; -- wake_up(&rdev->irq.vblank_queue); -- disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { -+ if (rdev->irq.crtc_vblank_int[3]) { -+ drm_handle_vblank(rdev->ddev, 3); -+ rdev->pm.vblank_sync = true; -+ wake_up(&rdev->irq.vblank_queue); -+ } -+ if (rdev->irq.pflip[3]) -+ radeon_crtc_handle_flip(rdev, 3); -+ rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D4 vblank\n"); - } - break; - case 1: /* D4 vline */ -- if (disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { -- disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { -+ rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; - DRM_DEBUG("IH: D4 vline\n"); - } - break; -@@ -2410,17 +2620,21 @@ - case 5: /* D5 vblank/vline */ - switch (src_data) { - case 0: /* D5 vblank */ -- if (disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { -- drm_handle_vblank(rdev->ddev, 4); -- rdev->pm.vblank_sync = true; -- wake_up(&rdev->irq.vblank_queue); -- disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { -+ if (rdev->irq.crtc_vblank_int[4]) { -+ drm_handle_vblank(rdev->ddev, 4); -+ rdev->pm.vblank_sync = true; -+ wake_up(&rdev->irq.vblank_queue); -+ } -+ if (rdev->irq.pflip[4]) -+ radeon_crtc_handle_flip(rdev, 4); -+ rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D5 vblank\n"); - } - break; - case 1: /* D5 vline */ -- if (disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { -- disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { -+ rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; - DRM_DEBUG("IH: D5 vline\n"); - } - break; -@@ -2432,17 +2646,21 @@ - case 6: /* D6 vblank/vline */ - switch (src_data) { - case 0: /* D6 vblank */ -- if (disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { -- drm_handle_vblank(rdev->ddev, 5); -- rdev->pm.vblank_sync = true; -- wake_up(&rdev->irq.vblank_queue); -- disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { -+ if (rdev->irq.crtc_vblank_int[5]) { -+ drm_handle_vblank(rdev->ddev, 5); -+ rdev->pm.vblank_sync = true; -+ wake_up(&rdev->irq.vblank_queue); -+ } -+ if (rdev->irq.pflip[5]) -+ radeon_crtc_handle_flip(rdev, 5); -+ rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D6 vblank\n"); - } - break; - case 1: /* D6 vline */ -- if (disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { -- disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { -+ rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; - DRM_DEBUG("IH: D6 vline\n"); - } - break; -@@ -2454,43 +2672,43 @@ - case 42: /* HPD hotplug */ - switch (src_data) { - case 0: -- if (disp_int & DC_HPD1_INTERRUPT) { -- disp_int &= ~DC_HPD1_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { -+ rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD1\n"); - } - break; - case 1: -- if (disp_int_cont & DC_HPD2_INTERRUPT) { -- disp_int_cont &= ~DC_HPD2_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { -+ rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD2\n"); - } - break; - case 2: -- if (disp_int_cont2 & DC_HPD3_INTERRUPT) { -- disp_int_cont2 &= ~DC_HPD3_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { -+ rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD3\n"); - } - break; - case 3: -- if (disp_int_cont3 & DC_HPD4_INTERRUPT) { -- disp_int_cont3 &= ~DC_HPD4_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { -+ rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD4\n"); - } - break; - case 4: -- if (disp_int_cont4 & DC_HPD5_INTERRUPT) { -- disp_int_cont4 &= ~DC_HPD5_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { -+ rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD5\n"); - } - break; - case 5: -- if (disp_int_cont5 & DC_HPD6_INTERRUPT) { -- disp_int_cont5 &= ~DC_HPD6_INTERRUPT; -+ if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { -+ rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD6\n"); - } -@@ -2666,12 +2884,16 @@ - u32 reg; - - /* first check CRTCs */ -- reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | -- RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) | -- RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) | -- RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) | -- RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) | -- RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); -+ if (rdev->flags & RADEON_IS_IGP) -+ reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | -+ RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); -+ else -+ reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | -+ RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) | -+ RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) | -+ RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) | -+ RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) | -+ RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); - if (reg & EVERGREEN_CRTC_MASTER_EN) - return true; - -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/evergreend.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/evergreend.h ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/evergreend.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/evergreend.h 2011-01-07 14:22:17.000000000 +0100 -@@ -164,11 +164,13 @@ - #define SE_SC_BUSY (1 << 29) - #define SE_DB_BUSY (1 << 30) - #define SE_CB_BUSY (1 << 31) -- -+/* evergreen */ - #define CG_MULT_THERMAL_STATUS 0x740 - #define ASIC_T(x) ((x) << 16) - #define ASIC_T_MASK 0x7FF0000 - #define ASIC_T_SHIFT 16 -+/* APU */ -+#define CG_THERMAL_STATUS 0x678 - - #define HDP_HOST_PATH_CNTL 0x2C00 - #define HDP_NONSURFACE_BASE 0x2C04 -@@ -180,6 +182,7 @@ - #define MC_SHARED_CHMAP 0x2004 - #define NOOFCHAN_SHIFT 12 - #define NOOFCHAN_MASK 0x00003000 -+#define MC_SHARED_CHREMAP 0x2008 - - #define MC_ARB_RAMCFG 0x2760 - #define NOOFBANK_SHIFT 0 -@@ -199,6 +202,7 @@ - #define MC_VM_AGP_BOT 0x202C - #define MC_VM_AGP_BASE 0x2030 - #define MC_VM_FB_LOCATION 0x2024 -+#define MC_FUS_VM_FB_OFFSET 0x2898 - #define MC_VM_MB_L1_TLB0_CNTL 0x2234 - #define MC_VM_MB_L1_TLB1_CNTL 0x2238 - #define MC_VM_MB_L1_TLB2_CNTL 0x223C -@@ -348,6 +352,9 @@ - #define SYNC_WALKER (1 << 25) - #define SYNC_ALIGNER (1 << 26) - -+#define TCP_CHAN_STEER_LO 0x960c -+#define TCP_CHAN_STEER_HI 0x9610 -+ - #define VGT_CACHE_INVALIDATION 0x88C4 - #define CACHE_INVALIDATION(x) ((x) << 0) - #define VC_ONLY 0 -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/evergreen_reg.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/evergreen_reg.h ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/evergreen_reg.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/evergreen_reg.h 2011-01-07 14:22:17.000000000 +0100 -@@ -105,6 +105,11 @@ - #define EVERGREEN_GRPH_Y_START 0x6830 - #define EVERGREEN_GRPH_X_END 0x6834 - #define EVERGREEN_GRPH_Y_END 0x6838 -+#define EVERGREEN_GRPH_UPDATE 0x6844 -+# define EVERGREEN_GRPH_SURFACE_UPDATE_PENDING (1 << 2) -+# define EVERGREEN_GRPH_UPDATE_LOCK (1 << 16) -+#define EVERGREEN_GRPH_FLIP_CONTROL 0x6848 -+# define EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN (1 << 0) - - /* CUR blocks at 0x6998, 0x7598, 0x10198, 0x10d98, 0x11998, 0x12598 */ - #define EVERGREEN_CUR_CONTROL 0x6998 -@@ -178,6 +183,7 @@ - # define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) - #define EVERGREEN_CRTC_STATUS 0x6e8c - #define EVERGREEN_CRTC_STATUS_POSITION 0x6e90 -+#define EVERGREEN_MASTER_UPDATE_MODE 0x6ef8 - #define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4 - - #define EVERGREEN_DC_GPIO_HPD_MASK 0x64b0 -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/Makefile linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/Makefile ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/Makefile 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/Makefile 2011-01-07 14:22:17.000000000 +0100 -@@ -65,10 +65,13 @@ - rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \ - r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ - r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \ -- evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o -+ evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \ -+ radeon_trace_points.o - - radeon-$(CONFIG_COMPAT) += radeon_ioc32.o - radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o - radeon-$(CONFIG_ACPI) += radeon_acpi.o - - obj-$(CONFIG_DRM_RADEON)+= radeon.o -+ -+CFLAGS_radeon_trace_points.o := -I$(src) -\ Kein Zeilenumbruch am Dateiende. -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/ObjectID.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/ObjectID.h ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/ObjectID.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/ObjectID.h 2011-01-07 14:22:17.000000000 +0100 -@@ -37,6 +37,8 @@ - #define GRAPH_OBJECT_TYPE_CONNECTOR 0x3 - #define GRAPH_OBJECT_TYPE_ROUTER 0x4 - /* deleted */ -+#define GRAPH_OBJECT_TYPE_DISPLAY_PATH 0x6 -+#define GRAPH_OBJECT_TYPE_GENERIC 0x7 - - /****************************************************/ - /* Encoder Object ID Definition */ -@@ -64,6 +66,9 @@ - #define ENCODER_OBJECT_ID_VT1623 0x10 - #define ENCODER_OBJECT_ID_HDMI_SI1930 0x11 - #define ENCODER_OBJECT_ID_HDMI_INTERNAL 0x12 -+#define ENCODER_OBJECT_ID_ALMOND 0x22 -+#define ENCODER_OBJECT_ID_TRAVIS 0x23 -+#define ENCODER_OBJECT_ID_NUTMEG 0x22 - /* Kaleidoscope (KLDSCP) Class Display Hardware (internal) */ - #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 0x13 - #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 0x14 -@@ -108,6 +113,7 @@ - #define CONNECTOR_OBJECT_ID_DISPLAYPORT 0x13 - #define CONNECTOR_OBJECT_ID_eDP 0x14 - #define CONNECTOR_OBJECT_ID_MXM 0x15 -+#define CONNECTOR_OBJECT_ID_LVDS_eDP 0x16 - - /* deleted */ - -@@ -124,6 +130,7 @@ - #define GENERIC_OBJECT_ID_GLSYNC 0x01 - #define GENERIC_OBJECT_ID_PX2_NON_DRIVABLE 0x02 - #define GENERIC_OBJECT_ID_MXM_OPM 0x03 -+#define GENERIC_OBJECT_ID_STEREO_PIN 0x04 //This object could show up from Misc Object table, it follows ATOM_OBJECT format, and contains one ATOM_OBJECT_GPIO_CNTL_RECORD for the stereo pin - - /****************************************************/ - /* Graphics Object ENUM ID Definition */ -@@ -360,6 +367,26 @@ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT) - -+#define ENCODER_ALMOND_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ -+ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ -+ ENCODER_OBJECT_ID_ALMOND << OBJECT_ID_SHIFT) -+ -+#define ENCODER_ALMOND_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ -+ GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ -+ ENCODER_OBJECT_ID_ALMOND << OBJECT_ID_SHIFT) -+ -+#define ENCODER_TRAVIS_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ -+ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ -+ ENCODER_OBJECT_ID_TRAVIS << OBJECT_ID_SHIFT) -+ -+#define ENCODER_TRAVIS_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ -+ GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ -+ ENCODER_OBJECT_ID_TRAVIS << OBJECT_ID_SHIFT) -+ -+#define ENCODER_NUTMEG_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ -+ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ -+ ENCODER_OBJECT_ID_NUTMEG << OBJECT_ID_SHIFT) -+ - /****************************************************/ - /* Connector Object ID definition - Shared with BIOS */ - /****************************************************/ -@@ -421,6 +448,14 @@ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) - -+#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID3 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ -+ GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\ -+ CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) -+ -+#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID4 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ -+ GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\ -+ CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) -+ - #define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT) -@@ -512,6 +547,7 @@ - #define CONNECTOR_7PIN_DIN_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT) -+ - #define CONNECTOR_7PIN_DIN_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT) -@@ -593,6 +629,14 @@ - GRAPH_OBJECT_ENUM_ID7 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_DAC - -+#define CONNECTOR_LVDS_eDP_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ -+ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ -+ CONNECTOR_OBJECT_ID_LVDS_eDP << OBJECT_ID_SHIFT) -+ -+#define CONNECTOR_LVDS_eDP_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ -+ GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ -+ CONNECTOR_OBJECT_ID_LVDS_eDP << OBJECT_ID_SHIFT) -+ - /****************************************************/ - /* Router Object ID definition - Shared with BIOS */ - /****************************************************/ -@@ -621,6 +665,10 @@ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - GENERIC_OBJECT_ID_MXM_OPM << OBJECT_ID_SHIFT) - -+#define GENERICOBJECT_STEREO_PIN_ENUM_ID1 (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\ -+ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ -+ GENERIC_OBJECT_ID_STEREO_PIN << OBJECT_ID_SHIFT) -+ - /****************************************************/ - /* Object Cap definition - Shared with BIOS */ - /****************************************************/ -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/r100.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/r100.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/r100.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/r100.c 2011-01-07 14:22:17.000000000 +0100 -@@ -68,6 +68,56 @@ - * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 - */ - -+void r100_pre_page_flip(struct radeon_device *rdev, int crtc) -+{ -+ struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; -+ u32 tmp; -+ -+ /* make sure flip is at vb rather than hb */ -+ tmp = RREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset); -+ tmp &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; -+ /* make sure pending bit is asserted */ -+ tmp |= RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN; -+ WREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset, tmp); -+ -+ /* set pageflip to happen as late as possible in the vblank interval. -+ * same field for crtc1/2 -+ */ -+ tmp = RREG32(RADEON_CRTC_GEN_CNTL); -+ tmp &= ~RADEON_CRTC_VSTAT_MODE_MASK; -+ WREG32(RADEON_CRTC_GEN_CNTL, tmp); -+ -+ /* enable the pflip int */ -+ radeon_irq_kms_pflip_irq_get(rdev, crtc); -+} -+ -+void r100_post_page_flip(struct radeon_device *rdev, int crtc) -+{ -+ /* disable the pflip int */ -+ radeon_irq_kms_pflip_irq_put(rdev, crtc); -+} -+ -+u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) -+{ -+ struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; -+ u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK; -+ -+ /* Lock the graphics update lock */ -+ /* update the scanout addresses */ -+ WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); -+ -+ /* Wait for update_pending to go high. */ -+ while (!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)); -+ DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); -+ -+ /* Unlock the lock, so double-buffering can take place inside vblank */ -+ tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK; -+ WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); -+ -+ /* Return current update_pending status: */ -+ return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET; -+} -+ - void r100_pm_get_dynpm_state(struct radeon_device *rdev) - { - int i; -@@ -526,10 +576,12 @@ - if (rdev->irq.gui_idle) { - tmp |= RADEON_GUI_IDLE_MASK; - } -- if (rdev->irq.crtc_vblank_int[0]) { -+ if (rdev->irq.crtc_vblank_int[0] || -+ rdev->irq.pflip[0]) { - tmp |= RADEON_CRTC_VBLANK_MASK; - } -- if (rdev->irq.crtc_vblank_int[1]) { -+ if (rdev->irq.crtc_vblank_int[1] || -+ rdev->irq.pflip[1]) { - tmp |= RADEON_CRTC2_VBLANK_MASK; - } - if (rdev->irq.hpd[0]) { -@@ -600,14 +652,22 @@ - } - /* Vertical blank interrupts */ - if (status & RADEON_CRTC_VBLANK_STAT) { -- drm_handle_vblank(rdev->ddev, 0); -- rdev->pm.vblank_sync = true; -- wake_up(&rdev->irq.vblank_queue); -+ if (rdev->irq.crtc_vblank_int[0]) { -+ drm_handle_vblank(rdev->ddev, 0); -+ rdev->pm.vblank_sync = true; -+ wake_up(&rdev->irq.vblank_queue); -+ } -+ if (rdev->irq.pflip[0]) -+ radeon_crtc_handle_flip(rdev, 0); - } - if (status & RADEON_CRTC2_VBLANK_STAT) { -- drm_handle_vblank(rdev->ddev, 1); -- rdev->pm.vblank_sync = true; -- wake_up(&rdev->irq.vblank_queue); -+ if (rdev->irq.crtc_vblank_int[1]) { -+ drm_handle_vblank(rdev->ddev, 1); -+ rdev->pm.vblank_sync = true; -+ wake_up(&rdev->irq.vblank_queue); -+ } -+ if (rdev->irq.pflip[1]) -+ radeon_crtc_handle_flip(rdev, 1); - } - if (status & RADEON_FP_DETECT_STAT) { - queue_hotplug = true; -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/r500_reg.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/r500_reg.h ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/r500_reg.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/r500_reg.h 2011-01-07 14:22:17.000000000 +0100 -@@ -355,6 +355,8 @@ - #define AVIVO_D1CRTC_FRAME_COUNT 0x60a4 - #define AVIVO_D1CRTC_STEREO_CONTROL 0x60c4 - -+#define AVIVO_D1MODE_MASTER_UPDATE_MODE 0x60e4 -+ - /* master controls */ - #define AVIVO_DC_CRTC_MASTER_EN 0x60f8 - #define AVIVO_DC_CRTC_TV_CONTROL 0x60fc -@@ -409,8 +411,10 @@ - #define AVIVO_D1GRPH_X_END 0x6134 - #define AVIVO_D1GRPH_Y_END 0x6138 - #define AVIVO_D1GRPH_UPDATE 0x6144 -+# define AVIVO_D1GRPH_SURFACE_UPDATE_PENDING (1 << 2) - # define AVIVO_D1GRPH_UPDATE_LOCK (1 << 16) - #define AVIVO_D1GRPH_FLIP_CONTROL 0x6148 -+# define AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN (1 << 0) - - #define AVIVO_D1CUR_CONTROL 0x6400 - # define AVIVO_D1CURSOR_EN (1 << 0) -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/r600.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/r600.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/r600.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/r600.c 2011-01-07 14:22:17.000000000 +0100 -@@ -83,6 +83,9 @@ - MODULE_FIRMWARE("radeon/CYPRESS_pfp.bin"); - MODULE_FIRMWARE("radeon/CYPRESS_me.bin"); - MODULE_FIRMWARE("radeon/CYPRESS_rlc.bin"); -+MODULE_FIRMWARE("radeon/PALM_pfp.bin"); -+MODULE_FIRMWARE("radeon/PALM_me.bin"); -+MODULE_FIRMWARE("radeon/SUMO_rlc.bin"); - - int r600_debugfs_mc_info_init(struct radeon_device *rdev); - -@@ -1161,7 +1164,7 @@ - * Note: GTT start, end, size should be initialized before calling this - * function on AGP platform. - */ --void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) -+static void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) - { - u64 size_bf, size_af; - -@@ -1998,6 +2001,10 @@ - chip_name = "CYPRESS"; - rlc_chip_name = "CYPRESS"; - break; -+ case CHIP_PALM: -+ chip_name = "PALM"; -+ rlc_chip_name = "SUMO"; -+ break; - default: BUG(); - } - -@@ -2863,6 +2870,8 @@ - WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); - WREG32(GRBM_INT_CNTL, 0); - WREG32(DxMODE_INT_MASK, 0); -+ WREG32(D1GRPH_INTERRUPT_CONTROL, 0); -+ WREG32(D2GRPH_INTERRUPT_CONTROL, 0); - if (ASIC_IS_DCE3(rdev)) { - WREG32(DCE3_DACA_AUTODETECT_INT_CONTROL, 0); - WREG32(DCE3_DACB_AUTODETECT_INT_CONTROL, 0); -@@ -2987,6 +2996,7 @@ - u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; - u32 grbm_int_cntl = 0; - u32 hdmi1, hdmi2; -+ u32 d1grph = 0, d2grph = 0; - - if (!rdev->irq.installed) { - WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); -@@ -3023,11 +3033,13 @@ - cp_int_cntl |= RB_INT_ENABLE; - cp_int_cntl |= TIME_STAMP_INT_ENABLE; - } -- if (rdev->irq.crtc_vblank_int[0]) { -+ if (rdev->irq.crtc_vblank_int[0] || -+ rdev->irq.pflip[0]) { - DRM_DEBUG("r600_irq_set: vblank 0\n"); - mode_int |= D1MODE_VBLANK_INT_MASK; - } -- if (rdev->irq.crtc_vblank_int[1]) { -+ if (rdev->irq.crtc_vblank_int[1] || -+ rdev->irq.pflip[1]) { - DRM_DEBUG("r600_irq_set: vblank 1\n"); - mode_int |= D2MODE_VBLANK_INT_MASK; - } -@@ -3070,6 +3082,8 @@ - - WREG32(CP_INT_CNTL, cp_int_cntl); - WREG32(DxMODE_INT_MASK, mode_int); -+ WREG32(D1GRPH_INTERRUPT_CONTROL, d1grph); -+ WREG32(D2GRPH_INTERRUPT_CONTROL, d2grph); - WREG32(GRBM_INT_CNTL, grbm_int_cntl); - WREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, hdmi1); - if (ASIC_IS_DCE3(rdev)) { -@@ -3092,32 +3106,35 @@ - return 0; - } - --static inline void r600_irq_ack(struct radeon_device *rdev, -- u32 *disp_int, -- u32 *disp_int_cont, -- u32 *disp_int_cont2) -+static inline void r600_irq_ack(struct radeon_device *rdev) - { - u32 tmp; - - if (ASIC_IS_DCE3(rdev)) { -- *disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); -- *disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE); -- *disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2); -- } else { -- *disp_int = RREG32(DISP_INTERRUPT_STATUS); -- *disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); -- *disp_int_cont2 = 0; -- } -- -- if (*disp_int & LB_D1_VBLANK_INTERRUPT) -+ rdev->irq.stat_regs.r600.disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); -+ rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE); -+ rdev->irq.stat_regs.r600.disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2); -+ } else { -+ rdev->irq.stat_regs.r600.disp_int = RREG32(DISP_INTERRUPT_STATUS); -+ rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); -+ rdev->irq.stat_regs.r600.disp_int_cont2 = 0; -+ } -+ rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS); -+ rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS); -+ -+ if (rdev->irq.stat_regs.r600.d1grph_int & DxGRPH_PFLIP_INT_OCCURRED) -+ WREG32(D1GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR); -+ if (rdev->irq.stat_regs.r600.d2grph_int & DxGRPH_PFLIP_INT_OCCURRED) -+ WREG32(D2GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR); -+ if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT) - WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); -- if (*disp_int & LB_D1_VLINE_INTERRUPT) -+ if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT) - WREG32(D1MODE_VLINE_STATUS, DxMODE_VLINE_ACK); -- if (*disp_int & LB_D2_VBLANK_INTERRUPT) -+ if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT) - WREG32(D2MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); -- if (*disp_int & LB_D2_VLINE_INTERRUPT) -+ if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT) - WREG32(D2MODE_VLINE_STATUS, DxMODE_VLINE_ACK); -- if (*disp_int & DC_HPD1_INTERRUPT) { -+ if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) { - if (ASIC_IS_DCE3(rdev)) { - tmp = RREG32(DC_HPD1_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; -@@ -3128,7 +3145,7 @@ - WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); - } - } -- if (*disp_int & DC_HPD2_INTERRUPT) { -+ if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) { - if (ASIC_IS_DCE3(rdev)) { - tmp = RREG32(DC_HPD2_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; -@@ -3139,7 +3156,7 @@ - WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); - } - } -- if (*disp_int_cont & DC_HPD3_INTERRUPT) { -+ if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) { - if (ASIC_IS_DCE3(rdev)) { - tmp = RREG32(DC_HPD3_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; -@@ -3150,18 +3167,18 @@ - WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); - } - } -- if (*disp_int_cont & DC_HPD4_INTERRUPT) { -+ if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) { - tmp = RREG32(DC_HPD4_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; - WREG32(DC_HPD4_INT_CONTROL, tmp); - } - if (ASIC_IS_DCE32(rdev)) { -- if (*disp_int_cont2 & DC_HPD5_INTERRUPT) { -+ if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) { - tmp = RREG32(DC_HPD5_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; - WREG32(DC_HPD5_INT_CONTROL, tmp); - } -- if (*disp_int_cont2 & DC_HPD6_INTERRUPT) { -+ if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { - tmp = RREG32(DC_HPD5_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; - WREG32(DC_HPD6_INT_CONTROL, tmp); -@@ -3183,12 +3200,10 @@ - - void r600_irq_disable(struct radeon_device *rdev) - { -- u32 disp_int, disp_int_cont, disp_int_cont2; -- - r600_disable_interrupts(rdev); - /* Wait and acknowledge irq */ - mdelay(1); -- r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2); -+ r600_irq_ack(rdev); - r600_disable_interrupt_state(rdev); - } - -@@ -3251,7 +3266,7 @@ - u32 wptr = r600_get_ih_wptr(rdev); - u32 rptr = rdev->ih.rptr; - u32 src_id, src_data; -- u32 ring_index, disp_int, disp_int_cont, disp_int_cont2; -+ u32 ring_index; - unsigned long flags; - bool queue_hotplug = false; - -@@ -3272,7 +3287,7 @@ - - restart_ih: - /* display interrupts */ -- r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2); -+ r600_irq_ack(rdev); - - rdev->ih.wptr = wptr; - while (rptr != wptr) { -@@ -3285,17 +3300,21 @@ - case 1: /* D1 vblank/vline */ - switch (src_data) { - case 0: /* D1 vblank */ -- if (disp_int & LB_D1_VBLANK_INTERRUPT) { -- drm_handle_vblank(rdev->ddev, 0); -- rdev->pm.vblank_sync = true; -- wake_up(&rdev->irq.vblank_queue); -- disp_int &= ~LB_D1_VBLANK_INTERRUPT; -+ if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT) { -+ if (rdev->irq.crtc_vblank_int[0]) { -+ drm_handle_vblank(rdev->ddev, 0); -+ rdev->pm.vblank_sync = true; -+ wake_up(&rdev->irq.vblank_queue); -+ } -+ if (rdev->irq.pflip[0]) -+ radeon_crtc_handle_flip(rdev, 0); -+ rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D1 vblank\n"); - } - break; - case 1: /* D1 vline */ -- if (disp_int & LB_D1_VLINE_INTERRUPT) { -- disp_int &= ~LB_D1_VLINE_INTERRUPT; -+ if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT) { -+ rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VLINE_INTERRUPT; - DRM_DEBUG("IH: D1 vline\n"); - } - break; -@@ -3307,17 +3326,21 @@ - case 5: /* D2 vblank/vline */ - switch (src_data) { - case 0: /* D2 vblank */ -- if (disp_int & LB_D2_VBLANK_INTERRUPT) { -- drm_handle_vblank(rdev->ddev, 1); -- rdev->pm.vblank_sync = true; -- wake_up(&rdev->irq.vblank_queue); -- disp_int &= ~LB_D2_VBLANK_INTERRUPT; -+ if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT) { -+ if (rdev->irq.crtc_vblank_int[1]) { -+ drm_handle_vblank(rdev->ddev, 1); -+ rdev->pm.vblank_sync = true; -+ wake_up(&rdev->irq.vblank_queue); -+ } -+ if (rdev->irq.pflip[1]) -+ radeon_crtc_handle_flip(rdev, 1); -+ rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D2 vblank\n"); - } - break; - case 1: /* D1 vline */ -- if (disp_int & LB_D2_VLINE_INTERRUPT) { -- disp_int &= ~LB_D2_VLINE_INTERRUPT; -+ if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT) { -+ rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VLINE_INTERRUPT; - DRM_DEBUG("IH: D2 vline\n"); - } - break; -@@ -3329,43 +3352,43 @@ - case 19: /* HPD/DAC hotplug */ - switch (src_data) { - case 0: -- if (disp_int & DC_HPD1_INTERRUPT) { -- disp_int &= ~DC_HPD1_INTERRUPT; -+ if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) { -+ rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD1_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD1\n"); - } - break; - case 1: -- if (disp_int & DC_HPD2_INTERRUPT) { -- disp_int &= ~DC_HPD2_INTERRUPT; -+ if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) { -+ rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD2_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD2\n"); - } - break; - case 4: -- if (disp_int_cont & DC_HPD3_INTERRUPT) { -- disp_int_cont &= ~DC_HPD3_INTERRUPT; -+ if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) { -+ rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD3_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD3\n"); - } - break; - case 5: -- if (disp_int_cont & DC_HPD4_INTERRUPT) { -- disp_int_cont &= ~DC_HPD4_INTERRUPT; -+ if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) { -+ rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD4_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD4\n"); - } - break; - case 10: -- if (disp_int_cont2 & DC_HPD5_INTERRUPT) { -- disp_int_cont2 &= ~DC_HPD5_INTERRUPT; -+ if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) { -+ rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD5_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD5\n"); - } - break; - case 12: -- if (disp_int_cont2 & DC_HPD6_INTERRUPT) { -- disp_int_cont2 &= ~DC_HPD6_INTERRUPT; -+ if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { -+ rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD6_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD6\n"); - } -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/r600d.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/r600d.h ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/r600d.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/r600d.h 2011-01-07 14:22:17.000000000 +0100 -@@ -728,6 +728,15 @@ - /* DCE 3.2 */ - # define DC_HPDx_EN (1 << 28) - -+#define D1GRPH_INTERRUPT_STATUS 0x6158 -+#define D2GRPH_INTERRUPT_STATUS 0x6958 -+# define DxGRPH_PFLIP_INT_OCCURRED (1 << 0) -+# define DxGRPH_PFLIP_INT_CLEAR (1 << 8) -+#define D1GRPH_INTERRUPT_CONTROL 0x615c -+#define D2GRPH_INTERRUPT_CONTROL 0x695c -+# define DxGRPH_PFLIP_INT_MASK (1 << 0) -+# define DxGRPH_PFLIP_INT_TYPE (1 << 8) -+ - /* - * PM4 - */ -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_asic.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_asic.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_asic.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_asic.c 2011-01-07 14:22:17.000000000 +0100 -@@ -171,6 +171,9 @@ - .pm_finish = &r100_pm_finish, - .pm_init_profile = &r100_pm_init_profile, - .pm_get_dynpm_state = &r100_pm_get_dynpm_state, -+ .pre_page_flip = &r100_pre_page_flip, -+ .page_flip = &r100_page_flip, -+ .post_page_flip = &r100_post_page_flip, - }; - - static struct radeon_asic r200_asic = { -@@ -215,6 +218,9 @@ - .pm_finish = &r100_pm_finish, - .pm_init_profile = &r100_pm_init_profile, - .pm_get_dynpm_state = &r100_pm_get_dynpm_state, -+ .pre_page_flip = &r100_pre_page_flip, -+ .page_flip = &r100_page_flip, -+ .post_page_flip = &r100_post_page_flip, - }; - - static struct radeon_asic r300_asic = { -@@ -260,6 +266,9 @@ - .pm_finish = &r100_pm_finish, - .pm_init_profile = &r100_pm_init_profile, - .pm_get_dynpm_state = &r100_pm_get_dynpm_state, -+ .pre_page_flip = &r100_pre_page_flip, -+ .page_flip = &r100_page_flip, -+ .post_page_flip = &r100_post_page_flip, - }; - - static struct radeon_asic r300_asic_pcie = { -@@ -304,6 +313,9 @@ - .pm_finish = &r100_pm_finish, - .pm_init_profile = &r100_pm_init_profile, - .pm_get_dynpm_state = &r100_pm_get_dynpm_state, -+ .pre_page_flip = &r100_pre_page_flip, -+ .page_flip = &r100_page_flip, -+ .post_page_flip = &r100_post_page_flip, - }; - - static struct radeon_asic r420_asic = { -@@ -349,6 +361,9 @@ - .pm_finish = &r100_pm_finish, - .pm_init_profile = &r420_pm_init_profile, - .pm_get_dynpm_state = &r100_pm_get_dynpm_state, -+ .pre_page_flip = &r100_pre_page_flip, -+ .page_flip = &r100_page_flip, -+ .post_page_flip = &r100_post_page_flip, - }; - - static struct radeon_asic rs400_asic = { -@@ -394,6 +409,9 @@ - .pm_finish = &r100_pm_finish, - .pm_init_profile = &r100_pm_init_profile, - .pm_get_dynpm_state = &r100_pm_get_dynpm_state, -+ .pre_page_flip = &r100_pre_page_flip, -+ .page_flip = &r100_page_flip, -+ .post_page_flip = &r100_post_page_flip, - }; - - static struct radeon_asic rs600_asic = { -@@ -439,6 +457,9 @@ - .pm_finish = &rs600_pm_finish, - .pm_init_profile = &r420_pm_init_profile, - .pm_get_dynpm_state = &r100_pm_get_dynpm_state, -+ .pre_page_flip = &rs600_pre_page_flip, -+ .page_flip = &rs600_page_flip, -+ .post_page_flip = &rs600_post_page_flip, - }; - - static struct radeon_asic rs690_asic = { -@@ -484,6 +505,9 @@ - .pm_finish = &rs600_pm_finish, - .pm_init_profile = &r420_pm_init_profile, - .pm_get_dynpm_state = &r100_pm_get_dynpm_state, -+ .pre_page_flip = &rs600_pre_page_flip, -+ .page_flip = &rs600_page_flip, -+ .post_page_flip = &rs600_post_page_flip, - }; - - static struct radeon_asic rv515_asic = { -@@ -529,6 +553,9 @@ - .pm_finish = &rs600_pm_finish, - .pm_init_profile = &r420_pm_init_profile, - .pm_get_dynpm_state = &r100_pm_get_dynpm_state, -+ .pre_page_flip = &rs600_pre_page_flip, -+ .page_flip = &rs600_page_flip, -+ .post_page_flip = &rs600_post_page_flip, - }; - - static struct radeon_asic r520_asic = { -@@ -574,6 +601,9 @@ - .pm_finish = &rs600_pm_finish, - .pm_init_profile = &r420_pm_init_profile, - .pm_get_dynpm_state = &r100_pm_get_dynpm_state, -+ .pre_page_flip = &rs600_pre_page_flip, -+ .page_flip = &rs600_page_flip, -+ .post_page_flip = &rs600_post_page_flip, - }; - - static struct radeon_asic r600_asic = { -@@ -618,6 +648,9 @@ - .pm_finish = &rs600_pm_finish, - .pm_init_profile = &r600_pm_init_profile, - .pm_get_dynpm_state = &r600_pm_get_dynpm_state, -+ .pre_page_flip = &rs600_pre_page_flip, -+ .page_flip = &rs600_page_flip, -+ .post_page_flip = &rs600_post_page_flip, - }; - - static struct radeon_asic rs780_asic = { -@@ -662,6 +695,9 @@ - .pm_finish = &rs600_pm_finish, - .pm_init_profile = &rs780_pm_init_profile, - .pm_get_dynpm_state = &r600_pm_get_dynpm_state, -+ .pre_page_flip = &rs600_pre_page_flip, -+ .page_flip = &rs600_page_flip, -+ .post_page_flip = &rs600_post_page_flip, - }; - - static struct radeon_asic rv770_asic = { -@@ -706,6 +742,9 @@ - .pm_finish = &rs600_pm_finish, - .pm_init_profile = &r600_pm_init_profile, - .pm_get_dynpm_state = &r600_pm_get_dynpm_state, -+ .pre_page_flip = &rs600_pre_page_flip, -+ .page_flip = &rv770_page_flip, -+ .post_page_flip = &rs600_post_page_flip, - }; - - static struct radeon_asic evergreen_asic = { -@@ -749,6 +788,52 @@ - .pm_finish = &evergreen_pm_finish, - .pm_init_profile = &r600_pm_init_profile, - .pm_get_dynpm_state = &r600_pm_get_dynpm_state, -+ .pre_page_flip = &evergreen_pre_page_flip, -+ .page_flip = &evergreen_page_flip, -+ .post_page_flip = &evergreen_post_page_flip, -+}; -+ -+static struct radeon_asic sumo_asic = { -+ .init = &evergreen_init, -+ .fini = &evergreen_fini, -+ .suspend = &evergreen_suspend, -+ .resume = &evergreen_resume, -+ .cp_commit = &r600_cp_commit, -+ .gpu_is_lockup = &evergreen_gpu_is_lockup, -+ .asic_reset = &evergreen_asic_reset, -+ .vga_set_state = &r600_vga_set_state, -+ .gart_tlb_flush = &evergreen_pcie_gart_tlb_flush, -+ .gart_set_page = &rs600_gart_set_page, -+ .ring_test = &r600_ring_test, -+ .ring_ib_execute = &r600_ring_ib_execute, -+ .irq_set = &evergreen_irq_set, -+ .irq_process = &evergreen_irq_process, -+ .get_vblank_counter = &evergreen_get_vblank_counter, -+ .fence_ring_emit = &r600_fence_ring_emit, -+ .cs_parse = &evergreen_cs_parse, -+ .copy_blit = &evergreen_copy_blit, -+ .copy_dma = &evergreen_copy_blit, -+ .copy = &evergreen_copy_blit, -+ .get_engine_clock = &radeon_atom_get_engine_clock, -+ .set_engine_clock = &radeon_atom_set_engine_clock, -+ .get_memory_clock = NULL, -+ .set_memory_clock = NULL, -+ .get_pcie_lanes = NULL, -+ .set_pcie_lanes = NULL, -+ .set_clock_gating = NULL, -+ .set_surface_reg = r600_set_surface_reg, -+ .clear_surface_reg = r600_clear_surface_reg, -+ .bandwidth_update = &evergreen_bandwidth_update, -+ .hpd_init = &evergreen_hpd_init, -+ .hpd_fini = &evergreen_hpd_fini, -+ .hpd_sense = &evergreen_hpd_sense, -+ .hpd_set_polarity = &evergreen_hpd_set_polarity, -+ .gui_idle = &r600_gui_idle, -+ .pm_misc = &evergreen_pm_misc, -+ .pm_prepare = &evergreen_pm_prepare, -+ .pm_finish = &evergreen_pm_finish, -+ .pm_init_profile = &rs780_pm_init_profile, -+ .pm_get_dynpm_state = &r600_pm_get_dynpm_state, - }; - - int radeon_asic_init(struct radeon_device *rdev) -@@ -835,6 +920,9 @@ - case CHIP_HEMLOCK: - rdev->asic = &evergreen_asic; - break; -+ case CHIP_PALM: -+ rdev->asic = &sumo_asic; -+ break; - default: - /* FIXME: not supported yet */ - return -EINVAL; -@@ -849,7 +937,9 @@ - if (rdev->flags & RADEON_SINGLE_CRTC) - rdev->num_crtc = 1; - else { -- if (ASIC_IS_DCE4(rdev)) -+ if (ASIC_IS_DCE41(rdev)) -+ rdev->num_crtc = 2; -+ else if (ASIC_IS_DCE4(rdev)) - rdev->num_crtc = 6; - else - rdev->num_crtc = 2; -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_asic.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_asic.h ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_asic.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_asic.h 2011-01-07 14:22:17.000000000 +0100 -@@ -130,6 +130,9 @@ - extern void r100_pm_finish(struct radeon_device *rdev); - extern void r100_pm_init_profile(struct radeon_device *rdev); - extern void r100_pm_get_dynpm_state(struct radeon_device *rdev); -+extern void r100_pre_page_flip(struct radeon_device *rdev, int crtc); -+extern u32 r100_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); -+extern void r100_post_page_flip(struct radeon_device *rdev, int crtc); - - /* - * r200,rv250,rs300,rv280 -@@ -205,6 +208,9 @@ - extern void rs600_pm_misc(struct radeon_device *rdev); - extern void rs600_pm_prepare(struct radeon_device *rdev); - extern void rs600_pm_finish(struct radeon_device *rdev); -+extern void rs600_pre_page_flip(struct radeon_device *rdev, int crtc); -+extern u32 rs600_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); -+extern void rs600_post_page_flip(struct radeon_device *rdev, int crtc); - - /* - * rs690,rs740 -@@ -287,6 +293,7 @@ - int rv770_suspend(struct radeon_device *rdev); - int rv770_resume(struct radeon_device *rdev); - extern void rv770_pm_misc(struct radeon_device *rdev); -+extern u32 rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); - - /* - * evergreen -@@ -314,5 +321,8 @@ - extern void evergreen_pm_misc(struct radeon_device *rdev); - extern void evergreen_pm_prepare(struct radeon_device *rdev); - extern void evergreen_pm_finish(struct radeon_device *rdev); -+extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc); -+extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); -+extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc); - - #endif -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_atombios.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_atombios.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_atombios.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_atombios.c 2011-01-07 14:22:17.000000000 +0100 -@@ -1321,6 +1321,43 @@ - return false; - } - -+static void radeon_atombios_get_igp_ss_overrides(struct radeon_device *rdev, -+ struct radeon_atom_ss *ss, -+ int id) -+{ -+ struct radeon_mode_info *mode_info = &rdev->mode_info; -+ int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); -+ u16 data_offset, size; -+ struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *igp_info; -+ u8 frev, crev; -+ u16 percentage = 0, rate = 0; -+ -+ /* get any igp specific overrides */ -+ if (atom_parse_data_header(mode_info->atom_context, index, &size, -+ &frev, &crev, &data_offset)) { -+ igp_info = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *) -+ (mode_info->atom_context->bios + data_offset); -+ switch (id) { -+ case ASIC_INTERNAL_SS_ON_TMDS: -+ percentage = le16_to_cpu(igp_info->usDVISSPercentage); -+ rate = le16_to_cpu(igp_info->usDVISSpreadRateIn10Hz); -+ break; -+ case ASIC_INTERNAL_SS_ON_HDMI: -+ percentage = le16_to_cpu(igp_info->usHDMISSPercentage); -+ rate = le16_to_cpu(igp_info->usHDMISSpreadRateIn10Hz); -+ break; -+ case ASIC_INTERNAL_SS_ON_LVDS: -+ percentage = le16_to_cpu(igp_info->usLvdsSSPercentage); -+ rate = le16_to_cpu(igp_info->usLvdsSSpreadRateIn10Hz); -+ break; -+ } -+ if (percentage) -+ ss->percentage = percentage; -+ if (rate) -+ ss->rate = rate; -+ } -+} -+ - union asic_ss_info { - struct _ATOM_ASIC_INTERNAL_SS_INFO info; - struct _ATOM_ASIC_INTERNAL_SS_INFO_V2 info_2; -@@ -1385,6 +1422,8 @@ - le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadSpectrumPercentage); - ss->type = ss_info->info_3.asSpreadSpectrum[i].ucSpreadSpectrumMode; - ss->rate = le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadRateIn10Hz); -+ if (rdev->flags & RADEON_IS_IGP) -+ radeon_atombios_get_igp_ss_overrides(rdev, ss, id); - return true; - } - } -@@ -1724,495 +1763,600 @@ - "RV6xx", - "RV770", - "adt7473", -+ "NONE", - "External GPIO", - "Evergreen", -- "adt7473 with internal", -- -+ "emc2103", -+ "Sumo", - }; - - union power_info { - struct _ATOM_POWERPLAY_INFO info; - struct _ATOM_POWERPLAY_INFO_V2 info_2; - struct _ATOM_POWERPLAY_INFO_V3 info_3; -- struct _ATOM_PPLIB_POWERPLAYTABLE info_4; -+ struct _ATOM_PPLIB_POWERPLAYTABLE pplib; -+ struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; -+ struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; - }; - --void radeon_atombios_get_power_modes(struct radeon_device *rdev) -+union pplib_clock_info { -+ struct _ATOM_PPLIB_R600_CLOCK_INFO r600; -+ struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; -+ struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; -+ struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; -+}; -+ -+union pplib_power_state { -+ struct _ATOM_PPLIB_STATE v1; -+ struct _ATOM_PPLIB_STATE_V2 v2; -+}; -+ -+static void radeon_atombios_parse_misc_flags_1_3(struct radeon_device *rdev, -+ int state_index, -+ u32 misc, u32 misc2) -+{ -+ rdev->pm.power_state[state_index].misc = misc; -+ rdev->pm.power_state[state_index].misc2 = misc2; -+ /* order matters! */ -+ if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) -+ rdev->pm.power_state[state_index].type = -+ POWER_STATE_TYPE_POWERSAVE; -+ if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE) -+ rdev->pm.power_state[state_index].type = -+ POWER_STATE_TYPE_BATTERY; -+ if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE) -+ rdev->pm.power_state[state_index].type = -+ POWER_STATE_TYPE_BATTERY; -+ if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN) -+ rdev->pm.power_state[state_index].type = -+ POWER_STATE_TYPE_BALANCED; -+ if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) { -+ rdev->pm.power_state[state_index].type = -+ POWER_STATE_TYPE_PERFORMANCE; -+ rdev->pm.power_state[state_index].flags &= -+ ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -+ } -+ if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) -+ rdev->pm.power_state[state_index].type = -+ POWER_STATE_TYPE_BALANCED; -+ if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { -+ rdev->pm.power_state[state_index].type = -+ POWER_STATE_TYPE_DEFAULT; -+ rdev->pm.default_power_state_index = state_index; -+ rdev->pm.power_state[state_index].default_clock_mode = -+ &rdev->pm.power_state[state_index].clock_info[0]; -+ } else if (state_index == 0) { -+ rdev->pm.power_state[state_index].clock_info[0].flags |= -+ RADEON_PM_MODE_NO_DISPLAY; -+ } -+} -+ -+static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) - { - struct radeon_mode_info *mode_info = &rdev->mode_info; -+ u32 misc, misc2 = 0; -+ int num_modes = 0, i; -+ int state_index = 0; -+ struct radeon_i2c_bus_rec i2c_bus; -+ union power_info *power_info; - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); -- u16 data_offset; -+ u16 data_offset; - u8 frev, crev; -- u32 misc, misc2 = 0, sclk, mclk; -- union power_info *power_info; -- struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; -- struct _ATOM_PPLIB_STATE *power_state; -- int num_modes = 0, i, j; -- int state_index = 0, mode_index = 0; -- struct radeon_i2c_bus_rec i2c_bus; -- -- rdev->pm.default_power_state_index = -1; - -- if (atom_parse_data_header(mode_info->atom_context, index, NULL, -- &frev, &crev, &data_offset)) { -- power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); -- if (frev < 4) { -- /* add the i2c bus for thermal/fan chip */ -- if (power_info->info.ucOverdriveThermalController > 0) { -- DRM_INFO("Possible %s thermal controller at 0x%02x\n", -- thermal_controller_names[power_info->info.ucOverdriveThermalController], -- power_info->info.ucOverdriveControllerAddress >> 1); -- i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine); -- rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); -- if (rdev->pm.i2c_bus) { -- struct i2c_board_info info = { }; -- const char *name = thermal_controller_names[power_info->info. -- ucOverdriveThermalController]; -- info.addr = power_info->info.ucOverdriveControllerAddress >> 1; -- strlcpy(info.type, name, sizeof(info.type)); -- i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); -- } -+ if (!atom_parse_data_header(mode_info->atom_context, index, NULL, -+ &frev, &crev, &data_offset)) -+ return state_index; -+ power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); -+ -+ /* add the i2c bus for thermal/fan chip */ -+ if (power_info->info.ucOverdriveThermalController > 0) { -+ DRM_INFO("Possible %s thermal controller at 0x%02x\n", -+ thermal_controller_names[power_info->info.ucOverdriveThermalController], -+ power_info->info.ucOverdriveControllerAddress >> 1); -+ i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine); -+ rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); -+ if (rdev->pm.i2c_bus) { -+ struct i2c_board_info info = { }; -+ const char *name = thermal_controller_names[power_info->info. -+ ucOverdriveThermalController]; -+ info.addr = power_info->info.ucOverdriveControllerAddress >> 1; -+ strlcpy(info.type, name, sizeof(info.type)); -+ i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); -+ } -+ } -+ num_modes = power_info->info.ucNumOfPowerModeEntries; -+ if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK) -+ num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK; -+ /* last mode is usually default, array is low to high */ -+ for (i = 0; i < num_modes; i++) { -+ rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; -+ switch (frev) { -+ case 1: -+ rdev->pm.power_state[state_index].num_clock_modes = 1; -+ rdev->pm.power_state[state_index].clock_info[0].mclk = -+ le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock); -+ rdev->pm.power_state[state_index].clock_info[0].sclk = -+ le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock); -+ /* skip invalid modes */ -+ if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || -+ (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) -+ continue; -+ rdev->pm.power_state[state_index].pcie_lanes = -+ power_info->info.asPowerPlayInfo[i].ucNumPciELanes; -+ misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo); -+ if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || -+ (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { -+ rdev->pm.power_state[state_index].clock_info[0].voltage.type = -+ VOLTAGE_GPIO; -+ rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = -+ radeon_lookup_gpio(rdev, -+ power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex); -+ if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) -+ rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = -+ true; -+ else -+ rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = -+ false; -+ } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { -+ rdev->pm.power_state[state_index].clock_info[0].voltage.type = -+ VOLTAGE_VDDC; -+ rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = -+ power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex; - } -- num_modes = power_info->info.ucNumOfPowerModeEntries; -- if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK) -- num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK; -- /* last mode is usually default, array is low to high */ -- for (i = 0; i < num_modes; i++) { -- rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; -- switch (frev) { -- case 1: -- rdev->pm.power_state[state_index].num_clock_modes = 1; -- rdev->pm.power_state[state_index].clock_info[0].mclk = -- le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock); -- rdev->pm.power_state[state_index].clock_info[0].sclk = -- le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock); -- /* skip invalid modes */ -- if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || -- (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) -- continue; -- rdev->pm.power_state[state_index].pcie_lanes = -- power_info->info.asPowerPlayInfo[i].ucNumPciELanes; -- misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo); -- if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || -- (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { -- rdev->pm.power_state[state_index].clock_info[0].voltage.type = -- VOLTAGE_GPIO; -- rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = -- radeon_lookup_gpio(rdev, -- power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex); -- if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) -- rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = -- true; -- else -- rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = -- false; -- } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { -- rdev->pm.power_state[state_index].clock_info[0].voltage.type = -- VOLTAGE_VDDC; -- rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = -- power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex; -- } -- rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -- rdev->pm.power_state[state_index].misc = misc; -- /* order matters! */ -- if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_POWERSAVE; -- if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE) -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_BATTERY; -- if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE) -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_BATTERY; -- if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN) -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_BALANCED; -- if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) { -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_PERFORMANCE; -- rdev->pm.power_state[state_index].flags &= -- ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -- } -- if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_DEFAULT; -- rdev->pm.default_power_state_index = state_index; -- rdev->pm.power_state[state_index].default_clock_mode = -- &rdev->pm.power_state[state_index].clock_info[0]; -- rdev->pm.power_state[state_index].flags &= -- ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -- } else if (state_index == 0) { -- rdev->pm.power_state[state_index].clock_info[0].flags |= -- RADEON_PM_MODE_NO_DISPLAY; -- } -- state_index++; -- break; -- case 2: -- rdev->pm.power_state[state_index].num_clock_modes = 1; -- rdev->pm.power_state[state_index].clock_info[0].mclk = -- le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock); -- rdev->pm.power_state[state_index].clock_info[0].sclk = -- le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock); -- /* skip invalid modes */ -- if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || -- (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) -- continue; -- rdev->pm.power_state[state_index].pcie_lanes = -- power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes; -- misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo); -- misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2); -- if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || -- (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { -- rdev->pm.power_state[state_index].clock_info[0].voltage.type = -- VOLTAGE_GPIO; -- rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = -- radeon_lookup_gpio(rdev, -- power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex); -- if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) -- rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = -- true; -- else -- rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = -- false; -- } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { -- rdev->pm.power_state[state_index].clock_info[0].voltage.type = -- VOLTAGE_VDDC; -- rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = -- power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex; -- } -- rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -- rdev->pm.power_state[state_index].misc = misc; -- rdev->pm.power_state[state_index].misc2 = misc2; -- /* order matters! */ -- if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_POWERSAVE; -- if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE) -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_BATTERY; -- if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE) -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_BATTERY; -- if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN) -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_BALANCED; -- if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) { -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_PERFORMANCE; -- rdev->pm.power_state[state_index].flags &= -- ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -- } -- if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_BALANCED; -- if (misc2 & ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT) -- rdev->pm.power_state[state_index].flags &= -- ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -- if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_DEFAULT; -- rdev->pm.default_power_state_index = state_index; -- rdev->pm.power_state[state_index].default_clock_mode = -- &rdev->pm.power_state[state_index].clock_info[0]; -- rdev->pm.power_state[state_index].flags &= -- ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -- } else if (state_index == 0) { -- rdev->pm.power_state[state_index].clock_info[0].flags |= -- RADEON_PM_MODE_NO_DISPLAY; -- } -- state_index++; -- break; -- case 3: -- rdev->pm.power_state[state_index].num_clock_modes = 1; -- rdev->pm.power_state[state_index].clock_info[0].mclk = -- le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock); -- rdev->pm.power_state[state_index].clock_info[0].sclk = -- le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock); -- /* skip invalid modes */ -- if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || -- (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) -- continue; -- rdev->pm.power_state[state_index].pcie_lanes = -- power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes; -- misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo); -- misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2); -- if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || -- (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { -- rdev->pm.power_state[state_index].clock_info[0].voltage.type = -- VOLTAGE_GPIO; -- rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = -- radeon_lookup_gpio(rdev, -- power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex); -- if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) -- rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = -- true; -- else -- rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = -- false; -- } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { -- rdev->pm.power_state[state_index].clock_info[0].voltage.type = -- VOLTAGE_VDDC; -- rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = -- power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex; -- if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) { -- rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled = -- true; -- rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id = -- power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex; -- } -- } -- rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -- rdev->pm.power_state[state_index].misc = misc; -- rdev->pm.power_state[state_index].misc2 = misc2; -- /* order matters! */ -- if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_POWERSAVE; -- if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE) -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_BATTERY; -- if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE) -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_BATTERY; -- if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN) -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_BALANCED; -- if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) { -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_PERFORMANCE; -- rdev->pm.power_state[state_index].flags &= -- ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -- } -- if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_BALANCED; -- if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_DEFAULT; -- rdev->pm.default_power_state_index = state_index; -- rdev->pm.power_state[state_index].default_clock_mode = -- &rdev->pm.power_state[state_index].clock_info[0]; -- } else if (state_index == 0) { -- rdev->pm.power_state[state_index].clock_info[0].flags |= -- RADEON_PM_MODE_NO_DISPLAY; -- } -- state_index++; -- break; -- } -+ rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -+ radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, 0); -+ state_index++; -+ break; -+ case 2: -+ rdev->pm.power_state[state_index].num_clock_modes = 1; -+ rdev->pm.power_state[state_index].clock_info[0].mclk = -+ le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock); -+ rdev->pm.power_state[state_index].clock_info[0].sclk = -+ le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock); -+ /* skip invalid modes */ -+ if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || -+ (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) -+ continue; -+ rdev->pm.power_state[state_index].pcie_lanes = -+ power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes; -+ misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo); -+ misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2); -+ if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || -+ (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { -+ rdev->pm.power_state[state_index].clock_info[0].voltage.type = -+ VOLTAGE_GPIO; -+ rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = -+ radeon_lookup_gpio(rdev, -+ power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex); -+ if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) -+ rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = -+ true; -+ else -+ rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = -+ false; -+ } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { -+ rdev->pm.power_state[state_index].clock_info[0].voltage.type = -+ VOLTAGE_VDDC; -+ rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = -+ power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex; - } -- /* last mode is usually default */ -- if (rdev->pm.default_power_state_index == -1) { -- rdev->pm.power_state[state_index - 1].type = -- POWER_STATE_TYPE_DEFAULT; -- rdev->pm.default_power_state_index = state_index - 1; -- rdev->pm.power_state[state_index - 1].default_clock_mode = -- &rdev->pm.power_state[state_index - 1].clock_info[0]; -- rdev->pm.power_state[state_index].flags &= -- ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -- rdev->pm.power_state[state_index].misc = 0; -- rdev->pm.power_state[state_index].misc2 = 0; -+ rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -+ radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2); -+ state_index++; -+ break; -+ case 3: -+ rdev->pm.power_state[state_index].num_clock_modes = 1; -+ rdev->pm.power_state[state_index].clock_info[0].mclk = -+ le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock); -+ rdev->pm.power_state[state_index].clock_info[0].sclk = -+ le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock); -+ /* skip invalid modes */ -+ if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || -+ (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) -+ continue; -+ rdev->pm.power_state[state_index].pcie_lanes = -+ power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes; -+ misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo); -+ misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2); -+ if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || -+ (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { -+ rdev->pm.power_state[state_index].clock_info[0].voltage.type = -+ VOLTAGE_GPIO; -+ rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = -+ radeon_lookup_gpio(rdev, -+ power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex); -+ if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) -+ rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = -+ true; -+ else -+ rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = -+ false; -+ } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { -+ rdev->pm.power_state[state_index].clock_info[0].voltage.type = -+ VOLTAGE_VDDC; -+ rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = -+ power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex; -+ if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) { -+ rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled = -+ true; -+ rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id = -+ power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex; -+ } - } -+ rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -+ radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2); -+ state_index++; -+ break; -+ } -+ } -+ /* last mode is usually default */ -+ if (rdev->pm.default_power_state_index == -1) { -+ rdev->pm.power_state[state_index - 1].type = -+ POWER_STATE_TYPE_DEFAULT; -+ rdev->pm.default_power_state_index = state_index - 1; -+ rdev->pm.power_state[state_index - 1].default_clock_mode = -+ &rdev->pm.power_state[state_index - 1].clock_info[0]; -+ rdev->pm.power_state[state_index].flags &= -+ ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -+ rdev->pm.power_state[state_index].misc = 0; -+ rdev->pm.power_state[state_index].misc2 = 0; -+ } -+ return state_index; -+} -+ -+static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *rdev, -+ ATOM_PPLIB_THERMALCONTROLLER *controller) -+{ -+ struct radeon_i2c_bus_rec i2c_bus; -+ -+ /* add the i2c bus for thermal/fan chip */ -+ if (controller->ucType > 0) { -+ if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { -+ DRM_INFO("Internal thermal controller %s fan control\n", -+ (controller->ucFanParameters & -+ ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); -+ rdev->pm.int_thermal_type = THERMAL_TYPE_RV6XX; -+ } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) { -+ DRM_INFO("Internal thermal controller %s fan control\n", -+ (controller->ucFanParameters & -+ ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); -+ rdev->pm.int_thermal_type = THERMAL_TYPE_RV770; -+ } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) { -+ DRM_INFO("Internal thermal controller %s fan control\n", -+ (controller->ucFanParameters & -+ ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); -+ rdev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN; -+ } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) { -+ DRM_INFO("Internal thermal controller %s fan control\n", -+ (controller->ucFanParameters & -+ ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); -+ rdev->pm.int_thermal_type = THERMAL_TYPE_SUMO; -+ } else if ((controller->ucType == -+ ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) || -+ (controller->ucType == -+ ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) || -+ (controller->ucType == -+ ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL)) { -+ DRM_INFO("Special thermal controller config\n"); - } else { -- int fw_index = GetIndexIntoMasterTable(DATA, FirmwareInfo); -- uint8_t fw_frev, fw_crev; -- uint16_t fw_data_offset, vddc = 0; -- union firmware_info *firmware_info; -- ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController; -- -- if (atom_parse_data_header(mode_info->atom_context, fw_index, NULL, -- &fw_frev, &fw_crev, &fw_data_offset)) { -- firmware_info = -- (union firmware_info *)(mode_info->atom_context->bios + -- fw_data_offset); -- vddc = firmware_info->info_14.usBootUpVDDCVoltage; -+ DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", -+ pp_lib_thermal_controller_names[controller->ucType], -+ controller->ucI2cAddress >> 1, -+ (controller->ucFanParameters & -+ ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); -+ i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); -+ rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); -+ if (rdev->pm.i2c_bus) { -+ struct i2c_board_info info = { }; -+ const char *name = pp_lib_thermal_controller_names[controller->ucType]; -+ info.addr = controller->ucI2cAddress >> 1; -+ strlcpy(info.type, name, sizeof(info.type)); -+ i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); - } -+ } -+ } -+} - -- /* add the i2c bus for thermal/fan chip */ -- if (controller->ucType > 0) { -- if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { -- DRM_INFO("Internal thermal controller %s fan control\n", -- (controller->ucFanParameters & -- ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); -- rdev->pm.int_thermal_type = THERMAL_TYPE_RV6XX; -- } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) { -- DRM_INFO("Internal thermal controller %s fan control\n", -- (controller->ucFanParameters & -- ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); -- rdev->pm.int_thermal_type = THERMAL_TYPE_RV770; -- } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) { -- DRM_INFO("Internal thermal controller %s fan control\n", -- (controller->ucFanParameters & -- ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); -- rdev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN; -- } else if ((controller->ucType == -- ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) || -- (controller->ucType == -- ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL)) { -- DRM_INFO("Special thermal controller config\n"); -- } else { -- DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", -- pp_lib_thermal_controller_names[controller->ucType], -- controller->ucI2cAddress >> 1, -- (controller->ucFanParameters & -- ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); -- i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); -- rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); -- if (rdev->pm.i2c_bus) { -- struct i2c_board_info info = { }; -- const char *name = pp_lib_thermal_controller_names[controller->ucType]; -- info.addr = controller->ucI2cAddress >> 1; -- strlcpy(info.type, name, sizeof(info.type)); -- i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); -- } -+static u16 radeon_atombios_get_default_vddc(struct radeon_device *rdev) -+{ -+ struct radeon_mode_info *mode_info = &rdev->mode_info; -+ int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); -+ u8 frev, crev; -+ u16 data_offset; -+ union firmware_info *firmware_info; -+ u16 vddc = 0; - -- } -- } -- /* first mode is usually default, followed by low to high */ -- for (i = 0; i < power_info->info_4.ucNumStates; i++) { -- mode_index = 0; -- power_state = (struct _ATOM_PPLIB_STATE *) -- (mode_info->atom_context->bios + -- data_offset + -- le16_to_cpu(power_info->info_4.usStateArrayOffset) + -- i * power_info->info_4.ucStateEntrySize); -- non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) -- (mode_info->atom_context->bios + -- data_offset + -- le16_to_cpu(power_info->info_4.usNonClockInfoArrayOffset) + -- (power_state->ucNonClockStateIndex * -- power_info->info_4.ucNonClockSize)); -- for (j = 0; j < (power_info->info_4.ucStateEntrySize - 1); j++) { -- if (rdev->flags & RADEON_IS_IGP) { -- struct _ATOM_PPLIB_RS780_CLOCK_INFO *clock_info = -- (struct _ATOM_PPLIB_RS780_CLOCK_INFO *) -- (mode_info->atom_context->bios + -- data_offset + -- le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) + -- (power_state->ucClockStateIndices[j] * -- power_info->info_4.ucClockInfoSize)); -- sclk = le16_to_cpu(clock_info->usLowEngineClockLow); -- sclk |= clock_info->ucLowEngineClockHigh << 16; -- rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; -- /* skip invalid modes */ -- if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0) -- continue; -- /* voltage works differently on IGPs */ -- mode_index++; -- } else if (ASIC_IS_DCE4(rdev)) { -- struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *clock_info = -- (struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *) -- (mode_info->atom_context->bios + -- data_offset + -- le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) + -- (power_state->ucClockStateIndices[j] * -- power_info->info_4.ucClockInfoSize)); -- sclk = le16_to_cpu(clock_info->usEngineClockLow); -- sclk |= clock_info->ucEngineClockHigh << 16; -- mclk = le16_to_cpu(clock_info->usMemoryClockLow); -- mclk |= clock_info->ucMemoryClockHigh << 16; -- rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; -- rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; -- /* skip invalid modes */ -- if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) || -- (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)) -- continue; -- rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = -- VOLTAGE_SW; -- rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = -- clock_info->usVDDC; -- /* XXX usVDDCI */ -- mode_index++; -- } else { -- struct _ATOM_PPLIB_R600_CLOCK_INFO *clock_info = -- (struct _ATOM_PPLIB_R600_CLOCK_INFO *) -- (mode_info->atom_context->bios + -- data_offset + -- le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) + -- (power_state->ucClockStateIndices[j] * -- power_info->info_4.ucClockInfoSize)); -- sclk = le16_to_cpu(clock_info->usEngineClockLow); -- sclk |= clock_info->ucEngineClockHigh << 16; -- mclk = le16_to_cpu(clock_info->usMemoryClockLow); -- mclk |= clock_info->ucMemoryClockHigh << 16; -- rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; -- rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; -- /* skip invalid modes */ -- if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) || -- (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)) -- continue; -- rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = -- VOLTAGE_SW; -- rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = -- clock_info->usVDDC; -- mode_index++; -- } -- } -- rdev->pm.power_state[state_index].num_clock_modes = mode_index; -- if (mode_index) { -- misc = le32_to_cpu(non_clock_info->ulCapsAndSettings); -- misc2 = le16_to_cpu(non_clock_info->usClassification); -- rdev->pm.power_state[state_index].misc = misc; -- rdev->pm.power_state[state_index].misc2 = misc2; -- rdev->pm.power_state[state_index].pcie_lanes = -- ((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> -- ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; -- switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { -- case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_BATTERY; -- break; -- case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_BALANCED; -- break; -- case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_PERFORMANCE; -- break; -- case ATOM_PPLIB_CLASSIFICATION_UI_NONE: -- if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_PERFORMANCE; -- break; -- } -- rdev->pm.power_state[state_index].flags = 0; -- if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) -- rdev->pm.power_state[state_index].flags |= -- RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -- if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) { -- rdev->pm.power_state[state_index].type = -- POWER_STATE_TYPE_DEFAULT; -- rdev->pm.default_power_state_index = state_index; -- rdev->pm.power_state[state_index].default_clock_mode = -- &rdev->pm.power_state[state_index].clock_info[mode_index - 1]; -- /* patch the table values with the default slck/mclk from firmware info */ -- for (j = 0; j < mode_index; j++) { -- rdev->pm.power_state[state_index].clock_info[j].mclk = -- rdev->clock.default_mclk; -- rdev->pm.power_state[state_index].clock_info[j].sclk = -- rdev->clock.default_sclk; -- if (vddc) -- rdev->pm.power_state[state_index].clock_info[j].voltage.voltage = -- vddc; -- } -- } -- state_index++; -- } -- } -- /* if multiple clock modes, mark the lowest as no display */ -- for (i = 0; i < state_index; i++) { -- if (rdev->pm.power_state[i].num_clock_modes > 1) -- rdev->pm.power_state[i].clock_info[0].flags |= -- RADEON_PM_MODE_NO_DISPLAY; -- } -- /* first mode is usually default */ -- if (rdev->pm.default_power_state_index == -1) { -- rdev->pm.power_state[0].type = -- POWER_STATE_TYPE_DEFAULT; -- rdev->pm.default_power_state_index = 0; -- rdev->pm.power_state[0].default_clock_mode = -- &rdev->pm.power_state[0].clock_info[0]; -- } -+ if (atom_parse_data_header(mode_info->atom_context, index, NULL, -+ &frev, &crev, &data_offset)) { -+ firmware_info = -+ (union firmware_info *)(mode_info->atom_context->bios + -+ data_offset); -+ vddc = firmware_info->info_14.usBootUpVDDCVoltage; -+ } -+ -+ return vddc; -+} -+ -+static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev, -+ int state_index, int mode_index, -+ struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info) -+{ -+ int j; -+ u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings); -+ u32 misc2 = le16_to_cpu(non_clock_info->usClassification); -+ u16 vddc = radeon_atombios_get_default_vddc(rdev); -+ -+ rdev->pm.power_state[state_index].misc = misc; -+ rdev->pm.power_state[state_index].misc2 = misc2; -+ rdev->pm.power_state[state_index].pcie_lanes = -+ ((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> -+ ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; -+ switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { -+ case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: -+ rdev->pm.power_state[state_index].type = -+ POWER_STATE_TYPE_BATTERY; -+ break; -+ case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: -+ rdev->pm.power_state[state_index].type = -+ POWER_STATE_TYPE_BALANCED; -+ break; -+ case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: -+ rdev->pm.power_state[state_index].type = -+ POWER_STATE_TYPE_PERFORMANCE; -+ break; -+ case ATOM_PPLIB_CLASSIFICATION_UI_NONE: -+ if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) -+ rdev->pm.power_state[state_index].type = -+ POWER_STATE_TYPE_PERFORMANCE; -+ break; -+ } -+ rdev->pm.power_state[state_index].flags = 0; -+ if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) -+ rdev->pm.power_state[state_index].flags |= -+ RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; -+ if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) { -+ rdev->pm.power_state[state_index].type = -+ POWER_STATE_TYPE_DEFAULT; -+ rdev->pm.default_power_state_index = state_index; -+ rdev->pm.power_state[state_index].default_clock_mode = -+ &rdev->pm.power_state[state_index].clock_info[mode_index - 1]; -+ /* patch the table values with the default slck/mclk from firmware info */ -+ for (j = 0; j < mode_index; j++) { -+ rdev->pm.power_state[state_index].clock_info[j].mclk = -+ rdev->clock.default_mclk; -+ rdev->pm.power_state[state_index].clock_info[j].sclk = -+ rdev->clock.default_sclk; -+ if (vddc) -+ rdev->pm.power_state[state_index].clock_info[j].voltage.voltage = -+ vddc; -+ } -+ } -+} -+ -+static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev, -+ int state_index, int mode_index, -+ union pplib_clock_info *clock_info) -+{ -+ u32 sclk, mclk; -+ -+ if (rdev->flags & RADEON_IS_IGP) { -+ if (rdev->family >= CHIP_PALM) { -+ sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); -+ sclk |= clock_info->sumo.ucEngineClockHigh << 16; -+ rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; -+ } else { -+ sclk = le16_to_cpu(clock_info->rs780.usLowEngineClockLow); -+ sclk |= clock_info->rs780.ucLowEngineClockHigh << 16; -+ rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; -+ } -+ } else if (ASIC_IS_DCE4(rdev)) { -+ sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow); -+ sclk |= clock_info->evergreen.ucEngineClockHigh << 16; -+ mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow); -+ mclk |= clock_info->evergreen.ucMemoryClockHigh << 16; -+ rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; -+ rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; -+ rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = -+ VOLTAGE_SW; -+ rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = -+ clock_info->evergreen.usVDDC; -+ } else { -+ sclk = le16_to_cpu(clock_info->r600.usEngineClockLow); -+ sclk |= clock_info->r600.ucEngineClockHigh << 16; -+ mclk = le16_to_cpu(clock_info->r600.usMemoryClockLow); -+ mclk |= clock_info->r600.ucMemoryClockHigh << 16; -+ rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; -+ rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; -+ rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = -+ VOLTAGE_SW; -+ rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = -+ clock_info->r600.usVDDC; -+ } -+ -+ if (rdev->flags & RADEON_IS_IGP) { -+ /* skip invalid modes */ -+ if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0) -+ return false; -+ } else { -+ /* skip invalid modes */ -+ if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) || -+ (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)) -+ return false; -+ } -+ return true; -+} -+ -+static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev) -+{ -+ struct radeon_mode_info *mode_info = &rdev->mode_info; -+ struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; -+ union pplib_power_state *power_state; -+ int i, j; -+ int state_index = 0, mode_index = 0; -+ union pplib_clock_info *clock_info; -+ bool valid; -+ union power_info *power_info; -+ int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); -+ u16 data_offset; -+ u8 frev, crev; -+ -+ if (!atom_parse_data_header(mode_info->atom_context, index, NULL, -+ &frev, &crev, &data_offset)) -+ return state_index; -+ power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); -+ -+ radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); -+ /* first mode is usually default, followed by low to high */ -+ for (i = 0; i < power_info->pplib.ucNumStates; i++) { -+ mode_index = 0; -+ power_state = (union pplib_power_state *) -+ (mode_info->atom_context->bios + data_offset + -+ le16_to_cpu(power_info->pplib.usStateArrayOffset) + -+ i * power_info->pplib.ucStateEntrySize); -+ non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) -+ (mode_info->atom_context->bios + data_offset + -+ le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) + -+ (power_state->v1.ucNonClockStateIndex * -+ power_info->pplib.ucNonClockSize)); -+ for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) { -+ clock_info = (union pplib_clock_info *) -+ (mode_info->atom_context->bios + data_offset + -+ le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) + -+ (power_state->v1.ucClockStateIndices[j] * -+ power_info->pplib.ucClockInfoSize)); -+ valid = radeon_atombios_parse_pplib_clock_info(rdev, -+ state_index, mode_index, -+ clock_info); -+ if (valid) -+ mode_index++; -+ } -+ rdev->pm.power_state[state_index].num_clock_modes = mode_index; -+ if (mode_index) { -+ radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index, -+ non_clock_info); -+ state_index++; -+ } -+ } -+ /* if multiple clock modes, mark the lowest as no display */ -+ for (i = 0; i < state_index; i++) { -+ if (rdev->pm.power_state[i].num_clock_modes > 1) -+ rdev->pm.power_state[i].clock_info[0].flags |= -+ RADEON_PM_MODE_NO_DISPLAY; -+ } -+ /* first mode is usually default */ -+ if (rdev->pm.default_power_state_index == -1) { -+ rdev->pm.power_state[0].type = -+ POWER_STATE_TYPE_DEFAULT; -+ rdev->pm.default_power_state_index = 0; -+ rdev->pm.power_state[0].default_clock_mode = -+ &rdev->pm.power_state[0].clock_info[0]; -+ } -+ return state_index; -+} -+ -+static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) -+{ -+ struct radeon_mode_info *mode_info = &rdev->mode_info; -+ struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; -+ union pplib_power_state *power_state; -+ int i, j, non_clock_array_index, clock_array_index; -+ int state_index = 0, mode_index = 0; -+ union pplib_clock_info *clock_info; -+ struct StateArray *state_array; -+ struct ClockInfoArray *clock_info_array; -+ struct NonClockInfoArray *non_clock_info_array; -+ bool valid; -+ union power_info *power_info; -+ int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); -+ u16 data_offset; -+ u8 frev, crev; -+ -+ if (!atom_parse_data_header(mode_info->atom_context, index, NULL, -+ &frev, &crev, &data_offset)) -+ return state_index; -+ power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); -+ -+ radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); -+ state_array = (struct StateArray *) -+ (mode_info->atom_context->bios + data_offset + -+ power_info->pplib.usStateArrayOffset); -+ clock_info_array = (struct ClockInfoArray *) -+ (mode_info->atom_context->bios + data_offset + -+ power_info->pplib.usClockInfoArrayOffset); -+ non_clock_info_array = (struct NonClockInfoArray *) -+ (mode_info->atom_context->bios + data_offset + -+ power_info->pplib.usNonClockInfoArrayOffset); -+ for (i = 0; i < state_array->ucNumEntries; i++) { -+ mode_index = 0; -+ power_state = (union pplib_power_state *)&state_array->states[i]; -+ /* XXX this might be an inagua bug... */ -+ non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */ -+ non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) -+ &non_clock_info_array->nonClockInfo[non_clock_array_index]; -+ for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { -+ clock_array_index = power_state->v2.clockInfoIndex[j]; -+ /* XXX this might be an inagua bug... */ -+ if (clock_array_index >= clock_info_array->ucNumEntries) -+ continue; -+ clock_info = (union pplib_clock_info *) -+ &clock_info_array->clockInfo[clock_array_index]; -+ valid = radeon_atombios_parse_pplib_clock_info(rdev, -+ state_index, mode_index, -+ clock_info); -+ if (valid) -+ mode_index++; -+ } -+ rdev->pm.power_state[state_index].num_clock_modes = mode_index; -+ if (mode_index) { -+ radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index, -+ non_clock_info); -+ state_index++; -+ } -+ } -+ /* if multiple clock modes, mark the lowest as no display */ -+ for (i = 0; i < state_index; i++) { -+ if (rdev->pm.power_state[i].num_clock_modes > 1) -+ rdev->pm.power_state[i].clock_info[0].flags |= -+ RADEON_PM_MODE_NO_DISPLAY; -+ } -+ /* first mode is usually default */ -+ if (rdev->pm.default_power_state_index == -1) { -+ rdev->pm.power_state[0].type = -+ POWER_STATE_TYPE_DEFAULT; -+ rdev->pm.default_power_state_index = 0; -+ rdev->pm.power_state[0].default_clock_mode = -+ &rdev->pm.power_state[0].clock_info[0]; -+ } -+ return state_index; -+} -+ -+void radeon_atombios_get_power_modes(struct radeon_device *rdev) -+{ -+ struct radeon_mode_info *mode_info = &rdev->mode_info; -+ int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); -+ u16 data_offset; -+ u8 frev, crev; -+ int state_index = 0; -+ -+ rdev->pm.default_power_state_index = -1; -+ -+ if (atom_parse_data_header(mode_info->atom_context, index, NULL, -+ &frev, &crev, &data_offset)) { -+ switch (frev) { -+ case 1: -+ case 2: -+ case 3: -+ state_index = radeon_atombios_parse_power_table_1_3(rdev); -+ break; -+ case 4: -+ case 5: -+ state_index = radeon_atombios_parse_power_table_4_5(rdev); -+ break; -+ case 6: -+ state_index = radeon_atombios_parse_power_table_6(rdev); -+ break; -+ default: -+ break; - } - } else { - /* add the default mode */ -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_cs.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_cs.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_cs.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_cs.c 2011-01-07 14:22:17.000000000 +0100 -@@ -77,13 +77,13 @@ - p->relocs_ptr[i] = &p->relocs[i]; - p->relocs[i].robj = p->relocs[i].gobj->driver_private; - p->relocs[i].lobj.bo = p->relocs[i].robj; -- p->relocs[i].lobj.rdomain = r->read_domains; - p->relocs[i].lobj.wdomain = r->write_domain; -+ p->relocs[i].lobj.rdomain = r->read_domains; -+ p->relocs[i].lobj.tv.bo = &p->relocs[i].robj->tbo; - p->relocs[i].handle = r->handle; - p->relocs[i].flags = r->flags; -- INIT_LIST_HEAD(&p->relocs[i].lobj.list); - radeon_bo_list_add_object(&p->relocs[i].lobj, -- &p->validated); -+ &p->validated); - } - } - return radeon_bo_list_validate(&p->validated); -@@ -189,10 +189,13 @@ - { - unsigned i; - -- if (!error && parser->ib) { -- radeon_bo_list_fence(&parser->validated, parser->ib->fence); -- } -- radeon_bo_list_unreserve(&parser->validated); -+ -+ if (!error && parser->ib) -+ ttm_eu_fence_buffer_objects(&parser->validated, -+ parser->ib->fence); -+ else -+ ttm_eu_backoff_reservation(&parser->validated); -+ - if (parser->relocs != NULL) { - for (i = 0; i < parser->nrelocs; i++) { - if (parser->relocs[i].gobj) -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_device.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_device.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_device.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_device.c 2011-01-07 14:22:17.000000000 +0100 -@@ -81,6 +81,7 @@ - "JUNIPER", - "CYPRESS", - "HEMLOCK", -+ "PALM", - "LAST", - }; - -@@ -335,7 +336,12 @@ - uint32_t reg; - - /* first check CRTCs */ -- if (ASIC_IS_DCE4(rdev)) { -+ if (ASIC_IS_DCE41(rdev)) { -+ reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | -+ RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); -+ if (reg & EVERGREEN_CRTC_MASTER_EN) -+ return true; -+ } else if (ASIC_IS_DCE4(rdev)) { - reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) | -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_display.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_display.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_display.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_display.c 2011-01-07 14:22:17.000000000 +0100 -@@ -183,12 +183,272 @@ - kfree(radeon_crtc); - } - -+/* -+ * Handle unpin events outside the interrupt handler proper. -+ */ -+static void radeon_unpin_work_func(struct work_struct *__work) -+{ -+ struct radeon_unpin_work *work = -+ container_of(__work, struct radeon_unpin_work, work); -+ int r; -+ -+ /* unpin of the old buffer */ -+ r = radeon_bo_reserve(work->old_rbo, false); -+ if (likely(r == 0)) { -+ r = radeon_bo_unpin(work->old_rbo); -+ if (unlikely(r != 0)) { -+ DRM_ERROR("failed to unpin buffer after flip\n"); -+ } -+ radeon_bo_unreserve(work->old_rbo); -+ } else -+ DRM_ERROR("failed to reserve buffer after flip\n"); -+ kfree(work); -+} -+ -+void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) -+{ -+ struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; -+ struct radeon_unpin_work *work; -+ struct drm_pending_vblank_event *e; -+ struct timeval now; -+ unsigned long flags; -+ u32 update_pending; -+ int vpos, hpos; -+ -+ spin_lock_irqsave(&rdev->ddev->event_lock, flags); -+ work = radeon_crtc->unpin_work; -+ if (work == NULL || -+ !radeon_fence_signaled(work->fence)) { -+ spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); -+ return; -+ } -+ /* New pageflip, or just completion of a previous one? */ -+ if (!radeon_crtc->deferred_flip_completion) { -+ /* do the flip (mmio) */ -+ update_pending = radeon_page_flip(rdev, crtc_id, work->new_crtc_base); -+ } else { -+ /* This is just a completion of a flip queued in crtc -+ * at last invocation. Make sure we go directly to -+ * completion routine. -+ */ -+ update_pending = 0; -+ radeon_crtc->deferred_flip_completion = 0; -+ } -+ -+ /* Has the pageflip already completed in crtc, or is it certain -+ * to complete in this vblank? -+ */ -+ if (update_pending && -+ (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, -+ &vpos, &hpos)) && -+ (vpos >=0) && -+ (vpos < (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100)) { -+ /* crtc didn't flip in this target vblank interval, -+ * but flip is pending in crtc. It will complete it -+ * in next vblank interval, so complete the flip at -+ * next vblank irq. -+ */ -+ radeon_crtc->deferred_flip_completion = 1; -+ spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); -+ return; -+ } -+ -+ /* Pageflip (will be) certainly completed in this vblank. Clean up. */ -+ radeon_crtc->unpin_work = NULL; -+ -+ /* wakeup userspace */ -+ if (work->event) { -+ e = work->event; -+ e->event.sequence = drm_vblank_count_and_time(rdev->ddev, crtc_id, &now); -+ e->event.tv_sec = now.tv_sec; -+ e->event.tv_usec = now.tv_usec; -+ list_add_tail(&e->base.link, &e->base.file_priv->event_list); -+ wake_up_interruptible(&e->base.file_priv->event_wait); -+ } -+ spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); -+ -+ drm_vblank_put(rdev->ddev, radeon_crtc->crtc_id); -+ radeon_fence_unref(&work->fence); -+ radeon_post_page_flip(work->rdev, work->crtc_id); -+ schedule_work(&work->work); -+} -+ -+static int radeon_crtc_page_flip(struct drm_crtc *crtc, -+ struct drm_framebuffer *fb, -+ struct drm_pending_vblank_event *event) -+{ -+ struct drm_device *dev = crtc->dev; -+ struct radeon_device *rdev = dev->dev_private; -+ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); -+ struct radeon_framebuffer *old_radeon_fb; -+ struct radeon_framebuffer *new_radeon_fb; -+ struct drm_gem_object *obj; -+ struct radeon_bo *rbo; -+ struct radeon_fence *fence; -+ struct radeon_unpin_work *work; -+ unsigned long flags; -+ u32 tiling_flags, pitch_pixels; -+ u64 base; -+ int r; -+ -+ work = kzalloc(sizeof *work, GFP_KERNEL); -+ if (work == NULL) -+ return -ENOMEM; -+ -+ r = radeon_fence_create(rdev, &fence); -+ if (unlikely(r != 0)) { -+ kfree(work); -+ DRM_ERROR("flip queue: failed to create fence.\n"); -+ return -ENOMEM; -+ } -+ work->event = event; -+ work->rdev = rdev; -+ work->crtc_id = radeon_crtc->crtc_id; -+ work->fence = radeon_fence_ref(fence); -+ old_radeon_fb = to_radeon_framebuffer(crtc->fb); -+ new_radeon_fb = to_radeon_framebuffer(fb); -+ /* schedule unpin of the old buffer */ -+ obj = old_radeon_fb->obj; -+ rbo = obj->driver_private; -+ work->old_rbo = rbo; -+ INIT_WORK(&work->work, radeon_unpin_work_func); -+ -+ /* We borrow the event spin lock for protecting unpin_work */ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ if (radeon_crtc->unpin_work) { -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ kfree(work); -+ radeon_fence_unref(&fence); -+ -+ DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); -+ return -EBUSY; -+ } -+ radeon_crtc->unpin_work = work; -+ radeon_crtc->deferred_flip_completion = 0; -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ -+ /* pin the new buffer */ -+ obj = new_radeon_fb->obj; -+ rbo = obj->driver_private; -+ -+ DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n", -+ work->old_rbo, rbo); -+ -+ r = radeon_bo_reserve(rbo, false); -+ if (unlikely(r != 0)) { -+ DRM_ERROR("failed to reserve new rbo buffer before flip\n"); -+ goto pflip_cleanup; -+ } -+ r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &base); -+ if (unlikely(r != 0)) { -+ radeon_bo_unreserve(rbo); -+ r = -EINVAL; -+ DRM_ERROR("failed to pin new rbo buffer before flip\n"); -+ goto pflip_cleanup; -+ } -+ radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); -+ radeon_bo_unreserve(rbo); -+ -+ if (!ASIC_IS_AVIVO(rdev)) { -+ /* crtc offset is from display base addr not FB location */ -+ base -= radeon_crtc->legacy_display_base_addr; -+ pitch_pixels = fb->pitch / (fb->bits_per_pixel / 8); -+ -+ if (tiling_flags & RADEON_TILING_MACRO) { -+ if (ASIC_IS_R300(rdev)) { -+ base &= ~0x7ff; -+ } else { -+ int byteshift = fb->bits_per_pixel >> 4; -+ int tile_addr = (((crtc->y >> 3) * pitch_pixels + crtc->x) >> (8 - byteshift)) << 11; -+ base += tile_addr + ((crtc->x << byteshift) % 256) + ((crtc->y % 8) << 8); -+ } -+ } else { -+ int offset = crtc->y * pitch_pixels + crtc->x; -+ switch (fb->bits_per_pixel) { -+ case 8: -+ default: -+ offset *= 1; -+ break; -+ case 15: -+ case 16: -+ offset *= 2; -+ break; -+ case 24: -+ offset *= 3; -+ break; -+ case 32: -+ offset *= 4; -+ break; -+ } -+ base += offset; -+ } -+ base &= ~7; -+ } -+ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ work->new_crtc_base = base; -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ -+ /* update crtc fb */ -+ crtc->fb = fb; -+ -+ r = drm_vblank_get(dev, radeon_crtc->crtc_id); -+ if (r) { -+ DRM_ERROR("failed to get vblank before flip\n"); -+ goto pflip_cleanup1; -+ } -+ -+ /* 32 ought to cover us */ -+ r = radeon_ring_lock(rdev, 32); -+ if (r) { -+ DRM_ERROR("failed to lock the ring before flip\n"); -+ goto pflip_cleanup2; -+ } -+ -+ /* emit the fence */ -+ radeon_fence_emit(rdev, fence); -+ /* set the proper interrupt */ -+ radeon_pre_page_flip(rdev, radeon_crtc->crtc_id); -+ /* fire the ring */ -+ radeon_ring_unlock_commit(rdev); -+ -+ return 0; -+ -+pflip_cleanup2: -+ drm_vblank_put(dev, radeon_crtc->crtc_id); -+ -+pflip_cleanup1: -+ r = radeon_bo_reserve(rbo, false); -+ if (unlikely(r != 0)) { -+ DRM_ERROR("failed to reserve new rbo in error path\n"); -+ goto pflip_cleanup; -+ } -+ r = radeon_bo_unpin(rbo); -+ if (unlikely(r != 0)) { -+ radeon_bo_unreserve(rbo); -+ r = -EINVAL; -+ DRM_ERROR("failed to unpin new rbo in error path\n"); -+ goto pflip_cleanup; -+ } -+ radeon_bo_unreserve(rbo); -+ -+pflip_cleanup: -+ spin_lock_irqsave(&dev->event_lock, flags); -+ radeon_crtc->unpin_work = NULL; -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ radeon_fence_unref(&fence); -+ kfree(work); -+ -+ return r; -+} -+ - static const struct drm_crtc_funcs radeon_crtc_funcs = { - .cursor_set = radeon_crtc_cursor_set, - .cursor_move = radeon_crtc_cursor_move, - .gamma_set = radeon_crtc_gamma_set, - .set_config = drm_crtc_helper_set_config, - .destroy = radeon_crtc_destroy, -+ .page_flip = radeon_crtc_page_flip, - }; - - static void radeon_crtc_init(struct drm_device *dev, int index) -@@ -225,7 +485,7 @@ - radeon_legacy_init_crtc(dev, radeon_crtc); - } - --static const char *encoder_names[34] = { -+static const char *encoder_names[36] = { - "NONE", - "INTERNAL_LVDS", - "INTERNAL_TMDS1", -@@ -260,6 +520,8 @@ - "INTERNAL_KLDSCP_LVTMA", - "INTERNAL_UNIPHY1", - "INTERNAL_UNIPHY2", -+ "NUTMEG", -+ "TRAVIS", - }; - - static const char *connector_names[15] = { -@@ -1019,7 +1281,7 @@ - /* - * Retrieve current video scanout position of crtc on a given gpu. - * -- * \param rdev Device to query. -+ * \param dev Device to query. - * \param crtc Crtc to query. - * \param *vpos Location where vertical scanout position should be stored. - * \param *hpos Location where horizontal scanout position should go. -@@ -1031,72 +1293,74 @@ - * - * \return Flags, or'ed together as follows: - * -- * RADEON_SCANOUTPOS_VALID = Query successfull. -- * RADEON_SCANOUTPOS_INVBL = Inside vblank. -- * RADEON_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of -+ * DRM_SCANOUTPOS_VALID = Query successfull. -+ * DRM_SCANOUTPOS_INVBL = Inside vblank. -+ * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of - * this flag means that returned position may be offset by a constant but - * unknown small number of scanlines wrt. real scanout position. - * - */ --int radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, int *vpos, int *hpos) -+int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int *hpos) - { - u32 stat_crtc = 0, vbl = 0, position = 0; - int vbl_start, vbl_end, vtotal, ret = 0; - bool in_vbl = true; - -+ struct radeon_device *rdev = dev->dev_private; -+ - if (ASIC_IS_DCE4(rdev)) { - if (crtc == 0) { - vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + - EVERGREEN_CRTC0_REGISTER_OFFSET); - position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + - EVERGREEN_CRTC0_REGISTER_OFFSET); -- ret |= RADEON_SCANOUTPOS_VALID; -+ ret |= DRM_SCANOUTPOS_VALID; - } - if (crtc == 1) { - vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + - EVERGREEN_CRTC1_REGISTER_OFFSET); - position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + - EVERGREEN_CRTC1_REGISTER_OFFSET); -- ret |= RADEON_SCANOUTPOS_VALID; -+ ret |= DRM_SCANOUTPOS_VALID; - } - if (crtc == 2) { - vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + - EVERGREEN_CRTC2_REGISTER_OFFSET); - position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + - EVERGREEN_CRTC2_REGISTER_OFFSET); -- ret |= RADEON_SCANOUTPOS_VALID; -+ ret |= DRM_SCANOUTPOS_VALID; - } - if (crtc == 3) { - vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + - EVERGREEN_CRTC3_REGISTER_OFFSET); - position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + - EVERGREEN_CRTC3_REGISTER_OFFSET); -- ret |= RADEON_SCANOUTPOS_VALID; -+ ret |= DRM_SCANOUTPOS_VALID; - } - if (crtc == 4) { - vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + - EVERGREEN_CRTC4_REGISTER_OFFSET); - position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + - EVERGREEN_CRTC4_REGISTER_OFFSET); -- ret |= RADEON_SCANOUTPOS_VALID; -+ ret |= DRM_SCANOUTPOS_VALID; - } - if (crtc == 5) { - vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + - EVERGREEN_CRTC5_REGISTER_OFFSET); - position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + - EVERGREEN_CRTC5_REGISTER_OFFSET); -- ret |= RADEON_SCANOUTPOS_VALID; -+ ret |= DRM_SCANOUTPOS_VALID; - } - } else if (ASIC_IS_AVIVO(rdev)) { - if (crtc == 0) { - vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END); - position = RREG32(AVIVO_D1CRTC_STATUS_POSITION); -- ret |= RADEON_SCANOUTPOS_VALID; -+ ret |= DRM_SCANOUTPOS_VALID; - } - if (crtc == 1) { - vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END); - position = RREG32(AVIVO_D2CRTC_STATUS_POSITION); -- ret |= RADEON_SCANOUTPOS_VALID; -+ ret |= DRM_SCANOUTPOS_VALID; - } - } else { - /* Pre-AVIVO: Different encoding of scanout pos and vblank interval. */ -@@ -1112,7 +1376,7 @@ - if (!(stat_crtc & 1)) - in_vbl = false; - -- ret |= RADEON_SCANOUTPOS_VALID; -+ ret |= DRM_SCANOUTPOS_VALID; - } - if (crtc == 1) { - vbl = (RREG32(RADEON_CRTC2_V_TOTAL_DISP) & -@@ -1122,7 +1386,7 @@ - if (!(stat_crtc & 1)) - in_vbl = false; - -- ret |= RADEON_SCANOUTPOS_VALID; -+ ret |= DRM_SCANOUTPOS_VALID; - } - } - -@@ -1133,13 +1397,13 @@ - /* Valid vblank area boundaries from gpu retrieved? */ - if (vbl > 0) { - /* Yes: Decode. */ -- ret |= RADEON_SCANOUTPOS_ACCURATE; -+ ret |= DRM_SCANOUTPOS_ACCURATE; - vbl_start = vbl & 0x1fff; - vbl_end = (vbl >> 16) & 0x1fff; - } - else { - /* No: Fake something reasonable which gives at least ok results. */ -- vbl_start = rdev->mode_info.crtcs[crtc]->base.mode.crtc_vdisplay; -+ vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay; - vbl_end = 0; - } - -@@ -1155,7 +1419,7 @@ - - /* Inside "upper part" of vblank area? Apply corrective offset if so: */ - if (in_vbl && (*vpos >= vbl_start)) { -- vtotal = rdev->mode_info.crtcs[crtc]->base.mode.crtc_vtotal; -+ vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal; - *vpos = *vpos - vtotal; - } - -@@ -1164,7 +1428,7 @@ - - /* In vblank? */ - if (in_vbl) -- ret |= RADEON_SCANOUTPOS_INVBL; -+ ret |= DRM_SCANOUTPOS_INVBL; - - return ret; - } -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_drv.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_drv.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_drv.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_drv.c 2011-01-07 14:22:17.000000000 +0100 -@@ -48,9 +48,10 @@ - * - 2.5.0 - add get accel 2 to work around ddx breakage for evergreen - * - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500) - * 2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs -+ * 2.8.0 - pageflip support - */ - #define KMS_DRIVER_MAJOR 2 --#define KMS_DRIVER_MINOR 7 -+#define KMS_DRIVER_MINOR 8 - #define KMS_DRIVER_PATCHLEVEL 0 - int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); - int radeon_driver_unload_kms(struct drm_device *dev); -@@ -66,6 +67,10 @@ - u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc); - int radeon_enable_vblank_kms(struct drm_device *dev, int crtc); - void radeon_disable_vblank_kms(struct drm_device *dev, int crtc); -+int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, -+ int *max_error, -+ struct timeval *vblank_time, -+ unsigned flags); - void radeon_driver_irq_preinstall_kms(struct drm_device *dev); - int radeon_driver_irq_postinstall_kms(struct drm_device *dev); - void radeon_driver_irq_uninstall_kms(struct drm_device *dev); -@@ -74,6 +79,8 @@ - struct drm_file *file_priv); - int radeon_gem_object_init(struct drm_gem_object *obj); - void radeon_gem_object_free(struct drm_gem_object *obj); -+extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, -+ int *vpos, int *hpos); - extern struct drm_ioctl_desc radeon_ioctls_kms[]; - extern int radeon_max_kms_ioctl; - int radeon_mmap(struct file *filp, struct vm_area_struct *vma); -@@ -277,6 +284,8 @@ - .get_vblank_counter = radeon_get_vblank_counter_kms, - .enable_vblank = radeon_enable_vblank_kms, - .disable_vblank = radeon_disable_vblank_kms, -+ .get_vblank_timestamp = radeon_get_vblank_timestamp_kms, -+ .get_scanout_position = radeon_get_crtc_scanoutpos, - #if defined(CONFIG_DEBUG_FS) - .debugfs_init = radeon_debugfs_init, - .debugfs_cleanup = radeon_debugfs_cleanup, -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_encoders.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_encoders.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_encoders.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_encoders.c 2011-01-07 14:22:17.000000000 +0100 -@@ -713,7 +713,7 @@ - * DIG1/2 can drive UNIPHY0/1/2 link A or link B - * - * DCE 4.0 -- * - 3 DIG transmitter blocks UNPHY0/1/2 (links A and B). -+ * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). - * Supports up to 6 digital outputs - * - 6 DIG encoder blocks. - * - DIG to PHY mapping is hardcoded -@@ -724,6 +724,12 @@ - * DIG5 drives UNIPHY2 link A, A+B - * DIG6 drives UNIPHY2 link B - * -+ * DCE 4.1 -+ * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). -+ * Supports up to 6 digital outputs -+ * - 2 DIG encoder blocks. -+ * DIG1/2 can drive UNIPHY0/1/2 link A or link B -+ * - * Routing - * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links) - * Examples: -@@ -904,9 +910,15 @@ - else - args.v3.ucLaneNum = 4; - -- if (dig->linkb) { -- args.v3.acConfig.ucLinkSel = 1; -- args.v3.acConfig.ucEncoderSel = 1; -+ if (ASIC_IS_DCE41(rdev)) { -+ args.v3.acConfig.ucEncoderSel = dig->dig_encoder; -+ if (dig->linkb) -+ args.v3.acConfig.ucLinkSel = 1; -+ } else { -+ if (dig->linkb) { -+ args.v3.acConfig.ucLinkSel = 1; -+ args.v3.acConfig.ucEncoderSel = 1; -+ } - } - - /* Select the PLL for the PHY -@@ -1044,6 +1056,7 @@ - - union external_encoder_control { - EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1; -+ EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3; - }; - - static void -@@ -1054,6 +1067,7 @@ - struct drm_device *dev = encoder->dev; - struct radeon_device *rdev = dev->dev_private; - struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); -+ struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder); - union external_encoder_control args; - struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); - int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); -@@ -1061,6 +1075,7 @@ - int dp_clock = 0; - int dp_lane_count = 0; - int connector_object_id = 0; -+ u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT; - - if (connector) { - struct radeon_connector *radeon_connector = to_radeon_connector(connector); -@@ -1099,6 +1114,37 @@ - else - args.v1.sDigEncoder.ucLaneNum = 4; - break; -+ case 3: -+ args.v3.sExtEncoder.ucAction = action; -+ if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) -+ args.v3.sExtEncoder.usConnectorId = connector_object_id; -+ else -+ args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); -+ args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder); -+ -+ if (args.v3.sExtEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) { -+ if (dp_clock == 270000) -+ args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; -+ else if (dp_clock == 540000) -+ args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ; -+ args.v3.sExtEncoder.ucLaneNum = dp_lane_count; -+ } else if (radeon_encoder->pixel_clock > 165000) -+ args.v3.sExtEncoder.ucLaneNum = 8; -+ else -+ args.v3.sExtEncoder.ucLaneNum = 4; -+ switch (ext_enum) { -+ case GRAPH_OBJECT_ENUM_ID1: -+ args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1; -+ break; -+ case GRAPH_OBJECT_ENUM_ID2: -+ args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2; -+ break; -+ case GRAPH_OBJECT_ENUM_ID3: -+ args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3; -+ break; -+ } -+ args.v3.sExtEncoder.ucBitPerColor = PANEL_8BIT_PER_COLOR; -+ break; - default: - DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); - return; -@@ -1289,12 +1335,18 @@ - switch (mode) { - case DRM_MODE_DPMS_ON: - default: -- action = ATOM_ENABLE; -+ if (ASIC_IS_DCE41(rdev) && (rdev->flags & RADEON_IS_IGP)) -+ action = EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT; -+ else -+ action = ATOM_ENABLE; - break; - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - case DRM_MODE_DPMS_OFF: -- action = ATOM_DISABLE; -+ if (ASIC_IS_DCE41(rdev) && (rdev->flags & RADEON_IS_IGP)) -+ action = EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT; -+ else -+ action = ATOM_DISABLE; - break; - } - atombios_external_encoder_setup(encoder, ext_encoder, action); -@@ -1483,6 +1535,11 @@ - struct radeon_encoder_atom_dig *dig; - uint32_t dig_enc_in_use = 0; - -+ /* on DCE41 and encoder can driver any phy so just crtc id */ -+ if (ASIC_IS_DCE41(rdev)) { -+ return radeon_crtc->crtc_id; -+ } -+ - if (ASIC_IS_DCE4(rdev)) { - dig = radeon_encoder->enc_priv; - switch (radeon_encoder->encoder_id) { -@@ -1610,7 +1667,13 @@ - } - - if (ext_encoder) { -- atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); -+ if (ASIC_IS_DCE41(rdev) && (rdev->flags & RADEON_IS_IGP)) { -+ atombios_external_encoder_setup(encoder, ext_encoder, -+ EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT); -+ atombios_external_encoder_setup(encoder, ext_encoder, -+ EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); -+ } else -+ atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); - } - - atombios_apply_encoder_quirks(encoder, adjusted_mode); -@@ -2029,6 +2092,8 @@ - case ENCODER_OBJECT_ID_TITFP513: - case ENCODER_OBJECT_ID_VT1623: - case ENCODER_OBJECT_ID_HDMI_SI1930: -+ case ENCODER_OBJECT_ID_TRAVIS: -+ case ENCODER_OBJECT_ID_NUTMEG: - /* these are handled by the primary encoders */ - radeon_encoder->is_ext_encoder = true; - if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_family.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_family.h ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_family.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_family.h 2011-01-07 14:22:17.000000000 +0100 -@@ -80,6 +80,7 @@ - CHIP_JUNIPER, - CHIP_CYPRESS, - CHIP_HEMLOCK, -+ CHIP_PALM, - CHIP_LAST, - }; - -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_fence.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_fence.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_fence.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_fence.c 2011-01-07 14:22:17.000000000 +0100 -@@ -38,6 +38,7 @@ - #include "drm.h" - #include "radeon_reg.h" - #include "radeon.h" -+#include "radeon_trace.h" - - int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) - { -@@ -57,6 +58,7 @@ - } else - radeon_fence_ring_emit(rdev, fence); - -+ trace_radeon_fence_emit(rdev->ddev, fence->seq); - fence->emited = true; - list_del(&fence->list); - list_add_tail(&fence->list, &rdev->fence_drv.emited); -@@ -213,6 +215,7 @@ - retry: - /* save current sequence used to check for GPU lockup */ - seq = rdev->fence_drv.last_seq; -+ trace_radeon_fence_wait_begin(rdev->ddev, seq); - if (intr) { - radeon_irq_kms_sw_irq_get(rdev); - r = wait_event_interruptible_timeout(rdev->fence_drv.queue, -@@ -227,6 +230,7 @@ - radeon_fence_signaled(fence), timeout); - radeon_irq_kms_sw_irq_put(rdev); - } -+ trace_radeon_fence_wait_end(rdev->ddev, seq); - if (unlikely(!radeon_fence_signaled(fence))) { - /* we were interrupted for some reason and fence isn't - * isn't signaled yet, resume wait -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon.h ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon.h 2011-01-07 14:22:17.000000000 +0100 -@@ -69,6 +69,7 @@ - #include - #include - #include -+#include - - #include "radeon_family.h" - #include "radeon_mode.h" -@@ -180,6 +181,7 @@ - extern u32 rv6xx_get_temp(struct radeon_device *rdev); - extern u32 rv770_get_temp(struct radeon_device *rdev); - extern u32 evergreen_get_temp(struct radeon_device *rdev); -+extern u32 sumo_get_temp(struct radeon_device *rdev); - - /* - * Fences. -@@ -259,13 +261,12 @@ - }; - - struct radeon_bo_list { -- struct list_head list; -+ struct ttm_validate_buffer tv; - struct radeon_bo *bo; - uint64_t gpu_offset; - unsigned rdomain; - unsigned wdomain; - u32 tiling_flags; -- bool reserved; - }; - - /* -@@ -377,11 +378,56 @@ - /* - * IRQS. - */ -+ -+struct radeon_unpin_work { -+ struct work_struct work; -+ struct radeon_device *rdev; -+ int crtc_id; -+ struct radeon_fence *fence; -+ struct drm_pending_vblank_event *event; -+ struct radeon_bo *old_rbo; -+ u64 new_crtc_base; -+}; -+ -+struct r500_irq_stat_regs { -+ u32 disp_int; -+}; -+ -+struct r600_irq_stat_regs { -+ u32 disp_int; -+ u32 disp_int_cont; -+ u32 disp_int_cont2; -+ u32 d1grph_int; -+ u32 d2grph_int; -+}; -+ -+struct evergreen_irq_stat_regs { -+ u32 disp_int; -+ u32 disp_int_cont; -+ u32 disp_int_cont2; -+ u32 disp_int_cont3; -+ u32 disp_int_cont4; -+ u32 disp_int_cont5; -+ u32 d1grph_int; -+ u32 d2grph_int; -+ u32 d3grph_int; -+ u32 d4grph_int; -+ u32 d5grph_int; -+ u32 d6grph_int; -+}; -+ -+union radeon_irq_stat_regs { -+ struct r500_irq_stat_regs r500; -+ struct r600_irq_stat_regs r600; -+ struct evergreen_irq_stat_regs evergreen; -+}; -+ - struct radeon_irq { - bool installed; - bool sw_int; - /* FIXME: use a define max crtc rather than hardcode it */ - bool crtc_vblank_int[6]; -+ bool pflip[6]; - wait_queue_head_t vblank_queue; - /* FIXME: use defines for max hpd/dacs */ - bool hpd[6]; -@@ -392,12 +438,17 @@ - bool hdmi[2]; - spinlock_t sw_lock; - int sw_refcount; -+ union radeon_irq_stat_regs stat_regs; -+ spinlock_t pflip_lock[6]; -+ int pflip_refcount[6]; - }; - - int radeon_irq_kms_init(struct radeon_device *rdev); - void radeon_irq_kms_fini(struct radeon_device *rdev); - void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev); - void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev); -+void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc); -+void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc); - - /* - * CP & ring. -@@ -687,6 +738,7 @@ - THERMAL_TYPE_RV6XX, - THERMAL_TYPE_RV770, - THERMAL_TYPE_EVERGREEN, -+ THERMAL_TYPE_SUMO, - }; - - struct radeon_voltage { -@@ -881,6 +933,10 @@ - void (*pm_finish)(struct radeon_device *rdev); - void (*pm_init_profile)(struct radeon_device *rdev); - void (*pm_get_dynpm_state)(struct radeon_device *rdev); -+ /* pageflipping */ -+ void (*pre_page_flip)(struct radeon_device *rdev, int crtc); -+ u32 (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base); -+ void (*post_page_flip)(struct radeon_device *rdev, int crtc); - }; - - /* -@@ -1269,6 +1325,7 @@ - #define ASIC_IS_DCE3(rdev) ((rdev->family >= CHIP_RV620)) - #define ASIC_IS_DCE32(rdev) ((rdev->family >= CHIP_RV730)) - #define ASIC_IS_DCE4(rdev) ((rdev->family >= CHIP_CEDAR)) -+#define ASIC_IS_DCE41(rdev) ((rdev->family >= CHIP_PALM)) - - /* - * BIOS helpers. -@@ -1344,6 +1401,9 @@ - #define radeon_pm_finish(rdev) (rdev)->asic->pm_finish((rdev)) - #define radeon_pm_init_profile(rdev) (rdev)->asic->pm_init_profile((rdev)) - #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm_get_dynpm_state((rdev)) -+#define radeon_pre_page_flip(rdev, crtc) rdev->asic->pre_page_flip((rdev), (crtc)) -+#define radeon_page_flip(rdev, crtc, base) rdev->asic->page_flip((rdev), (crtc), (base)) -+#define radeon_post_page_flip(rdev, crtc) rdev->asic->post_page_flip((rdev), (crtc)) - - /* Common functions */ - /* AGP */ -@@ -1432,7 +1492,6 @@ - struct drm_display_mode *mode2); - - /* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */ --extern void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); - extern bool r600_card_posted(struct radeon_device *rdev); - extern void r600_cp_stop(struct radeon_device *rdev); - extern int r600_cp_start(struct radeon_device *rdev); -@@ -1478,6 +1537,7 @@ - extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); - extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); - -+extern void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); - extern void r700_cp_stop(struct radeon_device *rdev); - extern void r700_cp_fini(struct radeon_device *rdev); - extern void evergreen_disable_interrupt_state(struct radeon_device *rdev); -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_irq_kms.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_irq_kms.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_irq_kms.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_irq_kms.c 2011-01-07 14:22:17.000000000 +0100 -@@ -71,8 +71,10 @@ - rdev->irq.gui_idle = false; - for (i = 0; i < rdev->num_crtc; i++) - rdev->irq.crtc_vblank_int[i] = false; -- for (i = 0; i < 6; i++) -+ for (i = 0; i < 6; i++) { - rdev->irq.hpd[i] = false; -+ rdev->irq.pflip[i] = false; -+ } - radeon_irq_set(rdev); - /* Clear bits */ - radeon_irq_process(rdev); -@@ -101,8 +103,10 @@ - rdev->irq.gui_idle = false; - for (i = 0; i < rdev->num_crtc; i++) - rdev->irq.crtc_vblank_int[i] = false; -- for (i = 0; i < 6; i++) -+ for (i = 0; i < 6; i++) { - rdev->irq.hpd[i] = false; -+ rdev->irq.pflip[i] = false; -+ } - radeon_irq_set(rdev); - } - -@@ -121,7 +125,7 @@ - * chips. Disable MSI on them for now. - */ - if ((rdev->family >= CHIP_RV380) && -- (!(rdev->flags & RADEON_IS_IGP)) && -+ ((!(rdev->flags & RADEON_IS_IGP)) || (rdev->family >= CHIP_PALM)) && - (!(rdev->flags & RADEON_IS_AGP))) { - int ret = pci_enable_msi(rdev->pdev); - if (!ret) { -@@ -175,3 +179,34 @@ - spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); - } - -+void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) -+{ -+ unsigned long irqflags; -+ -+ if (crtc < 0 || crtc >= rdev->num_crtc) -+ return; -+ -+ spin_lock_irqsave(&rdev->irq.pflip_lock[crtc], irqflags); -+ if (rdev->ddev->irq_enabled && (++rdev->irq.pflip_refcount[crtc] == 1)) { -+ rdev->irq.pflip[crtc] = true; -+ radeon_irq_set(rdev); -+ } -+ spin_unlock_irqrestore(&rdev->irq.pflip_lock[crtc], irqflags); -+} -+ -+void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) -+{ -+ unsigned long irqflags; -+ -+ if (crtc < 0 || crtc >= rdev->num_crtc) -+ return; -+ -+ spin_lock_irqsave(&rdev->irq.pflip_lock[crtc], irqflags); -+ BUG_ON(rdev->ddev->irq_enabled && rdev->irq.pflip_refcount[crtc] <= 0); -+ if (rdev->ddev->irq_enabled && (--rdev->irq.pflip_refcount[crtc] == 0)) { -+ rdev->irq.pflip[crtc] = false; -+ radeon_irq_set(rdev); -+ } -+ spin_unlock_irqrestore(&rdev->irq.pflip_lock[crtc], irqflags); -+} -+ -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_kms.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_kms.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_kms.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_kms.c 2011-01-07 14:22:17.000000000 +0100 -@@ -277,6 +277,27 @@ - radeon_irq_set(rdev); - } - -+int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, -+ int *max_error, -+ struct timeval *vblank_time, -+ unsigned flags) -+{ -+ struct drm_crtc *drmcrtc; -+ struct radeon_device *rdev = dev->dev_private; -+ -+ if (crtc < 0 || crtc >= dev->num_crtcs) { -+ DRM_ERROR("Invalid crtc %d\n", crtc); -+ return -EINVAL; -+ } -+ -+ /* Get associated drm_crtc: */ -+ drmcrtc = &rdev->mode_info.crtcs[crtc]->base; -+ -+ /* Helper routine in DRM core does all the work: */ -+ return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error, -+ vblank_time, flags, -+ drmcrtc); -+} - - /* - * IOCTL. -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_mode.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_mode.h ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_mode.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_mode.h 2011-01-07 14:22:17.000000000 +0100 -@@ -277,6 +277,9 @@ - fixed20_12 hsc; - struct drm_display_mode native_mode; - int pll_id; -+ /* page flipping */ -+ struct radeon_unpin_work *unpin_work; -+ int deferred_flip_completion; - }; - - struct radeon_encoder_primary_dac { -@@ -442,10 +445,6 @@ - struct drm_gem_object *obj; - }; - --/* radeon_get_crtc_scanoutpos() return flags */ --#define RADEON_SCANOUTPOS_VALID (1 << 0) --#define RADEON_SCANOUTPOS_INVBL (1 << 1) --#define RADEON_SCANOUTPOS_ACCURATE (1 << 2) - - extern enum radeon_tv_std - radeon_combios_get_tv_info(struct radeon_device *rdev); -@@ -562,7 +561,8 @@ - extern int radeon_crtc_cursor_move(struct drm_crtc *crtc, - int x, int y); - --extern int radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, int *vpos, int *hpos); -+extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, -+ int *vpos, int *hpos); - - extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev); - extern struct edid * -@@ -662,4 +662,7 @@ - bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj); - - void radeon_fb_output_poll_changed(struct radeon_device *rdev); -+ -+void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id); -+ - #endif -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_object.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_object.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_object.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_object.c 2011-01-07 14:22:17.000000000 +0100 -@@ -34,6 +34,7 @@ - #include - #include "radeon_drm.h" - #include "radeon.h" -+#include "radeon_trace.h" - - - int radeon_ttm_init(struct radeon_device *rdev); -@@ -137,6 +138,7 @@ - list_add_tail(&bo->list, &rdev->gem.objects); - mutex_unlock(&bo->rdev->gem.mutex); - } -+ trace_radeon_bo_create(bo); - return 0; - } - -@@ -293,34 +295,9 @@ - struct list_head *head) - { - if (lobj->wdomain) { -- list_add(&lobj->list, head); -+ list_add(&lobj->tv.head, head); - } else { -- list_add_tail(&lobj->list, head); -- } --} -- --int radeon_bo_list_reserve(struct list_head *head) --{ -- struct radeon_bo_list *lobj; -- int r; -- -- list_for_each_entry(lobj, head, list){ -- r = radeon_bo_reserve(lobj->bo, false); -- if (unlikely(r != 0)) -- return r; -- lobj->reserved = true; -- } -- return 0; --} -- --void radeon_bo_list_unreserve(struct list_head *head) --{ -- struct radeon_bo_list *lobj; -- -- list_for_each_entry(lobj, head, list) { -- /* only unreserve object we successfully reserved */ -- if (lobj->reserved && radeon_bo_is_reserved(lobj->bo)) -- radeon_bo_unreserve(lobj->bo); -+ list_add_tail(&lobj->tv.head, head); - } - } - -@@ -331,14 +308,11 @@ - u32 domain; - int r; - -- list_for_each_entry(lobj, head, list) { -- lobj->reserved = false; -- } -- r = radeon_bo_list_reserve(head); -+ r = ttm_eu_reserve_buffers(head); - if (unlikely(r != 0)) { - return r; - } -- list_for_each_entry(lobj, head, list) { -+ list_for_each_entry(lobj, head, tv.head) { - bo = lobj->bo; - if (!bo->pin_count) { - domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain; -@@ -361,25 +335,6 @@ - return 0; - } - --void radeon_bo_list_fence(struct list_head *head, void *fence) --{ -- struct radeon_bo_list *lobj; -- struct radeon_bo *bo; -- struct radeon_fence *old_fence = NULL; -- -- list_for_each_entry(lobj, head, list) { -- bo = lobj->bo; -- spin_lock(&bo->tbo.lock); -- old_fence = (struct radeon_fence *)bo->tbo.sync_obj; -- bo->tbo.sync_obj = radeon_fence_ref(fence); -- bo->tbo.sync_obj_arg = NULL; -- spin_unlock(&bo->tbo.lock); -- if (old_fence) { -- radeon_fence_unref(&old_fence); -- } -- } --} -- - int radeon_bo_fbdev_mmap(struct radeon_bo *bo, - struct vm_area_struct *vma) - { -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_object.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_object.h ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_object.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_object.h 2011-01-07 14:22:17.000000000 +0100 -@@ -126,12 +126,12 @@ - r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0); - if (unlikely(r != 0)) - return r; -- spin_lock(&bo->tbo.lock); -+ spin_lock(&bo->tbo.bdev->fence_lock); - if (mem_type) - *mem_type = bo->tbo.mem.mem_type; - if (bo->tbo.sync_obj) - r = ttm_bo_wait(&bo->tbo, true, true, no_wait); -- spin_unlock(&bo->tbo.lock); -+ spin_unlock(&bo->tbo.bdev->fence_lock); - ttm_bo_unreserve(&bo->tbo); - return r; - } -@@ -152,10 +152,7 @@ - extern void radeon_bo_fini(struct radeon_device *rdev); - extern void radeon_bo_list_add_object(struct radeon_bo_list *lobj, - struct list_head *head); --extern int radeon_bo_list_reserve(struct list_head *head); --extern void radeon_bo_list_unreserve(struct list_head *head); - extern int radeon_bo_list_validate(struct list_head *head); --extern void radeon_bo_list_fence(struct list_head *head, void *fence); - extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo, - struct vm_area_struct *vma); - extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo, -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_pm.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_pm.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_pm.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_pm.c 2011-01-07 14:22:17.000000000 +0100 -@@ -449,6 +449,9 @@ - case THERMAL_TYPE_EVERGREEN: - temp = evergreen_get_temp(rdev); - break; -+ case THERMAL_TYPE_SUMO: -+ temp = sumo_get_temp(rdev); -+ break; - default: - temp = 0; - break; -@@ -487,6 +490,7 @@ - case THERMAL_TYPE_RV6XX: - case THERMAL_TYPE_RV770: - case THERMAL_TYPE_EVERGREEN: -+ case THERMAL_TYPE_SUMO: - rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); - if (IS_ERR(rdev->pm.int_hwmon_dev)) { - err = PTR_ERR(rdev->pm.int_hwmon_dev); -@@ -720,9 +724,9 @@ - */ - for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) { - if (rdev->pm.active_crtcs & (1 << crtc)) { -- vbl_status = radeon_get_crtc_scanoutpos(rdev, crtc, &vpos, &hpos); -- if ((vbl_status & RADEON_SCANOUTPOS_VALID) && -- !(vbl_status & RADEON_SCANOUTPOS_INVBL)) -+ vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, &vpos, &hpos); -+ if ((vbl_status & DRM_SCANOUTPOS_VALID) && -+ !(vbl_status & DRM_SCANOUTPOS_INVBL)) - in_vbl = false; - } - } -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_reg.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_reg.h ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_reg.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_reg.h 2011-01-07 14:22:17.000000000 +0100 -@@ -422,6 +422,7 @@ - # define RADEON_CRTC_CSYNC_EN (1 << 4) - # define RADEON_CRTC_ICON_EN (1 << 15) - # define RADEON_CRTC_CUR_EN (1 << 16) -+# define RADEON_CRTC_VSTAT_MODE_MASK (3 << 17) - # define RADEON_CRTC_CUR_MODE_MASK (7 << 20) - # define RADEON_CRTC_CUR_MODE_SHIFT 20 - # define RADEON_CRTC_CUR_MODE_MONO 0 -@@ -509,6 +510,8 @@ - # define RADEON_CRTC_TILE_EN (1 << 15) - # define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) - # define RADEON_CRTC_STEREO_OFFSET_EN (1 << 17) -+# define RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN (1 << 28) -+# define RADEON_CRTC_GUI_TRIG_OFFSET_RIGHT_EN (1 << 29) - - #define R300_CRTC_TILE_X0_Y0 0x0350 - #define R300_CRTC2_TILE_X0_Y0 0x0358 -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_trace.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_trace.h ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_trace.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_trace.h 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,82 @@ -+#if !defined(_RADEON_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) -+#define _RADEON_TRACE_H_ -+ -+#include -+#include -+#include -+ -+#include -+ -+#undef TRACE_SYSTEM -+#define TRACE_SYSTEM radeon -+#define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM) -+#define TRACE_INCLUDE_FILE radeon_trace -+ -+TRACE_EVENT(radeon_bo_create, -+ TP_PROTO(struct radeon_bo *bo), -+ TP_ARGS(bo), -+ TP_STRUCT__entry( -+ __field(struct radeon_bo *, bo) -+ __field(u32, pages) -+ ), -+ -+ TP_fast_assign( -+ __entry->bo = bo; -+ __entry->pages = bo->tbo.num_pages; -+ ), -+ TP_printk("bo=%p, pages=%u", __entry->bo, __entry->pages) -+); -+ -+DECLARE_EVENT_CLASS(radeon_fence_request, -+ -+ TP_PROTO(struct drm_device *dev, u32 seqno), -+ -+ TP_ARGS(dev, seqno), -+ -+ TP_STRUCT__entry( -+ __field(u32, dev) -+ __field(u32, seqno) -+ ), -+ -+ TP_fast_assign( -+ __entry->dev = dev->primary->index; -+ __entry->seqno = seqno; -+ ), -+ -+ TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno) -+); -+ -+DEFINE_EVENT(radeon_fence_request, radeon_fence_emit, -+ -+ TP_PROTO(struct drm_device *dev, u32 seqno), -+ -+ TP_ARGS(dev, seqno) -+); -+ -+DEFINE_EVENT(radeon_fence_request, radeon_fence_retire, -+ -+ TP_PROTO(struct drm_device *dev, u32 seqno), -+ -+ TP_ARGS(dev, seqno) -+); -+ -+DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_begin, -+ -+ TP_PROTO(struct drm_device *dev, u32 seqno), -+ -+ TP_ARGS(dev, seqno) -+); -+ -+DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_end, -+ -+ TP_PROTO(struct drm_device *dev, u32 seqno), -+ -+ TP_ARGS(dev, seqno) -+); -+ -+#endif -+ -+/* This part must be outside protection */ -+#undef TRACE_INCLUDE_PATH -+#define TRACE_INCLUDE_PATH . -+#include -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_trace_points.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_trace_points.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/radeon_trace_points.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/radeon_trace_points.c 2011-01-07 14:22:17.000000000 +0100 -@@ -0,0 +1,9 @@ -+/* Copyright Red Hat Inc 2010. -+ * Author : Dave Airlie -+ */ -+#include -+#include "radeon_drm.h" -+#include "radeon.h" -+ -+#define CREATE_TRACE_POINTS -+#include "radeon_trace.h" -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/rs600.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/rs600.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/rs600.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/rs600.c 2011-01-07 14:22:17.000000000 +0100 -@@ -46,6 +46,56 @@ - void rs600_gpu_init(struct radeon_device *rdev); - int rs600_mc_wait_for_idle(struct radeon_device *rdev); - -+void rs600_pre_page_flip(struct radeon_device *rdev, int crtc) -+{ -+ struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; -+ u32 tmp; -+ -+ /* make sure flip is at vb rather than hb */ -+ tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); -+ tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN; -+ WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); -+ -+ /* set pageflip to happen anywhere in vblank interval */ -+ WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); -+ -+ /* enable the pflip int */ -+ radeon_irq_kms_pflip_irq_get(rdev, crtc); -+} -+ -+void rs600_post_page_flip(struct radeon_device *rdev, int crtc) -+{ -+ /* disable the pflip int */ -+ radeon_irq_kms_pflip_irq_put(rdev, crtc); -+} -+ -+u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) -+{ -+ struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; -+ u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); -+ -+ /* Lock the graphics update lock */ -+ tmp |= AVIVO_D1GRPH_UPDATE_LOCK; -+ WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); -+ -+ /* update the scanout addresses */ -+ WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, -+ (u32)crtc_base); -+ WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, -+ (u32)crtc_base); -+ -+ /* Wait for update_pending to go high. */ -+ while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)); -+ DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); -+ -+ /* Unlock the lock, so double-buffering can take place inside vblank */ -+ tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; -+ WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); -+ -+ /* Return current update_pending status: */ -+ return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING; -+} -+ - void rs600_pm_misc(struct radeon_device *rdev) - { - int requested_index = rdev->pm.requested_power_state_index; -@@ -515,10 +565,12 @@ - if (rdev->irq.gui_idle) { - tmp |= S_000040_GUI_IDLE(1); - } -- if (rdev->irq.crtc_vblank_int[0]) { -+ if (rdev->irq.crtc_vblank_int[0] || -+ rdev->irq.pflip[0]) { - mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1); - } -- if (rdev->irq.crtc_vblank_int[1]) { -+ if (rdev->irq.crtc_vblank_int[1] || -+ rdev->irq.pflip[1]) { - mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1); - } - if (rdev->irq.hpd[0]) { -@@ -534,7 +586,7 @@ - return 0; - } - --static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_int) -+static inline u32 rs600_irq_ack(struct radeon_device *rdev) - { - uint32_t irqs = RREG32(R_000044_GEN_INT_STATUS); - uint32_t irq_mask = S_000044_SW_INT(1); -@@ -547,27 +599,27 @@ - } - - if (G_000044_DISPLAY_INT_STAT(irqs)) { -- *r500_disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS); -- if (G_007EDC_LB_D1_VBLANK_INTERRUPT(*r500_disp_int)) { -+ rdev->irq.stat_regs.r500.disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS); -+ if (G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { - WREG32(R_006534_D1MODE_VBLANK_STATUS, - S_006534_D1MODE_VBLANK_ACK(1)); - } -- if (G_007EDC_LB_D2_VBLANK_INTERRUPT(*r500_disp_int)) { -+ if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { - WREG32(R_006D34_D2MODE_VBLANK_STATUS, - S_006D34_D2MODE_VBLANK_ACK(1)); - } -- if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(*r500_disp_int)) { -+ if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { - tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL); - tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_ACK(1); - WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); - } -- if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(*r500_disp_int)) { -+ if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { - tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL); - tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_ACK(1); - WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); - } - } else { -- *r500_disp_int = 0; -+ rdev->irq.stat_regs.r500.disp_int = 0; - } - - if (irqs) { -@@ -578,32 +630,30 @@ - - void rs600_irq_disable(struct radeon_device *rdev) - { -- u32 tmp; -- - WREG32(R_000040_GEN_INT_CNTL, 0); - WREG32(R_006540_DxMODE_INT_MASK, 0); - /* Wait and acknowledge irq */ - mdelay(1); -- rs600_irq_ack(rdev, &tmp); -+ rs600_irq_ack(rdev); - } - - int rs600_irq_process(struct radeon_device *rdev) - { -- uint32_t status, msi_rearm; -- uint32_t r500_disp_int; -+ u32 status, msi_rearm; - bool queue_hotplug = false; - - /* reset gui idle ack. the status bit is broken */ - rdev->irq.gui_idle_acked = false; - -- status = rs600_irq_ack(rdev, &r500_disp_int); -- if (!status && !r500_disp_int) { -+ status = rs600_irq_ack(rdev); -+ if (!status && !rdev->irq.stat_regs.r500.disp_int) { - return IRQ_NONE; - } -- while (status || r500_disp_int) { -+ while (status || rdev->irq.stat_regs.r500.disp_int) { - /* SW interrupt */ -- if (G_000044_SW_INT(status)) -+ if (G_000044_SW_INT(status)) { - radeon_fence_process(rdev); -+ } - /* GUI idle */ - if (G_000040_GUI_IDLE(status)) { - rdev->irq.gui_idle_acked = true; -@@ -611,25 +661,33 @@ - wake_up(&rdev->irq.idle_queue); - } - /* Vertical blank interrupts */ -- if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int)) { -- drm_handle_vblank(rdev->ddev, 0); -- rdev->pm.vblank_sync = true; -- wake_up(&rdev->irq.vblank_queue); -- } -- if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int)) { -- drm_handle_vblank(rdev->ddev, 1); -- rdev->pm.vblank_sync = true; -- wake_up(&rdev->irq.vblank_queue); -+ if (G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { -+ if (rdev->irq.crtc_vblank_int[0]) { -+ drm_handle_vblank(rdev->ddev, 0); -+ rdev->pm.vblank_sync = true; -+ wake_up(&rdev->irq.vblank_queue); -+ } -+ if (rdev->irq.pflip[0]) -+ radeon_crtc_handle_flip(rdev, 0); -+ } -+ if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { -+ if (rdev->irq.crtc_vblank_int[1]) { -+ drm_handle_vblank(rdev->ddev, 1); -+ rdev->pm.vblank_sync = true; -+ wake_up(&rdev->irq.vblank_queue); -+ } -+ if (rdev->irq.pflip[1]) -+ radeon_crtc_handle_flip(rdev, 1); - } -- if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(r500_disp_int)) { -+ if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { - queue_hotplug = true; - DRM_DEBUG("HPD1\n"); - } -- if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(r500_disp_int)) { -+ if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { - queue_hotplug = true; - DRM_DEBUG("HPD2\n"); - } -- status = rs600_irq_ack(rdev, &r500_disp_int); -+ status = rs600_irq_ack(rdev); - } - /* reset gui idle ack. the status bit is broken */ - rdev->irq.gui_idle_acked = false; -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/rv770.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/rv770.c ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/rv770.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/rv770.c 2011-01-07 14:22:17.000000000 +0100 -@@ -42,6 +42,40 @@ - static void rv770_gpu_init(struct radeon_device *rdev); - void rv770_fini(struct radeon_device *rdev); - -+u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) -+{ -+ struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; -+ u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); -+ -+ /* Lock the graphics update lock */ -+ tmp |= AVIVO_D1GRPH_UPDATE_LOCK; -+ WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); -+ -+ /* update the scanout addresses */ -+ if (radeon_crtc->crtc_id) { -+ WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); -+ WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); -+ } else { -+ WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); -+ WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); -+ } -+ WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, -+ (u32)crtc_base); -+ WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, -+ (u32)crtc_base); -+ -+ /* Wait for update_pending to go high. */ -+ while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)); -+ DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); -+ -+ /* Unlock the lock, so double-buffering can take place inside vblank */ -+ tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; -+ WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); -+ -+ /* Return current update_pending status: */ -+ return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING; -+} -+ - /* get temperature in millidegrees */ - u32 rv770_get_temp(struct radeon_device *rdev) - { -@@ -489,6 +523,49 @@ - return backend_map; - } - -+static void rv770_program_channel_remap(struct radeon_device *rdev) -+{ -+ u32 tcp_chan_steer, mc_shared_chremap, tmp; -+ bool force_no_swizzle; -+ -+ switch (rdev->family) { -+ case CHIP_RV770: -+ case CHIP_RV730: -+ force_no_swizzle = false; -+ break; -+ case CHIP_RV710: -+ case CHIP_RV740: -+ default: -+ force_no_swizzle = true; -+ break; -+ } -+ -+ tmp = RREG32(MC_SHARED_CHMAP); -+ switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { -+ case 0: -+ case 1: -+ default: -+ /* default mapping */ -+ mc_shared_chremap = 0x00fac688; -+ break; -+ case 2: -+ case 3: -+ if (force_no_swizzle) -+ mc_shared_chremap = 0x00fac688; -+ else -+ mc_shared_chremap = 0x00bbc298; -+ break; -+ } -+ -+ if (rdev->family == CHIP_RV740) -+ tcp_chan_steer = 0x00ef2a60; -+ else -+ tcp_chan_steer = 0x00fac688; -+ -+ WREG32(TCP_CHAN_STEER, tcp_chan_steer); -+ WREG32(MC_SHARED_CHREMAP, mc_shared_chremap); -+} -+ - static void rv770_gpu_init(struct radeon_device *rdev) - { - int i, j, num_qd_pipes; -@@ -688,6 +765,8 @@ - WREG32(DCP_TILING_CONFIG, (gb_tiling_config & 0xffff)); - WREG32(HDP_TILING_CONFIG, (gb_tiling_config & 0xffff)); - -+ rv770_program_channel_remap(rdev); -+ - WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); - WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); - WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); -@@ -956,6 +1035,45 @@ - radeon_bo_unref(&rdev->vram_scratch.robj); - } - -+void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) -+{ -+ u64 size_bf, size_af; -+ -+ if (mc->mc_vram_size > 0xE0000000) { -+ /* leave room for at least 512M GTT */ -+ dev_warn(rdev->dev, "limiting VRAM\n"); -+ mc->real_vram_size = 0xE0000000; -+ mc->mc_vram_size = 0xE0000000; -+ } -+ if (rdev->flags & RADEON_IS_AGP) { -+ size_bf = mc->gtt_start; -+ size_af = 0xFFFFFFFF - mc->gtt_end + 1; -+ if (size_bf > size_af) { -+ if (mc->mc_vram_size > size_bf) { -+ dev_warn(rdev->dev, "limiting VRAM\n"); -+ mc->real_vram_size = size_bf; -+ mc->mc_vram_size = size_bf; -+ } -+ mc->vram_start = mc->gtt_start - mc->mc_vram_size; -+ } else { -+ if (mc->mc_vram_size > size_af) { -+ dev_warn(rdev->dev, "limiting VRAM\n"); -+ mc->real_vram_size = size_af; -+ mc->mc_vram_size = size_af; -+ } -+ mc->vram_start = mc->gtt_end; -+ } -+ mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; -+ dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n", -+ mc->mc_vram_size >> 20, mc->vram_start, -+ mc->vram_end, mc->real_vram_size >> 20); -+ } else { -+ radeon_vram_location(rdev, &rdev->mc, 0); -+ rdev->mc.gtt_base_align = 0; -+ radeon_gtt_location(rdev, mc); -+ } -+} -+ - int rv770_mc_init(struct radeon_device *rdev) - { - u32 tmp; -@@ -996,7 +1114,7 @@ - rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); - rdev->mc.visible_vram_size = rdev->mc.aper_size; - rdev->mc.active_vram_size = rdev->mc.visible_vram_size; -- r600_vram_gtt_location(rdev, &rdev->mc); -+ r700_vram_gtt_location(rdev, &rdev->mc); - radeon_update_bandwidth_info(rdev); - - return 0; -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/radeon/rv770d.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/rv770d.h ---- linux-2.6.37-rc3/drivers/gpu/drm/radeon/rv770d.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/radeon/rv770d.h 2011-01-07 14:22:17.000000000 +0100 -@@ -138,6 +138,7 @@ - #define MC_SHARED_CHMAP 0x2004 - #define NOOFCHAN_SHIFT 12 - #define NOOFCHAN_MASK 0x00003000 -+#define MC_SHARED_CHREMAP 0x2008 - - #define MC_ARB_RAMCFG 0x2760 - #define NOOFBANK_SHIFT 0 -@@ -303,6 +304,7 @@ - #define BILINEAR_PRECISION_8_BIT (1 << 31) - - #define TCP_CNTL 0x9610 -+#define TCP_CHAN_STEER 0x9614 - - #define VGT_CACHE_INVALIDATION 0x88C4 - #define CACHE_INVALIDATION(x) ((x)<<0) -@@ -351,4 +353,11 @@ - - #define SRBM_STATUS 0x0E50 - -+#define D1GRPH_PRIMARY_SURFACE_ADDRESS 0x6110 -+#define D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x6914 -+#define D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x6114 -+#define D1GRPH_SECONDARY_SURFACE_ADDRESS 0x6118 -+#define D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x691c -+#define D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x611c -+ - #endif -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/ttm/ttm_bo.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/ttm/ttm_bo.c ---- linux-2.6.37-rc3/drivers/gpu/drm/ttm/ttm_bo.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/ttm/ttm_bo.c 2011-01-07 14:22:17.000000000 +0100 -@@ -169,7 +169,7 @@ - } - EXPORT_SYMBOL(ttm_bo_wait_unreserved); - --static void ttm_bo_add_to_lru(struct ttm_buffer_object *bo) -+void ttm_bo_add_to_lru(struct ttm_buffer_object *bo) - { - struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_type_manager *man; -@@ -191,11 +191,7 @@ - } - } - --/** -- * Call with the lru_lock held. -- */ -- --static int ttm_bo_del_from_lru(struct ttm_buffer_object *bo) -+int ttm_bo_del_from_lru(struct ttm_buffer_object *bo) - { - int put_count = 0; - -@@ -227,9 +223,18 @@ - /** - * Deadlock avoidance for multi-bo reserving. - */ -- if (use_sequence && bo->seq_valid && -- (sequence - bo->val_seq < (1 << 31))) { -- return -EAGAIN; -+ if (use_sequence && bo->seq_valid) { -+ /** -+ * We've already reserved this one. -+ */ -+ if (unlikely(sequence == bo->val_seq)) -+ return -EDEADLK; -+ /** -+ * Already reserved by a thread that will not back -+ * off for us. We need to back off. -+ */ -+ if (unlikely(sequence - bo->val_seq < (1 << 31))) -+ return -EAGAIN; - } - - if (no_wait) -@@ -267,6 +272,13 @@ - BUG(); - } - -+void ttm_bo_list_ref_sub(struct ttm_buffer_object *bo, int count, -+ bool never_free) -+{ -+ kref_sub(&bo->list_kref, count, -+ (never_free) ? ttm_bo_ref_bug : ttm_bo_release_list); -+} -+ - int ttm_bo_reserve(struct ttm_buffer_object *bo, - bool interruptible, - bool no_wait, bool use_sequence, uint32_t sequence) -@@ -282,20 +294,24 @@ - put_count = ttm_bo_del_from_lru(bo); - spin_unlock(&glob->lru_lock); - -- while (put_count--) -- kref_put(&bo->list_kref, ttm_bo_ref_bug); -+ ttm_bo_list_ref_sub(bo, put_count, true); - - return ret; - } - -+void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo) -+{ -+ ttm_bo_add_to_lru(bo); -+ atomic_set(&bo->reserved, 0); -+ wake_up_all(&bo->event_queue); -+} -+ - void ttm_bo_unreserve(struct ttm_buffer_object *bo) - { - struct ttm_bo_global *glob = bo->glob; - - spin_lock(&glob->lru_lock); -- ttm_bo_add_to_lru(bo); -- atomic_set(&bo->reserved, 0); -- wake_up_all(&bo->event_queue); -+ ttm_bo_unreserve_locked(bo); - spin_unlock(&glob->lru_lock); - } - EXPORT_SYMBOL(ttm_bo_unreserve); -@@ -362,8 +378,13 @@ - int ret = 0; - - if (old_is_pci || new_is_pci || -- ((mem->placement & bo->mem.placement & TTM_PL_MASK_CACHING) == 0)) -- ttm_bo_unmap_virtual(bo); -+ ((mem->placement & bo->mem.placement & TTM_PL_MASK_CACHING) == 0)) { -+ ret = ttm_mem_io_lock(old_man, true); -+ if (unlikely(ret != 0)) -+ goto out_err; -+ ttm_bo_unmap_virtual_locked(bo); -+ ttm_mem_io_unlock(old_man); -+ } - - /* - * Create and bind a ttm if required. -@@ -416,11 +437,9 @@ - } - - if (bo->mem.mm_node) { -- spin_lock(&bo->lock); - bo->offset = (bo->mem.start << PAGE_SHIFT) + - bdev->man[bo->mem.mem_type].gpu_offset; - bo->cur_placement = bo->mem.placement; -- spin_unlock(&bo->lock); - } else - bo->offset = 0; - -@@ -452,7 +471,6 @@ - ttm_tt_destroy(bo->ttm); - bo->ttm = NULL; - } -- - ttm_bo_mem_put(bo, &bo->mem); - - atomic_set(&bo->reserved, 0); -@@ -474,14 +492,14 @@ - int put_count; - int ret; - -- spin_lock(&bo->lock); -+ spin_lock(&bdev->fence_lock); - (void) ttm_bo_wait(bo, false, false, true); - if (!bo->sync_obj) { - - spin_lock(&glob->lru_lock); - - /** -- * Lock inversion between bo::reserve and bo::lock here, -+ * Lock inversion between bo:reserve and bdev::fence_lock here, - * but that's OK, since we're only trylocking. - */ - -@@ -490,14 +508,13 @@ - if (unlikely(ret == -EBUSY)) - goto queue; - -- spin_unlock(&bo->lock); -+ spin_unlock(&bdev->fence_lock); - put_count = ttm_bo_del_from_lru(bo); - - spin_unlock(&glob->lru_lock); - ttm_bo_cleanup_memtype_use(bo); - -- while (put_count--) -- kref_put(&bo->list_kref, ttm_bo_ref_bug); -+ ttm_bo_list_ref_sub(bo, put_count, true); - - return; - } else { -@@ -512,7 +529,7 @@ - kref_get(&bo->list_kref); - list_add_tail(&bo->ddestroy, &bdev->ddestroy); - spin_unlock(&glob->lru_lock); -- spin_unlock(&bo->lock); -+ spin_unlock(&bdev->fence_lock); - - if (sync_obj) { - driver->sync_obj_flush(sync_obj, sync_obj_arg); -@@ -537,14 +554,15 @@ - bool no_wait_reserve, - bool no_wait_gpu) - { -+ struct ttm_bo_device *bdev = bo->bdev; - struct ttm_bo_global *glob = bo->glob; - int put_count; - int ret = 0; - - retry: -- spin_lock(&bo->lock); -+ spin_lock(&bdev->fence_lock); - ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu); -- spin_unlock(&bo->lock); -+ spin_unlock(&bdev->fence_lock); - - if (unlikely(ret != 0)) - return ret; -@@ -580,8 +598,7 @@ - spin_unlock(&glob->lru_lock); - ttm_bo_cleanup_memtype_use(bo); - -- while (put_count--) -- kref_put(&bo->list_kref, ttm_bo_ref_bug); -+ ttm_bo_list_ref_sub(bo, put_count, true); - - return 0; - } -@@ -652,6 +669,7 @@ - struct ttm_buffer_object *bo = - container_of(kref, struct ttm_buffer_object, kref); - struct ttm_bo_device *bdev = bo->bdev; -+ struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type]; - - if (likely(bo->vm_node != NULL)) { - rb_erase(&bo->vm_rb, &bdev->addr_space_rb); -@@ -659,6 +677,9 @@ - bo->vm_node = NULL; - } - write_unlock(&bdev->vm_lock); -+ ttm_mem_io_lock(man, false); -+ ttm_mem_io_free_vm(bo); -+ ttm_mem_io_unlock(man); - ttm_bo_cleanup_refs_or_queue(bo); - kref_put(&bo->list_kref, ttm_bo_release_list); - write_lock(&bdev->vm_lock); -@@ -698,9 +719,9 @@ - struct ttm_placement placement; - int ret = 0; - -- spin_lock(&bo->lock); -+ spin_lock(&bdev->fence_lock); - ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu); -- spin_unlock(&bo->lock); -+ spin_unlock(&bdev->fence_lock); - - if (unlikely(ret != 0)) { - if (ret != -ERESTARTSYS) { -@@ -715,7 +736,8 @@ - - evict_mem = bo->mem; - evict_mem.mm_node = NULL; -- evict_mem.bus.io_reserved = false; -+ evict_mem.bus.io_reserved_vm = false; -+ evict_mem.bus.io_reserved_count = 0; - - placement.fpfn = 0; - placement.lpfn = 0; -@@ -802,8 +824,7 @@ - - BUG_ON(ret != 0); - -- while (put_count--) -- kref_put(&bo->list_kref, ttm_bo_ref_bug); -+ ttm_bo_list_ref_sub(bo, put_count, true); - - ret = ttm_bo_evict(bo, interruptible, no_wait_reserve, no_wait_gpu); - ttm_bo_unreserve(bo); -@@ -1036,6 +1057,7 @@ - { - int ret = 0; - struct ttm_mem_reg mem; -+ struct ttm_bo_device *bdev = bo->bdev; - - BUG_ON(!atomic_read(&bo->reserved)); - -@@ -1044,15 +1066,16 @@ - * Have the driver move function wait for idle when necessary, - * instead of doing it here. - */ -- spin_lock(&bo->lock); -+ spin_lock(&bdev->fence_lock); - ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu); -- spin_unlock(&bo->lock); -+ spin_unlock(&bdev->fence_lock); - if (ret) - return ret; - mem.num_pages = bo->num_pages; - mem.size = mem.num_pages << PAGE_SHIFT; - mem.page_alignment = bo->mem.page_alignment; -- mem.bus.io_reserved = false; -+ mem.bus.io_reserved_vm = false; -+ mem.bus.io_reserved_count = 0; - /* - * Determine where to move the buffer. - */ -@@ -1163,7 +1186,6 @@ - } - bo->destroy = destroy; - -- spin_lock_init(&bo->lock); - kref_init(&bo->kref); - kref_init(&bo->list_kref); - atomic_set(&bo->cpu_writers, 0); -@@ -1172,6 +1194,7 @@ - INIT_LIST_HEAD(&bo->lru); - INIT_LIST_HEAD(&bo->ddestroy); - INIT_LIST_HEAD(&bo->swap); -+ INIT_LIST_HEAD(&bo->io_reserve_lru); - bo->bdev = bdev; - bo->glob = bdev->glob; - bo->type = type; -@@ -1181,7 +1204,8 @@ - bo->mem.num_pages = bo->num_pages; - bo->mem.mm_node = NULL; - bo->mem.page_alignment = page_alignment; -- bo->mem.bus.io_reserved = false; -+ bo->mem.bus.io_reserved_vm = false; -+ bo->mem.bus.io_reserved_count = 0; - bo->buffer_start = buffer_start & PAGE_MASK; - bo->priv_flags = 0; - bo->mem.placement = (TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED); -@@ -1355,6 +1379,10 @@ - BUG_ON(type >= TTM_NUM_MEM_TYPES); - man = &bdev->man[type]; - BUG_ON(man->has_type); -+ man->io_reserve_fastpath = true; -+ man->use_io_reserve_lru = false; -+ mutex_init(&man->io_reserve_mutex); -+ INIT_LIST_HEAD(&man->io_reserve_lru); - - ret = bdev->driver->init_mem_type(bdev, type, man); - if (ret) -@@ -1527,7 +1555,8 @@ - bdev->dev_mapping = NULL; - bdev->glob = glob; - bdev->need_dma32 = need_dma32; -- -+ bdev->val_seq = 0; -+ spin_lock_init(&bdev->fence_lock); - mutex_lock(&glob->device_list_mutex); - list_add_tail(&bdev->device_list, &glob->device_list); - mutex_unlock(&glob->device_list_mutex); -@@ -1561,7 +1590,7 @@ - return true; - } - --void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) -+void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo) - { - struct ttm_bo_device *bdev = bo->bdev; - loff_t offset = (loff_t) bo->addr_space_offset; -@@ -1570,8 +1599,20 @@ - if (!bdev->dev_mapping) - return; - unmap_mapping_range(bdev->dev_mapping, offset, holelen, 1); -- ttm_mem_io_free(bdev, &bo->mem); -+ ttm_mem_io_free_vm(bo); -+} -+ -+void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) -+{ -+ struct ttm_bo_device *bdev = bo->bdev; -+ struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type]; -+ -+ ttm_mem_io_lock(man, false); -+ ttm_bo_unmap_virtual_locked(bo); -+ ttm_mem_io_unlock(man); - } -+ -+ - EXPORT_SYMBOL(ttm_bo_unmap_virtual); - - static void ttm_bo_vm_insert_rb(struct ttm_buffer_object *bo) -@@ -1651,6 +1692,7 @@ - bool lazy, bool interruptible, bool no_wait) - { - struct ttm_bo_driver *driver = bo->bdev->driver; -+ struct ttm_bo_device *bdev = bo->bdev; - void *sync_obj; - void *sync_obj_arg; - int ret = 0; -@@ -1664,9 +1706,9 @@ - void *tmp_obj = bo->sync_obj; - bo->sync_obj = NULL; - clear_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags); -- spin_unlock(&bo->lock); -+ spin_unlock(&bdev->fence_lock); - driver->sync_obj_unref(&tmp_obj); -- spin_lock(&bo->lock); -+ spin_lock(&bdev->fence_lock); - continue; - } - -@@ -1675,29 +1717,29 @@ - - sync_obj = driver->sync_obj_ref(bo->sync_obj); - sync_obj_arg = bo->sync_obj_arg; -- spin_unlock(&bo->lock); -+ spin_unlock(&bdev->fence_lock); - ret = driver->sync_obj_wait(sync_obj, sync_obj_arg, - lazy, interruptible); - if (unlikely(ret != 0)) { - driver->sync_obj_unref(&sync_obj); -- spin_lock(&bo->lock); -+ spin_lock(&bdev->fence_lock); - return ret; - } -- spin_lock(&bo->lock); -+ spin_lock(&bdev->fence_lock); - if (likely(bo->sync_obj == sync_obj && - bo->sync_obj_arg == sync_obj_arg)) { - void *tmp_obj = bo->sync_obj; - bo->sync_obj = NULL; - clear_bit(TTM_BO_PRIV_FLAG_MOVING, - &bo->priv_flags); -- spin_unlock(&bo->lock); -+ spin_unlock(&bdev->fence_lock); - driver->sync_obj_unref(&sync_obj); - driver->sync_obj_unref(&tmp_obj); -- spin_lock(&bo->lock); -+ spin_lock(&bdev->fence_lock); - } else { -- spin_unlock(&bo->lock); -+ spin_unlock(&bdev->fence_lock); - driver->sync_obj_unref(&sync_obj); -- spin_lock(&bo->lock); -+ spin_lock(&bdev->fence_lock); - } - } - return 0; -@@ -1706,6 +1748,7 @@ - - int ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait) - { -+ struct ttm_bo_device *bdev = bo->bdev; - int ret = 0; - - /* -@@ -1715,9 +1758,9 @@ - ret = ttm_bo_reserve(bo, true, no_wait, false, 0); - if (unlikely(ret != 0)) - return ret; -- spin_lock(&bo->lock); -+ spin_lock(&bdev->fence_lock); - ret = ttm_bo_wait(bo, false, true, no_wait); -- spin_unlock(&bo->lock); -+ spin_unlock(&bdev->fence_lock); - if (likely(ret == 0)) - atomic_inc(&bo->cpu_writers); - ttm_bo_unreserve(bo); -@@ -1783,16 +1826,15 @@ - put_count = ttm_bo_del_from_lru(bo); - spin_unlock(&glob->lru_lock); - -- while (put_count--) -- kref_put(&bo->list_kref, ttm_bo_ref_bug); -+ ttm_bo_list_ref_sub(bo, put_count, true); - - /** - * Wait for GPU, then move to system cached. - */ - -- spin_lock(&bo->lock); -+ spin_lock(&bo->bdev->fence_lock); - ret = ttm_bo_wait(bo, false, false, false); -- spin_unlock(&bo->lock); -+ spin_unlock(&bo->bdev->fence_lock); - - if (unlikely(ret != 0)) - goto out; -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/ttm/ttm_bo_util.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/ttm/ttm_bo_util.c ---- linux-2.6.37-rc3/drivers/gpu/drm/ttm/ttm_bo_util.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/ttm/ttm_bo_util.c 2011-01-07 14:22:17.000000000 +0100 -@@ -75,37 +75,123 @@ - } - EXPORT_SYMBOL(ttm_bo_move_ttm); - --int ttm_mem_io_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) -+int ttm_mem_io_lock(struct ttm_mem_type_manager *man, bool interruptible) - { -- int ret; -+ if (likely(man->io_reserve_fastpath)) -+ return 0; -+ -+ if (interruptible) -+ return mutex_lock_interruptible(&man->io_reserve_mutex); -+ -+ mutex_lock(&man->io_reserve_mutex); -+ return 0; -+} - -- if (!mem->bus.io_reserved) { -- mem->bus.io_reserved = true; -+void ttm_mem_io_unlock(struct ttm_mem_type_manager *man) -+{ -+ if (likely(man->io_reserve_fastpath)) -+ return; -+ -+ mutex_unlock(&man->io_reserve_mutex); -+} -+ -+static int ttm_mem_io_evict(struct ttm_mem_type_manager *man) -+{ -+ struct ttm_buffer_object *bo; -+ -+ if (!man->use_io_reserve_lru || list_empty(&man->io_reserve_lru)) -+ return -EAGAIN; -+ -+ bo = list_first_entry(&man->io_reserve_lru, -+ struct ttm_buffer_object, -+ io_reserve_lru); -+ list_del_init(&bo->io_reserve_lru); -+ ttm_bo_unmap_virtual_locked(bo); -+ -+ return 0; -+} -+ -+static int ttm_mem_io_reserve(struct ttm_bo_device *bdev, -+ struct ttm_mem_reg *mem) -+{ -+ struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; -+ int ret = 0; -+ -+ if (!bdev->driver->io_mem_reserve) -+ return 0; -+ if (likely(man->io_reserve_fastpath)) -+ return bdev->driver->io_mem_reserve(bdev, mem); -+ -+ if (bdev->driver->io_mem_reserve && -+ mem->bus.io_reserved_count++ == 0) { -+retry: - ret = bdev->driver->io_mem_reserve(bdev, mem); -+ if (ret == -EAGAIN) { -+ ret = ttm_mem_io_evict(man); -+ if (ret == 0) -+ goto retry; -+ } -+ } -+ return ret; -+} -+ -+static void ttm_mem_io_free(struct ttm_bo_device *bdev, -+ struct ttm_mem_reg *mem) -+{ -+ struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; -+ -+ if (likely(man->io_reserve_fastpath)) -+ return; -+ -+ if (bdev->driver->io_mem_reserve && -+ --mem->bus.io_reserved_count == 0 && -+ bdev->driver->io_mem_free) -+ bdev->driver->io_mem_free(bdev, mem); -+ -+} -+ -+int ttm_mem_io_reserve_vm(struct ttm_buffer_object *bo) -+{ -+ struct ttm_mem_reg *mem = &bo->mem; -+ int ret; -+ -+ if (!mem->bus.io_reserved_vm) { -+ struct ttm_mem_type_manager *man = -+ &bo->bdev->man[mem->mem_type]; -+ -+ ret = ttm_mem_io_reserve(bo->bdev, mem); - if (unlikely(ret != 0)) - return ret; -+ mem->bus.io_reserved_vm = true; -+ if (man->use_io_reserve_lru) -+ list_add_tail(&bo->io_reserve_lru, -+ &man->io_reserve_lru); - } - return 0; - } - --void ttm_mem_io_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) -+void ttm_mem_io_free_vm(struct ttm_buffer_object *bo) - { -- if (bdev->driver->io_mem_reserve) { -- if (mem->bus.io_reserved) { -- mem->bus.io_reserved = false; -- bdev->driver->io_mem_free(bdev, mem); -- } -+ struct ttm_mem_reg *mem = &bo->mem; -+ -+ if (mem->bus.io_reserved_vm) { -+ mem->bus.io_reserved_vm = false; -+ list_del_init(&bo->io_reserve_lru); -+ ttm_mem_io_free(bo->bdev, mem); - } - } - - int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem, - void **virtual) - { -+ struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; - int ret; - void *addr; - - *virtual = NULL; -+ (void) ttm_mem_io_lock(man, false); - ret = ttm_mem_io_reserve(bdev, mem); -+ ttm_mem_io_unlock(man); - if (ret || !mem->bus.is_iomem) - return ret; - -@@ -117,7 +203,9 @@ - else - addr = ioremap_nocache(mem->bus.base + mem->bus.offset, mem->bus.size); - if (!addr) { -+ (void) ttm_mem_io_lock(man, false); - ttm_mem_io_free(bdev, mem); -+ ttm_mem_io_unlock(man); - return -ENOMEM; - } - } -@@ -134,7 +222,9 @@ - - if (virtual && mem->bus.addr == NULL) - iounmap(virtual); -+ (void) ttm_mem_io_lock(man, false); - ttm_mem_io_free(bdev, mem); -+ ttm_mem_io_unlock(man); - } - - static int ttm_copy_io_page(void *dst, void *src, unsigned long page) -@@ -231,7 +321,7 @@ - struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type]; - struct ttm_tt *ttm = bo->ttm; - struct ttm_mem_reg *old_mem = &bo->mem; -- struct ttm_mem_reg old_copy = *old_mem; -+ struct ttm_mem_reg old_copy; - void *old_iomap; - void *new_iomap; - int ret; -@@ -280,8 +370,7 @@ - } - mb(); - out2: -- ttm_bo_free_old_node(bo); -- -+ old_copy = *old_mem; - *old_mem = *new_mem; - new_mem->mm_node = NULL; - -@@ -292,9 +381,10 @@ - } - - out1: -- ttm_mem_reg_iounmap(bdev, new_mem, new_iomap); -+ ttm_mem_reg_iounmap(bdev, old_mem, new_iomap); - out: - ttm_mem_reg_iounmap(bdev, &old_copy, old_iomap); -+ ttm_bo_mem_put(bo, &old_copy); - return ret; - } - EXPORT_SYMBOL(ttm_bo_move_memcpy); -@@ -337,11 +427,11 @@ - * TODO: Explicit member copy would probably be better here. - */ - -- spin_lock_init(&fbo->lock); - init_waitqueue_head(&fbo->event_queue); - INIT_LIST_HEAD(&fbo->ddestroy); - INIT_LIST_HEAD(&fbo->lru); - INIT_LIST_HEAD(&fbo->swap); -+ INIT_LIST_HEAD(&fbo->io_reserve_lru); - fbo->vm_node = NULL; - atomic_set(&fbo->cpu_writers, 0); - -@@ -453,6 +543,8 @@ - unsigned long start_page, unsigned long num_pages, - struct ttm_bo_kmap_obj *map) - { -+ struct ttm_mem_type_manager *man = -+ &bo->bdev->man[bo->mem.mem_type]; - unsigned long offset, size; - int ret; - -@@ -467,7 +559,9 @@ - if (num_pages > 1 && !DRM_SUSER(DRM_CURPROC)) - return -EPERM; - #endif -+ (void) ttm_mem_io_lock(man, false); - ret = ttm_mem_io_reserve(bo->bdev, &bo->mem); -+ ttm_mem_io_unlock(man); - if (ret) - return ret; - if (!bo->mem.bus.is_iomem) { -@@ -482,12 +576,15 @@ - - void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) - { -+ struct ttm_buffer_object *bo = map->bo; -+ struct ttm_mem_type_manager *man = -+ &bo->bdev->man[bo->mem.mem_type]; -+ - if (!map->virtual) - return; - switch (map->bo_kmap_type) { - case ttm_bo_map_iomap: - iounmap(map->virtual); -- ttm_mem_io_free(map->bo->bdev, &map->bo->mem); - break; - case ttm_bo_map_vmap: - vunmap(map->virtual); -@@ -500,6 +597,9 @@ - default: - BUG(); - } -+ (void) ttm_mem_io_lock(man, false); -+ ttm_mem_io_free(map->bo->bdev, &map->bo->mem); -+ ttm_mem_io_unlock(man); - map->virtual = NULL; - map->page = NULL; - } -@@ -520,7 +620,7 @@ - struct ttm_buffer_object *ghost_obj; - void *tmp_obj = NULL; - -- spin_lock(&bo->lock); -+ spin_lock(&bdev->fence_lock); - if (bo->sync_obj) { - tmp_obj = bo->sync_obj; - bo->sync_obj = NULL; -@@ -529,7 +629,7 @@ - bo->sync_obj_arg = sync_obj_arg; - if (evict) { - ret = ttm_bo_wait(bo, false, false, false); -- spin_unlock(&bo->lock); -+ spin_unlock(&bdev->fence_lock); - if (tmp_obj) - driver->sync_obj_unref(&tmp_obj); - if (ret) -@@ -552,7 +652,7 @@ - */ - - set_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags); -- spin_unlock(&bo->lock); -+ spin_unlock(&bdev->fence_lock); - if (tmp_obj) - driver->sync_obj_unref(&tmp_obj); - -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/ttm/ttm_bo_vm.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/ttm/ttm_bo_vm.c ---- linux-2.6.37-rc3/drivers/gpu/drm/ttm/ttm_bo_vm.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/ttm/ttm_bo_vm.c 2011-01-07 14:22:17.000000000 +0100 -@@ -83,6 +83,8 @@ - int i; - unsigned long address = (unsigned long)vmf->virtual_address; - int retval = VM_FAULT_NOPAGE; -+ struct ttm_mem_type_manager *man = -+ &bdev->man[bo->mem.mem_type]; - - /* - * Work around locking order reversal in fault / nopfn -@@ -118,24 +120,28 @@ - * move. - */ - -- spin_lock(&bo->lock); -+ spin_lock(&bdev->fence_lock); - if (test_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags)) { - ret = ttm_bo_wait(bo, false, true, false); -- spin_unlock(&bo->lock); -+ spin_unlock(&bdev->fence_lock); - if (unlikely(ret != 0)) { - retval = (ret != -ERESTARTSYS) ? - VM_FAULT_SIGBUS : VM_FAULT_NOPAGE; - goto out_unlock; - } - } else -- spin_unlock(&bo->lock); -+ spin_unlock(&bdev->fence_lock); - -- -- ret = ttm_mem_io_reserve(bdev, &bo->mem); -- if (ret) { -- retval = VM_FAULT_SIGBUS; -+ ret = ttm_mem_io_lock(man, true); -+ if (unlikely(ret != 0)) { -+ retval = VM_FAULT_NOPAGE; - goto out_unlock; - } -+ ret = ttm_mem_io_reserve_vm(bo); -+ if (unlikely(ret != 0)) { -+ retval = VM_FAULT_SIGBUS; -+ goto out_io_unlock; -+ } - - page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) + - bo->vm_node->start - vma->vm_pgoff; -@@ -144,7 +150,7 @@ - - if (unlikely(page_offset >= bo->num_pages)) { - retval = VM_FAULT_SIGBUS; -- goto out_unlock; -+ goto out_io_unlock; - } - - /* -@@ -182,7 +188,7 @@ - page = ttm_tt_get_page(ttm, page_offset); - if (unlikely(!page && i == 0)) { - retval = VM_FAULT_OOM; -- goto out_unlock; -+ goto out_io_unlock; - } else if (unlikely(!page)) { - break; - } -@@ -200,14 +206,15 @@ - else if (unlikely(ret != 0)) { - retval = - (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS; -- goto out_unlock; -+ goto out_io_unlock; - } - - address += PAGE_SIZE; - if (unlikely(++page_offset >= page_last)) - break; - } -- -+out_io_unlock: -+ ttm_mem_io_unlock(man); - out_unlock: - ttm_bo_unreserve(bo); - return retval; -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/ttm/ttm_execbuf_util.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/ttm/ttm_execbuf_util.c ---- linux-2.6.37-rc3/drivers/gpu/drm/ttm/ttm_execbuf_util.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/ttm/ttm_execbuf_util.c 2011-01-07 14:22:17.000000000 +0100 -@@ -32,7 +32,7 @@ - #include - #include - --void ttm_eu_backoff_reservation(struct list_head *list) -+static void ttm_eu_backoff_reservation_locked(struct list_head *list) - { - struct ttm_validate_buffer *entry; - -@@ -41,10 +41,77 @@ - if (!entry->reserved) - continue; - -+ if (entry->removed) { -+ ttm_bo_add_to_lru(bo); -+ entry->removed = false; -+ -+ } - entry->reserved = false; -- ttm_bo_unreserve(bo); -+ atomic_set(&bo->reserved, 0); -+ wake_up_all(&bo->event_queue); -+ } -+} -+ -+static void ttm_eu_del_from_lru_locked(struct list_head *list) -+{ -+ struct ttm_validate_buffer *entry; -+ -+ list_for_each_entry(entry, list, head) { -+ struct ttm_buffer_object *bo = entry->bo; -+ if (!entry->reserved) -+ continue; -+ -+ if (!entry->removed) { -+ entry->put_count = ttm_bo_del_from_lru(bo); -+ entry->removed = true; -+ } -+ } -+} -+ -+static void ttm_eu_list_ref_sub(struct list_head *list) -+{ -+ struct ttm_validate_buffer *entry; -+ -+ list_for_each_entry(entry, list, head) { -+ struct ttm_buffer_object *bo = entry->bo; -+ -+ if (entry->put_count) { -+ ttm_bo_list_ref_sub(bo, entry->put_count, true); -+ entry->put_count = 0; -+ } - } - } -+ -+static int ttm_eu_wait_unreserved_locked(struct list_head *list, -+ struct ttm_buffer_object *bo) -+{ -+ struct ttm_bo_global *glob = bo->glob; -+ int ret; -+ -+ ttm_eu_del_from_lru_locked(list); -+ spin_unlock(&glob->lru_lock); -+ ret = ttm_bo_wait_unreserved(bo, true); -+ spin_lock(&glob->lru_lock); -+ if (unlikely(ret != 0)) -+ ttm_eu_backoff_reservation_locked(list); -+ return ret; -+} -+ -+ -+void ttm_eu_backoff_reservation(struct list_head *list) -+{ -+ struct ttm_validate_buffer *entry; -+ struct ttm_bo_global *glob; -+ -+ if (list_empty(list)) -+ return; -+ -+ entry = list_first_entry(list, struct ttm_validate_buffer, head); -+ glob = entry->bo->glob; -+ spin_lock(&glob->lru_lock); -+ ttm_eu_backoff_reservation_locked(list); -+ spin_unlock(&glob->lru_lock); -+} - EXPORT_SYMBOL(ttm_eu_backoff_reservation); - - /* -@@ -59,37 +126,76 @@ - * buffers in different orders. - */ - --int ttm_eu_reserve_buffers(struct list_head *list, uint32_t val_seq) -+int ttm_eu_reserve_buffers(struct list_head *list) - { -+ struct ttm_bo_global *glob; - struct ttm_validate_buffer *entry; - int ret; -+ uint32_t val_seq; -+ -+ if (list_empty(list)) -+ return 0; -+ -+ list_for_each_entry(entry, list, head) { -+ entry->reserved = false; -+ entry->put_count = 0; -+ entry->removed = false; -+ } -+ -+ entry = list_first_entry(list, struct ttm_validate_buffer, head); -+ glob = entry->bo->glob; - - retry: -+ spin_lock(&glob->lru_lock); -+ val_seq = entry->bo->bdev->val_seq++; -+ - list_for_each_entry(entry, list, head) { - struct ttm_buffer_object *bo = entry->bo; - -- entry->reserved = false; -- ret = ttm_bo_reserve(bo, true, false, true, val_seq); -- if (ret != 0) { -- ttm_eu_backoff_reservation(list); -- if (ret == -EAGAIN) { -- ret = ttm_bo_wait_unreserved(bo, true); -- if (unlikely(ret != 0)) -- return ret; -- goto retry; -- } else -+retry_this_bo: -+ ret = ttm_bo_reserve_locked(bo, true, true, true, val_seq); -+ switch (ret) { -+ case 0: -+ break; -+ case -EBUSY: -+ ret = ttm_eu_wait_unreserved_locked(list, bo); -+ if (unlikely(ret != 0)) { -+ spin_unlock(&glob->lru_lock); -+ ttm_eu_list_ref_sub(list); - return ret; -+ } -+ goto retry_this_bo; -+ case -EAGAIN: -+ ttm_eu_backoff_reservation_locked(list); -+ spin_unlock(&glob->lru_lock); -+ ttm_eu_list_ref_sub(list); -+ ret = ttm_bo_wait_unreserved(bo, true); -+ if (unlikely(ret != 0)) -+ return ret; -+ goto retry; -+ default: -+ ttm_eu_backoff_reservation_locked(list); -+ spin_unlock(&glob->lru_lock); -+ ttm_eu_list_ref_sub(list); -+ return ret; - } - - entry->reserved = true; - if (unlikely(atomic_read(&bo->cpu_writers) > 0)) { -- ttm_eu_backoff_reservation(list); -+ ttm_eu_backoff_reservation_locked(list); -+ spin_unlock(&glob->lru_lock); -+ ttm_eu_list_ref_sub(list); - ret = ttm_bo_wait_cpu(bo, false); - if (ret) - return ret; - goto retry; - } - } -+ -+ ttm_eu_del_from_lru_locked(list); -+ spin_unlock(&glob->lru_lock); -+ ttm_eu_list_ref_sub(list); -+ - return 0; - } - EXPORT_SYMBOL(ttm_eu_reserve_buffers); -@@ -97,21 +203,36 @@ - void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj) - { - struct ttm_validate_buffer *entry; -+ struct ttm_buffer_object *bo; -+ struct ttm_bo_global *glob; -+ struct ttm_bo_device *bdev; -+ struct ttm_bo_driver *driver; -+ -+ if (list_empty(list)) -+ return; -+ -+ bo = list_first_entry(list, struct ttm_validate_buffer, head)->bo; -+ bdev = bo->bdev; -+ driver = bdev->driver; -+ glob = bo->glob; - -- list_for_each_entry(entry, list, head) { -- struct ttm_buffer_object *bo = entry->bo; -- struct ttm_bo_driver *driver = bo->bdev->driver; -- void *old_sync_obj; -+ spin_lock(&bdev->fence_lock); -+ spin_lock(&glob->lru_lock); - -- spin_lock(&bo->lock); -- old_sync_obj = bo->sync_obj; -+ list_for_each_entry(entry, list, head) { -+ bo = entry->bo; -+ entry->old_sync_obj = bo->sync_obj; - bo->sync_obj = driver->sync_obj_ref(sync_obj); - bo->sync_obj_arg = entry->new_sync_obj_arg; -- spin_unlock(&bo->lock); -- ttm_bo_unreserve(bo); -+ ttm_bo_unreserve_locked(bo); - entry->reserved = false; -- if (old_sync_obj) -- driver->sync_obj_unref(&old_sync_obj); -+ } -+ spin_unlock(&glob->lru_lock); -+ spin_unlock(&bdev->fence_lock); -+ -+ list_for_each_entry(entry, list, head) { -+ if (entry->old_sync_obj) -+ driver->sync_obj_unref(&entry->old_sync_obj); - } - } - EXPORT_SYMBOL(ttm_eu_fence_buffer_objects); -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h ---- linux-2.6.37-rc3/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h 2011-01-07 14:22:17.000000000 +0100 -@@ -264,7 +264,6 @@ - */ - - struct vmw_sw_context ctx; -- uint32_t val_seq; - struct mutex cmdbuf_mutex; - - /** -diff -Naur linux-2.6.37-rc3/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c ---- linux-2.6.37-rc3/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c 2011-01-07 14:22:17.000000000 +0100 -@@ -653,8 +653,7 @@ - ret = vmw_cmd_check_all(dev_priv, sw_context, cmd, arg->command_size); - if (unlikely(ret != 0)) - goto out_err; -- ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes, -- dev_priv->val_seq++); -+ ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes); - if (unlikely(ret != 0)) - goto out_err; - -diff -Naur linux-2.6.37-rc3/include/drm/drm_crtc.h linux-2.6.37-rc3.drm-nouveau-next-20110111/include/drm/drm_crtc.h ---- linux-2.6.37-rc3/include/drm/drm_crtc.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/include/drm/drm_crtc.h 2011-01-07 14:22:17.000000000 +0100 -@@ -351,8 +351,14 @@ - - bool enabled; - -+ /* Requested mode from modesetting. */ - struct drm_display_mode mode; - -+ /* Programmed mode in hw, after adjustments for encoders, -+ * crtc, panel scaling etc. Needed for timestamping etc. -+ */ -+ struct drm_display_mode hwmode; -+ - int x, y; - const struct drm_crtc_funcs *funcs; - -@@ -360,6 +366,9 @@ - uint32_t gamma_size; - uint16_t *gamma_store; - -+ /* Constants needed for precise vblank and swap timestamping. */ -+ s64 framedur_ns, linedur_ns, pixeldur_ns; -+ - /* if you are using the helper */ - void *helper_private; - }; -diff -Naur linux-2.6.37-rc3/include/drm/drm_pciids.h linux-2.6.37-rc3.drm-nouveau-next-20110111/include/drm/drm_pciids.h ---- linux-2.6.37-rc3/include/drm/drm_pciids.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/include/drm/drm_pciids.h 2011-01-07 14:22:17.000000000 +0100 -@@ -419,6 +419,10 @@ - {0x1002, 0x9713, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ - {0x1002, 0x9714, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ - {0x1002, 0x9715, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ -+ {0x1002, 0x9802, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ -+ {0x1002, 0x9803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ -+ {0x1002, 0x9804, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ -+ {0x1002, 0x9805, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ - {0, 0, 0} - - #define r128_PCI_IDS \ -diff -Naur linux-2.6.37-rc3/include/drm/drmP.h linux-2.6.37-rc3.drm-nouveau-next-20110111/include/drm/drmP.h ---- linux-2.6.37-rc3/include/drm/drmP.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/include/drm/drmP.h 2011-01-07 14:22:17.000000000 +0100 -@@ -683,6 +683,21 @@ - void *driver_priv; /**< Private structure for driver to use */ - }; - -+/* Size of ringbuffer for vblank timestamps. Just double-buffer -+ * in initial implementation. -+ */ -+#define DRM_VBLANKTIME_RBSIZE 2 -+ -+/* Flags and return codes for get_vblank_timestamp() driver function. */ -+#define DRM_CALLED_FROM_VBLIRQ 1 -+#define DRM_VBLANKTIME_SCANOUTPOS_METHOD (1 << 0) -+#define DRM_VBLANKTIME_INVBL (1 << 1) -+ -+/* get_scanout_position() return flags */ -+#define DRM_SCANOUTPOS_VALID (1 << 0) -+#define DRM_SCANOUTPOS_INVBL (1 << 1) -+#define DRM_SCANOUTPOS_ACCURATE (1 << 2) -+ - /** - * DRM driver structure. This structure represent the common code for - * a family of cards. There will one drm_device for each card present -@@ -760,6 +775,68 @@ - */ - int (*device_is_agp) (struct drm_device *dev); - -+ /** -+ * Called by vblank timestamping code. -+ * -+ * Return the current display scanout position from a crtc. -+ * -+ * \param dev DRM device. -+ * \param crtc Id of the crtc to query. -+ * \param *vpos Target location for current vertical scanout position. -+ * \param *hpos Target location for current horizontal scanout position. -+ * -+ * Returns vpos as a positive number while in active scanout area. -+ * Returns vpos as a negative number inside vblank, counting the number -+ * of scanlines to go until end of vblank, e.g., -1 means "one scanline -+ * until start of active scanout / end of vblank." -+ * -+ * \return Flags, or'ed together as follows: -+ * -+ * DRM_SCANOUTPOS_VALID = Query successfull. -+ * DRM_SCANOUTPOS_INVBL = Inside vblank. -+ * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of -+ * this flag means that returned position may be offset by a constant -+ * but unknown small number of scanlines wrt. real scanout position. -+ * -+ */ -+ int (*get_scanout_position) (struct drm_device *dev, int crtc, -+ int *vpos, int *hpos); -+ -+ /** -+ * Called by \c drm_get_last_vbltimestamp. Should return a precise -+ * timestamp when the most recent VBLANK interval ended or will end. -+ * -+ * Specifically, the timestamp in @vblank_time should correspond as -+ * closely as possible to the time when the first video scanline of -+ * the video frame after the end of VBLANK will start scanning out, -+ * the time immmediately after end of the VBLANK interval. If the -+ * @crtc is currently inside VBLANK, this will be a time in the future. -+ * If the @crtc is currently scanning out a frame, this will be the -+ * past start time of the current scanout. This is meant to adhere -+ * to the OpenML OML_sync_control extension specification. -+ * -+ * \param dev dev DRM device handle. -+ * \param crtc crtc for which timestamp should be returned. -+ * \param *max_error Maximum allowable timestamp error in nanoseconds. -+ * Implementation should strive to provide timestamp -+ * with an error of at most *max_error nanoseconds. -+ * Returns true upper bound on error for timestamp. -+ * \param *vblank_time Target location for returned vblank timestamp. -+ * \param flags 0 = Defaults, no special treatment needed. -+ * \param DRM_CALLED_FROM_VBLIRQ = Function is called from vblank -+ * irq handler. Some drivers need to apply some workarounds -+ * for gpu-specific vblank irq quirks if flag is set. -+ * -+ * \returns -+ * Zero if timestamping isn't supported in current display mode or a -+ * negative number on failure. A positive status code on success, -+ * which describes how the vblank_time timestamp was computed. -+ */ -+ int (*get_vblank_timestamp) (struct drm_device *dev, int crtc, -+ int *max_error, -+ struct timeval *vblank_time, -+ unsigned flags); -+ - /* these have to be filled in */ - - irqreturn_t(*irq_handler) (DRM_IRQ_ARGS); -@@ -983,6 +1060,8 @@ - - wait_queue_head_t *vbl_queue; /**< VBLANK wait queue */ - atomic_t *_vblank_count; /**< number of VBLANK interrupts (driver must alloc the right number of counters) */ -+ struct timeval *_vblank_time; /**< timestamp of current vblank_count (drivers must alloc right number of fields) */ -+ spinlock_t vblank_time_lock; /**< Protects vblank count and time updates during vblank enable/disable */ - spinlock_t vbl_lock; - atomic_t *vblank_refcount; /* number of users of vblank interruptsper crtc */ - u32 *last_vblank; /* protected by dev->vbl_lock, used */ -@@ -1284,11 +1363,22 @@ - struct drm_file *filp); - extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq); - extern u32 drm_vblank_count(struct drm_device *dev, int crtc); -+extern u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, -+ struct timeval *vblanktime); - extern void drm_handle_vblank(struct drm_device *dev, int crtc); - extern int drm_vblank_get(struct drm_device *dev, int crtc); - extern void drm_vblank_put(struct drm_device *dev, int crtc); - extern void drm_vblank_off(struct drm_device *dev, int crtc); - extern void drm_vblank_cleanup(struct drm_device *dev); -+extern u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, -+ struct timeval *tvblank, unsigned flags); -+extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, -+ int crtc, int *max_error, -+ struct timeval *vblank_time, -+ unsigned flags, -+ struct drm_crtc *refcrtc); -+extern void drm_calc_timestamping_constants(struct drm_crtc *crtc); -+ - /* Modesetting support */ - extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc); - extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc); -@@ -1340,6 +1430,9 @@ - extern int drm_put_minor(struct drm_minor **minor); - extern unsigned int drm_debug; - -+extern unsigned int drm_vblank_offdelay; -+extern unsigned int drm_timestamp_precision; -+ - extern struct class *drm_class; - extern struct proc_dir_entry *drm_proc_root; - extern struct dentry *drm_debugfs_root; -diff -Naur linux-2.6.37-rc3/include/drm/nouveau_drm.h linux-2.6.37-rc3.drm-nouveau-next-20110111/include/drm/nouveau_drm.h ---- linux-2.6.37-rc3/include/drm/nouveau_drm.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/include/drm/nouveau_drm.h 2011-01-07 14:22:17.000000000 +0100 -@@ -71,16 +71,14 @@ - #define NOUVEAU_GETPARAM_PCI_VENDOR 3 - #define NOUVEAU_GETPARAM_PCI_DEVICE 4 - #define NOUVEAU_GETPARAM_BUS_TYPE 5 --#define NOUVEAU_GETPARAM_FB_PHYSICAL 6 --#define NOUVEAU_GETPARAM_AGP_PHYSICAL 7 - #define NOUVEAU_GETPARAM_FB_SIZE 8 - #define NOUVEAU_GETPARAM_AGP_SIZE 9 --#define NOUVEAU_GETPARAM_PCI_PHYSICAL 10 - #define NOUVEAU_GETPARAM_CHIPSET_ID 11 - #define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 - #define NOUVEAU_GETPARAM_GRAPH_UNITS 13 - #define NOUVEAU_GETPARAM_PTIMER_TIME 14 - #define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 -+#define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16 - struct drm_nouveau_getparam { - uint64_t param; - uint64_t value; -@@ -171,7 +169,6 @@ - }; - - #define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001 --#define NOUVEAU_GEM_CPU_PREP_NOBLOCK 0x00000002 - #define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004 - struct drm_nouveau_gem_cpu_prep { - uint32_t handle; -diff -Naur linux-2.6.37-rc3/include/drm/ttm/ttm_bo_api.h linux-2.6.37-rc3.drm-nouveau-next-20110111/include/drm/ttm/ttm_bo_api.h ---- linux-2.6.37-rc3/include/drm/ttm/ttm_bo_api.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/include/drm/ttm/ttm_bo_api.h 2011-01-07 14:22:17.000000000 +0100 -@@ -74,6 +74,8 @@ - * @is_iomem: is this io memory ? - * @size: size in byte - * @offset: offset from the base address -+ * @io_reserved_vm: The VM system has a refcount in @io_reserved_count -+ * @io_reserved_count: Refcounting the numbers of callers to ttm_mem_io_reserve - * - * Structure indicating the bus placement of an object. - */ -@@ -83,7 +85,8 @@ - unsigned long size; - unsigned long offset; - bool is_iomem; -- bool io_reserved; -+ bool io_reserved_vm; -+ uint64_t io_reserved_count; - }; - - -@@ -154,7 +157,6 @@ - * keeps one refcount. When this refcount reaches zero, - * the object is destroyed. - * @event_queue: Queue for processes waiting on buffer object status change. -- * @lock: spinlock protecting mostly synchronization members. - * @mem: structure describing current placement. - * @persistant_swap_storage: Usually the swap storage is deleted for buffers - * pinned in physical memory. If this behaviour is not desired, this member -@@ -213,7 +215,6 @@ - struct kref kref; - struct kref list_kref; - wait_queue_head_t event_queue; -- spinlock_t lock; - - /** - * Members protected by the bo::reserved lock. -@@ -237,6 +238,7 @@ - struct list_head lru; - struct list_head ddestroy; - struct list_head swap; -+ struct list_head io_reserve_lru; - uint32_t val_seq; - bool seq_valid; - -@@ -248,10 +250,10 @@ - atomic_t reserved; - - /** -- * Members protected by the bo::lock -+ * Members protected by struct buffer_object_device::fence_lock - * In addition, setting sync_obj to anything else - * than NULL requires bo::reserved to be held. This allows for -- * checking NULL while reserved but not holding bo::lock. -+ * checking NULL while reserved but not holding the mentioned lock. - */ - - void *sync_obj_arg; -@@ -364,6 +366,44 @@ - */ - extern void ttm_bo_unref(struct ttm_buffer_object **bo); - -+ -+/** -+ * ttm_bo_list_ref_sub -+ * -+ * @bo: The buffer object. -+ * @count: The number of references with which to decrease @bo::list_kref; -+ * @never_free: The refcount should not reach zero with this operation. -+ * -+ * Release @count lru list references to this buffer object. -+ */ -+extern void ttm_bo_list_ref_sub(struct ttm_buffer_object *bo, int count, -+ bool never_free); -+ -+/** -+ * ttm_bo_add_to_lru -+ * -+ * @bo: The buffer object. -+ * -+ * Add this bo to the relevant mem type lru and, if it's backed by -+ * system pages (ttms) to the swap list. -+ * This function must be called with struct ttm_bo_global::lru_lock held, and -+ * is typically called immediately prior to unreserving a bo. -+ */ -+extern void ttm_bo_add_to_lru(struct ttm_buffer_object *bo); -+ -+/** -+ * ttm_bo_del_from_lru -+ * -+ * @bo: The buffer object. -+ * -+ * Remove this bo from all lru lists used to lookup and reserve an object. -+ * This function must be called with struct ttm_bo_global::lru_lock held, -+ * and is usually called just immediately after the bo has been reserved to -+ * avoid recursive reservation from lru lists. -+ */ -+extern int ttm_bo_del_from_lru(struct ttm_buffer_object *bo); -+ -+ - /** - * ttm_bo_lock_delayed_workqueue - * -diff -Naur linux-2.6.37-rc3/include/drm/ttm/ttm_bo_driver.h linux-2.6.37-rc3.drm-nouveau-next-20110111/include/drm/ttm/ttm_bo_driver.h ---- linux-2.6.37-rc3/include/drm/ttm/ttm_bo_driver.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/include/drm/ttm/ttm_bo_driver.h 2011-01-07 14:22:17.000000000 +0100 -@@ -179,30 +179,6 @@ - #define TTM_MEMTYPE_FLAG_MAPPABLE (1 << 1) /* Memory mappable */ - #define TTM_MEMTYPE_FLAG_CMA (1 << 3) /* Can't map aperture */ - --/** -- * struct ttm_mem_type_manager -- * -- * @has_type: The memory type has been initialized. -- * @use_type: The memory type is enabled. -- * @flags: TTM_MEMTYPE_XX flags identifying the traits of the memory -- * managed by this memory type. -- * @gpu_offset: If used, the GPU offset of the first managed page of -- * fixed memory or the first managed location in an aperture. -- * @size: Size of the managed region. -- * @available_caching: A mask of available caching types, TTM_PL_FLAG_XX, -- * as defined in ttm_placement_common.h -- * @default_caching: The default caching policy used for a buffer object -- * placed in this memory type if the user doesn't provide one. -- * @manager: The range manager used for this memory type. FIXME: If the aperture -- * has a page size different from the underlying system, the granularity -- * of this manager should take care of this. But the range allocating code -- * in ttm_bo.c needs to be modified for this. -- * @lru: The lru list for this memory type. -- * -- * This structure is used to identify and manage memory types for a device. -- * It's set up by the ttm_bo_driver::init_mem_type method. -- */ -- - struct ttm_mem_type_manager; - - struct ttm_mem_type_manager_func { -@@ -287,6 +263,36 @@ - void (*debug)(struct ttm_mem_type_manager *man, const char *prefix); - }; - -+/** -+ * struct ttm_mem_type_manager -+ * -+ * @has_type: The memory type has been initialized. -+ * @use_type: The memory type is enabled. -+ * @flags: TTM_MEMTYPE_XX flags identifying the traits of the memory -+ * managed by this memory type. -+ * @gpu_offset: If used, the GPU offset of the first managed page of -+ * fixed memory or the first managed location in an aperture. -+ * @size: Size of the managed region. -+ * @available_caching: A mask of available caching types, TTM_PL_FLAG_XX, -+ * as defined in ttm_placement_common.h -+ * @default_caching: The default caching policy used for a buffer object -+ * placed in this memory type if the user doesn't provide one. -+ * @func: structure pointer implementing the range manager. See above -+ * @priv: Driver private closure for @func. -+ * @io_reserve_mutex: Mutex optionally protecting shared io_reserve structures -+ * @use_io_reserve_lru: Use an lru list to try to unreserve io_mem_regions -+ * reserved by the TTM vm system. -+ * @io_reserve_lru: Optional lru list for unreserving io mem regions. -+ * @io_reserve_fastpath: Only use bdev::driver::io_mem_reserve to obtain -+ * static information. bdev::driver::io_mem_free is never used. -+ * @lru: The lru list for this memory type. -+ * -+ * This structure is used to identify and manage memory types for a device. -+ * It's set up by the ttm_bo_driver::init_mem_type method. -+ */ -+ -+ -+ - struct ttm_mem_type_manager { - struct ttm_bo_device *bdev; - -@@ -303,6 +309,15 @@ - uint32_t default_caching; - const struct ttm_mem_type_manager_func *func; - void *priv; -+ struct mutex io_reserve_mutex; -+ bool use_io_reserve_lru; -+ bool io_reserve_fastpath; -+ -+ /* -+ * Protected by @io_reserve_mutex: -+ */ -+ -+ struct list_head io_reserve_lru; - - /* - * Protected by the global->lru_lock. -@@ -510,9 +525,12 @@ - * - * @driver: Pointer to a struct ttm_bo_driver struct setup by the driver. - * @man: An array of mem_type_managers. -+ * @fence_lock: Protects the synchronizing members on *all* bos belonging -+ * to this device. - * @addr_space_mm: Range manager for the device address space. - * lru_lock: Spinlock that protects the buffer+device lru lists and - * ddestroy lists. -+ * @val_seq: Current validation sequence. - * @nice_mode: Try nicely to wait for buffer idle when cleaning a manager. - * If a GPU lockup has been detected, this is forced to 0. - * @dev_mapping: A pointer to the struct address_space representing the -@@ -531,6 +549,7 @@ - struct ttm_bo_driver *driver; - rwlock_t vm_lock; - struct ttm_mem_type_manager man[TTM_NUM_MEM_TYPES]; -+ spinlock_t fence_lock; - /* - * Protected by the vm lock. - */ -@@ -541,6 +560,7 @@ - * Protected by the global:lru lock. - */ - struct list_head ddestroy; -+ uint32_t val_seq; - - /* - * Protected by load / firstopen / lastclose /unload sync. -@@ -753,31 +773,6 @@ - - extern int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait); - --/** -- * ttm_bo_pci_offset - Get the PCI offset for the buffer object memory. -- * -- * @bo Pointer to a struct ttm_buffer_object. -- * @bus_base On return the base of the PCI region -- * @bus_offset On return the byte offset into the PCI region -- * @bus_size On return the byte size of the buffer object or zero if -- * the buffer object memory is not accessible through a PCI region. -- * -- * Returns: -- * -EINVAL if the buffer object is currently not mappable. -- * 0 otherwise. -- */ -- --extern int ttm_bo_pci_offset(struct ttm_bo_device *bdev, -- struct ttm_mem_reg *mem, -- unsigned long *bus_base, -- unsigned long *bus_offset, -- unsigned long *bus_size); -- --extern int ttm_mem_io_reserve(struct ttm_bo_device *bdev, -- struct ttm_mem_reg *mem); --extern void ttm_mem_io_free(struct ttm_bo_device *bdev, -- struct ttm_mem_reg *mem); -- - extern void ttm_bo_global_release(struct drm_global_reference *ref); - extern int ttm_bo_global_init(struct drm_global_reference *ref); - -@@ -810,6 +805,22 @@ - extern void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo); - - /** -+ * ttm_bo_unmap_virtual -+ * -+ * @bo: tear down the virtual mappings for this BO -+ * -+ * The caller must take ttm_mem_io_lock before calling this function. -+ */ -+extern void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo); -+ -+extern int ttm_mem_io_reserve_vm(struct ttm_buffer_object *bo); -+extern void ttm_mem_io_free_vm(struct ttm_buffer_object *bo); -+extern int ttm_mem_io_lock(struct ttm_mem_type_manager *man, -+ bool interruptible); -+extern void ttm_mem_io_unlock(struct ttm_mem_type_manager *man); -+ -+ -+/** - * ttm_bo_reserve: - * - * @bo: A pointer to a struct ttm_buffer_object. -@@ -859,11 +870,44 @@ - * try again. (only if use_sequence == 1). - * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by - * a signal. Release all buffer reservations and return to user-space. -+ * -EBUSY: The function needed to sleep, but @no_wait was true -+ * -EDEADLK: Bo already reserved using @sequence. This error code will only -+ * be returned if @use_sequence is set to true. - */ - extern int ttm_bo_reserve(struct ttm_buffer_object *bo, - bool interruptible, - bool no_wait, bool use_sequence, uint32_t sequence); - -+ -+/** -+ * ttm_bo_reserve_locked: -+ * -+ * @bo: A pointer to a struct ttm_buffer_object. -+ * @interruptible: Sleep interruptible if waiting. -+ * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY. -+ * @use_sequence: If @bo is already reserved, Only sleep waiting for -+ * it to become unreserved if @sequence < (@bo)->sequence. -+ * -+ * Must be called with struct ttm_bo_global::lru_lock held, -+ * and will not remove reserved buffers from the lru lists. -+ * The function may release the LRU spinlock if it needs to sleep. -+ * Otherwise identical to ttm_bo_reserve. -+ * -+ * Returns: -+ * -EAGAIN: The reservation may cause a deadlock. -+ * Release all buffer reservations, wait for @bo to become unreserved and -+ * try again. (only if use_sequence == 1). -+ * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by -+ * a signal. Release all buffer reservations and return to user-space. -+ * -EBUSY: The function needed to sleep, but @no_wait was true -+ * -EDEADLK: Bo already reserved using @sequence. This error code will only -+ * be returned if @use_sequence is set to true. -+ */ -+extern int ttm_bo_reserve_locked(struct ttm_buffer_object *bo, -+ bool interruptible, -+ bool no_wait, bool use_sequence, -+ uint32_t sequence); -+ - /** - * ttm_bo_unreserve - * -@@ -874,6 +918,16 @@ - extern void ttm_bo_unreserve(struct ttm_buffer_object *bo); - - /** -+ * ttm_bo_unreserve_locked -+ * -+ * @bo: A pointer to a struct ttm_buffer_object. -+ * -+ * Unreserve a previous reservation of @bo. -+ * Needs to be called with struct ttm_bo_global::lru_lock held. -+ */ -+extern void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo); -+ -+/** - * ttm_bo_wait_unreserved - * - * @bo: A pointer to a struct ttm_buffer_object. -diff -Naur linux-2.6.37-rc3/include/drm/ttm/ttm_execbuf_util.h linux-2.6.37-rc3.drm-nouveau-next-20110111/include/drm/ttm/ttm_execbuf_util.h ---- linux-2.6.37-rc3/include/drm/ttm/ttm_execbuf_util.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/include/drm/ttm/ttm_execbuf_util.h 2011-01-07 14:22:17.000000000 +0100 -@@ -41,7 +41,10 @@ - * @bo: refcounted buffer object pointer. - * @new_sync_obj_arg: New sync_obj_arg for @bo, to be used once - * adding a new sync object. -- * @reservied: Indicates whether @bo has been reserved for validation. -+ * @reserved: Indicates whether @bo has been reserved for validation. -+ * @removed: Indicates whether @bo has been removed from lru lists. -+ * @put_count: Number of outstanding references on bo::list_kref. -+ * @old_sync_obj: Pointer to a sync object about to be unreferenced - */ - - struct ttm_validate_buffer { -@@ -49,6 +52,9 @@ - struct ttm_buffer_object *bo; - void *new_sync_obj_arg; - bool reserved; -+ bool removed; -+ int put_count; -+ void *old_sync_obj; - }; - - /** -@@ -66,7 +72,6 @@ - * function ttm_eu_reserve_buffers - * - * @list: thread private list of ttm_validate_buffer structs. -- * @val_seq: A unique sequence number. - * - * Tries to reserve bos pointed to by the list entries for validation. - * If the function returns 0, all buffers are marked as "unfenced", -@@ -88,7 +93,7 @@ - * has failed. - */ - --extern int ttm_eu_reserve_buffers(struct list_head *list, uint32_t val_seq); -+extern int ttm_eu_reserve_buffers(struct list_head *list); - - /** - * function ttm_eu_fence_buffer_objects. -diff -Naur linux-2.6.37-rc3/include/linux/kref.h linux-2.6.37-rc3.drm-nouveau-next-20110111/include/linux/kref.h ---- linux-2.6.37-rc3/include/linux/kref.h 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/include/linux/kref.h 2011-01-07 14:22:17.000000000 +0100 -@@ -24,5 +24,7 @@ - void kref_init(struct kref *kref); - void kref_get(struct kref *kref); - int kref_put(struct kref *kref, void (*release) (struct kref *kref)); -+int kref_sub(struct kref *kref, unsigned int count, -+ void (*release) (struct kref *kref)); - - #endif /* _KREF_H_ */ -diff -Naur linux-2.6.37-rc3/lib/kref.c linux-2.6.37-rc3.drm-nouveau-next-20110111/lib/kref.c ---- linux-2.6.37-rc3/lib/kref.c 2010-11-22 00:18:56.000000000 +0100 -+++ linux-2.6.37-rc3.drm-nouveau-next-20110111/lib/kref.c 2011-01-07 14:22:17.000000000 +0100 -@@ -62,6 +62,36 @@ - return 0; - } - -+ -+/** -+ * kref_sub - subtract a number of refcounts for object. -+ * @kref: object. -+ * @count: Number of recounts to subtract. -+ * @release: pointer to the function that will clean up the object when the -+ * last reference to the object is released. -+ * This pointer is required, and it is not acceptable to pass kfree -+ * in as this function. -+ * -+ * Subtract @count from the refcount, and if 0, call release(). -+ * Return 1 if the object was removed, otherwise return 0. Beware, if this -+ * function returns 0, you still can not count on the kref from remaining in -+ * memory. Only use the return value if you want to see if the kref is now -+ * gone, not present. -+ */ -+int kref_sub(struct kref *kref, unsigned int count, -+ void (*release)(struct kref *kref)) -+{ -+ WARN_ON(release == NULL); -+ WARN_ON(release == (void (*)(struct kref *))kfree); -+ -+ if (atomic_sub_and_test((int) count, &kref->refcount)) { -+ release(kref); -+ return 1; -+ } -+ return 0; -+} -+ - EXPORT_SYMBOL(kref_init); - EXPORT_SYMBOL(kref_get); - EXPORT_SYMBOL(kref_put); -+EXPORT_SYMBOL(kref_sub); diff --git a/packages/linux/patches/linux-2.6.38-rc5-110-drm_nouveau_upstream-20110222.patch b/packages/linux/patches/linux-2.6.38-rc5-110-drm_nouveau_upstream-20110222.patch new file mode 100644 index 0000000000..364b99654c --- /dev/null +++ b/packages/linux/patches/linux-2.6.38-rc5-110-drm_nouveau_upstream-20110222.patch @@ -0,0 +1,4649 @@ +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bios.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bios.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.c 2011-02-20 23:32:11.000000000 +0100 +@@ -282,7 +282,7 @@ + { + #if 0 + sync(); +- msleep(2); ++ mdelay(2); + #endif + } + +@@ -1904,7 +1904,7 @@ + BIOSLOG(bios, "0x%04X: " + "Condition not met, sleeping for 20ms\n", + offset); +- msleep(20); ++ mdelay(20); + } + } + +@@ -1938,7 +1938,7 @@ + BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X milliseconds\n", + offset, time); + +- msleep(time); ++ mdelay(time); + + return 3; + } +@@ -2962,7 +2962,7 @@ + if (time < 1000) + udelay(time); + else +- msleep((time + 900) / 1000); ++ mdelay((time + 900) / 1000); + + return 3; + } +@@ -3856,7 +3856,7 @@ + + if (script == LVDS_PANEL_OFF) { + /* off-on delay in ms */ +- msleep(ROM16(bios->data[bios->fp.xlated_entry + 7])); ++ mdelay(ROM16(bios->data[bios->fp.xlated_entry + 7])); + } + #ifdef __powerpc__ + /* Powerbook specific quirks */ +@@ -5950,6 +5950,11 @@ + } + } + ++static const u8 hpd_gpio[16] = { ++ 0xff, 0x07, 0x08, 0xff, 0xff, 0x51, 0x52, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x5f, 0x60, ++}; ++ + static void + parse_dcb_connector_table(struct nvbios *bios) + { +@@ -5986,23 +5991,9 @@ + + cte->type = (cte->entry & 0x000000ff) >> 0; + cte->index2 = (cte->entry & 0x00000f00) >> 8; +- switch (cte->entry & 0x00033000) { +- case 0x00001000: +- cte->gpio_tag = 0x07; +- break; +- case 0x00002000: +- cte->gpio_tag = 0x08; +- break; +- case 0x00010000: +- cte->gpio_tag = 0x51; +- break; +- case 0x00020000: +- cte->gpio_tag = 0x52; +- break; +- default: +- cte->gpio_tag = 0xff; +- break; +- } ++ ++ cte->gpio_tag = ffs((cte->entry & 0x07033000) >> 12); ++ cte->gpio_tag = hpd_gpio[cte->gpio_tag]; + + if (cte->type == 0xff) + continue; +@@ -6228,7 +6219,7 @@ + entry->tvconf.has_component_output = false; + break; + case OUTPUT_LVDS: +- if ((conn & 0x00003f00) != 0x10) ++ if ((conn & 0x00003f00) >> 8 != 0x10) + entry->lvdsconf.use_straps_for_mode = true; + entry->lvdsconf.use_power_scripts = true; + break; +@@ -6702,11 +6693,11 @@ + struct nvbios *bios = &dev_priv->vbios; + struct init_exec iexec = { true, false }; + +- mutex_lock(&bios->lock); ++ spin_lock_bh(&bios->lock); + bios->display.output = dcbent; + parse_init_table(bios, table, &iexec); + bios->display.output = NULL; +- mutex_unlock(&bios->lock); ++ spin_unlock_bh(&bios->lock); + } + + static bool NVInitVBIOS(struct drm_device *dev) +@@ -6715,7 +6706,7 @@ + struct nvbios *bios = &dev_priv->vbios; + + memset(bios, 0, sizeof(struct nvbios)); +- mutex_init(&bios->lock); ++ spin_lock_init(&bios->lock); + bios->dev = dev; + + if (!NVShadowVBIOS(dev, bios->data)) +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bios.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.h +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bios.h 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.h 2011-02-20 23:32:11.000000000 +0100 +@@ -251,7 +251,7 @@ + uint8_t digital_min_front_porch; + bool fp_no_ddc; + +- struct mutex lock; ++ spinlock_t lock; + + uint8_t data[NV_PROM_SIZE]; + unsigned int length; +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_bo.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_bo.c 2011-02-20 23:32:11.000000000 +0100 +@@ -54,8 +54,8 @@ + } + + static void +-nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size, +- int *page_shift) ++nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags, ++ int *align, int *size, int *page_shift) + { + struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); + +@@ -80,7 +80,7 @@ + } + } else { + if (likely(dev_priv->chan_vm)) { +- if (*size > 256 * 1024) ++ 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; +@@ -98,8 +98,7 @@ + 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, bool no_vm, bool mappable, +- struct nouveau_bo **pnvbo) ++ uint32_t tile_flags, struct nouveau_bo **pnvbo) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_bo *nvbo; +@@ -110,16 +109,14 @@ + return -ENOMEM; + INIT_LIST_HEAD(&nvbo->head); + INIT_LIST_HEAD(&nvbo->entry); +- nvbo->mappable = mappable; +- nvbo->no_vm = no_vm; + nvbo->tile_mode = tile_mode; + nvbo->tile_flags = tile_flags; + nvbo->bo.bdev = &dev_priv->ttm.bdev; + +- nouveau_bo_fixup_align(nvbo, &align, &size, &page_shift); ++ nouveau_bo_fixup_align(nvbo, flags, &align, &size, &page_shift); + align >>= PAGE_SHIFT; + +- if (!nvbo->no_vm && dev_priv->chan_vm) { ++ if (dev_priv->chan_vm) { + ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift, + NV_MEM_ACCESS_RW, &nvbo->vma); + if (ret) { +@@ -128,6 +125,7 @@ + } + } + ++ nvbo->bo.mem.num_pages = size >> PAGE_SHIFT; + nouveau_bo_placement_set(nvbo, flags, 0); + + nvbo->channel = chan; +@@ -140,11 +138,8 @@ + } + nvbo->channel = NULL; + +- if (nvbo->vma.node) { +- if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) +- nvbo->bo.offset = nvbo->vma.offset; +- } +- ++ if (nvbo->vma.node) ++ nvbo->bo.offset = nvbo->vma.offset; + *pnvbo = nvbo; + return 0; + } +@@ -166,17 +161,17 @@ + set_placement_range(struct nouveau_bo *nvbo, uint32_t type) + { + struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); ++ int vram_pages = dev_priv->vram_size >> PAGE_SHIFT; + + if (dev_priv->card_type == NV_10 && +- nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM)) { ++ nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) && ++ nvbo->bo.mem.num_pages < vram_pages / 2) { + /* + * Make sure that the color and depth buffers are handled + * by independent memory controller units. Up to a 9x + * speed up when alpha-blending and depth-test are enabled + * at the same time. + */ +- int vram_pages = dev_priv->vram_size >> PAGE_SHIFT; +- + if (nvbo->tile_flags & NOUVEAU_GEM_TILE_ZETA) { + nvbo->placement.fpfn = vram_pages / 2; + nvbo->placement.lpfn = ~0; +@@ -314,11 +309,8 @@ + if (ret) + return ret; + +- if (nvbo->vma.node) { +- if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) +- nvbo->bo.offset = nvbo->vma.offset; +- } +- ++ if (nvbo->vma.node) ++ nvbo->bo.offset = nvbo->vma.offset; + return 0; + } + +@@ -381,7 +373,8 @@ + case NOUVEAU_GART_AGP: + return ttm_agp_backend_init(bdev, dev->agp->bridge); + #endif +- case NOUVEAU_GART_SGDMA: ++ case NOUVEAU_GART_PDMA: ++ case NOUVEAU_GART_HW: + return nouveau_sgdma_init_ttm(dev); + default: + NV_ERROR(dev, "Unknown GART type %d\n", +@@ -427,7 +420,10 @@ + man->default_caching = TTM_PL_FLAG_WC; + break; + case TTM_PL_TT: +- man->func = &ttm_bo_manager_func; ++ if (dev_priv->card_type >= NV_50) ++ man->func = &nouveau_gart_manager; ++ else ++ man->func = &ttm_bo_manager_func; + switch (dev_priv->gart_info.type) { + case NOUVEAU_GART_AGP: + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; +@@ -435,7 +431,8 @@ + TTM_PL_FLAG_WC; + man->default_caching = TTM_PL_FLAG_WC; + break; +- case NOUVEAU_GART_SGDMA: ++ case NOUVEAU_GART_PDMA: ++ case NOUVEAU_GART_HW: + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | + TTM_MEMTYPE_FLAG_CMA; + man->available_caching = TTM_PL_MASK_CACHING; +@@ -497,45 +494,22 @@ + return ret; + } + +-static inline uint32_t +-nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo, +- struct nouveau_channel *chan, struct ttm_mem_reg *mem) +-{ +- struct nouveau_bo *nvbo = nouveau_bo(bo); +- +- if (nvbo->no_vm) { +- if (mem->mem_type == TTM_PL_TT) +- return NvDmaGART; +- return NvDmaVRAM; +- } +- +- if (mem->mem_type == TTM_PL_TT) +- return chan->gart_handle; +- return chan->vram_handle; +-} +- + static int + nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, + struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) + { +- struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); ++ struct nouveau_mem *old_node = old_mem->mm_node; ++ struct nouveau_mem *new_node = new_mem->mm_node; + struct nouveau_bo *nvbo = nouveau_bo(bo); +- u64 src_offset = old_mem->start << PAGE_SHIFT; +- u64 dst_offset = new_mem->start << PAGE_SHIFT; + u32 page_count = new_mem->num_pages; ++ u64 src_offset, dst_offset; + int ret; + +- if (!nvbo->no_vm) { +- if (old_mem->mem_type == TTM_PL_VRAM) +- src_offset = nvbo->vma.offset; +- else +- src_offset += dev_priv->gart_info.aper_base; +- +- if (new_mem->mem_type == TTM_PL_VRAM) +- dst_offset = nvbo->vma.offset; +- else +- dst_offset += dev_priv->gart_info.aper_base; +- } ++ 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) { +@@ -570,33 +544,18 @@ + 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 drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); ++ 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); + u64 length = (new_mem->num_pages << PAGE_SHIFT); + u64 src_offset, dst_offset; + int ret; + +- src_offset = old_mem->start << PAGE_SHIFT; +- dst_offset = new_mem->start << PAGE_SHIFT; +- if (!nvbo->no_vm) { +- if (old_mem->mem_type == TTM_PL_VRAM) +- src_offset = nvbo->vma.offset; +- else +- src_offset += dev_priv->gart_info.aper_base; +- +- if (new_mem->mem_type == TTM_PL_VRAM) +- dst_offset = nvbo->vma.offset; +- else +- dst_offset += dev_priv->gart_info.aper_base; +- } +- +- ret = RING_SPACE(chan, 3); +- if (ret) +- return ret; +- +- BEGIN_RING(chan, NvSubM2MF, 0x0184, 2); +- OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, old_mem)); +- OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, new_mem)); ++ 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; +@@ -677,6 +636,15 @@ + return 0; + } + ++static inline uint32_t ++nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo, ++ struct nouveau_channel *chan, struct ttm_mem_reg *mem) ++{ ++ if (mem->mem_type == TTM_PL_TT) ++ return chan->gart_handle; ++ return chan->vram_handle; ++} ++ + static int + nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, + struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) +@@ -730,15 +698,43 @@ + { + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct nouveau_bo *nvbo = nouveau_bo(bo); ++ struct ttm_mem_reg *old_mem = &bo->mem; + struct nouveau_channel *chan; + int ret; + + chan = nvbo->channel; +- if (!chan || nvbo->no_vm) { ++ if (!chan) { + chan = dev_priv->channel; + 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 ++ */ ++ 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); ++ } ++ } ++ + if (dev_priv->card_type < NV_50) + ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem); + else +@@ -752,6 +748,7 @@ + no_wait_gpu, new_mem); + } + ++out: + if (chan == dev_priv->channel) + mutex_unlock(&chan->mutex); + return ret; +@@ -762,6 +759,7 @@ + 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; +@@ -781,11 +779,27 @@ + 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; + +- ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); ++ ret = ttm_bo_move_ttm(bo, true, no_wait_reserve, no_wait_gpu, new_mem); + out: + ttm_bo_mem_put(bo, &tmp_mem); + return ret; +@@ -811,11 +825,11 @@ + if (ret) + return ret; + +- ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, &tmp_mem); ++ ret = ttm_bo_move_ttm(bo, true, no_wait_reserve, no_wait_gpu, &tmp_mem); + if (ret) + goto out; + +- ret = nouveau_bo_move_m2mf(bo, evict, intr, no_wait_reserve, no_wait_gpu, new_mem); ++ ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, new_mem); + if (ret) + goto out; + +@@ -824,6 +838,36 @@ + return ret; + } + ++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; ++ ++ 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) { ++ 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; ++ } ++} ++ + static int + nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, + struct nouveau_tile_reg **new_tile) +@@ -831,19 +875,13 @@ + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct drm_device *dev = dev_priv->dev; + struct nouveau_bo *nvbo = nouveau_bo(bo); +- uint64_t offset; ++ u64 offset = new_mem->start << PAGE_SHIFT; + +- if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) { +- /* Nothing to do. */ +- *new_tile = NULL; ++ *new_tile = NULL; ++ if (new_mem->mem_type != TTM_PL_VRAM) + return 0; +- } + +- offset = new_mem->start << PAGE_SHIFT; +- +- if (dev_priv->chan_vm) { +- nouveau_vm_map(&nvbo->vma, new_mem->mm_node); +- } else if (dev_priv->card_type >= NV_10) { ++ if (dev_priv->card_type >= NV_10) { + *new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size, + nvbo->tile_mode, + nvbo->tile_flags); +@@ -860,11 +898,8 @@ + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct drm_device *dev = dev_priv->dev; + +- if (dev_priv->card_type >= NV_10 && +- dev_priv->card_type < NV_50) { +- nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj); +- *old_tile = new_tile; +- } ++ nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj); ++ *old_tile = new_tile; + } + + static int +@@ -878,9 +913,11 @@ + struct nouveau_tile_reg *new_tile = NULL; + int ret = 0; + +- ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile); +- if (ret) +- return ret; ++ if (dev_priv->card_type < NV_50) { ++ ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile); ++ if (ret) ++ return ret; ++ } + + /* Fake bo copy. */ + if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { +@@ -911,10 +948,12 @@ + ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); + + out: +- if (ret) +- nouveau_bo_vm_cleanup(bo, NULL, &new_tile); +- else +- nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile); ++ if (dev_priv->card_type < NV_50) { ++ if (ret) ++ nouveau_bo_vm_cleanup(bo, NULL, &new_tile); ++ else ++ nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile); ++ } + + return ret; + } +@@ -955,7 +994,7 @@ + break; + case TTM_PL_VRAM: + { +- struct nouveau_vram *vram = mem->mm_node; ++ struct nouveau_mem *node = mem->mm_node; + u8 page_shift; + + if (!dev_priv->bar1_vm) { +@@ -966,23 +1005,23 @@ + } + + if (dev_priv->card_type == NV_C0) +- page_shift = vram->page_shift; ++ page_shift = node->page_shift; + else + page_shift = 12; + + ret = nouveau_vm_get(dev_priv->bar1_vm, mem->bus.size, + page_shift, NV_MEM_ACCESS_RW, +- &vram->bar_vma); ++ &node->bar_vma); + if (ret) + return ret; + +- nouveau_vm_map(&vram->bar_vma, vram); ++ nouveau_vm_map(&node->bar_vma, node); + if (ret) { +- nouveau_vm_put(&vram->bar_vma); ++ nouveau_vm_put(&node->bar_vma); + return ret; + } + +- mem->bus.offset = vram->bar_vma.offset; ++ mem->bus.offset = node->bar_vma.offset; + if (dev_priv->card_type == NV_50) /*XXX*/ + mem->bus.offset -= 0x0020000000ULL; + mem->bus.base = pci_resource_start(dev->pdev, 1); +@@ -999,16 +1038,16 @@ + nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) + { + struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); +- struct nouveau_vram *vram = mem->mm_node; ++ struct nouveau_mem *node = mem->mm_node; + + if (!dev_priv->bar1_vm || mem->mem_type != TTM_PL_VRAM) + return; + +- if (!vram->bar_vma.node) ++ if (!node->bar_vma.node) + return; + +- nouveau_vm_unmap(&vram->bar_vma); +- nouveau_vm_put(&vram->bar_vma); ++ nouveau_vm_unmap(&node->bar_vma); ++ nouveau_vm_put(&node->bar_vma); + } + + static int +@@ -1058,6 +1097,7 @@ + .invalidate_caches = nouveau_bo_invalidate_caches, + .init_mem_type = nouveau_bo_init_mem_type, + .evict_flags = nouveau_bo_evict_flags, ++ .move_notify = nouveau_bo_move_ntfy, + .move = nouveau_bo_move, + .verify_access = nouveau_bo_verify_access, + .sync_obj_signaled = __nouveau_fence_signalled, +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_channel.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_channel.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_channel.c 2011-02-20 23:32:11.000000000 +0100 +@@ -35,7 +35,7 @@ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_bo *pb = chan->pushbuf_bo; + struct nouveau_gpuobj *pushbuf = NULL; +- int ret; ++ int ret = 0; + + if (dev_priv->card_type >= NV_50) { + if (dev_priv->card_type < NV_C0) { +@@ -90,8 +90,7 @@ + else + location = TTM_PL_FLAG_TT; + +- ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, false, +- true, &pushbuf); ++ 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; +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_connector.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.c 2011-02-20 23:32:11.000000000 +0100 +@@ -507,6 +507,7 @@ + int high_w = 0, high_h = 0, high_v = 0; + + list_for_each_entry(mode, &nv_connector->base.probed_modes, head) { ++ mode->vrefresh = drm_mode_vrefresh(mode); + if (helper->mode_valid(connector, mode) != MODE_OK || + (mode->flags & DRM_MODE_FLAG_INTERLACE)) + continue; +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_display.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_display.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_display.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_display.c 2011-02-20 23:32:11.000000000 +0100 +@@ -32,6 +32,7 @@ + #include "nouveau_hw.h" + #include "nouveau_crtc.h" + #include "nouveau_dma.h" ++#include "nv50_display.h" + + static void + nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) +@@ -61,18 +62,59 @@ + }; + + int +-nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb, +- struct drm_mode_fb_cmd *mode_cmd, struct nouveau_bo *nvbo) ++nouveau_framebuffer_init(struct drm_device *dev, ++ struct nouveau_framebuffer *nv_fb, ++ struct drm_mode_fb_cmd *mode_cmd, ++ struct nouveau_bo *nvbo) + { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct drm_framebuffer *fb = &nv_fb->base; + int ret; + +- ret = drm_framebuffer_init(dev, &nouveau_fb->base, &nouveau_framebuffer_funcs); ++ ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs); + if (ret) { + return ret; + } + +- drm_helper_mode_fill_fb_struct(&nouveau_fb->base, mode_cmd); +- nouveau_fb->nvbo = nvbo; ++ drm_helper_mode_fill_fb_struct(fb, mode_cmd); ++ nv_fb->nvbo = nvbo; ++ ++ if (dev_priv->card_type >= NV_50) { ++ u32 tile_flags = nouveau_bo_tile_layout(nvbo); ++ if (tile_flags == 0x7a00 || ++ tile_flags == 0xfe00) ++ nv_fb->r_dma = NvEvoFB32; ++ else ++ if (tile_flags == 0x7000) ++ nv_fb->r_dma = NvEvoFB16; ++ else ++ nv_fb->r_dma = NvEvoVRAM_LP; ++ ++ switch (fb->depth) { ++ case 8: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_8; break; ++ case 15: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_15; break; ++ case 16: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_16; break; ++ case 24: ++ case 32: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_24; break; ++ case 30: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_30; break; ++ default: ++ NV_ERROR(dev, "unknown depth %d\n", fb->depth); ++ return -EINVAL; ++ } ++ ++ if (dev_priv->chipset == 0x50) ++ nv_fb->r_format |= (tile_flags << 8); ++ ++ if (!tile_flags) ++ nv_fb->r_pitch = 0x00100000 | fb->pitch; ++ else { ++ u32 mode = nvbo->tile_mode; ++ if (dev_priv->card_type >= NV_C0) ++ mode >>= 4; ++ nv_fb->r_pitch = ((fb->pitch / 4) << 4) | mode; ++ } ++ } ++ + return 0; + } + +@@ -182,6 +224,7 @@ + struct nouveau_page_flip_state *s, + struct nouveau_fence **pfence) + { ++ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct drm_device *dev = chan->dev; + unsigned long flags; + int ret; +@@ -201,9 +244,12 @@ + if (ret) + goto fail; + +- BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); +- OUT_RING(chan, 0); +- FIRE_RING(chan); ++ if (dev_priv->card_type < NV_C0) ++ BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); ++ else ++ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0500, 1); ++ OUT_RING (chan, 0); ++ FIRE_RING (chan); + + ret = nouveau_fence_new(chan, pfence, true); + if (ret) +@@ -244,7 +290,7 @@ + + /* Initialize a page flip struct */ + *s = (struct nouveau_page_flip_state) +- { { }, s->event, nouveau_crtc(crtc)->index, ++ { { }, event, nouveau_crtc(crtc)->index, + fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y, + new_bo->bo.offset }; + +@@ -255,6 +301,14 @@ + mutex_lock(&chan->mutex); + + /* Emit a page flip */ ++ if (dev_priv->card_type >= NV_50) { ++ ret = nv50_display_flip_next(crtc, fb, chan); ++ if (ret) { ++ nouveau_channel_put(&chan); ++ goto fail_unreserve; ++ } ++ } ++ + ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); + nouveau_channel_put(&chan); + if (ret) +@@ -305,7 +359,8 @@ + } + + list_del(&s->head); +- *ps = *s; ++ if (ps) ++ *ps = *s; + kfree(s); + + spin_unlock_irqrestore(&dev->event_lock, flags); +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dma.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dma.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.c 2011-02-20 23:32:11.000000000 +0100 +@@ -96,13 +96,15 @@ + OUT_RING(chan, 0); + + /* Initialise NV_MEMORY_TO_MEMORY_FORMAT */ +- ret = RING_SPACE(chan, 4); ++ ret = RING_SPACE(chan, 6); + if (ret) + return ret; + BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1); +- OUT_RING(chan, NvM2MF); +- BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); +- OUT_RING(chan, NvNotify0); ++ OUT_RING (chan, NvM2MF); ++ BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3); ++ OUT_RING (chan, NvNotify0); ++ OUT_RING (chan, chan->vram_handle); ++ OUT_RING (chan, chan->gart_handle); + + /* Sit back and pray the channel works.. */ + FIRE_RING(chan); +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dma.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.h +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dma.h 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.h 2011-02-20 23:32:11.000000000 +0100 +@@ -61,8 +61,6 @@ + NvM2MF = 0x80000001, + NvDmaFB = 0x80000002, + NvDmaTT = 0x80000003, +- NvDmaVRAM = 0x80000004, +- NvDmaGART = 0x80000005, + NvNotify0 = 0x80000006, + Nv2D = 0x80000007, + NvCtxSurf2D = 0x80000008, +@@ -73,12 +71,15 @@ + NvImageBlit = 0x8000000d, + NvSw = 0x8000000e, + NvSema = 0x8000000f, ++ NvEvoSema0 = 0x80000010, ++ NvEvoSema1 = 0x80000011, + + /* G80+ display objects */ + NvEvoVRAM = 0x01000000, + NvEvoFB16 = 0x01000001, + NvEvoFB32 = 0x01000002, +- NvEvoVRAM_LP = 0x01000003 ++ NvEvoVRAM_LP = 0x01000003, ++ NvEvoSync = 0xcafe0000 + }; + + #define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039 +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dp.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_dp.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dp.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_dp.c 2011-02-20 23:32:11.000000000 +0100 +@@ -175,7 +175,6 @@ + { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; +- struct bit_displayport_encoder_table_entry *dpse; + struct bit_displayport_encoder_table *dpe; + int ret, i, dpe_headerlen, vs = 0, pre = 0; + uint8_t request[2]; +@@ -183,7 +182,6 @@ + dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); + if (!dpe) + return false; +- dpse = (void *)((char *)dpe + dpe_headerlen); + + ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2); + if (ret) +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.h +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_drv.h 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.h 2011-02-20 23:32:11.000000000 +0100 +@@ -57,7 +57,7 @@ + #include "nouveau_util.h" + + struct nouveau_grctx; +-struct nouveau_vram; ++struct nouveau_mem; + #include "nouveau_vm.h" + + #define MAX_NUM_DCB_ENTRIES 16 +@@ -65,13 +65,16 @@ + #define NOUVEAU_MAX_CHANNEL_NR 128 + #define NOUVEAU_MAX_TILE_NR 15 + +-struct nouveau_vram { ++struct nouveau_mem { + struct drm_device *dev; + + struct nouveau_vma bar_vma; ++ struct nouveau_vma tmp_vma; + u8 page_shift; + ++ struct drm_mm_node *tag; + struct list_head regions; ++ dma_addr_t *pages; + u32 memtype; + u64 offset; + u64 size; +@@ -90,6 +93,7 @@ + struct nouveau_bo { + struct ttm_buffer_object bo; + struct ttm_placement placement; ++ u32 valid_domains; + u32 placements[3]; + u32 busy_placements[3]; + struct ttm_bo_kmap_obj kmap; +@@ -104,8 +108,6 @@ + struct nouveau_channel *channel; + + struct nouveau_vma vma; +- bool mappable; +- bool no_vm; + + uint32_t tile_mode; + uint32_t tile_flags; +@@ -387,6 +389,7 @@ + }; + + struct nouveau_display_engine { ++ void *priv; + int (*early_init)(struct drm_device *); + void (*late_takedown)(struct drm_device *); + int (*create)(struct drm_device *); +@@ -509,8 +512,8 @@ + struct nouveau_vram_engine { + int (*init)(struct drm_device *); + int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, +- u32 type, struct nouveau_vram **); +- void (*put)(struct drm_device *, struct nouveau_vram **); ++ u32 type, struct nouveau_mem **); ++ void (*put)(struct drm_device *, struct nouveau_mem **); + + bool (*flags_valid)(struct drm_device *, u32 tile_flags); + }; +@@ -652,8 +655,6 @@ + /* interrupt handling */ + void (*irq_handler[32])(struct drm_device *); + bool msi_enabled; +- struct workqueue_struct *wq; +- struct work_struct irq_work; + + struct list_head vbl_waiting; + +@@ -691,15 +692,22 @@ + struct { + enum { + NOUVEAU_GART_NONE = 0, +- NOUVEAU_GART_AGP, +- NOUVEAU_GART_SGDMA ++ NOUVEAU_GART_AGP, /* AGP */ ++ NOUVEAU_GART_PDMA, /* paged dma object */ ++ NOUVEAU_GART_HW /* on-chip gart/vm */ + } type; + uint64_t aper_base; + uint64_t aper_size; + uint64_t aper_free; + ++ struct ttm_backend_func *func; ++ ++ struct { ++ struct page *page; ++ dma_addr_t addr; ++ } dummy; ++ + struct nouveau_gpuobj *sg_ctxdma; +- struct nouveau_vma vma; + } gart_info; + + /* nv10-nv40 tiling regions */ +@@ -740,14 +748,6 @@ + + struct backlight_device *backlight; + +- struct nouveau_channel *evo; +- u32 evo_alloc; +- struct { +- struct dcb_entry *dcb; +- u16 script; +- u32 pclk; +- } evo_irq; +- + struct { + struct dentry *channel_root; + } debugfs; +@@ -847,6 +847,7 @@ + struct nouveau_tile_reg *tile, + struct nouveau_fence *fence); + extern const struct ttm_mem_type_manager_func nouveau_vram_manager; ++extern const struct ttm_mem_type_manager_func nouveau_gart_manager; + + /* nouveau_notifier.c */ + extern int nouveau_notifier_init_channel(struct nouveau_channel *); +@@ -1294,7 +1295,7 @@ + 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, +- bool no_vm, bool mappable, struct nouveau_bo **); ++ 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 *); +@@ -1355,9 +1356,9 @@ + + /* nouveau_gem.c */ + extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, +- int size, int align, uint32_t flags, ++ int size, int align, uint32_t domain, + uint32_t tile_mode, uint32_t tile_flags, +- bool no_vm, bool mappable, struct nouveau_bo **); ++ 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_ioctl_new(struct drm_device *, void *, +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2011-02-20 23:32:11.000000000 +0100 +@@ -296,8 +296,8 @@ + size = mode_cmd.pitch * mode_cmd.height; + size = roundup(size, PAGE_SIZE); + +- ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, TTM_PL_FLAG_VRAM, +- 0, 0x0000, false, true, &nvbo); ++ ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, ++ NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo); + if (ret) { + NV_ERROR(dev, "failed to allocate framebuffer\n"); + goto out; +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fb.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_fb.h +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fb.h 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_fb.h 2011-02-20 23:32:11.000000000 +0100 +@@ -30,6 +30,9 @@ + struct nouveau_framebuffer { + struct drm_framebuffer base; + struct nouveau_bo *nvbo; ++ u32 r_dma; ++ u32 r_format; ++ u32 r_pitch; + }; + + static inline struct nouveau_framebuffer * +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_fence.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fence.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_fence.c 2011-02-20 23:32:11.000000000 +0100 +@@ -32,8 +32,7 @@ + #include "nouveau_dma.h" + + #define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10) +-#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17 && \ +- nouveau_private(dev)->card_type < NV_C0) ++#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17) + + struct nouveau_fence { + struct nouveau_channel *channel; +@@ -259,11 +258,12 @@ + } + + static struct nouveau_semaphore * +-alloc_semaphore(struct drm_device *dev) ++semaphore_alloc(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_semaphore *sema; +- int ret; ++ int size = (dev_priv->chipset < 0x84) ? 4 : 16; ++ int ret, i; + + if (!USE_SEMA(dev)) + return NULL; +@@ -277,9 +277,9 @@ + goto fail; + + spin_lock(&dev_priv->fence.lock); +- sema->mem = drm_mm_search_free(&dev_priv->fence.heap, 4, 0, 0); ++ sema->mem = drm_mm_search_free(&dev_priv->fence.heap, size, 0, 0); + if (sema->mem) +- sema->mem = drm_mm_get_block_atomic(sema->mem, 4, 0); ++ sema->mem = drm_mm_get_block_atomic(sema->mem, size, 0); + spin_unlock(&dev_priv->fence.lock); + + if (!sema->mem) +@@ -287,7 +287,8 @@ + + kref_init(&sema->ref); + sema->dev = dev; +- nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 0); ++ for (i = sema->mem->start; i < sema->mem->start + size; i += 4) ++ nouveau_bo_wr32(dev_priv->fence.bo, i / 4, 0); + + return sema; + fail: +@@ -296,7 +297,7 @@ + } + + static void +-free_semaphore(struct kref *ref) ++semaphore_free(struct kref *ref) + { + struct nouveau_semaphore *sema = + container_of(ref, struct nouveau_semaphore, ref); +@@ -318,61 +319,107 @@ + if (unlikely(!signalled)) + nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 1); + +- kref_put(&sema->ref, free_semaphore); ++ kref_put(&sema->ref, semaphore_free); + } + + static int +-emit_semaphore(struct nouveau_channel *chan, int method, +- struct nouveau_semaphore *sema) ++semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) + { +- struct drm_nouveau_private *dev_priv = sema->dev->dev_private; +- struct nouveau_fence *fence; +- bool smart = (dev_priv->card_type >= NV_50); ++ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; ++ struct nouveau_fence *fence = NULL; + int ret; + +- ret = RING_SPACE(chan, smart ? 8 : 4); ++ if (dev_priv->chipset < 0x84) { ++ ret = RING_SPACE(chan, 3); ++ if (ret) ++ return ret; ++ ++ BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 2); ++ OUT_RING (chan, sema->mem->start); ++ 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, 5); ++ if (ret) ++ return ret; ++ ++ BEGIN_RING(chan, NvSubSw, 0x0010, 4); ++ OUT_RING (chan, upper_32_bits(offset)); ++ OUT_RING (chan, lower_32_bits(offset)); ++ 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; ++ ++ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); ++ OUT_RING (chan, upper_32_bits(offset)); ++ OUT_RING (chan, lower_32_bits(offset)); ++ OUT_RING (chan, 1); ++ OUT_RING (chan, 0x1001); /* ACQUIRE_EQ */ ++ } ++ ++ /* Delay semaphore destruction until its work is done */ ++ ret = nouveau_fence_new(chan, &fence, true); + if (ret) + return ret; + +- if (smart) { +- BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); +- OUT_RING(chan, NvSema); +- } +- BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1); +- OUT_RING(chan, sema->mem->start); ++ kref_get(&sema->ref); ++ nouveau_fence_work(fence, semaphore_work, sema); ++ nouveau_fence_unref(&fence); ++ return 0; ++} + +- if (smart && method == NV_SW_SEMAPHORE_ACQUIRE) { +- /* +- * NV50 tries to be too smart and context-switch +- * between semaphores instead of doing a "first come, +- * first served" strategy like previous cards +- * do. +- * +- * That's bad because the ACQUIRE latency can get as +- * large as the PFIFO context time slice in the +- * typical DRI2 case where you have several +- * outstanding semaphores at the same moment. +- * +- * If we're going to ACQUIRE, force the card to +- * context switch before, just in case the matching +- * RELEASE is already scheduled to be executed in +- * another channel. +- */ +- BEGIN_RING(chan, NvSubSw, NV_SW_YIELD, 1); +- OUT_RING(chan, 0); +- } +- +- BEGIN_RING(chan, NvSubSw, method, 1); +- OUT_RING(chan, 1); +- +- if (smart && method == NV_SW_SEMAPHORE_RELEASE) { +- /* +- * Force the card to context switch, there may be +- * another channel waiting for the semaphore we just +- * released. +- */ +- BEGIN_RING(chan, NvSubSw, NV_SW_YIELD, 1); +- OUT_RING(chan, 0); ++static int ++semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) ++{ ++ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; ++ struct nouveau_fence *fence = NULL; ++ int ret; ++ ++ if (dev_priv->chipset < 0x84) { ++ ret = RING_SPACE(chan, 4); ++ if (ret) ++ return ret; ++ ++ BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1); ++ OUT_RING (chan, sema->mem->start); ++ 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, 5); ++ if (ret) ++ return ret; ++ ++ BEGIN_RING(chan, NvSubSw, 0x0010, 4); ++ OUT_RING (chan, upper_32_bits(offset)); ++ OUT_RING (chan, lower_32_bits(offset)); ++ 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; ++ ++ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); ++ OUT_RING (chan, upper_32_bits(offset)); ++ OUT_RING (chan, lower_32_bits(offset)); ++ OUT_RING (chan, 1); ++ OUT_RING (chan, 0x1002); /* RELEASE */ + } + + /* Delay semaphore destruction until its work is done */ +@@ -383,7 +430,6 @@ + kref_get(&sema->ref); + nouveau_fence_work(fence, semaphore_work, sema); + nouveau_fence_unref(&fence); +- + return 0; + } + +@@ -400,7 +446,7 @@ + nouveau_fence_signalled(fence))) + goto out; + +- sema = alloc_semaphore(dev); ++ sema = semaphore_alloc(dev); + if (!sema) { + /* Early card or broken userspace, fall back to + * software sync. */ +@@ -418,17 +464,17 @@ + } + + /* Make wchan wait until it gets signalled */ +- ret = emit_semaphore(wchan, NV_SW_SEMAPHORE_ACQUIRE, sema); ++ ret = semaphore_acquire(wchan, sema); + if (ret) + goto out_unlock; + + /* Signal the semaphore from chan */ +- ret = emit_semaphore(chan, NV_SW_SEMAPHORE_RELEASE, sema); ++ ret = semaphore_release(chan, sema); + + out_unlock: + mutex_unlock(&chan->mutex); + out_unref: +- kref_put(&sema->ref, free_semaphore); ++ kref_put(&sema->ref, semaphore_free); + out: + if (chan) + nouveau_channel_put_unlocked(&chan); +@@ -449,22 +495,23 @@ + struct nouveau_gpuobj *obj = NULL; + int ret; + ++ if (dev_priv->card_type >= NV_C0) ++ goto out_initialised; ++ + /* Create an NV_SW object for various sync purposes */ + ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW); + if (ret) + return ret; + + /* we leave subchannel empty for nvc0 */ +- if (dev_priv->card_type < NV_C0) { +- ret = RING_SPACE(chan, 2); +- if (ret) +- return ret; +- BEGIN_RING(chan, NvSubSw, 0, 1); +- OUT_RING(chan, NvSw); +- } ++ ret = RING_SPACE(chan, 2); ++ if (ret) ++ return ret; ++ BEGIN_RING(chan, NvSubSw, 0, 1); ++ OUT_RING(chan, NvSw); + + /* Create a DMA object for the shared cross-channel sync area. */ +- if (USE_SEMA(dev)) { ++ if (USE_SEMA(dev) && dev_priv->chipset < 0x84) { + struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem; + + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, +@@ -484,14 +531,20 @@ + return ret; + BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); + OUT_RING(chan, NvSema); ++ } else { ++ ret = RING_SPACE(chan, 2); ++ if (ret) ++ return ret; ++ BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); ++ OUT_RING (chan, chan->vram_handle); /* whole VM */ + } + + FIRE_RING(chan); + ++out_initialised: + INIT_LIST_HEAD(&chan->fence.pending); + spin_lock_init(&chan->fence.lock); + atomic_set(&chan->fence.last_sequence_irq, 0); +- + return 0; + } + +@@ -519,12 +572,13 @@ + nouveau_fence_init(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ int size = (dev_priv->chipset < 0x84) ? 4096 : 16384; + int ret; + + /* Create a shared VRAM heap for cross-channel sync. */ + if (USE_SEMA(dev)) { +- ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, +- 0, 0, false, true, &dev_priv->fence.bo); ++ ret = nouveau_bo_new(dev, NULL, size, 0, TTM_PL_FLAG_VRAM, ++ 0, 0, &dev_priv->fence.bo); + if (ret) + return ret; + +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_gem.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_gem.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_gem.c 2011-02-20 23:32:11.000000000 +0100 +@@ -61,19 +61,36 @@ + + int + nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan, +- int size, int align, uint32_t flags, uint32_t tile_mode, +- uint32_t tile_flags, bool no_vm, bool mappable, +- struct nouveau_bo **pnvbo) ++ 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; ++ u32 flags = 0; + int ret; + ++ if (domain & NOUVEAU_GEM_DOMAIN_VRAM) ++ flags |= TTM_PL_FLAG_VRAM; ++ if (domain & NOUVEAU_GEM_DOMAIN_GART) ++ flags |= TTM_PL_FLAG_TT; ++ if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU) ++ flags |= TTM_PL_FLAG_SYSTEM; ++ + ret = nouveau_bo_new(dev, chan, size, align, flags, tile_mode, +- tile_flags, no_vm, mappable, pnvbo); ++ tile_flags, pnvbo); + if (ret) + return ret; + nvbo = *pnvbo; + ++ /* we restrict allowed domains on nv50+ to only the types ++ * that were requested at creation time. not possibly on ++ * earlier chips without busting the ABI. ++ */ ++ nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM | ++ NOUVEAU_GEM_DOMAIN_GART; ++ if (dev_priv->card_type >= NV_50) ++ nvbo->valid_domains &= domain; ++ + nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size); + if (!nvbo->gem) { + nouveau_bo_ref(NULL, pnvbo); +@@ -97,7 +114,7 @@ + + rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; + rep->offset = nvbo->bo.offset; +- rep->map_handle = nvbo->mappable ? nvbo->bo.addr_space_offset : 0; ++ rep->map_handle = nvbo->bo.addr_space_offset; + rep->tile_mode = nvbo->tile_mode; + rep->tile_flags = nvbo->tile_flags; + return 0; +@@ -111,19 +128,11 @@ + struct drm_nouveau_gem_new *req = data; + struct nouveau_bo *nvbo = NULL; + struct nouveau_channel *chan = NULL; +- uint32_t flags = 0; + int ret = 0; + + if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) + dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; + +- if (req->info.domain & NOUVEAU_GEM_DOMAIN_VRAM) +- flags |= TTM_PL_FLAG_VRAM; +- if (req->info.domain & NOUVEAU_GEM_DOMAIN_GART) +- flags |= TTM_PL_FLAG_TT; +- if (!flags || req->info.domain & NOUVEAU_GEM_DOMAIN_CPU) +- flags |= TTM_PL_FLAG_SYSTEM; +- + if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) { + NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); + return -EINVAL; +@@ -135,10 +144,9 @@ + return PTR_ERR(chan); + } + +- ret = nouveau_gem_new(dev, chan, req->info.size, req->align, flags, +- req->info.tile_mode, req->info.tile_flags, false, +- (req->info.domain & NOUVEAU_GEM_DOMAIN_MAPPABLE), +- &nvbo); ++ ret = nouveau_gem_new(dev, chan, 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) +@@ -161,7 +169,7 @@ + { + struct nouveau_bo *nvbo = gem->driver_private; + struct ttm_buffer_object *bo = &nvbo->bo; +- uint32_t domains = valid_domains & ++ uint32_t domains = valid_domains & nvbo->valid_domains & + (write_domains ? write_domains : read_domains); + uint32_t pref_flags = 0, valid_flags = 0; + +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_mem.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_mem.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_mem.c 2011-02-20 23:32:11.000000000 +0100 +@@ -152,7 +152,6 @@ + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + +- nouveau_bo_unpin(dev_priv->vga_ram); + nouveau_bo_ref(NULL, &dev_priv->vga_ram); + + ttm_bo_device_release(&dev_priv->ttm.bdev); +@@ -393,11 +392,17 @@ + struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; + int ret, dma_bits; + +- if (dev_priv->card_type >= NV_50 && +- pci_dma_supported(dev->pdev, DMA_BIT_MASK(40))) +- dma_bits = 40; +- else +- dma_bits = 32; ++ dma_bits = 32; ++ if (dev_priv->card_type >= NV_50) { ++ if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(40))) ++ dma_bits = 40; ++ } else ++ if (drm_device_is_pcie(dev) && ++ dev_priv->chipset != 0x40 && ++ dev_priv->chipset != 0x45) { ++ if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(39))) ++ dma_bits = 39; ++ } + + ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); + if (ret) +@@ -455,13 +460,17 @@ + return ret; + } + +- ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM, +- 0, 0, true, true, &dev_priv->vga_ram); +- if (ret == 0) +- ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM); +- if (ret) { +- NV_WARN(dev, "failed to reserve VGA memory\n"); +- nouveau_bo_ref(NULL, &dev_priv->vga_ram); ++ if (dev_priv->card_type < NV_50) { ++ ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM, ++ 0, 0, &dev_priv->vga_ram); ++ if (ret == 0) ++ ret = nouveau_bo_pin(dev_priv->vga_ram, ++ TTM_PL_FLAG_VRAM); ++ ++ if (ret) { ++ NV_WARN(dev, "failed to reserve VGA memory\n"); ++ nouveau_bo_ref(NULL, &dev_priv->vga_ram); ++ } + } + + dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1), +@@ -666,13 +675,14 @@ + { + struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); + struct nouveau_mm *mm; +- u32 b_size; ++ u64 size, block, rsvd; + int ret; + +- p_size = (p_size << PAGE_SHIFT) >> 12; +- b_size = dev_priv->vram_rblock_size >> 12; ++ rsvd = (256 * 1024); /* vga memory */ ++ size = (p_size << PAGE_SHIFT) - rsvd; ++ block = dev_priv->vram_rblock_size; + +- ret = nouveau_mm_init(&mm, 0, p_size, b_size); ++ ret = nouveau_mm_init(&mm, rsvd >> 12, size >> 12, block >> 12); + if (ret) + return ret; + +@@ -700,9 +710,15 @@ + { + 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; + +- vram->put(dev, (struct nouveau_vram **)&mem->mm_node); ++ if (node->tmp_vma.node) { ++ nouveau_vm_unmap(&node->tmp_vma); ++ nouveau_vm_put(&node->tmp_vma); ++ } ++ ++ vram->put(dev, (struct nouveau_mem **)&mem->mm_node); + } + + static int +@@ -715,7 +731,7 @@ + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; + struct drm_device *dev = dev_priv->dev; + struct nouveau_bo *nvbo = nouveau_bo(bo); +- struct nouveau_vram *node; ++ struct nouveau_mem *node; + u32 size_nc = 0; + int ret; + +@@ -724,7 +740,7 @@ + + ret = vram->get(dev, mem->num_pages << PAGE_SHIFT, + mem->page_alignment << PAGE_SHIFT, size_nc, +- (nvbo->tile_flags >> 8) & 0xff, &node); ++ (nvbo->tile_flags >> 8) & 0x3ff, &node); + if (ret) + return ret; + +@@ -769,3 +785,84 @@ + nouveau_vram_manager_del, + nouveau_vram_manager_debug + }; ++ ++static int ++nouveau_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) ++{ ++ return 0; ++} ++ ++static int ++nouveau_gart_manager_fini(struct ttm_mem_type_manager *man) ++{ ++ return 0; ++} ++ ++static void ++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); ++ } ++ mem->mm_node = NULL; ++} ++ ++static int ++nouveau_gart_manager_new(struct ttm_mem_type_manager *man, ++ struct ttm_buffer_object *bo, ++ struct ttm_placement *placement, ++ struct ttm_mem_reg *mem) ++{ ++ struct drm_nouveau_private *dev_priv = nouveau_bdev(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)) ++ return -ENOMEM; ++ ++ node = kzalloc(sizeof(*node), GFP_KERNEL); ++ if (!node) ++ return -ENOMEM; ++ ++ /* 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; ++} ++ ++void ++nouveau_gart_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) ++{ ++} ++ ++const struct ttm_mem_type_manager_func nouveau_gart_manager = { ++ nouveau_gart_manager_init, ++ nouveau_gart_manager_fini, ++ nouveau_gart_manager_new, ++ nouveau_gart_manager_del, ++ nouveau_gart_manager_debug ++}; +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_mm.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_mm.h +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_mm.h 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_mm.h 2011-02-20 23:32:11.000000000 +0100 +@@ -53,13 +53,13 @@ + + int nv50_vram_init(struct drm_device *); + int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc, +- u32 memtype, struct nouveau_vram **); +-void nv50_vram_del(struct drm_device *, struct nouveau_vram **); ++ u32 memtype, struct nouveau_mem **); ++void nv50_vram_del(struct drm_device *, struct nouveau_mem **); + bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags); + + int nvc0_vram_init(struct drm_device *); + int nvc0_vram_new(struct drm_device *, u64 size, u32 align, u32 ncmin, +- u32 memtype, struct nouveau_vram **); ++ u32 memtype, struct nouveau_mem **); + bool nvc0_vram_flags_valid(struct drm_device *, u32 tile_flags); + + #endif +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_notifier.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_notifier.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_notifier.c 2011-02-20 23:32:11.000000000 +0100 +@@ -39,12 +39,11 @@ + int ret; + + if (nouveau_vram_notify) +- flags = TTM_PL_FLAG_VRAM; ++ flags = NOUVEAU_GEM_DOMAIN_VRAM; + else +- flags = TTM_PL_FLAG_TT; ++ flags = NOUVEAU_GEM_DOMAIN_GART; + +- ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, +- 0, 0x0000, false, true, &ntfy); ++ ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, 0, 0, &ntfy); + if (ret) + return ret; + +@@ -99,6 +98,7 @@ + int size, uint32_t *b_offset) + { + struct drm_device *dev = chan->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *nobj = NULL; + struct drm_mm_node *mem; + uint32_t offset; +@@ -112,11 +112,16 @@ + return -ENOMEM; + } + +- if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) +- target = NV_MEM_TARGET_VRAM; +- else +- target = NV_MEM_TARGET_GART; +- offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; ++ if (dev_priv->card_type < NV_50) { ++ if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) ++ target = NV_MEM_TARGET_VRAM; ++ else ++ target = NV_MEM_TARGET_GART; ++ offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; ++ } else { ++ target = NV_MEM_TARGET_VM; ++ offset = chan->notifier_bo->vma.offset; ++ } + offset += mem->start; + + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset, +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_object.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_object.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_object.c 2011-02-20 23:32:11.000000000 +0100 +@@ -36,6 +36,7 @@ + #include "nouveau_drm.h" + #include "nouveau_ramht.h" + #include "nouveau_vm.h" ++#include "nv50_display.h" + + struct nouveau_gpuobj_method { + struct list_head head; +@@ -490,16 +491,22 @@ + } + + if (target == NV_MEM_TARGET_GART) { +- if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { +- target = NV_MEM_TARGET_PCI_NOSNOOP; +- base += dev_priv->gart_info.aper_base; +- } else +- if (base != 0) { +- base = nouveau_sgdma_get_physical(dev, base); ++ struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; ++ ++ if (dev_priv->gart_info.type == NOUVEAU_GART_PDMA) { ++ if (base == 0) { ++ nouveau_gpuobj_ref(gart, pobj); ++ return 0; ++ } ++ ++ base = nouveau_sgdma_get_physical(dev, base); + target = NV_MEM_TARGET_PCI; + } else { +- nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, pobj); +- return 0; ++ base += dev_priv->gart_info.aper_base; ++ if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) ++ target = NV_MEM_TARGET_PCI_NOSNOOP; ++ else ++ target = NV_MEM_TARGET_PCI; + } + } + +@@ -776,7 +783,7 @@ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *vram = NULL, *tt = NULL; +- int ret; ++ int ret, i; + + NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); + +@@ -841,6 +848,25 @@ + nouveau_gpuobj_ref(NULL, &ramht); + if (ret) + return ret; ++ ++ /* dma objects for display sync channel semaphore blocks */ ++ for (i = 0; i < 2; i++) { ++ 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; ++ ++ ret = nouveau_gpuobj_dma_new(chan, 0x3d, offset, 0xfff, ++ NV_MEM_ACCESS_RW, ++ NV_MEM_TARGET_VRAM, &sem); ++ if (ret) ++ return ret; ++ ++ ret = nouveau_ramht_insert(chan, NvEvoSema0 + i, sem); ++ nouveau_gpuobj_ref(NULL, &sem); ++ if (ret) ++ return ret; ++ } + } + + /* VRAM ctxdma */ +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_pm.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_pm.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.c 2011-02-20 23:32:11.000000000 +0100 +@@ -543,7 +543,7 @@ + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm_level *perflvl; + +- if (pm->cur == &pm->boot) ++ if (!pm->cur || pm->cur == &pm->boot) + return; + + perflvl = pm->cur; +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_ramht.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_ramht.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.c 2011-02-20 23:32:11.000000000 +0100 +@@ -114,7 +114,9 @@ + (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); + } else { + if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { +- ctx = (gpuobj->cinst << 10) | chan->id; ++ ctx = (gpuobj->cinst << 10) | ++ (chan->id << 28) | ++ chan->id; /* HASH_TAG */ + } else { + ctx = (gpuobj->cinst >> 4) | + ((gpuobj->engine << +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_sgdma.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2011-02-20 23:32:11.000000000 +0100 +@@ -74,8 +74,24 @@ + } + } + ++static void ++nouveau_sgdma_destroy(struct ttm_backend *be) ++{ ++ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; ++ ++ if (be) { ++ NV_DEBUG(nvbe->dev, "\n"); ++ ++ if (nvbe) { ++ if (nvbe->pages) ++ be->func->clear(be); ++ kfree(nvbe); ++ } ++ } ++} ++ + static int +-nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) ++nv04_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) + { + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct drm_device *dev = nvbe->dev; +@@ -102,7 +118,7 @@ + } + + static int +-nouveau_sgdma_unbind(struct ttm_backend *be) ++nv04_sgdma_unbind(struct ttm_backend *be) + { + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct drm_device *dev = nvbe->dev; +@@ -125,59 +141,245 @@ + return 0; + } + ++static struct ttm_backend_func nv04_sgdma_backend = { ++ .populate = nouveau_sgdma_populate, ++ .clear = nouveau_sgdma_clear, ++ .bind = nv04_sgdma_bind, ++ .unbind = nv04_sgdma_unbind, ++ .destroy = nouveau_sgdma_destroy ++}; ++ + static void +-nouveau_sgdma_destroy(struct ttm_backend *be) ++nv41_sgdma_flush(struct nouveau_sgdma_be *nvbe) ++{ ++ struct drm_device *dev = nvbe->dev; ++ ++ nv_wr32(dev, 0x100810, 0x00000022); ++ if (!nv_wait(dev, 0x100810, 0x00000100, 0x00000100)) ++ NV_ERROR(dev, "vm flush timeout: 0x%08x\n", ++ nv_rd32(dev, 0x100810)); ++ nv_wr32(dev, 0x100810, 0x00000000); ++} ++ ++static int ++nv41_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) + { + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; ++ struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; ++ struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; ++ dma_addr_t *list = nvbe->pages; ++ u32 pte = mem->start << 2; ++ u32 cnt = nvbe->nr_pages; + +- if (be) { +- NV_DEBUG(nvbe->dev, "\n"); ++ nvbe->offset = mem->start << PAGE_SHIFT; + +- if (nvbe) { +- if (nvbe->pages) +- be->func->clear(be); +- kfree(nvbe); ++ while (cnt--) { ++ nv_wo32(pgt, pte, (*list++ >> 7) | 1); ++ pte += 4; ++ } ++ ++ nv41_sgdma_flush(nvbe); ++ nvbe->bound = true; ++ return 0; ++} ++ ++static int ++nv41_sgdma_unbind(struct ttm_backend *be) ++{ ++ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; ++ struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; ++ struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; ++ u32 pte = (nvbe->offset >> 12) << 2; ++ u32 cnt = nvbe->nr_pages; ++ ++ while (cnt--) { ++ nv_wo32(pgt, pte, 0x00000000); ++ pte += 4; ++ } ++ ++ nv41_sgdma_flush(nvbe); ++ nvbe->bound = false; ++ return 0; ++} ++ ++static struct ttm_backend_func nv41_sgdma_backend = { ++ .populate = nouveau_sgdma_populate, ++ .clear = nouveau_sgdma_clear, ++ .bind = nv41_sgdma_bind, ++ .unbind = nv41_sgdma_unbind, ++ .destroy = nouveau_sgdma_destroy ++}; ++ ++static void ++nv44_sgdma_flush(struct nouveau_sgdma_be *nvbe) ++{ ++ struct drm_device *dev = nvbe->dev; ++ ++ nv_wr32(dev, 0x100814, (nvbe->nr_pages - 1) << 12); ++ nv_wr32(dev, 0x100808, nvbe->offset | 0x20); ++ if (!nv_wait(dev, 0x100808, 0x00000001, 0x00000001)) ++ NV_ERROR(dev, "gart flush timeout: 0x%08x\n", ++ nv_rd32(dev, 0x100808)); ++ nv_wr32(dev, 0x100808, 0x00000000); ++} ++ ++static void ++nv44_sgdma_fill(struct nouveau_gpuobj *pgt, dma_addr_t *list, u32 base, u32 cnt) ++{ ++ struct drm_nouveau_private *dev_priv = pgt->dev->dev_private; ++ dma_addr_t dummy = dev_priv->gart_info.dummy.addr; ++ u32 pte, tmp[4]; ++ ++ pte = base >> 2; ++ base &= ~0x0000000f; ++ ++ tmp[0] = nv_ro32(pgt, base + 0x0); ++ tmp[1] = nv_ro32(pgt, base + 0x4); ++ tmp[2] = nv_ro32(pgt, base + 0x8); ++ tmp[3] = nv_ro32(pgt, base + 0xc); ++ while (cnt--) { ++ u32 addr = list ? (*list++ >> 12) : (dummy >> 12); ++ switch (pte++ & 0x3) { ++ case 0: ++ tmp[0] &= ~0x07ffffff; ++ tmp[0] |= addr; ++ break; ++ case 1: ++ tmp[0] &= ~0xf8000000; ++ tmp[0] |= addr << 27; ++ tmp[1] &= ~0x003fffff; ++ tmp[1] |= addr >> 5; ++ break; ++ case 2: ++ tmp[1] &= ~0xffc00000; ++ tmp[1] |= addr << 22; ++ tmp[2] &= ~0x0001ffff; ++ tmp[2] |= addr >> 10; ++ break; ++ case 3: ++ tmp[2] &= ~0xfffe0000; ++ tmp[2] |= addr << 17; ++ tmp[3] &= ~0x00000fff; ++ tmp[3] |= addr >> 15; ++ break; + } + } ++ ++ tmp[3] |= 0x40000000; ++ ++ nv_wo32(pgt, base + 0x0, tmp[0]); ++ nv_wo32(pgt, base + 0x4, tmp[1]); ++ nv_wo32(pgt, base + 0x8, tmp[2]); ++ nv_wo32(pgt, base + 0xc, tmp[3]); + } + + static int +-nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) ++nv44_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) + { + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; ++ struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; ++ dma_addr_t *list = nvbe->pages; ++ u32 pte = mem->start << 2, tmp[4]; ++ u32 cnt = nvbe->nr_pages; ++ int i; + + nvbe->offset = mem->start << PAGE_SHIFT; + +- nouveau_vm_map_sg(&dev_priv->gart_info.vma, nvbe->offset, +- nvbe->nr_pages << PAGE_SHIFT, nvbe->pages); ++ if (pte & 0x0000000c) { ++ u32 max = 4 - ((pte >> 2) & 0x3); ++ u32 part = (cnt > max) ? max : cnt; ++ nv44_sgdma_fill(pgt, list, pte, part); ++ pte += (part << 2); ++ list += part; ++ cnt -= part; ++ } ++ ++ while (cnt >= 4) { ++ for (i = 0; i < 4; i++) ++ tmp[i] = *list++ >> 12; ++ nv_wo32(pgt, pte + 0x0, tmp[0] >> 0 | tmp[1] << 27); ++ nv_wo32(pgt, pte + 0x4, tmp[1] >> 5 | tmp[2] << 22); ++ nv_wo32(pgt, pte + 0x8, tmp[2] >> 10 | tmp[3] << 17); ++ nv_wo32(pgt, pte + 0xc, tmp[3] >> 15 | 0x40000000); ++ pte += 0x10; ++ cnt -= 4; ++ } ++ ++ if (cnt) ++ nv44_sgdma_fill(pgt, list, pte, cnt); ++ ++ nv44_sgdma_flush(nvbe); + nvbe->bound = true; + return 0; + } + + static int +-nv50_sgdma_unbind(struct ttm_backend *be) ++nv44_sgdma_unbind(struct ttm_backend *be) + { + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; ++ struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; ++ u32 pte = (nvbe->offset >> 12) << 2; ++ u32 cnt = nvbe->nr_pages; ++ ++ if (pte & 0x0000000c) { ++ u32 max = 4 - ((pte >> 2) & 0x3); ++ u32 part = (cnt > max) ? max : cnt; ++ nv44_sgdma_fill(pgt, NULL, pte, part); ++ pte += (part << 2); ++ cnt -= part; ++ } + +- if (!nvbe->bound) +- return 0; ++ while (cnt >= 4) { ++ nv_wo32(pgt, pte + 0x0, 0x00000000); ++ nv_wo32(pgt, pte + 0x4, 0x00000000); ++ nv_wo32(pgt, pte + 0x8, 0x00000000); ++ nv_wo32(pgt, pte + 0xc, 0x00000000); ++ pte += 0x10; ++ cnt -= 4; ++ } + +- nouveau_vm_unmap_at(&dev_priv->gart_info.vma, nvbe->offset, +- nvbe->nr_pages << PAGE_SHIFT); ++ if (cnt) ++ nv44_sgdma_fill(pgt, NULL, pte, cnt); ++ ++ nv44_sgdma_flush(nvbe); + nvbe->bound = false; + return 0; + } + +-static struct ttm_backend_func nouveau_sgdma_backend = { ++static struct ttm_backend_func nv44_sgdma_backend = { + .populate = nouveau_sgdma_populate, + .clear = nouveau_sgdma_clear, +- .bind = nouveau_sgdma_bind, +- .unbind = nouveau_sgdma_unbind, ++ .bind = nv44_sgdma_bind, ++ .unbind = nv44_sgdma_unbind, + .destroy = nouveau_sgdma_destroy + }; + ++static int ++nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) ++{ ++ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; ++ struct nouveau_mem *node = mem->mm_node; ++ /* noop: bound in move_notify() */ ++ node->pages = nvbe->pages; ++ nvbe->pages = (dma_addr_t *)node; ++ nvbe->bound = true; ++ return 0; ++} ++ ++static int ++nv50_sgdma_unbind(struct ttm_backend *be) ++{ ++ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; ++ struct nouveau_mem *node = (struct nouveau_mem *)nvbe->pages; ++ /* noop: unbound in move_notify() */ ++ nvbe->pages = node->pages; ++ node->pages = NULL; ++ nvbe->bound = false; ++ return 0; ++} ++ + static struct ttm_backend_func nv50_sgdma_backend = { + .populate = nouveau_sgdma_populate, + .clear = nouveau_sgdma_clear, +@@ -198,10 +400,7 @@ + + nvbe->dev = dev; + +- if (dev_priv->card_type < NV_50) +- nvbe->backend.func = &nouveau_sgdma_backend; +- else +- nvbe->backend.func = &nv50_sgdma_backend; ++ nvbe->backend.func = dev_priv->gart_info.func; + return &nvbe->backend; + } + +@@ -210,21 +409,65 @@ + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj = NULL; +- uint32_t aper_size, obj_size; +- int i, ret; ++ u32 aper_size, align; ++ int ret; + +- if (dev_priv->card_type < NV_50) { +- if(dev_priv->ramin_rsvd_vram < 2 * 1024 * 1024) +- aper_size = 64 * 1024 * 1024; +- else +- aper_size = 512 * 1024 * 1024; +- +- obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4; +- obj_size += 8; /* ctxdma header */ +- +- ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, +- NVOBJ_FLAG_ZERO_ALLOC | +- NVOBJ_FLAG_ZERO_FREE, &gpuobj); ++ if (dev_priv->card_type >= NV_50 || ++ dev_priv->ramin_rsvd_vram >= 2 * 1024 * 1024) ++ aper_size = 512 * 1024 * 1024; ++ else ++ aper_size = 64 * 1024 * 1024; ++ ++ /* Dear NVIDIA, NV44+ would like proper present bits in PTEs for ++ * christmas. The cards before it have them, the cards after ++ * it have them, why is NV44 so unloved? ++ */ ++ dev_priv->gart_info.dummy.page = alloc_page(GFP_DMA32 | GFP_KERNEL); ++ if (!dev_priv->gart_info.dummy.page) ++ return -ENOMEM; ++ ++ dev_priv->gart_info.dummy.addr = ++ pci_map_page(dev->pdev, dev_priv->gart_info.dummy.page, ++ 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); ++ if (pci_dma_mapping_error(dev->pdev, dev_priv->gart_info.dummy.addr)) { ++ NV_ERROR(dev, "error mapping dummy page\n"); ++ __free_page(dev_priv->gart_info.dummy.page); ++ dev_priv->gart_info.dummy.page = NULL; ++ return -ENOMEM; ++ } ++ ++ if (dev_priv->card_type >= NV_50) { ++ dev_priv->gart_info.aper_base = 0; ++ dev_priv->gart_info.aper_size = aper_size; ++ dev_priv->gart_info.type = NOUVEAU_GART_HW; ++ dev_priv->gart_info.func = &nv50_sgdma_backend; ++ } else ++ if (drm_device_is_pcie(dev) && ++ dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) { ++ if (nv44_graph_class(dev)) { ++ dev_priv->gart_info.func = &nv44_sgdma_backend; ++ align = 512 * 1024; ++ } else { ++ dev_priv->gart_info.func = &nv41_sgdma_backend; ++ align = 16; ++ } ++ ++ ret = nouveau_gpuobj_new(dev, NULL, aper_size / 1024, align, ++ NVOBJ_FLAG_ZERO_ALLOC | ++ NVOBJ_FLAG_ZERO_FREE, &gpuobj); ++ if (ret) { ++ NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); ++ return ret; ++ } ++ ++ dev_priv->gart_info.sg_ctxdma = gpuobj; ++ dev_priv->gart_info.aper_base = 0; ++ dev_priv->gart_info.aper_size = aper_size; ++ dev_priv->gart_info.type = NOUVEAU_GART_HW; ++ } else { ++ ret = nouveau_gpuobj_new(dev, NULL, (aper_size / 1024) + 8, 16, ++ NVOBJ_FLAG_ZERO_ALLOC | ++ NVOBJ_FLAG_ZERO_FREE, &gpuobj); + if (ret) { + NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); + return ret; +@@ -236,25 +479,14 @@ + (0 << 14) /* RW */ | + (2 << 16) /* PCI */); + nv_wo32(gpuobj, 4, aper_size - 1); +- for (i = 2; i < 2 + (aper_size >> 12); i++) +- nv_wo32(gpuobj, i * 4, 0x00000000); + + dev_priv->gart_info.sg_ctxdma = gpuobj; + dev_priv->gart_info.aper_base = 0; + dev_priv->gart_info.aper_size = aper_size; +- } else +- if (dev_priv->chan_vm) { +- ret = nouveau_vm_get(dev_priv->chan_vm, 512 * 1024 * 1024, +- 12, NV_MEM_ACCESS_RW, +- &dev_priv->gart_info.vma); +- if (ret) +- return ret; +- +- dev_priv->gart_info.aper_base = dev_priv->gart_info.vma.offset; +- dev_priv->gart_info.aper_size = 512 * 1024 * 1024; ++ dev_priv->gart_info.type = NOUVEAU_GART_PDMA; ++ dev_priv->gart_info.func = &nv04_sgdma_backend; + } + +- dev_priv->gart_info.type = NOUVEAU_GART_SGDMA; + return 0; + } + +@@ -264,7 +496,13 @@ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma); +- nouveau_vm_put(&dev_priv->gart_info.vma); ++ ++ if (dev_priv->gart_info.dummy.page) { ++ pci_unmap_page(dev->pdev, dev_priv->gart_info.dummy.addr, ++ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); ++ __free_page(dev_priv->gart_info.dummy.page); ++ dev_priv->gart_info.dummy.page = NULL; ++ } + } + + uint32_t +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_state.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_state.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_state.c 2011-02-20 23:32:11.000000000 +0100 +@@ -544,7 +544,6 @@ + nouveau_card_init_channel(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpuobj *gpuobj = NULL; + int ret; + + ret = nouveau_channel_alloc(dev, &dev_priv->channel, +@@ -552,41 +551,8 @@ + if (ret) + return ret; + +- /* no dma objects on fermi... */ +- if (dev_priv->card_type >= NV_C0) +- goto out_done; +- +- ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, +- 0, dev_priv->vram_size, +- NV_MEM_ACCESS_RW, NV_MEM_TARGET_VRAM, +- &gpuobj); +- if (ret) +- goto out_err; +- +- ret = nouveau_ramht_insert(dev_priv->channel, NvDmaVRAM, gpuobj); +- nouveau_gpuobj_ref(NULL, &gpuobj); +- if (ret) +- goto out_err; +- +- ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, +- 0, dev_priv->gart_info.aper_size, +- NV_MEM_ACCESS_RW, NV_MEM_TARGET_GART, +- &gpuobj); +- if (ret) +- goto out_err; +- +- ret = nouveau_ramht_insert(dev_priv->channel, NvDmaGART, gpuobj); +- nouveau_gpuobj_ref(NULL, &gpuobj); +- if (ret) +- goto out_err; +- +-out_done: + mutex_unlock(&dev_priv->channel->mutex); + return 0; +- +-out_err: +- nouveau_channel_put(&dev_priv->channel); +- return ret; + } + + static void nouveau_switcheroo_set_state(struct pci_dev *pdev, +@@ -929,12 +895,6 @@ + NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", + dev->pci_vendor, dev->pci_device, dev->pdev->class); + +- dev_priv->wq = create_workqueue("nouveau"); +- if (!dev_priv->wq) { +- ret = -EINVAL; +- goto err_priv; +- } +- + /* resource 0 is mmio regs */ + /* resource 1 is linear FB */ + /* resource 2 is RAMIN (mmio regs + 0x1000000) */ +@@ -947,7 +907,7 @@ + NV_ERROR(dev, "Unable to initialize the mmio mapping. " + "Please report your setup to " DRIVER_EMAIL "\n"); + ret = -EINVAL; +- goto err_wq; ++ goto err_priv; + } + NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", + (unsigned long long)mmio_start_offs); +@@ -1054,8 +1014,6 @@ + iounmap(dev_priv->ramin); + err_mmio: + iounmap(dev_priv->mmio); +-err_wq: +- destroy_workqueue(dev_priv->wq); + err_priv: + kfree(dev_priv); + dev->dev_private = NULL; +@@ -1126,7 +1084,7 @@ + getparam->value = 1; + break; + case NOUVEAU_GETPARAM_HAS_PAGEFLIP: +- getparam->value = (dev_priv->card_type < NV_50); ++ getparam->value = 1; + break; + case NOUVEAU_GETPARAM_GRAPH_UNITS: + /* NV40 and NV50 versions are quite different, but register +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_temp.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_temp.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_temp.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_temp.c 2011-02-20 23:32:11.000000000 +0100 +@@ -239,11 +239,9 @@ + probe_monitoring_device(struct nouveau_i2c_chan *i2c, + struct i2c_board_info *info) + { +- char modalias[16] = "i2c:"; + struct i2c_client *client; + +- strlcat(modalias, info->type, sizeof(modalias)); +- request_module(modalias); ++ request_module("%s%s", I2C_MODULE_PREFIX, info->type); + + client = i2c_new_device(&i2c->adapter, info); + if (!client) +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_vm.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_vm.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_vm.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_vm.c 2011-02-20 23:32:11.000000000 +0100 +@@ -28,7 +28,7 @@ + #include "nouveau_vm.h" + + void +-nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) ++nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) + { + struct nouveau_vm *vm = vma->vm; + struct nouveau_mm_node *r; +@@ -40,7 +40,8 @@ + u32 max = 1 << (vm->pgt_bits - bits); + u32 end, len; + +- list_for_each_entry(r, &vram->regions, rl_entry) { ++ delta = 0; ++ list_for_each_entry(r, &node->regions, rl_entry) { + u64 phys = (u64)r->offset << 12; + u32 num = r->length >> bits; + +@@ -52,7 +53,7 @@ + end = max; + len = end - pte; + +- vm->map(vma, pgt, vram, pte, len, phys); ++ vm->map(vma, pgt, node, pte, len, phys, delta); + + num -= len; + pte += len; +@@ -60,6 +61,8 @@ + pde++; + pte = 0; + } ++ ++ delta += (u64)len << vma->node->type; + } + } + +@@ -67,14 +70,14 @@ + } + + void +-nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_vram *vram) ++nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node) + { +- nouveau_vm_map_at(vma, 0, vram); ++ nouveau_vm_map_at(vma, 0, node); + } + + void + nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, +- dma_addr_t *list) ++ struct nouveau_mem *mem, dma_addr_t *list) + { + struct nouveau_vm *vm = vma->vm; + int big = vma->node->type != vm->spg_shift; +@@ -94,7 +97,7 @@ + end = max; + len = end - pte; + +- vm->map_sg(vma, pgt, pte, list, len); ++ vm->map_sg(vma, pgt, mem, pte, len, list); + + num -= len; + pte += len; +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_vm.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_vm.h +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_vm.h 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_vm.h 2011-02-20 23:32:11.000000000 +0100 +@@ -67,9 +67,10 @@ + void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde, + struct nouveau_gpuobj *pgt[2]); + void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *, +- struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); ++ struct nouveau_mem *, u32 pte, u32 cnt, ++ u64 phys, u64 delta); + void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, +- u32 pte, dma_addr_t *, u32 cnt); ++ struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); + void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt); + void (*flush)(struct nouveau_vm *); + }; +@@ -82,20 +83,20 @@ + int nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift, + u32 access, struct nouveau_vma *); + void nouveau_vm_put(struct nouveau_vma *); +-void nouveau_vm_map(struct nouveau_vma *, struct nouveau_vram *); +-void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_vram *); ++void nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *); ++void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *); + void nouveau_vm_unmap(struct nouveau_vma *); + void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); + void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, +- dma_addr_t *); ++ struct nouveau_mem *, dma_addr_t *); + + /* nv50_vm.c */ + void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, + struct nouveau_gpuobj *pgt[2]); + void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, +- struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); ++ struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta); + void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, +- u32 pte, dma_addr_t *, u32 cnt); ++ struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); + void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); + void nv50_vm_flush(struct nouveau_vm *); + void nv50_vm_flush_engine(struct drm_device *, int engine); +@@ -104,9 +105,9 @@ + void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, + struct nouveau_gpuobj *pgt[2]); + void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, +- struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); ++ struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta); + void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, +- u32 pte, dma_addr_t *, u32 cnt); ++ struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); + void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); + void nvc0_vm_flush(struct nouveau_vm *); + +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv04_crtc.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_crtc.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv04_crtc.c 2011-02-20 23:32:11.000000000 +0100 +@@ -1031,7 +1031,7 @@ + drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); + + ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, +- 0, 0x0000, false, true, &nv_crtc->cursor.nvbo); ++ 0, 0x0000, &nv_crtc->cursor.nvbo); + if (!ret) { + ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); + if (!ret) +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_dfp.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv04_dfp.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_dfp.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv04_dfp.c 2011-02-20 23:32:11.000000000 +0100 +@@ -342,8 +342,8 @@ + if (nv_encoder->dcb->type == OUTPUT_LVDS) { + bool duallink, dummy; + +- nouveau_bios_parse_lvds_table(dev, nv_connector->native_mode-> +- clock, &duallink, &dummy); ++ nouveau_bios_parse_lvds_table(dev, output_mode->clock, ++ &duallink, &dummy); + if (duallink) + regp->fp_control |= (8 << 28); + } else +@@ -518,8 +518,6 @@ + return; + + if (nv_encoder->dcb->lvdsconf.use_power_scripts) { +- struct nouveau_connector *nv_connector = nouveau_encoder_connector_get(nv_encoder); +- + /* when removing an output, crtc may not be set, but PANEL_OFF + * must still be run + */ +@@ -527,12 +525,8 @@ + nv04_dfp_get_bound_head(dev, nv_encoder->dcb); + + if (mode == DRM_MODE_DPMS_ON) { +- if (!nv_connector->native_mode) { +- NV_ERROR(dev, "Not turning on LVDS without native mode\n"); +- return; +- } + call_lvds_script(dev, nv_encoder->dcb, head, +- LVDS_PANEL_ON, nv_connector->native_mode->clock); ++ LVDS_PANEL_ON, nv_encoder->mode.clock); + } else + /* pxclk of 0 is fine for PANEL_OFF, and for a + * disconnected LVDS encoder there is no native_mode +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_fifo.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv04_fifo.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_fifo.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv04_fifo.c 2011-02-20 23:32:11.000000000 +0100 +@@ -379,6 +379,15 @@ + return handled; + } + ++static const char *nv_dma_state_err(u32 state) ++{ ++ static const char * const desc[] = { ++ "NONE", "CALL_SUBR_ACTIVE", "INVALID_MTHD", "RET_SUBR_INACTIVE", ++ "INVALID_CMD", "IB_EMPTY"/* NV50+ */, "MEM_FAULT", "UNK" ++ }; ++ return desc[(state >> 29) & 0x7]; ++} ++ + void + nv04_fifo_isr(struct drm_device *dev) + { +@@ -460,9 +469,10 @@ + if (nouveau_ratelimit()) + NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x " + "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " +- "State 0x%08x Push 0x%08x\n", ++ "State 0x%08x (err: %s) Push 0x%08x\n", + chid, ho_get, dma_get, ho_put, + dma_put, ib_get, ib_put, state, ++ nv_dma_state_err(state), + push); + + /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ +@@ -476,8 +486,9 @@ + } + } else { + NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " +- "Put 0x%08x State 0x%08x Push 0x%08x\n", +- chid, dma_get, dma_put, state, push); ++ "Put 0x%08x State 0x%08x (err: %s) Push 0x%08x\n", ++ chid, dma_get, dma_put, state, ++ nv_dma_state_err(state), push); + + if (dma_get != dma_put) + nv_wr32(dev, 0x003244, dma_put); +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv40_fb.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv40_fb.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv40_fb.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv40_fb.c 2011-02-20 23:32:11.000000000 +0100 +@@ -24,6 +24,53 @@ + } + } + ++static void ++nv40_fb_init_gart(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; ++ ++ if (dev_priv->gart_info.type != NOUVEAU_GART_HW) { ++ nv_wr32(dev, 0x100800, 0x00000001); ++ return; ++ } ++ ++ nv_wr32(dev, 0x100800, gart->pinst | 0x00000002); ++ nv_mask(dev, 0x10008c, 0x00000100, 0x00000100); ++ nv_wr32(dev, 0x100820, 0x00000000); ++} ++ ++static void ++nv44_fb_init_gart(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; ++ u32 vinst; ++ ++ if (dev_priv->gart_info.type != NOUVEAU_GART_HW) { ++ nv_wr32(dev, 0x100850, 0x80000000); ++ nv_wr32(dev, 0x100800, 0x00000001); ++ return; ++ } ++ ++ /* calculate vram address of this PRAMIN block, object ++ * must be allocated on 512KiB alignment, and not exceed ++ * a total size of 512KiB for this to work correctly ++ */ ++ vinst = nv_rd32(dev, 0x10020c); ++ vinst -= ((gart->pinst >> 19) + 1) << 19; ++ ++ nv_wr32(dev, 0x100850, 0x80000000); ++ nv_wr32(dev, 0x100818, dev_priv->gart_info.dummy.addr); ++ ++ nv_wr32(dev, 0x100804, dev_priv->gart_info.aper_size); ++ nv_wr32(dev, 0x100850, 0x00008000); ++ nv_mask(dev, 0x10008c, 0x00000200, 0x00000200); ++ nv_wr32(dev, 0x100820, 0x00000000); ++ nv_wr32(dev, 0x10082c, 0x00000001); ++ nv_wr32(dev, 0x100800, vinst | 0x00000010); ++} ++ + int + nv40_fb_init(struct drm_device *dev) + { +@@ -32,12 +79,12 @@ + uint32_t tmp; + int i; + +- /* This is strictly a NV4x register (don't know about NV5x). */ +- /* The blob sets these to all kinds of values, and they mess up our setup. */ +- /* I got value 0x52802 instead. For some cards the blob even sets it back to 0x1. */ +- /* Note: the blob doesn't read this value, so i'm pretty sure this is safe for all cards. */ +- /* Any idea what this is? */ +- nv_wr32(dev, NV40_PFB_UNK_800, 0x1); ++ if (dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) { ++ if (nv44_graph_class(dev)) ++ nv44_fb_init_gart(dev); ++ else ++ nv40_fb_init_gart(dev); ++ } + + switch (dev_priv->chipset) { + case 0x40: +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv40_graph.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv40_graph.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv40_graph.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv40_graph.c 2011-02-20 23:32:11.000000000 +0100 +@@ -211,18 +211,32 @@ + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + switch (dev_priv->chipset) { ++ case 0x40: ++ case 0x41: /* guess */ ++ case 0x42: ++ case 0x43: ++ case 0x45: /* guess */ ++ case 0x4e: ++ nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); ++ nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); ++ nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); ++ nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch); ++ nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit); ++ nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr); ++ break; + case 0x44: + case 0x4a: +- case 0x4e: + nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); + break; +- + case 0x46: + case 0x47: + case 0x49: + case 0x4b: ++ case 0x4c: ++ case 0x67: ++ default: + nv_wr32(dev, NV47_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(dev, NV47_PGRAPH_TILE(i), tile->addr); +@@ -230,15 +244,6 @@ + nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit); + nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr); + break; +- +- default: +- nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); +- nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); +- nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); +- nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch); +- nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit); +- nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr); +- break; + } + } + +@@ -396,17 +401,20 @@ + break; + default: + switch (dev_priv->chipset) { +- case 0x46: +- case 0x47: +- case 0x49: +- case 0x4b: +- nv_wr32(dev, 0x400DF0, nv_rd32(dev, NV04_PFB_CFG0)); +- nv_wr32(dev, 0x400DF4, nv_rd32(dev, NV04_PFB_CFG1)); +- break; +- default: ++ case 0x41: ++ case 0x42: ++ case 0x43: ++ case 0x45: ++ case 0x4e: ++ case 0x44: ++ case 0x4a: + nv_wr32(dev, 0x4009F0, nv_rd32(dev, NV04_PFB_CFG0)); + nv_wr32(dev, 0x4009F4, nv_rd32(dev, NV04_PFB_CFG1)); + break; ++ default: ++ nv_wr32(dev, 0x400DF0, nv_rd32(dev, NV04_PFB_CFG0)); ++ nv_wr32(dev, 0x400DF4, nv_rd32(dev, NV04_PFB_CFG1)); ++ break; + } + nv_wr32(dev, 0x4069F0, nv_rd32(dev, NV04_PFB_CFG0)); + nv_wr32(dev, 0x4069F4, nv_rd32(dev, NV04_PFB_CFG1)); +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_crtc.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_crtc.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_crtc.c 2011-02-20 23:32:11.000000000 +0100 +@@ -65,7 +65,7 @@ + { + struct drm_device *dev = nv_crtc->base.dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + int index = nv_crtc->index, ret; + + NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); +@@ -135,8 +135,7 @@ + nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update) + { + struct drm_device *dev = nv_crtc->base.dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + int ret; + + NV_DEBUG_KMS(dev, "\n"); +@@ -186,8 +185,7 @@ + struct nouveau_connector *nv_connector = + nouveau_crtc_connector_get(nv_crtc); + struct drm_device *dev = nv_crtc->base.dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + struct drm_display_mode *native_mode = NULL; + struct drm_display_mode *mode = &nv_crtc->base.mode; + uint32_t outX, outY, horiz, vert; +@@ -445,6 +443,42 @@ + { + } + ++static int ++nv50_crtc_wait_complete(struct drm_crtc *crtc) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; ++ struct nv50_display *disp = nv50_display(dev); ++ struct nouveau_channel *evo = disp->master; ++ u64 start; ++ int ret; ++ ++ ret = RING_SPACE(evo, 6); ++ if (ret) ++ return ret; ++ BEGIN_RING(evo, 0, 0x0084, 1); ++ OUT_RING (evo, 0x80000000); ++ BEGIN_RING(evo, 0, 0x0080, 1); ++ OUT_RING (evo, 0); ++ BEGIN_RING(evo, 0, 0x0084, 1); ++ OUT_RING (evo, 0x00000000); ++ ++ nv_wo32(disp->ntfy, 0x000, 0x00000000); ++ FIRE_RING (evo); ++ ++ start = ptimer->read(dev); ++ do { ++ nv_wr32(dev, 0x61002c, 0x370); ++ nv_wr32(dev, 0x000140, 1); ++ ++ if (nv_ro32(disp->ntfy, 0x000)) ++ return 0; ++ } while (ptimer->read(dev) - start < 2000000000ULL); ++ ++ return -EBUSY; ++} ++ + static void + nv50_crtc_prepare(struct drm_crtc *crtc) + { +@@ -453,6 +487,7 @@ + + NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); + ++ nv50_display_flip_stop(crtc); + drm_vblank_pre_modeset(dev, nv_crtc->index); + nv50_crtc_blank(nv_crtc, true); + } +@@ -461,24 +496,14 @@ + nv50_crtc_commit(struct drm_crtc *crtc) + { + struct drm_device *dev = crtc->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); +- int ret; + + NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); + + nv50_crtc_blank(nv_crtc, false); + drm_vblank_post_modeset(dev, nv_crtc->index); +- +- ret = RING_SPACE(evo, 2); +- if (ret) { +- NV_ERROR(dev, "no space while committing crtc\n"); +- return; +- } +- BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); +- OUT_RING (evo, 0); +- FIRE_RING (evo); ++ nv50_crtc_wait_complete(crtc); ++ nv50_display_flip_next(crtc, crtc->fb, NULL); + } + + static bool +@@ -491,15 +516,15 @@ + static int + nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, + struct drm_framebuffer *passed_fb, +- int x, int y, bool update, bool atomic) ++ int x, int y, bool atomic) + { + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct drm_device *dev = nv_crtc->base.dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + struct drm_framebuffer *drm_fb = nv_crtc->base.fb; + struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); +- int ret, format; ++ int ret; + + NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); + +@@ -525,28 +550,6 @@ + } + } + +- switch (drm_fb->depth) { +- case 8: +- format = NV50_EVO_CRTC_FB_DEPTH_8; +- break; +- case 15: +- format = NV50_EVO_CRTC_FB_DEPTH_15; +- break; +- case 16: +- format = NV50_EVO_CRTC_FB_DEPTH_16; +- break; +- case 24: +- case 32: +- format = NV50_EVO_CRTC_FB_DEPTH_24; +- break; +- case 30: +- format = NV50_EVO_CRTC_FB_DEPTH_30; +- break; +- default: +- NV_ERROR(dev, "unknown depth %d\n", drm_fb->depth); +- return -EINVAL; +- } +- + nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT; + nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo); + nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; +@@ -556,14 +559,7 @@ + return ret; + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1); +- if (nv_crtc->fb.tile_flags == 0x7a00 || +- nv_crtc->fb.tile_flags == 0xfe00) +- OUT_RING(evo, NvEvoFB32); +- else +- if (nv_crtc->fb.tile_flags == 0x7000) +- OUT_RING(evo, NvEvoFB16); +- else +- OUT_RING(evo, NvEvoVRAM_LP); ++ OUT_RING (evo, fb->r_dma); + } + + ret = RING_SPACE(evo, 12); +@@ -571,45 +567,26 @@ + return ret; + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_OFFSET), 5); +- OUT_RING(evo, nv_crtc->fb.offset >> 8); +- OUT_RING(evo, 0); +- OUT_RING(evo, (drm_fb->height << 16) | drm_fb->width); +- if (!nv_crtc->fb.tile_flags) { +- OUT_RING(evo, drm_fb->pitch | (1 << 20)); +- } else { +- u32 tile_mode = fb->nvbo->tile_mode; +- if (dev_priv->card_type >= NV_C0) +- tile_mode >>= 4; +- OUT_RING(evo, ((drm_fb->pitch / 4) << 4) | tile_mode); +- } +- if (dev_priv->chipset == 0x50) +- OUT_RING(evo, (nv_crtc->fb.tile_flags << 8) | format); +- else +- OUT_RING(evo, format); ++ OUT_RING (evo, nv_crtc->fb.offset >> 8); ++ OUT_RING (evo, 0); ++ OUT_RING (evo, (drm_fb->height << 16) | drm_fb->width); ++ OUT_RING (evo, fb->r_pitch); ++ OUT_RING (evo, fb->r_format); + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLUT_MODE), 1); +- OUT_RING(evo, fb->base.depth == 8 ? +- NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON); ++ OUT_RING (evo, fb->base.depth == 8 ? ++ NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON); + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1); +- OUT_RING(evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR); ++ OUT_RING (evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1); +- OUT_RING(evo, (y << 16) | x); ++ OUT_RING (evo, (y << 16) | x); + + if (nv_crtc->lut.depth != fb->base.depth) { + nv_crtc->lut.depth = fb->base.depth; + nv50_crtc_lut_load(crtc); + } + +- if (update) { +- ret = RING_SPACE(evo, 2); +- if (ret) +- return ret; +- BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); +- OUT_RING(evo, 0); +- FIRE_RING(evo); +- } +- + return 0; + } + +@@ -619,8 +596,7 @@ + struct drm_framebuffer *old_fb) + { + struct drm_device *dev = crtc->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct nouveau_connector *nv_connector = NULL; + uint32_t hsync_dur, vsync_dur, hsync_start_to_end, vsync_start_to_end; +@@ -700,14 +676,25 @@ + nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false); + nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false); + +- return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false, false); ++ return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false); + } + + static int + nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) + { +- return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, true, false); ++ int ret; ++ ++ nv50_display_flip_stop(crtc); ++ ret = nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false); ++ if (ret) ++ return ret; ++ ++ ret = nv50_crtc_wait_complete(crtc); ++ if (ret) ++ return ret; ++ ++ return nv50_display_flip_next(crtc, crtc->fb, NULL); + } + + static int +@@ -715,7 +702,14 @@ + struct drm_framebuffer *fb, + int x, int y, enum mode_set_atomic state) + { +- return nv50_crtc_do_mode_set_base(crtc, fb, x, y, true, true); ++ int ret; ++ ++ nv50_display_flip_stop(crtc); ++ ret = nv50_crtc_do_mode_set_base(crtc, fb, x, y, true); ++ if (ret) ++ return ret; ++ ++ return nv50_crtc_wait_complete(crtc); + } + + static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { +@@ -758,7 +752,7 @@ + nv_crtc->lut.depth = 0; + + ret = nouveau_bo_new(dev, NULL, 4096, 0x100, TTM_PL_FLAG_VRAM, +- 0, 0x0000, false, true, &nv_crtc->lut.nvbo); ++ 0, 0x0000, &nv_crtc->lut.nvbo); + if (!ret) { + ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); + if (!ret) +@@ -784,7 +778,7 @@ + drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); + + ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, +- 0, 0x0000, false, true, &nv_crtc->cursor.nvbo); ++ 0, 0x0000, &nv_crtc->cursor.nvbo); + if (!ret) { + ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); + if (!ret) +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_cursor.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_cursor.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_cursor.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_cursor.c 2011-02-20 23:32:11.000000000 +0100 +@@ -36,9 +36,9 @@ + static void + nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update) + { +- struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; + struct drm_device *dev = nv_crtc->base.dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + int ret; + + NV_DEBUG_KMS(dev, "\n"); +@@ -71,9 +71,9 @@ + static void + nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update) + { +- struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; + struct drm_device *dev = nv_crtc->base.dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + int ret; + + NV_DEBUG_KMS(dev, "\n"); +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_dac.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_dac.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_dac.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_dac.c 2011-02-20 23:32:11.000000000 +0100 +@@ -41,8 +41,7 @@ + { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + int ret; + + if (!nv_encoder->crtc) +@@ -216,8 +215,7 @@ + { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); + uint32_t mode_ctl = 0, mode_ctl2 = 0; + int ret; +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_display.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_display.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_display.c 2011-02-20 23:32:11.000000000 +0100 +@@ -24,6 +24,7 @@ + * + */ + ++#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) + #include "nv50_display.h" + #include "nouveau_crtc.h" + #include "nouveau_encoder.h" +@@ -34,6 +35,7 @@ + #include "drm_crtc_helper.h" + + static void nv50_display_isr(struct drm_device *); ++static void nv50_display_bh(unsigned long); + + static inline int + nv50_sor_nr(struct drm_device *dev) +@@ -172,16 +174,16 @@ + ret = nv50_evo_init(dev); + if (ret) + return ret; +- evo = dev_priv->evo; ++ evo = nv50_display(dev)->master; + + nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); + +- ret = RING_SPACE(evo, 11); ++ ret = RING_SPACE(evo, 15); + if (ret) + return ret; + BEGIN_RING(evo, 0, NV50_EVO_UNK84, 2); + OUT_RING(evo, NV50_EVO_UNK84_NOTIFY_DISABLED); +- OUT_RING(evo, NV50_EVO_DMA_NOTIFY_HANDLE_NONE); ++ OUT_RING(evo, NvEvoSync); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, FB_DMA), 1); + OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK0800), 1); +@@ -190,6 +192,11 @@ + OUT_RING(evo, 0); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1); + OUT_RING(evo, 0); ++ /* required to make display sync channels not hate life */ ++ BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK900), 1); ++ OUT_RING (evo, 0x00000311); ++ BEGIN_RING(evo, 0, NV50_EVO_CRTC(1, UNK900), 1); ++ OUT_RING (evo, 0x00000311); + FIRE_RING(evo); + if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2)) + NV_ERROR(dev, "evo pushbuf stalled\n"); +@@ -201,6 +208,8 @@ + static int nv50_display_disable(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv50_display *disp = nv50_display(dev); ++ struct nouveau_channel *evo = disp->master; + struct drm_crtc *drm_crtc; + int ret, i; + +@@ -212,12 +221,12 @@ + nv50_crtc_blank(crtc, true); + } + +- ret = RING_SPACE(dev_priv->evo, 2); ++ ret = RING_SPACE(evo, 2); + if (ret == 0) { +- BEGIN_RING(dev_priv->evo, 0, NV50_EVO_UPDATE, 1); +- OUT_RING(dev_priv->evo, 0); ++ BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); ++ OUT_RING(evo, 0); + } +- FIRE_RING(dev_priv->evo); ++ FIRE_RING(evo); + + /* Almost like ack'ing a vblank interrupt, maybe in the spirit of + * cleaning up? +@@ -267,10 +276,16 @@ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct dcb_table *dcb = &dev_priv->vbios.dcb; + struct drm_connector *connector, *ct; ++ struct nv50_display *priv; + int ret, i; + + NV_DEBUG_KMS(dev, "\n"); + ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ dev_priv->engine.display.priv = priv; ++ + /* init basic kernel modesetting */ + drm_mode_config_init(dev); + +@@ -330,7 +345,7 @@ + } + } + +- INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); ++ tasklet_init(&priv->tasklet, nv50_display_bh, (unsigned long)dev); + nouveau_irq_register(dev, 26, nv50_display_isr); + + ret = nv50_display_init(dev); +@@ -345,12 +360,131 @@ + void + nv50_display_destroy(struct drm_device *dev) + { ++ struct nv50_display *disp = nv50_display(dev); ++ + NV_DEBUG_KMS(dev, "\n"); + + drm_mode_config_cleanup(dev); + + nv50_display_disable(dev); + nouveau_irq_unregister(dev, 26); ++ kfree(disp); ++} ++ ++void ++nv50_display_flip_stop(struct drm_crtc *crtc) ++{ ++ struct nv50_display *disp = nv50_display(crtc->dev); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index]; ++ struct nouveau_channel *evo = dispc->sync; ++ int ret; ++ ++ ret = RING_SPACE(evo, 8); ++ if (ret) { ++ WARN_ON(1); ++ return; ++ } ++ ++ BEGIN_RING(evo, 0, 0x0084, 1); ++ OUT_RING (evo, 0x00000000); ++ BEGIN_RING(evo, 0, 0x0094, 1); ++ OUT_RING (evo, 0x00000000); ++ BEGIN_RING(evo, 0, 0x00c0, 1); ++ OUT_RING (evo, 0x00000000); ++ BEGIN_RING(evo, 0, 0x0080, 1); ++ OUT_RING (evo, 0x00000000); ++ FIRE_RING (evo); ++} ++ ++int ++nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, ++ struct nouveau_channel *chan) ++{ ++ struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; ++ struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); ++ struct nv50_display *disp = nv50_display(crtc->dev); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index]; ++ struct nouveau_channel *evo = dispc->sync; ++ int ret; ++ ++ ret = RING_SPACE(evo, 24); ++ if (unlikely(ret)) ++ return ret; ++ ++ /* 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); ++ return ret; ++ } ++ ++ if (dev_priv->chipset < 0xc0) { ++ BEGIN_RING(chan, NvSubSw, 0x0060, 2); ++ OUT_RING (chan, NvEvoSema0 + nv_crtc->index); ++ OUT_RING (chan, dispc->sem.offset); ++ BEGIN_RING(chan, NvSubSw, 0x006c, 1); ++ OUT_RING (chan, 0xf00d0000 | dispc->sem.value); ++ BEGIN_RING(chan, NvSubSw, 0x0064, 2); ++ OUT_RING (chan, dispc->sem.offset ^ 0x10); ++ OUT_RING (chan, 0x74b1e000); ++ BEGIN_RING(chan, NvSubSw, 0x0060, 1); ++ if (dev_priv->chipset < 0x84) ++ OUT_RING (chan, NvSema); ++ else ++ OUT_RING (chan, chan->vram_handle); ++ } else { ++ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); ++ OUT_RING (chan, upper_32_bits(offset)); ++ OUT_RING (chan, lower_32_bits(offset)); ++ OUT_RING (chan, 0xf00d0000 | dispc->sem.value); ++ OUT_RING (chan, 0x1002); ++ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); ++ OUT_RING (chan, upper_32_bits(offset)); ++ OUT_RING (chan, lower_32_bits(offset ^ 0x10)); ++ OUT_RING (chan, 0x74b1e000); ++ OUT_RING (chan, 0x1001); ++ } ++ FIRE_RING (chan); ++ } else { ++ nouveau_bo_wr32(dispc->sem.bo, dispc->sem.offset / 4, ++ 0xf00d0000 | dispc->sem.value); ++ } ++ ++ /* queue the flip on the crtc's "display sync" channel */ ++ BEGIN_RING(evo, 0, 0x0100, 1); ++ OUT_RING (evo, 0xfffe0000); ++ BEGIN_RING(evo, 0, 0x0084, 5); ++ OUT_RING (evo, chan ? 0x00000100 : 0x00000010); ++ OUT_RING (evo, dispc->sem.offset); ++ OUT_RING (evo, 0xf00d0000 | dispc->sem.value); ++ OUT_RING (evo, 0x74b1e000); ++ OUT_RING (evo, NvEvoSync); ++ BEGIN_RING(evo, 0, 0x00a0, 2); ++ OUT_RING (evo, 0x00000000); ++ OUT_RING (evo, 0x00000000); ++ BEGIN_RING(evo, 0, 0x00c0, 1); ++ OUT_RING (evo, nv_fb->r_dma); ++ BEGIN_RING(evo, 0, 0x0110, 2); ++ 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, 0); ++ OUT_RING (evo, (fb->height << 16) | fb->width); ++ OUT_RING (evo, nv_fb->r_pitch); ++ OUT_RING (evo, nv_fb->r_format); ++ BEGIN_RING(evo, 0, 0x0080, 1); ++ OUT_RING (evo, 0x00000000); ++ FIRE_RING (evo); ++ ++ dispc->sem.offset ^= 0x10; ++ dispc->sem.value++; ++ return 0; + } + + static u16 +@@ -466,11 +600,12 @@ + nv50_display_unk10_handler(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv50_display *disp = nv50_display(dev); + u32 unk30 = nv_rd32(dev, 0x610030), mc; + int i, crtc, or, type = OUTPUT_ANY; + + NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); +- dev_priv->evo_irq.dcb = NULL; ++ disp->irq.dcb = NULL; + + nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8); + +@@ -541,7 +676,7 @@ + + if (dcb->type == type && (dcb->or & (1 << or))) { + nouveau_bios_run_display_table(dev, dcb, 0, -1); +- dev_priv->evo_irq.dcb = dcb; ++ disp->irq.dcb = dcb; + goto ack; + } + } +@@ -587,15 +722,16 @@ + nv50_display_unk20_handler(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc; ++ struct nv50_display *disp = nv50_display(dev); ++ u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc = 0; + struct dcb_entry *dcb; + int i, crtc, or, type = OUTPUT_ANY; + + NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); +- dcb = dev_priv->evo_irq.dcb; ++ dcb = disp->irq.dcb; + if (dcb) { + nouveau_bios_run_display_table(dev, dcb, 0, -2); +- dev_priv->evo_irq.dcb = NULL; ++ disp->irq.dcb = NULL; + } + + /* CRTC clock change requested? */ +@@ -692,9 +828,9 @@ + nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); + } + +- dev_priv->evo_irq.dcb = dcb; +- dev_priv->evo_irq.pclk = pclk; +- dev_priv->evo_irq.script = script; ++ disp->irq.dcb = dcb; ++ disp->irq.pclk = pclk; ++ disp->irq.script = script; + + ack: + nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20); +@@ -735,13 +871,13 @@ + static void + nv50_display_unk40_handler(struct drm_device *dev) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct dcb_entry *dcb = dev_priv->evo_irq.dcb; +- u16 script = dev_priv->evo_irq.script; +- u32 unk30 = nv_rd32(dev, 0x610030), pclk = dev_priv->evo_irq.pclk; ++ struct nv50_display *disp = nv50_display(dev); ++ struct dcb_entry *dcb = disp->irq.dcb; ++ u16 script = disp->irq.script; ++ u32 unk30 = nv_rd32(dev, 0x610030), pclk = disp->irq.pclk; + + NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); +- dev_priv->evo_irq.dcb = NULL; ++ disp->irq.dcb = NULL; + if (!dcb) + goto ack; + +@@ -754,12 +890,10 @@ + nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) | 8); + } + +-void +-nv50_display_irq_handler_bh(struct work_struct *work) ++static void ++nv50_display_bh(unsigned long data) + { +- struct drm_nouveau_private *dev_priv = +- container_of(work, struct drm_nouveau_private, irq_work); +- struct drm_device *dev = dev_priv->dev; ++ struct drm_device *dev = (struct drm_device *)data; + + for (;;) { + uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); +@@ -807,7 +941,7 @@ + static void + nv50_display_isr(struct drm_device *dev) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv50_display *disp = nv50_display(dev); + uint32_t delayed = 0; + + while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { +@@ -835,8 +969,7 @@ + NV50_PDISPLAY_INTR_1_CLK_UNK40)); + if (clock) { + nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); +- if (!work_pending(&dev_priv->irq_work)) +- queue_work(dev_priv->wq, &dev_priv->irq_work); ++ tasklet_schedule(&disp->tasklet); + delayed |= clock; + intr1 &= ~clock; + } +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_display.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_display.h +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_display.h 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_display.h 2011-02-20 23:32:11.000000000 +0100 +@@ -35,7 +35,36 @@ + #include "nouveau_crtc.h" + #include "nv50_evo.h" + +-void nv50_display_irq_handler_bh(struct work_struct *work); ++struct nv50_display_crtc { ++ struct nouveau_channel *sync; ++ struct { ++ struct nouveau_bo *bo; ++ u32 offset; ++ u16 value; ++ } sem; ++}; ++ ++struct nv50_display { ++ struct nouveau_channel *master; ++ struct nouveau_gpuobj *ntfy; ++ ++ struct nv50_display_crtc crtc[2]; ++ ++ struct tasklet_struct tasklet; ++ struct { ++ struct dcb_entry *dcb; ++ u16 script; ++ u32 pclk; ++ } irq; ++}; ++ ++static inline struct nv50_display * ++nv50_display(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ return dev_priv->engine.display.priv; ++} ++ + int nv50_display_early_init(struct drm_device *dev); + void nv50_display_late_takedown(struct drm_device *dev); + int nv50_display_create(struct drm_device *dev); +@@ -44,4 +73,15 @@ + int nv50_crtc_blank(struct nouveau_crtc *, bool blank); + int nv50_crtc_set_clock(struct drm_device *, int head, int pclk); + ++int nv50_display_flip_next(struct drm_crtc *, struct drm_framebuffer *, ++ struct nouveau_channel *chan); ++void nv50_display_flip_stop(struct drm_crtc *); ++ ++int nv50_evo_init(struct drm_device *dev); ++void nv50_evo_fini(struct drm_device *dev); ++void nv50_evo_dmaobj_init(struct nouveau_gpuobj *, u32 memtype, u64 base, ++ u64 size); ++int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 handle, u32 memtype, ++ u64 base, u64 size, struct nouveau_gpuobj **); ++ + #endif /* __NV50_DISPLAY_H__ */ +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_evo.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_evo.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_evo.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_evo.c 2011-02-20 23:32:11.000000000 +0100 +@@ -27,20 +27,17 @@ + #include "nouveau_drv.h" + #include "nouveau_dma.h" + #include "nouveau_ramht.h" ++#include "nv50_display.h" + + static void + nv50_evo_channel_del(struct nouveau_channel **pevo) + { +- struct drm_nouveau_private *dev_priv; + struct nouveau_channel *evo = *pevo; + + if (!evo) + return; + *pevo = NULL; + +- dev_priv = evo->dev->dev_private; +- dev_priv->evo_alloc &= ~(1 << evo->id); +- + nouveau_gpuobj_channel_takedown(evo); + nouveau_bo_unmap(evo->pushbuf_bo); + nouveau_bo_ref(NULL, &evo->pushbuf_bo); +@@ -51,42 +48,61 @@ + kfree(evo); + } + ++void ++nv50_evo_dmaobj_init(struct nouveau_gpuobj *obj, u32 memtype, u64 base, u64 size) ++{ ++ struct drm_nouveau_private *dev_priv = obj->dev->dev_private; ++ u32 flags5; ++ ++ if (dev_priv->chipset < 0xc0) { ++ /* not supported on 0x50, specified in format mthd */ ++ if (dev_priv->chipset == 0x50) ++ memtype = 0; ++ flags5 = 0x00010000; ++ } else { ++ if (memtype & 0x80000000) ++ flags5 = 0x00000000; /* large pages */ ++ else ++ flags5 = 0x00020000; ++ } ++ ++ nv50_gpuobj_dma_init(obj, 0, 0x3d, base, size, NV_MEM_TARGET_VRAM, ++ NV_MEM_ACCESS_RW, (memtype >> 8) & 0xff, 0); ++ nv_wo32(obj, 0x14, flags5); ++ dev_priv->engine.instmem.flush(obj->dev); ++} ++ + int +-nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 class, u32 name, +- u32 tile_flags, u32 magic_flags, u32 offset, u32 limit, +- u32 flags5) ++nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 handle, u32 memtype, ++ u64 base, u64 size, struct nouveau_gpuobj **pobj) + { +- struct drm_nouveau_private *dev_priv = evo->dev->dev_private; +- struct drm_device *dev = evo->dev; ++ struct nv50_display *disp = nv50_display(evo->dev); + struct nouveau_gpuobj *obj = NULL; + int ret; + +- ret = nouveau_gpuobj_new(dev, dev_priv->evo, 6*4, 32, 0, &obj); ++ ret = nouveau_gpuobj_new(evo->dev, disp->master, 6*4, 32, 0, &obj); + if (ret) + return ret; + obj->engine = NVOBJ_ENGINE_DISPLAY; + +- nv_wo32(obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); +- nv_wo32(obj, 4, limit); +- nv_wo32(obj, 8, offset); +- nv_wo32(obj, 12, 0x00000000); +- nv_wo32(obj, 16, 0x00000000); +- nv_wo32(obj, 20, flags5); +- dev_priv->engine.instmem.flush(dev); ++ nv50_evo_dmaobj_init(obj, memtype, base, size); + +- ret = nouveau_ramht_insert(evo, name, obj); +- nouveau_gpuobj_ref(NULL, &obj); +- if (ret) { +- return ret; +- } ++ ret = nouveau_ramht_insert(evo, handle, obj); ++ if (ret) ++ goto out; + +- return 0; ++ if (pobj) ++ nouveau_gpuobj_ref(obj, pobj); ++out: ++ nouveau_gpuobj_ref(NULL, &obj); ++ return ret; + } + + static int +-nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo) ++nv50_evo_channel_new(struct drm_device *dev, int chid, ++ struct nouveau_channel **pevo) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv50_display *disp = nv50_display(dev); + struct nouveau_channel *evo; + int ret; + +@@ -95,25 +111,13 @@ + return -ENOMEM; + *pevo = evo; + +- for (evo->id = 0; evo->id < 5; evo->id++) { +- if (dev_priv->evo_alloc & (1 << evo->id)) +- continue; +- +- dev_priv->evo_alloc |= (1 << evo->id); +- break; +- } +- +- if (evo->id == 5) { +- kfree(evo); +- return -ENODEV; +- } +- ++ evo->id = chid; + evo->dev = dev; + evo->user_get = 4; + evo->user_put = 0; + + ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, +- false, true, &evo->pushbuf_bo); ++ &evo->pushbuf_bo); + if (ret == 0) + ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM); + if (ret) { +@@ -138,8 +142,8 @@ + } + + /* bind primary evo channel's ramht to the channel */ +- if (dev_priv->evo && evo != dev_priv->evo) +- nouveau_ramht_ref(dev_priv->evo->ramht, &evo->ramht, NULL); ++ if (disp->master && evo != disp->master) ++ nouveau_ramht_ref(disp->master->ramht, &evo->ramht, NULL); + + return 0; + } +@@ -212,21 +216,39 @@ + } + } + ++static void ++nv50_evo_destroy(struct drm_device *dev) ++{ ++ struct nv50_display *disp = nv50_display(dev); ++ int i; ++ ++ for (i = 0; i < 2; i++) { ++ if (disp->crtc[i].sem.bo) { ++ nouveau_bo_unmap(disp->crtc[i].sem.bo); ++ nouveau_bo_ref(NULL, &disp->crtc[i].sem.bo); ++ } ++ nv50_evo_channel_del(&disp->crtc[i].sync); ++ } ++ nouveau_gpuobj_ref(NULL, &disp->ntfy); ++ nv50_evo_channel_del(&disp->master); ++} ++ + static int + nv50_evo_create(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv50_display *disp = nv50_display(dev); + struct nouveau_gpuobj *ramht = NULL; + struct nouveau_channel *evo; +- int ret; ++ int ret, i, j; + + /* create primary evo channel, the one we use for modesetting + * purporses + */ +- ret = nv50_evo_channel_new(dev, &dev_priv->evo); ++ ret = nv50_evo_channel_new(dev, 0, &disp->master); + if (ret) + return ret; +- evo = dev_priv->evo; ++ evo = disp->master; + + /* setup object management on it, any other evo channel will + * use this also as there's no per-channel support on the +@@ -236,109 +258,167 @@ + NVOBJ_FLAG_ZERO_ALLOC, &evo->ramin); + if (ret) { + NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; ++ goto err; + } + + ret = drm_mm_init(&evo->ramin_heap, 0, 32768); + if (ret) { + NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; ++ goto err; + } + + ret = nouveau_gpuobj_new(dev, evo, 4096, 16, 0, &ramht); + if (ret) { + NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; ++ goto err; + } + + ret = nouveau_ramht_new(dev, ramht, &evo->ramht); + nouveau_gpuobj_ref(NULL, &ramht); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; +- } ++ if (ret) ++ goto err; ++ ++ /* not sure exactly what this is.. ++ * ++ * the first dword of the structure is used by nvidia to wait on ++ * full completion of an EVO "update" command. ++ * ++ * method 0x8c on the master evo channel will fill a lot more of ++ * this structure with some undefined info ++ */ ++ ret = nouveau_gpuobj_new(dev, disp->master, 0x1000, 0, ++ NVOBJ_FLAG_ZERO_ALLOC, &disp->ntfy); ++ if (ret) ++ goto err; ++ ++ ret = nv50_evo_dmaobj_new(disp->master, NvEvoSync, 0x0000, ++ disp->ntfy->vinst, disp->ntfy->size, NULL); ++ if (ret) ++ goto err; + + /* create some default objects for the scanout memtypes we support */ +- if (dev_priv->card_type >= NV_C0) { +- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0xfe, 0x19, +- 0, 0xffffffff, 0x00000000); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; +- } ++ ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM, 0x0000, ++ 0, dev_priv->vram_size, NULL); ++ if (ret) ++ goto err; + +- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19, +- 0, dev_priv->vram_size, 0x00020000); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; +- } ++ ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM_LP, 0x80000000, ++ 0, dev_priv->vram_size, NULL); ++ if (ret) ++ goto err; + +- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19, +- 0, dev_priv->vram_size, 0x00000000); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; +- } +- } else { +- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB16, 0x70, 0x19, +- 0, 0xffffffff, 0x00010000); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; +- } ++ ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB32, 0x80000000 | ++ (dev_priv->chipset < 0xc0 ? 0x7a00 : 0xfe00), ++ 0, dev_priv->vram_size, NULL); ++ if (ret) ++ goto err; + ++ ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB16, 0x80000000 | ++ (dev_priv->chipset < 0xc0 ? 0x7000 : 0xfe00), ++ 0, dev_priv->vram_size, NULL); ++ if (ret) ++ goto err; + +- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0x7a, 0x19, +- 0, 0xffffffff, 0x00010000); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; +- } ++ /* create "display sync" channels and other structures we need ++ * to implement page flipping ++ */ ++ for (i = 0; i < 2; i++) { ++ struct nv50_display_crtc *dispc = &disp->crtc[i]; ++ u64 offset; + +- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19, +- 0, dev_priv->vram_size, 0x00010000); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; +- } ++ ret = nv50_evo_channel_new(dev, 1 + i, &dispc->sync); ++ if (ret) ++ goto err; + +- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19, +- 0, dev_priv->vram_size, 0x00010000); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; ++ ret = nouveau_bo_new(dev, NULL, 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); + } ++ ++ if (ret) ++ goto err; ++ ++ ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoSync, 0x0000, ++ offset, 4096, NULL); ++ if (ret) ++ goto err; ++ ++ ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoVRAM_LP, 0x80000000, ++ 0, dev_priv->vram_size, NULL); ++ if (ret) ++ goto err; ++ ++ ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 | ++ (dev_priv->chipset < 0xc0 ? ++ 0x7a00 : 0xfe00), ++ 0, dev_priv->vram_size, NULL); ++ if (ret) ++ goto err; ++ ++ ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 | ++ (dev_priv->chipset < 0xc0 ? ++ 0x7000 : 0xfe00), ++ 0, dev_priv->vram_size, NULL); ++ if (ret) ++ goto err; ++ ++ for (j = 0; j < 4096; j += 4) ++ nouveau_bo_wr32(dispc->sem.bo, j / 4, 0x74b1e000); ++ dispc->sem.offset = 0; + } + + return 0; ++ ++err: ++ nv50_evo_destroy(dev); ++ return ret; + } + + int + nv50_evo_init(struct drm_device *dev) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- int ret; ++ struct nv50_display *disp = nv50_display(dev); ++ int ret, i; + +- if (!dev_priv->evo) { ++ if (!disp->master) { + ret = nv50_evo_create(dev); + if (ret) + return ret; + } + +- return nv50_evo_channel_init(dev_priv->evo); ++ ret = nv50_evo_channel_init(disp->master); ++ if (ret) ++ return ret; ++ ++ for (i = 0; i < 2; i++) { ++ ret = nv50_evo_channel_init(disp->crtc[i].sync); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; + } + + void + nv50_evo_fini(struct drm_device *dev) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv50_display *disp = nv50_display(dev); ++ int i; + +- if (dev_priv->evo) { +- nv50_evo_channel_fini(dev_priv->evo); +- nv50_evo_channel_del(&dev_priv->evo); ++ for (i = 0; i < 2; i++) { ++ if (disp->crtc[i].sync) ++ nv50_evo_channel_fini(disp->crtc[i].sync); + } ++ ++ if (disp->master) ++ nv50_evo_channel_fini(disp->master); ++ ++ nv50_evo_destroy(dev); + } +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_evo.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_evo.h +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_evo.h 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_evo.h 2011-02-20 23:32:11.000000000 +0100 +@@ -27,12 +27,6 @@ + #ifndef __NV50_EVO_H__ + #define __NV50_EVO_H__ + +-int nv50_evo_init(struct drm_device *dev); +-void nv50_evo_fini(struct drm_device *dev); +-int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 class, u32 name, +- u32 tile_flags, u32 magic_flags, +- u32 offset, u32 limit); +- + #define NV50_EVO_UPDATE 0x00000080 + #define NV50_EVO_UNK84 0x00000084 + #define NV50_EVO_UNK84_NOTIFY 0x40000000 +@@ -119,5 +113,7 @@ + /* Both of these are needed, otherwise nothing happens. */ + #define NV50_EVO_CRTC_SCALE_RES1 0x000008d8 + #define NV50_EVO_CRTC_SCALE_RES2 0x000008dc ++#define NV50_EVO_CRTC_UNK900 0x00000900 ++#define NV50_EVO_CRTC_UNK904 0x00000904 + + #endif +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_fb.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_fb.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_fb.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_fb.c 2011-02-20 23:32:11.000000000 +0100 +@@ -8,31 +8,61 @@ + dma_addr_t r100c08; + }; + ++static void ++nv50_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 nv50_fb_priv *priv = pfb->priv; ++ ++ if (pfb->tag_heap.free_stack.next) ++ drm_mm_takedown(&pfb->tag_heap); ++ ++ if (priv->r100c08_page) { ++ pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, ++ PCI_DMA_BIDIRECTIONAL); ++ __free_page(priv->r100c08_page); ++ } ++ ++ kfree(priv); ++ pfb->priv = NULL; ++} ++ + static int + nv50_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 nv50_fb_priv *priv; ++ u32 tagmem; ++ int ret; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; ++ pfb->priv = priv; + + priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!priv->r100c08_page) { +- kfree(priv); ++ nv50_fb_destroy(dev); + return -ENOMEM; + } + + priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) { +- __free_page(priv->r100c08_page); +- kfree(priv); ++ nv50_fb_destroy(dev); + return -EFAULT; + } + +- dev_priv->engine.fb.priv = priv; ++ tagmem = nv_rd32(dev, 0x100320); ++ NV_DEBUG(dev, "%d tags available\n", tagmem); ++ ret = drm_mm_init(&pfb->tag_heap, 0, tagmem); ++ if (ret) { ++ nv50_fb_destroy(dev); ++ return ret; ++ } ++ + return 0; + } + +@@ -81,18 +111,7 @@ + void + nv50_fb_takedown(struct drm_device *dev) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nv50_fb_priv *priv; +- +- priv = dev_priv->engine.fb.priv; +- if (!priv) +- return; +- dev_priv->engine.fb.priv = NULL; +- +- pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, +- PCI_DMA_BIDIRECTIONAL); +- __free_page(priv->r100c08_page); +- kfree(priv); ++ nv50_fb_destroy(dev); + } + + void +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_fifo.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_fifo.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_fifo.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_fifo.c 2011-02-20 23:32:11.000000000 +0100 +@@ -149,6 +149,7 @@ + nv_wr32(dev, 0x3204, 0); + nv_wr32(dev, 0x3210, 0); + nv_wr32(dev, 0x3270, 0); ++ nv_wr32(dev, 0x2044, 0x01003fff); + + /* Enable dummy channels setup by nv50_instmem.c */ + nv50_fifo_channel_enable(dev, 0); +@@ -273,7 +274,7 @@ + nv_wo32(ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | + (4 << 24) /* SEARCH_FULL */ | + (chan->ramht->gpuobj->cinst >> 4)); +- nv_wo32(ramfc, 0x44, 0x2101ffff); ++ nv_wo32(ramfc, 0x44, 0x01003fff); + nv_wo32(ramfc, 0x60, 0x7fffffff); + nv_wo32(ramfc, 0x40, 0x00000000); + nv_wo32(ramfc, 0x7c, 0x30000001); +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_gpio.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_gpio.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_gpio.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_gpio.c 2011-02-20 23:32:11.000000000 +0100 +@@ -137,6 +137,7 @@ + struct nv50_gpio_priv *priv = pgpio->priv; + struct nv50_gpio_handler *gpioh, *tmp; + struct dcb_gpio_entry *gpio; ++ LIST_HEAD(tofree); + unsigned long flags; + + gpio = nouveau_bios_gpio_entry(dev, tag); +@@ -149,10 +150,14 @@ + gpioh->handler != handler || + gpioh->data != data) + continue; +- list_del(&gpioh->head); +- kfree(gpioh); ++ list_move(&gpioh->head, &tofree); + } + spin_unlock_irqrestore(&priv->lock, flags); ++ ++ list_for_each_entry_safe(gpioh, tmp, &tofree, head) { ++ flush_work_sync(&gpioh->work); ++ kfree(gpioh); ++ } + } + + bool +@@ -205,7 +210,6 @@ + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- struct nv50_gpio_priv *priv; + int ret; + + if (!pgpio->priv) { +@@ -213,7 +217,6 @@ + if (ret) + return ret; + } +- priv = pgpio->priv; + + /* disable, and ack any pending gpio interrupts */ + nv_wr32(dev, 0xe050, 0x00000000); +@@ -293,7 +296,7 @@ + continue; + gpioh->inhibit = true; + +- queue_work(dev_priv->wq, &gpioh->work); ++ schedule_work(&gpioh->work); + } + spin_unlock(&priv->lock); + } +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_graph.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_graph.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_graph.c 2011-02-20 23:32:11.000000000 +0100 +@@ -409,12 +409,7 @@ + nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) + { +- struct nouveau_page_flip_state s; +- +- if (!nouveau_finish_page_flip(chan, &s)) { +- /* XXX - Do something here */ +- } +- ++ nouveau_finish_page_flip(chan, NULL); + return 0; + } + +@@ -912,10 +907,10 @@ + printk("\n"); + NV_INFO(dev, "PGRAPH - TRAP_CCACHE %08x %08x %08x %08x" + " %08x %08x %08x\n", +- nv_rd32(dev, 0x405800), nv_rd32(dev, 0x405804), +- nv_rd32(dev, 0x405808), nv_rd32(dev, 0x40580c), +- nv_rd32(dev, 0x405810), nv_rd32(dev, 0x405814), +- nv_rd32(dev, 0x40581c)); ++ nv_rd32(dev, 0x405000), nv_rd32(dev, 0x405004), ++ nv_rd32(dev, 0x405008), nv_rd32(dev, 0x40500c), ++ nv_rd32(dev, 0x405010), nv_rd32(dev, 0x405014), ++ nv_rd32(dev, 0x40501c)); + + } + +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_instmem.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_instmem.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_instmem.c 2011-02-20 23:32:11.000000000 +0100 +@@ -300,7 +300,7 @@ + } + + struct nv50_gpuobj_node { +- struct nouveau_vram *vram; ++ struct nouveau_mem *vram; + struct nouveau_vma chan_vma; + u32 align; + }; +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_sor.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_sor.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_sor.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_sor.c 2011-02-20 23:32:11.000000000 +0100 +@@ -41,8 +41,7 @@ + { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + int ret; + + if (!nv_encoder->crtc) +@@ -184,8 +183,7 @@ + nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) + { +- struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(encoder->dev)->master; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_vm.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_vm.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_vm.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_vm.c 2011-02-20 23:32:11.000000000 +0100 +@@ -31,7 +31,6 @@ + nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, + struct nouveau_gpuobj *pgt[2]) + { +- struct drm_nouveau_private *dev_priv = pgd->dev->dev_private; + u64 phys = 0xdeadcafe00000000ULL; + u32 coverage = 0; + +@@ -58,10 +57,9 @@ + } + + static inline u64 +-nv50_vm_addr(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, +- u64 phys, u32 memtype, u32 target) ++nv50_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) + { +- struct drm_nouveau_private *dev_priv = pgt->dev->dev_private; ++ struct drm_nouveau_private *dev_priv = vma->vm->dev->dev_private; + + phys |= 1; /* present */ + phys |= (u64)memtype << 40; +@@ -85,12 +83,13 @@ + + void + nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, +- struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys) ++ struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) + { ++ u32 comp = (mem->memtype & 0x180) >> 7; + u32 block; + int i; + +- phys = nv50_vm_addr(vma, pgt, phys, mem->memtype, 0); ++ phys = nv50_vm_addr(vma, phys, mem->memtype, 0); + pte <<= 3; + cnt <<= 3; + +@@ -107,6 +106,11 @@ + + phys += block << (vma->node->type - 3); + cnt -= block; ++ if (comp) { ++ u32 tag = mem->tag->start + ((delta >> 16) * comp); ++ offset_h |= (tag << 17); ++ delta += block << (vma->node->type - 3); ++ } + + while (block) { + nv_wo32(pgt, pte + 0, offset_l); +@@ -119,11 +123,11 @@ + + void + nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, +- u32 pte, dma_addr_t *list, u32 cnt) ++ struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) + { + pte <<= 3; + while (cnt--) { +- u64 phys = nv50_vm_addr(vma, pgt, (u64)*list++, 0, 2); ++ u64 phys = nv50_vm_addr(vma, (u64)*list++, mem->memtype, 2); + nv_wo32(pgt, pte + 0, lower_32_bits(phys)); + nv_wo32(pgt, pte + 4, upper_32_bits(phys)); + pte += 8; +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_vram.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_vram.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_vram.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_vram.c 2011-02-20 23:32:11.000000000 +0100 +@@ -48,42 +48,49 @@ + } + + void +-nv50_vram_del(struct drm_device *dev, struct nouveau_vram **pvram) ++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_node *this; +- struct nouveau_vram *vram; ++ struct nouveau_mem *mem; + +- vram = *pvram; +- *pvram = NULL; +- if (unlikely(vram == NULL)) ++ mem = *pmem; ++ *pmem = NULL; ++ if (unlikely(mem == NULL)) + return; + + mutex_lock(&mm->mutex); +- while (!list_empty(&vram->regions)) { +- this = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); ++ while (!list_empty(&mem->regions)) { ++ this = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); + + list_del(&this->rl_entry); + nouveau_mm_put(mm, this); + } ++ ++ if (mem->tag) { ++ drm_mm_put_block(mem->tag); ++ mem->tag = NULL; ++ } + mutex_unlock(&mm->mutex); + +- kfree(vram); ++ kfree(mem); + } + + int + nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, +- u32 type, struct nouveau_vram **pvram) ++ 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_node *r; +- struct nouveau_vram *vram; ++ struct nouveau_mem *mem; ++ int comp = (memtype & 0x300) >> 8; ++ int type = (memtype & 0x07f); + int ret; + + if (!types[type]) +@@ -92,32 +99,46 @@ + align >>= 12; + size_nc >>= 12; + +- vram = kzalloc(sizeof(*vram), GFP_KERNEL); +- if (!vram) ++ mem = kzalloc(sizeof(*mem), GFP_KERNEL); ++ if (!mem) + return -ENOMEM; + +- INIT_LIST_HEAD(&vram->regions); +- vram->dev = dev_priv->dev; +- vram->memtype = type; +- vram->size = size; +- + mutex_lock(&mm->mutex); ++ if (comp) { ++ if (align == 16) { ++ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; ++ int n = (size >> 4) * comp; ++ ++ mem->tag = drm_mm_search_free(&pfb->tag_heap, n, 0, 0); ++ if (mem->tag) ++ mem->tag = drm_mm_get_block(mem->tag, n, 0); ++ } ++ ++ if (unlikely(!mem->tag)) ++ comp = 0; ++ } ++ ++ INIT_LIST_HEAD(&mem->regions); ++ mem->dev = dev_priv->dev; ++ mem->memtype = (comp << 7) | type; ++ mem->size = size; ++ + do { + ret = nouveau_mm_get(mm, types[type], size, size_nc, align, &r); + if (ret) { + mutex_unlock(&mm->mutex); +- nv50_vram_del(dev, &vram); ++ nv50_vram_del(dev, &mem); + return ret; + } + +- list_add_tail(&r->rl_entry, &vram->regions); ++ list_add_tail(&r->rl_entry, &mem->regions); + size -= r->length; + } while (size); + mutex_unlock(&mm->mutex); + +- r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); +- vram->offset = (u64)r->offset << 12; +- *pvram = vram; ++ r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); ++ mem->offset = (u64)r->offset << 12; ++ *pmem = mem; + return 0; + } + +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_fifo.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_fifo.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_fifo.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_fifo.c 2011-02-20 23:32:11.000000000 +0100 +@@ -116,7 +116,7 @@ + + /* allocate vram for control regs, map into polling area */ + ret = nouveau_bo_new(dev, NULL, 0x1000, 0, TTM_PL_FLAG_VRAM, +- 0, 0, true, true, &fifoch->user); ++ 0, 0, &fifoch->user); + if (ret) + goto error; + +@@ -418,6 +418,12 @@ + { + u32 stat = nv_rd32(dev, 0x002100); + ++ if (stat & 0x00000100) { ++ NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); ++ nv_wr32(dev, 0x002100, 0x00000100); ++ stat &= ~0x00000100; ++ } ++ + if (stat & 0x10000000) { + u32 units = nv_rd32(dev, 0x00259c); + u32 u = units; +@@ -446,10 +452,15 @@ + stat &= ~0x20000000; + } + ++ if (stat & 0x40000000) { ++ NV_INFO(dev, "PFIFO: unknown status 0x40000000\n"); ++ nv_mask(dev, 0x002a00, 0x00000000, 0x00000000); ++ stat &= ~0x40000000; ++ } ++ + if (stat) { + NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat); + nv_wr32(dev, 0x002100, stat); ++ nv_wr32(dev, 0x002140, 0); + } +- +- nv_wr32(dev, 0x2140, 0); + } +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_graph.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_graph.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_graph.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_graph.c 2011-02-20 23:32:11.000000000 +0100 +@@ -299,6 +299,14 @@ + } + + static int ++nvc0_graph_mthd_page_flip(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) ++{ ++ nouveau_finish_page_flip(chan, NULL); ++ return 0; ++} ++ ++static int + nvc0_graph_create(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +@@ -395,6 +403,7 @@ + nouveau_irq_register(dev, 25, nvc0_runk140_isr); + 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 */ + NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ + return 0; +@@ -640,7 +649,6 @@ + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; +- struct nvc0_graph_priv *priv; + int ret; + + dev_priv->engine.graph.accel_blocked = true; +@@ -665,7 +673,6 @@ + if (ret) + return ret; + } +- priv = pgraph->priv; + + nvc0_graph_init_obj418880(dev); + nvc0_graph_init_regs(dev); +@@ -730,9 +737,12 @@ + u32 class = nv_rd32(dev, 0x404200 + (subc * 4)); + + if (stat & 0x00000010) { +- NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] subc %d " +- "class 0x%04x mthd 0x%04x data 0x%08x\n", +- chid, inst, subc, class, mthd, data); ++ if (nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) { ++ NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] " ++ "subc %d class 0x%04x mthd 0x%04x " ++ "data 0x%08x\n", ++ chid, inst, subc, class, mthd, data); ++ } + nv_wr32(dev, 0x400100, 0x00000010); + stat &= ~0x00000010; + } +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_vm.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_vm.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_vm.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_vm.c 2011-02-20 23:32:11.000000000 +0100 +@@ -59,7 +59,7 @@ + + void + nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, +- struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys) ++ struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) + { + u32 next = 1 << (vma->node->type - 8); + +@@ -75,11 +75,11 @@ + + void + nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, +- u32 pte, dma_addr_t *list, u32 cnt) ++ struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) + { + pte <<= 3; + while (cnt--) { +- u64 phys = nvc0_vm_addr(vma, *list++, 0, 5); ++ u64 phys = nvc0_vm_addr(vma, *list++, mem->memtype, 5); + nv_wo32(pgt, pte + 0, lower_32_bits(phys)); + nv_wo32(pgt, pte + 4, upper_32_bits(phys)); + pte += 8; +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_vram.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_vram.c +--- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_vram.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_vram.c 2011-02-20 23:32:11.000000000 +0100 +@@ -26,64 +26,78 @@ + #include "nouveau_drv.h" + #include "nouveau_mm.h" + ++/* 0 = unsupported ++ * 1 = non-compressed ++ * 3 = compressed ++ */ ++static const u8 types[256] = { ++ 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, ++ 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, ++ 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, ++ 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, ++ 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3, ++ 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0, ++ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0 ++}; ++ + bool + nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags) + { +- switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) { +- case 0x0000: +- case 0xfe00: +- case 0xdb00: +- case 0x1100: +- return true; +- default: +- break; +- } +- +- return false; ++ u8 memtype = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; ++ return likely((types[memtype] == 1)); + } + + int + nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, +- u32 type, struct nouveau_vram **pvram) ++ 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_node *r; +- struct nouveau_vram *vram; ++ struct nouveau_mem *mem; + int ret; + + size >>= 12; + align >>= 12; + ncmin >>= 12; + +- vram = kzalloc(sizeof(*vram), GFP_KERNEL); +- if (!vram) ++ mem = kzalloc(sizeof(*mem), GFP_KERNEL); ++ if (!mem) + return -ENOMEM; + +- INIT_LIST_HEAD(&vram->regions); +- vram->dev = dev_priv->dev; +- vram->memtype = type; +- vram->size = size; ++ INIT_LIST_HEAD(&mem->regions); ++ mem->dev = dev_priv->dev; ++ mem->memtype = (type & 0xff); ++ mem->size = size; + + mutex_lock(&mm->mutex); + do { + ret = nouveau_mm_get(mm, 1, size, ncmin, align, &r); + if (ret) { + mutex_unlock(&mm->mutex); +- nv50_vram_del(dev, &vram); ++ nv50_vram_del(dev, &mem); + return ret; + } + +- list_add_tail(&r->rl_entry, &vram->regions); ++ list_add_tail(&r->rl_entry, &mem->regions); + size -= r->length; + } while (size); + mutex_unlock(&mm->mutex); + +- r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); +- vram->offset = (u64)r->offset << 12; +- *pvram = vram; ++ r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); ++ mem->offset = (u64)r->offset << 12; ++ *pmem = mem; + return 0; + } + +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/ttm/ttm_bo.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/ttm/ttm_bo.c +--- linux-2.6.38-rc5/drivers/gpu/drm/ttm/ttm_bo.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/ttm/ttm_bo.c 2011-02-20 23:32:11.000000000 +0100 +@@ -406,11 +406,12 @@ + } + + if (bo->mem.mem_type == TTM_PL_SYSTEM) { ++ if (bdev->driver->move_notify) ++ bdev->driver->move_notify(bo, mem); + bo->mem = *mem; + mem->mm_node = NULL; + goto moved; + } +- + } + + if (bdev->driver->move_notify) +diff -Naur linux-2.6.38-rc5/include/drm/nouveau_drm.h linux-2.6.38-rc5.nouveau/include/drm/nouveau_drm.h +--- linux-2.6.38-rc5/include/drm/nouveau_drm.h 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.nouveau/include/drm/nouveau_drm.h 2011-02-20 23:32:11.000000000 +0100 +@@ -94,6 +94,7 @@ + #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) + #define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3) + ++#define NOUVEAU_GEM_TILE_COMP 0x00030000 /* nv50-only */ + #define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00 + #define NOUVEAU_GEM_TILE_16BPP 0x00000001 + #define NOUVEAU_GEM_TILE_32BPP 0x00000002 From c29f8536807de8be25df3f6d7199a658caf71a00 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 02:31:31 +0100 Subject: [PATCH 11/16] linux: fix meta file Signed-off-by: Stephan Raue --- packages/linux/meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/linux/meta b/packages/linux/meta index 9fad95a8ab..0a0e7c83d5 100644 --- a/packages/linux/meta +++ b/packages/linux/meta @@ -24,7 +24,7 @@ PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" PKG_SITE="http://www.kernel.org" -PKG_URL="http://www.kernel.org/pub/linux/kernel/v2.6/$PKG_NAME-$PKG_VERSION.tar.bz2" +#PKG_URL="http://www.kernel.org/pub/linux/kernel/v2.6/$PKG_NAME-$PKG_VERSION.tar.bz2" PKG_URL="http://www.kernel.org/pub/linux/kernel/v2.6/testing/$PKG_NAME-$PKG_VERSION.tar.bz2" PKG_DEPENDS="busybox linux-drivers linux-firmware" PKG_BUILD_DEPENDS="toolchain busybox-hosttools" From 1d8876d335840eb1697745e0bce1ef3d0e5d5fac Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 13:50:53 +0100 Subject: [PATCH 12/16] linux: add patch to add ITE CIR support Signed-off-by: Stephan Raue --- ....6.38-rc5-051_add_ite-cir_driver-0.1.patch | 2998 +++++++++++++++++ projects/ATV/linux/linux.i386.conf | 1 + projects/Generic/linux/linux.i386.conf | 72 +- projects/ION/linux/linux.i386.conf | 64 +- projects/ION/linux/linux.x86_64.conf | 65 +- projects/Intel/linux/linux.i386.conf | 72 +- projects/Intel/linux/linux.x86_64.conf | 72 +- 7 files changed, 3330 insertions(+), 14 deletions(-) create mode 100644 packages/linux/patches/linux-2.6.38-rc5-051_add_ite-cir_driver-0.1.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-051_add_ite-cir_driver-0.1.patch b/packages/linux/patches/linux-2.6.38-rc5-051_add_ite-cir_driver-0.1.patch new file mode 100644 index 0000000000..338523f3d9 --- /dev/null +++ b/packages/linux/patches/linux-2.6.38-rc5-051_add_ite-cir_driver-0.1.patch @@ -0,0 +1,2998 @@ +diff -Naur linux-2.6.38-rc5/drivers/media/rc/ite-cir.c linux-2.6.38-rc5.patch/drivers/media/rc/ite-cir.c +--- linux-2.6.38-rc5/drivers/media/rc/ite-cir.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.38-rc5.patch/drivers/media/rc/ite-cir.c 2011-02-22 03:19:26.753636264 +0100 +@@ -0,0 +1,1334 @@ ++/* ++ * Driver for ITE Tech Inc. IT8712F/IT8512 CIR ++ * ++ * Copyright (C) 2010 Juan J. Garcia de Soria ++ * ++ * Based on nuvoton-cir and lirc_it87 drivers. ++ * ++ * 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 the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ * USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ite-cir.h" ++ ++/* module parameters */ ++ ++/* debug level */ ++static int debug; ++module_param(debug, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(debug, "Enable debugging output"); ++ ++/* low limit for RX carrier freq, Hz, 0 for no RX demodulation */ ++static int rx_low_carrier_freq; ++module_param(rx_low_carrier_freq, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(rx_low_carrier_freq, "Override low RX carrier frequency, Hz, \ ++0 for no RX demodulation"); ++ ++/* high limit for RX carrier freq, Hz, 0 for no RX demodulation */ ++static int rx_high_carrier_freq; ++module_param(rx_high_carrier_freq, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(rx_high_carrier_freq, "Override high RX carrier frequency, \ ++Hz, 0 for no RX demodulation"); ++ ++/* override tx carrier frequency */ ++static int tx_carrier_freq; ++module_param(tx_carrier_freq, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(tx_carrier_freq, "Override TX carrier frequency, Hz"); ++ ++/* override tx duty cycle */ ++static int tx_duty_cycle; ++module_param(tx_duty_cycle, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(tx_duty_cycle, "Override TX duty cycle, 1-100"); ++ ++/* override default sample period */ ++static long sample_period; ++module_param(sample_period, long, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(sample_period, "Override carrier sample period, \ ++us"); ++ ++/* override detected model id */ ++static int model_number = -1; ++module_param(model_number, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(model_number, "Use this model number, don't \ ++autodetect"); ++ ++ ++/* forward declaration */ ++static void ite_set_carrier_params(struct ite_dev *dev); ++ ++ ++/* IT8712F HW-specific functions */ ++ ++/* retrieve a bitmask of the current causes for a pending interrupt; this may ++ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN ++ * */ ++static int it87_get_irq_causes(struct ite_dev *dev) ++{ ++ u8 iflags; ++ int ret = 0; ++ ++ /* read the interrupt flags */ ++ iflags = inb(dev->cir_addr + IT87_IIR) & IT87_II; ++ ++ switch (iflags) { ++ case IT87_II_RXDS: ++ ret = ITE_IRQ_RX_FIFO; ++ break; ++ case IT87_II_RXFO: ++ ret = ITE_IRQ_RX_FIFO_OVERRUN; ++ break; ++ case IT87_II_TXLDL: ++ ret = ITE_IRQ_TX_FIFO; ++ break; ++ } ++ ++ return ret; ++} ++ ++/* set the carrier parameters; to be called with the spinlock held */ ++static void it87_set_carrier_params(struct ite_dev *dev, bool high_freq, ++ bool use_demodulator, u8 carrier_freq_bits, u8 allowance_bits, ++ u8 pulse_width_bits) ++{ ++ u8 val; ++ ++ /* program the RCR register */ ++ val = inb(dev->cir_addr + IT87_RCR) ++ & ~(IT87_HCFS | IT87_RXEND | IT87_RXDCR); ++ ++ if (high_freq) ++ val |= IT87_HCFS; ++ ++ if (use_demodulator) ++ val |= IT87_RXEND; ++ ++ val |= allowance_bits; ++ ++ outb(val, dev->cir_addr + IT87_RCR); ++ ++ /* program the TCR2 register */ ++ outb((carrier_freq_bits << IT87_CFQ_SHIFT) | pulse_width_bits, ++ dev->cir_addr + IT87_TCR2); ++} ++ ++/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock ++ * held */ ++static int it87_get_rx_bytes(struct ite_dev *dev, u8 *buf, int buf_size) ++{ ++ int fifo, read = 0; ++ ++ /* read how many bytes are still in the FIFO */ ++ fifo = inb(dev->cir_addr + IT87_RSR) & IT87_RXBFC; ++ ++ while (fifo > 0 && buf_size > 0) { ++ *(buf++) = inb(dev->cir_addr + IT87_DR); ++ fifo--; ++ read++; ++ buf_size--; ++ } ++ ++ return read; ++} ++ ++/* return how many bytes we can send through the FIFO; this will be called ++ * with the device spinlock NOT HELD while waiting for the TX FIFO to get ++ * empty; let's expect this won't be a problem */ ++static int it87_get_tx_free_slots(struct ite_dev *dev) ++{ ++ return inb(dev->cir_addr + IT87_TSR) & IT87_TXBFC; ++} ++ ++/* put a byte to the TX fifo; this should be called with the spinlock held */ ++static void it87_put_tx_byte(struct ite_dev *dev, u8 value) ++{ ++ outb(value, dev->cir_addr + IT87_DR); ++} ++ ++/* idle the receiver so that we won't receive samples until another ++ pulse is detected; this must be called with the device spinlock held */ ++static void it87_idle_rx(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable streaming by clearing RXACT writing it as 1 */ ++ outb(inb(dev->cir_addr + IT87_RCR) | IT87_RXACT, ++ dev->cir_addr + IT87_RCR); ++ ++ /* clear the FIFO */ ++ outb(inb(dev->cir_addr + IT87_TCR1) | IT87_FIFOCLR, ++ dev->cir_addr + IT87_TCR1); ++} ++ ++/* disable the receiver; this must be called with the device spinlock held */ ++static void it87_disable_rx(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable the receiver interrupts */ ++ outb(inb(dev->cir_addr + IT87_IER) & ~(IT87_RDAIE | IT87_RFOIE), ++ dev->cir_addr + IT87_IER); ++ ++ /* disable the receiver */ ++ outb(inb(dev->cir_addr + IT87_RCR) & ~IT87_RXEN, ++ dev->cir_addr + IT87_RCR); ++ ++ /* clear the FIFO and RXACT (actually RXACT should have been cleared ++ * in the previous outb() call) */ ++ it87_idle_rx(dev); ++} ++ ++/* enable the receiver; this must be called with the device spinlock held */ ++static void it87_enable_rx(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* enable the receiver by setting RXEN */ ++ outb(inb(dev->cir_addr + IT87_RCR) | IT87_RXEN, ++ dev->cir_addr + IT87_RCR); ++ ++ /* just prepare it to idle for the next reception */ ++ it87_idle_rx(dev); ++ ++ /* enable the receiver interrupts and master enable flag */ ++ outb(inb(dev->cir_addr + IT87_IER) ++ | IT87_RDAIE | IT87_RFOIE | IT87_IEC, ++ dev->cir_addr + IT87_IER); ++} ++ ++/* disable the transmitter interrupt; this must be called with the device ++ * spinlock held */ ++static void it87_disable_tx_interrupt(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable the transmitter interrupts */ ++ outb(inb(dev->cir_addr + IT87_IER) & ~IT87_TLDLIE, ++ dev->cir_addr + IT87_IER); ++} ++ ++/* enable the transmitter interrupt; this must be called with the device ++ * spinlock held */ ++static void it87_enable_tx_interrupt(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* enable the transmitter interrupts and master enable flag */ ++ outb(inb(dev->cir_addr + IT87_IER) ++ | IT87_TLDLIE | IT87_IEC, ++ dev->cir_addr + IT87_IER); ++} ++ ++/* disable the device; this must be called with the device spinlock held */ ++static void it87_disable(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* clear out all interrupt enable flags */ ++ outb(inb(dev->cir_addr + IT87_IER) & ~(IT87_IEC | IT87_RFOIE | ++ IT87_RDAIE | IT87_TLDLIE), dev->cir_addr + IT87_IER); ++ ++ /* disable the receiver */ ++ it87_disable_rx(dev); ++ ++ /* erase the FIFO */ ++ outb(IT87_FIFOCLR | inb(dev->cir_addr + IT87_TCR1), ++ dev->cir_addr + IT87_TCR1); ++} ++ ++/* initialize the hardware */ ++static void it87_init_hardware(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* enable just the baud rate divisor register, ++ disabling all the interrupts at the same time */ ++ outb((inb(dev->cir_addr + IT87_IER) & ~(IT87_IEC | IT87_RFOIE | ++ IT87_RDAIE | IT87_TLDLIE)) | IT87_BR, ++ dev->cir_addr + IT87_IER); ++ ++ /* write out the baud rate divisor */ ++ outb(ITE_BAUDRATE_DIVISOR & 0xff, dev->cir_addr + IT87_BDLR); ++ outb((ITE_BAUDRATE_DIVISOR >> 8) & 0xff, dev->cir_addr + IT87_BDHR); ++ ++ /* disable the baud rate divisor register again */ ++ outb(inb(dev->cir_addr + IT87_IER) & ~IT87_BR, ++ dev->cir_addr + IT87_IER); ++ ++ /* program the RCR register defaults */ ++ outb(ITE_RXDCR_DEFAULT, dev->cir_addr + IT87_RCR); ++ ++ /* program the TCR1 register */ ++ outb(IT87_TXMPM_DEFAULT ++ | IT87_TXENDF ++ | IT87_TXRLE ++ | IT87_FIFOTL_DEFAULT ++ | IT87_FIFOCLR, dev->cir_addr + IT87_TCR1); ++ ++ /* program the carrier parameters */ ++ ite_set_carrier_params(dev); ++} ++ ++/* IT8512F on ITE8708 HW-specific functions */ ++ ++/* retrieve a bitmask of the current causes for a pending interrupt; this may ++ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN ++ * */ ++static int it8708_get_irq_causes(struct ite_dev *dev) ++{ ++ u8 iflags; ++ int ret = 0; ++ ++ /* read the interrupt flags */ ++ iflags = inb(dev->cir_addr + IT8708_C0IIR); ++ ++ if (iflags & IT85_TLDLI) ++ ret |= ITE_IRQ_TX_FIFO; ++ if (iflags & IT85_RDAI) ++ ret |= ITE_IRQ_RX_FIFO; ++ if (iflags & IT85_RFOI) ++ ret |= ITE_IRQ_RX_FIFO_OVERRUN; ++ ++ return ret; ++} ++ ++/* set the carrier parameters; to be called with the spinlock held */ ++static void it8708_set_carrier_params(struct ite_dev *dev, bool high_freq, ++ bool use_demodulator, u8 carrier_freq_bits, u8 allowance_bits, ++ u8 pulse_width_bits) ++{ ++ u8 val; ++ ++ /* program the C0CFR register, with HRAE=1 */ ++ outb(inb(dev->cir_addr + IT8708_BANKSEL) | IT8708_HRAE, dev->cir_addr ++ + IT8708_BANKSEL); ++ ++ val = (inb(dev->cir_addr + IT8708_C0CFR) ++ & ~(IT85_HCFS | IT85_CFQ)) | carrier_freq_bits; ++ ++ if (high_freq) ++ val |= IT85_HCFS; ++ ++ outb(val, dev->cir_addr + IT8708_C0CFR); ++ ++ outb(inb(dev->cir_addr + IT8708_BANKSEL) & ~IT8708_HRAE, dev->cir_addr ++ + IT8708_BANKSEL); ++ ++ /* program the C0RCR register */ ++ val = inb(dev->cir_addr + IT8708_C0RCR) ++ & ~(IT85_RXEND | IT85_RXDCR); ++ ++ if (use_demodulator) ++ val |= IT85_RXEND; ++ ++ val |= allowance_bits; ++ ++ outb(val, dev->cir_addr + IT8708_C0RCR); ++ ++ /* program the C0TCR register */ ++ val = inb(dev->cir_addr + IT8708_C0TCR) & ~IT85_TXMPW; ++ val |= pulse_width_bits; ++ outb(val, dev->cir_addr + IT8708_C0TCR); ++} ++ ++/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock ++ * held */ ++static int it8708_get_rx_bytes(struct ite_dev *dev, u8 *buf, int buf_size) ++{ ++ int fifo, read = 0; ++ ++ /* read how many bytes are still in the FIFO */ ++ fifo = inb(dev->cir_addr + IT8708_C0RFSR) & IT85_RXFBC; ++ ++ while (fifo > 0 && buf_size > 0) { ++ *(buf++) = inb(dev->cir_addr + IT8708_C0DR); ++ fifo--; ++ read++; ++ buf_size--; ++ } ++ ++ return read; ++} ++ ++/* return how many bytes we can send through the FIFO; this will be called ++ * with the device spinlock NOT HELD while waiting for the TX FIFO to get ++ * empty; let's expect this won't be a problem */ ++static int it8708_get_tx_free_slots(struct ite_dev *dev) ++{ ++ return inb(dev->cir_addr + IT8708_C0TFSR) & IT85_TXFBC; ++} ++ ++/* put a byte to the TX fifo; this should be called with the spinlock held */ ++static void it8708_put_tx_byte(struct ite_dev *dev, u8 value) ++{ ++ outb(value, dev->cir_addr + IT8708_C0DR); ++} ++ ++/* idle the receiver so that we won't receive samples until another ++ pulse is detected; this must be called with the device spinlock held */ ++static void it8708_idle_rx(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable streaming by clearing RXACT writing it as 1 */ ++ outb(inb(dev->cir_addr + IT8708_C0RCR) | IT85_RXACT, ++ dev->cir_addr + IT8708_C0RCR); ++ ++ /* clear the FIFO */ ++ outb(inb(dev->cir_addr + IT8708_C0MSTCR) | IT85_FIFOCLR, ++ dev->cir_addr + IT8708_C0MSTCR); ++} ++ ++/* disable the receiver; this must be called with the device spinlock held */ ++static void it8708_disable_rx(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable the receiver interrupts */ ++ outb(inb(dev->cir_addr + IT8708_C0IER) & ~(IT85_RDAIE | IT85_RFOIE), ++ dev->cir_addr + IT8708_C0IER); ++ ++ /* disable the receiver */ ++ outb(inb(dev->cir_addr + IT8708_C0RCR) & ~IT85_RXEN, ++ dev->cir_addr + IT8708_C0RCR); ++ ++ /* clear the FIFO and RXACT (actually RXACT should have been cleared ++ * in the previous outb() call) */ ++ it8708_idle_rx(dev); ++} ++ ++/* enable the receiver; this must be called with the device spinlock held */ ++static void it8708_enable_rx(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* enable the receiver by setting RXEN */ ++ outb(inb(dev->cir_addr + IT8708_C0RCR) | IT85_RXEN, ++ dev->cir_addr + IT8708_C0RCR); ++ ++ /* just prepare it to idle for the next reception */ ++ it8708_idle_rx(dev); ++ ++ /* enable the receiver interrupts and master enable flag */ ++ outb(inb(dev->cir_addr + IT8708_C0IER) ++ | IT85_RDAIE | IT85_RFOIE | IT85_IEC, ++ dev->cir_addr + IT8708_C0IER); ++} ++ ++/* disable the transmitter interrupt; this must be called with the device ++ * spinlock held */ ++static void it8708_disable_tx_interrupt(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable the transmitter interrupts */ ++ outb(inb(dev->cir_addr + IT8708_C0IER) & ~IT85_TLDLIE, ++ dev->cir_addr + IT8708_C0IER); ++} ++ ++/* enable the transmitter interrupt; this must be called with the device ++ * spinlock held */ ++static void it8708_enable_tx_interrupt(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* enable the transmitter interrupts and master enable flag */ ++ outb(inb(dev->cir_addr + IT8708_C0IER) ++ | IT85_TLDLIE | IT85_IEC, ++ dev->cir_addr + IT8708_C0IER); ++} ++ ++/* disable the device; this must be called with the device spinlock held */ ++static void it8708_disable(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* clear out all interrupt enable flags */ ++ outb(inb(dev->cir_addr + IT8708_C0IER) & ~(IT85_IEC | IT85_RFOIE | ++ IT85_RDAIE | IT85_TLDLIE), dev->cir_addr + IT8708_C0IER); ++ ++ /* disable the receiver */ ++ it8708_disable_rx(dev); ++ ++ /* erase the FIFO */ ++ outb(IT85_FIFOCLR | inb(dev->cir_addr + IT8708_C0MSTCR), ++ dev->cir_addr + IT8708_C0MSTCR); ++} ++ ++/* initialize the hardware */ ++static void it8708_init_hardware(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable all the interrupts */ ++ outb(inb(dev->cir_addr + IT8708_C0IER) & ~(IT85_IEC | IT85_RFOIE | ++ IT85_RDAIE | IT85_TLDLIE), dev->cir_addr + IT8708_C0IER); ++ ++ /* program the baud rate divisor */ ++ outb(inb(dev->cir_addr + IT8708_BANKSEL) | IT8708_HRAE, dev->cir_addr ++ + IT8708_BANKSEL); ++ ++ outb(ITE_BAUDRATE_DIVISOR & 0xff, dev->cir_addr + IT8708_C0BDLR); ++ outb((ITE_BAUDRATE_DIVISOR >> 8) & 0xff, ++ dev->cir_addr + IT8708_C0BDHR); ++ ++ outb(inb(dev->cir_addr + IT8708_BANKSEL) & ~IT8708_HRAE, dev->cir_addr ++ + IT8708_BANKSEL); ++ ++ ++ /* program the C0MSTCR register defaults */ ++ outb((inb(dev->cir_addr + IT8708_C0MSTCR) & ~(IT85_ILSEL | IT85_ILE | ++ IT85_FIFOTL | IT85_FIFOCLR | IT85_RESET)) | ++ IT85_FIFOTL_DEFAULT, dev->cir_addr + IT8708_C0MSTCR); ++ ++ /* program the C0RCR register defaults */ ++ outb((inb(dev->cir_addr + IT8708_C0RCR) & ~(IT85_RXEN | IT85_RDWOS | ++ IT85_RXEND | IT85_RXACT | IT85_RXDCR)) | ++ ITE_RXDCR_DEFAULT, dev->cir_addr + IT8708_C0RCR); ++ ++ /* program the C0TCR register defaults */ ++ outb((inb(dev->cir_addr + IT8708_C0TCR) & ~(IT85_TXMPM | IT85_TXMPW)) ++ | IT85_TXRLE | IT85_TXENDF | IT85_TXMPM_DEFAULT | ++ IT85_TXMPW_DEFAULT, dev->cir_addr + IT8708_C0TCR); ++ ++ /* program the carrier parameters */ ++ ite_set_carrier_params(dev); ++} ++ ++ ++ ++ ++/* supported models and their parameters */ ++static const struct ite_dev_params ite_dev_descs[] = { ++ { /* 0: ITE8704, ITE8713 */ ++ .model = "ITE8704/ITE8713 CIR transceiver", ++ .io_region_size = IT87_IOREG_LENGTH, ++ .hw_tx_capable = true, ++ .sample_period = (u32)(1000000000ULL / 115200), ++ .tx_carrier_freq = 38000, ++ .tx_duty_cycle = 33, ++ .rx_low_carrier_freq = 0, ++ .rx_high_carrier_freq = 0, ++ ++ /* operations */ ++ .get_irq_causes = it87_get_irq_causes, ++ .enable_rx = it87_enable_rx, ++ .idle_rx = it87_idle_rx, ++ .disable_rx = it87_idle_rx, ++ .get_rx_bytes = it87_get_rx_bytes, ++ .enable_tx_interrupt = it87_enable_tx_interrupt, ++ .disable_tx_interrupt = it87_disable_tx_interrupt, ++ .get_tx_free_slots = it87_get_tx_free_slots, ++ .put_tx_byte = it87_put_tx_byte, ++ .disable = it87_disable, ++ .init_hardware = it87_init_hardware, ++ .set_carrier_params = it87_set_carrier_params, ++ }, ++ { /* 1: ITE8708 */ ++ .model = "ITE8708 CIR transceiver", ++ .io_region_size = IT8708_IOREG_LENGTH, ++ .hw_tx_capable = true, ++ .sample_period = (u32)(1000000000ULL / 115200), ++ .tx_carrier_freq = 38000, ++ .tx_duty_cycle = 33, ++ .rx_low_carrier_freq = 0, ++ .rx_high_carrier_freq = 0, ++ ++ /* operations */ ++ .get_irq_causes = it8708_get_irq_causes, ++ .enable_rx = it8708_enable_rx, ++ .idle_rx = it8708_idle_rx, ++ .disable_rx = it8708_idle_rx, ++ .get_rx_bytes = it8708_get_rx_bytes, ++ .enable_tx_interrupt = it8708_enable_tx_interrupt, ++ .disable_tx_interrupt = it8708_disable_tx_interrupt, ++ .get_tx_free_slots = it8708_get_tx_free_slots, ++ .put_tx_byte = it8708_put_tx_byte, ++ .disable = it8708_disable, ++ .init_hardware = it8708_init_hardware, ++ .set_carrier_params = it8708_set_carrier_params, ++ }, ++}; ++ ++/* HW-independent code functions */ ++ ++/* check whether carrier frequency is high frequency */ ++static inline bool ite_is_high_carrier_freq(unsigned int freq) ++{ ++ return freq >= ITE_HCF_MIN_CARRIER_FREQ; ++} ++ ++/* get the bits required to program the carrier frequency in CFQ bits, ++ * unshifted */ ++static u8 ite_get_carrier_freq_bits(unsigned int freq) ++{ ++ if (ite_is_high_carrier_freq(freq)) { ++ if (freq < 425000) ++ return ITE_CFQ_400; ++ else if (freq < 465000) ++ return ITE_CFQ_450; ++ else if (freq < 490000) ++ return ITE_CFQ_480; ++ else ++ return ITE_CFQ_500; ++ } else { ++ /* trim to limits */ ++ if (freq < ITE_LCF_MIN_CARRIER_FREQ) ++ freq = ITE_LCF_MIN_CARRIER_FREQ; ++ if (freq > ITE_LCF_MAX_CARRIER_FREQ) ++ freq = ITE_LCF_MAX_CARRIER_FREQ; ++ ++ /* convert to kHz and subtract the base freq */ ++ freq = DIV_ROUND_CLOSEST(freq - ITE_LCF_MIN_CARRIER_FREQ, ++ 1000); ++ ++ return (u8) freq; ++ } ++} ++ ++/* get the bits required to program the pulse with in TXMPW */ ++static u8 ite_get_pulse_width_bits(unsigned int freq, int duty_cycle) ++{ ++ unsigned long period_ns, on_ns; ++ ++ /* sanitize freq into range */ ++ if (freq < ITE_LCF_MIN_CARRIER_FREQ) ++ freq = ITE_LCF_MIN_CARRIER_FREQ; ++ if (freq > ITE_HCF_MAX_CARRIER_FREQ) ++ freq = ITE_HCF_MAX_CARRIER_FREQ; ++ ++ period_ns = 1000000000UL / freq; ++ on_ns = period_ns * duty_cycle / 100; ++ ++ if (ite_is_high_carrier_freq(freq)) { ++ if (on_ns < 750) ++ return ITE_TXMPW_A; ++ else if (on_ns < 850) ++ return ITE_TXMPW_B; ++ else if (on_ns < 950) ++ return ITE_TXMPW_C; ++ else if (on_ns < 1080) ++ return ITE_TXMPW_D; ++ else ++ return ITE_TXMPW_E; ++ } else { ++ if (on_ns < 6500) ++ return ITE_TXMPW_A; ++ else if (on_ns < 7850) ++ return ITE_TXMPW_B; ++ else if (on_ns < 9650) ++ return ITE_TXMPW_C; ++ else if (on_ns < 11950) ++ return ITE_TXMPW_D; ++ else ++ return ITE_TXMPW_E; ++ } ++} ++ ++/* set all the rx/tx carrier parameters; this must be called with the device ++ * spinlock held */ ++static void ite_set_carrier_params(struct ite_dev *dev) ++{ ++ unsigned int freq, low_freq, high_freq; ++ int allowance; ++ bool use_demodulator; ++ bool for_tx = dev->transmitting; ++ ++ ite_dbg("%s called", __func__); ++ ++ if (for_tx) { ++ /* we don't need no stinking calculations */ ++ freq = dev->params.tx_carrier_freq; ++ allowance = ITE_RXDCR_DEFAULT; ++ use_demodulator = false; ++ } else { ++ low_freq = dev->params.rx_low_carrier_freq; ++ high_freq = dev->params.rx_high_carrier_freq; ++ ++ if (low_freq == 0) { ++ /* don't demodulate */ ++ freq = ITE_DEFAULT_CARRIER_FREQ; ++ allowance = ITE_RXDCR_DEFAULT; ++ use_demodulator = false; ++ } else { ++ /* calculate the middle freq */ ++ freq = (low_freq + high_freq) / 2; ++ ++ /* calculate the allowance */ ++ allowance = DIV_ROUND_CLOSEST( ++ 10000 * (high_freq - low_freq), ++ ITE_RXDCR_PER_10000_STEP * ++ (high_freq + low_freq)); ++ ++ if (allowance < 1) ++ allowance = 1; ++ if (allowance > ITE_RXDCR_MAX) ++ allowance = ITE_RXDCR_MAX; ++ } ++ } ++ ++ /* set the carrier parameters in a device-dependent way */ ++ dev->params.set_carrier_params(dev, ite_is_high_carrier_freq(freq), ++ use_demodulator, ite_get_carrier_freq_bits(freq), allowance, ++ ite_get_pulse_width_bits(freq, dev->params.tx_duty_cycle)); ++} ++ ++/* decode raw bytes as received by the hardware, and push them to the ir-core ++ * layer */ ++static void ite_decode_bytes(struct ite_dev *dev, const u8 *data, int ++ length) ++{ ++ u32 sample_period; ++ unsigned long *ldata; ++ unsigned int next_one, next_zero, size; ++ DEFINE_IR_RAW_EVENT(ev); ++ ++ if (length == 0) ++ return; ++ ++ sample_period = dev->params.sample_period; ++ ldata = (unsigned long *) data; ++ size = length << 3; ++ next_one = generic_find_next_le_bit(ldata, size, 0); ++ if (next_one > 0) { ++ ev.pulse = true; ++ ev.duration = ITE_BITS_TO_NS(next_one, sample_period); ++ ir_raw_event_store_with_filter(dev->rdev, &ev); ++ } ++ ++ while (next_one < size) { ++ next_zero = generic_find_next_zero_le_bit(ldata, ++ size, next_one + 1); ++ ev.pulse = false; ++ ev.duration = ITE_BITS_TO_NS(next_zero - next_one, ++ sample_period); ++ ir_raw_event_store_with_filter(dev->rdev, &ev); ++ ++ if (next_zero < size) { ++ next_one = generic_find_next_le_bit(ldata, ++ size, next_zero + 1); ++ ev.pulse = true; ++ ev.duration = ITE_BITS_TO_NS(next_one - next_zero, ++ sample_period); ++ ir_raw_event_store_with_filter(dev->rdev, &ev); ++ } else ++ next_one = size; ++ } ++ ++ ir_raw_event_handle(dev->rdev); ++ ++ ite_dbg_verbose("decoded %d bytes.", length); ++} ++ ++/* interrupt service routine for incoming and outgoing CIR data */ ++static irqreturn_t ite_cir_isr(int irq, void *data) ++{ ++ struct ite_dev *dev = data; ++ unsigned long flags; ++ irqreturn_t ret = IRQ_RETVAL(IRQ_NONE); ++ u8 rx_buf[ITE_RX_FIFO_LEN]; ++ int rx_bytes; ++ int iflags; ++ ++ ite_dbg_verbose("%s firing", __func__); ++ ++ /* grab the spinlock */ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* read the interrupt flags */ ++ iflags = dev->params.get_irq_causes(dev); ++ ++ /* check for the receive interrupt */ ++ if (iflags & (ITE_IRQ_RX_FIFO | ITE_IRQ_RX_FIFO_OVERRUN)) { ++ /* read the FIFO bytes */ ++ rx_bytes = dev->params.get_rx_bytes(dev, rx_buf, ++ ITE_RX_FIFO_LEN); ++ ++ if (rx_bytes > 0) { ++ /* drop the spinlock, since the ir-core layer ++ * may call us back again through ++ * ite_s_idle() */ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ /* decode the data we've just received */ ++ ite_decode_bytes(dev, rx_buf, rx_bytes); ++ ++ /* reacquire the spinlock */ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* mark the interrupt as serviced */ ++ ret = IRQ_RETVAL(IRQ_HANDLED); ++ } ++ } else if (iflags & ITE_IRQ_TX_FIFO) { ++ /* FIFO space available interrupt */ ++ ite_dbg_verbose("got interrupt for TX FIFO"); ++ ++ /* wake any sleeping transmitter */ ++ wake_up_interruptible(&dev->tx_queue); ++ ++ /* mark the interrupt as serviced */ ++ ret = IRQ_RETVAL(IRQ_HANDLED); ++ } ++ ++ /* drop the spinlock */ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ ite_dbg_verbose("%s done returning %d", __func__, (int) ret); ++ ++ return ret; ++} ++ ++ ++/* set the rx carrier freq range, guess it's in Hz... */ ++static int ite_set_rx_carrier_range(struct rc_dev *rcdev, u32 carrier_low, u32 ++ carrier_high) ++{ ++ unsigned long flags; ++ struct ite_dev *dev = rcdev->priv; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ dev->params.rx_low_carrier_freq = carrier_low; ++ dev->params.rx_high_carrier_freq = carrier_high; ++ ite_set_carrier_params(dev); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ return 0; ++} ++ ++ ++/* set the tx carrier freq, guess it's in Hz... */ ++static int ite_set_tx_carrier(struct rc_dev *rcdev, u32 carrier) ++{ ++ unsigned long flags; ++ struct ite_dev *dev = rcdev->priv; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ dev->params.tx_carrier_freq = carrier; ++ ite_set_carrier_params(dev); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ return 0; ++} ++ ++/* set the tx duty cycle by controlling the pulse width */ ++static int ite_set_tx_duty_cycle(struct rc_dev *rcdev, u32 duty_cycle) ++{ ++ unsigned long flags; ++ struct ite_dev *dev = rcdev->priv; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ dev->params.tx_duty_cycle = duty_cycle; ++ ite_set_carrier_params(dev); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ return 0; ++} ++ ++/* transmit out IR pulses; what you get here is a batch of alternating ++ * pulse/space/pulse/space lengths that we should write out completely through ++ * the FIFO, blocking on a full FIFO */ ++static int ite_tx_ir(struct rc_dev *rcdev, int *txbuf, u32 n) ++{ ++ unsigned long flags; ++ struct ite_dev *dev = rcdev->priv; ++ bool is_pulse = false; ++ int remaining_us, fifo_avail, fifo_remaining, last_idx = 0; ++ int max_rle_us, next_rle_us; ++ int ret = n; ++ u8 last_sent[ITE_TX_FIFO_LEN]; ++ u8 val; ++ ++ ite_dbg("%s called", __func__); ++ ++ /* clear the array just in case */ ++ memset(last_sent, 0, ARRAY_SIZE(last_sent)); ++ ++ /* n comes in bytes; convert to ints */ ++ n /= sizeof(int); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* let everybody know we're now transmitting */ ++ dev->transmitting = true; ++ ++ /* and set the carrier values for transmission */ ++ ite_set_carrier_params(dev); ++ ++ /* calculate how much time we can send in one byte */ ++ max_rle_us = (ITE_BAUDRATE_DIVISOR * dev->params.sample_period * ++ ITE_TX_MAX_RLE) / 1000; ++ ++ /* disable the receiver */ ++ dev->params.disable_rx(dev); ++ ++ /* this is where we'll begin filling in the FIFO, until it's full. ++ * then we'll just activate the interrupt, wait for it to wake us up ++ * again, disable it, continue filling the FIFO... until everything ++ * has been pushed out */ ++ fifo_avail = dev->params.get_tx_free_slots(dev); ++ ++ while (n > 0 && dev->in_use) { ++ /* transmit the next sample */ ++ is_pulse = !is_pulse; ++ remaining_us = *(txbuf++); ++ n--; ++ ++ /* repeat while the pulse is non-zero length */ ++ while (remaining_us > 0 && dev->in_use) { ++ if (remaining_us > max_rle_us) ++ next_rle_us = max_rle_us; ++ else ++ next_rle_us = remaining_us; ++ remaining_us -= next_rle_us; ++ ++ /* check what's the length we have to pump out */ ++ val = (ITE_TX_MAX_RLE * next_rle_us) / max_rle_us; ++ ++ /* put it into the sent buffer */ ++ last_sent[last_idx++] = val; ++ last_idx &= (ITE_TX_FIFO_LEN); ++ ++ /* encode it for 7 bits */ ++ val = (val - 1) & ITE_TX_RLE_MASK; ++ ++ /* take into account pulse/space prefix */ ++ if (is_pulse) ++ val |= ITE_TX_PULSE; ++ else ++ val |= ITE_TX_SPACE; ++ ++ /* if we get to 0 available, read again, just in case ++ * some other slot got freed */ ++ if (fifo_avail <= 0) { ++ fifo_avail = ++ dev->params.get_tx_free_slots(dev); ++ } ++ ++ /* if it's still full */ ++ if (fifo_avail <= 0) { ++ /* enable the tx interrupt */ ++ dev->params.enable_tx_interrupt(dev); ++ ++ /* drop the spinlock */ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ /* wait for the FIFO to empty enough */ ++ wait_event_interruptible(dev->tx_queue, ++ (fifo_avail = ++ dev->params.get_tx_free_slots(dev)) ++ >= 8); ++ ++ /* get the spinlock again */ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* disable the tx interrupt again. */ ++ dev->params.disable_tx_interrupt(dev); ++ } ++ ++ /* now send the byte through the FIFO */ ++ dev->params.put_tx_byte(dev, val); ++ fifo_avail--; ++ } ++ } ++ ++ /* wait and don't return until the whole FIFO has been sent out; ++ * otherwise we could configure the RX carrier params instead of the ++ * TX ones while the transmission is still being performed! */ ++ fifo_remaining = ITE_TX_FIFO_LEN - ++ dev->params.get_tx_free_slots(dev); ++ remaining_us = 0; ++ while (fifo_remaining > 0) { ++ fifo_remaining--; ++ last_idx--; ++ last_idx &= (ITE_TX_FIFO_LEN - 1); ++ remaining_us += last_sent[last_idx]; ++ } ++ remaining_us = (remaining_us * max_rle_us) / (ITE_TX_MAX_RLE); ++ ++ /* drop the spinlock while we sleep */ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ /* sleep remaining_us microseconds */ ++ mdelay(DIV_ROUND_UP(remaining_us, 1000)); ++ ++ /* reacquire the spinlock */ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* now we're not transmitting anymore */ ++ dev->transmitting = false; ++ ++ /* and set the carrier values for reception */ ++ ite_set_carrier_params(dev); ++ ++ /* reenable the receiver */ ++ if (dev->in_use) ++ dev->params.enable_rx(dev); ++ ++ /* notify transmission end */ ++ wake_up_interruptible(&dev->tx_ended); ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ return ret; ++} ++ ++/* idle the receiver if needed */ ++static void ite_s_idle(struct rc_dev *rcdev, bool enable) ++{ ++ unsigned long flags; ++ struct ite_dev *dev = rcdev->priv; ++ ++ ite_dbg("%s called", __func__); ++ ++ if (enable) { ++ spin_lock_irqsave(&dev->lock, flags); ++ dev->params.idle_rx(dev); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ } ++} ++ ++/* activate the device for use */ ++static int ite_open(struct rc_dev *rcdev) ++{ ++ struct ite_dev *dev = rcdev->priv; ++ unsigned long flags; ++ ++ ite_dbg("%s called", __func__); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ dev->in_use = true; ++ ++ /* enable the receiver */ ++ dev->params.enable_rx(dev); ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ return 0; ++} ++ ++/* deactivate the device for use */ ++static void ite_close(struct rc_dev *rcdev) ++{ ++ struct ite_dev *dev = rcdev->priv; ++ unsigned long flags; ++ ++ ite_dbg("%s called", __func__); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ dev->in_use = false; ++ ++ /* wait for any transmission to end */ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ wait_event_interruptible(dev->tx_ended, !dev->transmitting); ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ dev->params.disable(dev); ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++} ++ ++/* allocate memory, probe hardware, and initialize everything */ ++static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id ++ *dev_id) ++{ ++ const struct ite_dev_params *dev_desc = NULL; ++ struct ite_dev *itdev = NULL; ++ struct rc_dev *rdev = NULL; ++ int ret = -ENOMEM; ++ int model_no; ++ ++ ite_dbg("%s called", __func__); ++ ++ itdev = kzalloc(sizeof(struct ite_dev), GFP_KERNEL); ++ if (!itdev) ++ return ret; ++ ++ /* input device for IR remote (and tx) */ ++ rdev = rc_allocate_device(); ++ if (!rdev) ++ goto failure; ++ ++ ret = -ENODEV; ++ ++ ++ /* get the model number */ ++ model_no = (int) dev_id->driver_data; ++ ite_pr(KERN_NOTICE, "Auto-detected model: %s\n", ++ ite_dev_descs[model_no].model); ++ ++ if (model_number >= 0 && model_number ++ < ARRAY_SIZE(ite_dev_descs)) { ++ model_no = model_number; ++ ite_pr(KERN_NOTICE, "The model has been fixed by a module \ ++parameter."); ++ } ++ ++ ite_pr(KERN_NOTICE, "Using model: %s\n", ++ ite_dev_descs[model_no].model); ++ ++ /* get the description for the device */ ++ dev_desc = &ite_dev_descs[model_no]; ++ ++ ++ /* validate pnp resources */ ++ if (!pnp_port_valid(pdev, 0) || ++ pnp_port_len(pdev, 0) != dev_desc->io_region_size) { ++ dev_err(&pdev->dev, "IR PNP Port not valid!\n"); ++ goto failure; ++ } ++ ++ if (!pnp_irq_valid(pdev, 0)) { ++ dev_err(&pdev->dev, "PNP IRQ not valid!\n"); ++ goto failure; ++ } ++ ++ /* store resource values */ ++ itdev->cir_addr = pnp_port_start(pdev, 0); ++ itdev->cir_irq = pnp_irq(pdev, 0); ++ ++ /* initialize spinlocks */ ++ spin_lock_init(&itdev->lock); ++ ++ /* initialize raw event */ ++ init_ir_raw_event(&itdev->rawir); ++ ++ ret = -EBUSY; ++ /* now claim resources */ ++ if (!request_region(itdev->cir_addr, ++ dev_desc->io_region_size, ITE_DRIVER_NAME)) ++ goto failure; ++ ++ if (request_irq(itdev->cir_irq, ite_cir_isr, IRQF_SHARED, ++ ITE_DRIVER_NAME, (void *)itdev)) ++ goto failure; ++ ++ /* set driver data into the pnp device */ ++ pnp_set_drvdata(pdev, itdev); ++ itdev->pdev = pdev; ++ ++ /* initialize waitqueues for transmission */ ++ init_waitqueue_head(&itdev->tx_queue); ++ init_waitqueue_head(&itdev->tx_ended); ++ ++ /* copy model-specific parameters */ ++ itdev->params = *dev_desc; ++ ++ /* apply any overrides */ ++ if (sample_period > 0) ++ itdev->params.sample_period = sample_period; ++ ++ if (tx_carrier_freq > 0) ++ itdev->params.tx_carrier_freq = tx_carrier_freq; ++ ++ if (tx_duty_cycle > 0 && tx_duty_cycle <= 100) ++ itdev->params.tx_duty_cycle = tx_duty_cycle; ++ ++ if (rx_low_carrier_freq > 0) ++ itdev->params.rx_low_carrier_freq = rx_low_carrier_freq; ++ ++ if (rx_high_carrier_freq > 0) ++ itdev->params.rx_high_carrier_freq = rx_high_carrier_freq; ++ ++ /* print out parameters */ ++ ite_pr(KERN_NOTICE, "TX-capable: %d\n", (int) ++ itdev->params.hw_tx_capable); ++ ite_pr(KERN_NOTICE, "Sample period (ns): %ld\n", (long) ++ itdev->params.sample_period); ++ ite_pr(KERN_NOTICE, "TX carrier frequency (Hz): %d\n", (int) ++ itdev->params.tx_carrier_freq); ++ ite_pr(KERN_NOTICE, "TX duty cycle (%%): %d\n", (int) ++ itdev->params.tx_duty_cycle); ++ ite_pr(KERN_NOTICE, "RX low carrier frequency (Hz): %d\n", (int) ++ itdev->params.rx_low_carrier_freq); ++ ite_pr(KERN_NOTICE, "RX high carrier frequency (Hz): %d\n", (int) ++ itdev->params.rx_high_carrier_freq); ++ ++ /* set up hardware initial state */ ++ itdev->params.init_hardware(itdev); ++ ++ /* set up ir-core props */ ++ rdev->priv = itdev; ++ rdev->driver_type = RC_DRIVER_IR_RAW; ++ rdev->allowed_protos = RC_TYPE_ALL; ++ rdev->open = ite_open; ++ rdev->close = ite_close; ++ rdev->s_idle = ite_s_idle; ++ rdev->s_rx_carrier_range = ite_set_rx_carrier_range; ++ rdev->min_timeout = ITE_MIN_IDLE_TIMEOUT; ++ rdev->max_timeout = ITE_MAX_IDLE_TIMEOUT; ++ rdev->timeout = ITE_IDLE_TIMEOUT; ++ rdev->rx_resolution = rdev->tx_resolution = ITE_BAUDRATE_DIVISOR * ++ itdev->params.sample_period; ++ ++ /* set up transmitter related values if needed */ ++ if (itdev->params.hw_tx_capable) { ++ rdev->tx_ir = ite_tx_ir; ++ rdev->s_tx_carrier = ite_set_tx_carrier; ++ rdev->s_tx_duty_cycle = ite_set_tx_duty_cycle; ++ } ++ ++ rdev->input_name = dev_desc->model; ++ rdev->input_id.bustype = BUS_HOST; ++ rdev->input_id.vendor = PCI_VENDOR_ID_ITE; ++ rdev->input_id.product = 0; ++ rdev->input_id.version = 0; ++ rdev->driver_name = ITE_DRIVER_NAME; ++ rdev->map_name = RC_MAP_RC6_MCE; ++ ++ ret = rc_register_device(rdev); ++ if (ret) ++ goto failure; ++ ++ itdev->rdev = rdev; ++ ite_pr(KERN_NOTICE, "driver has been successfully loaded\n"); ++ ++ return 0; ++ ++failure: ++ if (itdev->cir_irq) ++ free_irq(itdev->cir_irq, itdev); ++ if (itdev->cir_addr) ++ release_region(itdev->cir_addr, itdev->params.io_region_size); ++ ++ rc_free_device(rdev); ++ kfree(itdev); ++ ++ return ret; ++} ++ ++static void __devexit ite_remove(struct pnp_dev *pdev) ++{ ++ struct ite_dev *dev = pnp_get_drvdata(pdev); ++ unsigned long flags; ++ ++ ite_dbg("%s called", __func__); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* disable hardware */ ++ dev->params.disable(dev); ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ /* free resources */ ++ free_irq(dev->cir_irq, dev); ++ release_region(dev->cir_addr, dev->params.io_region_size); ++ ++ rc_unregister_device(dev->rdev); ++ ++ kfree(dev); ++} ++ ++static int ite_suspend(struct pnp_dev *pdev, pm_message_t state) ++{ ++ struct ite_dev *dev = pnp_get_drvdata(pdev); ++ unsigned long flags; ++ ++ ite_dbg("%s called", __func__); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* disable all interrupts */ ++ dev->params.disable(dev); ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ return 0; ++} ++ ++static int ite_resume(struct pnp_dev *pdev) ++{ ++ int ret = 0; ++ struct ite_dev *dev = pnp_get_drvdata(pdev); ++ unsigned long flags; ++ ++ ite_dbg("%s called", __func__); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ if (dev->transmitting) { ++ /* wake up the transmitter */ ++ wake_up_interruptible(&dev->tx_queue); ++ } else { ++ /* enable the receiver */ ++ dev->params.enable_rx(dev); ++ } ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ return ret; ++} ++ ++static void ite_shutdown(struct pnp_dev *pdev) ++{ ++ struct ite_dev *dev = pnp_get_drvdata(pdev); ++ unsigned long flags; ++ ++ ite_dbg("%s called", __func__); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* disable all interrupts */ ++ dev->params.disable(dev); ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++} ++ ++static const struct pnp_device_id ite_ids[] = { ++ { "ITE8704", 0 }, /* Default model */ ++ { "ITE8713", 0 }, /* CIR found in EEEBox 1501U */ ++ { "ITE8708", 1 }, /* Bridged IT8512 */ ++ { "", 0 }, ++}; ++ ++static struct pnp_driver ite_driver = { ++ .name = ITE_DRIVER_NAME, ++ .id_table = ite_ids, ++ .probe = ite_probe, ++ .remove = __devexit_p(ite_remove), ++ .suspend = ite_suspend, ++ .resume = ite_resume, ++ .shutdown = ite_shutdown, ++}; ++ ++int ite_init(void) ++{ ++ return pnp_register_driver(&ite_driver); ++} ++ ++void ite_exit(void) ++{ ++ pnp_unregister_driver(&ite_driver); ++} ++ ++MODULE_DEVICE_TABLE(pnp, ite_ids); ++MODULE_DESCRIPTION("ITE Tech Inc. IT8712F/ITE8512F CIR driver"); ++ ++MODULE_AUTHOR("Juan J. Garcia de Soria "); ++MODULE_LICENSE("GPL"); ++ ++module_init(ite_init); ++module_exit(ite_exit); +diff -Naur linux-2.6.38-rc5/drivers/media/rc/ite-cir.h linux-2.6.38-rc5.patch/drivers/media/rc/ite-cir.h +--- linux-2.6.38-rc5/drivers/media/rc/ite-cir.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.38-rc5.patch/drivers/media/rc/ite-cir.h 2011-02-22 03:19:26.755636229 +0100 +@@ -0,0 +1,446 @@ ++/* ++ * Driver for ITE Tech Inc. IT8712F/IT8512F CIR ++ * ++ * Copyright (C) 2010 Juan J. Garcia de Soria ++ * ++ * Based on nuvoton-cir and lirc_it87 drivers. ++ * ++ * 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 the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ * USA ++ */ ++ ++/* platform driver name to register */ ++#define ITE_DRIVER_NAME "ite-cir" ++ ++/* logging macros */ ++#define ite_pr(level, text, ...) \ ++ printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__) ++ ++#define ite_dbg(text, ...) \ ++ if (debug) \ ++ printk(KERN_DEBUG \ ++ KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) ++ ++#define ite_dbg_verbose(text, ...) \ ++ if (debug > 1) \ ++ printk(KERN_DEBUG \ ++ KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) ++ ++/* FIFO sizes */ ++#define ITE_TX_FIFO_LEN 32 ++#define ITE_RX_FIFO_LEN 32 ++ ++/* interrupt types */ ++#define ITE_IRQ_TX_FIFO 1 ++#define ITE_IRQ_RX_FIFO 2 ++#define ITE_IRQ_RX_FIFO_OVERRUN 4 ++ ++/* forward declaration */ ++struct ite_dev; ++ ++/* struct for storing the parameters of different recognized devices */ ++struct ite_dev_params { ++ /* model of the device */ ++ const char *model; ++ ++ /* size of the I/O region */ ++ int io_region_size; ++ ++ /* true if the hardware supports transmission */ ++ bool hw_tx_capable; ++ ++ /* base sampling period, in ns */ ++ u32 sample_period; ++ ++ /* rx low carrier frequency, in Hz, 0 means no demodulation */ ++ unsigned int rx_low_carrier_freq; ++ ++ /* tx high carrier frequency, in Hz, 0 means no demodulation */ ++ unsigned int rx_high_carrier_freq; ++ ++ /* tx carrier frequency, in Hz */ ++ unsigned int tx_carrier_freq; ++ ++ /* duty cycle, 0-100 */ ++ int tx_duty_cycle; ++ ++ /* hw-specific operation function pointers; most of these must be ++ * called while holding the spin lock, except for the TX FIFO length ++ * one */ ++ ++ /* get pending interrupt causes */ ++ int (*get_irq_causes)(struct ite_dev *dev); ++ ++ /* enable rx */ ++ void (*enable_rx)(struct ite_dev *dev); ++ ++ /* make rx enter the idle state; keep listening for a pulse, but stop ++ * streaming space bytes */ ++ void (*idle_rx)(struct ite_dev *dev); ++ ++ /* disable rx completely */ ++ void (*disable_rx)(struct ite_dev *dev); ++ ++ /* read bytes from RX FIFO; return read count */ ++ int (*get_rx_bytes)(struct ite_dev *dev, u8 *buf, int buf_size); ++ ++ /* enable tx FIFO space available interrupt */ ++ void (*enable_tx_interrupt)(struct ite_dev *dev); ++ ++ /* disable tx FIFO space available interrupt */ ++ void (*disable_tx_interrupt)(struct ite_dev *dev); ++ ++ /* get number of available TX FIFO slots */ ++ int (*get_tx_free_slots)(struct ite_dev *dev); ++ ++ /* put a byte to the TX FIFO */ ++ void (*put_tx_byte)(struct ite_dev *dev, u8 value); ++ ++ /* disable hardware completely */ ++ void (*disable)(struct ite_dev *dev); ++ ++ /* initialize the hardware */ ++ void (*init_hardware)(struct ite_dev *dev); ++ ++ /* set the carrier parameters */ ++ void (*set_carrier_params)(struct ite_dev *dev, bool high_freq, ++ bool use_demodulator, u8 carrier_freq_bits, ++ u8 allowance_bits, u8 pulse_width_bits); ++}; ++ ++/* ITE CIR device structure */ ++struct ite_dev { ++ struct pnp_dev *pdev; ++ struct rc_dev *rdev; ++ struct ir_raw_event rawir; ++ ++ /* sync data */ ++ spinlock_t lock; ++ bool in_use, transmitting; ++ ++ /* transmit support */ ++ int tx_fifo_allowance; ++ wait_queue_head_t tx_queue, tx_ended; ++ ++ /* hardware I/O settings */ ++ unsigned long cir_addr; ++ int cir_irq; ++ ++ /* overridable copy of model parameters */ ++ struct ite_dev_params params; ++}; ++ ++ ++/* common values for all kinds of hardware */ ++ ++/* baud rate divisor default */ ++#define ITE_BAUDRATE_DIVISOR 1 ++ ++/* low-speed carrier frequency limits (Hz) */ ++#define ITE_LCF_MIN_CARRIER_FREQ 27000 ++#define ITE_LCF_MAX_CARRIER_FREQ 58000 ++ ++/* high-speed carrier frequency limits (Hz) */ ++#define ITE_HCF_MIN_CARRIER_FREQ 400000 ++#define ITE_HCF_MAX_CARRIER_FREQ 500000 ++ ++/* default carrier freq for when demodulator is off (Hz) */ ++#define ITE_DEFAULT_CARRIER_FREQ 38000 ++ ++/* default idling timeout in ns (0.2 seconds) */ ++#define ITE_IDLE_TIMEOUT 200000000UL ++ ++/* limit timeout values */ ++#define ITE_MIN_IDLE_TIMEOUT 100000000UL ++#define ITE_MAX_IDLE_TIMEOUT 1000000000UL ++ ++/* convert bits to us */ ++#define ITE_BITS_TO_NS(bits, sample_period) \ ++((u32) ((bits) * ITE_BAUDRATE_DIVISOR * sample_period)) ++ ++/* ++ * n in IT87_RDCR produces a tolerance of +/- n * 6.25% around the center ++ * carrier frequency... ++ * ++ * From two limit frequencies, L (low) and H (high), we can get both the ++ * center frequency F = (L + H) / 2 and the variation from the center ++ * frequency A = (H - L) / (H + L). We can use this in order to honor the ++ * s_rx_carrier_range() call in ir-core. We'll suppose that any request ++ * setting L=0 means we must shut down the demodulator. ++ */ ++#define ITE_RXDCR_PER_10000_STEP 625 ++ ++/* high speed carrier freq values */ ++#define ITE_CFQ_400 0x03 ++#define ITE_CFQ_450 0x08 ++#define ITE_CFQ_480 0x0b ++#define ITE_CFQ_500 0x0d ++ ++/* values for pulse widths */ ++#define ITE_TXMPW_A 0x02 ++#define ITE_TXMPW_B 0x03 ++#define ITE_TXMPW_C 0x04 ++#define ITE_TXMPW_D 0x05 ++#define ITE_TXMPW_E 0x06 ++ ++/* values for demodulator carrier range allowance */ ++#define ITE_RXDCR_DEFAULT 0x01 /* default carrier range */ ++#define ITE_RXDCR_MAX 0x07 /* default carrier range */ ++ ++/* DR TX bits */ ++#define ITE_TX_PULSE 0x00 ++#define ITE_TX_SPACE 0x80 ++#define ITE_TX_MAX_RLE 0x80 ++#define ITE_TX_RLE_MASK 0x7F ++ ++ ++/* ++ * IT8712F ++ * ++ * hardware data obtained from: ++ * ++ * IT8712F ++ * Environment Control – Low Pin Count Input / Output ++ * (EC - LPC I/O) ++ * Preliminary Specification V0. 81 ++ */ ++ ++/* register offsets */ ++#define IT87_DR 0x00 /* data register */ ++#define IT87_IER 0x01 /* interrupt enable register */ ++#define IT87_RCR 0x02 /* receiver control register */ ++#define IT87_TCR1 0x03 /* transmitter control register 1 */ ++#define IT87_TCR2 0x04 /* transmitter control register 2 */ ++#define IT87_TSR 0x05 /* transmitter status register */ ++#define IT87_RSR 0x06 /* receiver status register */ ++#define IT87_BDLR 0x05 /* baud rate divisor low byte register */ ++#define IT87_BDHR 0x06 /* baud rate divisor high byte register */ ++#define IT87_IIR 0x07 /* interrupt identification register */ ++ ++#define IT87_IOREG_LENGTH 0x08 /* length of register file */ ++ ++/* IER bits */ ++#define IT87_TLDLIE 0x01 /* transmitter low data interrupt enable */ ++#define IT87_RDAIE 0x02 /* receiver data available interrupt enable */ ++#define IT87_RFOIE 0x04 /* receiver FIFO overrun interrupt enable */ ++#define IT87_IEC 0x08 /* interrupt enable control */ ++#define IT87_BR 0x10 /* baud rate register enable */ ++#define IT87_RESET 0x20 /* reset */ ++ ++/* RCR bits */ ++#define IT87_RXDCR 0x07 /* receiver demodulation carrier range mask */ ++#define IT87_RXACT 0x08 /* receiver active */ ++#define IT87_RXEND 0x10 /* receiver demodulation enable */ ++#define IT87_RXEN 0x20 /* receiver enable */ ++#define IT87_HCFS 0x40 /* high-speed carrier frequency select */ ++#define IT87_RDWOS 0x80 /* receiver data without sync */ ++ ++/* TCR1 bits */ ++#define IT87_TXMPM 0x03 /* transmitter modulation pulse mode mask */ ++#define IT87_TXMPM_DEFAULT 0x00 /* modulation pulse mode default */ ++#define IT87_TXENDF 0x04 /* transmitter deferral */ ++#define IT87_TXRLE 0x08 /* transmitter run length enable */ ++#define IT87_FIFOTL 0x30 /* FIFO level threshold mask */ ++#define IT87_FIFOTL_DEFAULT 0x20 /* FIFO level threshold default ++ 0x00 -> 1, 0x10 -> 7, 0x20 -> 17, ++ 0x30 -> 25 */ ++#define IT87_ILE 0x40 /* internal loopback enable */ ++#define IT87_FIFOCLR 0x80 /* FIFO clear bit */ ++ ++/* TCR2 bits */ ++#define IT87_TXMPW 0x07 /* transmitter modulation pulse width mask */ ++#define IT87_TXMPW_DEFAULT 0x04 /* default modulation pulse width */ ++#define IT87_CFQ 0xf8 /* carrier frequency mask */ ++#define IT87_CFQ_SHIFT 3 /* carrier frequency bit shift */ ++ ++/* TSR bits */ ++#define IT87_TXBFC 0x3f /* transmitter FIFO byte count mask */ ++ ++/* RSR bits */ ++#define IT87_RXBFC 0x3f /* receiver FIFO byte count mask */ ++#define IT87_RXFTO 0x80 /* receiver FIFO time-out */ ++ ++/* IIR bits */ ++#define IT87_IP 0x01 /* interrupt pending */ ++#define IT87_II 0x06 /* interrupt identification mask */ ++#define IT87_II_NOINT 0x00 /* no interrupt */ ++#define IT87_II_TXLDL 0x02 /* transmitter low data level */ ++#define IT87_II_RXDS 0x04 /* receiver data stored */ ++#define IT87_II_RXFO 0x06 /* receiver FIFO overrun */ ++ ++ ++/* ++ * IT8512E/F ++ * ++ * Hardware data obtained from: ++ * ++ * IT8512E/F ++ * Embedded Controller ++ * Preliminary Specification V0.4.1 ++ * ++ * Note that the CIR registers are not directly available to the host, because ++ * they only are accessible to the integrated microcontroller. Thus, in order ++ * use it, some kind of bridging is required. As the bridging may depend on ++ * the controller firmware in use, we are going to use the PNP ID in order to ++ * determine the strategy and ports available. See after these generic ++ * IT8512E/F register definitions for register definitions for those ++ * strategies. ++ */ ++ ++/* register offsets */ ++#define IT85_C0DR 0x00 /* data register */ ++#define IT85_C0MSTCR 0x01 /* master control register */ ++#define IT85_C0IER 0x02 /* interrupt enable register */ ++#define IT85_C0IIR 0x03 /* interrupt identification register */ ++#define IT85_C0CFR 0x04 /* carrier frequency register */ ++#define IT85_C0RCR 0x05 /* receiver control register */ ++#define IT85_C0TCR 0x06 /* transmitter control register */ ++#define IT85_C0SCK 0x07 /* slow clock control register */ ++#define IT85_C0BDLR 0x08 /* baud rate divisor low byte register */ ++#define IT85_C0BDHR 0x09 /* baud rate divisor high byte register */ ++#define IT85_C0TFSR 0x0a /* transmitter FIFO status register */ ++#define IT85_C0RFSR 0x0b /* receiver FIFO status register */ ++#define IT85_C0WCL 0x0d /* wakeup code length register */ ++#define IT85_C0WCR 0x0e /* wakeup code read/write register */ ++#define IT85_C0WPS 0x0f /* wakeup power control/status register */ ++ ++#define IT85_IOREG_LENGTH 0x10 /* length of register file */ ++ ++/* C0MSTCR bits */ ++#define IT85_RESET 0x01 /* reset */ ++#define IT85_FIFOCLR 0x02 /* FIFO clear bit */ ++#define IT85_FIFOTL 0x0c /* FIFO level threshold mask */ ++#define IT85_FIFOTL_DEFAULT 0x08 /* FIFO level threshold default ++ 0x00 -> 1, 0x04 -> 7, 0x08 -> 17, ++ 0x0c -> 25 */ ++#define IT85_ILE 0x10 /* internal loopback enable */ ++#define IT85_ILSEL 0x20 /* internal loopback select */ ++ ++/* C0IER bits */ ++#define IT85_TLDLIE 0x01 /* TX low data level interrupt enable */ ++#define IT85_RDAIE 0x02 /* RX data available interrupt enable */ ++#define IT85_RFOIE 0x04 /* RX FIFO overrun interrupt enable */ ++#define IT85_IEC 0x80 /* interrupt enable function control */ ++ ++/* C0IIR bits */ ++#define IT85_TLDLI 0x01 /* transmitter low data level interrupt */ ++#define IT85_RDAI 0x02 /* receiver data available interrupt */ ++#define IT85_RFOI 0x04 /* receiver FIFO overrun interrupt */ ++#define IT85_NIP 0x80 /* no interrupt pending */ ++ ++/* C0CFR bits */ ++#define IT85_CFQ 0x1f /* carrier frequency mask */ ++#define IT85_HCFS 0x20 /* high speed carrier frequency select */ ++ ++/* C0RCR bits */ ++#define IT85_RXDCR 0x07 /* receiver demodulation carrier range mask */ ++#define IT85_RXACT 0x08 /* receiver active */ ++#define IT85_RXEND 0x10 /* receiver demodulation enable */ ++#define IT85_RDWOS 0x20 /* receiver data without sync */ ++#define IT85_RXEN 0x80 /* receiver enable */ ++ ++/* C0TCR bits */ ++#define IT85_TXMPW 0x07 /* transmitter modulation pulse width mask */ ++#define IT85_TXMPW_DEFAULT 0x04 /* default modulation pulse width */ ++#define IT85_TXMPM 0x18 /* transmitter modulation pulse mode mask */ ++#define IT85_TXMPM_DEFAULT 0x00 /* modulation pulse mode default */ ++#define IT85_TXENDF 0x20 /* transmitter deferral */ ++#define IT85_TXRLE 0x40 /* transmitter run length enable */ ++ ++/* C0SCK bits */ ++#define IT85_SCKS 0x01 /* slow clock select */ ++#define IT85_TXDCKG 0x02 /* TXD clock gating */ ++#define IT85_DLL1P8E 0x04 /* DLL 1.8432M enable */ ++#define IT85_DLLTE 0x08 /* DLL test enable */ ++#define IT85_BRCM 0x70 /* baud rate count mode */ ++#define IT85_DLLOCK 0x80 /* DLL lock */ ++ ++/* C0TFSR bits */ ++#define IT85_TXFBC 0x3f /* transmitter FIFO count mask */ ++ ++/* C0RFSR bits */ ++#define IT85_RXFBC 0x3f /* receiver FIFO count mask */ ++#define IT85_RXFTO 0x80 /* receiver FIFO time-out */ ++ ++/* C0WCL bits */ ++#define IT85_WCL 0x3f /* wakeup code length mask */ ++ ++/* C0WPS bits */ ++#define IT85_CIRPOSIE 0x01 /* power on/off status interrupt enable */ ++#define IT85_CIRPOIS 0x02 /* power on/off interrupt status */ ++#define IT85_CIRPOII 0x04 /* power on/off interrupt identification */ ++#define IT85_RCRST 0x10 /* wakeup code reading counter reset bit */ ++#define IT85_WCRST 0x20 /* wakeup code writing counter reset bit */ ++ ++ ++/* ++ * ITE8708 ++ * ++ * Hardware data obtained from hacked driver for IT8512 in this forum post: ++ * ++ * http://ubuntuforums.org/showthread.php?t=1028640 ++ * ++ * Although there's no official documentation for that driver, analysis would ++ * suggest that it maps the 16 registers of IT8512 onto two 8-register banks, ++ * selectable by a single bank-select bit that's mapped onto both banks. The ++ * IT8512 registers are mapped in a different order, so that the first bank ++ * maps the ones that are used more often, and two registers that share a ++ * reserved high-order bit are placed at the same offset in both banks in ++ * order to reuse the reserved bit as the bank select bit. ++ */ ++ ++/* register offsets */ ++ ++/* mapped onto both banks */ ++#define IT8708_BANKSEL 0x07 /* bank select register */ ++#define IT8708_HRAE 0x80 /* high registers access enable */ ++ ++/* mapped onto the low bank */ ++#define IT8708_C0DR 0x00 /* data register */ ++#define IT8708_C0MSTCR 0x01 /* master control register */ ++#define IT8708_C0IER 0x02 /* interrupt enable register */ ++#define IT8708_C0IIR 0x03 /* interrupt identification register */ ++#define IT8708_C0RFSR 0x04 /* receiver FIFO status register */ ++#define IT8708_C0RCR 0x05 /* receiver control register */ ++#define IT8708_C0TFSR 0x06 /* transmitter FIFO status register */ ++#define IT8708_C0TCR 0x07 /* transmitter control register */ ++ ++/* mapped onto the high bank */ ++#define IT8708_C0BDLR 0x01 /* baud rate divisor low byte register */ ++#define IT8708_C0BDHR 0x02 /* baud rate divisor high byte register */ ++#define IT8708_C0CFR 0x04 /* carrier frequency register */ ++ ++/* registers whose bank mapping we don't know, since they weren't being used ++ * in the hacked driver... most probably they belong to the high bank too, ++ * since they fit in the holes the other registers leave */ ++#define IT8708_C0SCK 0x03 /* slow clock control register */ ++#define IT8708_C0WCL 0x05 /* wakeup code length register */ ++#define IT8708_C0WCR 0x06 /* wakeup code read/write register */ ++#define IT8708_C0WPS 0x07 /* wakeup power control/status register */ ++ ++#define IT8708_IOREG_LENGTH 0x08 /* length of register file */ ++ ++/* two more registers that are defined in the hacked driver, but can't be ++ * found in the data sheets; no idea what they are or how they are accessed, ++ * since the hacked driver doesn't seem to use them */ ++#define IT8708_CSCRR 0x00 ++#define IT8708_CGPINTR 0x01 ++ ++/* CSCRR bits */ ++#define IT8708_CSCRR_SCRB 0x3f ++#define IT8708_CSCRR_PM 0x80 ++ ++/* CGPINTR bits */ ++#define IT8708_CGPINT 0x01 +diff -Naur linux-2.6.38-rc5/drivers/media/rc/Kconfig linux-2.6.38-rc5.patch/drivers/media/rc/Kconfig +--- linux-2.6.38-rc5/drivers/media/rc/Kconfig 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.patch/drivers/media/rc/Kconfig 2011-02-22 03:24:59.239412519 +0100 +@@ -148,6 +148,19 @@ + To compile this driver as a module, choose M here: the + module will be called nuvoton-cir. + ++config IR_ITE_CIR ++ tristate "ITE Tech Inc. IT8712/IT8512 Consumer Infrared Transceiver" ++ depends on PNP ++ depends on RC_CORE ++ ---help--- ++ Say Y here to enable support for integrated infrared receivers ++ /transceivers made by ITE Tech Inc. These are found in ++ several ASUS devices, like the ASUS Digimatrix or the ASUS ++ EEEBox 1501U. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called ite-cir. ++ + config IR_STREAMZAP + tristate "Streamzap PC Remote IR Receiver" + depends on USB_ARCH_HAS_HCD +diff -Naur linux-2.6.38-rc5/drivers/media/rc/Makefile linux-2.6.38-rc5.patch/drivers/media/rc/Makefile +--- linux-2.6.38-rc5/drivers/media/rc/Makefile 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.patch/drivers/media/rc/Makefile 2011-02-22 03:24:09.659341983 +0100 +@@ -19,4 +19,5 @@ + obj-$(CONFIG_IR_ENE) += ene_ir.o + obj-$(CONFIG_IR_STREAMZAP) += streamzap.o + obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o ++obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o + obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o +diff -Naur linux-2.6.38-rc5/drivers/staging/lirc/Kconfig linux-2.6.38-rc5.patch/drivers/staging/lirc/Kconfig +--- linux-2.6.38-rc5/drivers/staging/lirc/Kconfig 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.patch/drivers/staging/lirc/Kconfig 2011-02-22 03:22:22.436351160 +0100 +@@ -32,12 +32,6 @@ + + Current generation iMON devices use the input layer imon driver. + +-config LIRC_IT87 +- tristate "ITE IT87XX CIR Port Receiver" +- depends on LIRC && PNP +- help +- Driver for the ITE IT87xx IR Receiver +- + config LIRC_ITE8709 + tristate "ITE8709 CIR Port Receiver" + depends on LIRC && PNP +diff -Naur linux-2.6.38-rc5/drivers/staging/lirc/lirc_it87.c linux-2.6.38-rc5.patch/drivers/staging/lirc/lirc_it87.c +--- linux-2.6.38-rc5/drivers/staging/lirc/lirc_it87.c 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.patch/drivers/staging/lirc/lirc_it87.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,1027 +0,0 @@ +-/* +- * LIRC driver for ITE IT8712/IT8705 CIR port +- * +- * Copyright (C) 2001 Hans-Gunter Lutke Uphues +- * +- * 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 the Free Software Foundation; either version 2 of the +- * License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- * General Public License for more details. +- +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +- * USA +- * +- * ITE IT8705 and IT8712(not tested) and IT8720 CIR-port support for lirc based +- * via cut and paste from lirc_sir.c (C) 2000 Milan Pikula +- * +- * Attention: Sendmode only tested with debugging logs +- * +- * 2001/02/27 Christoph Bartelmus : +- * reimplemented read function +- * 2005/06/05 Andrew Calkin implemented support for Asus Digimatrix, +- * based on work of the following member of the Outertrack Digimatrix +- * Forum: Art103 +- * 2009/12/24 James Edwards implemeted support +- * for ITE8704/ITE8718, on my machine, the DSDT reports 8704, but the +- * chip identifies as 18. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-#include +-#include +- +-#include "lirc_it87.h" +- +-#ifdef LIRC_IT87_DIGIMATRIX +-static int digimatrix = 1; +-static int it87_freq = 36; /* kHz */ +-static int irq = 9; +-#else +-static int digimatrix; +-static int it87_freq = 38; /* kHz */ +-static int irq = IT87_CIR_DEFAULT_IRQ; +-#endif +- +-static unsigned long it87_bits_in_byte_out; +-static unsigned long it87_send_counter; +-static unsigned char it87_RXEN_mask = IT87_CIR_RCR_RXEN; +- +-#define RBUF_LEN 1024 +- +-#define LIRC_DRIVER_NAME "lirc_it87" +- +-/* timeout for sequences in jiffies (=5/100s) */ +-/* must be longer than TIME_CONST */ +-#define IT87_TIMEOUT (HZ*5/100) +- +-/* module parameters */ +-static int debug; +-#define dprintk(fmt, args...) \ +- do { \ +- if (debug) \ +- printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ +- fmt, ## args); \ +- } while (0) +- +-static int io = IT87_CIR_DEFAULT_IOBASE; +-/* receiver demodulator default: off */ +-static int it87_enable_demodulator; +- +-static int timer_enabled; +-static DEFINE_SPINLOCK(timer_lock); +-static struct timer_list timerlist; +-/* time of last signal change detected */ +-static struct timeval last_tv = {0, 0}; +-/* time of last UART data ready interrupt */ +-static struct timeval last_intr_tv = {0, 0}; +-static int last_value; +- +-static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue); +- +-static DEFINE_SPINLOCK(hardware_lock); +-static DEFINE_SPINLOCK(dev_lock); +-static bool device_open; +- +-static int rx_buf[RBUF_LEN]; +-unsigned int rx_tail, rx_head; +- +-static struct pnp_driver it87_pnp_driver; +- +-/* SECTION: Prototypes */ +- +-/* Communication with user-space */ +-static int lirc_open(struct inode *inode, struct file *file); +-static int lirc_close(struct inode *inode, struct file *file); +-static unsigned int lirc_poll(struct file *file, poll_table *wait); +-static ssize_t lirc_read(struct file *file, char *buf, +- size_t count, loff_t *ppos); +-static ssize_t lirc_write(struct file *file, const char *buf, +- size_t n, loff_t *pos); +-static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); +-static void add_read_queue(int flag, unsigned long val); +-static int init_chrdev(void); +-static void drop_chrdev(void); +-/* Hardware */ +-static irqreturn_t it87_interrupt(int irq, void *dev_id); +-static void send_space(unsigned long len); +-static void send_pulse(unsigned long len); +-static void init_send(void); +-static void terminate_send(unsigned long len); +-static int init_hardware(void); +-static void drop_hardware(void); +-/* Initialisation */ +-static int init_port(void); +-static void drop_port(void); +- +- +-/* SECTION: Communication with user-space */ +- +-static int lirc_open(struct inode *inode, struct file *file) +-{ +- spin_lock(&dev_lock); +- if (device_open) { +- spin_unlock(&dev_lock); +- return -EBUSY; +- } +- device_open = true; +- spin_unlock(&dev_lock); +- return 0; +-} +- +- +-static int lirc_close(struct inode *inode, struct file *file) +-{ +- spin_lock(&dev_lock); +- device_open = false; +- spin_unlock(&dev_lock); +- return 0; +-} +- +- +-static unsigned int lirc_poll(struct file *file, poll_table *wait) +-{ +- poll_wait(file, &lirc_read_queue, wait); +- if (rx_head != rx_tail) +- return POLLIN | POLLRDNORM; +- return 0; +-} +- +- +-static ssize_t lirc_read(struct file *file, char *buf, +- size_t count, loff_t *ppos) +-{ +- int n = 0; +- int retval = 0; +- +- while (n < count) { +- if (file->f_flags & O_NONBLOCK && rx_head == rx_tail) { +- retval = -EAGAIN; +- break; +- } +- retval = wait_event_interruptible(lirc_read_queue, +- rx_head != rx_tail); +- if (retval) +- break; +- +- if (copy_to_user((void *) buf + n, (void *) (rx_buf + rx_head), +- sizeof(int))) { +- retval = -EFAULT; +- break; +- } +- rx_head = (rx_head + 1) & (RBUF_LEN - 1); +- n += sizeof(int); +- } +- if (n) +- return n; +- return retval; +-} +- +- +-static ssize_t lirc_write(struct file *file, const char *buf, +- size_t n, loff_t *pos) +-{ +- int i = 0; +- int *tx_buf; +- +- if (n % sizeof(int)) +- return -EINVAL; +- tx_buf = memdup_user(buf, n); +- if (IS_ERR(tx_buf)) +- return PTR_ERR(tx_buf); +- n /= sizeof(int); +- init_send(); +- while (1) { +- if (i >= n) +- break; +- if (tx_buf[i]) +- send_pulse(tx_buf[i]); +- i++; +- if (i >= n) +- break; +- if (tx_buf[i]) +- send_space(tx_buf[i]); +- i++; +- } +- terminate_send(tx_buf[i - 1]); +- kfree(tx_buf); +- return n; +-} +- +- +-static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) +-{ +- int retval = 0; +- __u32 value = 0; +- unsigned long hw_flags; +- +- if (cmd == LIRC_GET_FEATURES) +- value = LIRC_CAN_SEND_PULSE | +- LIRC_CAN_SET_SEND_CARRIER | +- LIRC_CAN_REC_MODE2; +- else if (cmd == LIRC_GET_SEND_MODE) +- value = LIRC_MODE_PULSE; +- else if (cmd == LIRC_GET_REC_MODE) +- value = LIRC_MODE_MODE2; +- +- switch (cmd) { +- case LIRC_GET_FEATURES: +- case LIRC_GET_SEND_MODE: +- case LIRC_GET_REC_MODE: +- retval = put_user(value, (__u32 *) arg); +- break; +- +- case LIRC_SET_SEND_MODE: +- case LIRC_SET_REC_MODE: +- retval = get_user(value, (__u32 *) arg); +- break; +- +- case LIRC_SET_SEND_CARRIER: +- retval = get_user(value, (__u32 *) arg); +- if (retval) +- return retval; +- value /= 1000; +- if (value > IT87_CIR_FREQ_MAX || +- value < IT87_CIR_FREQ_MIN) +- return -EINVAL; +- +- it87_freq = value; +- +- spin_lock_irqsave(&hardware_lock, hw_flags); +- outb(((inb(io + IT87_CIR_TCR2) & IT87_CIR_TCR2_TXMPW) | +- (it87_freq - IT87_CIR_FREQ_MIN) << 3), +- io + IT87_CIR_TCR2); +- spin_unlock_irqrestore(&hardware_lock, hw_flags); +- dprintk("demodulation frequency: %d kHz\n", it87_freq); +- +- break; +- +- default: +- retval = -EINVAL; +- } +- +- if (retval) +- return retval; +- +- if (cmd == LIRC_SET_REC_MODE) { +- if (value != LIRC_MODE_MODE2) +- retval = -ENOSYS; +- } else if (cmd == LIRC_SET_SEND_MODE) { +- if (value != LIRC_MODE_PULSE) +- retval = -ENOSYS; +- } +- return retval; +-} +- +-static void add_read_queue(int flag, unsigned long val) +-{ +- unsigned int new_rx_tail; +- int newval; +- +- dprintk("add flag %d with val %lu\n", flag, val); +- +- newval = val & PULSE_MASK; +- +- /* +- * statistically, pulses are ~TIME_CONST/2 too long. we could +- * maybe make this more exact, but this is good enough +- */ +- if (flag) { +- /* pulse */ +- if (newval > TIME_CONST / 2) +- newval -= TIME_CONST / 2; +- else /* should not ever happen */ +- newval = 1; +- newval |= PULSE_BIT; +- } else +- newval += TIME_CONST / 2; +- new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1); +- if (new_rx_tail == rx_head) { +- dprintk("Buffer overrun.\n"); +- return; +- } +- rx_buf[rx_tail] = newval; +- rx_tail = new_rx_tail; +- wake_up_interruptible(&lirc_read_queue); +-} +- +- +-static const struct file_operations lirc_fops = { +- .owner = THIS_MODULE, +- .read = lirc_read, +- .write = lirc_write, +- .poll = lirc_poll, +- .unlocked_ioctl = lirc_ioctl, +-#ifdef CONFIG_COMPAT +- .compat_ioctl = lirc_ioctl, +-#endif +- .open = lirc_open, +- .release = lirc_close, +- .llseek = noop_llseek, +-}; +- +-static int set_use_inc(void *data) +-{ +- return 0; +-} +- +-static void set_use_dec(void *data) +-{ +-} +- +-static struct lirc_driver driver = { +- .name = LIRC_DRIVER_NAME, +- .minor = -1, +- .code_length = 1, +- .sample_rate = 0, +- .data = NULL, +- .add_to_buf = NULL, +- .set_use_inc = set_use_inc, +- .set_use_dec = set_use_dec, +- .fops = &lirc_fops, +- .dev = NULL, +- .owner = THIS_MODULE, +-}; +- +- +-static int init_chrdev(void) +-{ +- driver.minor = lirc_register_driver(&driver); +- +- if (driver.minor < 0) { +- printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); +- return -EIO; +- } +- return 0; +-} +- +- +-static void drop_chrdev(void) +-{ +- lirc_unregister_driver(driver.minor); +-} +- +- +-/* SECTION: Hardware */ +-static long delta(struct timeval *tv1, struct timeval *tv2) +-{ +- unsigned long deltv; +- +- deltv = tv2->tv_sec - tv1->tv_sec; +- if (deltv > 15) +- deltv = 0xFFFFFF; +- else +- deltv = deltv*1000000 + tv2->tv_usec - tv1->tv_usec; +- return deltv; +-} +- +-static void it87_timeout(unsigned long data) +-{ +- unsigned long flags; +- +- /* avoid interference with interrupt */ +- spin_lock_irqsave(&timer_lock, flags); +- +- if (digimatrix) { +- /* We have timed out. Disable the RX mechanism. */ +- +- outb((inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN) | +- IT87_CIR_RCR_RXACT, io + IT87_CIR_RCR); +- if (it87_RXEN_mask) +- outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, +- io + IT87_CIR_RCR); +- dprintk(" TIMEOUT\n"); +- timer_enabled = 0; +- +- /* fifo clear */ +- outb(inb(io + IT87_CIR_TCR1) | IT87_CIR_TCR1_FIFOCLR, +- io+IT87_CIR_TCR1); +- +- } else { +- /* +- * if last received signal was a pulse, but receiving stopped +- * within the 9 bit frame, we need to finish this pulse and +- * simulate a signal change to from pulse to space. Otherwise +- * upper layers will receive two sequences next time. +- */ +- +- if (last_value) { +- unsigned long pulse_end; +- +- /* determine 'virtual' pulse end: */ +- pulse_end = delta(&last_tv, &last_intr_tv); +- dprintk("timeout add %d for %lu usec\n", +- last_value, pulse_end); +- add_read_queue(last_value, pulse_end); +- last_value = 0; +- last_tv = last_intr_tv; +- } +- } +- spin_unlock_irqrestore(&timer_lock, flags); +-} +- +-static irqreturn_t it87_interrupt(int irq, void *dev_id) +-{ +- unsigned char data; +- struct timeval curr_tv; +- static unsigned long deltv; +- unsigned long deltintrtv; +- unsigned long flags, hw_flags; +- int iir, lsr; +- int fifo = 0; +- static char lastbit; +- char bit; +- +- /* Bit duration in microseconds */ +- const unsigned long bit_duration = 1000000ul / +- (115200 / IT87_CIR_BAUDRATE_DIVISOR); +- +- +- iir = inb(io + IT87_CIR_IIR); +- +- switch (iir & IT87_CIR_IIR_IID) { +- case 0x4: +- case 0x6: +- lsr = inb(io + IT87_CIR_RSR) & (IT87_CIR_RSR_RXFTO | +- IT87_CIR_RSR_RXFBC); +- fifo = lsr & IT87_CIR_RSR_RXFBC; +- dprintk("iir: 0x%x fifo: 0x%x\n", iir, lsr); +- +- /* avoid interference with timer */ +- spin_lock_irqsave(&timer_lock, flags); +- spin_lock_irqsave(&hardware_lock, hw_flags); +- if (digimatrix) { +- static unsigned long acc_pulse; +- static unsigned long acc_space; +- +- do { +- data = inb(io + IT87_CIR_DR); +- data = ~data; +- fifo--; +- if (data != 0x00) { +- if (timer_enabled) +- del_timer(&timerlist); +- /* +- * start timer for end of +- * sequence detection +- */ +- timerlist.expires = jiffies + +- IT87_TIMEOUT; +- add_timer(&timerlist); +- timer_enabled = 1; +- } +- /* Loop through */ +- for (bit = 0; bit < 8; ++bit) { +- if ((data >> bit) & 1) { +- ++acc_pulse; +- if (lastbit == 0) { +- add_read_queue(0, +- acc_space * +- bit_duration); +- acc_space = 0; +- } +- } else { +- ++acc_space; +- if (lastbit == 1) { +- add_read_queue(1, +- acc_pulse * +- bit_duration); +- acc_pulse = 0; +- } +- } +- lastbit = (data >> bit) & 1; +- } +- +- } while (fifo != 0); +- } else { /* Normal Operation */ +- do { +- del_timer(&timerlist); +- data = inb(io + IT87_CIR_DR); +- +- dprintk("data=%02x\n", data); +- do_gettimeofday(&curr_tv); +- deltv = delta(&last_tv, &curr_tv); +- deltintrtv = delta(&last_intr_tv, &curr_tv); +- +- dprintk("t %lu , d %d\n", +- deltintrtv, (int)data); +- +- /* +- * if nothing came in last 2 cycles, +- * it was gap +- */ +- if (deltintrtv > TIME_CONST * 2) { +- if (last_value) { +- dprintk("GAP\n"); +- +- /* simulate signal change */ +- add_read_queue(last_value, +- deltv - +- deltintrtv); +- last_value = 0; +- last_tv.tv_sec = +- last_intr_tv.tv_sec; +- last_tv.tv_usec = +- last_intr_tv.tv_usec; +- deltv = deltintrtv; +- } +- } +- data = 1; +- if (data ^ last_value) { +- /* +- * deltintrtv > 2*TIME_CONST, +- * remember ? the other case is +- * timeout +- */ +- add_read_queue(last_value, +- deltv-TIME_CONST); +- last_value = data; +- last_tv = curr_tv; +- if (last_tv.tv_usec >= TIME_CONST) +- last_tv.tv_usec -= TIME_CONST; +- else { +- last_tv.tv_sec--; +- last_tv.tv_usec += 1000000 - +- TIME_CONST; +- } +- } +- last_intr_tv = curr_tv; +- if (data) { +- /* +- * start timer for end of +- * sequence detection +- */ +- timerlist.expires = +- jiffies + IT87_TIMEOUT; +- add_timer(&timerlist); +- } +- outb((inb(io + IT87_CIR_RCR) & +- ~IT87_CIR_RCR_RXEN) | +- IT87_CIR_RCR_RXACT, +- io + IT87_CIR_RCR); +- if (it87_RXEN_mask) +- outb(inb(io + IT87_CIR_RCR) | +- IT87_CIR_RCR_RXEN, +- io + IT87_CIR_RCR); +- fifo--; +- } while (fifo != 0); +- } +- spin_unlock_irqrestore(&hardware_lock, hw_flags); +- spin_unlock_irqrestore(&timer_lock, flags); +- +- return IRQ_RETVAL(IRQ_HANDLED); +- +- default: +- /* not our irq */ +- dprintk("unknown IRQ (shouldn't happen) !!\n"); +- return IRQ_RETVAL(IRQ_NONE); +- } +-} +- +- +-static void send_it87(unsigned long len, unsigned long stime, +- unsigned char send_byte, unsigned int count_bits) +-{ +- long count = len / stime; +- long time_left = 0; +- static unsigned char byte_out; +- unsigned long hw_flags; +- +- dprintk("%s: len=%ld, sb=%d\n", __func__, len, send_byte); +- +- time_left = (long)len - (long)count * (long)stime; +- count += ((2 * time_left) / stime); +- while (count) { +- long i = 0; +- for (i = 0; i < count_bits; i++) { +- byte_out = (byte_out << 1) | (send_byte & 1); +- it87_bits_in_byte_out++; +- } +- if (it87_bits_in_byte_out == 8) { +- dprintk("out=0x%x, tsr_txfbc: 0x%x\n", +- byte_out, +- inb(io + IT87_CIR_TSR) & +- IT87_CIR_TSR_TXFBC); +- +- while ((inb(io + IT87_CIR_TSR) & +- IT87_CIR_TSR_TXFBC) >= IT87_CIR_FIFO_SIZE) +- ; +- +- spin_lock_irqsave(&hardware_lock, hw_flags); +- outb(byte_out, io + IT87_CIR_DR); +- spin_unlock_irqrestore(&hardware_lock, hw_flags); +- +- it87_bits_in_byte_out = 0; +- it87_send_counter++; +- byte_out = 0; +- } +- count--; +- } +-} +- +- +-/*TODO: maybe exchange space and pulse because it8705 only modulates 0-bits */ +- +-static void send_space(unsigned long len) +-{ +- send_it87(len, TIME_CONST, IT87_CIR_SPACE, IT87_CIR_BAUDRATE_DIVISOR); +-} +- +-static void send_pulse(unsigned long len) +-{ +- send_it87(len, TIME_CONST, IT87_CIR_PULSE, IT87_CIR_BAUDRATE_DIVISOR); +-} +- +- +-static void init_send() +-{ +- unsigned long flags; +- +- spin_lock_irqsave(&hardware_lock, flags); +- /* RXEN=0: receiver disable */ +- it87_RXEN_mask = 0; +- outb(inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN, +- io + IT87_CIR_RCR); +- spin_unlock_irqrestore(&hardware_lock, flags); +- it87_bits_in_byte_out = 0; +- it87_send_counter = 0; +-} +- +- +-static void terminate_send(unsigned long len) +-{ +- unsigned long flags; +- unsigned long last = 0; +- +- last = it87_send_counter; +- /* make sure all necessary data has been sent */ +- while (last == it87_send_counter) +- send_space(len); +- /* wait until all data sent */ +- while ((inb(io + IT87_CIR_TSR) & IT87_CIR_TSR_TXFBC) != 0) +- ; +- /* then re-enable receiver */ +- spin_lock_irqsave(&hardware_lock, flags); +- it87_RXEN_mask = IT87_CIR_RCR_RXEN; +- outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, +- io + IT87_CIR_RCR); +- spin_unlock_irqrestore(&hardware_lock, flags); +-} +- +- +-static int init_hardware(void) +-{ +- unsigned long flags; +- unsigned char it87_rcr = 0; +- +- spin_lock_irqsave(&hardware_lock, flags); +- /* init cir-port */ +- /* enable r/w-access to Baudrate-Register */ +- outb(IT87_CIR_IER_BR, io + IT87_CIR_IER); +- outb(IT87_CIR_BAUDRATE_DIVISOR % 0x100, io+IT87_CIR_BDLR); +- outb(IT87_CIR_BAUDRATE_DIVISOR / 0x100, io+IT87_CIR_BDHR); +- /* Baudrate Register off, define IRQs: Input only */ +- if (digimatrix) { +- outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RFOIE, io + IT87_CIR_IER); +- /* RX: HCFS=0, RXDCR = 001b (33,75..38,25 kHz), RXEN=1 */ +- } else { +- outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RDAIE, io + IT87_CIR_IER); +- /* RX: HCFS=0, RXDCR = 001b (35,6..40,3 kHz), RXEN=1 */ +- } +- it87_rcr = (IT87_CIR_RCR_RXEN & it87_RXEN_mask) | 0x1; +- if (it87_enable_demodulator) +- it87_rcr |= IT87_CIR_RCR_RXEND; +- outb(it87_rcr, io + IT87_CIR_RCR); +- if (digimatrix) { +- /* Set FIFO depth to 1 byte, and disable TX */ +- outb(inb(io + IT87_CIR_TCR1) | 0x00, +- io + IT87_CIR_TCR1); +- +- /* +- * TX: it87_freq (36kHz), 'reserved' sensitivity +- * setting (0x00) +- */ +- outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x00, +- io + IT87_CIR_TCR2); +- } else { +- /* TX: 38kHz, 13,3us (pulse-width) */ +- outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x06, +- io + IT87_CIR_TCR2); +- } +- spin_unlock_irqrestore(&hardware_lock, flags); +- return 0; +-} +- +- +-static void drop_hardware(void) +-{ +- unsigned long flags; +- +- spin_lock_irqsave(&hardware_lock, flags); +- disable_irq(irq); +- /* receiver disable */ +- it87_RXEN_mask = 0; +- outb(0x1, io + IT87_CIR_RCR); +- /* turn off irqs */ +- outb(0, io + IT87_CIR_IER); +- /* fifo clear */ +- outb(IT87_CIR_TCR1_FIFOCLR, io+IT87_CIR_TCR1); +- /* reset */ +- outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); +- enable_irq(irq); +- spin_unlock_irqrestore(&hardware_lock, flags); +-} +- +- +-static unsigned char it87_read(unsigned char port) +-{ +- outb(port, IT87_ADRPORT); +- return inb(IT87_DATAPORT); +-} +- +- +-static void it87_write(unsigned char port, unsigned char data) +-{ +- outb(port, IT87_ADRPORT); +- outb(data, IT87_DATAPORT); +-} +- +- +-/* SECTION: Initialisation */ +- +-static int init_port(void) +-{ +- unsigned long hw_flags; +- int retval = 0; +- +- unsigned char init_bytes[4] = IT87_INIT; +- unsigned char it87_chipid = 0; +- unsigned char ldn = 0; +- unsigned int it87_io = 0; +- unsigned int it87_irq = 0; +- +- /* Enter MB PnP Mode */ +- outb(init_bytes[0], IT87_ADRPORT); +- outb(init_bytes[1], IT87_ADRPORT); +- outb(init_bytes[2], IT87_ADRPORT); +- outb(init_bytes[3], IT87_ADRPORT); +- +- /* 8712 or 8705 ? */ +- it87_chipid = it87_read(IT87_CHIP_ID1); +- if (it87_chipid != 0x87) { +- retval = -ENXIO; +- return retval; +- } +- it87_chipid = it87_read(IT87_CHIP_ID2); +- if ((it87_chipid != 0x05) && +- (it87_chipid != 0x12) && +- (it87_chipid != 0x18) && +- (it87_chipid != 0x20)) { +- printk(KERN_INFO LIRC_DRIVER_NAME +- ": no IT8704/05/12/18/20 found (claimed IT87%02x), " +- "exiting..\n", it87_chipid); +- retval = -ENXIO; +- return retval; +- } +- printk(KERN_INFO LIRC_DRIVER_NAME +- ": found IT87%02x.\n", +- it87_chipid); +- +- /* get I/O-Port and IRQ */ +- if (it87_chipid == 0x12 || it87_chipid == 0x18) +- ldn = IT8712_CIR_LDN; +- else +- ldn = IT8705_CIR_LDN; +- it87_write(IT87_LDN, ldn); +- +- it87_io = it87_read(IT87_CIR_BASE_MSB) * 256 + +- it87_read(IT87_CIR_BASE_LSB); +- if (it87_io == 0) { +- if (io == 0) +- io = IT87_CIR_DEFAULT_IOBASE; +- printk(KERN_INFO LIRC_DRIVER_NAME +- ": set default io 0x%x\n", +- io); +- it87_write(IT87_CIR_BASE_MSB, io / 0x100); +- it87_write(IT87_CIR_BASE_LSB, io % 0x100); +- } else +- io = it87_io; +- +- it87_irq = it87_read(IT87_CIR_IRQ); +- if (digimatrix || it87_irq == 0) { +- if (irq == 0) +- irq = IT87_CIR_DEFAULT_IRQ; +- printk(KERN_INFO LIRC_DRIVER_NAME +- ": set default irq 0x%x\n", +- irq); +- it87_write(IT87_CIR_IRQ, irq); +- } else +- irq = it87_irq; +- +- spin_lock_irqsave(&hardware_lock, hw_flags); +- /* reset */ +- outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); +- /* fifo clear */ +- outb(IT87_CIR_TCR1_FIFOCLR | +- /* IT87_CIR_TCR1_ILE | */ +- IT87_CIR_TCR1_TXRLE | +- IT87_CIR_TCR1_TXENDF, io+IT87_CIR_TCR1); +- spin_unlock_irqrestore(&hardware_lock, hw_flags); +- +- /* get I/O port access and IRQ line */ +- if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) { +- printk(KERN_ERR LIRC_DRIVER_NAME +- ": i/o port 0x%.4x already in use.\n", io); +- /* Leaving MB PnP Mode */ +- it87_write(IT87_CFGCTRL, 0x2); +- return -EBUSY; +- } +- +- /* activate CIR-Device */ +- it87_write(IT87_CIR_ACT, 0x1); +- +- /* Leaving MB PnP Mode */ +- it87_write(IT87_CFGCTRL, 0x2); +- +- retval = request_irq(irq, it87_interrupt, 0 /*IRQF_DISABLED*/, +- LIRC_DRIVER_NAME, NULL); +- if (retval < 0) { +- printk(KERN_ERR LIRC_DRIVER_NAME +- ": IRQ %d already in use.\n", +- irq); +- release_region(io, 8); +- return retval; +- } +- +- printk(KERN_INFO LIRC_DRIVER_NAME +- ": I/O port 0x%.4x, IRQ %d.\n", io, irq); +- +- init_timer(&timerlist); +- timerlist.function = it87_timeout; +- timerlist.data = 0xabadcafe; +- +- return 0; +-} +- +- +-static void drop_port(void) +-{ +-#if 0 +- unsigned char init_bytes[4] = IT87_INIT; +- +- /* Enter MB PnP Mode */ +- outb(init_bytes[0], IT87_ADRPORT); +- outb(init_bytes[1], IT87_ADRPORT); +- outb(init_bytes[2], IT87_ADRPORT); +- outb(init_bytes[3], IT87_ADRPORT); +- +- /* deactivate CIR-Device */ +- it87_write(IT87_CIR_ACT, 0x0); +- +- /* Leaving MB PnP Mode */ +- it87_write(IT87_CFGCTRL, 0x2); +-#endif +- +- del_timer_sync(&timerlist); +- free_irq(irq, NULL); +- release_region(io, 8); +-} +- +- +-static int init_lirc_it87(void) +-{ +- int retval; +- +- init_waitqueue_head(&lirc_read_queue); +- retval = init_port(); +- if (retval < 0) +- return retval; +- init_hardware(); +- printk(KERN_INFO LIRC_DRIVER_NAME ": Installed.\n"); +- return 0; +-} +- +-static int it87_probe(struct pnp_dev *pnp_dev, +- const struct pnp_device_id *dev_id) +-{ +- int retval; +- +- driver.dev = &pnp_dev->dev; +- +- retval = init_chrdev(); +- if (retval < 0) +- return retval; +- +- retval = init_lirc_it87(); +- if (retval) +- goto init_lirc_it87_failed; +- +- return 0; +- +-init_lirc_it87_failed: +- drop_chrdev(); +- +- return retval; +-} +- +-static int __init lirc_it87_init(void) +-{ +- return pnp_register_driver(&it87_pnp_driver); +-} +- +- +-static void __exit lirc_it87_exit(void) +-{ +- drop_hardware(); +- drop_chrdev(); +- drop_port(); +- pnp_unregister_driver(&it87_pnp_driver); +- printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); +-} +- +-/* SECTION: PNP for ITE8704/13/18 */ +- +-static const struct pnp_device_id pnp_dev_table[] = { +- {"ITE8704", 0}, +- {"ITE8713", 0}, +- {} +-}; +- +-MODULE_DEVICE_TABLE(pnp, pnp_dev_table); +- +-static struct pnp_driver it87_pnp_driver = { +- .name = LIRC_DRIVER_NAME, +- .id_table = pnp_dev_table, +- .probe = it87_probe, +-}; +- +-module_init(lirc_it87_init); +-module_exit(lirc_it87_exit); +- +-MODULE_DESCRIPTION("LIRC driver for ITE IT8704/05/12/18/20 CIR port"); +-MODULE_AUTHOR("Hans-Gunter Lutke Uphues"); +-MODULE_LICENSE("GPL"); +- +-module_param(io, int, S_IRUGO); +-MODULE_PARM_DESC(io, "I/O base address (default: 0x310)"); +- +-module_param(irq, int, S_IRUGO); +-#ifdef LIRC_IT87_DIGIMATRIX +-MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 9)"); +-#else +-MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 7)"); +-#endif +- +-module_param(it87_enable_demodulator, bool, S_IRUGO); +-MODULE_PARM_DESC(it87_enable_demodulator, +- "Receiver demodulator enable/disable (1/0), default: 0"); +- +-module_param(debug, bool, S_IRUGO | S_IWUSR); +-MODULE_PARM_DESC(debug, "Enable debugging messages"); +- +-module_param(digimatrix, bool, S_IRUGO | S_IWUSR); +-#ifdef LIRC_IT87_DIGIMATRIX +-MODULE_PARM_DESC(digimatrix, +- "Asus Digimatrix it87 compat. enable/disable (1/0), default: 1"); +-#else +-MODULE_PARM_DESC(digimatrix, +- "Asus Digimatrix it87 compat. enable/disable (1/0), default: 0"); +-#endif +- +- +-module_param(it87_freq, int, S_IRUGO); +-#ifdef LIRC_IT87_DIGIMATRIX +-MODULE_PARM_DESC(it87_freq, +- "Carrier demodulator frequency (kHz), (default: 36)"); +-#else +-MODULE_PARM_DESC(it87_freq, +- "Carrier demodulator frequency (kHz), (default: 38)"); +-#endif +diff -Naur linux-2.6.38-rc5/drivers/staging/lirc/lirc_it87.h linux-2.6.38-rc5.patch/drivers/staging/lirc/lirc_it87.h +--- linux-2.6.38-rc5/drivers/staging/lirc/lirc_it87.h 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.patch/drivers/staging/lirc/lirc_it87.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,116 +0,0 @@ +-/* lirc_it87.h */ +-/* SECTION: Definitions */ +- +-/********************************* ITE IT87xx ************************/ +- +-/* based on the following documentation from ITE: +- a) IT8712F Preliminary CIR Programming Guide V0.1 +- b) IT8705F Simple LPC I/O Preliminary Specification V0.3 +- c) IT8712F EC-LPC I/O Preliminary Specification V0.5 +-*/ +- +-/* IT8712/05 Ports: */ +-#define IT87_ADRPORT 0x2e +-#define IT87_DATAPORT 0x2f +-#define IT87_INIT {0x87, 0x01, 0x55, 0x55} +- +-/* alternate Ports: */ +-/* +-#define IT87_ADRPORT 0x4e +-#define IT87_DATAPORT 0x4f +-#define IT87_INIT {0x87, 0x01, 0x55, 0xaa} +- */ +- +-/* IT8712/05 Registers */ +-#define IT87_CFGCTRL 0x2 +-#define IT87_LDN 0x7 +-#define IT87_CHIP_ID1 0x20 +-#define IT87_CHIP_ID2 0x21 +-#define IT87_CFG_VERSION 0x22 +-#define IT87_SWSUSPEND 0x23 +- +-#define IT8712_CIR_LDN 0xa +-#define IT8705_CIR_LDN 0x7 +- +-/* CIR Configuration Registers: */ +-#define IT87_CIR_ACT 0x30 +-#define IT87_CIR_BASE_MSB 0x60 +-#define IT87_CIR_BASE_LSB 0x61 +-#define IT87_CIR_IRQ 0x70 +-#define IT87_CIR_CONFIG 0xf0 +- +-/* List of IT87_CIR registers: offset to BaseAddr */ +-#define IT87_CIR_DR 0 +-#define IT87_CIR_IER 1 +-#define IT87_CIR_RCR 2 +-#define IT87_CIR_TCR1 3 +-#define IT87_CIR_TCR2 4 +-#define IT87_CIR_TSR 5 +-#define IT87_CIR_RSR 6 +-#define IT87_CIR_BDLR 5 +-#define IT87_CIR_BDHR 6 +-#define IT87_CIR_IIR 7 +- +-/* Bit Definition */ +-/* IER: */ +-#define IT87_CIR_IER_TM_EN 0x80 +-#define IT87_CIR_IER_RESEVED 0x40 +-#define IT87_CIR_IER_RESET 0x20 +-#define IT87_CIR_IER_BR 0x10 +-#define IT87_CIR_IER_IEC 0x8 +-#define IT87_CIR_IER_RFOIE 0x4 +-#define IT87_CIR_IER_RDAIE 0x2 +-#define IT87_CIR_IER_TLDLIE 0x1 +- +-/* RCR: */ +-#define IT87_CIR_RCR_RDWOS 0x80 +-#define IT87_CIR_RCR_HCFS 0x40 +-#define IT87_CIR_RCR_RXEN 0x20 +-#define IT87_CIR_RCR_RXEND 0x10 +-#define IT87_CIR_RCR_RXACT 0x8 +-#define IT87_CIR_RCR_RXDCR 0x7 +- +-/* TCR1: */ +-#define IT87_CIR_TCR1_FIFOCLR 0x80 +-#define IT87_CIR_TCR1_ILE 0x40 +-#define IT87_CIR_TCR1_FIFOTL 0x30 +-#define IT87_CIR_TCR1_TXRLE 0x8 +-#define IT87_CIR_TCR1_TXENDF 0x4 +-#define IT87_CIR_TCR1_TXMPM 0x3 +- +-/* TCR2: */ +-#define IT87_CIR_TCR2_CFQ 0xf8 +-#define IT87_CIR_TCR2_TXMPW 0x7 +- +-/* TSR: */ +-#define IT87_CIR_TSR_RESERVED 0xc0 +-#define IT87_CIR_TSR_TXFBC 0x3f +- +-/* RSR: */ +-#define IT87_CIR_RSR_RXFTO 0x80 +-#define IT87_CIR_RSR_RESERVED 0x40 +-#define IT87_CIR_RSR_RXFBC 0x3f +- +-/* IIR: */ +-#define IT87_CIR_IIR_RESERVED 0xf8 +-#define IT87_CIR_IIR_IID 0x6 +-#define IT87_CIR_IIR_IIP 0x1 +- +-/* TM: */ +-#define IT87_CIR_TM_IL_SEL 0x80 +-#define IT87_CIR_TM_RESERVED 0x40 +-#define IT87_CIR_TM_TM_REG 0x3f +- +-#define IT87_CIR_FIFO_SIZE 32 +- +-/* Baudratedivisor for IT87: power of 2: only 1,2,4 or 8) */ +-#define IT87_CIR_BAUDRATE_DIVISOR 0x1 +-#define IT87_CIR_DEFAULT_IOBASE 0x310 +-#define IT87_CIR_DEFAULT_IRQ 0x7 +-#define IT87_CIR_SPACE 0x00 +-#define IT87_CIR_PULSE 0xff +-#define IT87_CIR_FREQ_MIN 27 +-#define IT87_CIR_FREQ_MAX 58 +-#define TIME_CONST (IT87_CIR_BAUDRATE_DIVISOR * 8000000ul / 115200ul) +- +-/********************************* ITE IT87xx ************************/ +diff -Naur linux-2.6.38-rc5/drivers/staging/lirc/Makefile linux-2.6.38-rc5.patch/drivers/staging/lirc/Makefile +--- linux-2.6.38-rc5/drivers/staging/lirc/Makefile 2011-02-16 04:23:45.000000000 +0100 ++++ linux-2.6.38-rc5.patch/drivers/staging/lirc/Makefile 2011-02-22 03:19:26.756636211 +0100 +@@ -6,7 +6,6 @@ + obj-$(CONFIG_LIRC_BT829) += lirc_bt829.o + obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o + obj-$(CONFIG_LIRC_IMON) += lirc_imon.o +-obj-$(CONFIG_LIRC_IT87) += lirc_it87.o + obj-$(CONFIG_LIRC_ITE8709) += lirc_ite8709.o + obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel.o + obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o diff --git a/projects/ATV/linux/linux.i386.conf b/projects/ATV/linux/linux.i386.conf index 784a27389d..cb16fbac7a 100644 --- a/projects/ATV/linux/linux.i386.conf +++ b/projects/ATV/linux/linux.i386.conf @@ -1289,6 +1289,7 @@ CONFIG_IR_RC5_SZ_DECODER=y # CONFIG_IR_IMON is not set CONFIG_IR_MCEUSB=m # CONFIG_IR_NUVOTON is not set +# CONFIG_IR_ITE_CIR is not set # CONFIG_IR_STREAMZAP is not set # CONFIG_IR_WINBOND_CIR is not set # CONFIG_RC_LOOPBACK is not set diff --git a/projects/Generic/linux/linux.i386.conf b/projects/Generic/linux/linux.i386.conf index 79d1c9f5ce..30ce74ac80 100644 --- a/projects/Generic/linux/linux.i386.conf +++ b/projects/Generic/linux/linux.i386.conf @@ -734,8 +734,44 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_ATA_OVER_ETH is not set # CONFIG_BLK_DEV_HD is not set # CONFIG_BLK_DEV_RBD is not set -# CONFIG_MISC_DEVICES is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_IBM_ASM is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_CS5535_MFGPT is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_VMWARE_BALLOON is not set +# CONFIG_BMP085 is not set +# CONFIG_PCH_PHUB is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set CONFIG_EEPROM_93CX6=m +# CONFIG_CB710_CORE is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1501,9 +1537,32 @@ CONFIG_SSB_SDIOHOST_POSSIBLE=y # CONFIG_SSB_DEBUG is not set CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y CONFIG_SSB_DRIVER_PCICORE=y -# CONFIG_MFD_SUPPORT is not set +CONFIG_MFD_SUPPORT=y CONFIG_MFD_CORE=m +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS6507X is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_CS5535 is not set CONFIG_LPC_SCH=m +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_WL1273_CORE is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=y @@ -1532,6 +1591,7 @@ CONFIG_IR_ENE=m CONFIG_IR_IMON=m CONFIG_IR_MCEUSB=m CONFIG_IR_NUVOTON=m +CONFIG_IR_ITE_CIR=m CONFIG_IR_STREAMZAP=m CONFIG_IR_WINBOND_CIR=m # CONFIG_RC_LOOPBACK is not set @@ -1829,8 +1889,14 @@ CONFIG_FB_VESA=y # CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set # CONFIG_FB_BROADSHEET is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_GENERIC is not set +# CONFIG_BACKLIGHT_PROGEAR is not set +# CONFIG_BACKLIGHT_MBP_NVIDIA is not set +# CONFIG_BACKLIGHT_SAHARA is not set +# CONFIG_BACKLIGHT_ADP8860 is not set # # Display device support diff --git a/projects/ION/linux/linux.i386.conf b/projects/ION/linux/linux.i386.conf index 1fb8668285..f21e3f5e82 100644 --- a/projects/ION/linux/linux.i386.conf +++ b/projects/ION/linux/linux.i386.conf @@ -730,8 +730,44 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_ATA_OVER_ETH is not set # CONFIG_BLK_DEV_HD is not set # CONFIG_BLK_DEV_RBD is not set -# CONFIG_MISC_DEVICES is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_IBM_ASM is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_CS5535_MFGPT is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_VMWARE_BALLOON is not set +# CONFIG_BMP085 is not set +# CONFIG_PCH_PHUB is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set CONFIG_EEPROM_93CX6=m +# CONFIG_CB710_CORE is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1403,9 +1439,32 @@ CONFIG_SSB_POSSIBLE=y # Sonics Silicon Backplane # # CONFIG_SSB is not set -# CONFIG_MFD_SUPPORT is not set +CONFIG_MFD_SUPPORT=y CONFIG_MFD_CORE=m +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS6507X is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_CS5535 is not set CONFIG_LPC_SCH=m +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_WL1273_CORE is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=y @@ -1434,6 +1493,7 @@ CONFIG_IR_ENE=m CONFIG_IR_IMON=m CONFIG_IR_MCEUSB=m CONFIG_IR_NUVOTON=m +CONFIG_IR_ITE_CIR=m CONFIG_IR_STREAMZAP=m CONFIG_IR_WINBOND_CIR=m # CONFIG_RC_LOOPBACK is not set diff --git a/projects/ION/linux/linux.x86_64.conf b/projects/ION/linux/linux.x86_64.conf index afa27505e2..449533c83c 100644 --- a/projects/ION/linux/linux.x86_64.conf +++ b/projects/ION/linux/linux.x86_64.conf @@ -679,8 +679,44 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_ATA_OVER_ETH is not set # CONFIG_BLK_DEV_HD is not set # CONFIG_BLK_DEV_RBD is not set -# CONFIG_MISC_DEVICES is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_IBM_ASM is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_CS5535_MFGPT is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_VMWARE_BALLOON is not set +# CONFIG_BMP085 is not set +# CONFIG_PCH_PHUB is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set CONFIG_EEPROM_93CX6=m +# CONFIG_CB710_CORE is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1345,9 +1381,32 @@ CONFIG_SSB_POSSIBLE=y # Sonics Silicon Backplane # # CONFIG_SSB is not set -# CONFIG_MFD_SUPPORT is not set +CONFIG_MFD_SUPPORT=y CONFIG_MFD_CORE=m +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS6507X is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_CS5535 is not set CONFIG_LPC_SCH=m +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_WL1273_CORE is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=y @@ -1376,6 +1435,7 @@ CONFIG_IR_ENE=m CONFIG_IR_IMON=m CONFIG_IR_MCEUSB=m CONFIG_IR_NUVOTON=m +CONFIG_IR_ITE_CIR=m CONFIG_IR_STREAMZAP=m CONFIG_IR_WINBOND_CIR=m # CONFIG_RC_LOOPBACK is not set @@ -2201,7 +2261,6 @@ CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set CONFIG_LIRC_IGORPLUGUSB=m # CONFIG_LIRC_IMON is not set -CONFIG_LIRC_IT87=m # CONFIG_LIRC_ITE8709 is not set # CONFIG_LIRC_SASEM is not set CONFIG_LIRC_SERIAL=m diff --git a/projects/Intel/linux/linux.i386.conf b/projects/Intel/linux/linux.i386.conf index f87e57232b..75c5ecc45b 100644 --- a/projects/Intel/linux/linux.i386.conf +++ b/projects/Intel/linux/linux.i386.conf @@ -732,8 +732,44 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_ATA_OVER_ETH is not set # CONFIG_BLK_DEV_HD is not set # CONFIG_BLK_DEV_RBD is not set -# CONFIG_MISC_DEVICES is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_IBM_ASM is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_CS5535_MFGPT is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_VMWARE_BALLOON is not set +# CONFIG_BMP085 is not set +# CONFIG_PCH_PHUB is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set CONFIG_EEPROM_93CX6=m +# CONFIG_CB710_CORE is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1365,9 +1401,32 @@ CONFIG_SSB_POSSIBLE=y # Sonics Silicon Backplane # # CONFIG_SSB is not set -# CONFIG_MFD_SUPPORT is not set +CONFIG_MFD_SUPPORT=y CONFIG_MFD_CORE=m +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS6507X is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_CS5535 is not set CONFIG_LPC_SCH=m +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_WL1273_CORE is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=y @@ -1396,6 +1455,7 @@ CONFIG_IR_ENE=m CONFIG_IR_IMON=m CONFIG_IR_MCEUSB=m CONFIG_IR_NUVOTON=m +CONFIG_IR_ITE_CIR=m CONFIG_IR_STREAMZAP=m CONFIG_IR_WINBOND_CIR=m # CONFIG_RC_LOOPBACK is not set @@ -1686,8 +1746,14 @@ CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set # CONFIG_FB_BROADSHEET is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_GENERIC is not set +# CONFIG_BACKLIGHT_PROGEAR is not set +# CONFIG_BACKLIGHT_MBP_NVIDIA is not set +# CONFIG_BACKLIGHT_SAHARA is not set +# CONFIG_BACKLIGHT_ADP8860 is not set # # Display device support diff --git a/projects/Intel/linux/linux.x86_64.conf b/projects/Intel/linux/linux.x86_64.conf index 8daaa61182..a6a9749dec 100644 --- a/projects/Intel/linux/linux.x86_64.conf +++ b/projects/Intel/linux/linux.x86_64.conf @@ -682,8 +682,44 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_ATA_OVER_ETH is not set # CONFIG_BLK_DEV_HD is not set # CONFIG_BLK_DEV_RBD is not set -# CONFIG_MISC_DEVICES is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_IBM_ASM is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_CS5535_MFGPT is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_VMWARE_BALLOON is not set +# CONFIG_BMP085 is not set +# CONFIG_PCH_PHUB is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set CONFIG_EEPROM_93CX6=m +# CONFIG_CB710_CORE is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1309,9 +1345,32 @@ CONFIG_SSB_POSSIBLE=y # Sonics Silicon Backplane # # CONFIG_SSB is not set -# CONFIG_MFD_SUPPORT is not set +CONFIG_MFD_SUPPORT=y CONFIG_MFD_CORE=m +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS6507X is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_CS5535 is not set CONFIG_LPC_SCH=m +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_WL1273_CORE is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=y @@ -1340,6 +1399,7 @@ CONFIG_IR_ENE=m CONFIG_IR_IMON=m CONFIG_IR_MCEUSB=m CONFIG_IR_NUVOTON=m +CONFIG_IR_ITE_CIR=m CONFIG_IR_STREAMZAP=m CONFIG_IR_WINBOND_CIR=m # CONFIG_RC_LOOPBACK is not set @@ -1626,8 +1686,14 @@ CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set # CONFIG_FB_BROADSHEET is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_GENERIC is not set +# CONFIG_BACKLIGHT_PROGEAR is not set +# CONFIG_BACKLIGHT_MBP_NVIDIA is not set +# CONFIG_BACKLIGHT_SAHARA is not set +# CONFIG_BACKLIGHT_ADP8860 is not set # # Display device support From aadac6c0330a3bd9f5db0c393d6abfcb168a6069 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 13:51:24 +0100 Subject: [PATCH 13/16] xf86-video-nouveau: update to xf86-video-nouveau-20110222 Signed-off-by: Stephan Raue --- packages/x11/driver/xf86-video-nouveau/meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x11/driver/xf86-video-nouveau/meta b/packages/x11/driver/xf86-video-nouveau/meta index 292ea19b89..db6f13934b 100644 --- a/packages/x11/driver/xf86-video-nouveau/meta +++ b/packages/x11/driver/xf86-video-nouveau/meta @@ -19,7 +19,7 @@ ################################################################################ PKG_NAME="xf86-video-nouveau" -PKG_VERSION="20110111" +PKG_VERSION="20110222" PKG_REV="1" PKG_ARCH="i386 x86_64" PKG_LICENSE="OSS" From 9bec7052ba2cd57b766d38a19415ee2464bc19b5 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 13:52:53 +0100 Subject: [PATCH 14/16] linux: update to linux-2.6.38-rc6 Signed-off-by: Stephan Raue --- packages/linux/meta | 2 +- ...osscompile.patch => linux-2.6.38-rc6-000_crosscompile.patch} | 0 ...ature.patch => linux-2.6.38-rc6-002_bash_only_feature.patch} | 0 ..._console.patch => linux-2.6.38-rc6-003-no_dev_console.patch} | 0 ... => linux-2.6.38-rc6-004_lower_undefined_mode_timeout.patch} | 0 ...mp.patch => linux-2.6.38-rc6-005_kconfig_no_timestamp.patch} | 0 ...enable_utf8.patch => linux-2.6.38-rc6-006_enable_utf8.patch} | 0 ...oppy_die.patch => linux-2.6.38-rc6-007_die_floppy_die.patch} | 0 ...linux-2.6.38-rc6-008-hda_intel_prealloc_4mb_dmabuffer.patch} | 0 ...linux-2.6.38-rc6-009_disable_i8042_check_on_apple_mac.patch} | 0 ....patch => linux-2.6.38-rc6-050_add_appleir_usb_driver.patch} | 0 ....patch => linux-2.6.38-rc6-051_add_ite-cir_driver-0.1.patch} | 0 ...patch => linux-2.6.38-rc6-052-aureal_remote_quirk-0.1.patch} | 0 ...-2.6.38-rc6-053_ati-remote_all_keys_and_keychange-0.1.patch} | 0 ...x-2.6.38-rc6-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch} | 0 ...=> linux-2.6.38-rc6-110-drm_nouveau_upstream-20110222.patch} | 0 16 files changed, 1 insertion(+), 1 deletion(-) rename packages/linux/patches/{linux-2.6.38-rc5-000_crosscompile.patch => linux-2.6.38-rc6-000_crosscompile.patch} (100%) rename packages/linux/patches/{linux-2.6.38-rc5-002_bash_only_feature.patch => linux-2.6.38-rc6-002_bash_only_feature.patch} (100%) rename packages/linux/patches/{linux-2.6.38-rc5-003-no_dev_console.patch => linux-2.6.38-rc6-003-no_dev_console.patch} (100%) rename packages/linux/patches/{linux-2.6.38-rc5-004_lower_undefined_mode_timeout.patch => linux-2.6.38-rc6-004_lower_undefined_mode_timeout.patch} (100%) rename packages/linux/patches/{linux-2.6.38-rc5-005_kconfig_no_timestamp.patch => linux-2.6.38-rc6-005_kconfig_no_timestamp.patch} (100%) rename packages/linux/patches/{linux-2.6.38-rc5-006_enable_utf8.patch => linux-2.6.38-rc6-006_enable_utf8.patch} (100%) rename packages/linux/patches/{linux-2.6.38-rc5-007_die_floppy_die.patch => linux-2.6.38-rc6-007_die_floppy_die.patch} (100%) rename packages/linux/patches/{linux-2.6.38-rc5-008-hda_intel_prealloc_4mb_dmabuffer.patch => linux-2.6.38-rc6-008-hda_intel_prealloc_4mb_dmabuffer.patch} (100%) rename packages/linux/patches/{linux-2.6.38-rc5-009_disable_i8042_check_on_apple_mac.patch => linux-2.6.38-rc6-009_disable_i8042_check_on_apple_mac.patch} (100%) rename packages/linux/patches/{linux-2.6.38-rc5-050_add_appleir_usb_driver.patch => linux-2.6.38-rc6-050_add_appleir_usb_driver.patch} (100%) rename packages/linux/patches/{linux-2.6.38-rc5-051_add_ite-cir_driver-0.1.patch => linux-2.6.38-rc6-051_add_ite-cir_driver-0.1.patch} (100%) rename packages/linux/patches/{linux-2.6.38-rc5-052-aureal_remote_quirk-0.1.patch => linux-2.6.38-rc6-052-aureal_remote_quirk-0.1.patch} (100%) rename packages/linux/patches/{linux-2.6.38-rc5-053_ati-remote_all_keys_and_keychange-0.1.patch => linux-2.6.38-rc6-053_ati-remote_all_keys_and_keychange-0.1.patch} (100%) rename packages/linux/patches/{linux-2.6.38-rc5-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch => linux-2.6.38-rc6-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch} (100%) rename packages/linux/patches/{linux-2.6.38-rc5-110-drm_nouveau_upstream-20110222.patch => linux-2.6.38-rc6-110-drm_nouveau_upstream-20110222.patch} (100%) diff --git a/packages/linux/meta b/packages/linux/meta index 0a0e7c83d5..b18e0ac9f1 100644 --- a/packages/linux/meta +++ b/packages/linux/meta @@ -19,7 +19,7 @@ ################################################################################ PKG_NAME="linux" -PKG_VERSION="2.6.38-rc5" +PKG_VERSION="2.6.38-rc6" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" diff --git a/packages/linux/patches/linux-2.6.38-rc5-000_crosscompile.patch b/packages/linux/patches/linux-2.6.38-rc6-000_crosscompile.patch similarity index 100% rename from packages/linux/patches/linux-2.6.38-rc5-000_crosscompile.patch rename to packages/linux/patches/linux-2.6.38-rc6-000_crosscompile.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-002_bash_only_feature.patch b/packages/linux/patches/linux-2.6.38-rc6-002_bash_only_feature.patch similarity index 100% rename from packages/linux/patches/linux-2.6.38-rc5-002_bash_only_feature.patch rename to packages/linux/patches/linux-2.6.38-rc6-002_bash_only_feature.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-003-no_dev_console.patch b/packages/linux/patches/linux-2.6.38-rc6-003-no_dev_console.patch similarity index 100% rename from packages/linux/patches/linux-2.6.38-rc5-003-no_dev_console.patch rename to packages/linux/patches/linux-2.6.38-rc6-003-no_dev_console.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-004_lower_undefined_mode_timeout.patch b/packages/linux/patches/linux-2.6.38-rc6-004_lower_undefined_mode_timeout.patch similarity index 100% rename from packages/linux/patches/linux-2.6.38-rc5-004_lower_undefined_mode_timeout.patch rename to packages/linux/patches/linux-2.6.38-rc6-004_lower_undefined_mode_timeout.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-005_kconfig_no_timestamp.patch b/packages/linux/patches/linux-2.6.38-rc6-005_kconfig_no_timestamp.patch similarity index 100% rename from packages/linux/patches/linux-2.6.38-rc5-005_kconfig_no_timestamp.patch rename to packages/linux/patches/linux-2.6.38-rc6-005_kconfig_no_timestamp.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-006_enable_utf8.patch b/packages/linux/patches/linux-2.6.38-rc6-006_enable_utf8.patch similarity index 100% rename from packages/linux/patches/linux-2.6.38-rc5-006_enable_utf8.patch rename to packages/linux/patches/linux-2.6.38-rc6-006_enable_utf8.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-007_die_floppy_die.patch b/packages/linux/patches/linux-2.6.38-rc6-007_die_floppy_die.patch similarity index 100% rename from packages/linux/patches/linux-2.6.38-rc5-007_die_floppy_die.patch rename to packages/linux/patches/linux-2.6.38-rc6-007_die_floppy_die.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-008-hda_intel_prealloc_4mb_dmabuffer.patch b/packages/linux/patches/linux-2.6.38-rc6-008-hda_intel_prealloc_4mb_dmabuffer.patch similarity index 100% rename from packages/linux/patches/linux-2.6.38-rc5-008-hda_intel_prealloc_4mb_dmabuffer.patch rename to packages/linux/patches/linux-2.6.38-rc6-008-hda_intel_prealloc_4mb_dmabuffer.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-009_disable_i8042_check_on_apple_mac.patch b/packages/linux/patches/linux-2.6.38-rc6-009_disable_i8042_check_on_apple_mac.patch similarity index 100% rename from packages/linux/patches/linux-2.6.38-rc5-009_disable_i8042_check_on_apple_mac.patch rename to packages/linux/patches/linux-2.6.38-rc6-009_disable_i8042_check_on_apple_mac.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-050_add_appleir_usb_driver.patch b/packages/linux/patches/linux-2.6.38-rc6-050_add_appleir_usb_driver.patch similarity index 100% rename from packages/linux/patches/linux-2.6.38-rc5-050_add_appleir_usb_driver.patch rename to packages/linux/patches/linux-2.6.38-rc6-050_add_appleir_usb_driver.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-051_add_ite-cir_driver-0.1.patch b/packages/linux/patches/linux-2.6.38-rc6-051_add_ite-cir_driver-0.1.patch similarity index 100% rename from packages/linux/patches/linux-2.6.38-rc5-051_add_ite-cir_driver-0.1.patch rename to packages/linux/patches/linux-2.6.38-rc6-051_add_ite-cir_driver-0.1.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-052-aureal_remote_quirk-0.1.patch b/packages/linux/patches/linux-2.6.38-rc6-052-aureal_remote_quirk-0.1.patch similarity index 100% rename from packages/linux/patches/linux-2.6.38-rc5-052-aureal_remote_quirk-0.1.patch rename to packages/linux/patches/linux-2.6.38-rc6-052-aureal_remote_quirk-0.1.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-053_ati-remote_all_keys_and_keychange-0.1.patch b/packages/linux/patches/linux-2.6.38-rc6-053_ati-remote_all_keys_and_keychange-0.1.patch similarity index 100% rename from packages/linux/patches/linux-2.6.38-rc5-053_ati-remote_all_keys_and_keychange-0.1.patch rename to packages/linux/patches/linux-2.6.38-rc6-053_ati-remote_all_keys_and_keychange-0.1.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch b/packages/linux/patches/linux-2.6.38-rc6-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch similarity index 100% rename from packages/linux/patches/linux-2.6.38-rc5-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch rename to packages/linux/patches/linux-2.6.38-rc6-062-Pioneer_DVR-216D_failed_xfermode-0.1.patch diff --git a/packages/linux/patches/linux-2.6.38-rc5-110-drm_nouveau_upstream-20110222.patch b/packages/linux/patches/linux-2.6.38-rc6-110-drm_nouveau_upstream-20110222.patch similarity index 100% rename from packages/linux/patches/linux-2.6.38-rc5-110-drm_nouveau_upstream-20110222.patch rename to packages/linux/patches/linux-2.6.38-rc6-110-drm_nouveau_upstream-20110222.patch From 165c0a4f276afb904bc2b455f4851ecc8e36ec79 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 15:02:04 +0100 Subject: [PATCH 15/16] linux: update nouveau upstream patch Signed-off-by: Stephan Raue --- ...c6-110-drm_nouveau_upstream-20110222.patch | 430 +++++------------- 1 file changed, 115 insertions(+), 315 deletions(-) diff --git a/packages/linux/patches/linux-2.6.38-rc6-110-drm_nouveau_upstream-20110222.patch b/packages/linux/patches/linux-2.6.38-rc6-110-drm_nouveau_upstream-20110222.patch index 364b99654c..32cbe2de6d 100644 --- a/packages/linux/patches/linux-2.6.38-rc6-110-drm_nouveau_upstream-20110222.patch +++ b/packages/linux/patches/linux-2.6.38-rc6-110-drm_nouveau_upstream-20110222.patch @@ -1,6 +1,6 @@ -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bios.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bios.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_bios.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bios.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_bios.c 2011-02-22 14:25:08.609606768 +0100 @@ -282,7 +282,7 @@ { #if 0 @@ -85,15 +85,6 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bios.c linux-2.6.38- if (cte->type == 0xff) continue; -@@ -6228,7 +6219,7 @@ - entry->tvconf.has_component_output = false; - break; - case OUTPUT_LVDS: -- if ((conn & 0x00003f00) != 0x10) -+ if ((conn & 0x00003f00) >> 8 != 0x10) - entry->lvdsconf.use_straps_for_mode = true; - entry->lvdsconf.use_power_scripts = true; - break; @@ -6702,11 +6693,11 @@ struct nvbios *bios = &dev_priv->vbios; struct init_exec iexec = { true, false }; @@ -117,9 +108,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bios.c linux-2.6.38- bios->dev = dev; if (!NVShadowVBIOS(dev, bios->data)) -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bios.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.h +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bios.h linux-2.6/drivers/gpu/drm/nouveau/nouveau_bios.h --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bios.h 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_bios.h 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_bios.h 2011-02-22 14:16:21.580230479 +0100 @@ -251,7 +251,7 @@ uint8_t digital_min_front_porch; bool fp_no_ddc; @@ -129,9 +120,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bios.h linux-2.6.38- uint8_t data[NV_PROM_SIZE]; unsigned int length; -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_bo.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_bo.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_bo.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_bo.c 2011-02-22 14:32:02.564311615 +0100 @@ -54,8 +54,8 @@ } @@ -181,15 +172,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift, NV_MEM_ACCESS_RW, &nvbo->vma); if (ret) { -@@ -128,6 +125,7 @@ - } - } - -+ nvbo->bo.mem.num_pages = size >> PAGE_SHIFT; - nouveau_bo_placement_set(nvbo, flags, 0); - - nvbo->channel = chan; -@@ -140,11 +138,8 @@ +@@ -140,11 +137,8 @@ } nvbo->channel = NULL; @@ -203,28 +186,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc *pnvbo = nvbo; return 0; } -@@ -166,17 +161,17 @@ - set_placement_range(struct nouveau_bo *nvbo, uint32_t type) - { - struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); -+ int vram_pages = dev_priv->vram_size >> PAGE_SHIFT; - - if (dev_priv->card_type == NV_10 && -- nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM)) { -+ nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) && -+ nvbo->bo.mem.num_pages < vram_pages / 2) { - /* - * Make sure that the color and depth buffers are handled - * by independent memory controller units. Up to a 9x - * speed up when alpha-blending and depth-test are enabled - * at the same time. - */ -- int vram_pages = dev_priv->vram_size >> PAGE_SHIFT; -- - if (nvbo->tile_flags & NOUVEAU_GEM_TILE_ZETA) { - nvbo->placement.fpfn = vram_pages / 2; - nvbo->placement.lpfn = ~0; -@@ -314,11 +309,8 @@ +@@ -314,11 +308,8 @@ if (ret) return ret; @@ -238,7 +200,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc return 0; } -@@ -381,7 +373,8 @@ +@@ -381,7 +372,8 @@ case NOUVEAU_GART_AGP: return ttm_agp_backend_init(bdev, dev->agp->bridge); #endif @@ -248,7 +210,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc return nouveau_sgdma_init_ttm(dev); default: NV_ERROR(dev, "Unknown GART type %d\n", -@@ -427,7 +420,10 @@ +@@ -427,7 +419,10 @@ man->default_caching = TTM_PL_FLAG_WC; break; case TTM_PL_TT: @@ -260,7 +222,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc switch (dev_priv->gart_info.type) { case NOUVEAU_GART_AGP: man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; -@@ -435,7 +431,8 @@ +@@ -435,7 +430,8 @@ TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; break; @@ -270,7 +232,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA; man->available_caching = TTM_PL_MASK_CACHING; -@@ -497,45 +494,22 @@ +@@ -497,45 +493,22 @@ return ret; } @@ -324,7 +286,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc page_count = new_mem->num_pages; while (page_count) { -@@ -570,33 +544,18 @@ +@@ -570,33 +543,18 @@ 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) { @@ -365,7 +327,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc while (length) { u32 amount, stride, height; -@@ -677,6 +636,15 @@ +@@ -677,6 +635,15 @@ return 0; } @@ -381,7 +343,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc static int nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) -@@ -730,15 +698,43 @@ +@@ -730,15 +697,43 @@ { struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); struct nouveau_bo *nvbo = nouveau_bo(bo); @@ -426,7 +388,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc if (dev_priv->card_type < NV_50) ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem); else -@@ -752,6 +748,7 @@ +@@ -752,6 +747,7 @@ no_wait_gpu, new_mem); } @@ -434,7 +396,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc if (chan == dev_priv->channel) mutex_unlock(&chan->mutex); return ret; -@@ -762,6 +759,7 @@ +@@ -762,6 +758,7 @@ bool no_wait_reserve, bool no_wait_gpu, struct ttm_mem_reg *new_mem) { @@ -442,7 +404,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; struct ttm_placement placement; struct ttm_mem_reg tmp_mem; -@@ -781,11 +779,27 @@ +@@ -781,7 +778,23 @@ if (ret) goto out; @@ -466,26 +428,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc if (ret) goto out; -- ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); -+ ret = ttm_bo_move_ttm(bo, true, no_wait_reserve, no_wait_gpu, new_mem); - out: - ttm_bo_mem_put(bo, &tmp_mem); - return ret; -@@ -811,11 +825,11 @@ - if (ret) - return ret; - -- ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, &tmp_mem); -+ ret = ttm_bo_move_ttm(bo, true, no_wait_reserve, no_wait_gpu, &tmp_mem); - if (ret) - goto out; - -- ret = nouveau_bo_move_m2mf(bo, evict, intr, no_wait_reserve, no_wait_gpu, new_mem); -+ ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, new_mem); - if (ret) - goto out; - -@@ -824,6 +838,36 @@ +@@ -824,6 +837,36 @@ return ret; } @@ -522,7 +465,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc static int nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, struct nouveau_tile_reg **new_tile) -@@ -831,19 +875,13 @@ +@@ -831,19 +874,13 @@ struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); struct drm_device *dev = dev_priv->dev; struct nouveau_bo *nvbo = nouveau_bo(bo); @@ -546,7 +489,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc *new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size, nvbo->tile_mode, nvbo->tile_flags); -@@ -860,11 +898,8 @@ +@@ -860,11 +897,8 @@ struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); struct drm_device *dev = dev_priv->dev; @@ -560,7 +503,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc } static int -@@ -878,9 +913,11 @@ +@@ -878,9 +912,11 @@ struct nouveau_tile_reg *new_tile = NULL; int ret = 0; @@ -575,7 +518,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc /* Fake bo copy. */ if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { -@@ -911,10 +948,12 @@ +@@ -911,10 +947,12 @@ ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); out: @@ -592,7 +535,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc return ret; } -@@ -955,7 +994,7 @@ +@@ -955,7 +993,7 @@ break; case TTM_PL_VRAM: { @@ -601,7 +544,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc u8 page_shift; if (!dev_priv->bar1_vm) { -@@ -966,23 +1005,23 @@ +@@ -966,23 +1004,23 @@ } if (dev_priv->card_type == NV_C0) @@ -630,7 +573,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc if (dev_priv->card_type == NV_50) /*XXX*/ mem->bus.offset -= 0x0020000000ULL; mem->bus.base = pci_resource_start(dev->pdev, 1); -@@ -999,16 +1038,16 @@ +@@ -999,16 +1037,16 @@ nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); @@ -651,7 +594,7 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc } static int -@@ -1058,6 +1097,7 @@ +@@ -1058,6 +1096,7 @@ .invalidate_caches = nouveau_bo_invalidate_caches, .init_mem_type = nouveau_bo_init_mem_type, .evict_flags = nouveau_bo_evict_flags, @@ -659,9 +602,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_bo.c linux-2.6.38-rc .move = nouveau_bo_move, .verify_access = nouveau_bo_verify_access, .sync_obj_signaled = __nouveau_fence_signalled, -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_channel.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_channel.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_channel.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_channel.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_channel.c 2011-02-22 14:16:21.581230459 +0100 @@ -35,7 +35,7 @@ struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_bo *pb = chan->pushbuf_bo; @@ -681,20 +624,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_channel.c linux-2.6. if (ret) { NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret); return NULL; -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_connector.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.c ---- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_connector.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_connector.c 2011-02-20 23:32:11.000000000 +0100 -@@ -507,6 +507,7 @@ - int high_w = 0, high_h = 0, high_v = 0; - - list_for_each_entry(mode, &nv_connector->base.probed_modes, head) { -+ mode->vrefresh = drm_mode_vrefresh(mode); - if (helper->mode_valid(connector, mode) != MODE_OK || - (mode->flags & DRM_MODE_FLAG_INTERLACE)) - continue; -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_display.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_display.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_display.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_display.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_display.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_display.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_display.c 2011-02-22 14:16:21.582230439 +0100 @@ -32,6 +32,7 @@ #include "nouveau_hw.h" #include "nouveau_crtc.h" @@ -826,9 +758,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_display.c linux-2.6. kfree(s); spin_unlock_irqrestore(&dev->event_lock, flags); -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dma.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dma.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_dma.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dma.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_dma.c 2011-02-22 14:16:21.582230439 +0100 @@ -96,13 +96,15 @@ OUT_RING(chan, 0); @@ -849,9 +781,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dma.c linux-2.6.38-r /* Sit back and pray the channel works.. */ FIRE_RING(chan); -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dma.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.h +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dma.h linux-2.6/drivers/gpu/drm/nouveau/nouveau_dma.h --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dma.h 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_dma.h 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_dma.h 2011-02-22 14:16:21.582230439 +0100 @@ -61,8 +61,6 @@ NvM2MF = 0x80000001, NvDmaFB = 0x80000002, @@ -878,9 +810,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dma.h linux-2.6.38-r }; #define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039 -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dp.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_dp.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dp.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_dp.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dp.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_dp.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_dp.c 2011-02-22 14:16:21.582230439 +0100 @@ -175,7 +175,6 @@ { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); @@ -897,9 +829,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_dp.c linux-2.6.38-rc ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2); if (ret) -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.h +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6/drivers/gpu/drm/nouveau/nouveau_drv.h --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_drv.h 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_drv.h 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_drv.h 2011-02-22 14:16:21.583230419 +0100 @@ -57,7 +57,7 @@ #include "nouveau_util.h" @@ -1042,9 +974,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.38-r extern int nouveau_gem_object_new(struct drm_gem_object *); extern void nouveau_gem_object_del(struct drm_gem_object *); extern int nouveau_gem_ioctl_new(struct drm_device *, void *, -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_fbcon.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2011-02-22 14:16:21.584230398 +0100 @@ -296,8 +296,8 @@ size = mode_cmd.pitch * mode_cmd.height; size = roundup(size, PAGE_SIZE); @@ -1056,9 +988,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-2.6.38 if (ret) { NV_ERROR(dev, "failed to allocate framebuffer\n"); goto out; -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fb.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_fb.h +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fb.h linux-2.6/drivers/gpu/drm/nouveau/nouveau_fb.h --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fb.h 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_fb.h 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_fb.h 2011-02-22 14:16:21.584230398 +0100 @@ -30,6 +30,9 @@ struct nouveau_framebuffer { struct drm_framebuffer base; @@ -1069,9 +1001,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fb.h linux-2.6.38-rc }; static inline struct nouveau_framebuffer * -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_fence.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_fence.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fence.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_fence.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_fence.c 2011-02-22 14:16:21.584230398 +0100 @@ -32,8 +32,7 @@ #include "nouveau_dma.h" @@ -1389,9 +1321,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.38 if (ret) return ret; -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_gem.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_gem.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_gem.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_gem.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_gem.c 2011-02-22 14:16:21.585230377 +0100 @@ -61,19 +61,36 @@ int @@ -1485,9 +1417,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.38-r (write_domains ? write_domains : read_domains); uint32_t pref_flags = 0, valid_flags = 0; -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_mem.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_mem.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_mem.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_mem.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_mem.c 2011-02-22 14:16:21.587230337 +0100 @@ -152,7 +152,6 @@ { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -1683,9 +1615,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_mem.c linux-2.6.38-r + nouveau_gart_manager_del, + nouveau_gart_manager_debug +}; -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_mm.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_mm.h +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_mm.h linux-2.6/drivers/gpu/drm/nouveau/nouveau_mm.h --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_mm.h 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_mm.h 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_mm.h 2011-02-22 14:16:21.587230337 +0100 @@ -53,13 +53,13 @@ int nv50_vram_init(struct drm_device *); @@ -1703,9 +1635,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_mm.h linux-2.6.38-rc bool nvc0_vram_flags_valid(struct drm_device *, u32 tile_flags); #endif -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_notifier.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_notifier.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_notifier.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_notifier.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_notifier.c 2011-02-22 14:16:21.587230337 +0100 @@ -39,12 +39,11 @@ int ret; @@ -1752,9 +1684,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-2.6 offset += mem->start; ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset, -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_object.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_object.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_object.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_object.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_object.c 2011-02-22 14:16:21.588230317 +0100 @@ -36,6 +36,7 @@ #include "nouveau_drm.h" #include "nouveau_ramht.h" @@ -1829,21 +1761,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_object.c linux-2.6.3 } /* VRAM ctxdma */ -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_pm.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.c ---- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_pm.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_pm.c 2011-02-20 23:32:11.000000000 +0100 -@@ -543,7 +543,7 @@ - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - struct nouveau_pm_level *perflvl; - -- if (pm->cur == &pm->boot) -+ if (!pm->cur || pm->cur == &pm->boot) - return; - - perflvl = pm->cur; -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_ramht.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_ramht.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_ramht.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_ramht.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_ramht.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_ramht.c 2011-02-22 14:16:21.589230297 +0100 @@ -114,7 +114,9 @@ (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); } else { @@ -1855,9 +1775,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_ramht.c linux-2.6.38 } else { ctx = (gpuobj->cinst >> 4) | ((gpuobj->engine << -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_sgdma.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_sgdma.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_sgdma.c 2011-02-22 14:16:21.589230297 +0100 @@ -74,8 +74,24 @@ } } @@ -2292,9 +2212,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-2.6.38 } uint32_t -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_state.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_state.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_state.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_state.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_state.c 2011-02-22 14:16:21.590230277 +0100 @@ -544,7 +544,6 @@ nouveau_card_init_channel(struct drm_device *dev) { @@ -2385,9 +2305,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.38 break; case NOUVEAU_GETPARAM_GRAPH_UNITS: /* NV40 and NV50 versions are quite different, but register -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_temp.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_temp.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_temp.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_temp.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_temp.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_temp.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_temp.c 2011-02-22 14:16:21.590230277 +0100 @@ -239,11 +239,9 @@ probe_monitoring_device(struct nouveau_i2c_chan *i2c, struct i2c_board_info *info) @@ -2401,9 +2321,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_temp.c linux-2.6.38- client = i2c_new_device(&i2c->adapter, info); if (!client) -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_vm.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_vm.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_vm.c linux-2.6/drivers/gpu/drm/nouveau/nouveau_vm.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_vm.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_vm.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_vm.c 2011-02-22 14:16:21.591230257 +0100 @@ -28,7 +28,7 @@ #include "nouveau_vm.h" @@ -2468,9 +2388,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_vm.c linux-2.6.38-rc num -= len; pte += len; -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_vm.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_vm.h +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_vm.h linux-2.6/drivers/gpu/drm/nouveau/nouveau_vm.h --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_vm.h 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nouveau_vm.h 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nouveau_vm.h 2011-02-22 14:16:21.591230257 +0100 @@ -67,9 +67,10 @@ void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde, struct nouveau_gpuobj *pgt[2]); @@ -2522,9 +2442,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nouveau_vm.h linux-2.6.38-rc void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); void nvc0_vm_flush(struct nouveau_vm *); -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv04_crtc.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6/drivers/gpu/drm/nouveau/nv04_crtc.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_crtc.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv04_crtc.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv04_crtc.c 2011-02-22 14:16:21.592230236 +0100 @@ -1031,7 +1031,7 @@ drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); @@ -2534,46 +2454,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_crtc.c linux-2.6.38-rc5 if (!ret) { ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); if (!ret) -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_dfp.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv04_dfp.c ---- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_dfp.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv04_dfp.c 2011-02-20 23:32:11.000000000 +0100 -@@ -342,8 +342,8 @@ - if (nv_encoder->dcb->type == OUTPUT_LVDS) { - bool duallink, dummy; - -- nouveau_bios_parse_lvds_table(dev, nv_connector->native_mode-> -- clock, &duallink, &dummy); -+ nouveau_bios_parse_lvds_table(dev, output_mode->clock, -+ &duallink, &dummy); - if (duallink) - regp->fp_control |= (8 << 28); - } else -@@ -518,8 +518,6 @@ - return; - - if (nv_encoder->dcb->lvdsconf.use_power_scripts) { -- struct nouveau_connector *nv_connector = nouveau_encoder_connector_get(nv_encoder); -- - /* when removing an output, crtc may not be set, but PANEL_OFF - * must still be run - */ -@@ -527,12 +525,8 @@ - nv04_dfp_get_bound_head(dev, nv_encoder->dcb); - - if (mode == DRM_MODE_DPMS_ON) { -- if (!nv_connector->native_mode) { -- NV_ERROR(dev, "Not turning on LVDS without native mode\n"); -- return; -- } - call_lvds_script(dev, nv_encoder->dcb, head, -- LVDS_PANEL_ON, nv_connector->native_mode->clock); -+ LVDS_PANEL_ON, nv_encoder->mode.clock); - } else - /* pxclk of 0 is fine for PANEL_OFF, and for a - * disconnected LVDS encoder there is no native_mode -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_fifo.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv04_fifo.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_fifo.c linux-2.6/drivers/gpu/drm/nouveau/nv04_fifo.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_fifo.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv04_fifo.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv04_fifo.c 2011-02-22 14:16:21.593230215 +0100 @@ -379,6 +379,15 @@ return handled; } @@ -2614,9 +2497,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv04_fifo.c linux-2.6.38-rc5 if (dma_get != dma_put) nv_wr32(dev, 0x003244, dma_put); -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv40_fb.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv40_fb.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv40_fb.c linux-2.6/drivers/gpu/drm/nouveau/nv40_fb.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv40_fb.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv40_fb.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv40_fb.c 2011-02-22 14:16:21.596230155 +0100 @@ -24,6 +24,53 @@ } } @@ -2690,92 +2573,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv40_fb.c linux-2.6.38-rc5.n switch (dev_priv->chipset) { case 0x40: -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv40_graph.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv40_graph.c ---- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv40_graph.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv40_graph.c 2011-02-20 23:32:11.000000000 +0100 -@@ -211,18 +211,32 @@ - struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - - switch (dev_priv->chipset) { -+ case 0x40: -+ case 0x41: /* guess */ -+ case 0x42: -+ case 0x43: -+ case 0x45: /* guess */ -+ case 0x4e: -+ nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); -+ nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); -+ nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); -+ nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch); -+ nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit); -+ nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr); -+ break; - case 0x44: - case 0x4a: -- case 0x4e: - nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); - break; -- - case 0x46: - case 0x47: - case 0x49: - case 0x4b: -+ case 0x4c: -+ case 0x67: -+ default: - nv_wr32(dev, NV47_PGRAPH_TSIZE(i), tile->pitch); - nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), tile->limit); - nv_wr32(dev, NV47_PGRAPH_TILE(i), tile->addr); -@@ -230,15 +244,6 @@ - nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit); - nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr); - break; -- -- default: -- nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); -- nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); -- nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); -- nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch); -- nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit); -- nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr); -- break; - } - } - -@@ -396,17 +401,20 @@ - break; - default: - switch (dev_priv->chipset) { -- case 0x46: -- case 0x47: -- case 0x49: -- case 0x4b: -- nv_wr32(dev, 0x400DF0, nv_rd32(dev, NV04_PFB_CFG0)); -- nv_wr32(dev, 0x400DF4, nv_rd32(dev, NV04_PFB_CFG1)); -- break; -- default: -+ case 0x41: -+ case 0x42: -+ case 0x43: -+ case 0x45: -+ case 0x4e: -+ case 0x44: -+ case 0x4a: - nv_wr32(dev, 0x4009F0, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x4009F4, nv_rd32(dev, NV04_PFB_CFG1)); - break; -+ default: -+ nv_wr32(dev, 0x400DF0, nv_rd32(dev, NV04_PFB_CFG0)); -+ nv_wr32(dev, 0x400DF4, nv_rd32(dev, NV04_PFB_CFG1)); -+ break; - } - nv_wr32(dev, 0x4069F0, nv_rd32(dev, NV04_PFB_CFG0)); - nv_wr32(dev, 0x4069F4, nv_rd32(dev, NV04_PFB_CFG1)); -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_crtc.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6/drivers/gpu/drm/nouveau/nv50_crtc.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_crtc.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_crtc.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv50_crtc.c 2011-02-22 14:16:21.598230115 +0100 @@ -65,7 +65,7 @@ { struct drm_device *dev = nv_crtc->base.dev; @@ -3074,9 +2874,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_crtc.c linux-2.6.38-rc5 if (!ret) { ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); if (!ret) -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_cursor.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_cursor.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_cursor.c linux-2.6/drivers/gpu/drm/nouveau/nv50_cursor.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_cursor.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_cursor.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv50_cursor.c 2011-02-22 14:16:21.598230115 +0100 @@ -36,9 +36,9 @@ static void nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update) @@ -3101,9 +2901,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_cursor.c linux-2.6.38-r int ret; NV_DEBUG_KMS(dev, "\n"); -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_dac.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_dac.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_dac.c linux-2.6/drivers/gpu/drm/nouveau/nv50_dac.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_dac.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_dac.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv50_dac.c 2011-02-22 14:16:21.599230095 +0100 @@ -41,8 +41,7 @@ { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); @@ -3124,9 +2924,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_dac.c linux-2.6.38-rc5. struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); uint32_t mode_ctl = 0, mode_ctl2 = 0; int ret; -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_display.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6/drivers/gpu/drm/nouveau/nv50_display.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_display.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_display.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv50_display.c 2011-02-22 14:16:21.599230095 +0100 @@ -24,6 +24,7 @@ * */ @@ -3469,9 +3269,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_display.c linux-2.6.38- delayed |= clock; intr1 &= ~clock; } -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_display.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_display.h +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_display.h linux-2.6/drivers/gpu/drm/nouveau/nv50_display.h --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_display.h 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_display.h 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv50_display.h 2011-02-22 14:16:21.599230095 +0100 @@ -35,7 +35,36 @@ #include "nouveau_crtc.h" #include "nv50_evo.h" @@ -3526,9 +3326,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_display.h linux-2.6.38- + u64 base, u64 size, struct nouveau_gpuobj **); + #endif /* __NV50_DISPLAY_H__ */ -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_evo.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_evo.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_evo.c linux-2.6/drivers/gpu/drm/nouveau/nv50_evo.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_evo.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_evo.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv50_evo.c 2011-02-22 14:16:21.599230095 +0100 @@ -27,20 +27,17 @@ #include "nouveau_drv.h" #include "nouveau_dma.h" @@ -3945,9 +3745,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_evo.c linux-2.6.38-rc5. + + nv50_evo_destroy(dev); } -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_evo.h linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_evo.h +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_evo.h linux-2.6/drivers/gpu/drm/nouveau/nv50_evo.h --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_evo.h 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_evo.h 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv50_evo.h 2011-02-22 14:16:21.600230075 +0100 @@ -27,12 +27,6 @@ #ifndef __NV50_EVO_H__ #define __NV50_EVO_H__ @@ -3969,9 +3769,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_evo.h linux-2.6.38-rc5. +#define NV50_EVO_CRTC_UNK904 0x00000904 #endif -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_fb.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_fb.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_fb.c linux-2.6/drivers/gpu/drm/nouveau/nv50_fb.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_fb.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_fb.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv50_fb.c 2011-02-22 14:16:21.600230075 +0100 @@ -8,31 +8,61 @@ dma_addr_t r100c08; }; @@ -4058,9 +3858,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_fb.c linux-2.6.38-rc5.n } void -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_fifo.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_fifo.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_fifo.c linux-2.6/drivers/gpu/drm/nouveau/nv50_fifo.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_fifo.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_fifo.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv50_fifo.c 2011-02-22 14:16:21.600230075 +0100 @@ -149,6 +149,7 @@ nv_wr32(dev, 0x3204, 0); nv_wr32(dev, 0x3210, 0); @@ -4078,9 +3878,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_fifo.c linux-2.6.38-rc5 nv_wo32(ramfc, 0x60, 0x7fffffff); nv_wo32(ramfc, 0x40, 0x00000000); nv_wo32(ramfc, 0x7c, 0x30000001); -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_gpio.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_gpio.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_gpio.c linux-2.6/drivers/gpu/drm/nouveau/nv50_gpio.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_gpio.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_gpio.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv50_gpio.c 2011-02-22 14:16:21.600230075 +0100 @@ -137,6 +137,7 @@ struct nv50_gpio_priv *priv = pgpio->priv; struct nv50_gpio_handler *gpioh, *tmp; @@ -4131,9 +3931,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_gpio.c linux-2.6.38-rc5 } spin_unlock(&priv->lock); } -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_graph.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6/drivers/gpu/drm/nouveau/nv50_graph.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_graph.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_graph.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv50_graph.c 2011-02-22 14:16:21.601230054 +0100 @@ -409,12 +409,7 @@ nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) @@ -4163,9 +3963,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_graph.c linux-2.6.38-rc } -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_instmem.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6/drivers/gpu/drm/nouveau/nv50_instmem.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_instmem.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_instmem.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv50_instmem.c 2011-02-22 14:16:21.602230033 +0100 @@ -300,7 +300,7 @@ } @@ -4175,9 +3975,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_instmem.c linux-2.6.38- struct nouveau_vma chan_vma; u32 align; }; -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_sor.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_sor.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_sor.c linux-2.6/drivers/gpu/drm/nouveau/nv50_sor.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_sor.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_sor.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv50_sor.c 2011-02-22 14:16:21.603230013 +0100 @@ -41,8 +41,7 @@ { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); @@ -4198,9 +3998,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_sor.c linux-2.6.38-rc5. struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_device *dev = encoder->dev; struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_vm.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_vm.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_vm.c linux-2.6/drivers/gpu/drm/nouveau/nv50_vm.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_vm.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_vm.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv50_vm.c 2011-02-22 14:16:21.603230013 +0100 @@ -31,7 +31,6 @@ nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, struct nouveau_gpuobj *pgt[2]) @@ -4264,9 +4064,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_vm.c linux-2.6.38-rc5.n nv_wo32(pgt, pte + 0, lower_32_bits(phys)); nv_wo32(pgt, pte + 4, upper_32_bits(phys)); pte += 8; -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_vram.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_vram.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_vram.c linux-2.6/drivers/gpu/drm/nouveau/nv50_vram.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_vram.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nv50_vram.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nv50_vram.c 2011-02-22 14:16:21.603230013 +0100 @@ -48,42 +48,49 @@ } @@ -4386,9 +4186,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nv50_vram.c linux-2.6.38-rc5 return 0; } -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_fifo.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_fifo.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_fifo.c linux-2.6/drivers/gpu/drm/nouveau/nvc0_fifo.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_fifo.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_fifo.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nvc0_fifo.c 2011-02-22 14:16:21.604229993 +0100 @@ -116,7 +116,7 @@ /* allocate vram for control regs, map into polling area */ @@ -4429,9 +4229,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_fifo.c linux-2.6.38-rc5 - - nv_wr32(dev, 0x2140, 0); } -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_graph.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_graph.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_graph.c linux-2.6/drivers/gpu/drm/nouveau/nvc0_graph.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_graph.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_graph.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nvc0_graph.c 2011-02-22 14:16:21.604229993 +0100 @@ -299,6 +299,14 @@ } @@ -4487,9 +4287,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_graph.c linux-2.6.38-rc nv_wr32(dev, 0x400100, 0x00000010); stat &= ~0x00000010; } -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_vm.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_vm.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_vm.c linux-2.6/drivers/gpu/drm/nouveau/nvc0_vm.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_vm.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_vm.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nvc0_vm.c 2011-02-22 14:16:21.606229953 +0100 @@ -59,7 +59,7 @@ void @@ -4513,9 +4313,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_vm.c linux-2.6.38-rc5.n nv_wo32(pgt, pte + 0, lower_32_bits(phys)); nv_wo32(pgt, pte + 4, upper_32_bits(phys)); pte += 8; -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_vram.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_vram.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_vram.c linux-2.6/drivers/gpu/drm/nouveau/nvc0_vram.c --- linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_vram.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/nouveau/nvc0_vram.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/nouveau/nvc0_vram.c 2011-02-22 14:16:21.606229953 +0100 @@ -26,64 +26,78 @@ #include "nouveau_drv.h" #include "nouveau_mm.h" @@ -4619,9 +4419,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/nouveau/nvc0_vram.c linux-2.6.38-rc5 return 0; } -diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/ttm/ttm_bo.c linux-2.6.38-rc5.nouveau/drivers/gpu/drm/ttm/ttm_bo.c +diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/ttm/ttm_bo.c linux-2.6/drivers/gpu/drm/ttm/ttm_bo.c --- linux-2.6.38-rc5/drivers/gpu/drm/ttm/ttm_bo.c 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/drivers/gpu/drm/ttm/ttm_bo.c 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/drivers/gpu/drm/ttm/ttm_bo.c 2011-02-22 14:16:21.822225582 +0100 @@ -406,11 +406,12 @@ } @@ -4636,9 +4436,9 @@ diff -Naur linux-2.6.38-rc5/drivers/gpu/drm/ttm/ttm_bo.c linux-2.6.38-rc5.nouvea } if (bdev->driver->move_notify) -diff -Naur linux-2.6.38-rc5/include/drm/nouveau_drm.h linux-2.6.38-rc5.nouveau/include/drm/nouveau_drm.h +diff -Naur linux-2.6.38-rc5/include/drm/nouveau_drm.h linux-2.6/include/drm/nouveau_drm.h --- linux-2.6.38-rc5/include/drm/nouveau_drm.h 2011-02-16 04:23:45.000000000 +0100 -+++ linux-2.6.38-rc5.nouveau/include/drm/nouveau_drm.h 2011-02-20 23:32:11.000000000 +0100 ++++ linux-2.6/include/drm/nouveau_drm.h 2011-02-22 14:16:28.891082551 +0100 @@ -94,6 +94,7 @@ #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) #define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3) From 35e44a74ca980b862b556310f52845cec9e307bd Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 22 Feb 2011 15:12:16 +0100 Subject: [PATCH 16/16] projects/*/linux: update kernel config for linux-2.6.38-rc6 Signed-off-by: Stephan Raue --- projects/ATV/linux/linux.i386.conf | 3 ++- projects/Generic/linux/linux.i386.conf | 3 ++- projects/ION/linux/linux.i386.conf | 3 ++- projects/ION/linux/linux.x86_64.conf | 3 ++- projects/Intel/linux/linux.i386.conf | 3 ++- projects/Intel/linux/linux.x86_64.conf | 3 ++- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/projects/ATV/linux/linux.i386.conf b/projects/ATV/linux/linux.i386.conf index cb16fbac7a..5a47bf85b8 100644 --- a/projects/ATV/linux/linux.i386.conf +++ b/projects/ATV/linux/linux.i386.conf @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux/i386 2.6.38-rc5 Kernel Configuration +# Linux/i386 2.6.38-rc6 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -1972,6 +1972,7 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc0" CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # CONFIG_RTC_DRV_TEST is not set # diff --git a/projects/Generic/linux/linux.i386.conf b/projects/Generic/linux/linux.i386.conf index 30ce74ac80..e8e8c191d7 100644 --- a/projects/Generic/linux/linux.i386.conf +++ b/projects/Generic/linux/linux.i386.conf @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux/i386 2.6.38-rc5 Kernel Configuration +# Linux/i386 2.6.38-rc6 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -2354,6 +2354,7 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc0" CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # CONFIG_RTC_DRV_TEST is not set # diff --git a/projects/ION/linux/linux.i386.conf b/projects/ION/linux/linux.i386.conf index f21e3f5e82..97fe8b9ac0 100644 --- a/projects/ION/linux/linux.i386.conf +++ b/projects/ION/linux/linux.i386.conf @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux/i386 2.6.38-rc5 Kernel Configuration +# Linux/i386 2.6.38-rc6 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -2234,6 +2234,7 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc0" CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # CONFIG_RTC_DRV_TEST is not set # diff --git a/projects/ION/linux/linux.x86_64.conf b/projects/ION/linux/linux.x86_64.conf index 449533c83c..01f58bf516 100644 --- a/projects/ION/linux/linux.x86_64.conf +++ b/projects/ION/linux/linux.x86_64.conf @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux/x86_64 2.6.38-rc5 Kernel Configuration +# Linux/x86_64 2.6.38-rc6 Kernel Configuration # CONFIG_64BIT=y # CONFIG_X86_32 is not set @@ -2168,6 +2168,7 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc0" CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # CONFIG_RTC_DRV_TEST is not set # diff --git a/projects/Intel/linux/linux.i386.conf b/projects/Intel/linux/linux.i386.conf index 75c5ecc45b..1bbc4db22c 100644 --- a/projects/Intel/linux/linux.i386.conf +++ b/projects/Intel/linux/linux.i386.conf @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux/i386 2.6.38-rc5 Kernel Configuration +# Linux/i386 2.6.38-rc6 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -2206,6 +2206,7 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc0" CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # CONFIG_RTC_DRV_TEST is not set # diff --git a/projects/Intel/linux/linux.x86_64.conf b/projects/Intel/linux/linux.x86_64.conf index a6a9749dec..5fe8984dab 100644 --- a/projects/Intel/linux/linux.x86_64.conf +++ b/projects/Intel/linux/linux.x86_64.conf @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux/x86_64 2.6.38-rc5 Kernel Configuration +# Linux/x86_64 2.6.38-rc6 Kernel Configuration # CONFIG_64BIT=y # CONFIG_X86_32 is not set @@ -2145,6 +2145,7 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc0" CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # CONFIG_RTC_DRV_TEST is not set #