diff options
167 files changed, 2625 insertions, 572 deletions
@@ -2611,8 +2611,9 @@ S: Perth, Western Australia S: Australia N: Miguel Ojeda Sandonis -E: maxextreme@gmail.com -W: http://maxextreme.googlepages.com/ +E: miguel.ojeda.sandonis@gmail.com +W: http://miguelojeda.es +W: http://jair.lab.fi.uva.es/~migojed/ D: Author of the ks0108, cfag12864b and cfag12864bfb auxiliary display drivers. D: Maintainer of the auxiliary display drivers tree (drivers/auxdisplay/*) S: C/ Mieses 20, 9-B diff --git a/Documentation/accounting/taskstats-struct.txt b/Documentation/accounting/taskstats-struct.txt index 8aa7529f825..cd784f46bf8 100644 --- a/Documentation/accounting/taskstats-struct.txt +++ b/Documentation/accounting/taskstats-struct.txt @@ -24,6 +24,8 @@ There are three different groups of fields in the struct taskstats: 4) Per-task and per-thread context switch count statistics +5) Time accounting for SMT machines + Future extension should add fields to the end of the taskstats struct, and should not change the relative position of each field within the struct. @@ -164,4 +166,8 @@ struct taskstats { __u64 nvcsw; /* Context voluntary switch counter */ __u64 nivcsw; /* Context involuntary switch counter */ +5) Time accounting for SMT machines + __u64 ac_utimescaled; /* utime scaled on frequency etc */ + __u64 ac_stimescaled; /* stime scaled on frequency etc */ + __u64 cpu_scaled_run_real_total; /* scaled cpu_run_real_total */ } diff --git a/Documentation/auxdisplay/cfag12864b b/Documentation/auxdisplay/cfag12864b index b714183d412..eb7be393a51 100644 --- a/Documentation/auxdisplay/cfag12864b +++ b/Documentation/auxdisplay/cfag12864b @@ -3,7 +3,7 @@ =================================== License: GPLv2 -Author & Maintainer: Miguel Ojeda Sandonis <maxextreme@gmail.com> +Author & Maintainer: Miguel Ojeda Sandonis Date: 2006-10-27 @@ -22,7 +22,7 @@ Date: 2006-10-27 1. DRIVER INFORMATION --------------------- -This driver support one cfag12864b display at time. +This driver supports a cfag12864b LCD. --------------------- diff --git a/Documentation/auxdisplay/cfag12864b-example.c b/Documentation/auxdisplay/cfag12864b-example.c index 7bfac354d4c..2caeea5e499 100644 --- a/Documentation/auxdisplay/cfag12864b-example.c +++ b/Documentation/auxdisplay/cfag12864b-example.c @@ -4,7 +4,7 @@ * Description: cfag12864b LCD userspace example program * License: GPLv2 * - * Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com> + * Author: Copyright (C) Miguel Ojeda Sandonis * Date: 2006-10-31 * * This program is free software; you can redistribute it and/or modify diff --git a/Documentation/auxdisplay/ks0108 b/Documentation/auxdisplay/ks0108 index 92b03b60c61..8ddda0c8cee 100644 --- a/Documentation/auxdisplay/ks0108 +++ b/Documentation/auxdisplay/ks0108 @@ -3,7 +3,7 @@ ========================================== License: GPLv2 -Author & Maintainer: Miguel Ojeda Sandonis <maxextreme@gmail.com> +Author & Maintainer: Miguel Ojeda Sandonis Date: 2006-10-27 @@ -21,7 +21,7 @@ Date: 2006-10-27 1. DRIVER INFORMATION --------------------- -This driver support the ks0108 LCD controller. +This driver supports the ks0108 LCD controller. --------------------- diff --git a/Documentation/cgroups.txt b/Documentation/cgroups.txt index 824fc027447..d9014aa0eb6 100644 --- a/Documentation/cgroups.txt +++ b/Documentation/cgroups.txt @@ -390,6 +390,10 @@ If you have several tasks to attach, you have to do it one after another: ... # /bin/echo PIDn > tasks +You can attach the current shell task by echoing 0: + +# echo 0 > tasks + 3. Kernel API ============= diff --git a/Documentation/controllers/devices.txt b/Documentation/controllers/devices.txt index 4dcea42432c..7cc6e6a6067 100644 --- a/Documentation/controllers/devices.txt +++ b/Documentation/controllers/devices.txt @@ -13,7 +13,7 @@ either an integer or * for all. Access is a composition of r The root device cgroup starts with rwm to 'all'. A child device cgroup gets a copy of the parent. Administrators can then remove devices from the whitelist or add new entries. A child cgroup can -never receive a device access which is denied its parent. However +never receive a device access which is denied by its parent. However when a device access is removed from a parent it will not also be removed from the child(ren). @@ -29,7 +29,11 @@ allows cgroup 1 to read and mknod the device usually known as echo a > /cgroups/1/devices.deny -will remove the default 'a *:* mrw' entry. +will remove the default 'a *:* rwm' entry. Doing + + echo a > /cgroups/1/devices.allow + +will add the 'a *:* rwm' entry to the whitelist. 3. Security diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt index 353504de308..1f5a924d1e5 100644 --- a/Documentation/cpusets.txt +++ b/Documentation/cpusets.txt @@ -154,13 +154,15 @@ browsing and modifying the cpusets presently known to the kernel. No new system calls are added for cpusets - all support for querying and modifying cpusets is via this cpuset file system. -The /proc/<pid>/status file for each task has two added lines, +The /proc/<pid>/status file for each task has four added lines, displaying the tasks cpus_allowed (on which CPUs it may be scheduled) and mems_allowed (on which Memory Nodes it may obtain memory), -in the format seen in the following example: +in the two formats seen in the following example: Cpus_allowed: ffffffff,ffffffff,ffffffff,ffffffff + Cpus_allowed_list: 0-127 Mems_allowed: ffffffff,ffffffff + Mems_allowed_list: 0-63 Each cpuset is represented by a directory in the cgroup file system containing (on top of the standard cgroup files) the following @@ -544,6 +546,9 @@ otherwise initial value -1 that indicates the cpuset has no request. ( 4 : search nodes in a chunk of node [on NUMA system] ) ( 5 : search system wide [on NUMA system] ) +The system default is architecture dependent. The system default +can be changed using the relax_domain_level= boot parameter. + This file is per-cpuset and affect the sched domain where the cpuset belongs to. Therefore if the flag 'sched_load_balance' of a cpuset is disabled, then 'sched_relax_domain_level' have no effect since diff --git a/Documentation/ftrace.txt b/Documentation/ftrace.txt new file mode 100644 index 00000000000..13e4bf054c3 --- /dev/null +++ b/Documentation/ftrace.txt @@ -0,0 +1,1353 @@ + ftrace - Function Tracer + ======================== + +Copyright 2008 Red Hat Inc. +Author: Steven Rostedt <srostedt@redhat.com> + + +Introduction +------------ + +Ftrace is an internal tracer designed to help out developers and +designers of systems to find what is going on inside the kernel. +It can be used for debugging or analyzing latencies and performance +issues that take place outside of user-space. + +Although ftrace is the function tracer, it also includes an +infrastructure that allows for other types of tracing. Some of the +tracers that are currently in ftrace is a tracer to trace +context switches, the time it takes for a high priority task to +run after it was woken up, the time interrupts are disabled, and +more. + + +The File System +--------------- + +Ftrace uses the debugfs file system to hold the control files as well +as the files to display output. + +To mount the debugfs system: + + # mkdir /debug + # mount -t debugfs nodev /debug + + +That's it! (assuming that you have ftrace configured into your kernel) + +After mounting the debugfs, you can see a directory called +"tracing". This directory contains the control and output files +of ftrace. Here is a list of some of the key files: + + + Note: all time values are in microseconds. + + current_tracer : This is used to set or display the current tracer + that is configured. + + available_tracers : This holds the different types of tracers that + has been compiled into the kernel. The tracers + listed here can be configured by echoing in their + name into current_tracer. + + tracing_enabled : This sets or displays whether the current_tracer + is activated and tracing or not. Echo 0 into this + file to disable the tracer or 1 (or non-zero) to + enable it. + + trace : This file holds the output of the trace in a human readable + format. + + latency_trace : This file shows the same trace but the information + is organized more to display possible latencies + in the system. + + trace_pipe : The output is the same as the "trace" file but this + file is meant to be streamed with live tracing. + Reads from this file will block until new data + is retrieved. Unlike the "trace" and "latency_trace" + files, this file is a consumer. This means reading + from this file causes sequential reads to display + more current data. Once data is read from this + file, it is consumed, and will not be read + again with a sequential read. The "trace" and + "latency_trace" files are static, and if the + tracer isn't adding more data, they will display + the same information every time they are read. + + iter_ctrl : This file lets the user control the amount of data + that is displayed in one of the above output + files. + + trace_max_latency : Some of the tracers record the max latency. + For example, the time interrupts are disabled. + This time is saved in this file. The max trace + will also be stored, and displayed by either + "trace" or "latency_trace". A new max trace will + only be recorded if the latency is greater than + the value in this file. (in microseconds) + + trace_entries : This sets or displays the number of trace + entries each CPU buffer can hold. The tracer buffers + are the same size for each CPU, so care must be + taken when modifying the trace_entries. The number + of actually entries will be the number given + times the number of possible CPUS. The buffers + are saved as individual pages, and the actual entries + will always be rounded up to entries per page. + + This can only be updated when the current_tracer + is set to "none". + + NOTE: It is planned on changing the allocated buffers + from being the number of possible CPUS to + the number of online CPUS. + + tracing_cpumask : This is a mask that lets the user only trace + on specified CPUS. The format is a hex string + representing the CPUS. + + set_ftrace_filter : When dynamic ftrace is configured in, the + code is dynamically modified to disable calling + of the function profiler (mcount). This lets + tracing be configured in with practically no overhead + in performance. This also has a side effect of + enabling or disabling specific functions to be + traced. Echoing in names of functions into this + file will limit the trace to only those files. + + set_ftrace_notrace: This has the opposite effect that + set_ftrace_filter has. Any function that is added + here will not be traced. If a function exists + in both set_ftrace_filter and set_ftrace_notrace + the function will _not_ bet traced. + + available_filter_functions : When a function is encountered the first + time by the dynamic tracer, it is recorded and + later the call is converted into a nop. This file + lists the functions that have been recorded + by the dynamic tracer and these functions can + be used to set the ftrace filter by the above + "set_ftrace_filter" file. + + +The Tracers +----------- + +Here are the list of current tracers that can be configured. + + ftrace - function tracer that uses mcount to trace all functions. + It is possible to filter out which functions that are + traced when dynamic ftrace is configured in. + + sched_switch - traces the context switches between tasks. + + irqsoff - traces the areas that disable interrupts and saves off + the trace with the longest max latency. + See tracing_max_latency. When a new max is recorded, + it replaces the old trace. It is best to view this + trace with the latency_trace file. + + preemptoff - Similar to irqsoff but traces and records the time + preemption is disabled. + + preemptirqsoff - Similar to irqsoff and preemptoff, but traces and + records the largest time irqs and/or preemption is + disabled. + + wakeup - Traces and records the max latency that it takes for + the highest priority task to get scheduled after + it has been woken up. + + none - This is not a tracer. To remove all tracers from tracing + simply echo "none" into current_tracer. + + +Examples of using the tracer +---------------------------- + +Here are typical examples of using the tracers with only controlling +them with the debugfs interface (without using any user-land utilities). + +Output format: +-------------- + +Here's an example of the output format of the file "trace" + + -------- +# tracer: ftrace +# +# TASK-PID CPU# TIMESTAMP FUNCTION +# | | | | | + bash-4251 [01] 10152.583854: path_put <-path_walk + bash-4251 [01] 10152.583855: dput <-path_put + bash-4251 [01] 10152.583855: _atomic_dec_and_lock <-dput + -------- + +A header is printed with the trace that is represented. In this case +the tracer is "ftrace". Then a header showing the format. Task name +"bash", the task PID "4251", the CPU that it was running on +"01", the timestamp in <secs>.<usecs> format, the function name that was +traced "path_put" and the parent function that called this function +"path_walk". + +The sched_switch tracer also includes tracing of task wake ups and +context switches. + + ksoftirqd/1-7 [01] 1453.070013: 7:115:R + 2916:115:S + ksoftirqd/1-7 [01] 1453.070013: 7:115:R + 10:115:S + ksoftirqd/1-7 [01] 1453.070013: 7:115:R ==> 10:115:R + events/1-10 [01] 1453.070013: 10:115:S ==> 2916:115:R + kondemand/1-2916 [01] 1453.070013: 2916:115:S ==> 7:115:R + ksoftirqd/1-7 [01] 1453.070013: 7:115:S ==> 0:140:R + +Wake ups are represented by a "+" and the context switches show +"==>". The format is: + + Context switches: + + Previous task Next Task + + <pid>:<prio>:<state> ==> <pid>:<prio>:<state> + + Wake ups: + + Current task Task waking up + + <pid>:<prio>:<state> + <pid>:<prio>:<state> + +The prio is the internal kernel priority, which is inverse to the +priority that is usually displayed by user-space tools. Zero represents +the highest priority (99). Prio 100 starts the "nice" priorities with +100 being equal to nice -20 and 139 being nice 19. The prio "140" is +reserved for the idle task which is the lowest priority thread (pid 0). + + +Latency trace format +-------------------- + +For traces that display latency times, the latency_trace file gives +a bit more information to see why a latency happened. Here's a typical +trace. + +# tracer: irqsoff +# +irqsoff latency trace v1.1.5 on 2.6.26-rc8 +-------------------------------------------------------------------- + latency: 97 us, #3/3, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2) + ----------------- + | task: swapper-0 (uid:0 nice:0 policy:0 rt_prio:0) + ----------------- + => started at: apic_timer_interrupt + => ended at: do_softirq + +# _------=> CPU# +# / _-----=> irqs-off +# | / _----=> need-resched +# || / _---=> hardirq/softirq +# ||| / _--=> preempt-depth +# |||| / +# ||||| delay +# cmd pid ||||| time | caller +# \ / ||||| \ | / + <idle>-0 0d..1 0us+: trace_hardirqs_off_thunk (apic_timer_interrupt) + <idle>-0 0d.s. 97us : __do_softirq (do_softirq) + <idle>-0 0d.s1 98us : trace_hardirqs_on (do_softirq) + + +vim:ft=help + + +This shows that the current tracer is "irqsoff" tracing the time +interrupts are disabled. It gives the trace version and the kernel +this was executed on (2.6.26-rc8). Then it displays the max latency +in microsecs (97 us). The number of trace entries displayed +by the total number recorded (both are three: #3/3). The type of +preemption that was used (PREEMPT). VP, KP, SP, and HP are always zero +and reserved for later use. #P is the number of online CPUS (#P:2). + +The task is the process that was running when the latency happened. +(swapper pid: 0). + +The start and stop that caused the latencies: + + apic_timer_interrupt is where the interrupts were disabled. + do_softirq is where they were enabled again. + +The next lines after the header are the trace itself. The header +explains which is which. + + cmd: The name of the process in the trace. + + pid: The PID of that process. + + CPU#: The CPU that the process was running on. + + irqs-off: 'd' interrupts are disabled. '.' otherwise. + + need-resched: 'N' task need_resched is set, '.' otherwise. + + hardirq/softirq: + 'H' - hard irq happened inside a softirq. + 'h' - hard irq is running + 's' - soft irq is running + '.' - normal context. + + preempt-depth: The level of preempt_disabled + +The above is mostly meaningful for kernel developers. + + time: This differs from the trace output where as the trace output + contained a absolute timestamp. This timestamp is relative + to the start of the first entry in the the trace. + + delay: This is just to help catch your eye a bit better. And + needs to be fixed to be only relative to the same CPU. + The marks is determined by the difference between this + current trace and the next trace. + '!' - greater than preempt_mark_thresh (default 100) + '+' - greater than 1 microsecond + ' ' - less than or equal to 1 microsecond. + + The rest is the same as the 'trace' file. + + +iter_ctrl +--------- + +The iter_ctrl file is used to control what gets printed in the trace +output. To see what is available, simply cat the file: + + cat /debug/tracing/iter_ctrl + print-parent nosym-offset nosym-addr noverbose noraw nohex nobin \ + noblock nostacktrace nosched-tree + +To disable one of the options, echo in the option appended with "no". + + echo noprint-parent > /debug/tracing/iter_ctrl + +To enable an option, leave off the "no". + + echo sym-offest > /debug/tracing/iter_ctrl + +Here are the available options: + + print-parent - On function traces, display the calling function + as well as the function being traced. + + print-parent: + bash-4000 [01] 1477.606694: simple_strtoul <-strict_strtoul + + noprint-parent: + bash-4000 [01] 1477.606694: simple_strtoul + + + sym-offset - Display not only the function name, but also the offset + in the function. For example, instead of seeing just + "ktime_get" you will see "ktime_get+0xb/0x20" + + sym-offset: + bash-4000 [01] 1477.606694: simple_strtoul+0x6/0xa0 + + sym-addr - this will also display the function address as well as + the function name. + + sym-addr: + bash-4000 [01] 1477.606694: simple_strtoul <c0339346> + + verbose - This deals with the latency_trace file. + + bash 4000 1 0 00000000 00010a95 [58127d26] 1720.415ms \ + (+0.000ms): simple_strtoul (strict_strtoul) + + raw - This will display raw numbers. This option is best for use with + user applications that can translate the raw numbers better than + having it done in the kernel. + + hex - similar to raw, but the numbers will be in a hexadecimal format. + + bin - This will print out the formats in raw binary. + + block - TBD (needs update) + + stacktrace - This is one of the options that changes the trace itself. + When a trace is recorded, so is the stack of functions. + This allows for back traces of trace sites. + + sched-tree - TBD (any users??) + + +sched_switch +------------ + +This tracer simply records schedule switches. Here's an example +on how to implement it. + + # echo sched_switch > /debug/tracing/current_tracer + # echo 1 > /debug/tracing/tracing_enabled + # sleep 1 + # echo 0 > /debug/tracing/tracing_enabled + # cat /debug/tracing/trace + +# tracer: sched_switch +# +# TASK-PID CPU# TIMESTAMP FUNCTION +# | | | | | + bash-3997 [01] 240.132281: 3997:120:R + 4055:120:R + bash-3997 [01] 240.132284: 3997:120:R ==> 4055:120:R + sleep-4055 [01] 240.132371: 4055:120:S ==> 3997:120:R + bash-3997 [01] 240.132454: 3997:120:R + 4055:120:S + bash-3997 [01] 240.132457: 3997:120:R ==> 4055:120:R + sleep-4055 [01] 240.132460: 4055:120:D ==> 3997:120:R + bash-3997 [01] 240.132463: 3997:120:R + 4055:120:D + bash-3997 [01] 240.132465: 3997:120:R ==> 4055:120:R + <idle>-0 [00] 240.132589: 0:140:R + 4:115:S + <idle>-0 [00] 240.132591: 0:140:R ==> 4:115:R + ksoftirqd/0-4 [00] 240.132595: 4:115:S ==> 0:140:R + <idle>-0 [00] 240.132598: 0:140:R + 4:115:S + <idle>-0 [00] 240.132599: 0:140:R ==> 4:115:R + ksoftirqd/0-4 [00] 240.132603: 4:115:S ==> 0:140:R + sleep-4055 [01] 240.133058: 4055:120:S ==> 3997:120:R + [...] + + +As we have discussed previously about this format, the header shows +the name of the trace and points to the options. The "FUNCTION" +is a misnomer since here it represents the wake ups and context +switches. + +The sched_switch only lists the wake ups (represented with '+') +and context switches ('==>') with the previous task or current +first followed by the next task or task waking up. The format for both +of these is PID:KERNEL-PRIO:TASK-STATE. Remember that the KERNEL-PRIO +is the inverse of the actual priority with zero (0) being the highest +priority and the nice values starting at 100 (nice -20). Below is +a quick chart to map the kernel priority to user land priorities. + + Kernel priority: 0 to 99 ==> user RT priority 99 to 0 + Kernel priority: 100 to 139 ==> user nice -20 to 19 + Kernel priority: 140 ==> idle task priority + +The task states are: + + R - running : wants to run, may not actually be running + S - sleep : process is waiting to be woken up (handles signals) + D - deep sleep : process must be woken up (ignores signals) + T - stopped : process suspended + t - traced : process is being traced (with something like gdb) + Z - zombie : process waiting to be cleaned up + X - unknown + + +ftrace_enabled +-------------- + +The following tracers give different output depending on whether +or not the sysctl ftrace_enabled is set. To set ftrace_enabled, +one can either use the sysctl function or set it via the proc +file system interface. + + sysctl kernel.ftrace_enabled=1 + + or + + echo 1 > /proc/sys/kernel/ftrace_enabled + +To disable ftrace_enabled simply replace the '1' with '0' in +the above commands. + +When ftrace_enabled is set the tracers will also record the functions +that are within the trace. The descriptions of the tracers +will also show an example with ftrace enabled. + + +irqsoff +------- + +When interrupts are disabled, the CPU can not react to any other +external event (besides NMIs and SMIs). This prevents the timer +interrupt from triggering or the mouse interrupt from letting the +kernel know of a new mouse event. The result is a latency with the +reaction time. + +The irqsoff tracer tracks the time interrupts are disabled and when +they are re-enabled. When a new maximum latency is hit, it saves off +the trace so that it may be retrieved at a later time. Every time a +new maximum in reached, the old saved trace is discarded and the new +trace is saved. + +To reset the maximum, echo 0 into tracing_max_latency. Here's an +example: + + # echo irqsoff > /debug/tracing/current_tracer + # echo 0 > /debug/tracing/tracing_max_latency + # echo 1 > /debug/tracing/tracing_enabled + # ls -ltr + [...] + # echo 0 > /debug/tracing/tracing_enabled + # cat /debug/tracing/latency_trace +# tracer: irqsoff +# +irqsoff latency trace v1.1.5 on 2.6.26-rc8 +-------------------------------------------------------------------- + latency: 6 us, #3/3, CPU#1 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2) + ----------------- + | task: bash-4269 (uid:0 nice:0 policy:0 rt_prio:0) + ----------------- + => started at: copy_page_range + => ended at: copy_page_range + +# _------=> CPU# +# / _-----=> irqs-off +# | / _----=> need-resched +# || / _---=> hardirq/softirq +# ||| / _--=> preempt-depth +# |||| / +# ||||| delay +# cmd pid ||||| time | caller +# \ / ||||| \ | / + bash-4269 1...1 0us+: _spin_lock (copy_page_range) + bash-4269 1...1 7us : _spin_unlock (copy_page_range) + bash-4269 1...2 7us : trace_preempt_on (copy_page_range) + + +vim:ft=help + +Here we see that that we had a latency of 6 microsecs (which is +very good). The spin_lock in copy_page_range disabled interrupts. +The difference between the 6 and the displayed timestamp 7us is +because the clock must have incremented between the time of recording +the max latency and recording the function that had that latency. + +Note the above had ftrace_enabled not set. If we set the ftrace_enabled +we get a much larger output: + +# tracer: irqsoff +# +irqsoff latency trace v1.1.5 on 2.6.26-rc8 +-------------------------------------------------------------------- + latency: 50 us, #101/101, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2) + ----------------- + | task: ls-4339 (uid:0 nice:0 policy:0 rt_prio:0) + ----------------- + => started at: __alloc_pages_internal + => ended at: __alloc_pages_internal + +# _------=> CPU# +# / _-----=> irqs-off +# | / _----=> need-resched +# || / _---=> hardirq/softirq +# ||| / _--=> preempt-depth +# |||| / +# ||||| delay +# cmd pid ||||| time | caller +# \ / ||||| \ | / + ls-4339 0...1 0us+: get_page_from_freelist (__alloc_pages_internal) + ls-4339 0d..1 3us : rmqueue_bulk (get_page_from_freelist) + ls-4339 0d..1 3us : _spin_lock (rmqueue_bulk) + ls-4339 0d..1 4us : add_preempt_count (_spin_lock) + ls-4339 0d..2 4us : __rmqueue (rmqueue_bulk) + ls-4339 0d..2 5us : __rmqueue_smallest (__rmqueue) + ls-4339 0d..2 5us : __mod_zone_page_state (__rmqueue_smallest) + ls-4339 0d..2 6us : __rmqueue (rmqueue_bulk) + ls-4339 0d..2 6us : __rmqueue_smallest (__rmqueue) + ls-4339 0d..2 7us : __mod_zone_page_state (__rmqueue_smallest) + ls-4339 0d..2 7us : __rmqueue (rmqueue_bulk) + ls-4339 0d..2 8us : __rmqueue_smallest (__rmqueue) +[...] + ls-4339 0d..2 46us : __rmqueue_smallest (__rmqueue) + ls-4339 0d..2 47us : __mod_zone_page_state (__rmqueue_smallest) + ls-4339 0d..2 47us : __rmqueue (rmqueue_bulk) + ls-4339 0d..2 48us : __rmqueue_smallest (__rmqueue) + ls-4339 0d..2 48us : __mod_zone_page_state (__rmqueue_smallest) + ls-4339 0d..2 49us : _spin_unlock (rmqueue_bulk) + ls-4339 0d..2 49us : sub_preempt_count (_spin_unlock) + ls-4339 0d..1 50us : get_page_from_freelist (__alloc_pages_internal) + ls-4339 0d..2 51us : trace_hardirqs_on (__alloc_pages_internal) + + +vim:ft=help + + +Here we traced a 50 microsecond latency. But we also see all the +functions that were called during that time. Note that enabling +function tracing we endure an added overhead. This overhead may +extend the latency times. But never the less, this trace has provided +some very helpful debugging. + + +preemptoff +---------- + +When preemption is disabled we may be able to receive interrupts but +the task can not be preempted and a higher priority task must wait +for preemption to be enabled again before it can preempt a lower +priority task. + +The preemptoff tracer traces the places that disables preemption. +Like the irqsoff, it records the maximum latency that preemption +was disabled. The control of preemptoff is much like the irqsoff. + + # echo preemptoff > /debug/tracing/current_tracer + # echo 0 > /debug/tracing/tracing_max_latency + # echo 1 > /debug/tracing/tracing_enabled + # ls -ltr + [...] + # echo 0 > /debug/tracing/tracing_enabled + # cat /debug/tracing/latency_trace +# tracer: preemptoff +# +preemptoff latency trace v1.1.5 on 2.6.26-rc8 +-------------------------------------------------------------------- + latency: 29 us, #3/3, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2) + ----------------- + | task: sshd-4261 (uid:0 nice:0 policy:0 rt_prio:0) + ----------------- + => started at: do_IRQ + => ended at: __do_softirq + +# _------=> CPU# +# / _-----=> irqs-off +# | / _----=> need-resched +# || / _---=> hardirq/softirq +# ||| / _--=> preempt-depth +# |||| / +# ||||| delay +# cmd pid ||||| time | caller +# \ / ||||| \ | / + sshd-4261 0d.h. 0us+: irq_enter (do_IRQ) + sshd-4261 0d.s. 29us : _local_bh_enable (__do_softirq) + sshd-4261 0d.s1 30us : trace_preempt_on (__do_softirq) + + +vim:ft=help + +This has some more changes. Preemption was disabled when an interrupt +came in (notice the 'h'), and was enabled while doing a softirq. +(notice the 's'). But we also see that interrupts have been disabled +when entering the preempt off section and leaving it (the 'd'). +We do not know if interrupts were enabled in the mean time. + +# tracer: preemptoff +# +preemptoff latency trace v1.1.5 on 2.6.26-rc8 +-------------------------------------------------------------------- + latency: 63 us, #87/87, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2) + ----------------- + | task: sshd-4261 (uid:0 nice:0 policy:0 rt_prio:0) + ----------------- + => started at: remove_wait_queue + => ended at: __do_softirq + +# _------=> CPU# +# / _-----=> irqs-off +# | / _----=> need-resched +# || / _---=> hardirq/softirq +# ||| / _--=> preempt-depth +# |||| / +# ||||| delay +# cmd pid ||||| time | caller +# \ / ||||| \ | / + sshd-4261 0d..1 0us : _spin_lock_irqsave (remove_wait_queue) + sshd-4261 0d..1 1us : _spin_unlock_irqrestore (remove_wait_queue) + sshd-4261 0d..1 2us : do_IRQ (common_interrupt) + sshd-4261 0d..1 2us : irq_enter (do_IRQ) + sshd-4261 0d..1 2us : idle_cpu (irq_enter) + sshd-4261 0d..1 3us : add_preempt_count (irq_enter) + sshd-4261 0d.h1 3us : idle_cpu (irq_enter) + sshd-4261 0d.h. 4us : handle_fasteoi_irq (do_IRQ) +[...] + sshd-4261 0d.h. 12us : add_preempt_count (_spin_lock) + sshd-4261 0d.h1 12us : ack_ioapic_quirk_irq (handle_fasteoi_irq) + sshd-4261 0d.h1 13us : move_native_irq (ack_ioapic_quirk_irq) + sshd-4261 0d.h1 13us : _spin_unlock (handle_fasteoi_irq) + sshd-4261 0d.h1 14us : sub_preempt_count (_spin_unlock) + sshd-4261 0d.h1 14us : irq_exit (do_IRQ) + sshd-4261 0d.h1 15us : sub_preempt_count (irq_exit) + sshd-4261 0d..2 15us : do_softirq (irq_exit) + sshd-4261 0d... 15us : __do_softirq (do_softirq) + sshd-4261 0d... 16us : __local_bh_disable (__do_softirq) + sshd-4261 0d... 16us+: add_preempt_count (__local_bh_disable) + sshd-4261 0d.s4 20us : add_preempt_count (__local_bh_disable) + sshd-4261 0d.s4 21us : sub_preempt_count (local_bh_enable) + sshd-4261 0d.s5 21us : sub_preempt_count (local_bh_enable) +[...] + sshd-4261 0d.s6 41us : add_preempt_count (__local_bh_disable) + sshd-4261 0d.s6 42us : sub_preempt_count (local_bh_enable) + sshd-4261 0d.s7 42us : sub_preempt_count (local_bh_enable) + sshd-4261 0d.s5 43us : add_preempt_count (__local_bh_disable) + sshd-4261 0d.s5 43us : sub_preempt_count (local_bh_enable_ip) + sshd-4261 0d.s6 44us : sub_preempt_count (local_bh_enable_ip) + sshd-4261 0d.s5 44us : add_preempt_count (__local_bh_disable) + sshd-4261 0d.s5 45us : sub_preempt_count (local_bh_enable) +[...] + sshd-4261 0d.s. 63us : _local_bh_enable (__do_softirq) + sshd-4261 0d.s1 64us : trace_preempt_on (__do_softirq) + + +The above is an example of the preemptoff trace with ftrace_enabled +set. Here we see that interrupts were disabled the entire time. +The irq_enter code lets us know that we entered an interrupt 'h'. +Before that, the functions being traced still show that it is not +in an interrupt, but we can see by the functions themselves that +this is not the case. + +Notice that the __do_softirq when called doesn't have a preempt_count. +It may seem that we missed a preempt enabled. What really happened +is that the preempt count is held on the threads stack and we +switched to the softirq stack (4K stacks in effect). The code +does not copy the preempt count, but because interrupts are disabled +we don't need to worry about it. Having a tracer like this is good +to let people know what really happens inside the kernel. + + +preemptirqsoff +-------------- + +Knowing the locations that have interrupts disabled or preemption +disabled for the longest times is helpful. But sometimes we would +like to know when either preemption and/or interrupts are disabled. + +The following code: + + local_irq_disable(); + call_function_with_irqs_off(); + preempt_disable(); + call_function_with_irqs_and_preemption_off(); + local_irq_enable(); + call_function_with_preemption_off(); + preempt_enable(); + +The irqsoff tracer will record the total length of +call_function_with_irqs_off() and +call_function_with_irqs_and_preemption_off(). + +The preemptoff tracer will record the total length of +call_function_with_irqs_and_preemption_off() and +call_function_with_preemption_off(). + +But neither will trace the time that interrupts and/or preemption +is disabled. This total time is the time that we can not schedule. +To record this time, use the preemptirqsoff tracer. + +Again, using this trace is much like the irqsoff and preemptoff tracers. + + # echo preemptoff > /debug/tracing/current_tracer + # echo 0 > /debug/tracing/tracing_max_latency + # echo 1 > /debug/tracing/tracing_enabled + # ls -ltr + [...] + # echo 0 > /debug/tracing/tracing_enabled + # cat /debug/tracing/latency_trace +# tracer: preemptirqsoff +# +preemptirqsoff latency trace v1.1.5 on 2.6.26-rc8 +-------------------------------------------------------------------- + latency: 293 us, #3/3, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2) + ----------------- + | task: ls-4860 (uid:0 nice:0 policy:0 rt_prio:0) + ----------------- + => started at: apic_timer_interrupt + => ended at: __do_softirq + +# _------=> CPU# +# / _-----=> irqs-off +# | / _----=> need-resched +# || / _---=> hardirq/softirq +# ||| / _--=> preempt-depth +# |||| / +# ||||| delay +# cmd pid ||||| time | caller +# \ / ||||| \ | / + ls-4860 0d... 0us!: trace_hardirqs_off_thunk (apic_timer_interrupt) + ls-4860 0d.s. 294us : _local_bh_enable (__do_softirq) + ls-4860 0d.s1 294us : trace_preempt_on (__do_softirq) + + +vim:ft=help + + +The trace_hardirqs_off_thunk is called from assembly on x86 when +interrupts are disabled in the assembly code. Without the function +tracing, we don't know if interrupts were enabled within the preemption +points. We do see that it started with preemption enabled. + +Here is a trace with ftrace_enabled set: + + +# tracer: preemptirqsoff +# +preemptirqsoff latency trace v1.1.5 on 2.6.26-rc8 +-------------------------------------------------------------------- + latency: 105 us, #183/183, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2) + ----------------- + | task: sshd-4261 (uid:0 nice:0 policy:0 rt_prio:0) + ----------------- + => started at: write_chan + => ended at: __do_softirq + +# _------=> CPU# +# / _-----=> irqs-off +# | / _----=> need-resched +# || / _---=> hardirq/softirq +# ||| / _--=> preempt-depth +# |||| / +# ||||| delay +# cmd pid ||||| time | caller +# \ / ||||| \ | / + ls-4473 0.N.. 0us : preempt_schedule (write_chan) + ls-4473 0dN.1 1us : _spin_lock (schedule) + ls-4473 0dN.1 2us : add_preempt_count (_spin_lock) + ls-4473 0d..2 2us : put_prev_task_fair (schedule) +[...] + ls-4473 0d..2 13us : set_normalized_timespec (ktime_get_ts) + ls-4473 0d..2 13us : __switch_to (schedule) + sshd-4261 0d..2 14us : finish_task_switch (schedule) + sshd-4261 0d..2 14us : _spin_unlock_irq (finish_task_switch) + sshd-4261 0d..1 15us : add_preempt_count (_spin_lock_irqsave) + sshd-4261 0d..2 16us : _spin_unlock_irqrestore (hrtick_set) + sshd-4261 0d..2 16us : do_IRQ (common_interrupt) + sshd-4261 0d..2 17us : irq_enter (do_IRQ) + sshd-4261 0d..2 17us : idle_cpu (irq_enter) + sshd-4261 0d..2 18us : add_preempt_count (irq_enter) + sshd-4261 0d.h2 18us : idle_cpu (irq_enter) + sshd-4261 0d.h. 18us : handle_fasteoi_irq (do_IRQ) + sshd-4261 0d.h. 19us : _spin_lock (handle_fasteoi_irq) + sshd-4261 0d.h. 19us : add_preempt_count (_spin_lock) + sshd-4261 0d.h1 20us : _spin_unlock (handle_fasteoi_irq) + sshd-4261 0d.h1 20us : sub_preempt_count (_spin_unlock) +[...] + sshd-4261 0d.h1 28us : _spin_unlock (handle_fasteoi_irq) + sshd-4261 0d.h1 29us : sub_preempt_count (_spin_unlock) + sshd-4261 0d.h2 29us : irq_exit (do_IRQ) + sshd-4261 0d.h2 29us : sub_preempt_count (irq_exit) + sshd-4261 0d..3 30us : do_softirq (irq_exit) + sshd-4261 0d... 30us : __do_softirq (do_softirq) + sshd-4261 0d... 31us : __local_bh_disable (__do_softirq) + sshd-4261 0d... 31us+: add_preempt_count (__local_bh_disable) + sshd-4261 0d.s4 34us : add_preempt_count (__local_bh_disable) +[...] + sshd-4261 0d.s3 43us : sub_preempt_count (local_bh_enable_ip) + sshd-4261 0d.s4 44us : sub_preempt_count (local_bh_enable_ip) + sshd-4261 0d.s3 44us : smp_apic_timer_interrupt (apic_timer_interrupt) + sshd-4261 0d.s3 45us : irq_enter (smp_apic_timer_interrupt) + sshd-4261 0d.s3 45us : idle_cpu (irq_enter) + sshd-4261 0d.s3 46us : add_preempt_count (irq_enter) + sshd-4261 0d.H3 46us : idle_cpu (irq_enter) + sshd-4261 0d.H3 47us : hrtimer_interrupt (smp_apic_timer_interrupt) + sshd-4261 0d.H3 47us : ktime_get (hrtimer_interrupt) +[...] + sshd-4261 0d.H3 81us : tick_program_event (hrtimer_interrupt) + sshd-4261 0d.H3 82us : ktime_get (tick_program_event) + sshd-4261 0d.H3 82us : ktime_get_ts (ktime_get) + sshd-4261 0d.H3 83us : getnstimeofday (ktime_get_ts) + sshd-4261 0d.H3 83us : set_normalized_timespec (ktime_get_ts) + sshd-4261 0d.H3 84us : clockevents_program_event (tick_program_event) + sshd-4261 0d.H3 84us : lapic_next_event (clockevents_program_event) + sshd-4261 0d.H3 85us : irq_exit (smp_apic_timer_interrupt) + sshd-4261 0d.H3 85us : sub_preempt_count (irq_exit) + sshd-4261 0d.s4 86us : sub_preempt_count (irq_exit) + sshd-4261 0d.s3 86us : add_preempt_count (__local_bh_disable) +[...] + sshd-4261 0d.s1 98us : sub_preempt_count (net_rx_action) + sshd-4261 0d.s. 99us : add_preempt_count (_spin_lock_irq) + sshd-4261 0d.s1 99us+: _spin_unlock_irq (run_timer_softirq) + sshd-4261 0d.s. 104us : _local_bh_enable (__do_softirq) + sshd-4261 0d.s. 104us : sub_preempt_count (_local_bh_enable) + sshd-4261 0d.s. 105us : _local_bh_enable (__do_softirq) + sshd-4261 0d.s1 105us : trace_preempt_on (__do_softirq) + + +This is a very interesting trace. It started with the preemption of +the ls task. We see that the task had the "need_resched" bit set +with the 'N' in the trace. Interrupts are disabled in the spin_lock +and the trace started. We see that a schedule took place to run +sshd. When the interrupts were enabled we took an interrupt. +On return of the interrupt the softirq ran. We took another interrupt +while running the softirq as we see with the capital 'H'. + + +wakeup +------ + +In Real-Time environment it is very important to know the wakeup +time it takes for the highest priority task that wakes up to the +time it executes. This is also known as "schedule latency". +I stress the point that this is about RT tasks. It is also important +to know the scheduling latency of non-RT tasks, but the average +schedule latency is better for non-RT tasks. Tools like +LatencyTop is more appropriate for such measurements. + +Real-Time environments is interested in the worst case latency. +That is the longest latency it takes for something to happen, and +not the average. We can have a very fast scheduler that may only +have a large latency once in a while, but that would not work well +with Real-Time tasks. The wakeup tracer was designed to record +the worst case wakeups of RT tasks. Non-RT tasks are not recorded +because the tracer only records one worst case and tracing non-RT +tasks that are unpredictable will overwrite the worst case latency +of RT tasks. + +Since this tracer only deals with RT tasks, we will run this slightly +different than we did with the previous tracers. Instead of performing +an 'ls' we will run 'sleep 1' under 'chrt' which changes the +priority of the task. + + # echo wakeup > /debug/tracing/current_tracer + # echo 0 > /debug/tracing/tracing_max_latency + # echo 1 > /debug/tracing/tracing_enabled + # chrt -f 5 sleep 1 + # echo 0 > /debug/tracing/tracing_enabled + # cat /debug/tracing/latency_trace +# tracer: wakeup +# +wakeup latency trace v1.1.5 on 2.6.26-rc8 +-------------------------------------------------------------------- + latency: 4 us, #2/2, CPU#1 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2) + ----------------- + | task: sleep-4901 (uid:0 nice:0 policy:1 rt_prio:5) + ----------------- + +# _------=> CPU# +# / _-----=> irqs-off +# | / _----=> need-resched +# || / _---=> hardirq/softirq +# ||| / _--=> preempt-depth +# |||| / +# ||||| delay +# cmd pid ||||| time | caller +# \ / ||||| \ | / + <idle>-0 1d.h4 0us+: try_to_wake_up (wake_up_process) + <idle>-0 1d..4 4us : schedule (cpu_idle) + + +vim:ft=help + + +Running this on an idle system we see that it only took 4 microseconds +to perform the task switch. Note, since the trace marker in the +schedule is before the actual "switch" we stop the tracing when +the recorded task is about to schedule in. This may change if +we add a new marker at the end of the scheduler. + +Notice that the recorded task is 'sleep' with the PID of 4901 and it +has an rt_prio of 5. This priority is user-space priority and not +the internal kernel priority. The policy is 1 for SCHED_FIFO and 2 +for SCHED_RR. + +Doing the same with chrt -r 5 and ftrace_enabled set. + +# tracer: wakeup +# +wakeup latency trace v1.1.5 on 2.6.26-rc8 +-------------------------------------------------------------------- + latency: 50 us, #60/60, CPU#1 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2) + ----------------- + | task: sleep-4068 (uid:0 nice:0 policy:2 rt_prio:5) + ----------------- + +# _------=> CPU# +# / _-----=> irqs-off +# | / _----=> need-resched +# || / _---=> hardirq/softirq +# ||| / _--=> preempt-depth +# |||| / +# ||||| delay +# cmd pid ||||| time | caller +# \ / ||||| \ | / +ksoftirq-7 1d.H3 0us : try_to_wake_up (wake_up_process) +ksoftirq-7 1d.H4 1us : sub_preempt_count (marker_probe_cb) +ksoftirq-7 1d.H3 2us : check_preempt_wakeup (try_to_wake_up) +ksoftirq-7 1d.H3 3us : update_curr (check_preempt_wakeup) +ksoftirq-7 1d.H3 4us : calc_delta_mine (update_curr) +ksoftirq-7 1d.H3 5us : __resched_task (check_preempt_wakeup) +ksoftirq-7 1d.H3 6us : task_wake_up_rt (try_to_wake_up) +ksoftirq-7 1d.H3 7us : _spin_unlock_irqrestore (try_to_wake_up) +[...] +ksoftirq-7 1d.H2 17us : irq_exit (smp_apic_timer_interrupt) +ksoftirq-7 1d.H2 18us : sub_preempt_count (irq_exit) +ksoftirq-7 1d.s3 19us : sub_preempt_count (irq_exit) +ksoftirq-7 1..s2 20us : rcu_process_callbacks (__do_softirq) +[...] +ksoftirq-7 1..s2 26us : __rcu_process_callbacks (rcu_process_callbacks) +ksoftirq-7 1d.s2 27us : _local_bh_enable (__do_softirq) +ksoftirq-7 1d.s2 28us : sub_preempt_count (_local_bh_enable) +ksoftirq-7 1.N.3 29us : sub_preempt_count (ksoftirqd) +ksoftirq-7 1.N.2 30us : _cond_resched (ksoftirqd) +ksoftirq-7 1.N.2 31us : __cond_resched (_cond_resched) +ksoftirq-7 1.N.2 32us : add_preempt_count (__cond_resched) +ksoftirq-7 1.N.2 33us : schedule (__cond_resched) +ksoftirq-7 1.N.2 33us : add_preempt_count (schedule) +ksoftirq-7 1.N.3 34us : hrtick_clear (schedule) +ksoftirq-7 1dN.3 35us : _spin_lock (schedule) +ksoftirq-7 1dN.3 36us : add_preempt_count (_spin_lock) +ksoftirq-7 1d..4 37us : put_prev_task_fair (schedule) +ksoftirq-7 1d..4 38us : update_curr (put_prev_task_fair) +[...] +ksoftirq-7 1d..5 47us : _spin_trylock (tracing_record_cmdline) +ksoftirq-7 1d..5 48us : add_preempt_count (_spin_trylock) +ksoftirq-7 1d..6 49us : _spin_unlock (tracing_record_cmdline) +ksoftirq-7 1d..6 49us : sub_preempt_count (_spin_unlock) +ksoftirq-7 1d..4 50us : schedule (__cond_resched) + +The interrupt went off while running ksoftirqd. This task runs at +SCHED_OTHER. Why didn't we see the 'N' set early? This may be +a harmless bug with x86_32 and 4K stacks. The need_reched() function +that tests if we need to reschedule looks on the actual stack. +Where as the setting of the NEED_RESCHED bit happens on the +task's stack. But because we are in a hard interrupt, the test +is with the interrupts stack which has that to be false. We don't +see the 'N' until we switch back to the task's stack. + +ftrace +------ + +ftrace is not only the name of the tracing infrastructure, but it +is also a name of one of the tracers. The tracer is the function +tracer. Enabling the function tracer can be done from the +debug file system. Make sure the ftrace_enabled is set otherwise +this tracer is a nop. + + # sysctl kernel.ftrace_enabled=1 + # echo ftrace > /debug/tracing/current_tracer + # echo 1 > /debug/tracing/tracing_enabled + # usleep 1 + # echo 0 > /debug/tracing/tracing_enabled + # cat /debug/tracing/trace +# tracer: ftrace +# +# TASK-PID CPU# TIMESTAMP FUNCTION +# | | | | | + bash-4003 [00] 123.638713: finish_task_switch <-schedule + bash-4003 [00] 123.638714: _spin_unlock_irq <-finish_task_switch + bash-4003 [00] 123.638714: sub_preempt_count <-_spin_unlock_irq + bash-4003 [00] 123.638715: hrtick_set <-schedule + bash-4003 [00] 123.638715: _spin_lock_irqsave <-hrtick_set + bash-4003 [00] 123.638716: add_preempt_count <-_spin_lock_irqsave + bash-4003 [00] 123.638716: _spin_unlock_irqrestore <-hrtick_set + bash-4003 [00] 123.638717: sub_preempt_count <-_spin_unlock_irqrestore + bash-4003 [00] 123.638717: hrtick_clear <-hrtick_set + bash-4003 [00] 123.638718: sub_preempt_count <-schedule + bash-4003 [00] 123.638718: sub_preempt_count <-preempt_schedule + bash-4003 [00] 123.638719: wait_for_completion <-__stop_machine_run + bash-4003 [00] 123.638719: wait_for_common <-wait_for_completion + bash-4003 [00] 123.638720: _spin_lock_irq <-wait_for_common + bash-4003 [00] 123.638720: add_preempt_count <-_spin_lock_irq +[...] + + +Note: It is sometimes better to enable or disable tracing directly from +a program, because the buffer may be overflowed by the echo commands +before you get to the point you want to trace. It is also easier to +stop the tracing at the point that you hit the part that you are +interested in. Since the ftrace buffer is a ring buffer with the +oldest data being overwritten, usually it is sufficient to start the +tracer with an echo command but have you code stop it. Something +like the following is usually appropriate for this. + +int trace_fd; +[...] +int main(int argc, char *argv[]) { + [...] + trace_fd = open("/debug/tracing/tracing_enabled", O_WRONLY); + [...] + if (condition_hit()) { + write(trace_fd, "0", 1); + } + [...] +} + + +dynamic ftrace +-------------- + +If CONFIG_DYNAMIC_FTRACE is set, then the system will run with +virtually no overhead when function tracing is disabled. The way +this works is the mcount function call (placed at the start of +every kernel function, produced by the -pg switch in gcc), starts +of pointing to a simple return. + +When dynamic ftrace is initialized, it calls kstop_machine to make it +act like a uniprocessor so that it can freely modify code without +worrying about other processors executing that same code. At +initialization, the mcount calls are change to call a "record_ip" +function. After this, the first time a kernel function is called, +it has the calling address saved in a hash table. + +Later on the ftraced kernel thread is awoken and will again call +kstop_machine if new functions have been recorded. The ftraced thread +will change all calls to mcount to "nop". Just calling mcount +and having mcount return has shown a 10% overhead. By converting +it to a nop, there is no recordable overhead to the system. + +One special side-effect to the recording of the functions being +traced, is that we can now selectively choose which functions we +want to trace and which ones we want the mcount calls to remain as +nops. + +Two files that contain to the enabling and disabling of recorded +functions are: + + set_ftrace_filter + +and + + set_ftrace_notrace + +A list of available functions that you can add to this files is listed +in: + + available_filter_functions + + # cat /debug/tracing/available_filter_functions +put_prev_task_idle +kmem_cache_create +pick_next_task_rt +get_online_cpus +pick_next_task_fair +mutex_lock +[...] + +If I'm only interested in sys_nanosleep and hrtimer_interrupt: + + # echo sys_nanosleep hrtimer_interrupt \ + > /debug/tracing/set_ftrace_filter + # echo ftrace > /debug/tracing/current_tracer + # echo 1 > /debug/tracing/tracing_enabled + # usleep 1 + # echo 0 > /debug/tracing/tracing_enabled + # cat /debug/tracing/trace +# tracer: ftrace +# +# TASK-PID CPU# TIMESTAMP FUNCTION +# | | | | | + usleep-4134 [00] 1317.070017: hrtimer_interrupt <-smp_apic_timer_interrupt + usleep-4134 [00] 1317.070111: sys_nanosleep <-syscall_call + <idle>-0 [00] 1317.070115: hrtimer_interrupt <-smp_apic_timer_interrupt + +To see what functions are being traced, you can cat the file: + + # cat /debug/tracing/set_ftrace_filter +hrtimer_interrupt +sys_nanosleep + + +Perhaps this isn't enough. The filters also allow simple wild cards. +Only the following is currently available + + <match>* - will match functions that begins with <match> + *<match> - will match functions that end with <match> + *<match>* - will match functions that have <match> in it + +Thats all the wild cards that are allowed. + + <match>*<match> will not work. + + # echo hrtimer_* > /debug/tracing/set_ftrace_filter + +Produces: + +# tracer: ftrace +# +# TASK-PID CPU# TIMESTAMP FUNCTION +# | | | | | + bash-4003 [00] 1480.611794: hrtimer_init <-copy_process + bash-4003 [00] 1480.611941: hrtimer_start <-hrtick_set + bash-4003 [00] 1480.611956: hrtimer_cancel <-hrtick_clear + bash-4003 [00] 1480.611956: hrtimer_try_to_cancel <-hrtimer_cancel + <idle>-0 [00] 1480.612019: hrtimer_get_next_event <-get_next_timer_interrupt + <idle>-0 [00] 1480.612025: hrtimer_get_next_event <-get_next_timer_interrupt + <idle>-0 [00] 1480.612032: hrtimer_get_next_event <-get_next_timer_interrupt + <idle>-0 [00] 1480.612037: hrtimer_get_next_event <-get_next_timer_interrupt + <idle>-0 [00] 1480.612382: hrtimer_get_next_event <-get_next_timer_interrupt + + +Notice that we lost the sys_nanosleep. + + # cat /debug/tracing/set_ftrace_filter +hrtimer_run_queues +hrtimer_run_pending +hrtimer_init +hrtimer_cancel +hrtimer_try_to_cancel +hrtimer_forward +hrtimer_start +hrtimer_reprogram +hrtimer_force_reprogram +hrtimer_get_next_event +hrtimer_interrupt +hrtimer_nanosleep +hrtimer_wakeup +hrtimer_get_remaining +hrtimer_get_res +hrtimer_init_sleeper + + +This is because the '>' and '>>' act just like they do in bash. +To rewrite the filters, use '>' +To append to the filters, use '>>' + +To clear out a filter so that all functions will be recorded again. + + # echo > /debug/tracing/set_ftrace_filter + # cat /debug/tracing/set_ftrace_filter + # + +Again, now we want to append. + + # echo sys_nanosleep > /debug/tracing/set_ftrace_filter + # cat /debug/tracing/set_ftrace_filter +sys_nanosleep + # echo hrtimer_* >> /debug/tracing/set_ftrace_filter + # cat /debug/tracing/set_ftrace_filter +hrtimer_run_queues +hrtimer_run_pending +hrtimer_init +hrtimer_cancel +hrtimer_try_to_cancel +hrtimer_forward +hrtimer_start +hrtimer_reprogram +hrtimer_force_reprogram +hrtimer_get_next_event +hrtimer_interrupt +sys_nanosleep +hrtimer_nanosleep +hrtimer_wakeup +hrtimer_get_remaining +hrtimer_get_res +hrtimer_init_sleeper + + +The set_ftrace_notrace prevents those functions from being traced. + + # echo '*preempt*' '*lock*' > /debug/tracing/set_ftrace_notrace + +Produces: + +# tracer: ftrace +# +# TASK-PID CPU# TIMESTAMP FUNCTION +# | | | | | + bash-4043 [01] 115.281644: finish_task_switch <-schedule + bash-4043 [01] 115.281645: hrtick_set <-schedule + bash-4043 [01] 115.281645: hrtick_clear <-hrtick_set + bash-4043 [01] 115.281646: wait_for_completion <-__stop_machine_run + bash-4043 [01] 115.281647: wait_for_common <-wait_for_completion + bash-4043 [01] 115.281647: kthread_stop <-stop_machine_run + bash-4043 [01] 115.281648: init_waitqueue_head <-kthread_stop + bash-4043 [01] 115.281648: wake_up_process <-kthread_stop + bash-4043 [01] 115.281649: try_to_wake_up <-wake_up_process + +We can see that there's no more lock or preempt tracing. + +ftraced +------- + +As mentioned above, when dynamic ftrace is configured in, a kernel +thread wakes up once a second and checks to see if there are mcount +calls that need to be converted into nops. If there is not, then +it simply goes back to sleep. But if there is, it will call +kstop_machine to convert the calls to nops. + +There may be a case that you do not want this added latency. +Perhaps you are doing some audio recording and this activity might +cause skips in the playback. There is an interface to disable +and enable the ftraced kernel thread. + + # echo 0 > /debug/tracing/ftraced_enabled + +This will disable the calling of the kstop_machine to update the +mcount calls to nops. Remember that there's a large overhead +to calling mcount. Without this kernel thread, that overhead will +exist. + +Any write to the ftraced_enabled file will cause the kstop_machine +to run if there are recorded calls to mcount. This means that a +user can manually perform the updates when they want to by simply +echoing a '0' into the ftraced_enabled file. + +The updates are also done at the beginning of enabling a tracer +that uses ftrace function recording. + + +trace_pipe +---------- + +The trace_pipe outputs the same as trace, but the effect on the +tracing is different. Every read from trace_pipe is consumed. +This means that subsequent reads will be different. The trace +is live. + + # echo ftrace > /debug/tracing/current_tracer + # cat /debug/tracing/trace_pipe > /tmp/trace.out & +[1] 4153 + # echo 1 > /debug/tracing/tracing_enabled + # usleep 1 + # echo 0 > /debug/tracing/tracing_enabled + # cat /debug/tracing/trace +# tracer: ftrace +# +# TASK-PID CPU# TIMESTAMP FUNCTION +# | | | | | + + # + # cat /tmp/trace.out + bash-4043 [00] 41.267106: finish_task_switch <-schedule + bash-4043 [00] 41.267106: hrtick_set <-schedule + bash-4043 [00] 41.267107: hrtick_clear <-hrtick_set + bash-4043 [00] 41.267108: wait_for_completion <-__stop_machine_run + bash-4043 [00] 41.267108: wait_for_common <-wait_for_completion + bash-4043 [00] 41.267109: kthread_stop <-stop_machine_run + bash-4043 [00] 41.267109: init_waitqueue_head <-kthread_stop + bash-4043 [00] 41.267110: wake_up_process <-kthread_stop + bash-4043 [00] 41.267110: try_to_wake_up <-wake_up_process + bash-4043 [00] 41.267111: select_task_rq_rt <-try_to_wake_up + + +Note, reading the trace_pipe will block until more input is added. +By changing the tracer, trace_pipe will issue an EOF. We needed +to set the ftrace tracer _before_ cating the trace_pipe file. + + +trace entries +------------- + +Having too much or not enough data can be troublesome in diagnosing +some issue in the kernel. The file trace_entries is used to modify +the size of the internal trace buffers. The numbers listed +is the number of entries that can be recorded per CPU. To know +the full size, multiply the number of possible CPUS with the +number of entries. + + # cat /debug/tracing/trace_entries +65620 + +Note, to modify this you must have tracing fulling disabled. To do that, +echo "none" into the current_tracer. + + # echo none > /debug/tracing/current_tracer + # echo 100000 > /debug/tracing/trace_entries + # cat /debug/tracing/trace_entries +100045 + + +Notice that we echoed in 100,000 but the size is 100,045. The entries +are held by individual pages. It allocates the number of pages it takes +to fulfill the request. If more entries may fit on the last page +it will add them. + + # echo 1 > /debug/tracing/trace_entries + # cat /debug/tracing/trace_entries +85 + +This shows us that 85 entries can fit on a single page. + +The number of pages that will be allocated is a percentage of available +memory. Allocating too much will produces an error. + + # echo 1000000000000 > /debug/tracing/trace_entries +-bash: echo: write error: Cannot allocate memory + # cat /debug/tracing/trace_entries +85 + diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index e07c432c731..b52f47d588b 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -295,7 +295,7 @@ and is between 256 and 4096 characters. It is defined in the file when initialising the APIC and IO-APIC components. apm= [APM] Advanced Power Management - See header of arch/i386/kernel/apm.c. + See header of arch/x86/kernel/apm_32.c. arcrimi= [HW,NET] ARCnet - "RIM I" (entirely mem-mapped) cards Format: <io>,<irq>,<nodeID> @@ -638,7 +638,7 @@ and is between 256 and 4096 characters. It is defined in the file elanfreq= [X86-32] See comment before function elanfreq_setup() in - arch/i386/kernel/cpu/cpufreq/elanfreq.c. + arch/x86/kernel/cpu/cpufreq/elanfreq.c. elevator= [IOSCHED] Format: {"anticipatory" | "cfq" | "deadline" | "noop"} @@ -1679,6 +1679,10 @@ and is between 256 and 4096 characters. It is defined in the file Format: <reboot_mode>[,<reboot_mode2>[,...]] See arch/*/kernel/reboot.c or arch/*/kernel/process.c + relax_domain_level= + [KNL, SMP] Set scheduler's default relax_domain_level. + See Documentation/cpusets.txt. + reserve= [KNL,BUGS] Force the kernel to ignore some iomem area reservetop= [X86-32] diff --git a/Documentation/vm/slabinfo.c b/Documentation/vm/slabinfo.c index e4230ed16ee..df3227605d5 100644 --- a/Documentation/vm/slabinfo.c +++ b/Documentation/vm/slabinfo.c @@ -1,7 +1,7 @@ /* * Slabinfo: Tool to get reports about slabs * - * (C) 2007 sgi, Christoph Lameter <clameter@sgi.com> + * (C) 2007 sgi, Christoph Lameter * * Compile by: * @@ -99,7 +99,7 @@ void fatal(const char *x, ...) void usage(void) { - printf("slabinfo 5/7/2007. (c) 2007 sgi. clameter@sgi.com\n\n" + printf("slabinfo 5/7/2007. (c) 2007 sgi.\n\n" "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n" "-a|--aliases Show aliases\n" "-A|--activity Most active slabs first\n" diff --git a/Documentation/vm/slub.txt b/Documentation/vm/slub.txt index 7c13f22a0c9..bb1f5c6e28b 100644 --- a/Documentation/vm/slub.txt +++ b/Documentation/vm/slub.txt @@ -266,4 +266,4 @@ of other objects. slub_debug=FZ,dentry -Christoph Lameter, <clameter@sgi.com>, May 30, 2007 +Christoph Lameter, May 30, 2007 diff --git a/MAINTAINERS b/MAINTAINERS index e6c06fa3290..6476125363e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -763,9 +763,10 @@ S: Maintained AUXILIARY DISPLAY DRIVERS P: Miguel Ojeda Sandonis -M: maxextreme@gmail.com +M: miguel.ojeda.sandonis@gmail.com L: linux-kernel@vger.kernel.org -W: http://auxdisplay.googlepages.com/ +W: http://miguelojeda.es/auxdisplay.htm +W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm S: Maintained AVR32 ARCHITECTURE @@ -1055,16 +1056,18 @@ S: Supported CFAG12864B LCD DRIVER P: Miguel Ojeda Sandonis -M: maxextreme@gmail.com +M: miguel.ojeda.sandonis@gmail.com L: linux-kernel@vger.kernel.org -W: http://auxdisplay.googlepages.com/ +W: http://miguelojeda.es/auxdisplay.htm +W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm S: Maintained CFAG12864BFB LCD FRAMEBUFFER DRIVER P: Miguel Ojeda Sandonis -M: maxextreme@gmail.com +M: miguel.ojeda.sandonis@gmail.com L: linux-kernel@vger.kernel.org -W: http://auxdisplay.googlepages.com/ +W: http://miguelojeda.es/auxdisplay.htm +W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm S: Maintained CFG80211 and NL80211 @@ -1420,6 +1423,14 @@ M: kristen.c.accardi@intel.com L: linux-acpi@vger.kernel.org S: Supported +DOCUMENTATION (/Documentation directory) +P: Michael Kerrisk +M: mtk.manpages@gmail.com +P: Randy Dunlap +M: rdunlap@xenotime.net +L: linux-doc@vger.kernel.org +S: Maintained + DOUBLETALK DRIVER P: James R. Van Zandt M: jrv@vanzandt.mv.com @@ -1626,13 +1637,13 @@ S: Maintained EXT3 FILE SYSTEM P: Stephen Tweedie, Andrew Morton -M: sct@redhat.com, akpm@linux-foundation.org, adilger@clusterfs.com +M: sct@redhat.com, akpm@linux-foundation.org, adilger@sun.com L: linux-ext4@vger.kernel.org S: Maintained EXT4 FILE SYSTEM P: Stephen Tweedie, Andrew Morton -M: sct@redhat.com, akpm@linux-foundation.org, adilger@clusterfs.com +M: sct@redhat.com, akpm@linux-foundation.org, adilger@sun.com L: linux-ext4@vger.kernel.org S: Maintained @@ -2428,9 +2439,10 @@ S: Maintained KS0108 LCD CONTROLLER DRIVER P: Miguel Ojeda Sandonis -M: maxextreme@gmail.com +M: miguel.ojeda.sandonis@gmail.com L: linux-kernel@vger.kernel.org -W: http://auxdisplay.googlepages.com/ +W: http://miguelojeda.es/auxdisplay.htm +W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm S: Maintained LAPB module @@ -2474,9 +2486,11 @@ M: James.Bottomley@HansenPartnership.com W: http://www.hansenpartnership.com/voyager S: Maintained -LINUX FOR POWERPC +LINUX FOR POWERPC (32-BIT AND 64-BIT) P: Paul Mackerras M: paulus@samba.org +P: Benjamin Herrenschmidt +M: benh@kernel.crashing.org W: http://www.penguinppc.org/ L: linuxppc-dev@ozlabs.org T: git kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc.git @@ -2516,13 +2530,6 @@ W: http://wiki.secretlab.ca/index.php/Linux_on_Xilinx_Virtex L: linuxppc-dev@ozlabs.org S: Maintained -LINUX FOR POWERPC BOOT CODE -P: Tom Rini -M: trini@kernel.crashing.org -W: http://www.penguinppc.org/ -L: linuxppc-dev@ozlabs.org -S: Maintained - LINUX FOR POWERPC EMBEDDED PPC8XX P: Vitaly Bordug M: vitb@kernel.crashing.org @@ -2551,17 +2558,6 @@ P: Arnaldo Carvalho de Melo M: acme@ghostprotocols.net S: Maintained -LINUX FOR 64BIT POWERPC -P: Paul Mackerras -M: paulus@samba.org -M: paulus@au.ibm.com -P: Anton Blanchard -M: anton@samba.org -M: anton@au.ibm.com -W: http://www.penguinppc.org/ppc64/ -L: linuxppc-dev@ozlabs.org -S: Supported - LINUX SECURITY MODULE (LSM) FRAMEWORK P: Chris Wright M: chrisw@sous-sol.org @@ -2680,8 +2676,8 @@ S: Supported MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7 P: Michael Kerrisk M: mtk.manpages@gmail.com -W: ftp://ftp.kernel.org/pub/linux/docs/manpages -S: Maintained +W: http://www.kernel.org/doc/man-pages +S: Supported MARVELL LIBERTAS WIRELESS DRIVER P: Dan Williams @@ -2814,6 +2810,12 @@ W: https://tango.0pointer.de/mailman/listinfo/s270-linux W: http://0pointer.de/lennart/tchibo.html S: Maintained +MULTIFUNCTION DEVICES (MFD) +P: Samuel Ortiz +M: sameo@openedhand.com +L: linux-kernel@vger.kernel.org +S: Supported + MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM P: Pierre Ossman M: drzeus-mmc@drzeus.cx @@ -3195,8 +3197,8 @@ L: netdev@vger.kernel.org S: Maintained PER-TASK DELAY ACCOUNTING -P: Shailabh Nagar -M: nagar@watson.ibm.com +P: Balbir Singh +M: balbir@linux.vnet.ibm.com L: linux-kernel@vger.kernel.org S: Maintained @@ -3688,7 +3690,7 @@ S: Maintained SLAB ALLOCATOR P: Christoph Lameter -M: clameter@sgi.com +M: cl@linux-foundation.org P: Pekka Enberg M: penberg@cs.helsinki.fi P: Matt Mackall @@ -3898,8 +3900,8 @@ M: hch@infradead.org S: Maintained TASKSTATS STATISTICS INTERFACE -P: Shailabh Nagar -M: nagar@watson.ibm.com +P: Balbir Singh +M: balbir@linux.vnet.ibm.com L: linux-kernel@vger.kernel.org S: Maintained @@ -3995,7 +3997,8 @@ W: http://www.buzzard.org.uk/toshiba/ S: Maintained TPM DEVICE DRIVER -P: Kylene Hall +P: Debora Velarde +P: Rajiv Andrade M: tpmdd-devel@lists.sourceforge.net W: http://tpmdd.sourceforge.net P: Marcel Selhorst @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 26 -EXTRAVERSION = -rc8 +EXTRAVERSION = -rc9 NAME = Rotary Wombat # *DOCUMENTATION* diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S index f13249be17c..ef37fc1acae 100644 --- a/arch/alpha/kernel/vmlinux.lds.S +++ b/arch/alpha/kernel/vmlinux.lds.S @@ -25,6 +25,13 @@ SECTIONS } :kernel _etext = .; /* End of text section */ + NOTES :kernel :note + .dummy : { + *(.dummy) + } :kernel + + RODATA + /* Exception table */ . = ALIGN(16); __ex_table : { @@ -33,13 +40,6 @@ SECTIONS __stop___ex_table = .; } - NOTES :kernel :note - .dummy : { - *(.dummy) - } :kernel - - RODATA - /* Will be freed after init */ . = ALIGN(PAGE_SIZE); /* Init code and data */ diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index e5a7c5d9636..24c5dee9176 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1006,7 +1006,7 @@ config BOOT_ELF32 config MIPS_L1_CACHE_SHIFT int default "4" if MACH_DECSTATION - default "7" if SGI_IP27 || SGI_IP28 || SNI_RM + default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM default "4" if PMC_MSP4200_EVAL default "5" diff --git a/arch/mips/kernel/cevt-txx9.c b/arch/mips/kernel/cevt-txx9.c index 795cb8fb0d7..b5fc4eb412d 100644 --- a/arch/mips/kernel/cevt-txx9.c +++ b/arch/mips/kernel/cevt-txx9.c @@ -161,6 +161,9 @@ void __init txx9_tmr_init(unsigned long baseaddr) struct txx9_tmr_reg __iomem *tmrptr; tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg)); + /* Start once to make CounterResetEnable effective */ + __raw_writel(TXx9_TMTCR_CRE | TXx9_TMTCR_TCE, &tmrptr->tcr); + /* Stop and reset the counter */ __raw_writel(TXx9_TMTCR_CRE, &tmrptr->tcr); __raw_writel(0, &tmrptr->tisr); __raw_writel(0xffffffff, &tmrptr->cpra); diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c index 76935e32021..27a5b466c85 100644 --- a/arch/mips/mm/c-r3k.c +++ b/arch/mips/mm/c-r3k.c @@ -26,7 +26,7 @@ static unsigned long icache_size, dcache_size; /* Size in bytes */ static unsigned long icache_lsize, dcache_lsize; /* Size in bytes */ -unsigned long __init r3k_cache_size(unsigned long ca_flags) +unsigned long __cpuinit r3k_cache_size(unsigned long ca_flags) { unsigned long flags, status, dummy, size; volatile unsigned long *p; @@ -61,7 +61,7 @@ unsigned long __init r3k_cache_size(unsigned long ca_flags) return size * sizeof(*p); } -unsigned long __init r3k_cache_lsize(unsigned long ca_flags) +unsigned long __cpuinit r3k_cache_lsize(unsigned long ca_flags) { unsigned long flags, status, lsize, i; volatile unsigned long *p; @@ -90,7 +90,7 @@ unsigned long __init r3k_cache_lsize(unsigned long ca_flags) return lsize * sizeof(*p); } -static void __init r3k_probe_cache(void) +static void __cpuinit r3k_probe_cache(void) { dcache_size = r3k_cache_size(ST0_ISC); if (dcache_size) diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c index 1edf0cbbeed..1417c649485 100644 --- a/arch/mips/mm/page.c +++ b/arch/mips/mm/page.c @@ -235,13 +235,12 @@ static void __cpuinit set_prefetch_parameters(void) } /* * Too much unrolling will overflow the available space in - * clear_space_array / copy_page_array. 8 words sounds generous, - * but a R4000 with 128 byte L2 line length can exceed even that. + * clear_space_array / copy_page_array. */ - half_clear_loop_size = min(8 * clear_word_size, + half_clear_loop_size = min(16 * clear_word_size, max(cache_line_size >> 1, 4 * clear_word_size)); - half_copy_loop_size = min(8 * copy_word_size, + half_copy_loop_size = min(16 * copy_word_size, max(cache_line_size >> 1, 4 * copy_word_size)); } @@ -263,21 +262,23 @@ static inline void __cpuinit build_clear_pref(u32 **buf, int off) if (pref_bias_clear_store) { uasm_i_pref(buf, pref_dst_mode, pref_bias_clear_store + off, A0); - } else if (cpu_has_cache_cdex_s) { - uasm_i_cache(buf, Create_Dirty_Excl_SD, off, A0); - } else if (cpu_has_cache_cdex_p) { - if (R4600_V1_HIT_CACHEOP_WAR && cpu_is_r4600_v1_x()) { - uasm_i_nop(buf); - uasm_i_nop(buf); - uasm_i_nop(buf); - uasm_i_nop(buf); - } + } else if (cache_line_size == (half_clear_loop_size << 1)) { + if (cpu_has_cache_cdex_s) { + uasm_i_cache(buf, Create_Dirty_Excl_SD, off, A0); + } else if (cpu_has_cache_cdex_p) { + if (R4600_V1_HIT_CACHEOP_WAR && cpu_is_r4600_v1_x()) { + uasm_i_nop(buf); + uasm_i_nop(buf); + uasm_i_nop(buf); + uasm_i_nop(buf); + } - if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) - uasm_i_lw(buf, ZERO, ZERO, AT); + if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) + uasm_i_lw(buf, ZERO, ZERO, AT); - uasm_i_cache(buf, Create_Dirty_Excl_D, off, A0); - } + uasm_i_cache(buf, Create_Dirty_Excl_D, off, A0); + } + } } void __cpuinit build_clear_page(void) @@ -403,20 +404,22 @@ static inline void build_copy_store_pref(u32 **buf, int off) if (pref_bias_copy_store) { uasm_i_pref(buf, pref_dst_mode, pref_bias_copy_store + off, A0); - } else if (cpu_has_cache_cdex_s) { - uasm_i_cache(buf, Create_Dirty_Excl_SD, off, A0); - } else if (cpu_has_cache_cdex_p) { - if (R4600_V1_HIT_CACHEOP_WAR && cpu_is_r4600_v1_x()) { - uasm_i_nop(buf); - uasm_i_nop(buf); - uasm_i_nop(buf); - uasm_i_nop(buf); - } + } else if (cache_line_size == (half_copy_loop_size << 1)) { + if (cpu_has_cache_cdex_s) { + uasm_i_cache(buf, Create_Dirty_Excl_SD, off, A0); + } else if (cpu_has_cache_cdex_p) { + if (R4600_V1_HIT_CACHEOP_WAR && cpu_is_r4600_v1_x()) { + uasm_i_nop(buf); + uasm_i_nop(buf); + uasm_i_nop(buf); + uasm_i_nop(buf); + } - if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) - uasm_i_lw(buf, ZERO, ZERO, AT); + if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) + uasm_i_lw(buf, ZERO, ZERO, AT); - uasm_i_cache(buf, Create_Dirty_Excl_D, off, A0); + uasm_i_cache(buf, Create_Dirty_Excl_D, off, A0); + } } } diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c index fc227f3b119..e3abfb2d7e8 100644 --- a/arch/mips/mm/sc-rm7k.c +++ b/arch/mips/mm/sc-rm7k.c @@ -86,7 +86,7 @@ static void rm7k_sc_inv(unsigned long addr, unsigned long size) /* * This function is executed in uncached address space. */ -static __init void __rm7k_sc_enable(void) +static __cpuinit void __rm7k_sc_enable(void) { int i; @@ -107,7 +107,7 @@ static __init void __rm7k_sc_enable(void) } } -static __init void rm7k_sc_enable(void) +static __cpuinit void rm7k_sc_enable(void) { if (read_c0_config() & RM7K_CONF_SE) return; diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c index b0ea0e43ba4..0d6b6663d5f 100644 --- a/arch/mips/sgi-ip32/ip32-irq.c +++ b/arch/mips/sgi-ip32/ip32-irq.c @@ -425,6 +425,11 @@ static void ip32_irq0(void) BUILD_BUG_ON(MACEISA_SERIAL2_RDMAOR_IRQ - MACEISA_AUDIO_SW_IRQ != 31); crime_int = crime->istat & crime_mask; + + /* crime sometime delivers spurious interrupts, ignore them */ + if (unlikely(crime_int == 0)) + return; + irq = MACE_VID_IN1_IRQ + __ffs(crime_int); if (crime_int & CRIME_MACEISA_INT_MASK) { diff --git a/arch/mn10300/kernel/mn10300_ksyms.c b/arch/mn10300/kernel/mn10300_ksyms.c index 6d19628634e..f9eb9753a40 100644 --- a/arch/mn10300/kernel/mn10300_ksyms.c +++ b/arch/mn10300/kernel/mn10300_ksyms.c @@ -10,8 +10,11 @@ */ #include <linux/module.h> #include <asm/uaccess.h> +#include <asm/pgtable.h> +EXPORT_SYMBOL(empty_zero_page); + EXPORT_SYMBOL(change_bit); EXPORT_SYMBOL(test_and_change_bit); @@ -31,7 +34,9 @@ extern u64 __ashrdi3(u64, unsigned); extern u64 __ashldi3(u64, unsigned); extern u64 __lshrdi3(u64, unsigned); extern s64 __negdi2(s64); +extern int __ucmpdi2(u64, u64); EXPORT_SYMBOL(__ashrdi3); EXPORT_SYMBOL(__ashldi3); EXPORT_SYMBOL(__lshrdi3); EXPORT_SYMBOL(__negdi2); +EXPORT_SYMBOL(__ucmpdi2); diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index 9c623c88387..b28c9a60445 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c @@ -153,6 +153,7 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } +EXPORT_SYMBOL(kernel_thread); /* * free current thread data structures etc.. diff --git a/arch/mn10300/lib/Makefile b/arch/mn10300/lib/Makefile index fdfa9ec5b5b..0cd2346f4c1 100644 --- a/arch/mn10300/lib/Makefile +++ b/arch/mn10300/lib/Makefile @@ -4,4 +4,4 @@ lib-y = delay.o usercopy.o checksum.o bitops.o memcpy.o memmove.o memset.o lib-y += do_csum.o -lib-y += __ashldi3.o __ashrdi3.o __lshrdi3.o negdi2.o +lib-y += __ashldi3.o __ashrdi3.o __lshrdi3.o negdi2.o __ucmpdi2.o diff --git a/arch/mn10300/lib/__ucmpdi2.S b/arch/mn10300/lib/__ucmpdi2.S new file mode 100644 index 00000000000..60dcbdfe386 --- /dev/null +++ b/arch/mn10300/lib/__ucmpdi2.S @@ -0,0 +1,43 @@ +/* __ucmpdi2.S: 64-bit unsigned compare + * + * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * 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. + */ + + + .text + .p2align 4 + +############################################################################### +# +# int __ucmpdi2(unsigned long long a [D0:D1], +# unsigned long long b [(SP,12),(SP,16)]) +# +# - returns 0, 1, or 2 as a <, =, > b respectively. +# +############################################################################### + .globl __ucmpdi2 + .type __ucmpdi2,@function +__ucmpdi2: + mov (12,sp),a0 # b.lsw + mov (16,sp),a1 # b.msw + + sub a0,d0 + subc a1,d1 # may clear Z, never sets it + bne __ucmpdi2_differ # a.msw != b.msw + mov +1,d0 + rets + +__ucmpdi2_differ: + # C flag is set if LE, clear if GE + subc d0,d0 # -1 if LE, 0 if GE + add +1,d0 # 0 if LE, 1 if GE + add d0,d0 # 0 if LE, 2 if GE + rets + + .size __ucmpdi2, .-__ucmpdi2 diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index cf37f5ca4b7..4d96e1db55e 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c @@ -33,13 +33,14 @@ static struct legacy_serial_info { phys_addr_t taddr; } legacy_serial_infos[MAX_LEGACY_SERIAL_PORTS]; -static struct __initdata of_device_id parents[] = { +static struct __initdata of_device_id legacy_serial_parents[] = { {.type = "soc",}, {.type = "tsi-bridge",}, {.type = "opb", }, {.compatible = "ibm,opb",}, {.compatible = "simple-bus",}, {.compatible = "wrs,epld-localbus",}, + {}, }; static unsigned int legacy_serial_count; @@ -327,7 +328,7 @@ void __init find_legacy_serial_ports(void) struct device_node *parent = of_get_parent(np); if (!parent) continue; - if (of_match_node(parents, parent) != NULL) { + if (of_match_node(legacy_serial_parents, parent) != NULL) { index = add_legacy_soc_port(np, np); if (index >= 0 && np == stdout) legacy_serial_console = index; diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index e79ad8afda0..3f37a6e6277 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c @@ -76,6 +76,8 @@ struct of_device* of_platform_device_create(struct device_node *np, return NULL; dev->dma_mask = 0xffffffffUL; + dev->dev.coherent_dma_mask = DMA_32BIT_MASK; + dev->dev.bus = &of_platform_bus_type; /* We do not fill the DMA ops for platform devices by default. diff --git a/arch/um/Makefile b/arch/um/Makefile index dbeab15e7bb..ca40397017b 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -77,7 +77,6 @@ include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) KERNEL_DEFINES = $(strip -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \ -Dmktime=kernel_mktime $(ARCH_KERNEL_DEFINES)) KBUILD_CFLAGS += $(KERNEL_DEFINES) -KBUILD_CFLAGS += $(call cc-option,-fno-unit-at-a-time,) PHONY += linux diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 561e373bd85..302cbe50454 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -32,4 +32,11 @@ cflags-y += $(call cc-option,-mpreferred-stack-boundary=2) # an unresolved reference. cflags-y += -ffreestanding +# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use +# a lot more stack due to the lack of sharing of stacklots. Also, gcc +# 4.3.0 needs -funit-at-a-time for extern inline functions. +KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \ + echo $(call cc-option,-fno-unit-at-a-time); \ + else echo $(call cc-option,-funit-at-a-time); fi ;) + KBUILD_CFLAGS += $(cflags-y) diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64 index 8ed362f9358..a9cd7e77a7a 100644 --- a/arch/um/Makefile-x86_64 +++ b/arch/um/Makefile-x86_64 @@ -21,3 +21,6 @@ HEADER_ARCH := x86 LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64 LINK-y += -m64 + +# Do unit-at-a-time unconditionally on x86_64, following the host +KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time) diff --git a/arch/x86/kernel/.gitignore b/arch/x86/kernel/.gitignore index 4ea38a39aed..08f4fd73146 100644 --- a/arch/x86/kernel/.gitignore +++ b/arch/x86/kernel/.gitignore @@ -1,2 +1,3 @@ vsyscall.lds vsyscall_32.lds +vmlinux.lds diff --git a/arch/x86/kernel/acpi/realmode/wakeup.S b/arch/x86/kernel/acpi/realmode/wakeup.S index f9b77fb37e5..3355973b12a 100644 --- a/arch/x86/kernel/acpi/realmode/wakeup.S +++ b/arch/x86/kernel/acpi/realmode/wakeup.S @@ -5,6 +5,7 @@ #include <asm/msr-index.h> #include <asm/page.h> #include <asm/pgtable.h> +#include <asm/processor-flags.h> .code16 .section ".header", "a" @@ -24,6 +25,11 @@ pmode_gdt: .quad 0 realmode_flags: .long 0 real_magic: .long 0 trampoline_segment: .word 0 +_pad1: .byte 0 +wakeup_jmp: .byte 0xea /* ljmpw */ +wakeup_jmp_off: .word 3f +wakeup_jmp_seg: .word 0 +wakeup_gdt: .quad 0, 0, 0 signature: .long 0x51ee1111 .text @@ -34,11 +40,34 @@ _start: cli cld + /* Apparently some dimwit BIOS programmers don't know how to + program a PM to RM transition, and we might end up here with + junk in the data segment descriptor registers. The only way + to repair that is to go into PM and fix it ourselves... */ + movw $16, %cx + lgdtl %cs:wakeup_gdt + movl %cr0, %eax + orb $X86_CR0_PE, %al + movl %eax, %cr0 + jmp 1f +1: ljmpw $8, $2f +2: + movw %cx, %ds + movw %cx, %es + movw %cx, %ss + movw %cx, %fs + movw %cx, %gs + + andb $~X86_CR0_PE, %al + movl %eax, %cr0 + jmp wakeup_jmp +3: /* Set up segments */ movw %cs, %ax movw %ax, %ds movw %ax, %es movw %ax, %ss + lidtl wakeup_idt movl $wakeup_stack_end, %esp @@ -98,7 +127,14 @@ bogus_real_magic: jmp 1b .data - .balign 4 + .balign 8 + + /* This is the standard real-mode IDT */ +wakeup_idt: + .word 0xffff /* limit */ + .long 0 /* address */ + .word 0 + .globl HEAP, heap_end HEAP: .long wakeup_heap diff --git a/arch/x86/kernel/acpi/realmode/wakeup.h b/arch/x86/kernel/acpi/realmode/wakeup.h index ef8166fe802..69d38d0b2b6 100644 --- a/arch/x86/kernel/acpi/realmode/wakeup.h +++ b/arch/x86/kernel/acpi/realmode/wakeup.h @@ -24,6 +24,11 @@ struct wakeup_header { u32 realmode_flags; u32 real_magic; u16 trampoline_segment; /* segment with trampoline code, 64-bit only */ + u8 _pad1; + u8 wakeup_jmp; + u16 wakeup_jmp_off; + u16 wakeup_jmp_seg; + u64 wakeup_gdt[3]; u32 signature; /* To check we have correct structure */ } __attribute__((__packed__)); diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index afc25ee9964..36af01f029e 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -50,6 +50,20 @@ int acpi_save_state_mem(void) header->video_mode = saved_video_mode; + header->wakeup_jmp_seg = acpi_wakeup_address >> 4; + /* GDT[0]: GDT self-pointer */ + header->wakeup_gdt[0] = + (u64)(sizeof(header->wakeup_gdt) - 1) + + ((u64)(acpi_wakeup_address + + ((char *)&header->wakeup_gdt - (char *)acpi_realmode)) + << 16); + /* GDT[1]: real-mode-like code segment */ + header->wakeup_gdt[1] = (0x009bULL << 40) + + ((u64)acpi_wakeup_address << 16) + 0xffff; + /* GDT[2]: real-mode-like data segment */ + header->wakeup_gdt[2] = (0x0093ULL << 40) + + ((u64)acpi_wakeup_address << 16) + 0xffff; + #ifndef CONFIG_64BIT store_gdt((struct desc_ptr *)&header->pmode_gdt); @@ -111,7 +125,7 @@ void __init acpi_reserve_bootmem(void) return; } - acpi_wakeup_address = acpi_realmode; + acpi_wakeup_address = virt_to_phys((void *)acpi_realmode); } diff --git a/arch/x86/kernel/efi_32.c b/arch/x86/kernel/efi_32.c index 5d23d85624d..4b63c8e1f13 100644 --- a/arch/x86/kernel/efi_32.c +++ b/arch/x86/kernel/efi_32.c @@ -49,13 +49,13 @@ void efi_call_phys_prelog(void) local_irq_save(efi_rt_eflags); /* - * If I don't have PSE, I should just duplicate two entries in page - * directory. If I have PSE, I just need to duplicate one entry in + * If I don't have PAE, I should just duplicate two entries in page + * directory. If I have PAE, I just need to duplicate one entry in * page directory. */ cr4 = read_cr4(); - if (cr4 & X86_CR4_PSE) { + if (cr4 & X86_CR4_PAE) { efi_bak_pg_dir_pointer[0].pgd = swapper_pg_dir[pgd_index(0)].pgd; swapper_pg_dir[0].pgd = @@ -93,7 +93,7 @@ void efi_call_phys_epilog(void) cr4 = read_cr4(); - if (cr4 & X86_CR4_PSE) { + if (cr4 & X86_CR4_PAE) { swapper_pg_dir[pgd_index(0)].pgd = efi_bak_pg_dir_pointer[0].pgd; } else { diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 10a1955bb1d..b817974ef94 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -128,7 +128,7 @@ ident_complete: /* Fixup phys_base */ addq %rbp, phys_base(%rip) -#ifdef CONFIG_SMP +#ifdef CONFIG_X86_TRAMPOLINE addq %rbp, trampoline_level4_pgt + 0(%rip) addq %rbp, trampoline_level4_pgt + (511*8)(%rip) #endif diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index f6d20be7a8f..819dad973b1 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -506,7 +506,7 @@ early_param("memtest", parse_memtest); static void __init early_memtest(unsigned long start, unsigned long end) { - unsigned long t_start, t_size; + u64 t_start, t_size; unsigned pattern; if (!memtest_pattern) @@ -525,8 +525,9 @@ static void __init early_memtest(unsigned long start, unsigned long end) if (t_start + t_size > end) t_size = end - t_start; - printk(KERN_CONT "\n %016lx - %016lx pattern %d", - t_start, t_start + t_size, pattern); + printk(KERN_CONT "\n %016llx - %016llx pattern %d", + (unsigned long long)t_start, + (unsigned long long)t_start + t_size, pattern); memtest(t_start, t_size, pattern); diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 2b2bb3f9b68..d1b867101e5 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -300,6 +300,29 @@ void __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size) } EXPORT_SYMBOL(ioremap_cache); +static void __iomem *ioremap_default(resource_size_t phys_addr, + unsigned long size) +{ + unsigned long flags; + void *ret; + int err; + + /* + * - WB for WB-able memory and no other conflicting mappings + * - UC_MINUS for non-WB-able memory with no other conflicting mappings + * - Inherit from confliting mappings otherwise + */ + err = reserve_memtype(phys_addr, phys_addr + size, -1, &flags); + if (err < 0) + return NULL; + + ret = (void *) __ioremap_caller(phys_addr, size, flags, + __builtin_return_address(0)); + + free_memtype(phys_addr, phys_addr + size); + return (void __iomem *)ret; +} + /** * iounmap - Free a IO remapping * @addr: virtual address from ioremap_* @@ -365,7 +388,7 @@ void *xlate_dev_mem_ptr(unsigned long phys) if (page_is_ram(start >> PAGE_SHIFT)) return __va(phys); - addr = (void *)ioremap(start, PAGE_SIZE); + addr = (void *)ioremap_default(start, PAGE_SIZE); if (addr) addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK)); diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 940185ecaed..6e64aaf00d1 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -328,18 +328,18 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { #endif { .callback = set_bf_sort, - .ident = "HP ProLiant DL360", + .ident = "HP ProLiant DL385 G2", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL360"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385 G2"), }, }, { .callback = set_bf_sort, - .ident = "HP ProLiant DL380", + .ident = "HP ProLiant DL585 G2", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL380"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"), }, }, {} diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index df40bf74ea7..4e527e7893a 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -185,7 +185,7 @@ static pteval_t pte_mfn_to_pfn(pteval_t val) if (val & _PAGE_PRESENT) { unsigned long mfn = (val & PTE_MASK) >> PAGE_SHIFT; pteval_t flags = val & ~PTE_MASK; - val = (mfn_to_pfn(mfn) << PAGE_SHIFT) | flags; + val = ((pteval_t)mfn_to_pfn(mfn) << PAGE_SHIFT) | flags; } return val; @@ -196,7 +196,7 @@ static pteval_t pte_pfn_to_mfn(pteval_t val) if (val & _PAGE_PRESENT) { unsigned long pfn = (val & PTE_MASK) >> PAGE_SHIFT; pteval_t flags = val & ~PTE_MASK; - val = (pfn_to_mfn(pfn) << PAGE_SHIFT) | flags; + val = ((pteval_t)pfn_to_mfn(pfn) << PAGE_SHIFT) | flags; } return val; diff --git a/crypto/chainiv.c b/crypto/chainiv.c index 6da3f577e4d..9affadee328 100644 --- a/crypto/chainiv.c +++ b/crypto/chainiv.c @@ -117,6 +117,7 @@ static int chainiv_init(struct crypto_tfm *tfm) static int async_chainiv_schedule_work(struct async_chainiv_ctx *ctx) { int queued; + int err = ctx->err; if (!ctx->queue.qlen) { smp_mb__before_clear_bit(); @@ -131,7 +132,7 @@ static int async_chainiv_schedule_work(struct async_chainiv_ctx *ctx) BUG_ON(!queued); out: - return ctx->err; + return err; } static int async_chainiv_postpone_request(struct skcipher_givcrypt_request *req) @@ -227,6 +228,7 @@ static void async_chainiv_do_postponed(struct work_struct *work) postponed); struct skcipher_givcrypt_request *req; struct ablkcipher_request *subreq; + int err; /* Only handle one request at a time to avoid hogging keventd. */ spin_lock_bh(&ctx->lock); @@ -241,7 +243,11 @@ static void async_chainiv_do_postponed(struct work_struct *work) subreq = skcipher_givcrypt_reqctx(req); subreq->base.flags |= CRYPTO_TFM_REQ_MAY_SLEEP; - async_chainiv_givencrypt_tail(req); + err = async_chainiv_givencrypt_tail(req); + + local_bh_disable(); + skcipher_givcrypt_complete(req, err); + local_bh_enable(); } static int async_chainiv_init(struct crypto_tfm *tfm) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 6beabc5abd0..e47f6e02133 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -586,12 +586,6 @@ static void test_cipher(char *algo, int enc, j = 0; for (i = 0; i < tcount; i++) { - data = kzalloc(template[i].ilen, GFP_KERNEL); - if (!data) - continue; - - memcpy(data, template[i].input, template[i].ilen); - if (template[i].iv) memcpy(iv, template[i].iv, MAX_IVLEN); else @@ -613,10 +607,8 @@ static void test_cipher(char *algo, int enc, printk("setkey() failed flags=%x\n", crypto_ablkcipher_get_flags(tfm)); - if (!template[i].fail) { - kfree(data); + if (!template[i].fail) goto out; - } } temp = 0; diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index c3b0cd88d09..495c63a3e0a 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -36,9 +36,8 @@ static int acpi_sleep_prepare(u32 acpi_state) if (!acpi_wakeup_address) { return -EFAULT; } - acpi_set_firmware_waking_vector((acpi_physical_address) - virt_to_phys((void *) - acpi_wakeup_address)); + acpi_set_firmware_waking_vector( + (acpi_physical_address)acpi_wakeup_address); } ACPI_FLUSH_CPU_CACHE(); diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 224c57c0338..4ebbba2b6b1 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c @@ -315,8 +315,11 @@ acpi_system_write_alarm(struct file *file, cmos_bcd_write(day, acpi_gbl_FADT.day_alarm, rtc_control); if (acpi_gbl_FADT.month_alarm) cmos_bcd_write(mo, acpi_gbl_FADT.month_alarm, rtc_control); - if (acpi_gbl_FADT.century) + if (acpi_gbl_FADT.century) { + if (adjust) + yr += cmos_bcd_read(acpi_gbl_FADT.century, rtc_control) * 100; cmos_bcd_write(yr / 100, acpi_gbl_FADT.century, rtc_control); + } /* enable the rtc alarm interrupt */ rtc_control |= RTC_AIE; CMOS_WRITE(rtc_control, RTC_CONTROL); diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 6a4a2a25d97..5e6468a7ca4 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1777,7 +1777,7 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance) struct ahci_host_priv *hpriv; unsigned int i, handled = 0; void __iomem *mmio; - u32 irq_stat, irq_ack = 0; + u32 irq_stat, irq_masked; VPRINTK("ENTER\n"); @@ -1786,16 +1786,17 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance) /* sigh. 0xffffffff is a valid return from h/w */ irq_stat = readl(mmio + HOST_IRQ_STAT); - irq_stat &= hpriv->port_map; if (!irq_stat) return IRQ_NONE; + irq_masked = irq_stat & hpriv->port_map; + spin_lock(&host->lock); for (i = 0; i < host->n_ports; i++) { struct ata_port *ap; - if (!(irq_stat & (1 << i))) + if (!(irq_masked & (1 << i))) continue; ap = host->ports[i]; @@ -1809,14 +1810,20 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance) "interrupt on disabled port %u\n", i); } - irq_ack |= (1 << i); - } - - if (irq_ack) { - writel(irq_ack, mmio + HOST_IRQ_STAT); handled = 1; } + /* HOST_IRQ_STAT behaves as level triggered latch meaning that + * it should be cleared after all the port events are cleared; + * otherwise, it will raise a spurious interrupt after each + * valid one. Please read section 10.6.2 of ahci 1.1 for more + * information. + * + * Also, use the unmasked value to clear interrupt as spurious + * pending event on a dummy port might cause screaming IRQ. + */ + writel(irq_stat, mmio + HOST_IRQ_STAT); + spin_unlock(&host->lock); VPRINTK("EXIT\n"); diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 215d18672a5..c0908c22548 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -1094,6 +1094,7 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, u8 status, int in_wq) { + struct ata_eh_info *ehi = &ap->link.eh_info; unsigned long flags = 0; int poll_next; @@ -1125,9 +1126,12 @@ fsm_start: if (likely(status & (ATA_ERR | ATA_DF))) /* device stops HSM for abort/error */ qc->err_mask |= AC_ERR_DEV; - else + else { /* HSM violation. Let EH handle this */ + ata_ehi_push_desc(ehi, + "ST_FIRST: !(DRQ|ERR|DF)"); qc->err_mask |= AC_ERR_HSM; + } ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; @@ -1146,9 +1150,9 @@ fsm_start: * the CDB. */ if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) { - ata_port_printk(ap, KERN_WARNING, - "DRQ=1 with device error, " - "dev_stat 0x%X\n", status); + ata_ehi_push_desc(ehi, "ST_FIRST: " + "DRQ=1 with device error, " + "dev_stat 0x%X", status); qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; @@ -1205,9 +1209,9 @@ fsm_start: * let the EH abort the command or reset the device. */ if (unlikely(status & (ATA_ERR | ATA_DF))) { - ata_port_printk(ap, KERN_WARNING, "DRQ=1 with " - "device error, dev_stat 0x%X\n", - status); + ata_ehi_push_desc(ehi, "ST-ATAPI: " + "DRQ=1 with device error, " + "dev_stat 0x%X", status); qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; @@ -1226,13 +1230,17 @@ fsm_start: if (likely(status & (ATA_ERR | ATA_DF))) /* device stops HSM for abort/error */ qc->err_mask |= AC_ERR_DEV; - else + else { /* HSM violation. Let EH handle this. * Phantom devices also trigger this * condition. Mark hint. */ + ata_ehi_push_desc(ehi, "ST-ATA: " + "DRQ=1 with device error, " + "dev_stat 0x%X", status); qc->err_mask |= AC_ERR_HSM | AC_ERR_NODEV_HINT; + } ap->hsm_task_state = HSM_ST_ERR; goto fsm_start; @@ -1257,8 +1265,12 @@ fsm_start: status = ata_wait_idle(ap); } - if (status & (ATA_BUSY | ATA_DRQ)) + if (status & (ATA_BUSY | ATA_DRQ)) { + ata_ehi_push_desc(ehi, "ST-ATA: " + "BUSY|DRQ persists on ERR|DF, " + "dev_stat 0x%X", status); qc->err_mask |= AC_ERR_HSM; + } /* ata_pio_sectors() might change the * state to HSM_ST_LAST. so, the state diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 28092bc5014..ad169ffbc4c 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1607,7 +1607,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) * Much of the time, this could just work regardless. * So for now, just log the incident, and allow the attempt. */ - if (limit_warnings && (qc->nbytes / qc->sect_size) > 1) { + if (limit_warnings > 0 && (qc->nbytes / qc->sect_size) > 1) { --limit_warnings; ata_link_printk(qc->dev->link, KERN_WARNING, DRV_NAME ": attempting PIO w/multiple DRQ: " diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 8ee6b5b4ede..84ffcc26a74 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -370,6 +370,7 @@ static const struct pci_device_id sil24_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x3124), BID_SIL3124 }, { PCI_VDEVICE(CMD, 0x3132), BID_SIL3132 }, { PCI_VDEVICE(CMD, 0x0242), BID_SIL3132 }, + { PCI_VDEVICE(CMD, 0x0244), BID_SIL3132 }, { PCI_VDEVICE(CMD, 0x3131), BID_SIL3131 }, { PCI_VDEVICE(CMD, 0x3531), BID_SIL3131 }, diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c index f277cea904c..db529b84994 100644 --- a/drivers/ata/sata_uli.c +++ b/drivers/ata/sata_uli.c @@ -83,6 +83,7 @@ static struct ata_port_operations uli_ops = { .inherits = &ata_bmdma_port_ops, .scr_read = uli_scr_read, .scr_write = uli_scr_write, + .hardreset = ATA_OP_NULL, }; static const struct ata_port_info uli_port_info = { diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig index 043353bd060..14b9d5f4c20 100644 --- a/drivers/auxdisplay/Kconfig +++ b/drivers/auxdisplay/Kconfig @@ -64,7 +64,7 @@ config KS0108_DELAY Amount of time the ks0108 should wait between each control write to the parallel port. - If your driver seems to miss random writings, increment this. + If your LCD seems to miss random writings, increment this. If you don't know what I'm talking about, ignore it. diff --git a/drivers/auxdisplay/cfag12864b.c b/drivers/auxdisplay/cfag12864b.c index 80bb0610538..683509f013a 100644 --- a/drivers/auxdisplay/cfag12864b.c +++ b/drivers/auxdisplay/cfag12864b.c @@ -5,7 +5,7 @@ * License: GPLv2 * Depends: ks0108 * - * Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com> + * Author: Copyright (C) Miguel Ojeda Sandonis * Date: 2006-10-31 * * This program is free software; you can redistribute it and/or modify @@ -398,5 +398,5 @@ module_init(cfag12864b_init); module_exit(cfag12864b_exit); MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Miguel Ojeda Sandonis <maxextreme@gmail.com>"); +MODULE_AUTHOR("Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>"); MODULE_DESCRIPTION("cfag12864b LCD driver"); diff --git a/drivers/auxdisplay/cfag12864bfb.c b/drivers/auxdisplay/cfag12864bfb.c index 307c190699e..fe3a865be4e 100644 --- a/drivers/auxdisplay/cfag12864bfb.c +++ b/drivers/auxdisplay/cfag12864bfb.c @@ -5,7 +5,7 @@ * License: GPLv2 * Depends: cfag12864b * - * Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com> + * Author: Copyright (C) Miguel Ojeda Sandonis * Date: 2006-10-31 * * This program is free software; you can redistribute it and/or modify @@ -186,5 +186,5 @@ module_init(cfag12864bfb_init); module_exit(cfag12864bfb_exit); MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Miguel Ojeda Sandonis <maxextreme@gmail.com>"); +MODULE_AUTHOR("Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>"); MODULE_DESCRIPTION("cfag12864b LCD framebuffer driver"); diff --git a/drivers/auxdisplay/ks0108.c b/drivers/auxdisplay/ks0108.c index e6c3646ef18..5b93852392b 100644 --- a/drivers/auxdisplay/ks0108.c +++ b/drivers/auxdisplay/ks0108.c @@ -5,7 +5,7 @@ * License: GPLv2 * Depends: parport * - * Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com> + * Author: Copyright (C) Miguel Ojeda Sandonis * Date: 2006-10-31 * * This program is free software; you can redistribute it and/or modify @@ -173,6 +173,6 @@ module_init(ks0108_init); module_exit(ks0108_exit); MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Miguel Ojeda Sandonis <maxextreme@gmail.com>"); +MODULE_AUTHOR("Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>"); MODULE_DESCRIPTION("ks0108 LCD Controller driver"); diff --git a/drivers/base/node.c b/drivers/base/node.c index 39f3d1b3a21..0f867a08333 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -84,8 +84,8 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) nid, K(i.totalram), nid, K(i.freeram), nid, K(i.totalram - i.freeram), - nid, node_page_state(nid, NR_ACTIVE), - nid, node_page_state(nid, NR_INACTIVE), + nid, K(node_page_state(nid, NR_ACTIVE)), + nid, K(node_page_state(nid, NR_INACTIVE)), #ifdef CONFIG_HIGHMEM nid, K(i.totalhigh), nid, K(i.freehigh), diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 5f1e1cc6165..d81632cd7d0 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -106,35 +106,34 @@ MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); /* board_id = Subsystem Device ID & Vendor ID * product = Marketing Name for the board * access = Address of the struct of function pointers - * nr_cmds = Number of commands supported by controller */ static struct board_type products[] = { - {0x40700E11, "Smart Array 5300", &SA5_access, 512}, - {0x40800E11, "Smart Array 5i", &SA5B_access, 512}, - {0x40820E11, "Smart Array 532", &SA5B_access, 512}, - {0x40830E11, "Smart Array 5312", &SA5B_access, 512}, - {0x409A0E11, "Smart Array 641", &SA5_access, 512}, - {0x409B0E11, "Smart Array 642", &SA5_access, 512}, - {0x409C0E11, "Smart Array 6400", &SA5_access, 512}, - {0x409D0E11, "Smart Array 6400 EM", &SA5_access, 512}, - {0x40910E11, "Smart Array 6i", &SA5_access, 512}, - {0x3225103C, "Smart Array P600", &SA5_access, 512}, - {0x3223103C, "Smart Array P800", &SA5_access, 512}, - {0x3234103C, "Smart Array P400", &SA5_access, 512}, - {0x3235103C, "Smart Array P400i", &SA5_access, 512}, - {0x3211103C, "Smart Array E200i", &SA5_access, 120}, - {0x3212103C, "Smart Array E200", &SA5_access, 120}, - {0x3213103C, "Smart Array E200i", &SA5_access, 120}, - {0x3214103C, "Smart Array E200i", &SA5_access, 120}, - {0x3215103C, "Smart Array E200i", &SA5_access, 120}, - {0x3237103C, "Smart Array E500", &SA5_access, 512}, - {0x323D103C, "Smart Array P700m", &SA5_access, 512}, - {0x3241103C, "Smart Array P212", &SA5_access, 384}, - {0x3243103C, "Smart Array P410", &SA5_access, 384}, - {0x3245103C, "Smart Array P410i", &SA5_access, 384}, - {0x3247103C, "Smart Array P411", &SA5_access, 384}, - {0x3249103C, "Smart Array P812", &SA5_access, 384}, - {0xFFFF103C, "Unknown Smart Array", &SA5_access, 120}, + {0x40700E11, "Smart Array 5300", &SA5_access}, + {0x40800E11, "Smart Array 5i", &SA5B_access}, + {0x40820E11, "Smart Array 532", &SA5B_access}, + {0x40830E11, "Smart Array 5312", &SA5B_access}, + {0x409A0E11, "Smart Array 641", &SA5_access}, + {0x409B0E11, "Smart Array 642", &SA5_access}, + {0x409C0E11, "Smart Array 6400", &SA5_access}, + {0x409D0E11, "Smart Array 6400 EM", &SA5_access}, + {0x40910E11, "Smart Array 6i", &SA5_access}, + {0x3225103C, "Smart Array P600", &SA5_access}, + {0x3223103C, "Smart Array P800", &SA5_access}, + {0x3234103C, "Smart Array P400", &SA5_access}, + {0x3235103C, "Smart Array P400i", &SA5_access}, + {0x3211103C, "Smart Array E200i", &SA5_access}, + {0x3212103C, "Smart Array E200", &SA5_access}, + {0x3213103C, "Smart Array E200i", &SA5_access}, + {0x3214103C, "Smart Array E200i", &SA5_access}, + {0x3215103C, "Smart Array E200i", &SA5_access}, + {0x3237103C, "Smart Array E500", &SA5_access}, + {0x323D103C, "Smart Array P700m", &SA5_access}, + {0x3241103C, "Smart Array P212", &SA5_access}, + {0x3243103C, "Smart Array P410", &SA5_access}, + {0x3245103C, "Smart Array P410i", &SA5_access}, + {0x3247103C, "Smart Array P411", &SA5_access}, + {0x3249103C, "Smart Array P812", &SA5_access}, + {0xFFFF103C, "Unknown Smart Array", &SA5_access}, }; /* How long to wait (in milliseconds) for board to go into simple mode */ @@ -3086,11 +3085,20 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) print_cfg_table(c->cfgtable); #endif /* CCISS_DEBUG */ + /* Some controllers support Zero Memory Raid (ZMR). + * When configured in ZMR mode the number of supported + * commands drops to 64. So instead of just setting an + * arbitrary value we make the driver a little smarter. + * We read the config table to tell us how many commands + * are supported on the controller then subtract 4 to + * leave a little room for ioctl calls. + */ + c->max_commands = readl(&(c->cfgtable->CmdsOutMax)); for (i = 0; i < ARRAY_SIZE(products); i++) { if (board_id == products[i].board_id) { c->product_name = products[i].product_name; c->access = *(products[i].access); - c->nr_cmds = products[i].nr_cmds; + c->nr_cmds = c->max_commands - 4; break; } } @@ -3110,7 +3118,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) if (subsystem_vendor_id == PCI_VENDOR_ID_HP) { c->product_name = products[i-1].product_name; c->access = *(products[i-1].access); - c->nr_cmds = products[i-1].nr_cmds; + c->nr_cmds = c->max_commands - 4; printk(KERN_WARNING "cciss: This is an unknown " "Smart Array controller.\n" "cciss: Please update to the latest driver " @@ -3546,6 +3554,10 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, for (j = 0; j <= hba[i]->highest_lun; j++) add_disk(hba[i]->gendisk[j]); + /* we must register the controller even if no disks exist */ + if (hba[i]->highest_lun == -1) + add_disk(hba[i]->gendisk[0]); + return 1; clean4: diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index bbd28342e77..008c38ba774 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -28,12 +28,18 @@ config DEBUG_GPIO comment "I2C GPIO expanders:" config GPIO_PCA953X - tristate "PCA953x I/O ports" + tristate "PCA953x, PCA955x, and MAX7310 I/O ports" depends on I2C help - Say yes here to support the PCA9534 (8-bit), PCA9535 (16-bit), - PCA9536 (4-bit), PCA9537 (4-bit), PCA9538 (8-bit), and PCA9539 - (16-bit) I/O ports. These parts are made by NXP and TI. + Say yes here to provide access to several register-oriented + SMBus I/O expanders, made mostly by NXP or TI. Compatible + models include: + + 4 bits: pca9536, pca9537 + + 8 bits: max7310, pca9534, pca9538, pca9554, pca9557 + + 16 bits: pca9535, pca9539, pca9555 This driver can also be built as a module. If so, the module will be called pca953x. diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index 7e40e8a55ed..a380730b61a 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c @@ -33,7 +33,7 @@ static const struct i2c_device_id pca953x_id[] = { { "pca9554", 8, }, { "pca9555", 16, }, { "pca9557", 8, }, - /* REVISIT several pca955x parts should work here too */ + { "max7310", 8, }, { } }; MODULE_DEVICE_TABLE(i2c, pca953x_id); diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index 26df06f840e..50f22690d61 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c @@ -516,17 +516,23 @@ static struct dmi_system_id __initdata hdaps_whitelist[] = { HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R51"), HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R52"), HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61i"), + HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61"), HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T41p"), HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T41"), HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p"), HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"), HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"), HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60"), + HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61p"), HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61"), HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X40"), HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X41"), HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X60"), + HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61s"), + HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61"), HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad Z60m"), + HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61m"), + HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61p"), { .ident = NULL } }; diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c index cc24803fadf..2f2b4f4cf22 100644 --- a/drivers/ide/arm/palm_bk3710.c +++ b/drivers/ide/arm/palm_bk3710.c @@ -76,7 +76,7 @@ struct palm_bk3710_udmatiming { #include "../ide-timing.h" -static long ide_palm_clk; +static unsigned ideclk_period; /* in nanoseconds */ static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = { {160, 240}, /* UDMA Mode 0 */ @@ -86,8 +86,6 @@ static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = { {85, 60}, /* UDMA Mode 4 */ }; -static struct clk *ideclkp; - static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev, unsigned int mode) { @@ -97,10 +95,10 @@ static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev, /* DMA Data Setup */ t0 = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].cycletime, - ide_palm_clk) - 1; - tenv = DIV_ROUND_UP(20, ide_palm_clk) - 1; + ideclk_period) - 1; + tenv = DIV_ROUND_UP(20, ideclk_period) - 1; trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime, - ide_palm_clk) - 1; + ideclk_period) - 1; /* udmatim Register */ val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0); @@ -141,8 +139,8 @@ static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev, cycletime = max_t(int, t->cycle, min_cycle); /* DMA Data Setup */ - t0 = DIV_ROUND_UP(cycletime, ide_palm_clk); - td = DIV_ROUND_UP(t->active, ide_palm_clk); + t0 = DIV_ROUND_UP(cycletime, ideclk_period); + td = DIV_ROUND_UP(t->active, ideclk_period); tkw = t0 - td - 1; td -= 1; @@ -168,9 +166,9 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate, struct ide_timing *t; /* PIO Data Setup */ - t0 = DIV_ROUND_UP(cycletime, ide_palm_clk); + t0 = DIV_ROUND_UP(cycletime, ideclk_period); t2 = DIV_ROUND_UP(ide_timing_find_mode(XFER_PIO_0 + mode)->active, - ide_palm_clk); + ideclk_period); t2i = t0 - t2 - 1; t2 -= 1; @@ -192,8 +190,8 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate, /* TASKFILE Setup */ t = ide_timing_find_mode(XFER_PIO_0 + mode); - t0 = DIV_ROUND_UP(t->cyc8b, ide_palm_clk); - t2 = DIV_ROUND_UP(t->act8b, ide_palm_clk); + t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period); + t2 = DIV_ROUND_UP(t->act8b, ideclk_period); t2i = t0 - t2 - 1; t2 -= 1; @@ -350,22 +348,22 @@ static const struct ide_port_info __devinitdata palm_bk3710_port_info = { static int __devinit palm_bk3710_probe(struct platform_device *pdev) { - struct clk *clkp; + struct clk *clk; struct resource *mem, *irq; ide_hwif_t *hwif; - unsigned long base; + unsigned long base, rate; int i; hw_regs_t hw; u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; - clkp = clk_get(NULL, "IDECLK"); - if (IS_ERR(clkp)) + clk = clk_get(NULL, "IDECLK"); + if (IS_ERR(clk)) return -ENODEV; - ideclkp = clkp; - clk_enable(ideclkp); - ide_palm_clk = clk_get_rate(ideclkp)/100000; - ide_palm_clk = (10000/ide_palm_clk) + 1; + clk_enable(clk); + rate = clk_get_rate(clk); + ideclk_period = 1000000000UL / rate; + /* Register the IDE interface with Linux ATA Interface */ memset(&hw, 0, sizeof(hw)); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 380fa0c8cc8..26e68b65b7c 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -646,8 +646,6 @@ static int ide_register_port(ide_hwif_t *hwif) goto out; } - get_device(&hwif->gendev); - hwif->portdev = device_create_drvdata(ide_port_class, &hwif->gendev, MKDEV(0, 0), hwif, hwif->name); if (IS_ERR(hwif->portdev)) { @@ -1220,16 +1218,12 @@ static void drive_release_dev (struct device *dev) complete(&drive->gendev_rel_comp); } -#ifndef ide_default_irq -#define ide_default_irq(irq) 0 -#endif - static int hwif_init(ide_hwif_t *hwif) { int old_irq; if (!hwif->irq) { - hwif->irq = ide_default_irq(hwif->io_ports.data_addr); + hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); if (!hwif->irq) { printk("%s: DISABLED, NO IRQ\n", hwif->name); return 0; @@ -1259,7 +1253,7 @@ static int hwif_init(ide_hwif_t *hwif) * It failed to initialise. Find the default IRQ for * this port and try that. */ - hwif->irq = ide_default_irq(hwif->io_ports.data_addr); + hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); if (!hwif->irq) { printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, old_irq); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index c758dcb13b1..300431d080a 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -315,13 +315,14 @@ void ide_unregister(ide_hwif_t *hwif) BUG_ON(in_interrupt()); BUG_ON(irqs_disabled()); + mutex_lock(&ide_cfg_mtx); - spin_lock_irq(&ide_lock); - if (!hwif->present) - goto abort; - __ide_port_unregister_devices(hwif); - hwif->present = 0; + spin_lock_irq(&ide_lock); + if (hwif->present) { + __ide_port_unregister_devices(hwif); + hwif->present = 0; + } spin_unlock_irq(&ide_lock); ide_proc_unregister_port(hwif); @@ -351,16 +352,15 @@ void ide_unregister(ide_hwif_t *hwif) blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS); kfree(hwif->sg_table); unregister_blkdev(hwif->major, hwif->name); - spin_lock_irq(&ide_lock); if (hwif->dma_base) ide_release_dma_engine(hwif); + spin_lock_irq(&ide_lock); /* restore hwif data to pristine status */ ide_init_port_data(hwif, hwif->index); - -abort: spin_unlock_irq(&ide_lock); + mutex_unlock(&ide_cfg_mtx); } @@ -1094,13 +1094,6 @@ struct bus_type ide_bus_type = { EXPORT_SYMBOL_GPL(ide_bus_type); -static void ide_port_class_release(struct device *portdev) -{ - ide_hwif_t *hwif = dev_get_drvdata(portdev); - - put_device(&hwif->gendev); -} - int ide_vlb_clk; EXPORT_SYMBOL_GPL(ide_vlb_clk); @@ -1305,7 +1298,6 @@ static int __init ide_init(void) ret = PTR_ERR(ide_port_class); goto out_port_class; } - ide_port_class->dev_release = ide_port_class_release; init_ide_data(); diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c index 9053c8771e6..2b71bdf74e7 100644 --- a/drivers/ide/pci/it8213.c +++ b/drivers/ide/pci/it8213.c @@ -184,8 +184,7 @@ static const struct ide_port_info it8213_chipsets[] __devinitdata = { static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_setup_pci_device(dev, &it8213_chipsets[id->driver_data]); - return 0; + return ide_setup_pci_device(dev, &it8213_chipsets[id->driver_data]); } static const struct pci_device_id it8213_pci_tbl[] = { diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c index fec4955f449..a7a41bb8277 100644 --- a/drivers/ide/pci/ns87415.c +++ b/drivers/ide/pci/ns87415.c @@ -225,10 +225,6 @@ static int ns87415_dma_setup(ide_drive_t *drive) return 1; } -#ifndef ide_default_irq -#define ide_default_irq(irq) 0 -#endif - static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); @@ -288,7 +284,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) } if (!using_inta) - hwif->irq = ide_default_irq(hwif->io_ports.data_addr); + hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); else if (!hwif->irq && hwif->mate && hwif->mate->irq) hwif->irq = hwif->mate->irq; /* share IRQ with mate */ diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c index 8934178a23e..95f82cfb6c5 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c @@ -1096,7 +1096,9 @@ static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, ch struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev; PDBG("%s dev 0x%p\n", __func__, dev); + rtnl_lock(); lldev->ethtool_ops->get_drvinfo(lldev, &info); + rtnl_unlock(); return sprintf(buf, "%s\n", info.fw_version); } @@ -1109,7 +1111,9 @@ static ssize_t show_hca(struct device *dev, struct device_attribute *attr, struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev; PDBG("%s dev 0x%p\n", __func__, dev); + rtnl_lock(); lldev->ethtool_ops->get_drvinfo(lldev, &info); + rtnl_unlock(); return sprintf(buf, "%s\n", info.driver); } diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 54c8ee28fcc..3b27df52456 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2017,12 +2017,7 @@ static int __handle_issuing_new_read_requests5(struct stripe_head *sh, */ s->uptodate++; return 0; /* uptodate + compute == disks */ - } else if ((s->uptodate < disks - 1) && - test_bit(R5_Insync, &dev->flags)) { - /* Note: we hold off compute operations while checks are - * in flight, but we still prefer 'compute' over 'read' - * hence we only read if (uptodate < * disks-1) - */ + } else if (test_bit(R5_Insync, &dev->flags)) { set_bit(R5_LOCKED, &dev->flags); set_bit(R5_Wantread, &dev->flags); if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending)) diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 65210fca37e..d89475d3698 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -114,6 +114,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) unsigned int nob = data->blocks; unsigned long long clks; unsigned int timeout; + bool dalgn = 0; u32 dcmd; int i; @@ -152,6 +153,9 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) host->sg_cpu[i].dcmd = dcmd | length; if (length & 31 && !(data->flags & MMC_DATA_READ)) host->sg_cpu[i].dcmd |= DCMD_ENDIRQEN; + /* Not aligned to 8-byte boundary? */ + if (sg_dma_address(&data->sg[i]) & 0x7) + dalgn = 1; if (data->flags & MMC_DATA_READ) { host->sg_cpu[i].dsadr = host->res->start + MMC_RXFIFO; host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]); @@ -165,6 +169,15 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) host->sg_cpu[host->dma_len - 1].ddadr = DDADR_STOP; wmb(); + /* + * The PXA27x DMA controller encounters overhead when working with + * unaligned (to 8-byte boundaries) data, so switch on byte alignment + * mode only if we have unaligned data. + */ + if (dalgn) + DALGN |= (1 << host->dma); + else + DALGN &= (1 << host->dma); DDADR(host->dma) = host->sg_dma; DCSR(host->dma) = DCSR_RUN; } diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 07c2048b230..b413aa6c246 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -55,6 +55,10 @@ static unsigned int debug_quirks = 0; #define SDHCI_QUIRK_32BIT_DMA_SIZE (1<<7) /* Controller needs to be reset after each request to stay stable */ #define SDHCI_QUIRK_RESET_AFTER_REQUEST (1<<8) +/* Controller needs voltage and power writes to happen separately */ +#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<9) +/* Controller has an off-by-one issue with timeout value */ +#define SDHCI_QUIRK_INCR_TIMEOUT_CONTROL (1<<10) static const struct pci_device_id pci_ids[] __devinitdata = { { @@ -115,7 +119,8 @@ static const struct pci_device_id pci_ids[] __devinitdata = { .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | - SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS, + SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS | + SDHCI_QUIRK_BROKEN_DMA, }, { @@ -124,7 +129,17 @@ static const struct pci_device_id pci_ids[] __devinitdata = { .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | - SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS, + SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS | + SDHCI_QUIRK_BROKEN_DMA, + }, + + { + .vendor = PCI_VENDOR_ID_MARVELL, + .device = PCI_DEVICE_ID_MARVELL_CAFE_SD, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | + SDHCI_QUIRK_INCR_TIMEOUT_CONTROL, }, { @@ -469,6 +484,13 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) break; } + /* + * Compensate for an off-by-one error in the CaFe hardware; otherwise, + * a too-small count gives us interrupt timeouts. + */ + if ((host->chip->quirks & SDHCI_QUIRK_INCR_TIMEOUT_CONTROL)) + count++; + if (count >= 0xF) { printk(KERN_WARNING "%s: Too large timeout requested!\n", mmc_hostname(host->mmc)); @@ -774,6 +796,14 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) BUG(); } + /* + * At least the CaFe chip gets confused if we set the voltage + * and set turn on power at the same time, so set the voltage first. + */ + if ((host->chip->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)) + writeb(pwr & ~SDHCI_POWER_ON, + host->ioaddr + SDHCI_POWER_CONTROL); + writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL); out: diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index a3497dc6ebc..338a3f94b4d 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1727,6 +1727,7 @@ static void __init quirk_disable_all_msi(struct pci_dev *dev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_disable_all_msi); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_all_msi); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_all_msi); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3336, quirk_disable_all_msi); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi); /* Disable MSI on chipsets that are known to not support it */ diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 7e3ad4f3b34..58b7336640f 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -126,12 +126,25 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) int err; struct rtc_time before, now; int first_time = 1; + unsigned long t_now, t_alm; + enum { none, day, month, year } missing = none; + unsigned days; - /* The lower level RTC driver may not be capable of filling - * in all fields of the rtc_time struct (eg. rtc-cmos), - * and so might instead return -1 in some fields. - * We deal with that here by grabbing a current RTC timestamp - * and using values from that for any missing (-1) values. + /* The lower level RTC driver may return -1 in some fields, + * creating invalid alarm->time values, for reasons like: + * + * - The hardware may not be capable of filling them in; + * many alarms match only on time-of-day fields, not + * day/month/year calendar data. + * + * - Some hardware uses illegal values as "wildcard" match + * values, which non-Linux firmware (like a BIOS) may try + * to set up as e.g. "alarm 15 minutes after each hour". + * Linux uses only oneshot alarms. + * + * When we see that here, we deal with it by using values from + * a current RTC timestamp for any missing (-1) values. The + * RTC driver prevents "periodic alarm" modes. * * But this can be racey, because some fields of the RTC timestamp * may have wrapped in the interval since we read the RTC alarm, @@ -174,6 +187,10 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) if (!alarm->enabled) return 0; + /* full-function RTCs won't have such missing fields */ + if (rtc_valid_tm(&alarm->time) == 0) + return 0; + /* get the "after" timestamp, to detect wrapped fields */ err = rtc_read_time(rtc, &now); if (err < 0) @@ -183,22 +200,85 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) } while ( before.tm_min != now.tm_min || before.tm_hour != now.tm_hour || before.tm_mon != now.tm_mon - || before.tm_year != now.tm_year - || before.tm_isdst != now.tm_isdst); + || before.tm_year != now.tm_year); - /* Fill in any missing alarm fields using the timestamp */ + /* Fill in the missing alarm fields using the timestamp; we + * know there's at least one since alarm->time is invalid. + */ if (alarm->time.tm_sec == -1) alarm->time.tm_sec = now.tm_sec; if (alarm->time.tm_min == -1) alarm->time.tm_min = now.tm_min; if (alarm->time.tm_hour == -1) alarm->time.tm_hour = now.tm_hour; - if (alarm->time.tm_mday == -1) + + /* For simplicity, only support date rollover for now */ + if (alarm->time.tm_mday == -1) { alarm->time.tm_mday = now.tm_mday; - if (alarm->time.tm_mon == -1) + missing = day; + } + if (alarm->time.tm_mon == -1) { alarm->time.tm_mon = now.tm_mon; - if (alarm->time.tm_year == -1) + if (missing == none) + missing = month; + } + if (alarm->time.tm_year == -1) { alarm->time.tm_year = now.tm_year; + if (missing == none) + missing = year; + } + + /* with luck, no rollover is needed */ + rtc_tm_to_time(&now, &t_now); + rtc_tm_to_time(&alarm->time, &t_alm); + if (t_now < t_alm) + goto done; + + switch (missing) { + + /* 24 hour rollover ... if it's now 10am Monday, an alarm that + * that will trigger at 5am will do so at 5am Tuesday, which + * could also be in the next month or year. This is a common + * case, especially for PCs. + */ + case day: + dev_dbg(&rtc->dev, "alarm rollover: %s\n", "day"); + t_alm += 24 * 60 * 60; + rtc_time_to_tm(t_alm, &alarm->time); + break; + + /* Month rollover ... if it's the 31th, an alarm on the 3rd will + * be next month. An alarm matching on the 30th, 29th, or 28th + * may end up in the month after that! Many newer PCs support + * this type of alarm. + */ + case month: + dev_dbg(&rtc->dev, "alarm rollover: %s\n", "month"); + do { + if (alarm->time.tm_mon < 11) + alarm->time.tm_mon++; + else { + alarm->time.tm_mon = 0; + alarm->time.tm_year++; + } + days = rtc_month_days(alarm->time.tm_mon, + alarm->time.tm_year); + } while (days < alarm->time.tm_mday); + break; + + /* Year rollover ... easy except for leap years! */ + case year: + dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year"); + do { + alarm->time.tm_year++; + } while (!rtc_valid_tm(&alarm->time)); + break; + + default: + dev_warn(&rtc->dev, "alarm rollover not handled\n"); + } + +done: return 0; } EXPORT_SYMBOL_GPL(rtc_read_alarm); diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index eaf55945f21..7dcfba1bbfe 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c @@ -71,6 +71,7 @@ #define X1205_SR_RTCF 0x01 /* Clock failure */ #define X1205_SR_WEL 0x02 /* Write Enable Latch */ #define X1205_SR_RWEL 0x04 /* Register Write Enable */ +#define X1205_SR_AL0 0x20 /* Alarm 0 match */ #define X1205_DTR_DTR0 0x01 #define X1205_DTR_DTR1 0x02 @@ -78,6 +79,8 @@ #define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */ +#define X1205_INT_AL0E 0x20 /* Alarm 0 enable */ + static struct i2c_driver x1205_driver; /* @@ -89,8 +92,8 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, unsigned char reg_base) { unsigned char dt_addr[2] = { 0, reg_base }; - unsigned char buf[8]; + int i; struct i2c_msg msgs[] = { { client->addr, 0, 2, dt_addr }, /* setup read ptr */ @@ -98,7 +101,7 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, }; /* read date registers */ - if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { + if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) { dev_err(&client->dev, "%s: read error\n", __func__); return -EIO; } @@ -110,6 +113,11 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); + /* Mask out the enable bits if these are alarm registers */ + if (reg_base < X1205_CCR_BASE) + for (i = 0; i <= 4; i++) + buf[i] &= 0x7F; + tm->tm_sec = BCD2BIN(buf[CCR_SEC]); tm->tm_min = BCD2BIN(buf[CCR_MIN]); tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */ @@ -138,7 +146,7 @@ static int x1205_get_status(struct i2c_client *client, unsigned char *sr) }; /* read status register */ - if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { + if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) { dev_err(&client->dev, "%s: read error\n", __func__); return -EIO; } @@ -147,10 +155,11 @@ static int x1205_get_status(struct i2c_client *client, unsigned char *sr) } static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, - int datetoo, u8 reg_base) + int datetoo, u8 reg_base, unsigned char alm_enable) { - int i, xfer; + int i, xfer, nbytes; unsigned char buf[8]; + unsigned char rdata[10] = { 0, reg_base }; static const unsigned char wel[3] = { 0, X1205_REG_SR, X1205_SR_WEL }; @@ -189,6 +198,11 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100); } + /* If writing alarm registers, set compare bits on registers 0-4 */ + if (reg_base < X1205_CCR_BASE) + for (i = 0; i <= 4; i++) + buf[i] |= 0x80; + /* this sequence is required to unlock the chip */ if ((xfer = i2c_master_send(client, wel, 3)) != 3) { dev_err(&client->dev, "%s: wel - %d\n", __func__, xfer); @@ -200,19 +214,57 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, return -EIO; } + /* write register's data */ - for (i = 0; i < (datetoo ? 8 : 3); i++) { - unsigned char rdata[3] = { 0, reg_base + i, buf[i] }; + if (datetoo) + nbytes = 8; + else + nbytes = 3; + for (i = 0; i < nbytes; i++) + rdata[2+i] = buf[i]; + + xfer = i2c_master_send(client, rdata, nbytes+2); + if (xfer != nbytes+2) { + dev_err(&client->dev, + "%s: result=%d addr=%02x, data=%02x\n", + __func__, + xfer, rdata[1], rdata[2]); + return -EIO; + } + + /* If we wrote to the nonvolatile region, wait 10msec for write cycle*/ + if (reg_base < X1205_CCR_BASE) { + unsigned char al0e[3] = { 0, X1205_REG_INT, 0 }; + + msleep(10); - xfer = i2c_master_send(client, rdata, 3); + /* ...and set or clear the AL0E bit in the INT register */ + + /* Need to set RWEL again as the write has cleared it */ + xfer = i2c_master_send(client, rwel, 3); if (xfer != 3) { dev_err(&client->dev, - "%s: xfer=%d addr=%02x, data=%02x\n", + "%s: aloe rwel - %d\n", __func__, - xfer, rdata[1], rdata[2]); + xfer); + return -EIO; + } + + if (alm_enable) + al0e[2] = X1205_INT_AL0E; + + xfer = i2c_master_send(client, al0e, 3); + if (xfer != 3) { + dev_err(&client->dev, + "%s: al0e - %d\n", + __func__, + xfer); return -EIO; } - }; + + /* and wait 10msec again for this write to complete */ + msleep(10); + } /* disable further writes */ if ((xfer = i2c_master_send(client, diswe, 3)) != 3) { @@ -230,9 +282,9 @@ static int x1205_fix_osc(struct i2c_client *client) tm.tm_hour = tm.tm_min = tm.tm_sec = 0; - if ((err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE)) < 0) - dev_err(&client->dev, - "unable to restart the oscillator\n"); + err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE, 0); + if (err < 0) + dev_err(&client->dev, "unable to restart the oscillator\n"); return err; } @@ -248,7 +300,7 @@ static int x1205_get_dtrim(struct i2c_client *client, int *trim) }; /* read dtr register */ - if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { + if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) { dev_err(&client->dev, "%s: read error\n", __func__); return -EIO; } @@ -280,7 +332,7 @@ static int x1205_get_atrim(struct i2c_client *client, int *trim) }; /* read atr register */ - if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { + if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) { dev_err(&client->dev, "%s: read error\n", __func__); return -EIO; } @@ -403,14 +455,33 @@ static int x1205_validate_client(struct i2c_client *client) static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - return x1205_get_datetime(to_i2c_client(dev), - &alrm->time, X1205_ALM0_BASE); + int err; + unsigned char intreg, status; + static unsigned char int_addr[2] = { 0, X1205_REG_INT }; + struct i2c_client *client = to_i2c_client(dev); + struct i2c_msg msgs[] = { + { client->addr, 0, 2, int_addr }, /* setup read ptr */ + { client->addr, I2C_M_RD, 1, &intreg }, /* read INT register */ + }; + + /* read interrupt register and status register */ + if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) { + dev_err(&client->dev, "%s: read error\n", __func__); + return -EIO; + } + err = x1205_get_status(client, &status); + if (err == 0) { + alrm->pending = (status & X1205_SR_AL0) ? 1 : 0; + alrm->enabled = (intreg & X1205_INT_AL0E) ? 1 : 0; + err = x1205_get_datetime(client, &alrm->time, X1205_ALM0_BASE); + } + return err; } static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { return x1205_set_datetime(to_i2c_client(dev), - &alrm->time, 1, X1205_ALM0_BASE); + &alrm->time, 1, X1205_ALM0_BASE, alrm->enabled); } static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm) @@ -422,7 +493,7 @@ static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm) static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm) { return x1205_set_datetime(to_i2c_client(dev), - tm, 1, X1205_CCR_BASE); + tm, 1, X1205_CCR_BASE, 0); } static int x1205_rtc_proc(struct device *dev, struct seq_file *seq) diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index c9b64e73c98..42d2e108b67 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1991,7 +1991,9 @@ struct uart_match { static int serial_match_port(struct device *dev, void *data) { struct uart_match *match = data; - dev_t devt = MKDEV(match->driver->major, match->driver->minor) + match->port->line; + struct tty_driver *tty_drv = match->driver->tty_driver; + dev_t devt = MKDEV(tty_drv->major, tty_drv->minor_start) + + match->port->line; return dev->devt == devt; /* Actually, only one tty per port */ } diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 799337f7fde..f5b60c70389 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -167,14 +167,14 @@ spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) mutex_lock(&spidev->buf_lock); status = spidev_sync_read(spidev, count); - if (status == 0) { + if (status > 0) { unsigned long missing; - missing = copy_to_user(buf, spidev->buffer, count); - if (count && missing == count) + missing = copy_to_user(buf, spidev->buffer, status); + if (missing == status) status = -EFAULT; else - status = count - missing; + status = status - missing; } mutex_unlock(&spidev->buf_lock); @@ -200,8 +200,6 @@ spidev_write(struct file *filp, const char __user *buf, missing = copy_from_user(spidev->buffer, buf, count); if (missing == 0) { status = spidev_sync_write(spidev, count); - if (status == 0) - status = count; } else status = -EFAULT; mutex_unlock(&spidev->buf_lock); diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 63c34043b4d..c3201affa0b 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1125,9 +1125,6 @@ static void stop_data_traffic(struct acm *acm) for (i = 0; i < acm->rx_buflimit; i++) usb_kill_urb(acm->ru[i].urb); - INIT_LIST_HEAD(&acm->filled_read_bufs); - INIT_LIST_HEAD(&acm->spare_read_bufs); - tasklet_enable(&acm->urb_task); cancel_work_sync(&acm->work); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 09a53e7f332..42a436478b7 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -924,6 +924,15 @@ static int register_root_hub(struct usb_hcd *hcd) return retval; } +void usb_enable_root_hub_irq (struct usb_bus *bus) +{ + struct usb_hcd *hcd; + + hcd = container_of (bus, struct usb_hcd, self); + if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT) + hcd->driver->hub_irq_enable (hcd); +} + /*-------------------------------------------------------------------------*/ @@ -1684,19 +1693,30 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum); irqreturn_t usb_hcd_irq (int irq, void *__hcd) { struct usb_hcd *hcd = __hcd; - int start = hcd->state; + unsigned long flags; + irqreturn_t rc; - if (unlikely(start == HC_STATE_HALT || - !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) - return IRQ_NONE; - if (hcd->driver->irq (hcd) == IRQ_NONE) - return IRQ_NONE; + /* IRQF_DISABLED doesn't work correctly with shared IRQs + * when the first handler doesn't use it. So let's just + * assume it's never used. + */ + local_irq_save(flags); - set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); + if (unlikely(hcd->state == HC_STATE_HALT || + !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { + rc = IRQ_NONE; + } else if (hcd->driver->irq(hcd) == IRQ_NONE) { + rc = IRQ_NONE; + } else { + set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); + + if (unlikely(hcd->state == HC_STATE_HALT)) + usb_hc_died(hcd); + rc = IRQ_HANDLED; + } - if (unlikely(hcd->state == HC_STATE_HALT)) - usb_hc_died (hcd); - return IRQ_HANDLED; + local_irq_restore(flags); + return rc; } /*-------------------------------------------------------------------------*/ @@ -1860,6 +1880,13 @@ int usb_add_hcd(struct usb_hcd *hcd, /* enable irqs just before we start the controller */ if (hcd->driver->irq) { + + /* IRQF_DISABLED doesn't work as advertised when used together + * with IRQF_SHARED. As usb_hcd_irq() will always disable + * interrupts we can remove it here. + */ + irqflags &= ~IRQF_DISABLED; + snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d", hcd->driver->description, hcd->self.busnum); if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags, diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index a0bf5df6cb6..b9de1569b39 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -210,6 +210,8 @@ struct hc_driver { int (*bus_suspend)(struct usb_hcd *); int (*bus_resume)(struct usb_hcd *); int (*start_port_reset)(struct usb_hcd *, unsigned port_num); + void (*hub_irq_enable)(struct usb_hcd *); + /* Needed only if port-change IRQs are level-triggered */ /* force handover of high-speed port to full-speed companion */ void (*relinquish_port)(struct usb_hcd *, int); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 94789be54ca..4cfe32a16c3 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -713,18 +713,11 @@ static void hub_restart(struct usb_hub *hub, int type) } /* Was the power session lost while we were suspended? */ - switch (type) { - case HUB_RESET_RESUME: - portstatus = 0; - portchange = USB_PORT_STAT_C_CONNECTION; - break; + status = hub_port_status(hub, port1, &portstatus, &portchange); - case HUB_RESET: - case HUB_RESUME: - status = hub_port_status(hub, port1, - &portstatus, &portchange); - break; - } + /* If the device is gone, khubd will handle it later */ + if (status == 0 && !(portstatus & USB_PORT_STAT_CONNECTION)) + continue; /* For "USB_PERSIST"-enabled children we must * mark the child device for reset-resume and @@ -2080,6 +2073,8 @@ int usb_port_resume(struct usb_device *udev) } clear_bit(port1, hub->busy_bits); + if (!hub->hdev->parent && !hub->busy_bits[0]) + usb_enable_root_hub_irq(hub->hdev->bus); if (status == 0) status = finish_port_resume(udev); @@ -3009,6 +3004,11 @@ static void hub_events(void) hub->activating = 0; + /* If this is a root hub, tell the HCD it's okay to + * re-enable port-change interrupts now. */ + if (!hdev->parent && !hub->busy_bits[0]) + usb_enable_root_hub_irq(hdev->bus); + loop_autopm: /* Allow autosuspend if we're not going to run again */ if (list_empty(&hub->event_list)) @@ -3234,6 +3234,8 @@ int usb_reset_device(struct usb_device *udev) break; } clear_bit(port1, parent_hub->busy_bits); + if (!parent_hdev->parent && !parent_hub->busy_bits[0]) + usb_enable_root_hub_irq(parent_hdev->bus); if (ret < 0) goto re_enumerate; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 35a03095757..90245fd8bac 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -177,6 +177,15 @@ timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action) static inline void timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) { + /* Don't override timeouts which shrink or (later) disable + * the async ring; just the I/O watchdog. Note that if a + * SHRINK were pending, OFF would never be requested. + */ + if (timer_pending(&ehci->watchdog) + && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) + & ehci->actions)) + return; + if (!test_and_set_bit (action, &ehci->actions)) { unsigned long t; @@ -192,15 +201,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) t = EHCI_SHRINK_JIFFIES; break; } - t += jiffies; - // all timings except IAA watchdog can be overridden. - // async queue SHRINK often precedes IAA. while it's ready - // to go OFF neither can matter, and afterwards the IO - // watchdog stops unless there's still periodic traffic. - if (time_before_eq(t, ehci->watchdog.expires) - && timer_pending (&ehci->watchdog)) - return; - mod_timer (&ehci->watchdog, t); + mod_timer(&ehci->watchdog, t + jiffies); } } diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index c96db1153dc..e534f9de0f0 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -261,6 +261,7 @@ static const struct hc_driver ohci_at91_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index 1b9abdba920..f90fe0c7373 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c @@ -288,6 +288,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 06aadfb0ec2..5adaf36e47d 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -135,6 +135,7 @@ static struct hc_driver ohci_ep93xx_hc_driver = { .get_frame_number = ohci_get_frame, .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 33f1c1c32ed..a8160d65f32 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1054,7 +1054,7 @@ MODULE_LICENSE ("GPL"); #ifdef CONFIG_MFD_SM501 #include "ohci-sm501.c" -#define PLATFORM_DRIVER ohci_hcd_sm501_driver +#define SM501_OHCI_DRIVER ohci_hcd_sm501_driver #endif #if !defined(PCI_DRIVER) && \ @@ -1062,6 +1062,7 @@ MODULE_LICENSE ("GPL"); !defined(OF_PLATFORM_DRIVER) && \ !defined(SA1111_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && \ + !defined(SM501_OHCI_DRIVER) && \ !defined(SSB_OHCI_DRIVER) #error "missing bus glue for ohci-hcd" #endif @@ -1121,9 +1122,18 @@ static int __init ohci_hcd_mod_init(void) goto error_ssb; #endif +#ifdef SM501_OHCI_DRIVER + retval = platform_driver_register(&SM501_OHCI_DRIVER); + if (retval < 0) + goto error_sm501; +#endif + return retval; /* Error path */ +#ifdef SM501_OHCI_DRIVER + error_sm501: +#endif #ifdef SSB_OHCI_DRIVER error_ssb: #endif @@ -1159,6 +1169,9 @@ module_init(ohci_hcd_mod_init); static void __exit ohci_hcd_mod_exit(void) { +#ifdef SM501_OHCI_DRIVER + platform_driver_unregister(&SM501_OHCI_DRIVER); +#endif #ifdef SSB_OHCI_DRIVER ssb_driver_unregister(&SSB_OHCI_DRIVER); #endif diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 79a78029f89..b56739221d1 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -36,6 +36,18 @@ /*-------------------------------------------------------------------------*/ +/* hcd->hub_irq_enable() */ +static void ohci_rhsc_enable (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + + spin_lock_irq(&ohci->lock); + if (!ohci->autostop) + del_timer(&hcd->rh_timer); /* Prevent next poll */ + ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); + spin_unlock_irq(&ohci->lock); +} + #define OHCI_SCHED_ENABLES \ (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) @@ -362,28 +374,18 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, int any_connected) { int poll_rh = 1; - int rhsc; - rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC; switch (ohci->hc_control & OHCI_CTRL_HCFS) { case OHCI_USB_OPER: - /* If no status changes are pending, enable status-change - * interrupts. - */ - if (!rhsc && !changed) { - rhsc = OHCI_INTR_RHSC; - ohci_writel(ohci, rhsc, &ohci->regs->intrenable); - } - - /* Keep on polling until we know a device is connected - * and RHSC is enabled, or until we autostop. - */ + /* keep on polling until we know a device is connected + * and RHSC is enabled */ if (!ohci->autostop) { if (any_connected || !device_may_wakeup(&ohci_to_hcd(ohci) ->self.root_hub->dev)) { - if (rhsc) + if (ohci_readl(ohci, &ohci->regs->intrenable) & + OHCI_INTR_RHSC) poll_rh = 0; } else { ohci->autostop = 1; @@ -396,13 +398,12 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, ohci->autostop = 0; ohci->next_statechange = jiffies + STATECHANGE_DELAY; - } else if (rhsc && time_after_eq(jiffies, + } else if (time_after_eq(jiffies, ohci->next_statechange) && !ohci->ed_rm_list && !(ohci->hc_control & OHCI_SCHED_ENABLES)) { ohci_rh_suspend(ohci, 1); - poll_rh = 0; } } break; @@ -416,12 +417,6 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, else usb_hcd_resume_root_hub(ohci_to_hcd(ohci)); } else { - if (!rhsc && (ohci->autostop || - ohci_to_hcd(ohci)->self.root_hub-> - do_remote_wakeup)) - ohci_writel(ohci, OHCI_INTR_RHSC, - &ohci->regs->intrenable); - /* everything is idle, no need for polling */ poll_rh = 0; } @@ -443,16 +438,12 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci) static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, int any_connected) { - /* If RHSC is enabled, don't poll */ - if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC) - return 0; + int poll_rh = 1; - /* If no status changes are pending, enable status-change interrupts */ - if (!changed) { - ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); - return 0; - } - return 1; + /* keep on polling until RHSC is enabled */ + if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC) + poll_rh = 0; + return poll_rh; } #endif /* CONFIG_PM */ diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c index 96d14fa1d83..13c12ed2225 100644 --- a/drivers/usb/host/ohci-lh7a404.c +++ b/drivers/usb/host/ohci-lh7a404.c @@ -193,6 +193,7 @@ static const struct hc_driver ohci_lh7a404_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 6859fb5f1d6..3a7c24c0367 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -466,6 +466,7 @@ static const struct hc_driver ohci_omap_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 3bf175d95a2..4696cc912e1 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -327,6 +327,7 @@ static const struct hc_driver ohci_pci_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index 664f07ee873..28b458f20cc 100644 --- a/drivers/usb/host/ohci-pnx4008.c +++ b/drivers/usb/host/ohci-pnx4008.c @@ -280,6 +280,7 @@ static const struct hc_driver ohci_pnx4008_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c index 28467e288a9..605d59cba28 100644 --- a/drivers/usb/host/ohci-pnx8550.c +++ b/drivers/usb/host/ohci-pnx8550.c @@ -201,6 +201,7 @@ static const struct hc_driver ohci_pnx8550_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index 50e55db1363..a6725279122 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -72,6 +72,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c index cd3398b675b..523c3012557 100644 --- a/drivers/usb/host/ohci-ppc-soc.c +++ b/drivers/usb/host/ohci-ppc-soc.c @@ -172,6 +172,7 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c index bfdeb0d22d0..c1935ae537f 100644 --- a/drivers/usb/host/ohci-ps3.c +++ b/drivers/usb/host/ohci-ps3.c @@ -68,6 +68,7 @@ static const struct hc_driver ps3_ohci_hc_driver = { .get_frame_number = ohci_get_frame, .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, .start_port_reset = ohci_start_port_reset, #if defined(CONFIG_PM) .bus_suspend = ohci_bus_suspend, diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 70b0d4b459e..d4ee27d92be 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -298,6 +298,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 9c9f3b59186..9b547407c93 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -952,6 +952,7 @@ rescan_this: struct urb *urb; urb_priv_t *urb_priv; __hc32 savebits; + u32 tdINFO; td = list_entry (entry, struct td, td_list); urb = td->urb; @@ -966,6 +967,17 @@ rescan_this: savebits = *prev & ~cpu_to_hc32 (ohci, TD_MASK); *prev = td->hwNextTD | savebits; + /* If this was unlinked, the TD may not have been + * retired ... so manually save the data toggle. + * The controller ignores the value we save for + * control and ISO endpoints. + */ + tdINFO = hc32_to_cpup(ohci, &td->hwINFO); + if ((tdINFO & TD_T) == TD_T_DATA0) + ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_C); + else if ((tdINFO & TD_T) == TD_T_DATA1) + ed->hwHeadP |= cpu_to_hc32(ohci, ED_C); + /* HC may have partly processed this TD */ td_done (ohci, urb, td); urb_priv->td_cnt++; diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index a73d2ff322e..ead4772f0f2 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -466,6 +466,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = { */ .hub_status_data = ohci_s3c2410_hub_status_data, .hub_control = ohci_s3c2410_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index 99438c65981..0f48f2d9922 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c @@ -231,6 +231,7 @@ static const struct hc_driver ohci_sa1111_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c index 60f03cc7ec4..e7ee607278f 100644 --- a/drivers/usb/host/ohci-sh.c +++ b/drivers/usb/host/ohci-sh.c @@ -68,6 +68,7 @@ static const struct hc_driver ohci_sh_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index e899a77dfb8..e610698c6b6 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -75,6 +75,7 @@ static const struct hc_driver ohci_sm501_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c index c4265caec78..7275186db31 100644 --- a/drivers/usb/host/ohci-ssb.c +++ b/drivers/usb/host/ohci-ssb.c @@ -81,6 +81,7 @@ static const struct hc_driver ssb_ohci_hc_driver = { .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index f29307405bb..9b6323f768b 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -2934,6 +2934,16 @@ static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num) return 0; } +static void u132_hub_irq_enable(struct usb_hcd *hcd) +{ + struct u132 *u132 = hcd_to_u132(hcd); + if (u132->going > 1) { + dev_err(&u132->platform_dev->dev, "device has been removed %d\n" + , u132->going); + } else if (u132->going > 0) + dev_err(&u132->platform_dev->dev, "device is being removed\n"); +} + #ifdef CONFIG_PM static int u132_bus_suspend(struct usb_hcd *hcd) @@ -2985,6 +2995,7 @@ static struct hc_driver u132_hc_driver = { .bus_suspend = u132_bus_suspend, .bus_resume = u132_bus_resume, .start_port_reset = u132_start_port_reset, + .hub_irq_enable = u132_hub_irq_enable, }; /* diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index cb7fa0eaf3a..33182f4c226 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -3264,8 +3264,6 @@ static void sisusb_disconnect(struct usb_interface *intf) /* decrement our usage count */ kref_put(&sisusb->kref, sisusb_delete); - - dev_info(&sisusb->sisusb_dev->dev, "Disconnected\n"); } static struct usb_device_id sisusb_table [] = { diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 5234e7a3bd2..0ff4a3971e4 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -637,6 +637,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, + { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 06e0ecabb3e..8302eca893e 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -828,6 +828,9 @@ /* Propox devices */ #define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 +/* Rig Expert Ukraine devices */ +#define FTDI_REU_TINY_PID 0xED22 /* RigExpert Tiny */ + /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index ea924dc4849..d9fb3768a2d 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -570,7 +570,12 @@ static struct usb_serial_driver ipaq_device = { .description = "PocketPC PDA", .usb_driver = &ipaq_driver, .id_table = ipaq_id_table, - .num_ports = 2, + /* + * some devices have an extra endpoint, which + * must be ignored as it would make the core + * create a second port which oopses when used + */ + .num_ports = 1, .open = ipaq_open, .close = ipaq_close, .attach = ipaq_startup, diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 43cfde83a93..a73420dd052 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -306,6 +306,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) }, { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) }, + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ { USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 103195abd41..2a0dd1b50dc 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -57,6 +57,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index cff160abb13..6ac3bbcf7a2 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -15,6 +15,7 @@ #define PL2303_PRODUCT_ID_RSAQ3 0xaaa2 #define PL2303_PRODUCT_ID_ALDIGA 0x0611 #define PL2303_PRODUCT_ID_MMX 0x0612 +#define PL2303_PRODUCT_ID_GPRS 0x0609 #define ATEN_VENDOR_ID 0x0557 #define ATEN_VENDOR_ID2 0x0547 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 45fe3663fa7..39a7c11795c 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -402,11 +402,19 @@ UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100, US_FL_IGNORE_RESIDUE ), #ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB +/* CY7C68300 : support atacb */ UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999, "Cypress", "Cypress AT2LP", US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0), + +/* CY7C68310 : support atacb and atacb2 */ +UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, + "Cypress", + "Cypress ISD-300LP", + US_SC_CYP_ATACB, US_PR_DEVICE, NULL, + 0), #endif /* Reported by Simon Levitt <simon@whattf.com> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 002b61b4f0f..e0c5f96b273 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1825,12 +1825,13 @@ config FB_FSL_DIU config FB_W100 tristate "W100 frame buffer support" - depends on FB && PXA_SHARPSL + depends on FB && ARCH_PXA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT ---help--- Frame buffer driver for the w100 as found on the Sharp SL-Cxx series. + It can also drive the w3220 chip found on iPAQ hx4700. This driver is also available as a module ( = code which can be inserted and removed from the running kernel whenever you want). The diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 0a2785361ca..09d7e22c6fe 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -286,7 +286,7 @@ static struct diu_pool pool; * rheap and make the furture large allocation fail. */ -void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys) +static void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys) { void *virt; @@ -311,12 +311,12 @@ void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys) memset(virt, 0, size); } - pr_debug("rh virt=%p phys=%lx\n", virt, *phys); + pr_debug("rh virt=%p phys=%llx\n", virt, (unsigned long long)*phys); return virt; } -void fsl_diu_free(void *p, unsigned long size) +static void fsl_diu_free(void *p, unsigned long size) { pr_debug("p=%p size=%lu\n", p, size); @@ -770,7 +770,7 @@ static int map_video_memory(struct fb_info *info) info->fix.smem_len = info->fix.line_length * info->var.yres_virtual; pr_debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->fix.smem_len); info->screen_base = fsl_diu_alloc(info->fix.smem_len, &phys); - if (info->screen_base == 0) { + if (info->screen_base == NULL) { printk(KERN_ERR "Unable to allocate fb memory\n"); return -ENOMEM; } @@ -788,7 +788,7 @@ static int map_video_memory(struct fb_info *info) static void unmap_video_memory(struct fb_info *info) { fsl_diu_free(info->screen_base, info->fix.smem_len); - info->screen_base = 0; + info->screen_base = NULL; info->fix.smem_start = 0; info->fix.smem_len = 0; } @@ -1158,7 +1158,7 @@ static int init_fbinfo(struct fb_info *info) return 0; } -static int install_fb(struct fb_info *info) +static int __devinit install_fb(struct fb_info *info) { int rc; struct mfb_info *mfbi = info->par; @@ -1233,7 +1233,7 @@ static int install_fb(struct fb_info *info) return 0; } -static void __exit uninstall_fb(struct fb_info *info) +static void uninstall_fb(struct fb_info *info) { struct mfb_info *mfbi = info->par; @@ -1287,7 +1287,7 @@ static int request_irq_local(int irq) /* Read to clear the status */ status = in_be32(&hw->int_status); - ret = request_irq(irq, fsl_diu_isr, 0, "diu", 0); + ret = request_irq(irq, fsl_diu_isr, 0, "diu", NULL); if (ret) pr_info("Request diu IRQ failed.\n"); else { @@ -1312,7 +1312,7 @@ static void free_irq_local(int irq) /* Disable all LCDC interrupt */ out_be32(&hw->int_mask, 0x1f); - free_irq(irq, 0); + free_irq(irq, NULL); } #ifdef CONFIG_PM @@ -1353,7 +1353,8 @@ static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align) dma_addr_t paddr = 0; ssize = size + bytes_align; - buf->vaddr = dma_alloc_coherent(0, ssize, &paddr, GFP_DMA | __GFP_ZERO); + buf->vaddr = dma_alloc_coherent(NULL, ssize, &paddr, GFP_DMA | + __GFP_ZERO); if (!buf->vaddr) return -ENOMEM; @@ -1371,7 +1372,7 @@ static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align) static void free_buf(struct diu_addr *buf, u32 size, u32 bytes_align) { - dma_free_coherent(0, size + bytes_align, + dma_free_coherent(NULL, size + bytes_align, buf->vaddr, (buf->paddr - buf->offset)); return; } @@ -1411,7 +1412,7 @@ static ssize_t show_monitor(struct device *device, return diu_ops.show_monitor_port(machine_data->monitor_port, buf); } -static int fsl_diu_probe(struct of_device *ofdev, +static int __devinit fsl_diu_probe(struct of_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->node; diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index 30469bf906e..d0674f1e3f1 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -1003,6 +1003,7 @@ static struct w100_pll_info xtal_14318000[] = { static struct w100_pll_info xtal_16000000[] = { /*freq M N_int N_fac tfgoal lock_time */ { 72, 1, 8, 0, 0xe0, 48}, /* tfgoal guessed */ + { 80, 1, 9, 0, 0xe0, 13}, /* tfgoal guessed */ { 95, 1, 10, 7, 0xe0, 38}, /* tfgoal guessed */ { 96, 1, 11, 0, 0xe0, 36}, /* tfgoal guessed */ { 0, 0, 0, 0, 0, 0}, diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index fd01d90cada..57997fa14e6 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h @@ -51,4 +51,4 @@ int v9fs_dir_release(struct inode *inode, struct file *filp); int v9fs_file_open(struct inode *inode, struct file *file); void v9fs_inode2stat(struct inode *inode, struct p9_stat *stat); void v9fs_dentry_release(struct dentry *); -int v9fs_uflags2omode(int uflags); +int v9fs_uflags2omode(int uflags, int extended); diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 0d55affe37d..52944d2249a 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -59,7 +59,7 @@ int v9fs_file_open(struct inode *inode, struct file *file) P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p \n", inode, file); v9ses = v9fs_inode2v9ses(inode); - omode = v9fs_uflags2omode(file->f_flags); + omode = v9fs_uflags2omode(file->f_flags, v9fs_extended(v9ses)); fid = file->private_data; if (!fid) { fid = v9fs_fid_clone(file->f_path.dentry); @@ -75,6 +75,8 @@ int v9fs_file_open(struct inode *inode, struct file *file) inode->i_size = 0; inode->i_blocks = 0; } + if ((file->f_flags & O_APPEND) && (!v9fs_extended(v9ses))) + generic_file_llseek(file, 0, SEEK_END); } file->private_data = fid; diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 40fa807bd92..c95295c6504 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -132,10 +132,10 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode) /** * v9fs_uflags2omode- convert posix open flags to plan 9 mode bits * @uflags: flags to convert - * + * @extended: if .u extensions are active */ -int v9fs_uflags2omode(int uflags) +int v9fs_uflags2omode(int uflags, int extended) { int ret; @@ -155,14 +155,16 @@ int v9fs_uflags2omode(int uflags) break; } - if (uflags & O_EXCL) - ret |= P9_OEXCL; - if (uflags & O_TRUNC) ret |= P9_OTRUNC; - if (uflags & O_APPEND) - ret |= P9_OAPPEND; + if (extended) { + if (uflags & O_EXCL) + ret |= P9_OEXCL; + + if (uflags & O_APPEND) + ret |= P9_OAPPEND; + } return ret; } @@ -506,7 +508,7 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, flags = O_RDWR; fid = v9fs_create(v9ses, dir, dentry, NULL, perm, - v9fs_uflags2omode(flags)); + v9fs_uflags2omode(flags, v9fs_extended(v9ses))); if (IS_ERR(fid)) { err = PTR_ERR(fid); fid = NULL; diff --git a/fs/Kconfig b/fs/Kconfig index cf12c403b8c..2694648cbd1 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -830,7 +830,7 @@ config NTFS_FS from the project web site. For more information see <file:Documentation/filesystems/ntfs.txt> - and <http://linux-ntfs.sourceforge.net/>. + and <http://www.linux-ntfs.org/>. To compile this file system support as a module, choose M here: the module will be called ntfs. diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c index 50c994a249a..09a4522f65e 100644 --- a/fs/ecryptfs/miscdev.c +++ b/fs/ecryptfs/miscdev.c @@ -575,13 +575,11 @@ int ecryptfs_init_ecryptfs_miscdev(void) int rc; atomic_set(&ecryptfs_num_miscdev_opens, 0); - mutex_lock(&ecryptfs_daemon_hash_mux); rc = misc_register(&ecryptfs_miscdev); if (rc) printk(KERN_ERR "%s: Failed to register miscellaneous device " "for communications with userspace daemons; rc = [%d]\n", __func__, rc); - mutex_unlock(&ecryptfs_daemon_hash_mux); return rc; } diff --git a/fs/exec.c b/fs/exec.c index da94a6f05df..fd9234379e8 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -610,7 +610,7 @@ int setup_arg_pages(struct linux_binprm *bprm, bprm->exec -= stack_shift; down_write(&mm->mmap_sem); - vm_flags = vma->vm_flags; + vm_flags = VM_STACK_FLAGS; /* * Adjust stack execute permissions; explicitly enable for diff --git a/fs/ext3/super.c b/fs/ext3/super.c index fe3119a71ad..2845425077e 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -2875,8 +2875,10 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type, blk++; } out: - if (len == towrite) + if (len == towrite) { + mutex_unlock(&inode->i_mutex); return err; + } if (inode->i_size < off+len-towrite) { i_size_write(inode, off+len-towrite); EXT3_I(inode)->i_disksize = inode->i_size; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index cb96f127c36..02bf2434397 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3337,8 +3337,10 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type, blk++; } out: - if (len == towrite) + if (len == towrite) { + mutex_unlock(&inode->i_mutex); return err; + } if (inode->i_size < off+len-towrite) { i_size_write(inode, off+len-towrite); EXT4_I(inode)->i_disksize = inode->i_size; diff --git a/fs/libfs.c b/fs/libfs.c index 892d41cb338..baeb71ee1cd 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -512,6 +512,20 @@ void simple_release_fs(struct vfsmount **mount, int *count) mntput(mnt); } +/** + * simple_read_from_buffer - copy data from the buffer to user space + * @to: the user space buffer to read to + * @count: the maximum number of bytes to read + * @ppos: the current position in the buffer + * @from: the buffer to read from + * @available: the size of the buffer + * + * The simple_read_from_buffer() function reads up to @count bytes from the + * buffer @from at offset @ppos into the user space address starting at @to. + * + * On success, the number of bytes read is returned and the offset @ppos is + * advanced by this number, or negative value is returned on error. + **/ ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos, const void *from, size_t available) { @@ -528,6 +542,20 @@ ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos, return count; } +/** + * memory_read_from_buffer - copy data from the buffer + * @to: the kernel space buffer to read to + * @count: the maximum number of bytes to read + * @ppos: the current position in the buffer + * @from: the buffer to read from + * @available: the size of the buffer + * + * The memory_read_from_buffer() function reads up to @count bytes from the + * buffer @from at offset @ppos into the kernel space address starting at @to. + * + * On success, the number of bytes read is returned and the offset @ppos is + * advanced by this number, or negative value is returned on error. + **/ ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos, const void *from, size_t available) { diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 58d43daec08..982a2064fe4 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -204,7 +204,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) * Note: assumes we have exclusive access to this mapping either * through inode->i_mutex or some other mechanism. */ - if (page->index == 0 && invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1) < 0) { + if (invalidate_inode_pages2_range(inode->i_mapping, page->index + 1, -1) < 0) { /* Should never happen */ nfs_zap_mapping(inode, inode->i_mapping); } diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index efc015c6128..44f87caf368 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -606,7 +606,9 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm, res->last_used = 0; + spin_lock(&dlm->spinlock); list_add_tail(&res->tracking, &dlm->tracking_list); + spin_unlock(&dlm->spinlock); memset(res->lvb, 0, DLM_LVB_LEN); memset(res->refmap, 0, sizeof(res->refmap)); diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 394d25a131a..80e20d9f278 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -1554,8 +1554,8 @@ out: */ int ocfs2_file_lock(struct file *file, int ex, int trylock) { - int ret, level = ex ? LKM_EXMODE : LKM_PRMODE; - unsigned int lkm_flags = trylock ? LKM_NOQUEUE : 0; + int ret, level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; + unsigned int lkm_flags = trylock ? DLM_LKF_NOQUEUE : 0; unsigned long flags; struct ocfs2_file_private *fp = file->private_data; struct ocfs2_lock_res *lockres = &fp->fp_flock; @@ -1582,7 +1582,7 @@ int ocfs2_file_lock(struct file *file, int ex, int trylock) * Get the lock at NLMODE to start - that way we * can cancel the upconvert request if need be. */ - ret = ocfs2_lock_create(osb, lockres, LKM_NLMODE, 0); + ret = ocfs2_lock_create(osb, lockres, DLM_LOCK_NL, 0); if (ret < 0) { mlog_errno(ret); goto out; @@ -1597,7 +1597,7 @@ int ocfs2_file_lock(struct file *file, int ex, int trylock) } lockres->l_action = OCFS2_AST_CONVERT; - lkm_flags |= LKM_CONVERT; + lkm_flags |= DLM_LKF_CONVERT; lockres->l_requested = level; lockres_or_flags(lockres, OCFS2_LOCK_BUSY); @@ -1664,7 +1664,7 @@ void ocfs2_file_unlock(struct file *file) if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) return; - if (lockres->l_level == LKM_NLMODE) + if (lockres->l_level == DLM_LOCK_NL) return; mlog(0, "Unlock: \"%s\" flags: 0x%lx, level: %d, act: %d\n", @@ -1678,11 +1678,11 @@ void ocfs2_file_unlock(struct file *file) lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED); lockres->l_blocking = DLM_LOCK_EX; - gen = ocfs2_prepare_downconvert(lockres, LKM_NLMODE); + gen = ocfs2_prepare_downconvert(lockres, DLM_LOCK_NL); lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0); spin_unlock_irqrestore(&lockres->l_lock, flags); - ret = ocfs2_downconvert_lock(osb, lockres, LKM_NLMODE, 0, gen); + ret = ocfs2_downconvert_lock(osb, lockres, DLM_LOCK_NL, 0, gen); if (ret) { mlog_errno(ret); return; diff --git a/fs/open.c b/fs/open.c index a1450086e92..a99ad09c319 100644 --- a/fs/open.c +++ b/fs/open.c @@ -16,6 +16,7 @@ #include <linux/namei.h> #include <linux/backing-dev.h> #include <linux/capability.h> +#include <linux/securebits.h> #include <linux/security.h> #include <linux/mount.h> #include <linux/vfs.h> @@ -425,7 +426,7 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) { struct nameidata nd; int old_fsuid, old_fsgid; - kernel_cap_t old_cap; + kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */ int res; if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ @@ -433,23 +434,27 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) old_fsuid = current->fsuid; old_fsgid = current->fsgid; - old_cap = current->cap_effective; current->fsuid = current->uid; current->fsgid = current->gid; - /* - * Clear the capabilities if we switch to a non-root user - * - * FIXME: There is a race here against sys_capset. The - * capabilities can change yet we will restore the old - * value below. We should hold task_capabilities_lock, - * but we cannot because user_path_walk can sleep. - */ - if (current->uid) - cap_clear(current->cap_effective); - else - current->cap_effective = current->cap_permitted; + if (!issecure(SECURE_NO_SETUID_FIXUP)) { + /* + * Clear the capabilities if we switch to a non-root user + */ +#ifndef CONFIG_SECURITY_FILE_CAPABILITIES + /* + * FIXME: There is a race here against sys_capset. The + * capabilities can change yet we will restore the old + * value below. We should hold task_capabilities_lock, + * but we cannot because user_path_walk can sleep. + */ +#endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */ + if (current->uid) + old_cap = cap_set_effective(__cap_empty_set); + else + old_cap = cap_set_effective(current->cap_permitted); + } res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); if (res) @@ -478,7 +483,9 @@ out_path_release: out: current->fsuid = old_fsuid; current->fsgid = old_fsgid; - current->cap_effective = old_cap; + + if (!issecure(SECURE_NO_SETUID_FIXUP)) + cap_set_effective(old_cap); return res; } diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index ab8ccc9d14f..c492449f3b4 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -476,10 +476,10 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf, return -ESRCH; mm = get_task_mm(task); if (mm) { - static struct mm_walk clear_refs_walk; - memset(&clear_refs_walk, 0, sizeof(clear_refs_walk)); - clear_refs_walk.pmd_entry = clear_refs_pte_range; - clear_refs_walk.mm = mm; + struct mm_walk clear_refs_walk = { + .pmd_entry = clear_refs_pte_range, + .mm = mm, + }; down_read(&mm->mmap_sem); for (vma = mm->mmap; vma; vma = vma->vm_next) { clear_refs_walk.private = vma; @@ -602,11 +602,6 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, return err; } -static struct mm_walk pagemap_walk = { - .pmd_entry = pagemap_pte_range, - .pte_hole = pagemap_pte_hole -}; - /* * /proc/pid/pagemap - an array mapping virtual pages to pfns * @@ -641,6 +636,11 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, struct pagemapread pm; int pagecount; int ret = -ESRCH; + struct mm_walk pagemap_walk; + unsigned long src; + unsigned long svpfn; + unsigned long start_vaddr; + unsigned long end_vaddr; if (!task) goto out; @@ -659,11 +659,15 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, if (!mm) goto out_task; - ret = -ENOMEM; + uaddr = (unsigned long)buf & PAGE_MASK; uend = (unsigned long)(buf + count); pagecount = (PAGE_ALIGN(uend) - uaddr) / PAGE_SIZE; - pages = kmalloc(pagecount * sizeof(struct page *), GFP_KERNEL); + ret = 0; + if (pagecount == 0) + goto out_mm; + pages = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL); + ret = -ENOMEM; if (!pages) goto out_mm; @@ -684,33 +688,33 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, pm.out = (u64 *)buf; pm.end = (u64 *)(buf + count); - if (!ptrace_may_attach(task)) { - ret = -EIO; - } else { - unsigned long src = *ppos; - unsigned long svpfn = src / PM_ENTRY_BYTES; - unsigned long start_vaddr = svpfn << PAGE_SHIFT; - unsigned long end_vaddr = TASK_SIZE_OF(task); - - /* watch out for wraparound */ - if (svpfn > TASK_SIZE_OF(task) >> PAGE_SHIFT) - start_vaddr = end_vaddr; - - /* - * The odds are that this will stop walking way - * before end_vaddr, because the length of the - * user buffer is tracked in "pm", and the walk - * will stop when we hit the end of the buffer. - */ - ret = walk_page_range(start_vaddr, end_vaddr, - &pagemap_walk); - if (ret == PM_END_OF_BUFFER) - ret = 0; - /* don't need mmap_sem for these, but this looks cleaner */ - *ppos += (char *)pm.out - buf; - if (!ret) - ret = (char *)pm.out - buf; - } + pagemap_walk.pmd_entry = pagemap_pte_range; + pagemap_walk.pte_hole = pagemap_pte_hole; + pagemap_walk.mm = mm; + pagemap_walk.private = ± + + src = *ppos; + svpfn = src / PM_ENTRY_BYTES; + start_vaddr = svpfn << PAGE_SHIFT; + end_vaddr = TASK_SIZE_OF(task); + + /* watch out for wraparound */ + if (svpfn > TASK_SIZE_OF(task) >> PAGE_SHIFT) + start_vaddr = end_vaddr; + + /* + * The odds are that this will stop walking way + * before end_vaddr, because the length of the + * user buffer is tracked in "pm", and the walk + * will stop when we hit the end of the buffer. + */ + ret = walk_page_range(start_vaddr, end_vaddr, &pagemap_walk); + if (ret == PM_END_OF_BUFFER) + ret = 0; + /* don't need mmap_sem for these, but this looks cleaner */ + *ppos += (char *)pm.out - buf; + if (!ret) + ret = (char *)pm.out - buf; out_pages: for (; pagecount; pagecount--) { diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 57917932212..192269698a8 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -45,6 +45,8 @@ void reiserfs_delete_inode(struct inode *inode) goto out; reiserfs_update_inode_transaction(inode); + reiserfs_discard_prealloc(&th, inode); + err = reiserfs_delete_object(&th, inode); /* Do quota update inside a transaction for journaled quotas. We must do that diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index ed424d708e6..1d40f2bd197 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -2165,8 +2165,10 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, blk++; } out: - if (len == towrite) + if (len == towrite) { + mutex_unlock(&inode->i_mutex); return err; + } if (inode->i_size < off + len - towrite) i_size_write(inode, off + len - towrite); inode->i_version++; diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h index 85fd0aa27a8..4ec0a296bde 100644 --- a/include/asm-generic/atomic.h +++ b/include/asm-generic/atomic.h @@ -2,7 +2,7 @@ #define _ASM_GENERIC_ATOMIC_H /* * Copyright (C) 2005 Silicon Graphics, Inc. - * Christoph Lameter <clameter@sgi.com> + * Christoph Lameter * * Allows to provide arch independent atomic definitions without the need to * edit all arch specific atomic.h files. diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h index a798d6299a7..1232be3885b 100644 --- a/include/asm-mips/atomic.h +++ b/include/asm-mips/atomic.h @@ -283,10 +283,10 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) " beqz %0, 2f \n" " subu %0, %1, %3 \n" " .set reorder \n" - "1: \n" " .subsection 2 \n" "2: b 1b \n" " .previous \n" + "1: \n" " .set mips0 \n" : "=&r" (result), "=&r" (temp), "=m" (v->counter) : "Ir" (i), "m" (v->counter) @@ -664,10 +664,10 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) " beqz %0, 2f \n" " dsubu %0, %1, %3 \n" " .set reorder \n" - "1: \n" " .subsection 2 \n" "2: b 1b \n" " .previous \n" + "1: \n" " .set mips0 \n" : "=&r" (result), "=&r" (temp), "=m" (v->counter) : "Ir" (i), "m" (v->counter) diff --git a/include/asm-powerpc/hugetlb.h b/include/asm-powerpc/hugetlb.h index 649c6c3b87b..be32ff02f4a 100644 --- a/include/asm-powerpc/hugetlb.h +++ b/include/asm-powerpc/hugetlb.h @@ -49,12 +49,6 @@ static inline pte_t huge_pte_wrprotect(pte_t pte) return pte_wrprotect(pte); } -static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - ptep_set_wrprotect(mm, addr, ptep); -} - static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, pte_t pte, int dirty) diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h index cc6a43ba41d..7686569a0be 100644 --- a/include/asm-powerpc/pgtable-ppc64.h +++ b/include/asm-powerpc/pgtable-ppc64.h @@ -314,6 +314,16 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, old = pte_update(mm, addr, ptep, _PAGE_RW, 0); } +static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) +{ + unsigned long old; + + if ((pte_val(*ptep) & _PAGE_RW) == 0) + return; + old = pte_update(mm, addr, ptep, _PAGE_RW, 1); +} + /* * We currently remove entries from the hashtable regardless of whether * the entry was young or dirty. The generic routines only flush if the diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h index c7f4f8e3e29..bd0ea191dfa 100644 --- a/include/asm-s390/pgtable.h +++ b/include/asm-s390/pgtable.h @@ -223,6 +223,9 @@ extern char empty_zero_page[PAGE_SIZE]; #define _PAGE_SPECIAL 0x004 /* SW associated with special page */ #define __HAVE_ARCH_PTE_SPECIAL +/* Set of bits not changed in pte_modify */ +#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_SPECIAL) + /* Six different types of pages. */ #define _PAGE_TYPE_EMPTY 0x400 #define _PAGE_TYPE_NONE 0x401 @@ -681,7 +684,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt */ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { - pte_val(pte) &= PAGE_MASK; + pte_val(pte) &= _PAGE_CHG_MASK; pte_val(pte) |= pgprot_val(newprot); return pte; } diff --git a/include/asm-x86/kvm_para.h b/include/asm-x86/kvm_para.h index bfd9900742b..76f392146da 100644 --- a/include/asm-x86/kvm_para.h +++ b/include/asm-x86/kvm_para.h @@ -71,7 +71,8 @@ static inline long kvm_hypercall0(unsigned int nr) long ret; asm volatile(KVM_HYPERCALL : "=a"(ret) - : "a"(nr)); + : "a"(nr) + : "memory"); return ret; } @@ -80,7 +81,8 @@ static inline long kvm_hypercall1(unsigned int nr, unsigned long p1) long ret; asm volatile(KVM_HYPERCALL : "=a"(ret) - : "a"(nr), "b"(p1)); + : "a"(nr), "b"(p1) + : "memory"); return ret; } @@ -90,7 +92,8 @@ static inline long kvm_hypercall2(unsigned int nr, unsigned long p1, long ret; asm volatile(KVM_HYPERCALL : "=a"(ret) - : "a"(nr), "b"(p1), "c"(p2)); + : "a"(nr), "b"(p1), "c"(p2) + : "memory"); return ret; } @@ -100,7 +103,8 @@ static inline long kvm_hypercall3(unsigned int nr, unsigned long p1, long ret; asm volatile(KVM_HYPERCALL : "=a"(ret) - : "a"(nr), "b"(p1), "c"(p2), "d"(p3)); + : "a"(nr), "b"(p1), "c"(p2), "d"(p3) + : "memory"); return ret; } @@ -111,7 +115,8 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned long p1, long ret; asm volatile(KVM_HYPERCALL : "=a"(ret) - : "a"(nr), "b"(p1), "c"(p2), "d"(p3), "S"(p4)); + : "a"(nr), "b"(p1), "c"(p2), "d"(p3), "S"(p4) + : "memory"); return ret; } diff --git a/include/linux/capability.h b/include/linux/capability.h index fa830f8de03..02673846d20 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -501,6 +501,8 @@ extern const kernel_cap_t __cap_empty_set; extern const kernel_cap_t __cap_full_set; extern const kernel_cap_t __cap_init_eff_set; +kernel_cap_t cap_set_effective(const kernel_cap_t pE_new); + int capable(int cap); int __capable(struct task_struct *t, int cap); diff --git a/include/linux/cfag12864b.h b/include/linux/cfag12864b.h index 1605dd8aa64..6f9f19d6659 100644 --- a/include/linux/cfag12864b.h +++ b/include/linux/cfag12864b.h @@ -4,7 +4,7 @@ * Description: cfag12864b LCD driver header * License: GPLv2 * - * Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com> + * Author: Copyright (C) Miguel Ojeda Sandonis * Date: 2006-10-12 * * This program is free software; you can redistribute it and/or modify diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 5df3db58fcc..c24875bd9c5 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -353,6 +353,10 @@ static inline void __cpus_fold(cpumask_t *dstp, const cpumask_t *origp, for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask) #endif /* NR_CPUS */ +#define next_cpu_nr(n, src) next_cpu(n, src) +#define cpus_weight_nr(cpumask) cpus_weight(cpumask) +#define for_each_cpu_mask_nr(cpu, mask) for_each_cpu_mask(cpu, mask) + /* * The following particular system cpumasks and operations manage * possible, present and online cpus. Each of them is a fixed size diff --git a/include/linux/debug_locks.h b/include/linux/debug_locks.h index f4a5871767f..4aaa4afb1cb 100644 --- a/include/linux/debug_locks.h +++ b/include/linux/debug_locks.h @@ -1,6 +1,8 @@ #ifndef __LINUX_DEBUG_LOCKING_H #define __LINUX_DEBUG_LOCKING_H +#include <linux/kernel.h> + struct task_struct; extern int debug_locks; @@ -11,14 +13,6 @@ extern int debug_locks_silent; */ extern int debug_locks_off(void); -/* - * In the debug case we carry the caller's instruction pointer into - * other functions, but we dont want the function argument overhead - * in the nondebug case - hence these macros: - */ -#define _RET_IP_ (unsigned long)__builtin_return_address(0) -#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; }) - #define DEBUG_LOCKS_WARN_ON(c) \ ({ \ int __ret = 0; \ diff --git a/include/linux/firmware.h b/include/linux/firmware.h index 4d10c7328d2..6c7eff2ebad 100644 --- a/include/linux/firmware.h +++ b/include/linux/firmware.h @@ -13,7 +13,7 @@ struct firmware { struct device; -#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) +#if defined(CONFIG_FW_LOADER) || (defined(CONFIG_FW_LOADER_MODULE) && defined(MODULE)) int request_firmware(const struct firmware **fw, const char *name, struct device *device); int request_firmware_nowait( diff --git a/include/linux/ide.h b/include/linux/ide.h index 9918772bf27..eddb6daadf4 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -189,6 +189,21 @@ static inline void ide_std_init_ports(hw_regs_t *hw, hw->io_ports.ctl_addr = ctl_addr; } +/* for IDE PCI controllers in legacy mode, temporary */ +static inline int __ide_default_irq(unsigned long base) +{ + switch (base) { +#ifdef CONFIG_IA64 + case 0x1f0: return isa_irq_to_vector(14); + case 0x170: return isa_irq_to_vector(15); +#else + case 0x1f0: return 14; + case 0x170: return 15; +#endif + } + return 0; +} + #include <asm/ide.h> #if !defined(MAX_HWIFS) || defined(CONFIG_EMBEDDED) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 792bf0aa779..2e70006c7fa 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -46,6 +46,9 @@ extern const char linux_proc_banner[]; #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) +#define _RET_IP_ (unsigned long)__builtin_return_address(0) +#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; }) + #ifdef CONFIG_LBD # include <asm/div64.h> # define sector_div(a, b) do_div(a, b) diff --git a/include/linux/ks0108.h b/include/linux/ks0108.h index a2c54acceb4..cb311798e0b 100644 --- a/include/linux/ks0108.h +++ b/include/linux/ks0108.h @@ -4,7 +4,7 @@ * Description: ks0108 LCD Controller driver header * License: GPLv2 * - * Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com> + * Author: Copyright (C) Miguel Ojeda Sandonis * Date: 2006-10-31 * * This program is free software; you can redistribute it and/or modify diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index eafc9d6d2b3..65953822c9c 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1520,6 +1520,7 @@ #define PCI_DEVICE_ID_MARVELL_GT64260 0x6430 #define PCI_DEVICE_ID_MARVELL_MV64360 0x6460 #define PCI_DEVICE_ID_MARVELL_MV64460 0x6480 +#define PCI_DEVICE_ID_MARVELL_CAFE_SD 0x4101 #define PCI_VENDOR_ID_V3 0x11b0 #define PCI_DEVICE_ID_V3_V960 0x0001 diff --git a/include/linux/rculist.h b/include/linux/rculist.h new file mode 100644 index 00000000000..bde4586f438 --- /dev/null +++ b/include/linux/rculist.h @@ -0,0 +1,6 @@ +#ifndef _LINUX_RCULIST_H +#define _LINUX_RCULIST_H + +#include <linux/list.h> + +#endif /* _LINUX_RCULIST_H */ diff --git a/include/linux/securebits.h b/include/linux/securebits.h index c1f19dbceb0..92f09bdf117 100644 --- a/include/linux/securebits.h +++ b/include/linux/securebits.h @@ -7,14 +7,15 @@ inheritance of root-permissions and suid-root executable under compatibility mode. We raise the effective and inheritable bitmasks *of the executable file* if the effective uid of the new process is - 0. If the real uid is 0, we raise the inheritable bitmask of the + 0. If the real uid is 0, we raise the effective (legacy) bit of the executable file. */ #define SECURE_NOROOT 0 #define SECURE_NOROOT_LOCKED 1 /* make bit-0 immutable */ -/* When set, setuid to/from uid 0 does not trigger capability-"fixes" - to be compatible with old programs relying on set*uid to loose - privileges. When unset, setuid doesn't change privileges. */ +/* When set, setuid to/from uid 0 does not trigger capability-"fixup". + When unset, to provide compatiblility with old programs relying on + set*uid to gain/lose privilege, transitions to/from uid 0 cause + capabilities to be gained/lost. */ #define SECURE_NO_SETUID_FIXUP 2 #define SECURE_NO_SETUID_FIXUP_LOCKED 3 /* make bit-2 immutable */ @@ -26,10 +27,10 @@ #define SECURE_KEEP_CAPS 4 #define SECURE_KEEP_CAPS_LOCKED 5 /* make bit-4 immutable */ -/* Each securesetting is implemented using two bits. One bit specify +/* Each securesetting is implemented using two bits. One bit specifies whether the setting is on or off. The other bit specify whether the - setting is fixed or not. A setting which is fixed cannot be changed - from user-level. */ + setting is locked or not. A setting which is locked cannot be + changed from user-level. */ #define issecure_mask(X) (1 << (X)) #define issecure(X) (issecure_mask(X) & current->securebits) diff --git a/include/linux/slab.h b/include/linux/slab.h index c2ad3501659..9aa90a6f20e 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -1,7 +1,7 @@ /* * Written by Mark Hemment, 1996 (markhe@nextd.demon.co.uk). * - * (C) SGI 2006, Christoph Lameter <clameter@sgi.com> + * (C) SGI 2006, Christoph Lameter * Cleaned up and restructured to ease the addition of alternative * implementations of SLAB allocators. */ diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index 71e43a12ebb..d117ea2825a 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -4,7 +4,7 @@ /* * SLUB : A Slab allocator without object queues. * - * (C) 2007 SGI, Christoph Lameter <clameter@sgi.com> + * (C) 2007 SGI, Christoph Lameter */ #include <linux/types.h> #include <linux/gfp.h> @@ -137,10 +137,12 @@ static __always_inline int kmalloc_index(size_t size) if (size <= KMALLOC_MIN_SIZE) return KMALLOC_SHIFT_LOW; +#if KMALLOC_MIN_SIZE <= 64 if (size > 64 && size <= 96) return 1; if (size > 128 && size <= 192) return 2; +#endif if (size <= 8) return 3; if (size <= 16) return 4; if (size <= 32) return 5; diff --git a/kernel/capability.c b/kernel/capability.c index cfbe4429948..901e0fdc3ff 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -121,6 +121,27 @@ static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy) * uninteresting and/or not to be changed. */ +/* + * Atomically modify the effective capabilities returning the original + * value. No permission check is performed here - it is assumed that the + * caller is permitted to set the desired effective capabilities. + */ +kernel_cap_t cap_set_effective(const kernel_cap_t pE_new) +{ + kernel_cap_t pE_old; + + spin_lock(&task_capability_lock); + + pE_old = current->cap_effective; + current->cap_effective = pE_new; + + spin_unlock(&task_capability_lock); + + return pE_old; +} + +EXPORT_SYMBOL(cap_set_effective); + /** * sys_capget - get the capabilities of a given process. * @header: pointer to struct that contains capability version and diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 421be5fe5cc..ab80515008f 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -1003,10 +1003,18 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode) */ raise = timer->state == HRTIMER_STATE_PENDING; + /* + * We use preempt_disable to prevent this task from migrating after + * setting up the softirq and raising it. Otherwise, if me migrate + * we will raise the softirq on the wrong CPU. + */ + preempt_disable(); + unlock_hrtimer_base(timer, &flags); if (raise) hrtimer_raise_softirq(); + preempt_enable(); return ret; } diff --git a/kernel/kprobes.c b/kernel/kprobes.c index d4998f81e22..1485ca8d0e0 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -79,7 +79,7 @@ static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; * * For such cases, we now have a blacklist */ -struct kprobe_blackpoint kprobe_blacklist[] = { +static struct kprobe_blackpoint kprobe_blacklist[] = { {"preempt_schedule",}, {NULL} /* Terminator */ }; diff --git a/kernel/printk.c b/kernel/printk.c index 8fb01c32aa3..e2129e83fd7 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -666,7 +666,7 @@ static int acquire_console_semaphore_for_printk(unsigned int cpu) return retval; } -const char printk_recursion_bug_msg [] = +static const char printk_recursion_bug_msg [] = KERN_CRIT "BUG: recent printk recursion!\n"; static int printk_recursion_bug; diff --git a/kernel/rcupreempt.c b/kernel/rcupreempt.c index 5e02b774070..41d275a81df 100644 --- a/kernel/rcupreempt.c +++ b/kernel/rcupreempt.c @@ -925,26 +925,22 @@ void rcu_offline_cpu(int cpu) spin_unlock_irqrestore(&rdp->lock, flags); } -void __devinit rcu_online_cpu(int cpu) -{ - unsigned long flags; - - spin_lock_irqsave(&rcu_ctrlblk.fliplock, flags); - cpu_set(cpu, rcu_cpu_online_map); - spin_unlock_irqrestore(&rcu_ctrlblk.fliplock, flags); -} - #else /* #ifdef CONFIG_HOTPLUG_CPU */ void rcu_offline_cpu(int cpu) { } -void __devinit rcu_online_cpu(int cpu) +#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */ + +void __cpuinit rcu_online_cpu(int cpu) { -} + unsigned long flags; -#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */ + spin_lock_irqsave(&rcu_ctrlblk.fliplock, flags); + cpu_set(cpu, rcu_cpu_online_map); + spin_unlock_irqrestore(&rcu_ctrlblk.fliplock, flags); +} static void rcu_process_callbacks(struct softirq_action *unused) { diff --git a/kernel/sched.c b/kernel/sched.c index 94ead43eda6..4e2f6033565 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -5622,10 +5622,10 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu) double_rq_lock(rq_src, rq_dest); /* Already moved. */ if (task_cpu(p) != src_cpu) - goto out; + goto done; /* Affinity changed (again). */ if (!cpu_isset(dest_cpu, p->cpus_allowed)) - goto out; + goto fail; on_rq = p->se.on_rq; if (on_rq) @@ -5636,8 +5636,9 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu) activate_task(rq_dest, p, 0); check_preempt_curr(rq_dest, p); } +done: ret = 1; -out: +fail: double_rq_unlock(rq_src, rq_dest); return ret; } diff --git a/kernel/softlockup.c b/kernel/softlockup.c index c828c2339cc..a272d78185e 100644 --- a/kernel/softlockup.c +++ b/kernel/softlockup.c @@ -120,6 +120,7 @@ void softlockup_tick(void) printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %lus! [%s:%d]\n", this_cpu, now - touch_timestamp, current->comm, task_pid_nr(current)); + print_modules(); if (regs) show_regs(regs); else diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 29fc39f1029..ce7799540c9 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -13,7 +13,7 @@ * Kai Petzke <wpp@marie.physik.tu-berlin.de> * Theodore Ts'o <tytso@mit.edu> * - * Made to use alloc_percpu by Christoph Lameter <clameter@sgi.com>. + * Made to use alloc_percpu by Christoph Lameter. */ #include <linux/module.h> diff --git a/lib/bug.c b/lib/bug.c index 530f38f5578..bfeafd60ee9 100644 --- a/lib/bug.c +++ b/lib/bug.c @@ -37,6 +37,7 @@ */ #include <linux/list.h> #include <linux/module.h> +#include <linux/kernel.h> #include <linux/bug.h> #include <linux/sched.h> @@ -149,6 +150,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs) (void *)bugaddr); show_regs(regs); + add_taint(TAINT_WARN); return BUG_TRAP_TYPE_WARN; } diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 169a2f8dabc..56ec21a7f73 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2001 Momchil Velikov * Portions Copyright (C) 2001 Christoph Hellwig - * Copyright (C) 2005 SGI, Christoph Lameter <clameter@sgi.com> + * Copyright (C) 2005 SGI, Christoph Lameter * Copyright (C) 2006 Nick Piggin * * This program is free software; you can redistribute it and/or diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 6021757a449..1dc2d1d18fa 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -22,6 +22,8 @@ #include <linux/string.h> #include <linux/ctype.h> #include <linux/kernel.h> +#include <linux/kallsyms.h> +#include <linux/uaccess.h> #include <asm/page.h> /* for PAGE_SIZE */ #include <asm/div64.h> @@ -482,6 +484,89 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int return buf; } +static char *string(char *buf, char *end, char *s, int field_width, int precision, int flags) +{ + int len, i; + + if ((unsigned long)s < PAGE_SIZE) + s = "<NULL>"; + + len = strnlen(s, precision); + + if (!(flags & LEFT)) { + while (len < field_width--) { + if (buf < end) + *buf = ' '; + ++buf; + } + } + for (i = 0; i < len; ++i) { + if (buf < end) + *buf = *s; + ++buf; ++s; + } + while (len < field_width--) { + if (buf < end) + *buf = ' '; + ++buf; + } + return buf; +} + +static inline void *dereference_function_descriptor(void *ptr) +{ +#if defined(CONFIG_IA64) || defined(CONFIG_PPC64) + void *p; + if (!probe_kernel_address(ptr, p)) + ptr = p; +#endif + return ptr; +} + +static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int precision, int flags) +{ + unsigned long value = (unsigned long) ptr; +#ifdef CONFIG_KALLSYMS + char sym[KSYM_SYMBOL_LEN]; + sprint_symbol(sym, value); + return string(buf, end, sym, field_width, precision, flags); +#else + field_width = 2*sizeof(void *); + flags |= SPECIAL | SMALL | ZEROPAD; + return number(buf, end, value, 16, field_width, precision, flags); +#endif +} + +/* + * Show a '%p' thing. A kernel extension is that the '%p' is followed + * by an extra set of alphanumeric characters that are extended format + * specifiers. + * + * Right now we just handle 'F' (for symbolic Function descriptor pointers) + * and 'S' (for Symbolic direct pointers), but this can easily be + * extended in the future (network address types etc). + * + * The difference between 'S' and 'F' is that on ia64 and ppc64 function + * pointers are really function descriptors, which contain a pointer the + * real address. + */ +static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags) +{ + switch (*fmt) { + case 'F': + ptr = dereference_function_descriptor(ptr); + /* Fallthrough */ + case 'S': + return symbol_string(buf, end, ptr, field_width, precision, flags); + } + flags |= SMALL; + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + return number(buf, end, (unsigned long) ptr, 16, field_width, precision, flags); +} + /** * vsnprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into @@ -502,11 +587,9 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int */ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) { - int len; unsigned long long num; - int i, base; + int base; char *str, *end, c; - const char *s; int flags; /* flags to number() */ @@ -622,43 +705,18 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) continue; case 's': - s = va_arg(args, char *); - if ((unsigned long)s < PAGE_SIZE) - s = "<NULL>"; - - len = strnlen(s, precision); - - if (!(flags & LEFT)) { - while (len < field_width--) { - if (str < end) - *str = ' '; - ++str; - } - } - for (i = 0; i < len; ++i) { - if (str < end) - *str = *s; - ++str; ++s; - } - while (len < field_width--) { - if (str < end) - *str = ' '; - ++str; - } + str = string(str, end, va_arg(args, char *), field_width, precision, flags); continue; case 'p': - flags |= SMALL; - if (field_width == -1) { - field_width = 2*sizeof(void *); - flags |= ZEROPAD; - } - str = number(str, end, - (unsigned long) va_arg(args, void *), - 16, field_width, precision, flags); + str = pointer(fmt+1, str, end, + va_arg(args, void *), + field_width, precision, flags); + /* Skip all alphanumeric pointer suffixes */ + while (isalnum(fmt[1])) + fmt++; continue; - case 'n': /* FIXME: * What does C99 say about the overflow case here? */ diff --git a/mm/allocpercpu.c b/mm/allocpercpu.c index f4026bae6ee..05f2b4009cc 100644 --- a/mm/allocpercpu.c +++ b/mm/allocpercpu.c @@ -1,7 +1,7 @@ /* * linux/mm/allocpercpu.c * - * Separated from slab.c August 11, 2006 Christoph Lameter <clameter@sgi.com> + * Separated from slab.c August 11, 2006 Christoph Lameter */ #include <linux/mm.h> #include <linux/module.h> diff --git a/mm/memory.c b/mm/memory.c index d14b251a25a..2302d228fe0 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1151,7 +1151,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, * be processed until returning to user space. */ if (unlikely(test_tsk_thread_flag(tsk, TIF_MEMDIE))) - return -ENOMEM; + return i ? i : -ENOMEM; if (write) foll_flags |= FOLL_WRITE; @@ -1697,8 +1697,19 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, struct page *dirty_page = NULL; old_page = vm_normal_page(vma, address, orig_pte); - if (!old_page) + if (!old_page) { + /* + * VM_MIXEDMAP !pfn_valid() case + * + * We should not cow pages in a shared writeable mapping. + * Just mark the pages writable as we can't do any dirty + * accounting on raw pfn maps. + */ + if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) == + (VM_WRITE|VM_SHARED)) + goto reuse; goto gotten; + } /* * Take out anonymous pages first, anonymous shared vmas are @@ -1751,6 +1762,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, } if (reuse) { +reuse: flush_cache_page(vma, address, pte_pfn(orig_pte)); entry = pte_mkyoung(orig_pte); entry = maybe_mkwrite(pte_mkdirty(entry), vma); diff --git a/mm/mempolicy.c b/mm/mempolicy.c index a37a5034f63..c94e58b192c 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -729,7 +729,11 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask, } else { *policy = pol == &default_policy ? MPOL_DEFAULT : pol->mode; - *policy |= pol->flags; + /* + * Internal mempolicy flags must be masked off before exposing + * the policy to userspace. + */ + *policy |= (pol->flags & MPOL_MODE_FLAGS); } if (vma) { diff --git a/mm/migrate.c b/mm/migrate.c index 112bcaeaa10..55bd355d170 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -9,7 +9,7 @@ * IWAMOTO Toshihiro <iwamoto@valinux.co.jp> * Hirokazu Takahashi <taka@valinux.co.jp> * Dave Hansen <haveblue@us.ibm.com> - * Christoph Lameter <clameter@sgi.com> + * Christoph Lameter */ #include <linux/migrate.h> diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2f552955a02..f32fae3121f 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2328,7 +2328,6 @@ static void build_zonelists(pg_data_t *pgdat) static void build_zonelist_cache(pg_data_t *pgdat) { pgdat->node_zonelists[0].zlcache_ptr = NULL; - pgdat->node_zonelists[1].zlcache_ptr = NULL; } #endif /* CONFIG_NUMA */ diff --git a/mm/slub.c b/mm/slub.c index 0987d1cd943..315c392253c 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -5,7 +5,7 @@ * The allocator synchronizes using per slab locks and only * uses a centralized lock to manage a pool of partial slabs. * - * (C) 2007 SGI, Christoph Lameter <clameter@sgi.com> + * (C) 2007 SGI, Christoph Lameter */ #include <linux/mm.h> @@ -1628,9 +1628,11 @@ static __always_inline void *slab_alloc(struct kmem_cache *s, void **object; struct kmem_cache_cpu *c; unsigned long flags; + unsigned int objsize; local_irq_save(flags); c = get_cpu_slab(s, smp_processor_id()); + objsize = c->objsize; if (unlikely(!c->freelist || !node_match(c, node))) object = __slab_alloc(s, gfpflags, node, addr, c); @@ -1643,7 +1645,7 @@ static __always_inline void *slab_alloc(struct kmem_cache *s, local_irq_restore(flags); if (unlikely((gfpflags & __GFP_ZERO) && object)) - memset(object, 0, c->objsize); + memset(object, 0, objsize); return object; } @@ -2995,8 +2997,6 @@ void __init kmem_cache_init(void) create_kmalloc_cache(&kmalloc_caches[1], "kmalloc-96", 96, GFP_KERNEL); caches++; - } - if (KMALLOC_MIN_SIZE <= 128) { create_kmalloc_cache(&kmalloc_caches[2], "kmalloc-192", 192, GFP_KERNEL); caches++; @@ -3026,6 +3026,16 @@ void __init kmem_cache_init(void) for (i = 8; i < KMALLOC_MIN_SIZE; i += 8) size_index[(i - 1) / 8] = KMALLOC_SHIFT_LOW; + if (KMALLOC_MIN_SIZE == 128) { + /* + * The 192 byte sized cache is not used if the alignment + * is 128 byte. Redirect kmalloc to use the 256 byte cache + * instead. + */ + for (i = 128 + 8; i <= 192; i += 8) + size_index[(i - 1) / 8] = 8; + } + slab_state = UP; /* Provide the correct kmalloc names now that the caches are up */ diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c index 99c4f36eb8a..a91b5f8fcaf 100644 --- a/mm/sparse-vmemmap.c +++ b/mm/sparse-vmemmap.c @@ -1,7 +1,7 @@ /* * Virtual Memory Map support * - * (C) 2007 sgi. Christoph Lameter <clameter@sgi.com>. + * (C) 2007 sgi. Christoph Lameter. * * Virtual memory maps allow VM primitives pfn_to_page, page_to_pfn, * virt_to_page, page_address() to be implemented as a base offset diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 5905d56737d..81ae3d62a0c 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -1144,20 +1144,20 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) case RPC_GSS_SVC_NONE: break; case RPC_GSS_SVC_INTEGRITY: + /* placeholders for length and seq. number: */ + svc_putnl(resv, 0); + svc_putnl(resv, 0); if (unwrap_integ_data(&rqstp->rq_arg, gc->gc_seq, rsci->mechctx)) goto garbage_args; + break; + case RPC_GSS_SVC_PRIVACY: /* placeholders for length and seq. number: */ svc_putnl(resv, 0); svc_putnl(resv, 0); - break; - case RPC_GSS_SVC_PRIVACY: if (unwrap_priv_data(rqstp, &rqstp->rq_arg, gc->gc_seq, rsci->mechctx)) goto garbage_args; - /* placeholders for length and seq. number: */ - svc_putnl(resv, 0); - svc_putnl(resv, 0); break; default: goto auth_err; @@ -1170,8 +1170,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) goto out; } garbage_args: - /* Restore write pointer to its original value: */ - xdr_ressize_check(rqstp, reject_stat); ret = SVC_GARBAGE; goto out; auth_err: diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 0517967a68b..e6fb21b19b8 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -243,10 +243,10 @@ int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot) } EXPORT_SYMBOL_GPL(rpcb_getport_sync); -static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, int version) +static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, struct rpc_procinfo *proc) { struct rpc_message msg = { - .rpc_proc = rpcb_next_version[version].rpc_proc, + .rpc_proc = proc, .rpc_argp = map, .rpc_resp = &map->r_port, }; @@ -271,6 +271,7 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi void rpcb_getport_async(struct rpc_task *task) { struct rpc_clnt *clnt = task->tk_client; + struct rpc_procinfo *proc; u32 bind_version; struct rpc_xprt *xprt = task->tk_xprt; struct rpc_clnt *rpcb_clnt; @@ -280,7 +281,6 @@ void rpcb_getport_async(struct rpc_task *task) struct sockaddr *sap = (struct sockaddr *)&addr; size_t salen; int status; - struct rpcb_info *info; dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", task->tk_pid, __func__, @@ -313,10 +313,12 @@ void rpcb_getport_async(struct rpc_task *task) /* Don't ever use rpcbind v2 for AF_INET6 requests */ switch (sap->sa_family) { case AF_INET: - info = rpcb_next_version; + proc = rpcb_next_version[xprt->bind_index].rpc_proc; + bind_version = rpcb_next_version[xprt->bind_index].rpc_vers; break; case AF_INET6: - info = rpcb_next_version6; + proc = rpcb_next_version6[xprt->bind_index].rpc_proc; + bind_version = rpcb_next_version6[xprt->bind_index].rpc_vers; break; default: status = -EAFNOSUPPORT; @@ -324,14 +326,13 @@ void rpcb_getport_async(struct rpc_task *task) task->tk_pid, __func__); goto bailout_nofree; } - if (info[xprt->bind_index].rpc_proc == NULL) { + if (proc == NULL) { xprt->bind_index = 0; status = -EPFNOSUPPORT; dprintk("RPC: %5u %s: no more getport versions available\n", task->tk_pid, __func__); goto bailout_nofree; } - bind_version = info[xprt->bind_index].rpc_vers; dprintk("RPC: %5u %s: trying rpcbind version %u\n", task->tk_pid, __func__, bind_version); @@ -361,22 +362,20 @@ void rpcb_getport_async(struct rpc_task *task) map->r_addr = rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR); map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ - child = rpcb_call_async(rpcb_clnt, map, xprt->bind_index); + child = rpcb_call_async(rpcb_clnt, map, proc); rpc_release_client(rpcb_clnt); if (IS_ERR(child)) { status = -EIO; + /* rpcb_map_release() has freed the arguments */ dprintk("RPC: %5u %s: rpc_run_task failed\n", task->tk_pid, __func__); - goto bailout; + goto bailout_nofree; } rpc_put_task(child); task->tk_xprt->stat.bind_count++; return; -bailout: - kfree(map); - xprt_put(xprt); bailout_nofree: rpcb_wake_rpcbind_waiters(xprt, status); bailout_nowake: diff --git a/security/commoncap.c b/security/commoncap.c index 5edabc7542a..33d34330841 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -103,10 +103,16 @@ static inline int cap_inh_is_capped(void) return (cap_capable(current, CAP_SETPCAP) != 0); } +static inline int cap_limit_ptraced_target(void) { return 1; } + #else /* ie., ndef CONFIG_SECURITY_FILE_CAPABILITIES */ static inline int cap_block_setpcap(struct task_struct *t) { return 0; } static inline int cap_inh_is_capped(void) { return 1; } +static inline int cap_limit_ptraced_target(void) +{ + return !capable(CAP_SETPCAP); +} #endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ @@ -342,9 +348,10 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) bprm->e_uid = current->uid; bprm->e_gid = current->gid; } - if (!capable (CAP_SETPCAP)) { - new_permitted = cap_intersect (new_permitted, - current->cap_permitted); + if (cap_limit_ptraced_target()) { + new_permitted = + cap_intersect(new_permitted, + current->cap_permitted); } } } diff --git a/security/device_cgroup.c b/security/device_cgroup.c index baf348834b6..fd764a0858d 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -382,6 +382,8 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft, case 'a': wh.type = DEV_ALL; wh.access = ACC_MASK; + wh.major = ~0; + wh.minor = ~0; goto handle; case 'b': wh.type = DEV_BLOCK; diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 1dcf9f3d110..44589088941 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c @@ -278,7 +278,7 @@ static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi) ent->fields.remote_irr = 0; if (!ent->fields.mask && (ioapic->irr & (1 << gsi))) - ioapic_deliver(ioapic, gsi); + ioapic_service(ioapic, gsi); } void kvm_ioapic_update_eoi(struct kvm *kvm, int vector) |